我们的流水线化的设计有点不太现实,因为寄存器文件有两个写端口,然而只有popq指令需要对寄存器文件同时进行两个写操作。因此,其他指令只使用一个写端口,共享这个端口来写valE和valM。下面这个图是一个对写回逻辑的修改版,其中,我们将写回寄存器ID(W_dstE和W_dstM) 合并成一个信号w_dstE,同时也将写回值(W_valE和W_valM)合并成一个信号w_valE:
用HCL写执行这些合并的逻辑,如下所示;
##Set E port register ID word w_dstE =[ ## writing from valM W_dstM != RNONE:W_dstM; 1: W_dstE; ]; ## Set E port value word w_valE =[ W.dstM !=RNONE:W.valM; 1: W.valE; ];
对这些多路复用器的控制是由dstE确定的——当它表明有某个寄存器时,就选择端口 E的值,否则就选择端口M的值。
在模拟模型中,我们可以禁止寄存器端口M,如下面这段HCL代码所示:
##Disable register port M ## Set M port register ID word w_dstM = RNONE; ## Set M port value word w_valM = 0;
接下来的问题就是要设计处理popq的方法。一种方法是用控制逻辑动态地处理指令popq rA,使之与下面两条指令序列有一样的效果:
iaddq $8,%rsp mrmovq -8(%rsp), rA
要注意两条指令的顺序,以保证popq %rsp能正确工作。要达到这个目的,可以让译码阶段的逻辑对上面列出的popq指令和addq指令一视同仁,除了它会预测下一个PC与当前PC相等以外。在下一个周期,再次取出了popq指令,但是指令代码变成了特IP0P2。它会被当作一条特殊的指令来处理,行为与上面列出的mrmovq指令一样。
文件pipe-lw. hcl包含上面讲的修改过的写端口逻辑。它将常数IP0P2声明为十六进制值E。还包括信号f_icode的定义,它产生流水线寄存器D的icode字段。可以修改这个定义,使得当第二次取出popq指令时,插人指令代码IP0P2。这个HCL文件还包含信号f_pc的声明,也就是标号为“Select PC”的块(图4-57)在取指阶段产生的程序计数器的值。
修改该文件中的控制逻辑,使之按照我们描述的方式来处理popq指令。可以参考实验资料获得如何为你的解答生成模拟器以及如何测试模拟器的指导。