没有合适的资源?快使用搜索试试~ 我知道了~
首页TI C6XXX系列DSP软件优化策略
TI C6XXX系列DSP软件优化策略
需积分: 21 11 下载量 51 浏览量
更新于2023-03-16
评论
收藏 117KB DOC 举报
本文详细结绍了TI的C6XXX系列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 语言源程序作为注释。
-mw:在汇编语言文件加入软件流水线信息。
(四)有关调试和剖析的选项
-g:允许符号调试,在“out”文件中包含符号信息和行号信息,可以在 c 语言级别进行调试
和剖析。使用联合使用-g、-mt 和-o3 可以保
证能够进行符号调试的情况下最大限度的优化。
-mg:允许 profile 优化后的程序。 在“out”文件中包含符号信息和很少的行号信息。允许在
c 语言的函数基本进行剖析。
如果联合使用这两个选项,-g 选项可能被忽略,结果与只用-mg 相同。
(五)其它类型
-mln:生成大内存模式的程序。
-ml0:缺省情况下将集合变量(数组和结构)作为 far 型。
-ml1:缺省情况下将全部函数作为 far 型
-ml2: 等于-ml0 加-ml1
-ml3: 缺省情况下将全部数据和函数作为 far 型
(六)建议使用的编译方式
Cl6x -gk -mt -o3 -mw -ss “filename”
方式 1 用于程序的调试,这种方式具有比较强的优化能力,并且支持符号调试。在编译的
过程中不会发生错误。
由于生成的“out”文件中包含了符号信息和行号信息,所以比较大。
Cl6x -k -mgt -o3 -mw -ss “filename”
方式 2 用于程序的剖析(profile),这种方式的优化能力几乎最强(绝大多数情况下与方
式 3 相同),
并且支持对程序进行 profile。文件中只包含了符号信息和很少的行号信息,所以“out” 文件
比较小。
Cl6x -k -mt -o3 -mw -ss “filename”
方式 3 用于最终的发行版本程序,可以对程序进行最强的优化,并且去掉了全部的符号和
行号信息,所以“out”文件比较小。
由多个文件组成的程序应该编写 makefile,将编译参数放在该文件中,并在其中说明使用
的编译器的版本号。
(七)连接参数
-heap:指定堆的大小
-stack: 指定栈的大小
连接的各种选项应该统一放在“cmd”文件中
二、双重循环和多重循环的优化总结
双重循环多重循环看起来比较复杂,但实际上多重循环优化方法比较简单,就在于一个字
“拆”,一旦完成这一步之后,
多重循环就成为单层循环,优化就可以按照普通的单层循环来做了。
多重循环的特点是在优化器优化时只在最内层循环中形成一个 pipeline,这样循环语句就不
能充分利用 C6 的软件流水线,
而且对于内部循环的次数较少的情况,消耗在 prolog 和 eplog 上的 cycle 数也是不可忽视的。
针对这种状况可以考虑将多重循环拆开形成一个单层循环,可以拆外层循环也可以拆内层
循环,
一般视具体情况而定。这样就可以充分利用优化器构成的 Pipeline。如下例:
void fir2(const short input[], const short coefs[], short out[])
{
int i, j;
int sum = 0;
for (i = 0; i < 40; i++)
{
for (j = 0; j < 16; j++)
sum += coefs[j] * input[i + 15 - j];
out[i] = (sum >> 15);
}
内层循环循环次数较少,运算量也不大,资源方面只占用了一个乘法器,一个 cycle 只使用
一次乘法器,
而事实上我们可以在一个 cycle 内使用两个乘法器,所以还可以充分利用另外的一个乘法器。
因此考虑将内层循环拆开来执行,如下:
void fir2_u(const short input[], const short coefs[], short out[])
{
int i, j;
int sum;
for (i = 0; i < 40; i++)
{
sum = coefs[0] * input[i + 15];
sum += coefs[1] * input[i + 14];
sum += coefs[2] * input[i + 13];
sum += coefs[3] * input[i + 12];
sum += coefs[4] * input[i + 11];
sum += coefs[5] * input[i + 10];
sum += coefs[6] * input[i + 9];
sum += coefs[7] * input[i + 8];
sum += coefs[8] * input[i + 7];
sum += coefs[9] * input[i + 6];
sum += coefs[10] * input[i + 5];
sum += coefs[11] * input[i + 4];
sum += coefs[12] * input[i + 3];
sum += coefs[13] * input[i + 2];
sum += coefs[14] * input[i + 1];
sum += coefs[15] * input[i + 0];
out[i] = (sum >> 15);
}
这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到 pipeline 中来,在 Piped
loop kernal
中产生每一个 cycle 内都使用了两个乘法器,充分利用了 DSP 内部的资源,提高了运行效
率。又如下例:
tot = 4;
for (k = 0; k < 4; k++)
{
max = 0;
for (i = k; i < 44; i += STEP)
{
s = 0;
for (j = i; j < 44; j++)
s = L_mac(s, x[j], h[j - i]);
y32[i] = s;
s = L_abs(s);
if (L_sub(s, max) > (Word32) 0)
max = s;
}
tot = L_add(tot, L_shr(max, 1));
}
在这个多层循环中一共有三层循环,而最内层的循环的运算量很小,只有一次乘累加操作,
而我们知道 C6 中一个 packet 中可以做两个乘累加运算,所以为了增加内部循环的运算,
减少外部循环的层数,
我们可以将第一层循环的操作拆开,其负责的运算加入到内部循环中,也就是在内层循环
中一次做四次的乘累加运算,
这样将多次操作形成 pipeline,提高了运行效率,优化后的 C 代码如下:
tot = 4;
max0=0;
max1=0;
max2=0;
max3=0;
for (i = 0; i <44; i += STEP) //STEP=4, 11 times cirs
{
//code
for (j=0;j<=40-i;j++)
{s0=(Word32)(_sadd(s0,_smpy(hh[j],xx[j+i])));
s1=(Word32)(_sadd(s1,_smpy(hh[j],xx[j+i+1])));
s2=(Word32)(_sadd(s2,_smpy(hh[j],xx[j+i+2])));
s3=(Word32)(_sadd(s3,_smpy(hh[j],xx[j+i+3])));
}
}
//code
CCS 的优化:
三、16 位变为 32 位操作,使用 intrinsic 函数,用 const 等。
1、源代码:
Word32 L_mpy_ll(Word32 L_var1, Word32 L_var2)
{
double aReg;
Word32 lvar;
/* (unsigned)low1 * (unsigned)low1 */
aReg = (double)(0xffff & L_var1) * (double)(0xffff & L_var2) * 2.0;
/* >> 16 */
aReg = (aReg / 65536);
aReg = floor(aReg);
/* (unsigned)low1 * (signed)high2 */
aReg += (double)(0xffff & L_var1) * ((double)L_shr(L_var2,16)) * 2.0;
/* (unsigned)low2 * (signed)high1 */
aReg += (double)(0xffff & L_var2) * ((double)L_shr(L_var1,16)) * 2.0;
/* >> 16 */
aReg = (aReg / 65536);
aReg = floor(aReg);
/* (signed)high1 * (signed)high2 */
aReg += (double)(L_shr(L_var1,16)) * (double)(L_shr(L_var2,16)) * 2.0;
/* saturate result.. */
lvar = L_saturate(aReg);
return(lvar);
}
2、改编后的代码:
static inline Word32 L_mpy_ll(Word32 L_var1, Word32 L_var2)
{
Word32 aReg_hh;
Word40 aReg,aReg_ll,aReg_lh,aReg_hl;
aReg_ll = (Word40)_mpyu(L_var1, L_var2)>>16;
aReg_lh = (Word40)_mpyluhs(L_var1, L_var2);
aReg_hl = (Word40)_mpyhslu(L_var1, L_var2);
aReg_hh = _smpyh(L_var1, L_var2);
aReg = _lsadd(aReg_ll, _lsadd(aReg_lh, aReg_hl));
aReg = _lsadd(aReg>>15, aReg_hh);
return(_sat(aReg));
}
3、优化方法说明:
C6000 编译器提供的 intrinsic 可快速优化 C 代码,intrinsic 用前下划线表示同调用函数一样
可以调用它,即直接内联为 C6000 的函数。
剩余21页未读,继续阅读
livilditto
- 粉丝: 0
- 资源: 3
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
- SPC统计方法基础知识.pptx
- MW全能培训汽轮机调节保安系统PPT教学课件.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0