From 6f026723586fd2990be7d0883f72dea61653a1fb Mon Sep 17 00:00:00 2001 From: Liphen Date: Thu, 7 Dec 2023 15:02:22 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=B0=86=E8=AE=BF=E5=AD=98?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E9=87=8D=E6=9E=84=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../playground/src/pipeline/execute/Csr.scala | 21 ++- .../pipeline/execute/ExeAccessMemCtrl.scala | 92 ------------ .../src/pipeline/execute/ExecuteUnit.scala | 20 +-- .../src/pipeline/memory/AtomAlu.scala | 48 ++++++ .../src/pipeline/memory/LSExe.scala | 140 ++++++++++++++++++ .../src/pipeline/memory/MemoryStage.scala | 36 ++--- chisel/playground/test/src/TestMain.scala | 4 +- 7 files changed, 223 insertions(+), 138 deletions(-) delete mode 100644 chisel/playground/src/pipeline/execute/ExeAccessMemCtrl.scala create mode 100644 chisel/playground/src/pipeline/memory/AtomAlu.scala create mode 100644 chisel/playground/src/pipeline/memory/LSExe.scala diff --git a/chisel/playground/src/pipeline/execute/Csr.scala b/chisel/playground/src/pipeline/execute/Csr.scala index 596087e..529264f 100644 --- a/chisel/playground/src/pipeline/execute/Csr.scala +++ b/chisel/playground/src/pipeline/execute/Csr.scala @@ -103,6 +103,23 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst { val rdata = Wire(UInt(XLEN.W)) val wdata = Wire(UInt(XLEN.W)) + // Atom LR/SC Control Bits + val setLr = WireInit(Bool(), false.B) + val setLrVal = WireInit(Bool(), false.B) + val setLrAddr = WireInit(UInt(XLEN.W), DontCare) //TODO : need check + val lr = RegInit(Bool(), false.B) + val lrAddr = RegInit(UInt(XLEN.W), 0.U) + BoringUtils.addSink(setLr, "set_lr") + BoringUtils.addSink(setLrVal, "set_lr_val") + BoringUtils.addSink(setLrAddr, "set_lr_addr") + BoringUtils.addSource(lr, "lr") + BoringUtils.addSource(lrAddr, "lr_addr") + + when(setLr) { + lr := setLrVal + lrAddr := setLrAddr + } + // Side Effect def mstatusUpdateSideEffect(mstatus: UInt): UInt = { val mstatusOld = WireInit(mstatus.asTypeOf(new Mstatus)) @@ -325,8 +342,8 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst { mstatusNew.pie.m := true.B mstatusNew.mpp := ModeU mstatus := mstatusNew.asUInt - // lr := false.B //TODO: add原子操作 - ret_target := mepc(VADDR_WID - 1, 0) + lr := false.B + ret_target := mepc(VADDR_WID - 1, 0) } io.decoderUnit.priv_mode := priv_mode diff --git a/chisel/playground/src/pipeline/execute/ExeAccessMemCtrl.scala b/chisel/playground/src/pipeline/execute/ExeAccessMemCtrl.scala deleted file mode 100644 index 4107dbf..0000000 --- a/chisel/playground/src/pipeline/execute/ExeAccessMemCtrl.scala +++ /dev/null @@ -1,92 +0,0 @@ -package cpu.pipeline.execute - -import chisel3._ -import chisel3.util._ -import cpu.CpuConfig -import cpu.defines._ -import cpu.defines.Const._ - -class ExeAccessMemCtrl(implicit val config: CpuConfig) extends Module { - val io = IO(new Bundle { - val mem = new Bundle { - val out = Output(new Bundle { - val en = Bool() - val ren = Bool() - val wen = Bool() - val info = new InstInfo() - val addr = UInt(DATA_ADDR_WID.W) - val wdata = UInt(DATA_WID.W) - }) - } - - val inst = Vec( - config.fuNum, - new Bundle { - val info = Input(new InstInfo()) - val src_info = Input(new SrcInfo()) - val ex = new Bundle { - val in = Input(new ExceptionInfo()) - val out = Output(new ExceptionInfo()) - } - val mem_sel = Output(Bool()) - } - ) - }) - io.mem.out.en := io.inst.map(_.mem_sel).reduce(_ || _) - io.mem.out.ren := io.inst(0).mem_sel && LSUOpType.isLoad(io.inst(0).info.op) || - io.inst(1).mem_sel && LSUOpType.isLoad(io.inst(1).info.op) - io.mem.out.wen := io.inst(0).mem_sel && LSUOpType.isStore(io.inst(0).info.op) || - io.inst(1).mem_sel && LSUOpType.isStore(io.inst(1).info.op) - io.mem.out.info := Mux1H( - Seq( - (io.inst(0).info.fusel === FuType.lsu) -> io.inst(0).info, - (io.inst(1).info.fusel === FuType.lsu) -> io.inst(1).info - ) - ) - val mem_addr = Wire(Vec(config.fuNum, UInt(DATA_ADDR_WID.W))) - mem_addr(0) := io.inst(0).src_info.src1_data + io.inst(0).info.imm - mem_addr(1) := io.inst(1).src_info.src1_data + io.inst(1).info.imm - io.mem.out.addr := Mux1H( - Seq( - (io.inst(0).info.fusel === FuType.lsu) -> mem_addr(0), - (io.inst(1).info.fusel === FuType.lsu) -> mem_addr(1) - ) - ) - io.mem.out.wdata := Mux1H( - Seq( - (io.inst(0).info.fusel === FuType.lsu) -> - io.inst(0).src_info.src2_data, - (io.inst(1).info.fusel === FuType.lsu) -> - io.inst(1).src_info.src2_data - ) - ) - val addr_aligned = Wire(Vec(config.fuNum, Bool())) - for (i <- 0 until config.fuNum) { - addr_aligned(i) := LookupTree( - io.inst(i).info.op(1, 0), - List( - "b00".U -> true.B, //b - "b01".U -> (mem_addr(i)(0) === 0.U), //h - "b10".U -> (mem_addr(i)(1, 0) === 0.U), //w - "b11".U -> (mem_addr(i)(2, 0) === 0.U) //d - ) - ) - } - - for (i <- 0 until config.fuNum) { - val store_inst = LSUOpType.isStore(io.inst(i).info.op) - io.inst(i).ex.out := io.inst(i).ex.in - io.inst(i).ex.out.exception(loadAddrMisaligned) := !store_inst && !addr_aligned(i) - io.inst(i).ex.out.exception(storeAddrMisaligned) := store_inst && !addr_aligned(i) - io.inst(i).ex.out.tval := Mux( - io.inst(i).ex.in.exception.asUInt.orR, - io.inst(i).ex.in.tval, - mem_addr(i) - ) - } - io.inst(0).mem_sel := (io.inst(0).info.fusel === FuType.lsu) && - !(HasExcInt(io.inst(0).ex.out)) && io.inst(0).info.valid - io.inst(1).mem_sel := (io.inst(1).info.fusel === FuType.lsu) && - !(HasExcInt(io.inst(0).ex.out)) && !(HasExcInt(io.inst(1).ex.out)) && io.inst(1).info.valid - -} diff --git a/chisel/playground/src/pipeline/execute/ExecuteUnit.scala b/chisel/playground/src/pipeline/execute/ExecuteUnit.scala index ea021fe..a35dbb8 100644 --- a/chisel/playground/src/pipeline/execute/ExecuteUnit.scala +++ b/chisel/playground/src/pipeline/execute/ExecuteUnit.scala @@ -33,8 +33,7 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module { val memoryStage = Output(new ExecuteUnitMemoryUnit()) }) - val fu = Module(new Fu()).io - val accessMemCtrl = Module(new ExeAccessMemCtrl()).io + val fu = Module(new Fu()).io val valid = VecInit( io.executeStage.inst0.info.valid && io.ctrl.allow_to_go, @@ -88,13 +87,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module { fusel(1) === FuType.lsu && valid(1) && !(HasExcInt(io.executeStage.inst1.ex)) ) - // input accessMemCtrl - accessMemCtrl.inst(0).info := Mux(is_lsu(0), io.executeStage.inst0.info, 0.U.asTypeOf(new InstInfo())) - accessMemCtrl.inst(0).src_info := Mux(is_lsu(0), io.executeStage.inst0.src_info, 0.U.asTypeOf(new SrcInfo())) - accessMemCtrl.inst(0).ex.in := Mux(is_lsu(0), io.executeStage.inst0.ex, 0.U.asTypeOf(new ExceptionInfo())) - accessMemCtrl.inst(1).info := Mux(is_lsu(1), io.executeStage.inst1.info, 0.U.asTypeOf(new InstInfo())) - accessMemCtrl.inst(1).src_info := Mux(is_lsu(1), io.executeStage.inst1.src_info, 0.U.asTypeOf(new SrcInfo())) - accessMemCtrl.inst(1).ex.in := Mux(is_lsu(1), io.executeStage.inst1.ex, 0.U.asTypeOf(new ExceptionInfo())) // input fu fu.ctrl <> io.ctrl.fu @@ -119,14 +111,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module { io.ctrl.fu_stall := fu.stall_req - io.memoryStage.inst0.mem.en := accessMemCtrl.mem.out.en - io.memoryStage.inst0.mem.ren := accessMemCtrl.mem.out.ren - io.memoryStage.inst0.mem.wen := accessMemCtrl.mem.out.wen - io.memoryStage.inst0.mem.addr := accessMemCtrl.mem.out.addr - io.memoryStage.inst0.mem.wdata := accessMemCtrl.mem.out.wdata - io.memoryStage.inst0.mem.sel := accessMemCtrl.inst.map(_.mem_sel) - io.memoryStage.inst0.mem.info := accessMemCtrl.mem.out.info - io.memoryStage.inst0.pc := io.executeStage.inst0.pc io.memoryStage.inst0.info := io.executeStage.inst0.info io.memoryStage.inst0.rd_info.wdata(FuType.alu) := fu.inst(0).result.alu @@ -141,7 +125,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module { io.executeStage.inst0.ex, MuxLookup(io.executeStage.inst0.info.fusel, io.executeStage.inst0.ex)( Seq( - FuType.lsu -> accessMemCtrl.inst(0).ex.out, FuType.csr -> io.csr.out.ex ) ) @@ -166,7 +149,6 @@ class ExecuteUnit(implicit val config: CpuConfig) extends Module { io.executeStage.inst1.ex, MuxLookup(io.executeStage.inst1.info.fusel, io.executeStage.inst1.ex)( Seq( - FuType.lsu -> accessMemCtrl.inst(1).ex.out, FuType.csr -> io.csr.out.ex ) ) diff --git a/chisel/playground/src/pipeline/memory/AtomAlu.scala b/chisel/playground/src/pipeline/memory/AtomAlu.scala new file mode 100644 index 0000000..2f6b4ea --- /dev/null +++ b/chisel/playground/src/pipeline/memory/AtomAlu.scala @@ -0,0 +1,48 @@ +package cpu.pipeline.memory + +import chisel3._ +import chisel3.util._ +import cpu.defines._ +import cpu.defines.Const._ +import cpu.CpuConfig + +class AtomAlu extends Module { + val io = IO(new Bundle { + val in = Input(new Bundle { + val rdata = Input(UInt(XLEN.W)) // load data + val wdata = Input(UInt(XLEN.W)) // reg data + val info = new InstInfo() + }) + val out = Output(new Bundle { + val result = Output(UInt(XLEN.W)) + }) + }) + + val src1 = io.in.rdata + val src2 = io.in.wdata + val op = io.in.info.op + val is_sub = !LSUOpType.isAdd(op) + val sum = (src1 +& (src2 ^ Fill(XLEN, is_sub))) + is_sub + val oxr = src1 ^ src2 + val sltu = !sum(XLEN) + val slt = oxr(XLEN - 1) ^ sltu + val is_word = !io.in.info.inst(12) + + val res = LookupTreeDefault( + op(5, 0), + sum, + List( + LSUOpType.amoswap -> src2, + LSUOpType.amoadd -> sum, + LSUOpType.amoxor -> oxr, + LSUOpType.amoand -> (src1 & src2), + LSUOpType.amoor -> (src1 | src2), + LSUOpType.amomin -> Mux(slt(0), src1, src2), + LSUOpType.amomax -> Mux(slt(0), src2, src1), + LSUOpType.amominu -> Mux(sltu(0), src1, src2), + LSUOpType.amomaxu -> Mux(sltu(0), src2, src1) + ) + ) + + io.out.result := Mux(is_word, SignedExtend(res(31, 0), 64), res(XLEN - 1, 0)) +} diff --git a/chisel/playground/src/pipeline/memory/LSExe.scala b/chisel/playground/src/pipeline/memory/LSExe.scala new file mode 100644 index 0000000..e111496 --- /dev/null +++ b/chisel/playground/src/pipeline/memory/LSExe.scala @@ -0,0 +1,140 @@ +package cpu.pipeline.memory + +import chisel3._ +import chisel3.util._ +import cpu.defines._ +import cpu.defines.Const._ +import cpu.CpuConfig + +class LSExe extends Module { + val io = IO(new Bundle { + val dataMemory = new DataMemoryAccess_DataMemory() + val in = Input(new Bundle { + val mem_en = Bool() + val mem_addr = UInt(DATA_ADDR_WID.W) + val wdata = UInt(DATA_WID.W) + val info = new InstInfo() + }) + val out = Output(new Bundle { + val loadAddrMisaligned = Bool() + val storeAddrMisaligned = Bool() + val rdata = UInt(DATA_WID.W) + }) + }) + + def genWmask(addr: UInt, sizeEncode: UInt): UInt = { + LookupTree( + sizeEncode, + List( + "b00".U -> 0x1.U, //0001 << addr(2:0) + "b01".U -> 0x3.U, //0011 + "b10".U -> 0xf.U, //1111 + "b11".U -> 0xff.U //11111111 + ) + ) << addr(2, 0) + } + def genWdata(data: UInt, sizeEncode: UInt): UInt = { + LookupTree( + sizeEncode, + List( + "b00".U -> Fill(8, data(7, 0)), + "b01".U -> Fill(4, data(15, 0)), + "b10".U -> Fill(2, data(31, 0)), + "b11".U -> data + ) + ) + } + + def genWmask32(addr: UInt, sizeEncode: UInt): UInt = { + LookupTree( + sizeEncode, + List( + "b00".U -> 0x1.U, //0001 << addr(1:0) + "b01".U -> 0x3.U, //0011 + "b10".U -> 0xf.U //1111 + ) + ) << addr(1, 0) + } + def genWdata32(data: UInt, sizeEncode: UInt): UInt = { + LookupTree( + sizeEncode, + List( + "b00".U -> Fill(4, data(7, 0)), + "b01".U -> Fill(2, data(15, 0)), + "b10".U -> data + ) + ) + } + + val valid = io.in.mem_en + val addr = io.in.mem_addr + val addrLatch = RegNext(addr) + val op = io.in.info.op + + val isStore = valid && LSUOpType.isStore(op) + val partialLoad = !isStore && (op =/= LSUOpType.ld) + + val size = op(1, 0) + val reqAddr = if (XLEN == 32) SignedExtend(addr, VADDR_WID) else addr(VADDR_WID - 1, 0) + val reqWdata = if (XLEN == 32) genWdata32(io.in.wdata, size) else genWdata(io.in.wdata, size) + val reqWmask = if (XLEN == 32) genWmask32(addr, size) else genWmask(addr, size) + + io.dataMemory.out.en := valid && !io.out.storeAddrMisaligned && !io.out.loadAddrMisaligned + io.dataMemory.out.rlen := size + io.dataMemory.out.wen := isStore + io.dataMemory.out.wstrb := reqWmask + io.dataMemory.out.addr := reqAddr + io.dataMemory.out.wdata := reqWdata + + val rdata = io.dataMemory.in.rdata + val acc_err = io.dataMemory.in.acc_err + + val rdataSel64 = LookupTree( + addrLatch(2, 0), + List( + "b000".U -> rdata(63, 0), + "b001".U -> rdata(63, 8), + "b010".U -> rdata(63, 16), + "b011".U -> rdata(63, 24), + "b100".U -> rdata(63, 32), + "b101".U -> rdata(63, 40), + "b110".U -> rdata(63, 48), + "b111".U -> rdata(63, 56) + ) + ) + val rdataSel32 = LookupTree( + addrLatch(1, 0), + List( + "b00".U -> rdata(31, 0), + "b01".U -> rdata(31, 8), + "b10".U -> rdata(31, 16), + "b11".U -> rdata(31, 24) + ) + ) + val rdataSel = if (XLEN == 32) rdataSel32 else rdataSel64 + val rdataPartialLoad = LookupTree( + op, + List( + LSUOpType.lb -> SignedExtend(rdataSel(7, 0), XLEN), + LSUOpType.lh -> SignedExtend(rdataSel(15, 0), XLEN), + LSUOpType.lw -> SignedExtend(rdataSel(31, 0), XLEN), + LSUOpType.lbu -> ZeroExtend(rdataSel(7, 0), XLEN), + LSUOpType.lhu -> ZeroExtend(rdataSel(15, 0), XLEN), + LSUOpType.lwu -> ZeroExtend(rdataSel(31, 0), XLEN) + ) + ) + val addrAligned = LookupTree( + op(1, 0), + List( + "b00".U -> true.B, //b + "b01".U -> (addr(0) === 0.U), //h + "b10".U -> (addr(1, 0) === 0.U), //w + "b11".U -> (addr(2, 0) === 0.U) //d + ) + ) + + val is_amo = valid && LSUOpType.isAMO(op) + io.out.rdata := Mux(partialLoad, rdataPartialLoad, rdataSel) + io.out.loadAddrMisaligned := valid && !isStore && !is_amo && !addrAligned + io.out.storeAddrMisaligned := valid && (isStore || is_amo) && !addrAligned +} diff --git a/chisel/playground/src/pipeline/memory/MemoryStage.scala b/chisel/playground/src/pipeline/memory/MemoryStage.scala index 67e70f5..0d4bc6b 100644 --- a/chisel/playground/src/pipeline/memory/MemoryStage.scala +++ b/chisel/playground/src/pipeline/memory/MemoryStage.scala @@ -6,29 +6,17 @@ import cpu.defines._ import cpu.defines.Const._ import cpu.CpuConfig -class ExeMemInst1 extends Bundle { - val pc = UInt(PC_WID.W) - val info = new InstInfo() - val rd_info = new RdInfo() - val ex = new ExceptionInfo() -} - -class ExeMemInst0(implicit val config: CpuConfig) extends ExeMemInst1 { - val mem = new Bundle { - val en = Bool() - val ren = Bool() - val wen = Bool() - val info = new InstInfo() - val addr = UInt(DATA_ADDR_WID.W) - val wdata = UInt(DATA_WID.W) - val sel = Vec(config.fuNum, Bool()) - } +class ExeMemInst extends Bundle { + val pc = UInt(PC_WID.W) + val info = new InstInfo() + val rd_info = new RdInfo() + val src_info = new SrcInfo() + val ex = new ExceptionInfo() } class ExecuteUnitMemoryUnit(implicit val config: CpuConfig) extends Bundle { - - val inst0 = new ExeMemInst0() - val inst1 = new ExeMemInst1() + val inst0 = new ExeMemInst() + val inst1 = new ExeMemInst() } class MemoryStage(implicit val config: CpuConfig) extends Module { @@ -40,12 +28,12 @@ class MemoryStage(implicit val config: CpuConfig) extends Module { val executeUnit = Input(new ExecuteUnitMemoryUnit()) val memoryUnit = Output(new ExecuteUnitMemoryUnit()) }) - val inst0 = RegInit(0.U.asTypeOf(new ExeMemInst0())) - val inst1 = RegInit(0.U.asTypeOf(new ExeMemInst1())) + val inst0 = RegInit(0.U.asTypeOf(new ExeMemInst())) + val inst1 = RegInit(0.U.asTypeOf(new ExeMemInst())) when(io.ctrl.clear) { - inst0 := 0.U.asTypeOf(new ExeMemInst0()) - inst1 := 0.U.asTypeOf(new ExeMemInst1()) + inst0 := 0.U.asTypeOf(new ExeMemInst()) + inst1 := 0.U.asTypeOf(new ExeMemInst()) }.elsewhen(io.ctrl.allow_to_go) { inst0 := io.executeUnit.inst0 inst1 := io.executeUnit.inst1 diff --git a/chisel/playground/test/src/TestMain.scala b/chisel/playground/test/src/TestMain.scala index 21d8574..5311df5 100644 --- a/chisel/playground/test/src/TestMain.scala +++ b/chisel/playground/test/src/TestMain.scala @@ -2,10 +2,12 @@ import cpu._ import circt.stage._ import cpu.pipeline.execute.Csr +import cpu.pipeline.memory.LSExe +import cpu.pipeline.memory.AtomAlu object TestMain extends App { implicit val config = new CpuConfig() - def top = new Csr() + def top = new AtomAlu() val useMFC = false // use MLIR-based firrtl compiler val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top)) if (useMFC) {