在 6 级标量或超标量 MIPS 中的错误预测需要杀死多少条指令?

How many instructions need to be killed on a miss-predict in a 6-stage scalar or superscalar MIPS?

我正在处理一个有 6 个阶段的流水线:F D I X0 X1 W。我被问到当发生分支预测错误时需要终止多少条指令。

我想到了 4。我认为这是因为分支解析发生在 X1 中,我们需要终止分支之后的所有指令。在流水线图中,看起来需要终止流经流水线的 4 条指令。那是对的吗?

我还被问到,如果管道是三宽超标量,需要杀死多少个。这个我不确定。我认为应该是 12,因为您一次可以获取 3 条指令。对吗?

kill all the instructions that came after the branch

如果这是真正的 MIPS,则不会。 MIPS 有一个branch-delay slot:分支之后的指令总是执行,无论该分支是否被采用。 (jal的return地址是延迟槽的末尾,所以它不会执行两次。)

这足以完全隐藏使用标量 classic RISC 5-stage pipeline. It managed that 1 cycle branch latency by 的经典 MIPS I (R2000) 上的 1 个分支延迟周期。这就是为什么 MIPS 分支条件都是 "simple"(不需要通过整个字进位传播),比如两个寄存器之间的 beq 但只有一个操作数 bgez / bltz 针对带符号 2 的补码比较的隐式 0。那只需要检查符号位。

如果您的流水线设计良好,您会期望它在 X0 之后解析分支,因为 MIPS ISA 已经限制为 ALU 轻松做出低延迟分支决策。但显然你的流水线没有优化,分支决策直到 X1 结束才准备好,这违背了用 运行 MIPS 代码代替 RISC-V 或任何其他 RISC 指令集的目的。


I have come up with 4. I think this because the branch resolution happens in X1 and we will need to kill all the instructions that came after the branch.

我认为 4 个周期看起来适合通用标量流水线 没有 分支延迟槽。

在那个 X1 周期结束时,前 4 个流水线阶段中的每一个都有一条指令,等待在该时钟边沿移动到下一个阶段。 (假设没有其他管道气泡)。延迟槽指令就是其中之一,不需要被终止。

(除非I-cache未命中获取延迟槽指令,在这种情况下延迟槽指令可能甚至还没有在流水线中。所以它不像杀死X0之前的3个阶段那么简单,或者甚至杀死流水线中除了最旧的前一条指令之外的所有指令。延迟槽不能自由实现,也使异常处理复杂化。)

因此需要在从 F 到 I 的流水线阶段中终止 0..3 条指令。(如果延迟槽指令可能处于这些阶段之一,则必须检测该特殊情况。如果它不是,例如,我缓存未命中延迟足够长,以至于它要么在 X0 中,要么仍在等待获取,然后管道可以终止前 3 个阶段,并根据 X0 是否为气泡来做一些事情。)


I think that it would be 12 because you can fetch 3 instructions at a time

没有。 请记住,分支本身是一组可以通过流水线的 3 条指令之一。在 predict-not-taken 的情况下,大概解码阶段会发送该 fetch/decode 组中的所有 3 条指令。

我认为最坏的情况是分支是组中的第一条(程序顺序中最旧的)指令。然后必须终止 X1 中该组的 1 条(或 2 条没有分支延迟槽的指令)指令,以及之前阶段中的所有指令。然后(假设没有气泡)您要取消 13(或 14)条指令,每个前一阶段 3 条。

最好的情况是分支在 3 个一组中是最后一个(程序顺序中最年轻的)。然后您将丢弃 11 个(或没有延迟槽的 12 个)。

因此,对于没有延迟槽的此管道的 3 宽版本,取决于先前管道阶段中的气泡,您正在杀死管道中已经存在的 0..14 条指令。

实现延迟槽很糟糕;较新的 ISA 不公开该管道细节是有原因的。长期痛苦换短期收益。