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.{HgatpMode, SatpMode} 11import xiangshan.backend.fu.NewCSR._ 12import xiangshan.AddrTransType 13 14 15class TrapEntryVSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase { 16 17 val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE, _.SDT)) 18 val vsepc = ValidIO((new Epc ).addInEvent(_.epc)) 19 val vscause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode)) 20 val vstval = ValidIO((new OneFieldBundle).addInEvent(_.ALL)) 21 val targetPc = ValidIO(new TargetPCBundle) 22} 23 24class TrapEntryVSEventModule(implicit val p: Parameters) extends Module with CSREventBase { 25 val in = IO(new TrapEntryEventInput) 26 val out = IO(new TrapEntryVSEventOutput) 27 28 when (valid) { 29 assert(in.privState.isVirtual, "The mode must be VU or VS when entry VS mode") 30 } 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 trapCode = in.causeNO.ExceptionCode.asUInt 40 private val isException = !in.causeNO.Interrupt.asBool 41 private val isInterrupt = in.causeNO.Interrupt.asBool 42 private val virtualInterruptIsHvictlInject = in.virtualInterruptIsHvictlInject 43 private val hvictlIID = in.hvictlIID 44 45 when(valid && isInterrupt && !virtualInterruptIsHvictlInject) { 46 assert( 47 (InterruptNO.getVS ++ InterruptNO.getLocal).map(_.U === trapCode).reduce(_ || _), 48 "The VS mode can only handle VSEI, VSTI, VSSI and local interrupts" 49 ) 50 } 51 52 private val highPrioTrapNO = Mux( 53 InterruptNO.getVS.map(_.U === trapCode).reduce(_ || _) && isInterrupt, 54 trapCode - 1.U, // map VSSIP, VSTIP, VSEIP to SSIP, STIP, SEIP 55 trapCode, 56 ) 57 58 private val trapPC = genTrapVA( 59 iMode, 60 satp, 61 vsatp, 62 hgatp, 63 in.trapPc, 64 ) 65 66 private val trapMemVA = in.memExceptionVAddr 67 68 private val trapMemGPA = in.memExceptionGPAddr 69 70 private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U) 71 72 private val fetchIsVirt = current.iMode.isVirtual 73 private val memIsVirt = current.dMode.isVirtual 74 75 private val isFetchExcp = isException && Seq(/*EX_IAM, */ EX_IAF, EX_IPF).map(_.U === highPrioTrapNO).reduce(_ || _) 76 private val isMemExcp = isException && Seq(EX_LAM, EX_LAF, EX_SAM, EX_SAF, EX_LPF, EX_SPF).map(_.U === highPrioTrapNO).reduce(_ || _) 77 private val isBpExcp = isException && EX_BP.U === highPrioTrapNO 78 private val isFetchBkpt = isBpExcp && in.isFetchBkpt 79 private val isMemBkpt = isBpExcp && !in.isFetchBkpt 80 private val fetchCrossPage = in.isCrossPageIPF 81 private val isFetchMalAddr = in.isFetchMalAddr 82 private val isFetchMalAddrExcp = isException && isFetchMalAddr 83 private val isIllegalInst = isException && (EX_II.U === highPrioTrapNO || EX_VI.U === highPrioTrapNO) 84 85 // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval 86 // We fill pc here 87 private val tvalFillPc = isFetchExcp && !fetchCrossPage || isFetchBkpt 88 private val tvalFillPcPlus2 = isFetchExcp && fetchCrossPage 89 private val tvalFillMemVaddr = isMemExcp || isMemBkpt 90 private val tvalFillGVA = 91 (isFetchExcp || isFetchBkpt) && fetchIsVirt || 92 (isMemExcp || isMemBkpt) && memIsVirt 93 private val tvalFillInst = isIllegalInst 94 95 private val tval = Mux1H(Seq( 96 tvalFillPc -> trapPC, 97 tvalFillPcPlus2 -> (trapPC + 2.U), 98 tvalFillMemVaddr -> trapMemVA, 99 tvalFillInst -> trapInst, 100 )) 101 102 private val instrAddrTransType = AddrTransType( 103 bare = vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Bare, 104 sv39 = vsatp.MODE === SatpMode.Sv39, 105 sv48 = vsatp.MODE === SatpMode.Sv48, 106 sv39x4 = vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv39x4, 107 sv48x4 = vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4 108 ) 109 110 out := DontCare 111 112 out.privState.valid := valid 113 114 out.vsstatus .valid := valid 115 out.vsepc .valid := valid 116 out.vscause .valid := valid 117 out.vstval .valid := valid 118 out.targetPc .valid := valid 119 120 out.privState.bits := PrivState.ModeVS 121 // vsstatus 122 out.vsstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width 123 out.vsstatus.bits.SPIE := current.vsstatus.SIE 124 out.vsstatus.bits.SIE := 0.U 125 out.vsstatus.bits.SDT := in.henvcfg.DTE.asBool // when DTE open set SDT to 1, else SDT is readonly 0 126 // SPVP is not PrivMode enum type, so asUInt and shrink the width 127 out.vsepc.bits.epc := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1)) 128 out.vscause.bits.Interrupt := isInterrupt 129 out.vscause.bits.ExceptionCode := Mux(virtualInterruptIsHvictlInject, hvictlIID, highPrioTrapNO) 130 out.vstval.bits.ALL := Mux(isFetchMalAddrExcp, in.fetchMalTval, tval) 131 out.targetPc.bits.pc := in.pcFromXtvec 132 out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(in.pcFromXtvec) 133 out.targetPc.bits.raiseIAF := instrAddrTransType.checkAccessFault(in.pcFromXtvec) 134 out.targetPc.bits.raiseIGPF := instrAddrTransType.checkGuestPageFault(in.pcFromXtvec) 135 136 dontTouch(tvalFillGVA) 137} 138 139trait TrapEntryVSEventSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] => 140 val trapToVS = IO(Flipped(new TrapEntryVSEventOutput)) 141 142 addUpdateBundleInCSREnumType(trapToVS.getBundleByName(self.modName.toLowerCase())) 143 144 reconnectReg() 145} 146