1package xiangshan.backend.fu.NewCSR.CSREvents 2 3import chisel3._ 4import chisel3.util._ 5import org.chipsalliance.cde.config.Parameters 6import utility.{SignExt, ZeroExt} 7import xiangshan.ExceptionNO 8import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState} 9import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN} 10import xiangshan.backend.fu.NewCSR.CSRDefines.SatpMode 11import xiangshan.backend.fu.NewCSR._ 12import xiangshan.AddrTransType 13 14 15class TrapEntryHSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase { 16 17 // Todo: use sstatus instead of mstatus 18 val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE, _.SDT)) 19 val hstatus = ValidIO((new HstatusBundle ).addInEvent(_.SPV, _.SPVP, _.GVA)) 20 val sepc = ValidIO((new Epc ).addInEvent(_.epc)) 21 val scause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode)) 22 val stval = ValidIO((new OneFieldBundle).addInEvent(_.ALL)) 23 val htval = ValidIO((new OneFieldBundle).addInEvent(_.ALL)) 24 val htinst = ValidIO((new OneFieldBundle).addInEvent(_.ALL)) 25 val targetPc = ValidIO(new TargetPCBundle) 26} 27 28class TrapEntryHSEventModule(implicit val p: Parameters) extends Module with CSREventBase { 29 val in = IO(new TrapEntryEventInput) 30 val out = IO(new TrapEntryHSEventOutput) 31 32 private val current = in 33 private val iMode = current.iMode 34 private val dMode = current.dMode 35 private val satp = current.satp 36 private val vsatp = current.vsatp 37 private val hgatp = current.hgatp 38 39 private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt 40 private val isException = !in.causeNO.Interrupt.asBool 41 private val isInterrupt = in.causeNO.Interrupt.asBool 42 43 private val trapPC = genTrapVA( 44 iMode, 45 satp, 46 vsatp, 47 hgatp, 48 in.trapPc, 49 ) 50 51 private val trapPCGPA = in.trapPcGPA 52 53 private val trapMemVA = in.memExceptionVAddr 54 55 private val trapMemGPA = in.memExceptionGPAddr 56 57 private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U) 58 59 private val fetchIsVirt = current.iMode.isVirtual 60 private val memIsVirt = current.dMode.isVirtual 61 62 private val isFetchExcp = isException && ExceptionNO.getFetchFault.map(_.U === highPrioTrapNO).reduce(_ || _) 63 private val isMemExcp = isException && (ExceptionNO.getLoadFault ++ ExceptionNO.getStoreFault).map(_.U === highPrioTrapNO).reduce(_ || _) 64 private val isBpExcp = isException && ExceptionNO.EX_BP.U === highPrioTrapNO 65 private val isFetchBkpt = isBpExcp && in.isFetchBkpt 66 private val isMemBkpt = isBpExcp && !in.isFetchBkpt 67 private val isHlsExcp = isException && in.isHls 68 private val fetchCrossPage = in.isCrossPageIPF 69 private val isFetchMalAddr = in.isFetchMalAddr 70 private val isFetchMalAddrExcp = isException && isFetchMalAddr 71 private val isIllegalInst = isException && (ExceptionNO.EX_II.U === highPrioTrapNO || ExceptionNO.EX_VI.U === highPrioTrapNO) 72 73 private val isLSGuestExcp = isException && ExceptionNO.getLSGuestPageFault.map(_.U === highPrioTrapNO).reduce(_ || _) 74 private val isFetchGuestExcp = isException && ExceptionNO.EX_IGPF.U === highPrioTrapNO 75 // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval 76 // We fill pc here 77 private val tvalFillPc = (isFetchExcp || isFetchGuestExcp) && !fetchCrossPage || isFetchBkpt 78 private val tvalFillPcPlus2 = (isFetchExcp || isFetchGuestExcp) && fetchCrossPage 79 private val tvalFillMemVaddr = isMemExcp || isMemBkpt 80 private val tvalFillGVA = 81 isHlsExcp && isMemExcp || 82 isLSGuestExcp|| isFetchGuestExcp || 83 (isFetchExcp || isFetchBkpt) && fetchIsVirt || 84 (isMemExcp || isMemBkpt) && memIsVirt 85 private val tvalFillInst = isIllegalInst 86 87 private val tval = Mux1H(Seq( 88 (tvalFillPc ) -> trapPC, 89 (tvalFillPcPlus2 ) -> (trapPC + 2.U), 90 (tvalFillMemVaddr || isLSGuestExcp ) -> trapMemVA, 91 (tvalFillInst ) -> trapInst, 92 )) 93 94 private val tval2 = Mux1H(Seq( 95 (isFetchGuestExcp && isFetchMalAddr ) -> in.fetchMalTval, 96 (isFetchGuestExcp && !isFetchMalAddr && !fetchCrossPage) -> trapPCGPA, 97 (isFetchGuestExcp && !isFetchMalAddr && fetchCrossPage ) -> (trapPCGPA + 2.U), 98 (isLSGuestExcp ) -> trapMemGPA, 99 )) 100 101 private val instrAddrTransType = AddrTransType( 102 bare = satp.MODE === SatpMode.Bare, 103 sv39 = satp.MODE === SatpMode.Sv39, 104 sv48 = satp.MODE === SatpMode.Sv48, 105 sv39x4 = false.B, 106 sv48x4 = false.B 107 ) 108 109 out := DontCare 110 111 out.privState.valid := valid 112 out.mstatus .valid := valid 113 out.hstatus .valid := valid 114 out.sepc .valid := valid 115 out.scause .valid := valid 116 out.stval .valid := valid 117 out.htval .valid := valid 118 out.htinst .valid := valid 119 out.targetPc .valid := valid 120 121 out.privState.bits := PrivState.ModeHS 122 // mstatus 123 out.mstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width 124 out.mstatus.bits.SPIE := current.sstatus.SIE 125 out.mstatus.bits.SIE := 0.U 126 out.mstatus.bits.SDT := in.menvcfg.DTE.asBool // when DTE open set SDT to 1, else SDT is readonly 0 127 // hstatus 128 out.hstatus.bits.SPV := current.privState.V 129 // SPVP is not PrivMode enum type, so asUInt and shrink the width 130 out.hstatus.bits.SPVP := Mux(!current.privState.isVirtual, in.hstatus.SPVP.asUInt, current.privState.PRVM.asUInt(0, 0)) 131 out.hstatus.bits.GVA := tvalFillGVA 132 out.sepc.bits.epc := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1)) 133 out.scause.bits.Interrupt := isInterrupt 134 out.scause.bits.ExceptionCode := highPrioTrapNO 135 out.stval.bits.ALL := Mux(isFetchMalAddrExcp, in.fetchMalTval, tval) 136 out.htval.bits.ALL := tval2 >> 2 137 out.htinst.bits.ALL := Mux(isFetchGuestExcp && in.trapIsForVSnonLeafPTE || isLSGuestExcp && in.memExceptionIsForVSnonLeafPTE, 0x3000.U, 0.U) 138 out.targetPc.bits.pc := in.pcFromXtvec 139 out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(in.pcFromXtvec) 140 out.targetPc.bits.raiseIAF := instrAddrTransType.checkAccessFault(in.pcFromXtvec) 141 out.targetPc.bits.raiseIGPF := false.B 142 143 dontTouch(isLSGuestExcp) 144 dontTouch(tvalFillGVA) 145} 146 147trait TrapEntryHSEventSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] => 148 val trapToHS = IO(Flipped(new TrapEntryHSEventOutput)) 149 150 addUpdateBundleInCSREnumType(trapToHS.getBundleByName(self.modName.toLowerCase())) 151 152 reconnectReg() 153} 154