package xiangshan.backend.fu.NewCSR.CSREvents import chisel3._ import chisel3.util._ import org.chipsalliance.cde.config.Parameters import utility.{SignExt, ZeroExt} import xiangshan.ExceptionNO import xiangshan.ExceptionNO._ import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState} import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN} import xiangshan.backend.fu.NewCSR.CSRDefines.{HgatpMode, PrivMode, SatpMode, VirtMode} import xiangshan.backend.fu.NewCSR._ import xiangshan.AddrTransType class SretEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase { // Todo: write sstatus instead of mstatus val mstatus = ValidIO((new MstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP, _.MPRV, _.MDT, _.SDT)) val hstatus = ValidIO((new HstatusBundle).addInEvent(_.SPV)) val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP)) val targetPc = ValidIO(new TargetPCBundle) } class SretEventSDTOutput extends Bundle with EventOutputBase { val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SDT)) } class SretEventInput extends Bundle { val privState = Input(new PrivState) val mstatus = Input(new MstatusBundle) val hstatus = Input(new HstatusBundle) val vsstatus = Input(new SstatusBundle) val sepc = Input(new Epc()) val vsepc = Input(new Epc()) val satp = Input(new SatpBundle) val vsatp = Input(new SatpBundle) val hgatp = Input(new HgatpBundle) } class SretEventModule(implicit p: Parameters) extends Module with CSREventBase { val in = IO(new SretEventInput) val out = IO(new SretEventOutput) val outSDT = IO(new SretEventSDTOutput) private val satp = in.satp private val vsatp = in.vsatp private val hgatp = in.hgatp private val nextPrivState = out.privState.bits private val instrAddrTransType = AddrTransType( bare = (!nextPrivState.isVirtual && satp.MODE === SatpMode.Bare) || (nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Bare), sv39 = !nextPrivState.isVirtual && satp.MODE === SatpMode.Sv39 || nextPrivState.isVirtual && vsatp.MODE === SatpMode.Sv39, sv48 = !nextPrivState.isVirtual && satp.MODE === SatpMode.Sv48 || nextPrivState.isVirtual && vsatp.MODE === SatpMode.Sv48, sv39x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv39x4, sv48x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4 ) private val sretInM = in.privState.isModeM private val sretInHS = in.privState.isModeHS private val sretInHSorM = sretInM || sretInHS private val sretInVS = in.privState.isModeVS private val xepc = Mux1H(Seq( sretInHSorM -> in.sepc, sretInVS -> in.vsepc, )).asUInt private val outPrivState = Wire(new PrivState) outPrivState.PRVM := Mux1H(Seq( // SPP is not PrivMode enum type, so asUInt sretInHSorM -> in.mstatus.SPP.asUInt, sretInVS -> in.vsstatus.SPP.asUInt, )) outPrivState.V := Mux1H(Seq( sretInHSorM -> in.hstatus.SPV, sretInVS -> in.privState.V, // keep )) private val sretToVU = outPrivState.isModeVU private val sretToVS = outPrivState.isModeVS private val sretToU = outPrivState.isModeHU out := DontCare outSDT := DontCare out.privState.valid := valid out.targetPc .valid := valid out.privState.bits := outPrivState // hstatus out.hstatus.valid := valid && sretInHSorM out.hstatus.bits.SPV := VirtMode.Off // sstatus out.mstatus.valid := valid && sretInHSorM out.mstatus.bits.SPP := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width out.mstatus.bits.SIE := in.mstatus.SPIE out.mstatus.bits.SPIE := 1.U out.mstatus.bits.MPRV := 0.U // sret will always leave M mode out.mstatus.bits.MDT := Mux(sretInM, 0.U, in.mstatus.MDT.asBool) // when execute return in M mode, set MDT 0 out.mstatus.bits.SDT := MuxCase(in.mstatus.SDT.asBool, Seq( sretInHS -> 0.U, // sret will alway leave M mode (sretInM && (sretToU || sretToVS || sretToVU)) -> 0.U )) // vsstatus out.vsstatus.valid := valid && sretInVS out.vsstatus.bits.SPP := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width out.vsstatus.bits.SIE := in.vsstatus.SPIE out.vsstatus.bits.SPIE := 1.U outSDT.vsstatus.valid := valid && (sretToVU || sretInVS) // clear SDT when return to VU or sret in vs outSDT.vsstatus.bits.SDT := 0.U out.targetPc.bits.pc := xepc out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(xepc) out.targetPc.bits.raiseIAF := instrAddrTransType.checkAccessFault(xepc) out.targetPc.bits.raiseIGPF := instrAddrTransType.checkGuestPageFault(xepc) // for better verilog dontTouch(sretInHSorM) dontTouch(sretInVS) } trait SretEventSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] => val retFromS = IO(Flipped(new SretEventOutput)) addUpdateBundleInCSREnumType(retFromS.getBundleByName(self.modName.toLowerCase())) reconnectReg() } trait SretEventSDTSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] => val retFromSSDT = IO(Flipped(new SretEventSDTOutput)) addUpdateBundleInCSREnumType(retFromSSDT.getBundleByName(self.modName.toLowerCase())) reconnectReg() }