结构/数据冒险检测
记分牌(Scoreboard)是最早用于允许乱序执行的技术,由CDC 6600(1964年)首次实现。它通过跟踪每条指令的状态和每个寄存器的忙碌情况,检测结构冒险和数据冒险。与完整的OoO不同,记分牌只允许乱序完成(Out-of-Order Completion),但仍然按序发射(In-Order Issue)。
| 冒险类型 | 记分牌处理 | OoO+重命名 |
|---|---|---|
| RAW | 检测并stall | 通过CDB转发 |
| WAR | 检测并延迟写回 | 重命名消除 |
| WAW | 检测并stall发射 | 重命名消除 |
| 结构 | 检测并stall | 多功能单元 |
CDC 6600由Seymour Cray设计,是第一台使用记分牌的超级计算机。它有10个并行功能单元,记分牌协调它们的工作。虽然简单,但记分牌让CDC 6600达到了当时世界上最快的速度——3 MFLOPS。
// Lesson 18: Scoreboard
module scoreboard #(parameter NUM_REGS=32, XLEN=32)(
input wire clk, rst_n, issue_valid,
input wire [4:0] issue_rd, issue_rs1, issue_rs2,
input wire [3:0] issue_fu_type,
output wire issue_ok, output wire [3:0] hazard_type,
input wire wb_valid, input wire [4:0] wb_rd, input wire [XLEN-1:0] wb_data,
output wire [3:0] fu_busy);
reg reg_busy [0:NUM_REGS-1]; reg [XLEN-1:0] reg_val [0:NUM_REGS-1];
reg [4:0] fu_dest [0:3]; reg [3:0] fu_active; integer i;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin for(i=0;i<NUM_REGS;i=i+1) begin reg_busy[i]<=0; reg_val[i]<=0; end
fu_active<=0; for(i=0;i<4;i=i+1) fu_dest[i]<=0;
end else begin
if (wb_valid) begin reg_busy[wb_rd]<=0; reg_val[wb_rd]<=wb_data;
for(i=0;i<4;i=i+1) if(fu_active[i]&&fu_dest[i]==wb_rd) fu_active[i]<=0; end
if (issue_valid && issue_ok) begin reg_busy[issue_rd]<=1;
fu_active[issue_fu_type]<=1; fu_dest[issue_fu_type]<=issue_rd; end end end
assign hazard_type[0]=reg_busy[issue_rs1]; assign hazard_type[1]=reg_busy[issue_rs2];
assign hazard_type[2]=reg_busy[issue_rd]; assign hazard_type[3]=fu_active[issue_fu_type];
assign issue_ok=issue_valid && !hazard_type[0] && !hazard_type[1] && !hazard_type[2] && !hazard_type[3];
assign fu_busy=fu_active;
endmodule
| 方法 | 消除WAR | 消除WAW | 乱序发射 | 复杂度 |
|---|---|---|---|---|
| 记分牌 | 否 | 否 | 否 | 低 |
| Tomasulo | 是(重命名) | 否 | 是 | 中 |
| OoO+ROB | 是 | 是 | 是 | 高 |
记分牌适合功能单元数量多但不需要极限性能的场景,如DSP和嵌入式处理器。
掌握本课内容需要结合理论学习和动手实践:
| 工具 | 用途 | 安装 |
|---|---|---|
| Verilator 5.020 | Verilog编译仿真 | sudo apt install verilator |
| iverilog | 轻量仿真 | sudo apt install iverilog |
| GTKWave | 波形查看 | sudo apt install gtkwave |
| RISC-V GCC | 交叉编译 | apt install gcc-riscv64-unknown-elf |
| QEMU | 系统仿真 | apt install qemu-system-misc |
本课程推荐以下开发工具链:
| 工具 | 用途 | 安装命令 |
|---|---|---|
| Verilator | Verilog编译/仿真 | sudo apt install verilator |
| iverilog | 轻量Verilog仿真 | sudo apt install iverilog |
| GTKWave | 波形查看 | sudo apt install gtkwave |
| RISC-V GCC | 交叉编译 | apt install gcc-riscv64-unknown-elf |
| QEMU | 系统仿真 | apt install qemu-system-misc |
| Spike | ISA模拟器 | 从源码编译 |
# 编译本课Verilog代码
cd verilog/
iverilog -o tb_test *.v
vvp tb_test
# Verilator lint检查
verilator --lint-only -Wno-BLKLOOPINIT *.v
# 应无Error输出
完成基础实验后,尝试以下进阶挑战:
$display打印关键状态变化$dumpfile/$dumpvars生成VCD波形本课是第18课,在整体课程中承上启下。每一课都构建在前一课的基础上,建议按顺序学习。