ZHCUCH3A November 2024 – March 2025 F29H850TU , F29H859TU-Q1
C29x CPU 不像 C28x CPU 那样支持循环寻址的原生寻址模式。但是,C29x CPU 架构中存在的功能并行性可确保缺少原生循环寻址模式不会对性能产生影响。
循环寻址由以循环方式修改寻址寄存器的指令执行。这些是 16 位指令,需要 1 个周期来执行。支持的指令包括:
INC.CIRC Ay,Ax:
将 Ay 递增,直至达到限制 (Ax),然后将该值复位为 0。
if (Ay >= Ax) Ay = 0
else Ay = Ay + 1
; where Ay = A0 to A3
; and Ax = A0 to A14
DEC.CIRC Ay,Ax:
将 Ay 递减,直至达到限制 (0)、然后将值复位为 Ax。
if (Ay <= 0) Ay = Ax
else Ay = Ay – 1
; where Ay = A0 to A3
; and Ax = A0 to A14
这种类型的寻址模式通常用于实现有限脉冲响应 (FIR)、最小均方根 (LMS) 或卷积滤波器。
使用 C 语言的典型 FIR 滤波算法:
sum = 0;
circ_index = save_circ_index;
for(i=0; i < N_taps; i++)
{
sum += Data[circ_index] * Coef[i];
circ_index++;
if( circ_index >= N_taps)
circ_index = 0;
}
save_circ_index = circ_index;
滤波器的主内核可编码如下(7 抽头 FIR 示例):
LD.32 A0,@save_circ_index ; A0 = circ_index
MV A6,#N-1 ; A6 = filter taps, N = 7
MV A4,#Data ; A4 -> Data Array
MV A5,#Coef ; A5 -> Coef Array
LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M4,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M5,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M6,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M7,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M4,M0,M1
||SADDF M6,M6,M4
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M5,M0,M1
||SADDF M7,M7,M5
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M4,M0,M1
||SADDF M6,M6,M4
ADDF M7,M7,M5
ADDF M6,M6,M4
ST.32 @save_circ_index,A0 ; Save current circ index position
ADDF M7,M7,M6 ; final sum = M7