lab1_支持RV32I指令集的流水线CPU
实验1:支持RV32I指令集的流水线CPU(含bonus) 实验2:支持中断的流水线CPU(含bonus) 实验3:CPU高速缓存模块 实验4:搭载高速缓存的CPU(含bonus) 实验5:支持多周期指令与乱序执行的CPU (含bonus) 实验6:支持动态指令调度的CPU (含bonus)
实验得分点
- 流水线
-
正确执行指令
- R-type: 5
- I-type: 5
- load: 5
- store: 5
- branch: 10
- jal: 5
- jalr: 5
- lui: 5
- auipc: 5
-
正确处理以下情况
- predict failed: 10
- predict success: 10
- RR/RB: 5
- RRR/RRB: 5
- LR/LB: 10
- LS: 10
随手小记
hazard
hazard 是在 ID 阶段就被确定的,后面阶段的 hazard 是往前继承的,不用重复识别 hazard
在处理器设计中,冒险(Hazard)是指在流水线处理器中可能导致错误执行或性能下降的情况。主要有三种类型的冒险:数据冒险(Data Hazard)、控制冒险(Control Hazard)和结构冒险(Structural Hazard)。在你的 Verilog 代码中,定义了三种冒险类型的参数:HAZARD_EX
、HAZARD_MEM
和 HAZARD_ST
。以下是对这三种冒险的详细解释:
数据冒险(Data Hazard)
数据冒险发生在指令之间存在数据依赖关系时。数据冒险可以进一步分为以下几种类型:
- RAW(Read After Write):后续指令需要读取前一指令写入的数据,但前一指令尚未完成写操作。
- WAR(Write After Read):后续指令需要写入前一指令读取的数据,但前一指令尚未完成读操作。
- WAW(Write After Write):后续指令需要写入前一指令写入的数据,但前一指令尚未完成写操作。
HAZARD_EX
(2'b01):表示在执行阶段(EX)检测到的数据冒险。
当指令在执行阶段时,发现其所需的数据尚未准备好,RAW
这种情况通常发生在指令之间存在数据依赖关系时,特别是当前一条指令尚未完成写操作,而后一条指令已经需要读取该数据。
HAZARD_MEM
(2'b10):表示在存储阶段(MEM)检测到的数据冒险。
当指令在存储阶段时,发现其所需的数据尚未准备好,WAR,WAW
这种情况通常发生在指令之间存在数据依赖关系时,特别是当前一条指令尚未完成写操作,而后一条指令已经需要读取该数据。
处理执行阶段的数据冒险的方法包括:
- 数据转发(Data Forwarding):
- 通过旁路路径将前一条指令的结果直接转发给当前指令,而不必等待前一条指令写回寄存器文件。
- 流水线暂停(Stall):
- 暂停流水线,直到前一条指令完成写操作。
控制冒险(Control Hazard)
控制冒险发生在分支指令或跳转指令改变程序流时。由于分支指令的目标地址在执行阶段才能确定,可能导致流水线中的后续指令被错误地取指。控制冒险的处理方法包括:
- 分支预测:预测分支是否会被采取,并预取相应的指令。
- 延迟槽:在分支指令后插入一条无关指令,以减少冒险的影响。
- 流水线刷新:当分支预测错误时,刷新流水线并重新取指。
HAZARD_ST
(2'b11)可能用于表示存储器访问阶段的控制冒险。
存储器访问阶段的控制冒险(Control Hazard in Memory Access Stage)通常是指在处理器的流水线中,由于分支指令或跳转指令的目标地址在存储器访问阶段(MEM)才能确定,从而导致的控制冒险。
处理存储器访问阶段的控制冒险的方法包括:
- 分支预测:
- 预测分支是否会被采取,并预取相应的指令。如果预测错误,则需要刷新流水线并重新取指。
- 延迟槽:
- 在分支指令后插入一条无关指令,以减少冒险的影响。
- 流水线暂停(Stall):
- 暂停流水线,直到分支指令的目标地址确定。
- 流水线刷新(Flush):
- 当分支预测错误时,刷新流水线并重新取指。
结构冒险(Structural Hazard)
结构冒险发生在硬件资源冲突时。例如,当多个指令同时需要访问同一个存储器或寄存器文件时,可能会导致结构冒险。结构冒险通常通过增加硬件资源或引入流水线暂停(stall)来解决。
详细解释
在 Verilog 代码中,hazard_optype_MEM = hazard_optype_EX;
这一行代码表示存储阶段(MEM)的冒险类型直接继承自执行阶段(EX)的冒险类型,而不需要考虑 flush
信号。这是因为在流水线处理器中,flush
信号主要用于处理控制冒险(例如分支预测错误),这些冒险通常在执行阶段(EX)或更早的阶段被检测和处理。
- 控制冒险的处理:
- 控制冒险通常在执行阶段(EX)或更早的阶段被检测到。例如,当分支指令在执行阶段确定其目标地址时,如果分支预测错误,处理器需要刷新(flush)流水线,以确保错误的指令不会被执行。
flush
信号用于指示需要刷新流水线的阶段,通常是取指阶段(IF)和译码阶段(ID)。这些阶段的指令会被丢弃,以避免错误的执行。
- 存储阶段的冒险类型:
- 存储阶段(MEM)的冒险类型直接继承自执行阶段(EX)的冒险类型。这是因为在执行阶段已经处理了控制冒险,并且确定了是否需要刷新流水线。
- 存储阶段主要处理数据存取操作(如加载和存储指令),这些操作的冒险类型在执行阶段已经确定,因此不需要再次考虑
flush
信号。
- 流水线刷新(Flush):
- 当发生控制冒险时,
flush
信号会被置高,表示需要刷新流水线。此时,执行阶段的冒险类型会被设置为无冒险(2'b00
),以避免错误的冒险类型影响流水线的执行。 - 存储阶段的指令已经通过了执行阶段的冒险处理,因此不需要再次考虑
flush
信号。
- 当发生控制冒险时,
总结
存储阶段(MEM)的冒险类型直接继承自执行阶段(EX)的冒险类型,而不需要考虑 flush
信号。这是因为控制冒险通常在执行阶段或更早的阶段被检测和处理,flush
信号主要用于处理这些阶段的冒险情况。存储阶段的指令已经通过了执行阶段的冒险处理,因此不需要再次考虑 flush
信号。