控制冒险
在算术操作和数据传输中存在冒险。
要等到MEM流水线阶段才可以决定分支是否发生。
为了决定正确执行指令所产生的延迟被称为控制冒险或分支冒险。
分支指令
分支指令在MEM阶段决定是否跳转,beq指令在第四个时钟周期内的操作。分支指令后续的三条指令都将被取值并且开始执行。如果不进行干预,这三条指令在beq指令跳转到地址72上的ld指令之前就开始执行。
假设分支不发生
阻塞流水线直到分支完成的策略非常耗时。一种提升分支阻塞效率的方法是预测条件分支不发生并持续执行顺序指令流,一旦条件分支发生,已经被读取和译码的指令就会被丢弃,流水线继续从分支目标处开始执行。如果条件分支不发生的概率是50%,同时丢弃指令的代价又很小。那么这种优化,可以减少一半由控制冒险带来的代价。
想丢弃指令,只需将初始控制值变为0即可。 这与指令停顿解决加载 -使用的数据冒险类似。不同的是丢弃指令的同时,需要改变当分支指令到达MEM阶段时IF、ID和EX三条指令。而在加载使用的数据停顿中,只需要将ID阶段的控制信号变为0并且将该阶段的指令从流水线中过滤出去即可。
丢弃指令,意味着我们必须能够将流水线中IF,ID和EX阶段中的指令都清除。
缩短分支延迟
计算分支目标地址和判断分支条件。
在IF/ID流水线寄存器中已经得到了PC值和立即数字段,只需将分支地址从EX阶段移动到ID阶段。 分支地址的目标计算将会在所有指令中都执行。但只在需要时才会被使用。
分支决定本身。 对于相等跳转指令,在ID阶段比较两个寄存器中的值是否相等,判断方法将对应位进行异或,再对按位进行或操作。为了实现相等时跳转指令,需要在ID阶段将结果传递给相等测试逻辑。
1 在ID阶段指令译码,决定是否需要将指令旁路至相等检测单元。
2 ID阶段分支比较的值可能在之后才会产生,因此可能产生数据冒险。所以指令停顿是必须的。 如果ALU在分支指令之前,ALU指令的EX阶段将发生在分支指令ID阶段之后。又例如,一条加载指令恰好发生在条件分支指令之后,并且条件分支指令依赖加载指令的结果,那么两个时钟周期的停顿是必须的。 因为加载指令的结果要在MEM阶段的最后才能发生。但是在分支指令的ID阶段就需要了。
将条件分支指令的执行阶段移动到ID阶段
将分支发生的代价减轻至一条指令,也就是分支发生时正在取的那条指令。
动态分支预测
对于更深的流水线,从时钟周期的角度出发,分支预测错误的代价会增大。
分支预测: 分支预测缓存
检查指令中的地址,查看上一次该指令执行时条件分支是否发生了跳转,如果发生了,则从上一次执行的地址中取出指令。
动态预测:锦标赛分支预测器
对于每个分支使用多种预测器,并最终给出一个最佳的预测结果。典型的锦标赛预测器对每个分支地址使用两个预测,一个基于局部信息,另一个基于全局分支行为。
一个选择器用于选择采取哪一个预测器的信息进行预测。选择两个预测器中更准确地那个。