lab3截图和小更改
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
BIN
lab3/成功截图/3cpu.png
Normal file
|
After Width: | Height: | Size: 544 KiB |
BIN
lab3/成功截图/CLINT.png
Normal file
|
After Width: | Height: | Size: 282 KiB |
BIN
lab3/成功截图/cpu1.png
Normal file
|
After Width: | Height: | Size: 336 KiB |
BIN
lab3/成功截图/cpu2.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
lab3/成功截图/cpufinal.png
Normal file
|
After Width: | Height: | Size: 528 KiB |
BIN
lab3/成功截图/cpuforward.png
Normal file
|
After Width: | Height: | Size: 509 KiB |
BIN
lab3/成功截图/cpustall.png
Normal file
|
After Width: | Height: | Size: 538 KiB |
BIN
lab3/成功截图/ppl.png
Normal file
|
After Width: | Height: | Size: 570 KiB |