Chapter 1
Introduction
Why go digital?
数字信号处理技术的功能十分强大,它所达到的处理性能和指标,往往是模拟处理技术难以达到的。例如:
FIR filter with linear pha.
Adaptive filters.
chapter2
C6000的结构概述
General DSP System Block Diagram
一个DSP系统通常由CPU、内部存储器、外部存储器、片内外设,以及连接它们的内部和外
部总线组成。
为了提高对数字信号的处理速度,DSP处理器针对DSP的典型算法,在结构和功能模块等方面进行了优化。下面我们通过对C6000结构的研究,来了解DSP处理器的特点。
Implementation of Sum of Products(SOP)
在第一章中已经指出:积之和SOP是大多数DSP算法中的关键要素。下面我们通过编写实现级数计算的代码,来深入理解C6000的结构。
Implementation of Sum of Products(SOP)
该代码模块用汇编语言编写,其好处是汇编语言与处理器的结构密切相关,便于我们了解DSP的结构。
从级数的计算公式看,实现该算法有两个基本的操作:
(1) 乘法计算
(2) 加法计算
因此,要有两条基本指令:乘法指令和加法指令。
Multiply(MPY)
系数a1和采样值x1的乘法用下面汇编指令实现:
MPY a1,x1,Y
该指令的功能是:将a1和x1相乘,并将乘积送给Y。
Multiply(.M unit)
该指令由一个硬件乘法器单元完成,该单元称之为“.M”单元。
qzone所以,乘法指令更改为:MPY .M a1,x1,Y
16位乘16位的乘法器得到32位的结果。
32位乘32位的乘法器得到64位的结果。
Addition(.?)
下面考虑加法操作:
MPY .M a1,x1,prod
ADD .? Y,prod,Y
加法指令将前一条指令计算出的乘积prod,累加到Y中。
这里要考虑一下加法指令是如何实现的?
Addition(.L unit)
C6000中有一个.L单元,加法指令就是通过该单元实现的。因此,代码要改为:
MPY .M a1,x1,prod
ADD .L Y,prod,Y
Register File-A
C6000是RISC处理器,这类处理器用寄存器保存操作数,所以刚刚写的代码还要修改。用寄存器取代a1、x1、prod、Y。
Specifying Register Names
C6000的CPU中有两组寄存器:A、B。每组寄存器由16个寄存器组成,每个寄存器的宽度是32比特。
MPY .M A0,A1,A3
ADD .L A4,A3,A4
寄存器A0、A1、A3、A4包含了这两条指令要用的数值。
Data Loading
通过刚才讨论,我们看到:操作数是存放在寄存器中的。那么,如何将操作数加载到寄存器中去呢?
Load Unit“.D”
电脑尺寸在哪里看C6000CPU中有个.D单元,通过这个.D单元就可将操作数从数据存储器加载到寄存器中。
值得注意的是:.D单元是访问数据存储器的唯一方法。
Load Instruction
下面要考虑的是:将操作数从数据存储器加载到寄存器中,应该用什么指令?
其答案是加载指令。(LDB、LDH、LDW、LDDW)
Using the Load Instructions
在使用加载单元之前,必须要清楚处理器是按字节寻址的,也就是说:存储器中每个字节对应一个唯一的地址。
地址的宽度是32位,可寻址范围:00000000~FFFFFFFF。
Using the Load Instructions
加载指令的句法是:LD *Rn,Rm
其中,Rn是一个寄存器,该寄存器中存放的是要加载操作数的地址,作为寄存器指针。
Rm是目的寄存器。讲诚信
Using the Load Instructions
现在的问题是:加载到目的寄存器中的数据宽度(位数)如何确定?
Using the Load Instructions
长高的征兆
这可以通过选用不同的指令来完成。
LDB:加载1个字节(8比特)
LDH:加载半个字(16比特)
LDW:加载1个字(32比特)
LDDW:加载1个双字(64比特)
注意:不存在LD指令。
Using the Load Instructions
例如:假设A5=0x4
LDB *A5,A7;A7=0x00000001
LDH *A5,A7;A7=0x00000201
LDW *A5,A7;A7=0x04030201
LDDW *A5,A7;A7=0x0807060504030201
Using the Load Instructions
请大家思考这样一个问题:如果只能通过加载指令和.D单元访问数据存储器,那么我们首先如何加载寄存器指针Rn呢?
Loading the Pointer Rn
指令MVKL可以将一个16位的常数移入到一个寄存器的低16位中。
MVKL .? a,A5;a是一个常量或标号。
一个完整的地址有32位,所以要将一个32位的地址移动到一个寄存器中,而所有的指令宽度为32位,所以不能进行一个32位的数据移动。
Loading the Pointer Rn
使用指令MVKH可以解决32位的数据移动问题。
MVKH .? a,A5;将一个16位的常数移入到一个寄存器的高16位中。
这样,使用下面代码就可以将32位的地址移到一个寄存器中:
MVKL .? a,A5
MVKH .? a,A5
Loading the Pointer Rn
MVKL指令和MVKH指令的使用是有顺序的。请看下面两个例子。
江西明月山风景区由于MVKL指令存在符号位扩展问题,所以要MVKL在前,MVKH在后。
LDH,MVKL and MVKH
pt1和pt2指向数据存储器中的存储单元,用MVKL和MVKH指令分别加载到A5和A6中。
A5和A6所指的数据存储器单元内容用LDH指令分别加载到A0和A1中。
Creating a loop
在前面的讨论中,我们实现了Y=a1*x1的计算。但这只是SOP计算中的一个节点,我们还要通过循环操作实现N节点SOP计算。
Creating a loop
在C6000处理器中,没有专门的块重复指令。循环要用分支转移指令B实现。
What are the steps for creating a loop
1. 创建一个要转移的目标地址的标号。
2. 添加一条分支转移指令B。
3. 创建一个循环计数器。
4. 添加一条将循环计数器减一的指令。
5. 根据循环计数器的值,建立分支转移的条件。
1. Create a label to branch to:loop
2. Add a branch instruction, B:B .? loop
Which unit is ud by the B instruction?
.S单元用于分支转移指令B和数据移动指令MVKL、MVKH。
3. Create a loop counter:MVKL .S count,B0;B0计数器后面介绍。
4. Decrement the loop counter:SUB .S B0,1,B0
5. Make the branch conditional bad on the value in the loop counter
建立指令条件的方法是:在指令前面加上条件,这样原来的非条件指令就变成了条件指令。只有条件满足的情况下,该指令才能执行。
[condition] Instruction Label
例如:[B1] B loop
(1)条件可以是下列寄存器之一:A1、A2、B0、B1、B2
(2)所有指令都可以变成条件指令。
5. Make the branch conditional bad on the value in the loop counter
在条件前面加“!”号,可以使条件取反。
[!condition] Instruction Label
有温度的话语例如:
[!B0] B loop;如果B0=0,则转移到loop
[B0] B loop;如果B!=0,则转移到loop
5. Make the branch conditional bad on the value in the loop counter
[B0] B .S loop
More on the Branch Instruction(1)
C6000处理器的所有指令编码成32位。
因此,分支转移指令B 的目的地址要小于32位。实际上,32位B指令中,低21位是要跳转的相对地址。
例1:B .S1 label
相对转移,偏移量+/- 220。
More on the Branch Instruction(1)
指定一个寄存器,而不使用标号,可以实现绝对转移。转移范围可达:232。
此时,分支转移指令B 的编码中,低5位指出存放要跳转的目标绝对地址的寄存器。
例1:B .S2 register
绝对转移,仅由.S2单元实现。
Testing the code
折纸灯笼该代码完成下面运算:
a0*x0+a0*x0+a0*x0+...+a0*x0
而我们希望完成下面计算:
a0*x0+a1*x1+a2*x2+...+aN*xN
问题在于:从数据存储器中取数据的过程中,没有修改数据指针,从而造成每次循环时取的是同一对数据。
Modifying the pointer
解决方法是修改指针A5和A6。
下面讨论索引指针的方法。
自我介绍英文作文
Indexing Pointer
在寄存器R前面加“*”:*R。其含义是R做为指针,在使用过程中不被修改。R可以是任意一个寄存器。
Indexing Pointer
在寄存器R前面加“*+”,后面加“[disp]”:*+R[disp]。其含义是R做为指针,在使用前被修改,使用后恢复为原来的值。
在寄存器R前面加“*-”,后面加“[disp]”:*-R[disp]。其含义是R做为指针,在使用前被修改,使用后恢复为原来的值。
[disp]指明数据元素的大小:DW(64位)、W(32位)、H(16位)、B(8位)
disp=R或5位的常量。
R可以是任何一个寄存器。
Indexing Pointer
在寄存器R前面加“*++”,后面加“[disp]”:*++R[disp]。其含义是R做为指针,在使用前被修改,使用后不恢复为原来的值。