DSP相关知识.docx
- 文档编号:11078365
- 上传时间:2023-02-24
- 格式:DOCX
- 页数:22
- 大小:32.95KB
DSP相关知识.docx
《DSP相关知识.docx》由会员分享,可在线阅读,更多相关《DSP相关知识.docx(22页珍藏版)》请在冰豆网上搜索。
DSP相关知识
工作阶段:
工作流程一般分为三个阶段。
阶段一:
直接按照需要用C语言实现功能。
在实际的DSP应用中,许多算法都是非常复杂,直接用汇编代码编写,虽然优化效率很高,可是实现的难度却很大,所以一般都采用先用C语言来实现,然后编译运行,利用C64X开发环境的工具测试程序运行时间,若不能满足要求,则进行第二阶段。
阶段二:
C语言级的优化。
选择C64X开发环境提供的优化方式(O2,O3)以及充分运用其他技巧,优化C代码,若还不能满足效率要求,则进行第三步。
阶段三:
汇编级的优化。
将上一阶段C程序中优化效率较低的部分提出来,用线性汇编语言编写,利用汇编优化器进行优化。
汇编优化器的作用是让开发人员在不考虑C64X流水线结构和分配其内部寄存器的情况下,编写线形汇编语言程序,然后汇编优化器通过分配寄存器和循环优化将汇编语言程序转化为利用流水线方式的高速并行汇编程序。
上述的三个阶段不是都必须经过,当在某一阶段获得了期望的性能,就不必进行下一阶段的优化。
1)选用C编译器提供的优化选项
在编译器中提供了分为若干等级和种类的自动优化选项,如下:
●-o:
使能软件流水和其他优化方法
●-pm:
使能程序级优化
●-mt:
使能编译器假设程序中没有数据存储混淆,可进一步优化代码。
●-mg:
使能分析(profile)优化代码
●-ms:
确保不产生冗余循环,从而减小代码尺寸
●-mh:
允许投机执行
●-mx:
使能软件流水循环重试,基于循环次数对循环试用多个方案,以便选择最佳方案。
根据实际编译的程序,选择合适的优化选项,进行源程序的优化。
2)减小存储器相关性
为使指令达到最大效率,C64X编译器尽可能将指令安排为并行执行。
为使指令并行操作,编译器必须知道指令间的关系,因为只有不相关的指令才可以并行执行。
当编译器不能确定两条指令是否相关时,则编译器假定它们是相关的,从而不能并行执行。
设计中常采用关键字cONst来指定目标,const表示一个变量或一个变量的存储单元保持不变。
因此,在代码中加入关键字const,可以去除指令间的相关性。
例如下面的程序:
voidvecsum(short*sum,short*in1,short*in2,unsignedintN)
{
inti;
for(i=0;i sum[i]=in1[i]+in2[i]; } 由其相关图2(a)可见,写sum可能对指针in1、in2所指向的地址有影响,从而in1和in2的读操作必须等到写sum操作完成之后才能进行,降低了流水效率,为帮助编译器确定存储器的相关性,使用const关键字来指定一个目标,上面的源程序可改为含关键字const的优化源代码: voidvecsum(short*sum,constshort*in1,constshort*in2,unsignedintN) { inti; for(i=0;i sum[i]=in1[i]+in2[i]; } 由其相关图2(b)可见,由于使用了关键字const,消除了指令之间的相关路径,从而使编译器能够判别内存操作之间的相关性,找到更好的指令执行方案。 3)使用内联函数(intrinsics) 内联函数是C64X编译器提供的专门函数,它们与嵌入式的汇编指令是一一对应的,其目的是快速优化C源程序。 在源程序中调用内联函数,与调用一般的函数相同,只不过内联函数名称前有下划线作特殊标识。 当汇编指令功能不易采用C语言表达时,可采用内联函数表示。 例如在定点运算中经常要求出源操作数的冗余符号位数,这一功能如果用C完成的话,需要如下的代码: unsignedintnorm(intsrc1) { unsignedintsign,result=0; sign=src1&0×80000000; while (1) { if(sign) { if((src1=src1<<1)&sign) result+=1; else returnresult; } else { if((src1=src1<<1)|sign) returnresult; else result+=1; } } } 该源程序代码冗长,有较多的逻辑操作和判断跳转,运行效率低下。 若用内联函数,则是result=_norm(src1),减少了代码长度,提高了运行效率。 因此对于需要大量C代码才能表示的复杂功能,应该尽量用C64X的内联函数来表示。 4)short型数据的int处理 C64Xdsp具有双16bit扩充功能,芯片能在一个周期内完成双16bit的乘法、加减法、比较、移位等操作。 在设计时,当对连续的short型数据流操作时,应该转化成对int型数据流的操作,这样一次可以把两个16位的数据读入一个32位的寄存器,然后用内部函数来对它们处理(如_sub2等),充分运用双16bit扩充功能,一次可以进行两个16bit数据的运算,速度将提升一倍。 5)尽量少进行函数调用 函数调用的时候,要将PC和一些寄存器压栈保存,函数返回时,则将这些寄存器出栈返回,增加了一些不必要的操作。 所以一些小的函数,最好是用适当的内联函数代替直接写入主函数里,一些调用不多的函数,也可以直接写入主函数内,这样可减少不必要的操作,提高速度。 但是这样往往会增加程序的长度,因此是一种利用空间换取时间的办法。 6)尽量使用逻辑运算代替乘除运算 在DSP里,乘除运算指令的执行时间要远远超过逻辑移位指令,尤其是除法指令,在设计的时候,可以根据实际情况,进行一些调整,尽量用逻辑移位运算来代替乘除运算,这样可以加快指令的运行时间。 7)软件流水线技术的使用 软件流水线技术用来对一个循环结构的指令进行调度安排,使之成为多重迭代循环并行执行。 在编译代码时,可以选择编译器的-o2或-o3选项,则编译器将根据程序尽可能地安排软件流水线。 在DSP算法中存在大量的循环操作,因此充分地运用软件流水线方式,能极大地提高程序的运行速度。 但使用软件流水线还有下面几点限制: ●循环结构不能包含代码调用,但可以包含内联函数。 ●循环计数器应该是递减的。 ●循环结构不能包含break,if语句不能嵌套,条件代码应当尽量的简单。 ●循环结构中不要包含改变循环计数器的代码。 ●循环体代码不能过长,因为寄存器(32个)的数量有限,应该分解为多个循环。 在软件流水线的运用上,应该尽量使复杂的循环分解成简单的小循环,以避免寄存器的数量不够;对于过于简单的循环,应该适当的展开,以增加代码数量,增加流水线中的迭代指令。 8)采用指令乱序技术 程序中,有些指令的执行顺序没有严格的要求,可以作出一些位置上的调整,因此可以适当的调整这些指令的位置,穿插于其他的指令之中,从而减小指令的相关性,增加运行时的并行性。 尤其在循环里,当循环体较小的时候,可以把多个循环的代码写在一个循环体里,合并成一个循环,从而减小循环内指令的相关性,增加指令运行的并行性。 但是要注意不要使循环过于复杂,以至不能进行软件流水线的优化。 由于C语言编译出来的程序,不是最有效率的汇编语言,而没有办法达到实时播放。 所以为了要使程序执行的速度能够加快,必须要做最佳化,使其能够达到实时播放的速度。 然而C6x的编译器也提供了最佳化的指令,如在编译时加上-o3的参数,它可以用软件来分析我们的程序是否有可以改进的地方,如此一来,在产生组语的汇编语言档案之前,编译器会对我们写的C语言程序不断的进行编译,也会对程序中的循环部份重新编排,产生另一较有效率的核心循环,以最有效率的方式重新编排程序,来加快程序速度 方法一把浮点运算改成定点运算 因为C6xDSP板并不支持浮点运算,但我们的原始程序代码是浮点运算的格式,所以必须改成定点运算,而其修改后的执行速度也会加快很多。 我们采用Q-format规格来表示浮点运算。 以下将介绍其相关原理。 定点DSP使用固定的小数点来表示小数部份的数字,这也造成了使用上的限制,而为了要分类不同范围的小数点,我们必须使用Q-format的格式。 不同的Q-format表示不同的小数点位置,也就是整数的范围。 表2呈现Q15数字的格式,要注意在小数点后的每一位,表示下一位为前一位的二分之一,而MSB(most-significant-bit)则被指定成有号数(Signbit)。 由表2可以知道,当有号数被设成0而其余位设成1时,可得到最大的正数(7FFFH);而当有号数被设成1而其余位设成0时,可得到最大的负数(8000H)。 所以Q15格式的范围从-1到0.9999694(@1),因此我们可以藉由把小数点向右移位,来增加整数部份的范围,如表3所示,Q14格式的范围增为-2.0到1.9999694(@2),然而范围的增加却牺牲了精确度。 方法二建立表格(table) 原来程序的设计是除了要读AAC的档案外,在译码时,还要再另外读取一些C语言程序代码的内容再做计算,如读取一些数值做sin、cos、exp的运算,但是为了加快程序的执行速度,故将这这些运算的结果建成表格,内建在程序中,可以不必再做额外的计算动做,以加速程序。 方法三减短程序的长度 1.去除Debug的功能 原本程序在Debug的阶段时,就加了许多用来侦测错误的部份,程序Debug完后,已经没有错误发生,所以就可以把这些部份给去除,以减少程序的长度,也可以减少程序执行时的时脉数,加快程序的速度。 2.去除计算时脉(clock)功能 原本程序可以计算执行程序所需的时脉数,我们也可以把这些部份给去除,如果有需要计算时脉时,我们可以用C6x的工具软件来作,功能更强大。 方法四减少I/O过程 原本在做译码的动作时,是先读取AAC档案的一部份做译码,译码完成后再读取下一部份,再做译码。 但是由于C6x的板子跟PC做档案读取时相当的缓慢,读取的动作占了大部份的时间,所以就将程序改成先将AAC档案全部读到C6x的内存中,再做译码。 或是将AAC建成表格(约1MB),以避免DSP板上的内存不足。 方法五减少子程序的呼叫 在呼叫子程序时,必须先将缓存器的内容放到堆栈(stack)中,而从子程序返回时,也要将这些缓存器原本的内容从堆栈中取出来。 但是有些子程序的长度很短,而且被呼叫的次数又很多,往往几个时脉就可以完成却浪费时间在存取堆栈的内容上,所以干脆将这些很短的子程序直接写在主程序当中,以减少时脉数。 方法六写汇编语言 虽然由C语言所编译出来的汇编语言可以正确无误的执行,但是这个汇编语言却不是最有效率的写法,所以为了增加程序的效率,于是在某些地方,例如一些被呼叫很多次且程序代码不长的函式(funcTIon),必须改以自己动手写汇编语言来取代。 方法七利用平行处理的观念 C6x是一颗功能强大的处理器,它CPU的内部提供了八个可以执行不同指令的单元,也就是说最多可以同时处理八个指令。 所以如果我们可以用它来作平行处理,我们就可以大大的缩短程序执行的时间,最有效率的来利用它来作解码的动作。 最后还要知道: 第三级优化(-O3),效率不高(经验),还有一些诸如用一条读32位的指令读两个相邻的16位数据等,具体情况可以看看C优化手册。 但这些效率都不高(虽然ti的宣传说能达到80%,我自己做的时候发现绝对没有这个效率! 65%还差不多),如果要提高效率只能用汇编来做了。 还有要看看你的c程序是怎么编的,如果里面有很多中断的话,6000可以说没什么优势。 还有,profiler的数据也是不准确的,比实际的要大,大多少不好说。 还有dsp在初始化的时候特别慢,这些时间就不要和pc机相比了,如果要比就比核心的部分。 关于profile: C6x的Debug工具提供了一个profile界面。 在图9中,包括了几个重要的窗口,左上角的窗口是显示出我们写的C语言,可以让我们知道现在做到了哪一步。 右上角的窗口显示的是C6x所编译出来的汇编语言,同样的我们也可以知道现在做到了哪一步。 左下角的窗口是命令列,是让我们下指令以及显示讯息的窗口。 而中间的profile窗口就是在profile模式下最重要的窗口,它显示出的项目如下表: 表5: profile的各项参数[8] 字段意义 Count被呼叫的次数 Inclusive包含子程序的总执行clock数 Incl-Max包含子程序的执行一次最大clock数 Exclusive不包含子程序的总执行clock数 Excl-Max不包含子程序的执行一次最大clock数 利用这个profile模式我们可以用来分析程序中每个函数被呼叫的次数、执行的时脉数等等。 用这个分析的结果,我们就可以知道哪个函数所花费的时脉最多,是可以再改进的,而针对它来作最佳化。 汇编代码级的优化 在经过C代码的优化之后,还不能满足性能上的要求,则可以通过profile clock工具找出效率很低的部分,使用线性汇编重新改写。 再通过汇编优化器编译,汇编优化器从输入的线性汇编代码中,完成以下功能: ●寻找可以平行执行的CPU指令。 ●在软件流水线期间,处理流水线标号。 ●分配寄存器的用法。 ●分配功能单元。 TI提供的汇编优化器可以得到很高的效率,一般可以满足性能上的要求。 优化中的问题、 在优化过程中,总是要对程序进行一定的改动,这样经常会出现一些问题。 1)优化结果的验证、 优化过的程序往往不知道是否运行正确,这就需要加以验证。 一般采用的办法就是通过测试序列来验证。 测试序列指的是对于不同的算法所取的一组特殊的数据,这些数据可以准确的反映算法的特性。 测试序列中每组数据包括输入数据和输出数据,通过对输入数据的运算,把结果与输出数据进行比较,判断程序的正确性。 一些常见的算法,一般都提供了测试序列。 还有一些,没有测试序列。 这时就需要根据算法的特点,自己构造测试序列,进行验证。 构造的时候,注意序列最好有几组,数据最好有一定的长度,这样验证的更准确。 2)内存泄漏的问题、 C64X系列DSP的内部存储空间有1MB,其中程序和数据还有CPU的二级缓存将共享这片空间,因此当程序的运行不正常时,很有可能就是内存泄漏造成的。 因此,在程序设计中,应尽量不用指针,同时注意进行边界检测。 程序设计的一些方法 程序设计时,一切以满足实际的要求为目标。 在实际的设计中,除了优化能够提高性能以外,还可以采取其他的办法,利用DSP的特性,提高程序的运行性能,满足实际的设计要求。 1)把程序和经常要用的数据放入片内RAM 片内RAM与CPU 工作在同一时钟频率,比片外RAM性能高得多。 因此把程序放在片内可以大大提高运行的速度。 同时对于一些经常要用到的数据,放入片内,也会节省处理时间。 2)通过DMA技术搬移数据 对于C64X芯片,其片内RAM有1MB,但是对于一些大型的图像处理算法而言,仍可能是不够的,因此经常通过DMA技术,把需要用到的数据搬入片内,把不需要的搬到片外,可以大大的提高程序的运行速度。 3)CACHE的使用 增大CACHE,可以明显的提高性能。 但是C64X系列DSP中程序和数据还有CACHE共享片内RAM,因此增大CACHE,就减小了实际的片内可用空间,设计中需要注意。 高速缓冲存储器是存在于主存与CPU之间的一级存储器,由静态存储芯片(SRAM)组成,容量比较小但速度比主存高得多,接近于CPU的速度。 主要由三大部分组成: Cache存储体: 存放由主存调入的指令与数据块。 地址转换部件: 建立目录表以实现主存地址到缓存地址的转换。 替换部件: 在缓存已满时按一定策略进行数据块替换,并修改地址转换部件。 [1] 正在使用的主存储器某一单元邻近的那些单元将被用到的可能性很大。 因而,当中央处理器存取主存储器某一单元时,计算机硬件就自动地将包括该单元在内的那一组单元内容调入高速缓冲存储器,中央处理器即将存取的主存储器单元很可能就在刚刚调入到高速缓冲存储器的那一组单元内。 于是,中央处理器就可以直接对高速缓冲存储器进行存取。 项目里面的优化: 首先是算法上的优化,算法上的优化才是最大的优化,比如单载波链路里面均衡模块的矩阵求逆作乐展开化简然后就是考虑到DSP构架的一些优化了,比如循环次数尽量是确定的数而不是变量;循环次数尽量是2或4的倍数;尽量使用16bit的计算而不是32bit;尽量使用基本运算,避免开方这样的复杂运算;尽量避免除法运算;尽量使用intrinsic指令,例如MIMO检测中使用的矩阵计算函数 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! 输入/输出系统 1、主机与外设的连接 1.1、输入输出接口 I/O接口是主存和外设之间的交接界面,通过接口可以实现主机和外设之间的信息交换 主机和外设之间需要交换的信息: 数据信息: 这些信息可以是通过输入设备送到计算机的输入数据,也可以是经过计算机运算处理和加工后,送到输出设备的结果数据 控制信息: 这是CPU对外设的控制信息或管理命令,如外设的启动和停止指控,输入和输出操作的制定、工作方式的选择、中断功能的允许和禁止等 状态信息: 这类信息用来标志外设的工作状态,比如,输入设备数据准备好标志,输出设备忙、闲标志等 联络信息: 主机与外设间的时间配合信息 外设识别信息: I/O寻址信息,使CPU能从众多的外设中寻找出与自己进行信息交换的唯一的设备 2、接口的功能和基本组成 (1)接口的功能 实现主机和外部设备的通信联络控制 进行地址译码和设备选择: 当CPU送来选择外设的地址码后,接口必须对地址进行译码以产生设备选择信息,使主机能和指定外设交换信息 实现数据缓冲: 在接口电路中,一般设置一个或几个数据缓冲寄存器,用于数据的暂存,以避免因速度不一致而丢失数据。 在传送过程中,先将数据送入数据缓冲寄存器中,然后再送到外部设备或主机中去 数据格式的变换: 在输入或输出操作过程中,为了满足主机或外设的各自要求,接口电路中必须具有实现各类数据相互转换的功能,如: 并-串转换、串-并转换、模-数转换、数-模转换以及二进制数和ASCII码的相互转换等 传递控制命令和状态信息: 当CPU要启动某一外设时,通过接口中的命令寄存器向外设发出启动命令;当外设准备就绪时,则有“准备好”状态信息送回接口中的状态寄存器,为CPU提供反馈信息,告诉CPU,外设已经具备与主机交换数据的条件 (2)接口的基本组成 接口中要分别传送数据信息、控制信息、和状态信息,数据信息、控制信息和状态信息都通过数据总线来传送。 大多数计算机都把外部设备的状态信息视为输入数据,而把控制信息看成是输出数据,并在接口中分设各自相应的寄存器,赋以不同的端口地址,各种信息分时地使用数据总线传送到各自的寄存器中 接口与端口是两个不同的概念,端口是指接口电路中可以被CPU直接访问的寄存器,若干个端口加上相应的控制逻辑电路才组成接口 通常,一个接口中包含有数据端口、命令端口和状态端口。 存放数据信息的寄存器称为数据端口,存放控制命令的寄存器称为命令端口,存放状态信息的寄存器称为状态端口。 CPU通过输入指令可以从有关端口中读取信息,通过输出指令可以把信息写入有关端口。 CPU对不同端口的操作有所不同,有的端口只能读或只能写,有的端口可读可写。 例如,对状态端口只能读,可将外设的标志送到CPU中去;对命令端口只能写,可将CPU的各种控制命令发送给外设 1.3、外设的识别与端口寻址 外设识别是通过地址总线和接口电路中的外设识别电路来实现的,I/O端口地址就是主机与外设直接通信的地址,CPU可以通过端口发送命令、读取状态和传送数据。 (1)端口地址的编址方式 I/O端口的编址方式有两种: 独立编址: 主存地址空间和I/O端口地址空间是相对独立的,分别单独编址。 CPU访问主存时,由主存读/写控制线控制,访问外设时,由I/O读/写控制线控制,在指令系统中,必须设置专门的I/O指令。 当CPU使用I/O指令时,其指令的地址字段直接或间接的指出端口地址。 这些端口地址被接口电路中的地址译码器接受并进行译码,符合者就是CPU所指定的外设寄存器,该寄存器将被CPU访问 统一编址: 在这种编址方式中,I/O端口地址和主存单元的地址是统一编址的,把I/O接口中的端口作为主存单元一样进行访问,不设置专门的I/O指令。 当CPU访问外设时,把分配给该外设的地址码送到地址总线上,然后各外设接口中的地址译码器对地址码进行译码,如果符合就是CPU指定的外设寄存器 (2)独立编址方式的端口访问 Intel80X86的I/O地址空间由64K个独立编址的8位端口组成。 两个连续的8位端口可作为16位端口处理;4个连续的8位端口可作为32位端口处理。 因此,I/O地址空间最多可提供64K个8位端口、32K个16位端口、16K个32位端口 80X86的专用I/O指令IN和OUT有直接寻址和间接寻址两种类型。 直接寻址I/O端口的寻址范围为00~FFH,最多为256个端口地址 间接寻址由DX寄存器间接给出I/O端口地址,DX寄存器长16位,寻址范围为0000~FFFFH,最多可寻址64K个端口地址。 CPU一次可实现字节(8位)、字(16位)或双字(32位)的数据传送。 32位的端口地址应对准可被4整除的地址;16位端口应对准偶地址;8位端口可定位在偶地址,也可定位在奇地址 1.4、输入/输出信息传送控制方式 外设与主机之间的信息传送控制方式,经历了由低级到高级、由简单到复杂、由集中管理到各部件分散管理的发展过程,按其发展的先后顺序和主机与外设并行工作的程度,可以分为四种: 程序查询方式: 程序直接查询控制方式,这是主机与外设间进行信息交换的最简单的方式,输入和输出完全是通过CPU执行程序来完成的。 一旦某一外设被选中并启动之后,主机将查询这个外设的某些状态位,看其是否准备就绪。 若外设未准备就绪,主机将再次查询;若外设已准备就绪,则执行一次I/O操作 程序中断方式: 在主机启动外设后,无需等待查询,而是继续执行原来的程序,外设在做好输入/输出准备时,向主机发中断请求,主机接到请求后就暂时中止原来执行的程序,转去执行中断服务程序对外部请求进行处理,在中断处理完毕后返回原来的程序继续执行。 程序中断不仅适用于外部设备的输入输出操作,也适用于对外界发生的随机事件的处理 直接存储器存取(DMA)方式: DMA方式是在主存和外设之间开辟直接的数据通路,可以进行基本上不需要CPU介入的在主存和CPU之间的信息传送,这样不仅保证CPU的高效率,而且能满足高速外设的需要。 DMA方式只能进行简单的数据传送操作,在数据块的传送的开始和结束时还需要CPU和中断系统进行预处理和后处理 I/O通道控制方式: 在系统中设有通道控制部件,每个通道挂若干外设,主机在执行I/O操作时,只需启动有关通道,通道将执行通道程序,从而完成I/O操作。 通道是一个具有特殊功能的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DSP 相关 知识