From 2a16d26278cd4b98d1857771a30ebc5fefd90786 Mon Sep 17 00:00:00 2001 From: Liphen Date: Thu, 7 Dec 2023 21:14:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=80=9A=E8=BF=87=E6=89=80=E6=9C=89?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chisel/playground/src/Core.scala | 2 +- chisel/playground/src/cache/DCache.scala | 27 ++--- chisel/playground/src/defines/Bundles.scala | 3 +- .../pipeline/memory/DataMemoryAccess.scala | 111 +++++++++++++----- .../src/pipeline/memory/LSExe.scala | 24 +--- .../src/pipeline/memory/MemoryUnit.scala | 1 + 6 files changed, 98 insertions(+), 70 deletions(-) diff --git a/chisel/playground/src/Core.scala b/chisel/playground/src/Core.scala index 66978e8..adecd63 100644 --- a/chisel/playground/src/Core.scala +++ b/chisel/playground/src/Core.scala @@ -119,7 +119,7 @@ class Core(implicit val config: CpuConfig) extends Module { memoryUnit.dataMemory.in.rdata := io.data.rdata memoryUnit.dataMemory.in.acc_err := io.data.acc_err - memoryUnit.dataMemory.in.ready := !io.data.dcache_stall + memoryUnit.dataMemory.in.ready := io.data.dcache_ready io.data.en := memoryUnit.dataMemory.out.en io.data.size := memoryUnit.dataMemory.out.rlen io.data.wen := memoryUnit.dataMemory.out.wen diff --git a/chisel/playground/src/cache/DCache.scala b/chisel/playground/src/cache/DCache.scala index 38c90b6..f153706 100644 --- a/chisel/playground/src/cache/DCache.scala +++ b/chisel/playground/src/cache/DCache.scala @@ -15,10 +15,8 @@ class DCache(implicit config: CpuConfig) extends Module { }) // * fsm * // - val s_idle :: s_uncached :: s_writeback :: s_save :: Nil = Enum(4) - val status = RegInit(s_idle) - - io.cpu.valid := status === s_save + val s_idle :: s_uncached :: s_writeback :: Nil = Enum(3) + val status = RegInit(s_idle) val addr_err = io.cpu.addr(63, 32).orR @@ -69,13 +67,9 @@ class DCache(implicit config: CpuConfig) extends Module { val mmio_read_stall = !io.cpu.wen.orR val mmio_write_stall = io.cpu.wen.orR && !io.axi.w.ready val cached_stall = false.B - io.cpu.dcache_stall := Mux( - status === s_idle && !acc_err, - Mux(io.cpu.en, (cached_stall || mmio_read_stall || mmio_write_stall), io.cpu.fence), - status =/= s_save - ) - io.cpu.rdata := saved_rdata - io.cpu.acc_err := acc_err + io.cpu.dcache_ready := status === s_idle + io.cpu.rdata := saved_rdata + io.cpu.acc_err := acc_err switch(status) { is(s_idle) { @@ -83,7 +77,7 @@ class DCache(implicit config: CpuConfig) extends Module { when(io.cpu.en) { when(addr_err) { acc_err := true.B - status := s_save + status := s_idle }.otherwise { when(io.cpu.wen) { awaddr := io.cpu.addr(31, 0) @@ -110,7 +104,7 @@ class DCache(implicit config: CpuConfig) extends Module { when(io.axi.r.valid) { saved_rdata := io.axi.r.data acc_err := io.axi.r.resp =/= RESP_OKEY.U - status := s_save + status := s_idle } } is(s_writeback) { @@ -122,12 +116,7 @@ class DCache(implicit config: CpuConfig) extends Module { } when(io.axi.b.valid) { acc_err := io.axi.b.resp =/= RESP_OKEY.U - status := s_save - } - } - is(s_save) { - when(!io.cpu.dcache_stall) { - status := s_idle + status := s_idle } } } diff --git a/chisel/playground/src/defines/Bundles.scala b/chisel/playground/src/defines/Bundles.scala index b970c0f..97244ae 100644 --- a/chisel/playground/src/defines/Bundles.scala +++ b/chisel/playground/src/defines/Bundles.scala @@ -132,9 +132,8 @@ class Cache_DCache extends Bundle { val wstrb = Output(UInt(AXI_STRB_WID.W)) val rdata = Input(UInt(XLEN.W)) - val valid = Input(Bool()) val acc_err = Input(Bool()) - val dcache_stall = Input(Bool()) + val dcache_ready = Input(Bool()) } // axi diff --git a/chisel/playground/src/pipeline/memory/DataMemoryAccess.scala b/chisel/playground/src/pipeline/memory/DataMemoryAccess.scala index 8c31959..afe4c5b 100644 --- a/chisel/playground/src/pipeline/memory/DataMemoryAccess.scala +++ b/chisel/playground/src/pipeline/memory/DataMemoryAccess.scala @@ -32,6 +32,8 @@ class DataMemoryAccess_MemoryUnit extends Bundle { val lr = Bool() val lr_addr = UInt(DATA_ADDR_WID.W) + + val allow_to_go = Bool() }) val out = Output(new Bundle { val ready = Bool() @@ -86,7 +88,7 @@ class DataMemoryAccess(implicit val config: CpuConfig) extends Module { lr := io.memoryUnit.in.lr lrAddr := io.memoryUnit.in.lr_addr - val s_idle :: s_lr :: s_sc :: s_amo_l :: s_amo_a :: s_amo_s :: Nil = Enum(6) + val s_idle :: s_load :: s_sc :: s_amo_l :: s_amo_l_wait :: s_amo_a :: s_amo_s :: s_wait_allow :: Nil = Enum(8) val state = RegInit(s_idle) val atomMemReg = Reg(UInt(XLEN.W)) @@ -97,25 +99,42 @@ class DataMemoryAccess(implicit val config: CpuConfig) extends Module { val scInvalid = (src1 =/= lrAddr || !lr) && scReq - lsExe.in.info := io.memoryUnit.in.info - lsExe.in.mem_addr := 0.U + lsExe.in.info := DontCare + lsExe.in.mem_addr := DontCare lsExe.in.mem_en := false.B - lsExe.in.wdata := 0.U + lsExe.in.wdata := DontCare io.memoryUnit.out.ready := false.B + val allow_to_go = io.memoryUnit.in.allow_to_go + switch(state) { is(s_idle) { // calculate address lsExe.in.mem_en := io.memoryUnit.in.mem_en && !atomReq lsExe.in.mem_addr := src1 + imm lsExe.in.info.op := func lsExe.in.wdata := src2 - io.memoryUnit.out.ready := lsExe.out.ready || scInvalid - state := s_idle - + io.memoryUnit.out.ready := lsExe.out.ready && io.dataMemory.out.en || scInvalid + when(io.memoryUnit.out.ready) { + when(allow_to_go) { + state := s_idle + } + state := s_wait_allow; + } when(amoReq) { state := s_amo_l } - when(lrReq) { state := s_lr } + when(lrReq) { + lsExe.in.mem_en := true.B + lsExe.in.mem_addr := src1 + lsExe.in.info.op := Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw) + lsExe.in.wdata := DontCare + io.memoryUnit.out.ready := lsExe.out.ready && io.dataMemory.out.en + when(lsExe.out.ready) { + when(allow_to_go) { + state := s_idle + } + state := s_wait_allow; + } + } when(scReq) { state := Mux(scInvalid, s_idle, s_sc) } - } is(s_amo_l) { @@ -124,11 +143,22 @@ class DataMemoryAccess(implicit val config: CpuConfig) extends Module { lsExe.in.info.op := Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw) lsExe.in.wdata := DontCare io.memoryUnit.out.ready := false.B + when(lsExe.out.ready) { + state := s_amo_l_wait; + } + } + + is(s_amo_l_wait) { + lsExe.in.mem_en := false.B + lsExe.in.mem_addr := src1 + lsExe.in.info.op := Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw) + lsExe.in.wdata := DontCare + io.memoryUnit.out.ready := false.B + atomMemReg := lsExe.out.rdata + atomRegReg := lsExe.out.rdata when(lsExe.out.ready) { state := s_amo_a; } - atomMemReg := lsExe.out.rdata - atomRegReg := lsExe.out.rdata } is(s_amo_a) { @@ -146,19 +176,12 @@ class DataMemoryAccess(implicit val config: CpuConfig) extends Module { lsExe.in.mem_addr := src1 lsExe.in.info.op := Mux(atomWidthD, LSUOpType.sd, LSUOpType.sw) lsExe.in.wdata := atomMemReg - io.memoryUnit.out.ready := lsExe.out.ready + io.memoryUnit.out.ready := lsExe.out.ready && io.dataMemory.out.en when(lsExe.out.ready) { - state := s_idle; - } - } - is(s_lr) { - lsExe.in.mem_en := true.B - lsExe.in.mem_addr := src1 - lsExe.in.info.op := Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw) - lsExe.in.wdata := DontCare - io.memoryUnit.out.ready := lsExe.out.ready - when(lsExe.out.ready) { - state := s_idle; + when(allow_to_go) { + state := s_idle + } + state := s_wait_allow; } } is(s_sc) { @@ -166,16 +189,39 @@ class DataMemoryAccess(implicit val config: CpuConfig) extends Module { lsExe.in.mem_addr := src1 lsExe.in.info.op := Mux(atomWidthD, LSUOpType.sd, LSUOpType.sw) lsExe.in.wdata := src2 - io.memoryUnit.out.ready := lsExe.out.ready + io.memoryUnit.out.ready := lsExe.out.ready && io.dataMemory.out.en when(lsExe.out.ready) { - state := s_idle; + when(allow_to_go) { + state := s_idle + } + state := s_wait_allow; + } + } + is(s_wait_allow) { + lsExe.in.mem_en := false.B + lsExe.in.info.op := MuxCase( + func, + Seq( + lrReq -> Mux(atomWidthD, LSUOpType.ld, LSUOpType.lw), + scReq -> Mux(atomWidthD, LSUOpType.sd, LSUOpType.sw) + ) + ) + lsExe.in.mem_addr := Mux(amoReq || lrReq || scReq, src1, src1 + imm) + lsExe.in.wdata := DontCare + io.memoryUnit.out.ready := io.dataMemory.in.ready + when(allow_to_go && io.dataMemory.in.ready) { + state := s_idle } } } - when(lsExe.out.loadAddrMisaligned || lsExe.out.storeAddrMisaligned) { + when( + lsExe.out.loadAddrMisaligned || + lsExe.out.storeAddrMisaligned || + lsExe.out.loadAccessFault || + lsExe.out.storeAccessFault + ) { state := s_idle io.memoryUnit.out.ready := true.B - io.memoryUnit.out.ready := true.B } setLr := io.memoryUnit.out.ready && (lrReq || scReq) @@ -189,6 +235,13 @@ class DataMemoryAccess(implicit val config: CpuConfig) extends Module { io.memoryUnit.out.ex.exception(storeAddrMisaligned) := lsExe.out.storeAddrMisaligned io.memoryUnit.out.ex.exception(loadAccessFault) := lsExe.out.loadAccessFault io.memoryUnit.out.ex.exception(storeAccessFault) := lsExe.out.storeAccessFault - io.memoryUnit.out.ex.tval := io.dataMemory.out.addr - io.memoryUnit.out.rdata := lsExe.out.rdata + + io.memoryUnit.out.ex.tval := io.dataMemory.out.addr + io.memoryUnit.out.rdata := MuxCase( + lsExe.out.rdata, + Seq( + (scReq) -> scInvalid, + (amoReq) -> atomRegReg + ) + ) } diff --git a/chisel/playground/src/pipeline/memory/LSExe.scala b/chisel/playground/src/pipeline/memory/LSExe.scala index 10597ac..e1b3955 100644 --- a/chisel/playground/src/pipeline/memory/LSExe.scala +++ b/chisel/playground/src/pipeline/memory/LSExe.scala @@ -69,10 +69,9 @@ class LSExe extends Module { ) } - val valid = io.in.mem_en - val addr = io.in.mem_addr - val addrLatch = RegNext(addr) - val op = io.in.info.op + val valid = io.in.mem_en + val addr = io.in.mem_addr + val op = io.in.info.op val isStore = valid && LSUOpType.isStore(op) val partialLoad = !isStore && (op =/= LSUOpType.ld) @@ -88,7 +87,7 @@ class LSExe extends Module { val acc_err = io.dataMemory.in.acc_err val rdataSel64 = LookupTree( - addrLatch(2, 0), + addr(2, 0), List( "b000".U -> rdata(63, 0), "b001".U -> rdata(63, 8), @@ -101,7 +100,7 @@ class LSExe extends Module { ) ) val rdataSel32 = LookupTree( - addrLatch(1, 0), + addr(1, 0), List( "b00".U -> rdata(31, 0), "b01".U -> rdata(31, 8), @@ -131,19 +130,6 @@ class LSExe extends Module { ) ) - // val s_idle :: s_wait_resp :: Nil = Enum(2) - // val state = RegInit(s_idle) - - // switch(state) { - // is(s_idle) { - // when(io.dataMemory.in.ready && io.dataMemory.out.en) { state := s_wait_resp } - // } - - // is(s_wait_resp) { - // when(io.dataMemory.in.ready) { state := s_idle } - // } - // } - io.dataMemory.out.en := valid && !io.out.storeAddrMisaligned && !io.out.loadAddrMisaligned && !has_acc_err io.dataMemory.out.rlen := size io.dataMemory.out.wen := isStore diff --git a/chisel/playground/src/pipeline/memory/MemoryUnit.scala b/chisel/playground/src/pipeline/memory/MemoryUnit.scala index 653d993..0547ce9 100644 --- a/chisel/playground/src/pipeline/memory/MemoryUnit.scala +++ b/chisel/playground/src/pipeline/memory/MemoryUnit.scala @@ -24,6 +24,7 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module { }) val dataMemoryAccess = Module(new DataMemoryAccess()).io + dataMemoryAccess.memoryUnit.in.allow_to_go := io.ctrl.allow_to_go val mem_sel = VecInit( io.memoryStage.inst0.info.valid && io.memoryStage.inst0.info.fusel === FuType.lsu &&