执行阶段
执行阶段负责指令包的执行与寄存器堆的写回。在Zircon-2024中,每一个不同的功能单元对应的指令通路都被抽象为了一个流水线类。
算数-分支流水线
算数-分支流水线负责执行算数运算与分支跳转。每一条算数-分支流水线都配备一个算数逻辑单元(ALU)和一个分支计算单元(Branch),且所有算数-分支流水线的功能是完全一致的。
对于分支计算单元而言,为了降低设计复杂度,分支预测在发现分支预测失败时不会立刻冲刷流水线,而是将分支预测失败使能和跳转目标都存入ROB,等待提交时再进行处理。这样做的好处就是避免了冲刷流水线时,每个流水段寄存器都需要使用一个比较器来比较现有指令是否旧于冲刷指令的逻辑,从而降低了设计复杂度。
算数-分支流水线能够支持前后相邻的两条相关的算数或分支指令的背靠背执行,这是因为算数-分支发射队列在仲裁发射的同时,就会把即将发射的指令信息广播到所有算数-分支发射队列里,从而立刻唤醒相关指令。但对于乘法-除法流水线和访存流水线而言,算数-分支流水线只会在读寄存器阶段进行唤醒。
乘法-除法流水线
乘法-除法流水线负责执行乘法和除法指令。一般情况下,乘法指令和除法指令在程序中的占比是相对较小的,但Zircon-2024依然为其实现为一条独立的流水线,这主要是基于设计简便性的考虑。后续通过性能调优,可能会使该流水线也支持算数指令的执行。
乘法器
Zircon-2024的乘法器采用了2位Booth编码+Wallce树+全加器的设计,每一个功能单元都独占一级流水线,共三级流水。其中,作者将乘法器扩展为33位乘法,通过在最高位进行位扩展或零扩展,来使其neng'gou
华莱士树的“进位数”
在2位Booth编码中,有一种编码方式是对输入数据取相反数,这显然需要一个加法器的延迟,这是不可接受的。因此,2位Booth编码器往往在取相反数时,先对其按位取反,再将是否要+1的信号传入华莱士树和全加器。
全加器拥有两个空闲的输入端:华莱士树的进位输出最低位(因为进位需要左移一位,所以这一位一定是0)和全加器本身的进位输入。如果我们要执行n位乘法的话,那么我们必须再在华莱士树中留出n-2个进位端,这也就代表华莱士树有n-1个进位输出端(最顶层的CSA也需要产生一个进位),这代表需要n-1个CSA来构建华莱士树。事实上,一个华莱士树希望把n个数的和缩减为2个数的和,所以使用n-2的CSA一定可以构建一个华莱士树,但是这只能满足n-3个低位进位。所以能否插入一个额外“无效”的CSA用来增加一个进位就变得至关重要。
对于n位乘法器,当n=2、3、4、6、9、13、19、28、42....(每一个数都是前一个数乘3除以2,向下取整)时,拥有n-2个低位进位的华莱士树是不可构建的。这是因为他们构建的一定是“满CSA树”,即不存在哪一级余下两个输出信号要接入更高一级的CSA,而“余下两个输出信号”是能否插入一个“无效”(即不会减少剩余部分和数量)的CSA的关键。
除法器
Zircon-2024的除法器采用了SRT2除法器的设计思路,需要多周期且无法流水。SRT2除法器通过扩展试商的可能数字集到{-1,0,1},简化了试商时比较器的位宽,从而降低了设计复杂度。此外,SRT2除法所需的周期数为除数前导零与被除数前导零个数之差,在被除数较小或被除数和除数非常接近时,仅需要很少的周期就可以完成计算,进一步提升了除法器的整体性能。
访存流水线
访存流水线负责访问DCache,处理加载和存储指令。目前Zircon-2024只能支持一条访存流水线,因此单个周期只能执行一条load或store指令。
有关更多关于访存系统的介绍,请参考访存系统。
旁路网络
Zircon-2024的旁路网络会将写回段的数据前递给流水线的第一个执行阶段,从而避免了相关的算数指令间插入气泡。
在Zircon-2024的设计中,所有流水线都可以将写回段的数据前递给算数-分支流水线和乘法-除法流水线,但对访存流水线进行前递是毫无意义的,这是因为访存流水线会在读取寄存器后立刻计算源操作数,而这里的前递通过寄存器堆的写优先就可以解决了。