分支预测:预见1

一个程序中的指令之间存在相关性,如时间相关性和空间相关性。对于循环语句,一次次的跳转其实是类似的,只有到达极限才会停下来。直接让CPU预测程序下一步干什么,然后运行,而不是傻乎乎的等待,这样子可以显著提高运行效率——大多数情况下是的。

既然如此,我们的分支预测器一定要早于分支结果计算出来就生效。因此,需要将其放在ID级。

静态预测器

静态预测器很傻,但也很老实:它是“一根筋”,只会预测分支要么跳转、要么不跳转,自己不会做出改变。

我们需要留出哪些接口?需要判断当前指令是否为分支指令,以及输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
`include "include/defines.svh"

module Static_Predictor #(
parameter int unsigned META_BITS = 8
) (
input logic clk,
input logic rst_n,
input logic valid_i,
input logic is_branch_instr_i,
input logic [ 1:0] jump_type_i,
input logic [ 31:0] branch_target_i,
output logic predict_taken_o,
output logic [ 31:0] predict_target_o,
output logic [META_BITS-1:0] predict_meta_o
);

// 静态预测策略:
// - JAL: 恒预测跳转
// - JALR: 目标依赖寄存器,不在ID级预测
// - 条件分支: Backward Taken, Forward Not Taken
always_comb begin
predict_taken_o = 1'b0;
predict_target_o = branch_target_i;

if (valid_i) begin
unique case (jump_type_i)
`JUMP_JAL: predict_taken_o = 1'b1;
`JUMP_JALR: predict_taken_o = 1'b0;
default: begin
if (is_branch_instr_i) begin
predict_taken_o = imm_i[31];
end
end
endcase
end
end

endmodule