C66系列DSP程序优化说明
- 格式:docx
- 大小:790.39 KB
- 文档页数:17
《DSP技术实验》DSP程序的调试和分析方法实验一、实验目的1. 熟悉 CCS 集成开发环境,熟练掌握 DSP 程序设计方法;2. 熟悉利用 restrict、volatile 等关键字优化 DSP 程序,掌握利用#pragma 伪指令和内嵌操作优化 DSP 程序3. 掌握利用编译选项优化 DSP 程序的方法;4. 利用 DSPLIB 实现 FIR 滤波分析程序的优化设计。
二、实验预习内容1. 请写出 restrict 关键字的作用,并用之修改实验 1 中的 FIR 函数,优化DSP 程序。
答1:restrict关键字的作用:在函数参数中使用restrict关键字来定义指针变量,则在该函数中的指针变量不会指向同一个存储空间,这可以帮助编译器判别循环依赖性,使编译器充分利用流水线技术,从而提高优化水平。
答2:修改实验 1 中的 FIR 函数,优化 DSP 程序:DataBuf[i]=DataBuf[nx+i];改为:float*restrict pl;//Loop2float*restrict p2;p1=DataBuf;p2=&DataBuf[nx];for(i=0;i<nh-1;i++)p1[i]=p2[i];同时,把传输函数void FIR(float*x, float*h, float*y, float*DataBuf, float nh, float nx)改为:void FIR(float*restrict x, float*restrict h, float*restrict y, float*restrict DataBuf, float nh, float nx)2.请写出基于编译器反馈信息优化 DSP 程序的步骤。
答:阶段一:收集程序的剖析信息。
配置生成剖析信息选项-->生成剖析信息-->将剖析信息文件转化为相应反馈文件。
阶段二:利用收集的剖析信息优化DSP程序。
C6XX优化经验总结一、c6x的编译的常用选项(一)c6x的编译程序为“cl6x.exe”使用的方法Cl6x [options] [filenames]Cl6x:编译程序Options:编译选项Filenames: C或汇编源文件说明:编译选项是一个字母或者两个字母,对大小写不敏感。
编译选项的前面需要有一个“-”符号。
一个字母的选项可以合并在一起。
比如“-sgq”与“-s -g -q”相同。
两个字母的选项如果第一个字母相同也可以合并在一起。
比如“-mgt”与“-mg -mt”相同。
(二)有关优化的选项-mt:表示在程序中没有使用alaising技术,这使得编译器可以进行比较好的优化。
-o3:对文件级别进行最强的优化,一般在编译时应该使用这个选项。
但是在个别情况下使用这个选项优化程序可能会出现错误(-o2有相同现象,-o0和-o1不会出现错误)。
可能是在优化循环,组织流水线的时候发生错误。
如果有这种现象出现可以同时使用-g选项,程序优化就不会出现错误,但是优化效果会下降。
另外可以调整程序的表达方式,可能会避免编译器发生错误。
-pm:在程序级别进行优化。
可以将所以文件联合在一起进行优化,主要有去掉没有被调用的函数、总是常数的变量以及没有使用的函数返回值。
建议由程序员自己进行这种优化工作。
使用这个选项在win98下编译可能会出现找不到编译程序的情况。
-ms0:不使用冗余循环进行优化,减小程序的大小。
一般情况下这个选项对程序大小的优化作用不明显。
-mh[n]:去掉流水线的epilog,减小程序的大小。
这个选项的作用比较明显。
但是有可能出现读取地址超出有效范围的问题,所以要在数据段的开始和结尾处增加一些pading,或者在分配内存时保证数组的前面和后面一段范围内都是有效的地址。
可选的参数n给出这种pading的长度字节数。
(三)保留编译和优化信息的选项-k:保留优化后生成汇编语言文件。
-s:汇编语言文件中加入优化信息,如果没有则加入C语言源程序作为注释。
TMS320C6678 Programmar Guider本文是对DSP程序优化的第2到4章的部分翻译,水平有限,不妥之处敬请原谅。
2优化C/C++代码2.1写C/C++代码本章描述了如何分析和裁剪你的代码,以确认你已经从C6000体系获得最好的性能。
2.1.1数据类型小诀窍当写C代码时遵循以下指导方针:1.避免编码int和long类型一样大小,因为C6000编译器的long型为40bit;2.尽可能使用short数据类型为fixed-point乘法的输入,因为这种数据类型在C6000里提供了最有效的16-bit乘法器。
3.当有循环计数时,使用int或者unsigned int,而不要使用short和unsignedshort,以避免不必要的符号扩展说明。
2.1.2分析C代码的性能2.2编译C/C++代码编译工具提供了一个shell程序(cl6x),可以用来编译,汇编优化,汇编和单步链接程序。
调用编译时输入:cl6x [options] [filenames] [−z [linker options] [object files]]2.2.1编译选项表2.1 代码关键性能避免选择的编译器选项选项描述-mu 使软件流水线调试无效。
用-ms2/-ms3代替来减少代码大小将在其它代码大小的优化上禁用软件流水-o1/-o0 总是使用-o2/-o3来最大化编译分析和优化,在性能和代码大小之间用代码大小标志(-msn)来权衡-mz 过时的。
在3.00前,这个选项改善代码,但是在3.00后,这个选项会降低性能增加代码大小。
表2.2 性能编译选项选项描述-mh<n>§-mhh 允许投机执行。
适当的填充量必须在数据内存中可用来确保正确执行,这一般不是问题,但必须坚持如此。
-mi<n>§-mii 描述了编译器的中断阈值。
如果你知道在你的代码中没有中断发生,编译器可以在软件流水循环一个代码大小前后避免启用和禁止中断,另外,高寄存器压力循环的充分利用有潜在的性能改进。
剖析DSP编程优化的7个方法方法一把浮点运算改成定点运算因为C6x DSP板并不支持浮点运算,但我们的原始程序代码是浮点运算的格式,所以必须改成定点运算,而其修改后的执行速度也会加快很多。
我们采用Q-format 规格来表示浮点运算。
以下将介绍其相关原理。
定点DSP使用固定的小数点来表示小数部份的数字,这也造成了使用上的限制,而为了要分类不同范围的小数点,我们必须使用Q-format的格式。
不同的Q-format表示不同的小数点位置,也就是整数的范围。
Q15数字的格式,要注意在小数点后的每一位,表示下一位为前一位的二分之一,而MSB (most-significant-bit ) 则被指定成有号数( Sign bit )。
当有号数被设成0而其余位设成1时,可得到最大的正数(7FFFH ) ;而当有号数被设成1而其余位设成0时,可得到最大的负数( 8000H ) 。
所以Q15格式的范围从-1到0.9999694 (@1) ,因此我们可以藉由把小数点向右移位,来增加整数部份的范围,Q14格式的范围增为-2.0到1.9999694 (@2) ,然而范围的增加却牺牲了精确度。
方法二建立表格( table )原来程序的设计是除了要读AAC的档案外,在译码时,还要再另外读取一些C语言程序代码的内容再做计算,如读取一些数值做sin、cos、exp的运算,但是为了加快程序的执行速度,故将这这些运算的结果建成表格,内建在程序中,可以不必再做额外的计算动做,以加速程序。
方法三减短程序的长度1.去除Debug的功能原本程序在Debug的阶段时,就加了许多用来侦测错误的部份,程序Debug完后,已经没有错误发生,所以就可以把这些部份给去除,以减少程序的长度,也可以减少程序执行时的时脉数,加快程序的速度。
2.去除计算时脉( clock ) 功能原本程序可以计算执行程序所需的时脉数,我们也可以把这些部份给去除,如果有需要计。
66AK DSP程序优化说明此文档不介绍具体技术细节,相关技术细节,还望仔细理解官方文档。
如有疑问:请加QQ156898965平台配置66ak存储资源结构:存储资源包括DDRA、DDRB,共享内存MSMC,每个核的局部L2、L1P、L1D。
由于整个芯片的地址空间是物理统一编址的。
L1,L2运行时钟为主频,常规64系列L2运行时钟为主频一半。
MSMSRAM 运行在主频。
DSP core直接读取L1,L2,通过MSMC读取SRAM,外部DDRA。
DDRADDRBL1P可配置程序缓存;L1D可配置数据一级缓存,2-WayCache;L2可配置数据二级缓存,4-WayCache。
缓存区域从高地址开始分配。
如下图:程序数据存放区域分类程序存放区域:用于存放所有可以执行的代码和常量,程序运行过程中,不会发生改变;数据存放区域:用于全局变量和局部变量保留的空间,程序运行过程中会发生改变;堆栈存放区域:为系统堆栈保留的空间,用于和函数传递变量或为局部变量分配空间。
若因意外改变,会导致程序跑飞。
平台配置通过新建或修改Platform文件来实现存储资源定义,Cache大小分配,及程序数据存放区域指定。
以66ak12为例,缓存区域L1P,L1D 全部设置为缓存,L2缓存大小设置为256k。
程序存放于DDRB,数据存放于L2,堆栈存放于L2进行。
配置过程如下:Debug模式下,选择tools -> RTSC Tools -> Platform -> New,根据自己的需要选择Platform保存的路径以及对应的芯片,Next,填入所需要的各种空间的大小和起始位置。
芯片选择时钟定义Cache配置数据存放区域指定平台调用及验证调用Platform:在工程查看窗口,相应工程上右键Properties,选择General -> RTSC,找到最后一项,Other Repositories,点击Add,路径选择上一步保存的路径,需要注意选择XDCtools版本,然后就能找到自己新建的Platform验证:查看通过自动生成CMD文件查看,如下图所示,L2SRAM大小为768K。
电子书—彩读C66使用手册Ver 27.4.1您好感谢您选用本公司生产的产品!为了使您尽快轻松自如地操作您的产品,我们随机配备了内容详尽的用户手册,您可以获取有关产品介绍、使用方法等方面的知识。
使用您的产品之前,请仔细阅读我们随机提供的所有资料,以便您能更好地使用该产品。
在编写本手册时我们非常认真和严谨,希望能给您提供完备可靠的信息,然而难免有错误和疏漏之处,请您给予谅解并由衷地欢迎您批评和指正。
如果您在使用该产品的过程中发现什么问题,请及时拨打我们的服务热线,感谢您的支持和合作!请随时备份您的数据资料到您的电脑上。
本公司对于因软件、硬件的误操作、产品维修、电池更换或其它意外情况所引起的个人数据的丢失和损坏不负任何责任,也不对由此而造成的其它间接损失负责。
同时我们无法控制用户对本手册可能造成的误解,因此,本公司将不对在使用本手册过程中可能出现的意外损失负责,并不对因使用该产品而引起的第三方索赔负责。
本手册中的信息如有变更,恕不另行通知。
本手册信息受到版权保护,其任何部分未经本公司事先书面许可,不准以任何方式影印和复制。
本公司保留对本手册、三包凭证及其相关资料的最终解释权。
本产品符合GB/T 18220-2000手持式个人信息处理设备通用规范。
1注意事项✧不要在高度潮湿的环境下使用适配器,切勿用湿的手足去碰适配器。
✧切勿用金属物体接触机器,这样容易造成机器短路。
✧建议及时备份存放在本机中的个人资料。
✧请不要试图分解或改造本机,这样可能导致电击或妨碍产品质保。
✧清洁机器时,请使用柔软的布清洁表面。
✧如果表面严重污浊,可用软布占少许清水或柔软清洁剂清洁。
✧请注意不要让液体进入机器内部。
✧禁止儿童单独玩耍本机,请勿摔落或与硬物摩擦撞击,否则可能导致机器表面磨花、硬盘损伤、数据丢失或其它硬件损坏。
✧为保证机器安全,请勿在高温环境下对本机进行充电,如暖气旁、电热毯等环境下;并禁止在充电时将产品或充电器上放置遮盖物,如被子、衣物等。
1开发板简介基于TI KeyStone C66x多核定点/浮点DSP TMS320C665x,单核TMS320C6655和双核TMS320C6657管脚pin to pin兼容,同等频率下具有四倍于C64x+器件的乘累加能力; 主频1.0/1.25GHz,单核可高达40GMACS和20GFLOPS,包含2个Viterbi协处理器和1个Turbo协处理解码器,每核心32KByte L1P、32KByte L1D、1MByte L2,1MByte多核共享内存,8192个多用途硬件队列,支持DMA传输;可免装风扇,以最低的功率级别和成本提供最高的性能;支持PCIe、SRIO、HyperLink、uPP、EMIF16、千兆网口等多种高速接口,同时支持I2C、SPI、UART、McBSP等常见接口;连接稳定可靠,80mm*58mm,体积极小的C66x核心板,采用工业级高速B2B连接器,关键大数据接口使用高速连接器,保证信号完整性;提供丰富的开发例程,入门简单,支持裸机和SYS/BIOS操作系统。
图1 开发板正面图图2 开发板侧面图1图3 开发板侧面图2图4 开发板侧面图3图5 开发板侧面图4TL665x-EasyEVM是一款基于广州创龙TI KeyStone C66x多核定点/浮点TMS320C665x 核心板SOM-TL665x设计的高端DSP开发板,底板采用沉金无铅工艺的4层板设计,它为用户提供了SOM-TL665x核心板的测试平台,用于快速评估SOM-TL665x核心板的整体性能。
SOM-TL665x引出CPU全部资源信号引脚,二次开发极其容易,客户只需要专注上层运用,降低了开发难度和时间成本,让产品快速上市,及时抢占市场先机。
不仅提供丰富的Demo程序,还提供DSP核间通信开发教程,全面的技术支持,协助客户进行底板设计和调试以及多核软件开发。
2典型运用领域✓数据采集处理显示系统Telecom Tower:远端射频单元(RRU)✓X 射线:行李扫描仪✓专业音频混合器✓军用和航空电子成像✓军用:军需品和目标应用✓军用:雷达/声纳✓军用:雷达/电子战✓打印机✓无线通信测试仪✓机器视觉:帧捕捉器✓机器视觉:摄像机✓条码扫描仪✓点钞机✓电信基带单元✓视频分析服务器✓软件无线电(SDR)✓高速数据采集和生成3软硬件参数硬件框图图6 开发板硬件框图图7 开发板硬件资源图解1图8 开发板硬件资源图解2硬件参数表1CPU单核TMS320C6655/双核TMS320C6657,主频1.0/1.25GHzROM128/256MByte NAND FLASHRAM512M/1GByte DDR3EEPROM1MbitSENSOR 1x TMP102AIDRLT,核心板温度传感器,I2C接口B2B 2x 50pin公座B2B,2x 50pin母座B2B,间距0.8mm,合高5.0mm;Connector1x 80pin高速B2B连接器,间距0.5mm,合高5.0mm,共280pin,信号速率最高可达10GBaudLED2x供电指示灯(核心板1个,底板1个)5x用户指示灯(核心板2个,底板3个)KEY 2x复位按键,包含1个系统复位和1个软复位1x NMI按键1x用户按键SRIO1x SRIO,四端口四通道,每通道最高通信速率5GBaudPCIe1x PCIe Gen2,单端口双通道,每通道最高通信速率5GBaudHyperLink1x HyperLink,最高通信速率40GBaud,KeyStone处理器间互连的理想接口IO2x 25pin IDC3简易牛角座,间距2.54mm,含uPP、EMIF16拓展信号2x 25pin IDC3简易牛角座,间距2.54mm,含McBSP、SPI、TIMER、GPIO等拓展信号UART1x UART0,Micro USB接口,提供4针TTL电平测试端口1x UART1,DB9接口,提供6针TTL电平测试端口Ethernet 1x SGMII,RJ45接口,10/100/1000M自适应JTAG 1x 14pin TI Rev B JTAG接口,间距2.54mmFAN 1x FAN,12V供电,间距2.54mmBOOT SET 1x 5bit拨码开关SWITCH 1x电源开关POWER 1x 12V 2A直流输入DC417电源接口,外径4.4mm,内径1.65mm备注:广州创龙SOM-TL6655、SOM-TL6657核心板在硬件上pin to pin兼容。
DSP C6XX优化经验总结在C6XX的程序编写中,需尽量降低每一路的MCPS,以下是对编程过程中的经验总结。
(一)c6x的编译程序为“cl6x.exe”使用的方法Cl6x [options] [filenames]Cl6x:编译程序Options:编译选项Filenames:C或汇编源文件说明:1. 编译选项是一个字母或者两个字母,对大小写不敏感。
2. 编译选项的前面需要有一个“-”符号。
3. 一个字母的选项可以合并在一起。
比如“-sgq”与“-s -g -q”相同。
4. 两个字母的选项如果第一个字母相同也可以合并在一起。
比如“-mgt”与“-mg -mt”相同。
(二)有关优化的选项1. -mt:表示在程序中没有使用alaising技术,这使得编译器可以进行比较好的优化。
2. -o3:对文件级别进行最强的优化,一般在编译时应该使用这个选项。
但是在个别情况下使用这个选项优化程序可能会出现错误(-o2有相同现象,-o0和- o1不会出现错误)。
可能是在优化循环,组织流水线的时候发生错误。
如果有这种现象出现可以同时使用-g选项,程序优化就不会出现错误,但是优化效果会下降。
另外可以调整程序的表达方式,可能会避免编译器发生错误。
3. -pm:在程序级别进行优化。
可以将所以文件联合在一起进行优化,主要有去掉没有被调用的函数、总是常数的变量以及没有使用的函数返回值。
建议由程序员自己进行这种优化工作。
使用这个选项在win98下编译可能会出现找不到编译程序的情况。
4. -ms0:不使用冗余循环进行优化,减小程序的大小。
一般情况下这个选项对程序大小的优化作用不明显。
5. -mh[n]:去掉流水线的epilog,减小程序的大小。
这个选项的作用比较明显。
但是有可能出现读取地址超出有效范围的问题,所以要在数据段的开始和结尾处增加一些pading,或者在分配内存时保证数组的前面和后面一段范围内都是有效的地址。
可选的参数n给出这种pading的长度字节数。
1 创龙TMS320C665x基于广州创龙编写的RTSC组件的例程RTSC(Real-Time Software Components)实时软件组件,为嵌入式C语言引入组件技术。
组件(Component)技术是各种代码重用方法中最重要的一种方法,每个组件会提供一些标准且简单的应用接口,允许使用者设置和调整参数和属性。
用户可以将不同来源的多个组件有机地结合在一起,快速构成一个符合实际需要的复杂(大型)应用程序。
而基于广州创龙编写的RTSC组件的例程,其实目的是有效地简化对这部分操作,不需要用户编写代码就可以通过图形界面配置。
基于广州创龙编写的RTSC组件,可以生成为CCS插件,可以直接安装。
组件安装与TI发布的组件方法一致。
例如SYS/BIOS之类。
因SYS/BIOS程序运行后风扇停转,需要手动添加风扇的代码来解决此问题。
用RTSC 组件可以简单地解决这个问题,即boardlib_2_02_06_00组件,此组件位于Tools目录下,将此组件解压到CCS安装路径的ti目录下,打开CCS会识别到该组件,选中即可导入,成功导入后CCS会提示重启,重启后该组件生效。
图 1安装完成后可以在CCS新建工程窗口看到Fan组件。
图 2此处以SYS/BIOS例程中NDK_UDP为例进行操作。
右键选中NDK_UDP工程,在弹出的窗口点击属性项。
图 3图 4 打开CFG文件。
图 5图 6当组件添加到工程的时候,重新编译并运行这个程序时,风扇就会启动,转速可调。
7.1RTSC_Fan——对散热风扇转速进行控制基于广州创龙编写的RTSC组件的例程路径在光盘的"Demo/RTSC_C665x"文件夹下。
该程序实现的功能是通过定时器调整风扇定时器,控制频率来达到控制转速目的。
将开发板的串口和PC机连接,打开串口调试终端,按照工程导入步骤加载NonOS_Fan.out文件,然后点击程序运行按钮,串口打印信息如下:图7演示现象风扇转速在运行程序后降低。
DSP程序优化方法(4)DSP程序优化⽅法(4)9、采⽅递归与LISP之类的语⽅不同,C语⽅⽅开始就病态地喜欢⽅重复代码循环,许多C程序员都是除⽅算法要求,坚决不⽅递归。
事实上,C编译器们对优化递归调⽅⽅点都不反感,相反,它们还很喜欢⽅这件事。
只有在递归函数需要传递⽅量参数,可能造成瓶颈的时候,才应该使⽅循环代码,其他时候,还是⽅递归好些。
10、变量( 1)register变量在声明局部变量的时候可以使⽅register关键字。
这就使得编译器把变量放⽅⽅个多⽅途的寄存器中,⽅不是在堆栈中,合理使⽅这种⽅法可以提⽅执⽅速度。
函数调⽅越是频繁,越是可能提⽅代码的速度。
在最内层循环避免使⽅全局变量和静态变量,除⽅你能确定它在循环周期中不会动态变化,⽅多数编译器优化变量都只有⽅个办法,就是将他们置成寄存器变量,⽅对于动态变量,它们⽅脆放弃对整个表达式的优化。
尽量避免把⽅个变量地址传递给另⽅个函数,虽然这个还很常⽅。
C语⽅的编译器们总是先假定每⽅个函数的变量都是内部变量,这是由它的机制决定的,在这种情况下,它们的优化完成得最好。
但是,⽅旦⽅个变量有可能被别的函数改变,这帮兄弟就再也不敢把变量放到寄存器⽅了,严重影响速度。
看例⽅:a = b();c(&d);因为d的地址被c函数使⽅,有可能被改变,编译器不敢把它长时间的放在寄存器⽅,⽅旦运⽅到c(&d),编译器就把它放回内存,如果在循环⽅,会造成N次频繁的在内存和寄存器之间读写d的动作,众所周知,CPU在系统总线上的读写速度慢得很。
⽅如你的赛杨300,CPU主频300,总线速度最多66M,为了⽅个总线读,CPU可能要等4-5个周期,得。
得。
得。
想起来都打颤。
( 2)、同时声明多个变量优于单独声明变量( 3)、短变量名优于长变量名,应尽量使变量名短⽅点( 4)、在循环开始前声明变量11、使⽅嵌套的if结构在if结构中如果要判断的并列条件较多,最好将它们拆分成多个if结构,然后嵌套在⽅起,这样可以避免⽅谓的判断。
DSP程序优化方法(1)1、选择合适的算法和数据结构选择一种合适的数据结构很重要,如果在一堆随机存放的数中使用了大量的插入和删除指令,那使用链表要快得多。
数组与指针语句具有十分密切的关系,一般来说,指针比较灵活简洁,而数组则比较直观,容易理解。
对于大部分的编译器,使用指针比使用数组生成的代码更短,执行效率更高。
在许多种情况下,可以用指针运算代替数组索引,这样做常常能产生又快又短的代码。
与数组索引相比,指针一般能使代码速度更快,占用空间更少。
使用多维数组时差异更明显。
下面的代码作用是相同的,但是效率不一样。
数组索引指针运算For(;;){ p=arrayA=array[t++]; for(;;){a=*(p++);。
} }指针方法的优点是,array 的地址每次装入地址p 后,在每次循环中只需对p 增量操作。
在数组索引方法中,每次循环中都必须根据t 值求数组下标的复杂运算。
2、使用尽量小的数据类型能够使用字符型(char) 定义的变量,就不要使用整型(int) 变量来定义;能够使用整型变量定义的变量就不要用长整型(long int) ,能不使用浮点型(float) 变量就不要使用浮点型变量。
当然,在定义变量后不要超过变量的作用范围,如果超过变量的范围赋值,C 编译器并不报错,但程序运行结果却错了,而且这样的错误很难发现。
在ICCA VR 中,可以在Options 中设定使用printf 参数,尽量使用基本型参数(%c 、%d 、%x 、%X 、%u 和%s 格式说明符) ,少用长整型参数(%ld 、%lu 、%lx 和%lX 格式说明符) ,至于浮点型的参数(%f) 则尽量不要使用,其它C 编译器也一样。
在其它条件不变的情况下,使用%f 参数,会使生成的代码的数量增加很多,执行速度降低。
3、减少运算的强度(1)、查表(游戏程序员必修课)一个聪明的游戏大虾,基本上不会在自己的主循环里搞什么运算工作,绝对是先计算好了,再到循环里查表。
TMS320C6000系列DSP的软件优化1 DSP 系统的软件优化流程DSP 系统的软件优化流程如图1 所示。
整个工作流程分为3 个阶段:第1 阶段,直接根据需要用高级C 语言实现DSP 功能,测试代码的正确性。
然后,移植到C6X 平台,利用C6X 开发环境Profile 测试程序的运行时间。
若不满足要求,则进入下一阶段。
第2 阶段,利用C6X 提供的优化方式和其他各种优化技巧,如使用不同的编译器选项使能软件流水,循环展开,字存取代替半字存取等,优化C 语言代码。
如果还不能满足要求,则进入第3 阶段。
第3 阶段,将C 语言代码中耗时最长的部分抽取出来,用线性汇编语言重写,用汇编优化器进行优化。
使用profile 确定这段代码是否需要进一步优化。
2 优化过程首先,用C 语言编写程序,并通过编译验证其正确性。
然后,使用内联函数和合适的优化选项进行优化,并通过CCS 中的profiler 确定是否有函数需要被进一步优化,使用线性汇编语言重写需要被优化的函数。
最后,使用汇编优化编程技巧和汇编优化器优化汇编代码。
2.1 编译器当优化器被激活时,将完成图2 所示的过程。
C/C++语言源代码首先通过一个完成预处理的解析器(Parser),生成一个中间文件(.if)作为优化器(Optimizer) 的输入。
优化器生成一个优化文件(.opt),这个文件作为完成进一步优化的代码生成器(Code generator)的输入,最终生成汇编文件(.asm)。
当选择编译选项时,-o2 和-o3 将尽可能地优化软件。
2.2 编译器内联函数。
66AK DSP程序优化说明此文档不介绍具体技术细节,相关技术细节,还望仔细理解官方文档。
如有疑问:请加QQ156898965平台配置66ak存储资源结构:存储资源包括DDRA、DDRB,共享内存MSMC,每个核的局部L2、L1P、L1D。
由于整个芯片的地址空间是物理统一编址的。
L1,L2运行时钟为主频,常规64系列L2运行时钟为主频一半。
MSMSRAM 运行在主频。
DSP core直接读取L1,L2,通过MSMC读取SRAM,外部DDRA。
DDRADDRBL1P可配置程序缓存;L1D可配置数据一级缓存,2-WayCache;L2可配置数据二级缓存,4-WayCache。
缓存区域从高地址开始分配。
如下图:程序数据存放区域分类程序存放区域:用于存放所有可以执行的代码和常量,程序运行过程中,不会发生改变;数据存放区域:用于全局变量和局部变量保留的空间,程序运行过程中会发生改变;堆栈存放区域:为系统堆栈保留的空间,用于和函数传递变量或为局部变量分配空间。
若因意外改变,会导致程序跑飞。
平台配置通过新建或修改Platform文件来实现存储资源定义,Cache大小分配,及程序数据存放区域指定。
以66ak12为例,缓存区域L1P,L1D 全部设置为缓存,L2缓存大小设置为256k。
程序存放于DDRB,数据存放于L2,堆栈存放于L2进行。
配置过程如下:Debug模式下,选择tools -> RTSC Tools -> Platform -> New,根据自己的需要选择Platform保存的路径以及对应的芯片,Next,填入所需要的各种空间的大小和起始位置。
芯片选择时钟定义Cache配置数据存放区域指定平台调用及验证调用Platform:在工程查看窗口,相应工程上右键Properties,选择General -> RTSC,找到最后一项,Other Repositories,点击Add,路径选择上一步保存的路径,需要注意选择XDCtools版本,然后就能找到自己新建的Platform验证:查看通过自动生成CMD文件查看,如下图所示,L2SRAM大小为768K。
详细程序数据存放位置通过map文件查看。
程序调试过程中,通过ROV也能查看堆栈大小。
注意事项1.多核同时运行时,必须保证数据段,堆栈存放位置不重叠。
多核共享变量除外。
2.多核共用一个程序,程序区域位置可重叠,多核采用不同程序,程序存放区域也不能重叠。
3.未在平台配置文件中定义的区域,如不定义DDRA空间,也能通过绝对地址访问。
CACHE使用66ak DSPcore cache简要描述。
Cache是介于DSPCORE与MCMSRAM和外部DDR间高速缓冲器,解决系统中数据读写速度不匹配及读写方式不一样等问题。
针对读,L1,L2差不多,都是从cache里面找,找不到再去下一级存储区域读入。
数据读时,主要作用如下:减少重复读时间:刚刚使用的数据,很近的将来也可能会被用到。
如fir滤波的参数。
减少连续读时间:某地址单元的数据被用到,相邻地址也可能会被用到。
如fir滤波的输入数据。
针对写,L1 没有写缓存,L2有写缓存:L1 cache缓存里面存在时,写到L1;L1缓存里面没,立即写入到L2,CPU不等待,硬件自动完成。
L2 cache 不主动往下一级写结果,只有当缓存区满或用户指定是再写回下一级存储区域。
Cache配置基于sysbios配置参见上一节平台配置。
裸机情况下配置,参看相应的demo演示程序Cache影响运算速度测试以DDRA区域,长度为32K,数据类型分别为uint8,uint16,uint32,float,double进行加法,乘法测试。
Cache配置分别为L1D 32K、L2 512K,L1D 32K、L2 0K测试结果如下表:从上表可看成:1.不开启L2 cache,平均耗时会增加。
16位操作改变最大。
2.开启L2 cache,从快到慢uint8,uint16,float,uint32,doubleCache 同步1.L1D cache 同步L2采用绝对地址定义,常用作共享变量,共享核内L2,定义如下:#define CDHZ_SYNC_INT_FLAG (*( volatileunsignedint *)0x108BFFF0u)#define CDHZ_SYNC_INT_FLAG_ADD ( (unsignedint *) 0x108BFFF0u) 向该标记赋值是,需要强制写回;其他核读此标志时,需要强制刷新Cache。
相应的CLS函数为。
CACHE_wbL1d(addr, sizeBytes, CACHE_WAIT); /* Writeback L1D */CACHE_invL1d(addr, sizeBytes, CACHE_WAIT);/* Invalidate L1D */ 以核间同步作为实例,如下:if(coreNum == 0){CDHZ_SYNC_INT_FLAG = 0xaa55;CACHE_wbL1d ((void *) CDHZ_SYNC_INT_FLAG_ADD, sizeof(uint32_t) , CACHE_WAIT);}Else{do{CACHE_invL1d ((void *) CDHZ_SYNC_INT_FLAG_ADD, sizeof(uint32_t) , CACHE_WAIT);} while( CDHZ_SYNC_INT_FLAG != 0xaa55);}2.L2 cache 同步DDR:主要用于核间大量数据传递,需要保证下一级能获取到上一级完整运算结果。
相应CSL函数请参考开发文档。
以多核共用一个程序,每个核处理不同算法模块为例,实现方式如下:switch(coreNum){…case CORE_SYS_1:{CACHE_wbAllL2(CACHE_WAIT);CACHE_invAllL2(CACHE_WAIT);tscl0 = TSCL;tsch0 = TSCH;core1_task();CACHE_wbAllL2(CACHE_WAIT);tscl1 = TSCL - tscl0;tsch1 = TSCH - tsch0;System_printf("Debug(Core %d) %8x%8x cycles \n", coreNum, tsch1,tscl1);}break;…}注意事项1.重新加载程序时,内部存储区域的数据可能维持原值。
2.L2 cache DDR同步时,可只回写同步感兴趣区域。
3.注意缓存数据无效与回写的区别。
针对芯片的程序优化C66x DSPcore内核结构如下图所示,C66X DSP核中CPU数据通道包含如下几个部分1.两组通用寄存器组。
(部分寄存器就特殊用途,如堆栈SP等)2.八个功能单元。
(不同单元能同时运行)3.两个从memory装在数据通道。
4.两个向memory写入数据通道。
5.两个数据地址通道。
6.两个寄存器组交叉通道。
C66x CPU包含两组通用寄存器。
支持范围从打包8bit到数据128bit定点数据。
当超过32bit是,通过寄存器对进行存储。
C66x支持SIMD单指令多数据流,也QMPY32指令为例,同时执行4个32位乘法。
优化的目的主要就是确保内部多个功能模块同时运行,执行SIMD指令,及对部分C语言进行简化。
循环展开,流水优化循环展开,流水操作的主要目的是让多个功能单元同时执行,并行度受指令周期影响,是数据通道限制。
如下示意图所示,表示5个功能单元同时执行。
通过给编译器熟悉相应信息,编译器会循环(loop)流水优化。
主要设置项如下:1.程序优化--opt_level=2 (or -O2) and --opt_level=3 (or -O3)。
2.通过restrict告诉编译器地址参数地址不重叠3.MUST_ITERATE(min, max, multiple)指定最小循环次数,循环倍数以上实例,参见TMS320C6000Programmer’s Guide,第三章。
SIMD优化通过编译器指定UNROLL(),编译器自动优化。
通过mv 选项指定为c66。
如下图所示:内联函数intrinsics它可以将C几个指令周期才能完成的工作在一个指令周期内完成,大大的提高了程序的运行效率。
能高效的插入SIMD。
如下是常用指令_sadd(a,b) 32位饱和加法;_sadd2(a,b) 两个16位饱和加法,高16位和高16位相加,低16位和低16位相加;SIMD_ssub(a,b) 32位饱和减法;_smpy2(a,b) 两个16位饱和乘法;SIMD_dxpnd4 (a)低八位扩展至64位_dcmpeq4 (a, b) 8位打包8bit进行比较,产生8bit运算结果_amem8() 64位对齐数据存取_mem4() 32位非对齐数据存取综合实例也RGB转换为例,输入为24位连续存储的RGB原始数据。
采用定点乘法。
Gray = (R*19595 + G*38469 + B*7472) >> 16。
int rgb_to_y (const uint8_t *restrict pixel_array_rgb,uint8_t* restrict pixel_array_y,uint32_t total_pixel){int i,j=0;int result[4];longlong source,multiolier;multiolier = 0x00001D3096454C8B;#pragma MUST_ITERATE(16,,16)#pragma UNROLL(4);for(i = 0; i < (total_pixel); i = i+ 4){source = _unpkbu4(_mem4_const(&pixel_array_rgb[j]));result[0] = _dotpsu4h(source,multiolier)>> 16;j = j+3;source = _unpkbu4(_mem4_const(&pixel_array_rgb[j]));result[1] = _dotpsu4h(source,multiolier)>> 16;j = j+3;source = _unpkbu4(_mem4_const(&pixel_array_rgb[j]));result[2] = _dotpsu4h(source,multiolier)>> 16;j = j+3;source = _unpkbu4(_mem4_const(&pixel_array_rgb[j]));result[3] = _dotpsu4h(source,multiolier)>> 16;j = j+3;result[0] = _pack2(result[1],result[0]);result[2] = _pack2(result[3],result[2]);_amem4(&pixel_array_y[i]) = _packl4(result[2],result[0]);}return 0;}注意事项1.C66系列支持非对齐数据存储,采用_mem4()类intrinsics。