Visual DSP 编程讲稿.ppt_第1页
Visual DSP 编程讲稿.ppt_第2页
Visual DSP 编程讲稿.ppt_第3页
Visual DSP 编程讲稿.ppt_第4页
Visual DSP 编程讲稿.ppt_第5页
已阅读5页,还剩69页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、SHARC 系列DSP 编程和优化,本章要点:,IDDE的特点简述 SHARC系列DSP汇编语言程序设计 SHARC系列 DSP的C程序设计 链接器和链接描述文件 SHARC系列DSP程序的优化,IDDE的特点简述,Visual DSP+-IDDE的用户接口,SHARC DSP开发工具和流程,IDDE: 输出文件,IDDE: 编辑器,IDDE: 编辑器的特点,编辑器能够完成 自动识别关键字 自动识别注释等 支持标准的编辑操作 查找和替换 剪切和复制 选择等 可以设置不同的颜色区分关键字等 支持OLE拖拉 支持书签,SHARC系列DSP汇编语言程序设计,汇编语言程序特点,代数化语言 容易理解和学

2、习 可读性好 编译器支持伪指令 传统的结构 数据定义具有高级语言特点 预处理器处理宏 C的预处理器类似的工具,汇编语言程序结构,通过SECTION组织程序,SECTION 伪指令定义程序的段 至少需要代码和数据两个段,标识符,标识符(名称)必须以 26个大小写英文字母和下划线_开始; 可以包括09的数字符号; 大小写字母代表不同含义; 编译器使用的保留字是不能用于命名,表达式,汇编表达式与 C类似,如: 2.8e-3, l.67, (120-32)3, 0 x470 x7F,运算符及其含义,预处理伪指令,SHARC系列的汇编器包括一个能处理某些C语言形式的伪指令和宏的预处理器,这些伪指令包括(

3、必须小写): define undef if endif else elif ifdef if defined ifndef include,预处理伪指令例子,文件包含命令 #include private_header_file #include 宏用于条件汇编控制 #define DEBUG #ifdef DEBUG / 如果DEBUG已定义,编译此段 #endif 宏替换 符号常数 #define N 10 .var aN; #define arg(j) dm(i5+j) ar = arg(4); ar = dm(i5+4);,也可以在IDDE的defines对话框中设置,定义和使用宏(

4、Macro),例1 定义: define mac mrf=mrfR2*R5 使用: R2=R1 -R3; R5=DM(I0,M0); mac ; 例2 定义: define copy(src,dest) R0=DM(src); PM(dest)=R0,使用: copy(0X3f,0Xc0);,将3f地址的值拷贝到c0地址,宏定义必须在一行内写完,超过一行时,在行末加续行标志“”,,Include伪指令,include有两种形式: include“文件名” 在当前和指定途径中搜索指定文件 include 仅在指定途径中搜索指定文件 def21060.h 是很重要的头文件,它包含了对ADSP210

5、6X中大量寄存器、位段、初始化值、I/O地址等惯用名称的定义,汇编伪指令(1),汇编伪指令经汇编器处理后不产生代码,它们都以“”打头: SECTION 标记段的起始 ENDSEG 标记段的结束 VAR 定义变量或缓冲 PRECISION=3240 定义浮点精度,32 bit为默认 ROUND=ZERO 浮点常数取整方法:向零取近似 ROUND_MINUS 浮点常数取整方法:负向取近似 ROUND_PLUS 浮点常数取整方法:正向取近似,汇编伪指令(2),ROUND_NEAREST 浮点常数取整方法:取最接近值(默认) PORT 定义存储器映射的I/O口 GLOBAL 使一个符号全局化(其它文件

6、可用) EXTERN 使一个符号外部化(由其它文件定义) NEWPAGE 在列表文件中(lst)开启新页,SECTION伪指令,程序的每一部分都应该有一个有名段(named section) 在汇编语言中指明 编译器有默认的段名称 汇编程序中必须指明段名 .section name 有效范围到下一个段指定 如果需要,编译器会利用 “section” 命令产生非默认的段 LDF中指定每个段如何放置到存储区中 许多源文件中都可以命名段,默认段名,默认段名由默认的LDF支持 编译器使用默认段名如下: code: program dm data: data1 pm data: data2 system

7、 use: stack, heap, ctor 用户可以定义自己的段名,然后修改LDF,数据定义,定义数据的伪指令是: .var 格式: .var 符号名 定义符号 保留空间: 1 各或者多个字 可选: 初值表 举例: .var a; .var b=10; .var c37; .var d6 = 1, -1, 5, -5, 0 xA, -10; length(d) / expression returning / declared size (6) 可以指定符号的作用域 .global 符号名 / 全局,在本模块定义,外部也可以使用 .extern 符号名 / 外部,在其它模块定义,汇编程序举

8、例(DMPM数据传输),/*_ Dtran.ASM ADSP-2106x Data transfer _*/ #include def21060.h /* IOP register definitions */ #define N 64 .SECTION/DM dm_data; /* Declare variables in DM */ .VAR inputN= sin64.dat; .ENDSEG; .SECTION/PM pm_data; /*Declare variables in PM */ .VAR outputN; .ENDSEG;,汇编程序举例(DMPM数据传输)-续,.SECT

9、ION/PM pm_rsti; /* The interruput vectors */ NOP; JUMP start; /* rest vector */ NOP; NOP; RTI; RTI; RTI; RTI; /* other vector */ .ENDSEG; .SECTION/PM pm_code; /* Example program for data transfer */ start: I0=input; M0=1; I8=output; M8=1; LCNTR=N,DO LOOP1 UNTIL LCE; F0=DM(I0,M0); LOOP1: PM(I8,M8)=F0

10、; NOP; IDLE; .ENDSEG;,SHARC系列 DSP 的C程序设计,C和C编程的基本特点,优势:可移植性好,维护方便,缩短开发周期 完全的ANSI 标准 加上 C+ 特点的注释 可扩展性好 完整的特征库 完整的标准数学函数支持 附加的 DSP函数 基本I/O: printf, 简化的文件 I/O DSP扩展功能 高效优化器 完全集成的开发环境 编辑、编译支持 实时系统支持 源代码级调试,优化器(Optimizer)特征,提高程序的效率 减小程序代码空间需求 可选择:最小空间需求,或者最高速度要求 优化过程清楚明确 清理:“out of the box”的代码将很好地完成 提示妨碍

11、优化的事情 用户可以检查程序优化的结果 选择 “stop after compiler” ,可以使用编辑器打开相应的源文件(.s),支持DSP的特殊功能(1),优化器自动实现特殊的硬件特征 专门的并行指令(多功能指令) 零开销循环 MAC 指令 DSP语言扩展 双端口存储器空间 - “pm” 限制 DSP 数据类型: 复数、小数、 饱和算法 支持特殊功能 有效的访问DSP硬件资源的能力 特定的操作 访问系统寄存器、 I/O 空间等 全局中断使能/屏蔽 使用库函数模块 效率:可以容易的编译成为1条或者多条指令 完全优化,支持DSP的特殊功能(续),增强库 实现附加类型 .float , long

12、 double .complex (float, 包括 fract16) .fract16 可以使用DSP的特殊功能 基本矢量和矩阵操作 滤波和变换 统计分析 容易与汇编子程序接口 asm() 行嵌入方式 允许小段的汇编指令嵌入到C 可以适应大多数情况,C/C+与汇编程序的接口方法,C与汇编接口的注意事项,在下列情况需要注意接口问题: C调用汇编语言子程序 汇编语言中使用了库函数 使用了标准的中断调度程序 需要特别注意的是: C实时堆栈由帧指针(I6)和堆栈指针(I7)管理地址寄存器 最好保留它们,尽管可能并不使用堆栈 堆栈的完整性借助 debugger可以观察 函数参数和返回值处理 编译器是

13、按照约定的规则 寄存器可以分为: 保留寄存器和临时寄存器 编译器把某些寄存器指定为特定值或者功能,C/C+与汇编程序的接口方法,C/C+程序和汇编程序可以互相调用,在C/C+程序中调用汇编程序有3种方式: 把C变量和汇编语言符号联系起来; 编写可用C调用的汇编子程序函数; 利用行嵌入汇编语句。,联系C变量和汇编语言符号,使C程序和汇编程序使用同一变量,要求: 变量在C程序和汇编程序中都说明成全局变量 在汇编中的汇编变量命名为下划线“_”加C的变量名,以便明确其对应关系。如: C函数: int count_start(); 汇编声明为: . global _count_start; 使用此功能时

14、要注意: 全局变量必须在函数定义前声明; 选择始终被调用函数安全保存、恢复的寄存器; 寄存器用以表示全局变量后,它将不会被其它函数使用。,C调用汇编函数时的参数传递,函数参数传递可以通过: 寄存器 堆栈 参数传递规则: 最多允许3个参数通过寄存器传递,并且左起三个参数依次传递到R4,R8,R12; 如果有一个参数传到堆栈,其右边的所有参数都应传到堆栈; 字宽大于32位的复数或双精度型将传递到堆栈,且占用两个连续的地址单元: 实部在低地址、虚部在高地址; 或者高32位在低地址、低32位在高地址 函数参数个数可变时,最后一个有名参数进入堆栈。,函数参数传递例子,foo(int a, float b

15、, char c,float d); bar(int a, double b,char c,float d); test(float a, int b,char c,);,aR4, bR8,cR12,d堆栈,aR4, 其余进入堆栈,参数个数可变,aR4,bR8,c堆栈,汇编函数返回值传递,被调用的汇编函数在返回前必须完成: 把返回值存入寄存器R0、R1。 单字时放在R0中; 双精度字时,高32位放在R0,低32位放在R1; 复数时,实部放在R0,虚部放在R1; 返回值是大于二个字的结构型时,R1指向结构地址。 被保存并有新值覆盖的编译寄存器必须恢复其旧的保存值: 通过以帧指针I6为基准即可从堆

16、栈中恢复这些寄存器。 原堆栈指针I7也要恢复,即执行指令I7I6。 原帧指针I6必须从堆栈恢复,在入口处,I6值经R2再压入堆栈。,C/C+程序调用汇编子程序举例(1),C程序中需要 为汇编子程序建立函数原型 汇编程序需要 汇编子程序名称应该以下划线开始 或者使用extern “asm” 方式说明 寄存器使用原则: 实时库的临时寄存器汇编程序可以使用且不需要保护 汇编程序在使用预保留的寄存器时,必须保护和恢复其内容。 汇编程序中不允许使用专用寄存器。,C/C+程序调用汇编子程序举例(2),/* C源程序*/ #include define rows 30 define columns 30 f

17、loat dm x_inputrowscolumns; float pm y_inputrowscolumns; int count_start(); int count_end(int); volatile int time_temp,cycle_count;/*定义变量*/,汇编函数count_start说明为全局函数,它返回矩阵计算前的仿真时钟数,汇编函数count_end说明为全局函数,输入参数为计算前的仿真时钟数,返回值为计算矩阵所需的时钟数,C/C+程序调用汇编子程序举例(3),void main(void) int i; for(i0;irows*columns;i+) x_in

18、put0i=(float)i; y_input0i=(float)i; time_tempcount_start(); for (i = 0, i rows * columns; i+) output0i = x_input0i + y_input0i; cycle_count = count_end(time_temp); printf(The cycle count is %d cycles.n,cycle_count); exit(0); ,调用汇编函数, 记录开始仿真的时钟数,调用汇编函数,返回给定程序段花费的时钟数,C/C+程序调用汇编子程序举例(4),/*汇编函数源代码*/ #in

19、clude def2l060.h“ #include asm_sprt.h“ .section/pm seg_pmco; .global _count_start; .global _count_end; _count_start; R1=MPDE1; BITCLR MODE1 IRPTEN; /* 清全局中断使能*/ R0=emuclk; /* 将时钟数放到R0中 */ MODE1 =R1; exit;,为了与C中的函数声明关联,函数在汇编程序中加前缀“_”,即名称为: _count_start 和_count_end,汇编函数_count_start定义,C/C+程序调用汇编子程序举例(5

20、),_count_end; /* 计数结束函数 */ R2=MODE1; BIT CLR MODE1 IRPTEN; /* 清全局中断使能 */ R0=emuclk; /* 将当前仿真时钟数放到R0中 */ R0=R0-R4; /* R4所放的数值为函数输入参数,即计算开始时 的仿真时钟数,将计算前后的时钟差值放到R0中*/ R1=l4; /* 调用计数函数所多用的14个周期 */ R0=R0-R1; /* 减去多用的14周期后,将结果放在R0中返回*/ MODE1 =R2; exit; .endseg,汇编函数_count_end定义,链接器和链接描述文件,SECTION在链接时的作用,链接

21、器:命名的容器(Named Containers),先讨论容器,然后讨论 LDF. 各种容器: 输入段(Input Sections) 输出段(Output Sections) 存储器段 描述链接过程的基本单位 轮流查看各个容器,链接描述文件(LDF)的功能,控制链接器的操作 指定一般的配置 目标系统结构 库及其查找路径 需要链接的特殊目标文件 指定每个处理器的物理属性 存储器的物理结构 把它们分配到可以接收程序的逻辑单元 输入段如何映射到输出段和存储器 支持重叠、存储器共享和多处理器,如何获得LDF?,改写已有的LDF 在VisualDSP+的IDDE环境中查找合适的LDF 利用已有的LDF

22、,根据目标系统需要改写 利用专家链接器(Expert Linker) VisualDSP+V3.0支持专家链接器 专家链接器可以自动产生LDF 用户只需按照操作步骤,选取所需属性,链接描述文件举例,ARCHITECTURE(ADSP-21062) SEARCH_DIR( $ADI_DSP21klib) $LIBRARIES = lib060.dlb ; $OBJECT1 = main.doj,$COMMAND_LINE_OBJECTS;,MEMORY mem_isrTYPE(PM RAM) START(0 x00008000) END(0 x000080ff) WIDTH(48) mem_pm

23、coTYPE(PM RAM) START(0 x00008100) END(0 x000087ff) WIDTH(48) mem_pmdaTYPE(PM RAM) START(0 x00009000) END(0 x00009fff) WIDTH(32) mem_dmdaTYPE(DM RAM) START(0 x0000c000) END(0 x0000dfff) WIDTH(32) ,PROCESSOR p0 OUTPUT( $COMMAND_LINE_OUTPUT_FILE ) SECTIONS dxe_isr INPUT_SECTIONS ($OBJECT1 (isr_tbl) ) m

24、em_isr dxe_pmco INPUT_SECTIONS ($OBJECT1 (seg_pmco) ) mem_pmco dxe_pmda INPUT_SECTIONS (main.doj (seg_pmda) ) mem_pmda dxe_dmda INPUT_SECTIONS (main.doj (seg_dmda) ) mem_dmda /*End sections command for processor po */ /* End processor command,处理器类型 搜索路径、宏,P0存储器分配,P0链接命令,LDF命令ARCHITECTURE,命令格式: ARCHI

25、TECTURE (处理器类型) 如: ARCHITECTURE (ADSP-21062) LDF中只能包含一个ARCHITECTURE()命令,这个命令必须位于全局范围内应用于整个LDF文件。 指定系统的处理器 允许错误检查 链接器已知的存储器大小和形式,LDF命令SEARCH_DIR, $LIBRARIES,SEARCH_DIR( $ADI_DSP21klib) 指定库文件的搜索路径 默认为当前目录 可以指定多个目录 搜索的次序是从左到右 如果不指定,默认在命令行里指定 $LIBRARIES= 一个宏,等号后面是链接的库文件名称,LDF命令$OBJECT1,$OBJECT1 = main.d

26、oj,$COMMAND_LINE_OBJECTS; 指定需要链接的目标文件 特定文件 头文件管理通用的程序和处理器初始化 $COMMAND_LINE_OBJECTS由IDDE从工程中给出 $OBJECT1是一个宏,LDF命令Processor,命令格式: 用于指定处理器存储器和链接信息 对处理器p0进行唯一的指定,包括: OUTPUT 输出执行文件名称 MEMORY 定义存储器 SECTIONS 链接器的链接选择 其它信息 如果是多处理器,每个处理器需要分别指定,processor processor_name OUTPUT(output_file_name.dxe) MEMORYsegmen

27、t_commands SECTIONSsection_commands,LDF命令MEMORY,mem_isrTYPE(PM RAM) START(0 x00008000) END(0 x000080ff) WIDTH(48),MEMORY Segment_Commands,LDF命令sections,命令格式:,SECTIONS SECTION_STATEMENTS,section_namesection_typesection_commands mem_segment,INPUT_SECTIONS(file_sourcearchive_menber(input_labels),LDF ma

28、cro List_of_file,Section中输入/输出段和存储器的对应关系(默认),LDF的SECTION例子分析,SECTIONS sec_code INPUT_SECTIONS ( $OBJECTS (program) $LIBRARIES (program) mem_code sec_data1 INPUT_SECTIONS ( $OBJECTS (data1) $LIBRARIES (data1) mem_data1,输入SECTION,输出存储区. 任何输出都必须指定到一个已命名的存储器,输出段名称,运行经过所有的指定文件,处理有名段名称,库文件也经过类似处理,LDF:MEMO

29、RY和SECTION中的段,SECTIONS p /* section 命令 */ mseg_one; d /* section 命令 */ mseg_two; q /* section 命令 */ mseg_one;,MEMORY mseg_one /* 段定义 */ mseg_two /* 段定义 */ ,LDF的其它能力,多处理器链接 对称和非对称的 共享存储器 (SHARED_MEMORY命令) 分离程序 (LINK_AGAINST 和 RESOLVE命令) 重叠支持 重叠放置 (OVERLAY_INPUT和 OVERLAY_GROUP命令) 分离输出文件 (OVERLAY_OUTPU

30、T 命令) 重叠管理器的半自动PLIT构造 其它控制命令 FILL (存储器填充) 指定 (INPUT_SECTION_ALIGN 命令),SHARC系列DSP程序的优化,程序优化的方法和途径,实施高级优化(首选) 最有效的方法保留了可移植性 改进算法 使算法更适合硬件结构 挖掘机器的能力 可以使用专用指令(库/可移植) 调查所处理特定要求 不可移植的改变(最后使用) 利用 C语言? 利用汇编语言? 优化的目的 时间(速度)? 空间?,观察一个优化的简单例子,源代码: (1) a = b * c; (2) d = a + f; (3) a = b -g;,“a”的值可直接送到寄存器,不必经过存

31、储器,新值指定到“a”,也不必送到存储器,直接翻译后的代码 R2 = dm(_b); R3 = dm(_c); R1 = R2 * R3; Dm(_a) = R1; R1 = dm(_a); R6 = dm(_f); R4 = R1 + R6; dm(_d) = R4; R2 =dm(_b); R7 = dm(_g); R1 = R2 - R7; dm(_a) = R1;,优化后的代码 R2=dm(_b); R3 = dm(_c); R1 = R2 * R3; R6 =dm(_f); R4 = R1 + R6; dm(_d) = R4; R7 = dm(_g); R1 = R2 - R7; d

32、m(_a)=R1;,12个周期,9个周期,利用硬件的并行处理能力再次优化,源代码:(1) a = b * c; (2) d = a + f; (3) a = b - g;,并行处理后的代码 R2 = dm(_b); R3 = dm(_c); R1 = R2 * R3,R6 = dm(_f); R4 = R1 + R6,R7 = dm(_g); R1 = R2 - R7,dm(_d)=R4; dm(_a) = R1;,优化后的代码 R2=dm(_b); R3 =dm(_c); R1 = R2 * R3; R6 =dm(_f); R4 = R1 + R6; dm(_d) = R4; R7 = dm

33、(_g); R1 = R2 - R7; dm(_a)=R1;,6个周期,优化练习1:矢量A*B+C,计算公式,第一次:每次循环6个周期,lcntr = LENGTH, do loopend until lce; f0 = dm(i0,m1); /* 读A*/ f1 = pm(i8,m9); /*读B */ f3 = f0 * f1; /* 计算 A * B*/ f4 = dm(i1,m1); /*读 C */ f3 = f3 + f4; /* 把C与积相加 */ loopend: dm(i2,m1) = f3; /* 存放结果 */,第二次:每次循环3个周期,f0=dm(i0,m1), f1=

34、pm(i8,m9); /* 读A和B */ lcntr=LENGTH-1, do loopend until lce; f3=f0*f1, f4=dm(i1,m1); /* 计算A * B, 读C */ f3=f3+f4, f0=dm(i0,m1), f1=pm(i8,m9); /* 加C, 读A和B */ loopend: dm(i2,m1)=f3; /* 存放结果 */ f3=f0*f1, f4=dm(i1,m1); /* 计算A * B, 读C */ f3=f3+f4; /* 加C */ dm(i2,m1)=f3; /* 存放结果*/,循环准备,先读入第一组值,循环体部分,循环退出部分,完成结束循环时剩余的计算,第三次:每次循环2个周期,f0=dm(i0,m1), f1=pm(i8,m9); /* 读A和B */ f3=f0*f1, f4=dm(i1,m1); /* 计算A * B, 读C */ f3=f3+f4, f0=dm(i0,m1), f1=pm

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论