diff --git a/chisel/playground/src/defines/Const.scala b/chisel/playground/src/defines/Const.scala index 17fcc2c..e81e362 100644 --- a/chisel/playground/src/defines/Const.scala +++ b/chisel/playground/src/defines/Const.scala @@ -5,8 +5,9 @@ import chisel3.util._ import cpu.CpuConfig trait CoreParameter { - def config = new CpuConfig - val XLEN = if (config.isRV32) 32 else 64 + def config = new CpuConfig + val XLEN = if (config.isRV32) 32 else 64 + val VADDR_WID = 32 } trait Constants extends CoreParameter { diff --git a/chisel/playground/src/defines/CsrBundles.scala b/chisel/playground/src/defines/CsrBundles.scala index 916a132..62ee752 100644 --- a/chisel/playground/src/defines/CsrBundles.scala +++ b/chisel/playground/src/defines/CsrBundles.scala @@ -5,32 +5,26 @@ import chisel3.util._ import cpu.defines.Const._ class Mstatus extends Bundle { - val sd = Bool() - val wpri0 = UInt(25.W) - val mbe = Bool() - val sbe = Bool() - val sxl = UInt(2.W) - val uxl = UInt(2.W) - val wpri1 = UInt(9.W) - val tsr = Bool() - val tw = Bool() - val tvm = Bool() - val mxr = Bool() - val sum = Bool() - val mprv = Bool() - val xs = UInt(2.W) - val fs = UInt(2.W) - val mpp = UInt(2.W) - val vs = UInt(2.W) - val spp = Bool() - val mpie = Bool() - val ube = Bool() - val spie = Bool() - val wpri2 = Bool() - val mie = Bool() - val wpri3 = Bool() - val sie = Bool() - val wpri4 = Bool() + val sd = Output(UInt(1.W)) + + val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null + val sxl = if (XLEN == 64) Output(UInt(2.W)) else null + val uxl = if (XLEN == 64) Output(UInt(2.W)) else null + val pad0 = if (XLEN == 64) Output(UInt(9.W)) else Output(UInt(8.W)) + + val tsr = Output(UInt(1.W)) + val tw = Output(UInt(1.W)) + val tvm = Output(UInt(1.W)) + val mxr = Output(UInt(1.W)) + val sum = Output(UInt(1.W)) + val mprv = Output(UInt(1.W)) + val xs = Output(UInt(2.W)) + val fs = Output(UInt(2.W)) + val mpp = Output(UInt(2.W)) + val hpp = Output(UInt(2.W)) + val spp = Output(UInt(1.W)) + val pie = new Priv + val ie = new Priv } class Misa extends Bundle { diff --git a/chisel/playground/src/pipeline/decoder/DecoderUnit.scala b/chisel/playground/src/pipeline/decoder/DecoderUnit.scala index 69d276d..3bb9af4 100644 --- a/chisel/playground/src/pipeline/decoder/DecoderUnit.scala +++ b/chisel/playground/src/pipeline/decoder/DecoderUnit.scala @@ -124,11 +124,11 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module with HasExcepti io.executeStage.inst0.ex.exception(breakPoint) := inst_info(0).inst(31, 20) === privEbreak && inst_info(0).op === CSROpType.jmp io.executeStage.inst0.ex.exception(ecallM) := inst_info(0).inst(31, 20) === privEcall && - inst_info(0).op === CSROpType.jmp && priv_mode === ModeM + inst_info(0).op === CSROpType.jmp && priv_mode === ModeM && inst_info(0).fusel === FuType.csr io.executeStage.inst0.ex.exception(ecallS) := inst_info(0).inst(31, 20) === privEcall && - inst_info(0).op === CSROpType.jmp && priv_mode === ModeS + inst_info(0).op === CSROpType.jmp && priv_mode === ModeS && inst_info(0).fusel === FuType.csr io.executeStage.inst0.ex.exception(ecallU) := inst_info(0).inst(31, 20) === privEcall && - inst_info(0).op === CSROpType.jmp && priv_mode === ModeU + inst_info(0).op === CSROpType.jmp && priv_mode === ModeU && inst_info(0).fusel === FuType.csr io.executeStage.inst0.ex.tval := Mux( io.executeStage.inst0.ex.exception(instrAccessFault) || io.executeStage.inst0.ex.exception(instrAddrMisaligned), io.instFifo.inst(0).pc, @@ -162,11 +162,11 @@ class DecoderUnit(implicit val config: CpuConfig) extends Module with HasExcepti io.executeStage.inst1.ex.exception(breakPoint) := inst_info(1).inst(31, 20) === privEbreak && inst_info(1).op === CSROpType.jmp io.executeStage.inst1.ex.exception(ecallM) := inst_info(1).inst(31, 20) === privEcall && - inst_info(1).op === CSROpType.jmp && priv_mode === ModeM + inst_info(1).op === CSROpType.jmp && priv_mode === ModeM && inst_info(1).fusel === FuType.csr io.executeStage.inst1.ex.exception(ecallS) := inst_info(1).inst(31, 20) === privEcall && - inst_info(1).op === CSROpType.jmp && priv_mode === ModeS + inst_info(1).op === CSROpType.jmp && priv_mode === ModeS && inst_info(1).fusel === FuType.csr io.executeStage.inst1.ex.exception(ecallU) := inst_info(1).inst(31, 20) === privEcall && - inst_info(1).op === CSROpType.jmp && priv_mode === ModeU + inst_info(1).op === CSROpType.jmp && priv_mode === ModeU && inst_info(1).fusel === FuType.csr io.executeStage.inst1.ex.tval := Mux( io.executeStage.inst1.ex.exception(instrAccessFault) || io.executeStage.inst1.ex.exception(instrAddrMisaligned), diff --git a/chisel/playground/src/pipeline/execute/Csr.scala b/chisel/playground/src/pipeline/execute/Csr.scala index e77b654..9320094 100644 --- a/chisel/playground/src/pipeline/execute/Csr.scala +++ b/chisel/playground/src/pipeline/execute/Csr.scala @@ -12,8 +12,9 @@ class CsrMemoryUnit(implicit val config: CpuConfig) extends Bundle { val inst = Vec( config.fuNum, new Bundle { - val pc = UInt(PC_WID.W) - val ex = new ExceptionInfo() + val pc = UInt(PC_WID.W) + val ex = new ExceptionInfo() + val inst_info = new InstInfo() } ) }) @@ -194,7 +195,7 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst { val interrupt_enable = Wire(UInt(INT_WID.W)) // 不用考虑ideleg interrupt_enable := Fill( INT_WID, - (((priv_mode === ModeM) && mstatus.asTypeOf(new Mstatus()).mie) || (priv_mode < ModeM)) + (((priv_mode === ModeM) && mstatus.asTypeOf(new Mstatus()).ie.m) || (priv_mode < ModeM)) ) io.decoderUnit.interrupt := mie(11, 0) & mip_has_interrupt.asUInt & interrupt_enable.asUInt @@ -202,17 +203,21 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst { val exc_sel = (io.memoryUnit.in.inst(0).ex.exception.asUInt.orR || io.memoryUnit.in.inst(0).ex.interrupt.asUInt.orR) || !(io.memoryUnit.in.inst(1).ex.exception.asUInt.orR || io.memoryUnit.in.inst(1).ex.interrupt.asUInt.orR) - val pc = Mux(exc_sel, io.memoryUnit.in.inst(0).pc, io.memoryUnit.in.inst(1).pc) - val exc = Mux(exc_sel, io.memoryUnit.in.inst(0).ex, io.memoryUnit.in.inst(1).ex) - val valid = io.executeUnit.in.valid - val op = io.executeUnit.in.inst_info.op - val fusel = io.executeUnit.in.inst_info.fusel - val addr = io.executeUnit.in.inst_info.inst(31, 20) - val rdata = Wire(UInt(XLEN.W)) - val src1 = io.executeUnit.in.src_info.src1_data - val csri = ZeroExtend(io.executeUnit.in.inst_info.inst(19, 15), XLEN) - val exe_stall = io.ctrl.exe_stall - val mem_stall = io.ctrl.mem_stall + val mem_pc = Mux(exc_sel, io.memoryUnit.in.inst(0).pc, io.memoryUnit.in.inst(1).pc) + val mem_ex = Mux(exc_sel, io.memoryUnit.in.inst(0).ex, io.memoryUnit.in.inst(1).ex) + val mem_inst_info = Mux(exc_sel, io.memoryUnit.in.inst(0).inst_info, io.memoryUnit.in.inst(1).inst_info) + val mem_inst = mem_inst_info.inst + val mem_valid = mem_inst_info.valid + val mem_addr = mem_inst(31, 20) + val valid = io.executeUnit.in.valid + val op = io.executeUnit.in.inst_info.op + val fusel = io.executeUnit.in.inst_info.fusel + val addr = io.executeUnit.in.inst_info.inst(31, 20) + val rdata = Wire(UInt(XLEN.W)) + val src1 = io.executeUnit.in.src_info.src1_data + val csri = ZeroExtend(io.executeUnit.in.inst_info.inst(19, 15), XLEN) + val exe_stall = io.ctrl.exe_stall + val mem_stall = io.ctrl.mem_stall val wdata = LookupTree( op, List( @@ -244,18 +249,60 @@ class Csr(implicit val config: CpuConfig) extends Module with HasCSRConst { // CSR inst decode val ret = Wire(Bool()) - val isMret = addr === privMret && op === CSROpType.jmp - val isSret = addr === privSret && op === CSROpType.jmp - val isUret = addr === privUret && op === CSROpType.jmp + val isMret = mem_addr === privMret && op === CSROpType.jmp && mem_inst_info.fusel === FuType.csr && mem_valid + val isSret = mem_addr === privSret && op === CSROpType.jmp && mem_inst_info.fusel === FuType.csr && mem_valid + val isUret = mem_addr === privUret && op === CSROpType.jmp && mem_inst_info.fusel === FuType.csr && mem_valid ret := isMret || isSret || isUret + val has_exception = mem_ex.exception.asUInt.orR + val has_interrupt = mem_ex.interrupt.asUInt.orR + val has_exc_int = has_exception || has_interrupt + val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(mem_ex.exception(i), i.U, sum)) + val interruptNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(mem_ex.interrupt(i), i.U, sum)) + val causeNO = (has_interrupt << (XLEN - 1)) | Mux(has_interrupt, interruptNO, exceptionNO) + + val tval_wen = has_interrupt || + !(mem_ex.exception(instrPageFault) || + mem_ex.exception(loadPageFault) || + mem_ex.exception(storePageFault) || + mem_ex.exception(loadAddrMisaligned) || + mem_ex.exception(storeAddrMisaligned)) + + when(has_exc_int) { + val mstatusOld = WireInit(mstatus.asTypeOf(new Mstatus)) + val mstatusNew = WireInit(mstatus.asTypeOf(new Mstatus)) + mcause := causeNO + mepc := SignedExtend(mem_pc, XLEN) + mstatusNew.mpp := priv_mode + mstatusNew.pie.m := mstatusOld.ie.m + mstatusNew.ie.m := false.B + priv_mode := ModeM + when(tval_wen) { mtval := 0.U } + mstatus := mstatusNew.asUInt + } + + val ret_target = Wire(UInt(VADDR_WID.W)) + ret_target := DontCare + val trap_target = Wire(UInt(VADDR_WID.W)) + trap_target := mtvec(VADDR_WID - 1, 0) + + when(isMret) { + val mstatusOld = WireInit(mstatus.asTypeOf(new Mstatus)) + val mstatusNew = WireInit(mstatus.asTypeOf(new Mstatus)) + // mstatusNew.mpp.m := ModeU //TODO: add mode U + mstatusNew.ie.m := mstatusOld.pie.m + priv_mode := mstatusOld.mpp + mstatusNew.pie.m := true.B + mstatusNew.mpp := ModeU + mstatus := mstatusNew.asUInt + // lr := false.B //TODO: add原子操作 + ret_target := mepc(VADDR_WID - 1, 0) + } + + io.decoderUnit.priv_mode := priv_mode io.executeUnit.out.ex := io.executeUnit.in.ex io.executeUnit.out.ex.exception(illegalInstr) := (illegal_addr || illegal_access) && wen io.executeUnit.out.rdata := rdata - - io.decoderUnit.priv_mode := priv_mode - - io.memoryUnit.out.flush := exc.exception.asUInt.orR || exc.interrupt.asUInt.orR - io.memoryUnit.out.flush_pc := mtvec - + io.memoryUnit.out.flush := has_exc_int || ret + io.memoryUnit.out.flush_pc := Mux(has_exc_int, trap_target, ret_target) } diff --git a/chisel/playground/src/pipeline/memory/MemoryUnit.scala b/chisel/playground/src/pipeline/memory/MemoryUnit.scala index f321927..a52c419 100644 --- a/chisel/playground/src/pipeline/memory/MemoryUnit.scala +++ b/chisel/playground/src/pipeline/memory/MemoryUnit.scala @@ -70,10 +70,12 @@ class MemoryUnit(implicit val config: CpuConfig) extends Module { io.writeBackStage.inst1.commit := io.memoryStage.inst1.inst_info.valid && !(io.writeBackStage.inst0.ex.exception.asUInt.orR || io.writeBackStage.inst0.ex.interrupt.asUInt.orR) - io.csr.in.inst(0).pc := io.writeBackStage.inst0.pc - io.csr.in.inst(0).ex := io.writeBackStage.inst0.ex - io.csr.in.inst(1).pc := io.writeBackStage.inst1.pc - io.csr.in.inst(1).ex := io.writeBackStage.inst1.ex + io.csr.in.inst(0).pc := io.writeBackStage.inst0.pc + io.csr.in.inst(0).ex := io.writeBackStage.inst0.ex + io.csr.in.inst(0).inst_info := io.writeBackStage.inst0.inst_info + io.csr.in.inst(1).pc := io.writeBackStage.inst1.pc + io.csr.in.inst(1).ex := io.writeBackStage.inst1.ex + io.csr.in.inst(1).inst_info := io.writeBackStage.inst1.inst_info io.fetchUnit.flush := io.csr.out.flush io.fetchUnit.flush_pc := Mux(io.csr.out.flush, io.csr.out.flush_pc, io.writeBackStage.inst0.pc + 4.U)