Skip to content

lab1_支持RV32I指令集的流水线CPU

:material-circle-edit-outline: 约 1733 个字 :material-clock-time-two-outline: 预计阅读时间 6 分钟

实验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_EXHAZARD_MEMHAZARD_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

这种情况通常发生在指令之间存在数据依赖关系时,特别是当前一条指令尚未完成写操作,而后一条指令已经需要读取该数据。

处理执行阶段的数据冒险的方法包括:

  1. 数据转发(Data Forwarding)
    • 通过旁路路径将前一条指令的结果直接转发给当前指令,而不必等待前一条指令写回寄存器文件。
  2. 流水线暂停(Stall)
    • 暂停流水线,直到前一条指令完成写操作。

控制冒险(Control Hazard)

控制冒险发生在分支指令或跳转指令改变程序流时。由于分支指令的目标地址在执行阶段才能确定,可能导致流水线中的后续指令被错误地取指。控制冒险的处理方法包括:

  • 分支预测:预测分支是否会被采取,并预取相应的指令。
  • 延迟槽:在分支指令后插入一条无关指令,以减少冒险的影响。
  • 流水线刷新:当分支预测错误时,刷新流水线并重新取指。

HAZARD_ST(2'b11)可能用于表示存储器访问阶段的控制冒险。

存储器访问阶段的控制冒险(Control Hazard in Memory Access Stage)通常是指在处理器的流水线中,由于分支指令或跳转指令的目标地址在存储器访问阶段(MEM)才能确定,从而导致的控制冒险。

处理存储器访问阶段的控制冒险的方法包括:

  1. 分支预测
    • 预测分支是否会被采取,并预取相应的指令。如果预测错误,则需要刷新流水线并重新取指。
  2. 延迟槽
    • 在分支指令后插入一条无关指令,以减少冒险的影响。
  3. 流水线暂停(Stall)
    • 暂停流水线,直到分支指令的目标地址确定。
  4. 流水线刷新(Flush)
    • 当分支预测错误时,刷新流水线并重新取指。

结构冒险(Structural Hazard)

结构冒险发生在硬件资源冲突时。例如,当多个指令同时需要访问同一个存储器或寄存器文件时,可能会导致结构冒险。结构冒险通常通过增加硬件资源或引入流水线暂停(stall)来解决。

详细解释

在 Verilog 代码中,hazard_optype_MEM = hazard_optype_EX; 这一行代码表示存储阶段(MEM)的冒险类型直接继承自执行阶段(EX)的冒险类型,而不需要考虑 flush 信号。这是因为在流水线处理器中,flush 信号主要用于处理控制冒险(例如分支预测错误),这些冒险通常在执行阶段(EX)或更早的阶段被检测和处理。

  1. 控制冒险的处理
    • 控制冒险通常在执行阶段(EX)或更早的阶段被检测到。例如,当分支指令在执行阶段确定其目标地址时,如果分支预测错误,处理器需要刷新(flush)流水线,以确保错误的指令不会被执行。
    • flush 信号用于指示需要刷新流水线的阶段,通常是取指阶段(IF)和译码阶段(ID)。这些阶段的指令会被丢弃,以避免错误的执行。
  2. 存储阶段的冒险类型
    • 存储阶段(MEM)的冒险类型直接继承自执行阶段(EX)的冒险类型。这是因为在执行阶段已经处理了控制冒险,并且确定了是否需要刷新流水线。
    • 存储阶段主要处理数据存取操作(如加载和存储指令),这些操作的冒险类型在执行阶段已经确定,因此不需要再次考虑 flush 信号。
  3. 流水线刷新(Flush)
    • 当发生控制冒险时,flush 信号会被置高,表示需要刷新流水线。此时,执行阶段的冒险类型会被设置为无冒险(2'b00),以避免错误的冒险类型影响流水线的执行。
    • 存储阶段的指令已经通过了执行阶段的冒险处理,因此不需要再次考虑 flush 信号。

总结

存储阶段(MEM)的冒险类型直接继承自执行阶段(EX)的冒险类型,而不需要考虑 flush 信号。这是因为控制冒险通常在执行阶段或更早的阶段被检测和处理,flush 信号主要用于处理这些阶段的冒险情况。存储阶段的指令已经通过了执行阶段的冒险处理,因此不需要再次考虑 flush 信号。