Changchun Master Li

HDLbits学习记录 uwaterloo cs450

2022-03-17

刷完HDLbits后一段时间没关注了,偶然发现最近更新了。
新增加的四道题都和处理器分支预测相关,正好我之前有相关经验,借此机会重温一下

uwaterloo cs450 这几道题看起来是 滑铁卢大学cs450 计算机体系结构课程相关的题目,整体难度不大。
如果不了解相关知识背景可以先参考一下这个wiki Branch_predictor ,讲的不错。

1. Cs450/timer - HDLBits

很简单,实现一个递减计数器,计数器减到0的时候拉高tc,一个counter轻松秒杀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module top_module(
input clk,
input load,
input [9:0] data,
output tc
);
reg [9:0] counter;
always @(posedge clk) begin
if (load)
counter <= data;
else if (counter > 0)
counter <= counter - 1;
end
assign tc = !counter;
endmodule

2. Cs450/counter 2bc

实现饱和计数器,四个状态,说白了taken=1就往强选择状态移动,taken=0往强不选状态移动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module top_module(
input clk,
input areset,
input train_valid,
input train_taken,
output reg [1:0] state
);
always @(posedge clk, posedge areset) begin
if (areset)
state <= 2'b01;
else if (train_valid) begin
if (train_taken)
state <= (state == 2'b11) ? 2'b11 : (state + 1);
else
state <= (state == 2'b00) ? 2'b00 : (state - 1);
end
end
endmodule

3. Cs450/history shift

历史缓冲区,作用就是记录最近跳转的信息,供预测器使用。值得注意的就是当发生预测失败,需要冲刷流水线,在预测失败之后的预测(younger)都需要从历史缓冲区中冲刷掉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module top_module(
input clk,
input areset,

input predict_valid,
input predict_taken,
output [31:0] predict_history,

input train_mispredicted,
input train_taken,
input [31:0] train_history
);
always @(posedge clk, posedge areset) begin
if (areset)
predict_history <= 0;
else if (train_mispredicted)
predict_history <= {train_history[30:0], train_taken};
else if (predict_valid)
predict_history <= {predict_history[30:0], predict_taken};
end
endmodule

注意 预测失败的优先级高于预测使能信号,预测失败会冲刷出错之后全部的历史。

4. Cs450/gshare - HDLBits

本题相对比较复杂,需要实现一个gshare。
产生predict_taken的方式是通过一个叫模式匹配表(pattern history table, PHT)的东西
首先题目中历史缓冲区为7个bit,因此PHT的大小为2^7 = 128个。
pattern为 7bit历史缓冲区和7bit程序计数器(PC)按位异或,每个pattern对应一个2bit饱和计数器

PHT[history ^ pc] = 2'b01;

模块可以分成training和predicting两部分,分别由train_valid和predict_valid两个信号控制

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
39
module top_module(
input clk,
input areset,

input predict_valid,
input [6:0] predict_pc,
output predict_taken,
output reg [6:0] predict_history,

input train_valid,
input train_taken,
input train_mispredicted,
input [6:0] train_history,
input [6:0] train_pc
);

reg [1:0] PHT[127:0];
integer i;
always @(posedge clk, posedge areset) begin
if (areset) begin
predict_history <= 0;
for (i=0; i<128; i=i+1) PHT[i] <= 2'b01;
end
else begin
if (train_valid && train_mispredicted)
predict_history <= {train_history[6:0], train_taken};
else if (predict_valid)
predict_history <= {predict_history[6:0], predict_taken};

if (train_valid) begin
if (train_taken)
PHT[train_history ^ train_pc] <= (PHT[train_history ^ train_pc] == 2'b11) ? 2'b11 : (PHT[train_history ^ train_pc] + 1);
else
PHT[train_history ^ train_pc] <= (PHT[train_history ^ train_pc] == 2'b00) ? 2'b00 : (PHT[train_history ^ train_pc] - 1);
end
end
end
assign predict_taken = PHT[predict_history ^ predict_pc][1];
endmodule

总体来说,这几个题目相对其他题目不在拘泥于verilog基本语法,更多结合一些处理器的实现,有一些实用意义。

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章