乘法运算是数学中重要的基本算术运算,乘法累加操作(multiply and accumulate operations.MAC)在数字信号处理中被广泛应用,比如,FFT,DFT,卷积计算,甚至是微控制器的ALU中的通用计算单元都能见到它的身影。在DSP应用中,比通用处理器更加侧重MACs的设计,MACs的逻辑实现通常是数字电路设计中Critical path的主要贡献方,设计的好坏决定了PPA,本文试图从软件视角搞清楚MACs是什么以及如何工作的。
设计原理
MACs顶层实现方框图如下,其中的operand_1 和 operand_2是32位输入操作数,MACs操作的结果通过64位的Result pin输出,内部的64位加法器将乘法器的输出作为第一个操作数,与存储在内部的第二个加法操作数相加,第二个操作数的来源一般是上一个周期的Result结果,得到Result输出和进位信号Carry.
一个用VHDL实现的MACs单元逻辑:
1 LIBRARY ieee;
2 USE ieee.std_logic_1164.ALL;
3 USE ieee.numeric_std.ALL;
4
5 ENTITY mac IS
6 GENERIC (n : INTEGER := 4); --define X and Y size
7 PORT (
8 ck : IN STD_LOGIC;
9 rst : IN STD_LOGIC;
10 X : IN SIGNED (n-1 DOWNTO 0); --n
11 Y : IN SIGNED (n-1 DOWNTO 0); --n
12 A : OUT SIGNED ((2+2*n)-1 DOWNTO 0) --2+2n (include two leading bits for overflow)
13 );
14 END mac;
15
16 ARCHITECTURE hdl OF mac IS
17 SIGNAL acc : SIGNED ((2+2*n)-1 DOWNTO 0) := (OTHERS => '0'); --2+2n
18
19 BEGIN
20
21 PROCESS (ck)
22 BEGIN
23 IF rising_edge(ck) THEN
24 IF rst ='0' THEN --reset accumulator at low
25 acc <= (OTHERS => '0');
26 ELSE
27 acc <= acc + shift_left(X * Y, 1);
28 END IF;
29 END IF;
30 END PROCESS;
31
32 A <= acc;
33 END hdl;
这段代码对应的电路逻辑如下图所示,acc作为输出的同时,又通过一条反馈回路喂给加法器,作为其中一个操作数进行下次累加计算,所以叫做累加器-MACs.
Vedic Multiplier 电路实现
数字电路的设计中,内蕴了深刻的递归和同构的思想,当问题在不同层面具有相同的结构时,可以通过将复杂问题逐层递归分解,找到最小的问题可解决结构,再最小结构层面上把问题解决,然后再以此为基础,再按照分解的逆向过程逐步解决高层问题,最终得到整个问题的解,同样道理,构造,可以从最简单的乘法器开始构造。
采用Vedic算法的乘法器原理如下:
对应的数字电路实现如下图所示:
基于 multiplier,可实现的verdic multiplier
基于 multiplier,可实现的verdic multiplier
基于 multiplier,可实现的verdic multiplier
基于 multiplier,可实现的verdic multiplier
至此,的乘法器构造完成,下面需要构造加法器。
加法器有很多,下面方框图表示的是使用超前进位加法器的一个完整的MACs单元实现:
累加器的典型应用就是矩阵乘法,以点乘为例说明multiplier, adder 以及accumulator的作用:
计算向量和的点积,结果存在result里面
用程序表示就是:
u64 adder(u64 m, u64 n)
{
return m + n;
}
u64 multiplier(u32 m, u32 n)
{
return m*n;
}
u64 macs(u32 operand_1, u32 operand_2)
{
accumulator = 0;
result = 0;
temp1 = multiplier(operand_1, operand_2);
carrier, accumulator = adder(temp1, accumulator);
result = accumulator;
return result, carrier;
}
void dotproduct(u32*a, u32*b)
{
for(i = 0; i < n; i ++)
{
result = macs(a[i], b[i]);
}
}
经常在一些DSP芯片Spec中看到的指标,比如每时钟周期执行8个MACs操作,16个MACs操作等等,本质上表示DSP的微架构内实现了几个这样的MACs单元。
MIPS处理器MACs指令的实现:
MIPS中,乘累加,乘累减指令共有4条,包括:madd, maddu, msub, msubu.
其中
madd rs, rt.
指令作用为:
将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数进行乘法运算,运算结果与{HI,LO}相加,相加的结果保存到{HI,LO} 中,此处{HI,LO}表示HI,LO寄存器连接形成64位数.
maddu rs, rt.
和madd的唯一区别是rs,rt中的值作为无符号数.
msub rs, rt
将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数进行乘法运算,然后使用{HI,LO}减去乘法结果,相减的结果保存到{HI,LO} 中.
msubu rs, rt
和msub rs, rt的唯一区别是寄存器中的值是无符号数.