《大话处理器》连载——微架构(7) 流水线上的冒险——数据冒险

(2) 数据冒险

        流水线使原先有先后顺序的指令同时处理,当出现某些指令的组合时,可能会导致指令使用了错误的数据。

看下面这个例子:

寄存器访问的数据冒险

 

        add R1,R2,R3将寄存器R2和R3的和赋给R1,add R4,R1,R5将寄存器R1和R5的和赋给R4,很明显,R1在第1条指令中被更新,然后在第2条指令中使用,可是R1必须在第5个cycle之后才被更新,而指令2再第4个cycle就要访问R1,这时的R1还不是正确的值,执行结果出错。

        一种解决方法是在这2条语句之间增加2个cycle的等待:

通过增加等待来消除数据冒险

 

        延时2个cycle,cycle 5将第1条指令的结果写回到寄存器R1中后,第2个add指令的EX单元就可以正常执行了。

这种方法很大一个缺点就是中间增加了2个cycle的等待,影响了执行效率。实际的处理器使用直通(Forwarding)来解决这个问题。

        当硬件检测到当前指令的源操作数正好在EX/MEM流水线寄存器中时,就直接将EX/MEM寄存器的值传递给ALU的输入,而不是从寄存器堆中读数据,如图:

 

使用Forwarding,解决数据冒险

 

        不只寄存器访问有这样的问题,Memory访问也有同样的问题。看下面这个例子:

 

Memory访问的数据冒险

 

        load R1,(R2)将存储器中的值装载到R1中来,存储器的地址在R2中存储,store R1,(R3) 将R1中的值放到存储器中去。在cycle 4,load指令的MEM阶段将存储器中的值装载到MEM/WB寄存器中,在cycle 5,load指令的WB阶段将MEM/WB寄存器的值装载到寄存器R1中,而在cycle 5,store指令的MEM要将寄存器R1的值放到存储器中去,R1的值还没有被load指令更新。这个数据冒险的解决方法可以延时1个周期,也可以采用同样的Forwarding方法,将MEM/WB寄存器直通到MEM输入端。

  

使用Forwarding,解决数据冒险

       

        也不是每种数据冒险都能解决,同时又不引起stall,例如下面这个例子:

仍然需要stall的直通示例

 

        sub指令需要R1,但是R1最早也要在cycle 4才到MEM/WB寄存器中,即使将MEM/WB寄存器直通到EX的输入端,也需要延时一个cycle才能使用。

你可能感兴趣的:(处理器)