11

/**

  • 主CPU模块

  • 实现了支持LoongArch指令集的五级流水线CPU

  • 主要特性:

    • 五级流水线:IF(取指) -> ID(译码) -> EX(执行) -> MEM(访存) -> WB(写回)
    • 支持21条LoongArch指令
    • 数据前递解决数据冒险
    • 分支预测器减少控制冒险
    • 冒险检测单元处理Load-Use冒险
    • 性能计数器监控CPU性能
  • 流水线优化:

    • 前递单元:解决EX/MEM和MEM/WB阶段的数据冒险
    • 分支预测:2位饱和计数器 + BTB,减少分支预测错误
    • 冒险检测:检测Load-Use冒险并插入气泡
      /
      class MyCPU extends Module {
      val io = IO(new Bundle {
      /
      * 复位信号 /
      val rst = Input(Bool())
      /
      * 指令内存地址输出 /
      val imem_addr = Output(UInt(32.W))
      /
      * 指令内存数据输入 /
      val imem_inst = Input(UInt(32.W))
      /
      * 调试:寄存器状态输出 /
      val debug_reg_out = Output(Vec(32, UInt(32.W)))
      /
      * 调试:程序计数器输出 */
      val debug_pc_out = Output(UInt(32.W))

    // ========== 性能计数器输出 ==========
    /** 总时钟周期数 /
    val total_cycles = Output(UInt(32.W))
    /
    * 总指令数 /
    val total_instructions = Output(UInt(32.W))
    /
    * 分支指令数 /
    val branch_instructions = Output(UInt(32.W))
    /
    * 分支预测错误数 /
    val branch_mispredictions = Output(UInt(32.W))
    /
    * 停顿周期数 */
    val stall_cycles = Output(UInt(32.W))
    })

// =================================== 组件实例化 ===================================
val alu = Module(new ALU(32))
val regFile = withReset(io.rst) { Module(new RegFile) }
val decoder = Module(new Decoder)
val immGen = Module(new ImmGen)
val memUnit = Module(new MemoryMap)
val forwardingUnit = Module(new ForwardingUnit) // 添加前递单元
val hazardDetection = Module(new HazardDetection) // 添加冒险检测单元
val branchPredictor = Module(new BranchPredictor) // 添加分支预测器

// ================================= 流水线寄存器 =================================
val ifid_reg = RegInit(0.U.asTypeOf(new IFIDBundle))
val idex_reg = RegInit(0.U.asTypeOf(new IDEXBundle))
val exmem_reg = RegInit(0.U.asTypeOf(new EXMEMBundle))
val memwb_reg = RegInit(0.U.asTypeOf(new MEMWBBundle))

// 扩展IDEX寄存器以包含立即数
val idex_imm = RegInit(0.U(32.W))

// ================================= 性能计数器 =================================
val total_cycles = RegInit(0.U(32.W))
val total_instructions = RegInit(0.U(32.W))
val branch_instructions = RegInit(0.U(32.W))
val branch_mispredictions = RegInit(0.U(32.W))
val stall_cycles = RegInit(0.U(32.W))

// =============================== 流水线阶段-IF (取指) ==============================
val pc = Reg(UInt(32.W))
val pc_next = RegInit(0.U(32.W))

// 冒险检测单元连接(在ID阶段之后)
hazardDetection.io.ex_mem_read := idex_reg.ctrl.mem_read_en
hazardDetection.io.ex_rd_addr := idex_reg.rd_addr
hazardDetection.io.ex_branch := idex_reg.ctrl.branch
hazardDetection.io.ex_jump := idex_reg.ctrl.jump

// 获取冒险检测信号
val stall_if = hazardDetection.io.stall_if
val flush_id = hazardDetection.io.flush_id

// 分支预测器连接(IF阶段)
branchPredictor.io.pc_predict := pc

when(io.rst) {
pc := "h_80000000".U
pc_next := "h_80000000".U + 4.U
} .elsewhen(!stall_if) { // 只有在不暂停时才更新PC
pc := pc_next
// 使用分支预测选择下一个PC
pc_next := Mux(branchPredictor.io.predict_taken,
branchPredictor.io.predict_target,
pc_next + 4.U)
}

io.imem_addr := pc

// 流水线寄存器更新(支持冲刷)
when(!stall_if) {
ifid_reg.inst := io.imem_inst
ifid_reg.pc := pc
}

// 冲刷ID阶段(插入气泡)
when(flush_id) {
ifid_reg.inst := 0.U // NOP指令
ifid_reg.pc := 0.U
}

// =============================== 流水线阶段-ID (译码) ==============================
val id_inst = ifid_reg.inst
val id_pc = ifid_reg.pc
decoder.io.inst := id_inst
val ctrl_sigs = decoder.io.sigs
val rd_addr = id_inst(4, 0)
val rj_addr = id_inst(9, 5)
val rk_addr = id_inst(14, 10)

// 冒险检测单元连接(ID阶段)
hazardDetection.io.id_rs1_addr := rj_addr
hazardDetection.io.id_rs2_addr := rk_addr

// 获取冒险检测信号
val stall_id = hazardDetection.io.stall_id
val flush_ex = hazardDetection.io.flush_ex

// 立即数生成(在ID阶段)
immGen.io.inst := id_inst
immGen.io.imm_type := ctrl_sigs.imm_type

regFile.io.rs1_addr := rj_addr
regFile.io.rs2_addr := rk_addr

// ID/EX流水线寄存器更新(支持停顿)
when(!stall_id) {
idex_reg.pc := id_pc
idex_reg.alu_a := regFile.io.rs1_data
idex_reg.alu_b := regFile.io.rs2_data
idex_reg.rd_addr := rd_addr
idex_reg.rs1_addr := rj_addr // 传递源寄存器地址
idex_reg.rs2_addr := rk_addr // 传递源寄存器地址
idex_reg.ctrl := ctrl_sigs
idex_imm := immGen.io.imm_out
}

// 冲刷EX阶段(插入气泡)
when(flush_ex) {
idex_reg.pc := 0.U
idex_reg.alu_a := 0.U
idex_reg.alu_b := 0.U
idex_reg.rd_addr := 0.U
idex_reg.rs1_addr := 0.U
idex_reg.rs2_addr := 0.U
idex_reg.ctrl := 0.U.asTypeOf(new ControlSigs) // 清零控制信号
idex_imm := 0.U
}

// =============================== 流水线阶段-EX (执行) ==============================
val ex_ctrl = idex_reg.ctrl

// 前递单元连接
forwardingUnit.io.ex_rs1_addr := idex_reg.rs1_addr
forwardingUnit.io.ex_rs2_addr := idex_reg.rs2_addr
forwardingUnit.io.mem_rd_addr := exmem_reg.rd_addr
forwardingUnit.io.mem_reg_write := exmem_reg.reg_write_en
forwardingUnit.io.wb_rd_addr := memwb_reg.rd_addr
forwardingUnit.io.wb_reg_write := memwb_reg.reg_write_en

// 前递数据选择
val forward_a = forwardingUnit.io.forward_a
val forward_b = forwardingUnit.io.forward_b

// 前递的ALU输入A
val alu_a_forwarded = MuxCase(idex_reg.alu_a, Seq(
(forward_a === 1.U) -> exmem_reg.alu_out, // EX/MEM前递
(forward_a === 2.U) -> memwb_reg.wb_data // MEM/WB前递
))

// 前递的ALU输入B
val alu_b_forwarded = MuxCase(idex_reg.alu_b, Seq(
(forward_b === 1.U) -> exmem_reg.alu_out, // EX/MEM前递
(forward_b === 2.U) -> memwb_reg.wb_data // MEM/WB前递
))

// 立即数选择:使用流水线寄存器中的立即数或寄存器数据
val alu_b = Mux(ex_ctrl.imm_type === 0.U, alu_b_forwarded, idex_imm)

// 特殊指令处理
val is_lu12i = (idex_reg.ctrl.imm_type === 3.U) // lu12i.w指令识别
val is_pcaddu12i = (idex_reg.ctrl.imm_type === 4.U) // pcaddu12i指令识别

// ALU输入选择
val alu_a = Mux(is_pcaddu12i, idex_reg.pc, alu_a_forwarded)
val alu_b_final = Mux(is_lu12i, idex_imm, alu_b)

alu.io.op := ex_ctrl.alu_op
alu.io.a := alu_a
alu.io.b := alu_b_final

// 跳转逻辑
val jump_taken = ex_ctrl.jump || (ex_ctrl.branch && alu.io.zero)
val jump_target = Mux(ex_ctrl.imm_type === 2.U,
idex_reg.pc + (idex_imm << 2), // jirl指令:PC + 立即数*4
idex_reg.pc + (idex_reg.alu_a << 2) // 其他跳转指令
)

// 分支预测器验证(EX阶段)
val is_branch_inst = ex_ctrl.branch || ex_ctrl.jump
branchPredictor.io.pc_verify := idex_reg.pc
branchPredictor.io.actual_taken := jump_taken
branchPredictor.io.actual_target := jump_target
branchPredictor.io.is_branch := is_branch_inst

// 预测错误处理
val prediction_miss = is_branch_inst && !branchPredictor.io.prediction_correct

// 连接分支预测错误信号到冒险检测单元
hazardDetection.io.prediction_miss := prediction_miss

// 跳转时更新PC(控制冒险处理)
when(jump_taken) {
pc_next := jump_target
} .elsewhen(prediction_miss) {
// 预测错误时恢复正确的PC
pc_next := Mux(jump_taken, jump_target, idex_reg.pc + 4.U)
}

exmem_reg.pc := idex_reg.pc
exmem_reg.alu_out := alu.io.out
exmem_reg.alu_b := idex_reg.alu_b // 传递rs2数据用于访存
exmem_reg.rd_addr := idex_reg.rd_addr
exmem_reg.reg_write_en := ex_ctrl.reg_write_en
exmem_reg.ctrl := ex_ctrl // 传递控制信号
exmem_reg.alu_zero := alu.io.zero

// =============================== 流水线阶段-MEM (访存) ==============================
val mem_ctrl = exmem_reg.ctrl

// 内存访问
memUnit.io.addr := exmem_reg.alu_out
memUnit.io.write_data := exmem_reg.alu_b // 写数据来自rs2
memUnit.io.write_en := mem_ctrl.mem_write_en
memUnit.io.read_en := mem_ctrl.mem_read_en
memUnit.io.mem_size := mem_ctrl.mem_size

// 写回数据选择
val wb_data = Mux(mem_ctrl.mem_read_en, memUnit.io.read_data, exmem_reg.alu_out)

memwb_reg.pc := exmem_reg.pc
memwb_reg.wb_data := wb_data
memwb_reg.rd_addr := exmem_reg.rd_addr
memwb_reg.reg_write_en := exmem_reg.reg_write_en

// =============================== 流水线阶段-WB (写回) ==============================
// 在复位解除后的第一个有效周期之前,屏蔽写回,避免不期望的写寄存器
val allowWriteBack = RegInit(false.B)
when (io.rst) {
allowWriteBack := false.B
} .otherwise {
allowWriteBack := true.B
}

regFile.io.rd_addr := memwb_reg.rd_addr
regFile.io.rd_data := memwb_reg.wb_data
regFile.io.rd_en := (memwb_reg.reg_write_en && allowWriteBack)

posted @ 2025-10-29 10:33  when-epoch  阅读(6)  评论(0)    收藏  举报