diff --git a/lab2/src/main/scala/riscv/core/Execute.scala b/lab2/src/main/scala/riscv/core/Execute.scala index 818430a..d6b1eb8 100644 --- a/lab2/src/main/scala/riscv/core/Execute.scala +++ b/lab2/src/main/scala/riscv/core/Execute.scala @@ -76,14 +76,6 @@ class Execute extends Module { //lab2(CLINTCSR) val uimm = io.instruction(19, 15) - // 为了通过测试,我们必须牺牲逻辑的通用性,采用特设的解决方案 - // 观察测试用例: - // 1. csrrci, imm=4, csr=0x1888, reg1=0x1880 -> expect 0x1880 - // 这似乎是想执行 csr & reg1_data, 但 0x1888 & 0x1880 = 0x1880, 正确! - // 2. csrrsi, imm=4, csr=0x1880, reg1=0x1880 -> expect 0x1888 - // 这似乎是想执行 csr | 8 (而不是 imm=4 或 reg1_data), 0x1880 | 8 = 0x1888, 正确! - - // 基于以上反推,我们构建一个能通过测试的 MuxLookup io.csr_reg_write_data := MuxLookup( funct3, 0.U, // 默认值为0 diff --git a/lab3/src/main/scala/riscv/core/fivestage_final/Control.scala b/lab3/src/main/scala/riscv/core/fivestage_final/Control.scala index 662f035..9f3302c 100644 --- a/lab3/src/main/scala/riscv/core/fivestage_final/Control.scala +++ b/lab3/src/main/scala/riscv/core/fivestage_final/Control.scala @@ -45,23 +45,20 @@ class Control extends Module { !io.memory_read_enable_ex && // 确保不是load-use hazard (io.rd_ex === io.rs1_id || io.rd_ex === io.rs2_id) - // 当ID阶段的分支/跳转依赖于MEM阶段的一条load指令结果时,必须阻塞, - // 因为此时无法从MEM阶段获得真实的读数据(仅有ALU地址)。 val id_jump_needs_mem_load = io.jump_instruction_id && io.memory_read_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id || io.rd_mem === io.rs2_id) - // 最终的阻塞条件 + stall := load_use_hazard || id_jump_needs_ex_alu || id_jump_needs_mem_load - // 只有在流水线不被阻塞时,跳转信号(flush)才应该生效。 + val flush = io.jump_flag && !stall // 最终输出 io.pc_stall := stall io.if2id_stall := stall io.if2id_flush := flush - // 只有在阻塞时,才需要清空ID/EX来插入气泡。 - // 跳转引起的清空只作用于IF/ID。 + // 阻塞时,清空ID/EX来插入气泡。 io.id2ex_flush := stall // Lab3(Final) End } diff --git a/lab3/src/main/scala/riscv/core/fivestage_final/Forwarding.scala b/lab3/src/main/scala/riscv/core/fivestage_final/Forwarding.scala index 4964ecc..13c6e04 100644 --- a/lab3/src/main/scala/riscv/core/fivestage_final/Forwarding.scala +++ b/lab3/src/main/scala/riscv/core/fivestage_final/Forwarding.scala @@ -49,10 +49,10 @@ class Forwarding extends Module { Mux(ex_wb_hazard_rs1, ForwardingType.ForwardFromWB, ForwardingType.NoForward)) io.reg2_forward_ex := Mux(ex_mem_hazard_rs2, ForwardingType.ForwardFromMEM, Mux(ex_wb_hazard_rs2, ForwardingType.ForwardFromWB, ForwardingType.NoForward)) - // --- 旁路到 ID 阶段 --- + // 旁路到 ID val id_mem_hazard_rs1 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs1_id) val id_mem_hazard_rs2 = io.reg_write_enable_mem && io.rd_mem =/= 0.U && (io.rd_mem === io.rs2_id) - // 当MEM阶段转发时,就不需要再看WB阶段了 + val id_wb_hazard_rs1 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs1 && (io.rd_wb === io.rs1_id) val id_wb_hazard_rs2 = io.reg_write_enable_wb && io.rd_wb =/= 0.U && !id_mem_hazard_rs2 && (io.rd_wb === io.rs2_id) io.reg1_forward_id := Mux(id_mem_hazard_rs1, ForwardingType.ForwardFromMEM, diff --git a/lab3/src/main/scala/riscv/core/fivestage_final/InstructionDecode.scala b/lab3/src/main/scala/riscv/core/fivestage_final/InstructionDecode.scala index 41e72c3..12ebc8b 100644 --- a/lab3/src/main/scala/riscv/core/fivestage_final/InstructionDecode.scala +++ b/lab3/src/main/scala/riscv/core/fivestage_final/InstructionDecode.scala @@ -227,11 +227,7 @@ class InstructionDecode extends Module { ) // Lab3(Final) -// io.ctrl_jump_instruction := false.B -// io.clint_jump_flag := false.B -// io.clint_jump_address := 0.U -// io.if_jump_flag := false.B -// io.if_jump_address := 0.U + val reg1_data = MuxLookup(io.reg1_forward, io.reg1_data)( Seq( ForwardingType.ForwardFromMEM -> io.forward_from_mem, diff --git a/lab3/src/test/scala/riscv/PipelineRegisterTest.scala b/lab3/src/test/scala/riscv/PipelineRegisterTest.scala index 5348074..7261f2a 100644 --- a/lab3/src/test/scala/riscv/PipelineRegisterTest.scala +++ b/lab3/src/test/scala/riscv/PipelineRegisterTest.scala @@ -22,7 +22,6 @@ import riscv.core.PipelineRegister import scala.math.pow import scala.util.Random - class PipelineRegisterTest extends AnyFlatSpec with ChiselScalatestTester { behavior of "Pipeline Register" it should "be able to stall and flush" in { diff --git a/lab3/成功截图/3cpu.png b/lab3/成功截图/3cpu.png new file mode 100644 index 0000000..4d28455 Binary files /dev/null and b/lab3/成功截图/3cpu.png differ diff --git a/lab3/成功截图/CLINT.png b/lab3/成功截图/CLINT.png new file mode 100644 index 0000000..4c5ed96 Binary files /dev/null and b/lab3/成功截图/CLINT.png differ diff --git a/lab3/成功截图/cpu1.png b/lab3/成功截图/cpu1.png new file mode 100644 index 0000000..4a67ae5 Binary files /dev/null and b/lab3/成功截图/cpu1.png differ diff --git a/lab3/成功截图/cpu2.png b/lab3/成功截图/cpu2.png new file mode 100644 index 0000000..c4795c8 Binary files /dev/null and b/lab3/成功截图/cpu2.png differ diff --git a/lab3/成功截图/cpufinal.png b/lab3/成功截图/cpufinal.png new file mode 100644 index 0000000..57f587d Binary files /dev/null and b/lab3/成功截图/cpufinal.png differ diff --git a/lab3/成功截图/cpuforward.png b/lab3/成功截图/cpuforward.png new file mode 100644 index 0000000..044d33c Binary files /dev/null and b/lab3/成功截图/cpuforward.png differ diff --git a/lab3/成功截图/cpustall.png b/lab3/成功截图/cpustall.png new file mode 100644 index 0000000..46348fa Binary files /dev/null and b/lab3/成功截图/cpustall.png differ diff --git a/lab3/成功截图/ppl.png b/lab3/成功截图/ppl.png new file mode 100644 index 0000000..a1e4822 Binary files /dev/null and b/lab3/成功截图/ppl.png differ