引言
TMS320C55x(以下简称C55x)是德州仪器公司推出的新一代低功耗高性能16位定点数字信号处理器(DSP)。2002年初,德州仪器公司相继推出了TMS320C55x系列中TMS320VC5510的正式版本,以及TMS320VC5509和TMS320VC5502。C55x是在TMS320C54x(以下简称C54x)的基础上发展而来的,其源代码也与C54x的兼容。C55x达到了C54x的2倍的周期效率,并且只有C54x的1/6的功耗。C55x优异的性能和极低的功耗使其成为具有相当竞争力的DSP产品。
C55x是从C54x的基础上发展而来的,在结构上做了相当大的扩展,在指令集上也有很大的提高。C55x继续使用C54x在代码密度上建立的获得更低系统成本的标准,并将其进一步发展为采用1~6字节的可变字节宽度的指令,以提高代码密度。使用这种可缩放的指令字长度,C55x每个功能的控制代码可以比C54x的减少最多达40%。C55x还增加了总线宽度,其指令单元每次可从内部或外部存储器取32位程序代码(C54x每次只能取16位)。C55x含有指令高速缓存器(cache)以使外部存储器访问最少,改善数据吞吐率和省电。这种指令集的设计与低功耗需求结构的联合使用,使得应用系统具有极高的性能。
C55xDSP的最大特点就在于,其强有力的并行特性和方便用户编程的流水线自动保护机制,而C55x并行指令的实现和指令的高效率执行,在很大程度上都依赖于指令流水线的支持。
1TMS320C55x的指令流水线
DSP指令的执行,可以是直接执行,如AD公司的218x系列DSP,也可以采用指令流水线的方式。德州仪器公司的DSP产品一般都采用指令流水线的工作方式,即一条指令的执行分为若干个阶段完成,就像经过工厂里的生产流水线上的一道道工序一样,而同时,在流水线的其它阶段又分别有其它的指令在顺序地执行着。采用指令流水线的执行方式,可以大大提高系统的执行效率,使得系统可以低延迟或“无延迟”地执行较复杂的指令。因此,更多的DSP开始采用指令流水线的执行方式。
C55x继承了C54x的指令流水线的执行方式,其流水线分为两个分离的阶段,即“取指阶段”和“执行阶段”。在取指阶段,将4字节的指令包取入指令缓冲队列,这里面又包括提交地址、取指、预译码等4个阶段;而在执行阶段,则完成指令的译码执行,又可分为译码、取操作数、执行、写回结果等8个阶段。图1是“取指阶段”和“执行阶段”的示意图。
其中“数据回写+”只出现在数据写入存储器的指令中。
C55x的指令流水线一般由程序流单元(PU)控制。程序流单元对指令译码,分派指令到寻址单元(AU)和数据运算单元(DU),并管理全部的保护流水线,其具有的预测转移能力可以避免条件指令执行引起的流水线刷新。
2TMS320C55x指令流水线的自动保护机制
虽然采用指令流水线的工作方式,可以提高系统的效率,但不同的指令执行情况不同,就有可能造成流水线的冲突。如:当一条指令想写入某寄存器时,前一指令还未完成对该寄存器的读取操作,就会产生流水线冲突的问题,这时候就必须对流水线进行保护,确保前一指令的读取操作完成后才修改该寄存器的值。遇到这样的情况,必须在第二条指令之前加入等待延迟。如:在设计C54x程序时,就需要程序设计人员在可能发生流水线冲突的指令前后手工加入NOP(空操作)指令或调整指令的顺序,以使第二条指令执行时能取到正确的操作数。时刻关注流水线的冲突问题,在编程时是非常麻烦的;而在C55x中,由于采用多指令并行操作,流水线的冲突问题也就越发严重。但幸运的是,C55x中的指令流水线具有自动保护机制,其自动保护机制会在可能引起冲突的指令之间自动增加不活动的周期,以避免冲突的发生。这些都是在指令执行时自动加入的,不需要设计人员亲自去添加等待周期,从而省去了在编程时对流水线冲突进行调整的工作,大大降低了编程和调试的难度。而且,也正是由于指令流水线有了自动保护机制,才使得设计人员可以放心地使用C55x的并行指令。
3如何减少指令流水线的保护和延迟
虽然C55x的自动保护指令流水线结构降低了编程时的复杂度,但指令流水线的保护造成的延迟也是影响C55x程序执行效率的一个重要方面。
指令流水线的执行方式会产生流水线的冲突和保护,而C55x支持多指令同时执行,流水线冲突与保护的问题更加严重。所以,减少流水线的冲突,即减少流水线保护造成的延迟,对DSP的执行效率是大有影响的。下面就介绍流水线冲突的可能原因和如何避免流水线冲突,以尽量减少流水线保护机制所带来的延迟。
①对寄存器访问的竞争是影响流水线保护和延迟的主要原因。如果出现要对某寄存器读取/写入的时候,前一指令对该寄存器的写操作/读操作还未完成的情况,就会造成流水线保护和延迟。在以寄存器为条件执行指令的条件中,如果在测试条件时前面的指令对该寄存器的修改还未完成,也会造成流水线保护和延迟。而C55x大部分操作都是在寄存器内或依赖寄存器来完成的,所以这是造成流水线保护和延迟的主要原因。这时候,需要仔细安排指令的顺序,避免对寄存器访问的竞争;必要时可以采用加mmap()的方式,因为这会改变对相应的寄存器的读取和修改的流水线阶段,就有可能解决这个问题。
②对存储器访问的竞争也是影响流水线保护和延迟的重要原因。C55x内部存储器分为SARAM和DARAM两种。每个周期、每个SARAM体(bank)可被访问一次,DARAM体可被访问两次;如果在同一周期,指令(或并行指令对)中要对同一体访问超过两次的时候,就会造成流水线延迟。这时侯,可以考虑将其中一个数组复制到另一个存储器体中去,然后再执行相应的操作。在安排程序位置的时候,将程序代码放在SARAM区。因为,读取程序代码也可能和数据的存取产生竞争。
此外,我们还要注意,C55x流水线将某些状态寄存器STx的某些位看作“位组”,将某些寄存器看作“寄存器组”。所以,在同时访问这些“位组”或“寄存器组”成员的时候,也会产生与同时访问一个寄存器或存储器地址类似的冲突,也会造成流水线延迟。
③指令缓冲队列也有可能造成流水线保护和延迟。指令缓冲队列(IBQ)用于保存准备解码执行的指令,每次送出6字节的指令译码,同时从程序区取4字节的指令包补充。所以如果有太多的5或6字节的指令连续执行,就有可能使取指的速度跟不上译码的速度而导致延迟。而在程序执行出现子程序调用、跳转、块重复和循环等情况的时候,IBQ的内容被刷新,需要重新取指填充IBQ,这也会造成流水线延迟。在长指令间插入一些短指令,并尽可能地使用localrepeat,可以减少出现IBQ延迟的情况。
判断是否有流水线延迟的方法可以通过高版本的开发工具来检查,也可在怀疑有延迟的语句后添加NOP指令,观察前后的执行时间是否改变。若没有什么变化,则说明有延迟的情况存在,可以将其它指令调整到这个位置。
4如何提高流水线的效率
一般情况下,采用指令流水线可以提高系统的执行效率,但是这需要合理的程序设计来实现这一点。例如,上面提到的流水线冲突会引起流水线保护从而造成延迟。此外,即使在没有流水线保护的情况下,也有可能影响流水线的效率。比如在程序中发生调用子程序、条件跳转和块重复循环等分支跳转的情况时,处于指令流水线中各阶段的预处理过的指令都要丢弃,必须重新取入新的指令并重新预处理后才能执行,这就不可避免地带来延迟。所以,尽可能地减少指令流水线的刷新,将使程序运行的速度提高,延迟更少。
为了减少指令流水线的刷新,即减少分支跳转的情况出现,要尽可能地用条件执行指令来代替条件跳转指令,用单指令重复repeat(CSR)和本地循环(localrepeat)来代替块循环(blockrepeat)。这样不但可以加快程序的执行,而且可以减少代码空间和程序执行时的功耗。条件执行指令会根据条件是否成立来决定指令是否执行,而不会像条件跳转指令那样产生跳转,也就避免了出现分支跳转的情况;而使用单指令重复和本地循环,在循环结构中的指令被取入指令缓冲队列后就不再刷新指令缓冲队列,而直接使用指令缓冲队列中已经取好的指令反复执行,直到循环结束,从而也避免了取指和译码带来的延迟,大大提高了流水线执行的效率。但在编程时需要注意的是,本地循环第一条指令和最后一条指令之间最多为55字节的指令,否则,就无法采用本地循环而必须采用块循环方式。因为,最后一条指令前的长度可为55字节,而最后一条可以为长6字节的指令。所以,在整个循环指令长度较大时,可以将较短的指令前移,而将最长的指令放在最后一条,这样就有可能使得较长的指令也构成本地循环的结构。
结语
TMS320C55x是一种高性能的DSP,C55x指令流水线的优异性能是其中的非常重要的方面。通过合理的程序设计,减少指令流水线的冲突以减少保护所造成的延迟,并且尽量减少流水线的刷新,将使程序的执行效率更高,同时也降低了系统的功耗,从而可以真正发挥TMS320C55x的优异性能。