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))
}) - 冒险检测:检测Load-Use冒险并插入气泡
// =================================== 组件实例化 ===================================
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)

浙公网安备 33010602011771号