Tomasulo算法
通过重命名技术解决了记分牌WAW和通过直接读操作数WAR的问题
指令执行分三个阶段
流出阶段(IS)
记分牌算法是如何在流出阶段避免结构冲突和写后写冲突?
利用Busy位控制结构冲突的指令不流出
判断Fi对应的寄存器与当前的目的寄存器是否相同阻塞导致写后写冲突的指令
执行阶段(EX)
写结果阶段(WB)
记分牌算法是如何在写结果阶段避免读后写冲突?
在写回之前,判断是否有指令读目的寄存器但没有准备好来避免读后写冲突
记分牌的表格结构
指令状态表
表示正在执行的指令处于四步中的哪一步
保留站
Busy:指示功能部件是否在工作(结构冲突需要)
Op:功能部件当前执行的操作
Fi:目的寄存器编号
Fj, Fk:源寄存器编号
Qj, Qk:向Fj, Fk中写结果的功能部件,空表示结果已经写回寄存器
Rj, Rk:Fj, Fk就绪并且还没有被使用标志(如果数据已经读取完成,则也用no进行表示)
寄存器状态表
与Qi,Qj对应
算法流程
流出阶段算法
相较于记分牌,此时的结构冲突任然无法处理,WAW可以通过重命名消除,故流入条件变为只要保留站和ROB都有空,则流入
if(保留站和ROB都有空,则流入)//结构冲突
{
//更新三个表
Issue=yes;//指令状态表更新IS阶段
Busy(FU)=yes;//保留站
Op=对应指令;
填写Vj,Vk
查寄存器状态表,填写Qj,Qk;
根据目的寄存器更新寄存器状态表//此处体现了重命名的思想
填写ROB
}
执行阶段算法
找到一条源操作数都准备好的指令执行
(Qj0&&Qk0)
更新指令状态表
写结果阶段算法
更新寄存器表和寄存器
for(保留站每一项)
if (reg[x].Qi == R)
F[x]=data;Qi=0;
更新保留站
for(保留站每一项)
if (RS[x].Qj/Qk == R)
{RS[x].Vj/Vk ← result_data; //所有consumer
RS[x].Qi/Qk ← 0}) //数据Vj/Vk有效
清空对应保留站
Busy->no
存在的限制
- 受限于功能部件
- 程序本身的并行性
- 通过分支预测,可以提供更大的指令调度窗口
引入分支预测技术
//数据Vj/Vk有效
清空对应保留站
Busy->no
存在的限制
- 受限于功能部件
- 程序本身的并行性
- 通过分支预测,可以提供更大的指令调度窗口