进阶算法
基础算法无法解决中断恢复的问题,即假如有两个写寄存器的操作,指令1,指令2,可能乱序执行时指令2的结果已经将写回了寄存器,但是指令1还未执行,此时发生中断后,从指令1重新开始执行,就会重新进行两次写入,将会发生错误。
只要保证后面指令修改机器状态时, 前面的指令都已经不会发生中断即可。很自然想到用一个额外的缓冲部件来存储即将写入寄存器内的数据,然后根据前置写入的数据是否都以完成写入来将缓存器中的内容重新写回寄存器中。这种做法也叫做 乱序执行,有序结束,所用的缓冲器通常被称为Reorder Buffer(ROB),所以基础算法的过程中要加入一个提交Commit过程。
新算法的流程如下:
1) 发射: 把操作队列的指令根据操作类型送到保留站 (如果保留站以及ROB有空), 并在 ROB 中指定一项作为临时保存该指令结果之用; 发射过程中读寄存器的值和结果状态域, 如果结果状态域指出结果寄存器已被重命名到ROB, 则读ROB 执行: 如果所需的操作数都准备好, 则执行, 否则根据结果 ROB 号侦听结果总线并接收结果总线的值
2) 写回: 把结果送到结果总线, 释放保留站; ROB根据结果总线修改相应项
3) 提交: 如果队列中第一条指令的结果已经写回且没有发生例外, 把该指令的结果从 ROB 写回到寄存器或存储器, 释放 ROB 的相应项。如果队列头的指令发生了中断或是猜测错误的转移指令, 清除操作队列以及 ROB 等。
如果某个值在提交写回寄存器时发现发生了溢出,直接清除ROB缓存即可,如果时发生中断并准备继续执行,那么从中断的指令重新执行即可。
4)示例介绍
多了一个ROB,并且结果总线和浮点寄存器的连接被断开了,内容的写回必须通过ROB进行
1)保留站(发射队列)把有序变成乱序。
2)ROB把乱序重新变成有序。
3)重命名寄存器用于保存未提交的临时结果(就是把寄存器前边加了一个空位存储ROB序号)。
这里保留站的各个位置代表的含义有变动,取消了固定的编号,同时以ROB的序号作为替代,假设依次为 Ind Qj Vj , Qk Vk,Ind表示ROB序号,即执行完需要写回哪里。Qj,Qk表示如果寄存器没有结果时,发现依赖ROB的结果,此时将ROB对应的序号填入即可。
浮点寄存器新增了一个格子,用来存储ROB序号,表明它的值依赖哪个ROB的结果
ROB缓存中三个位置分别代表 (操作类型,写入寄存器的序号,值),例如(MUL,f0,2),值为空即正在等待保留站内的指令执行完毕,如图2-20所示。

图2-20 浮点寄存器新增了一个格子,用来存储ROB序号
1) DIV发射,首先访问寄存器发现F1F2都有值,直接写入乘法保留站(如果发现有前置序号还没写入,那么就将ROB序号写入保留站中的操作数值左边的序号部分)因为其结果要写回F0,所以将写入的信息先写入ROB1,并在寄存器0前边加上ROB序号1,表明他的值依赖于ROB1的执行,如图2-21所示。

图2-21 DIV发射示例
2) MUL1发射,对F0F2首先检索寄存器,发现F2存在,但F0依赖ROB1所以将其依赖的ROB序号1写入乘法保留站中F0的序号部分,F2则直接将值写入即可序号默认写0。此时其执行结果需要写入F3,所以将其写入的内容暂时保存在ROB2中,ROB2说明其正在等待写入。同时浮点寄存器中真正要写入的F3位置标记上对应等待的ROB序号2,表示接下来的指令如果需要寄存器3的内容时,直接找ROB2就行了,如图2-22所示。

图2-22 MUL1发射
3) ADD发射,并且两个操作数都已准备好,按照上述流程继续写入即可,如图2-23所示。

图2-23 ADD发射
4) MUL2发射,F0需要等待ROB3,所以将其序号3写入乘法保留站,如图2-24所示。

图2-24 MUL2发射
5) ADD 写回,ADD执行结果写入ROB3,并且因为保留站的第一个序号就代表写回的ROB序号,所以广播时其他需要ROB3的保留站指令,都会检查并接受相关值(这里保留站4就接受了ADD的结果,因为它就在等待ROB3),结果被写入ROB3中,此时不能写回寄存器,要等待它前边的12号ROB都有了值之后才行,如图2-25所示。

图2-25 ADD写回
6) DIV写回,广播以后保留站2收到值并修改自身。ROB1接受并修改自身。此时ROB中最前边的缓存1已经有值了,开始提交,并且提交可以和写回同时执行(执行不冲突),如图2-26所示。

图2-26 DIV写回
7) 提交ROB1并修改寄存器 f0(虽然此时修改已经没啥用了),此时将指令队列中第一条指令删去。同时MUL2写回(尽管MUL1和MUL2都准备好了,但是MUL2先准备好,先来后到),如图2-27所示。

图2-27 提交ROB1并修改寄存器 f0
8) 写回MUL1,此时ROB中所有缓存都已写入,按照ROB序号的次序,依次提交三个缓存内容来修改对应的寄存器即可,如图2-28所示。

图2-28 写回MUL1
9) 依次写入三个缓存,如图2-29与图2-30所示。


图2-29 依次写入三个缓存(前)


图2-30 依次写入三个缓存(后)