在嵌入式DSP应用开发中,乘法累加(MAC)操作是最核心的运算单元。传统实现方式需要多条指令分别完成乘法和加法,而C16x微控制器通过硬件MAC单元将这类操作压缩到单周期指令。以FIR滤波器为例,每个抽头计算原本需要MUL+ADD两条指令,使用MAC指令后性能可提升40%以上。
ST10系列微控制器的MAC单元包含三个关键组件:
C166编译器将ST10的MAC指令分为四类实现:
| 指令类型 | 对应操作 | 时钟周期 | 适用场景 |
|---|---|---|---|
| CoMUL | 纯乘法 | 1 | 单次乘法运算 |
| CoMAC | 乘后累加 | 1 | 向量点积运算 |
| CoMACR | 乘后累加并舍入 | 1 | 音频采样处理 |
| CoMAC- | 乘后减法 | 1 | 误差校正运算 |
典型应用场景对比:
c复制// 传统实现
long result = (long)a * b + (long)c * d;
// MAC优化版
#pragma MAC(MUL)
long result = _mac_(CoMAC, a, b);
result = _mac_(CoMAC, c, d);
MAC编译指令支持模块化配置:
c复制#pragma MAC(MUL, MOV, INTR) // 完整启用
#pragma MAC(MUL) // 仅启用乘法指令
#pragma MAC() // 完全禁用
关键参数说明:
头文件提供7类内联函数:
c复制#include <st10mac.h>
// 基本乘法操作
_mac_(CoMUL, op1, op2);
// 长整型加载
_macl_(CoLOAD, long_val);
// 立即数运算
_mac_(CoMACu, var, 0x1234);
// 数组运算(需IDX0寄存器配合)
_maci_(CoMAC, _IDX0p_, ptr);
中断处理中的寄存器保护策略:
c复制void ISR() interrupt 20 {
// 自动保存MAH/MAL (需MAC(INTR))
h1 = h2; // 使用CoMOV优化拷贝
// 手动保护方案
__asm push MAH;
__asm push MAL;
// ... ISR代码 ...
__asm pop MAL;
__asm pop MAH;
}
传统实现:
c复制long fir_filter(int *coeffs, int *samples, int len) {
long sum = 0;
for(int i=0; i<len; i++) {
sum += (long)coeffs[i] * samples[i];
}
return sum;
}
MAC优化版:
c复制long fir_filter_mac(int *coeffs, int *samples, int len) {
_mac_(CoCLR); // 清空累加器
for(int i=0; i<len; i++) {
_mac_(CoMAC, coeffs[i], samples[i]);
}
return _lmac_(); // 返回累加结果
}
实测数据(100次循环,GCC优化-O2):
| 实现方式 | 周期数 | 代码大小 |
|---|---|---|
| 标准实现 | 4200 | 128B |
| MAC优化 | 2400 | 86B |
c复制// 累加前预缩放
_mac_(CoMACR, input, coefficient); // 自动舍入
// 饱和处理
long val = _lmac_sat(); // 40->32位饱和转换
4x4矩阵乘法优化示例:
c复制void matrix_mul(int a[4][4], int b[4][4], int r[4][4]) {
for(int i=0; i<4; i++) {
for(int j=0; j<4; j++) {
_mac_(CoCLR);
for(int k=0; k<4; k++) {
_mac_(CoMAC, a[i][k], b[k][j]);
}
r[i][j] = (int)_lmac_();
}
}
}
优化要点:
实测性能提升达3.8倍(C167CR@20MHz)