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)) 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 def getBundleByName(name: String): Valid[CSRBundle] = { 28 name match { 29 case "mstatus" => this.mstatus 30 case "hstatus" => this.hstatus 31 case "sepc" => this.sepc 32 case "scause" => this.scause 33 case "stval" => this.stval 34 case "htval" => this.htval 35 case "htinst" => this.htinst 36 } 37 } 38} 39 40class TrapEntryHSEventModule(implicit val p: Parameters) extends Module with CSREventBase { 41 val in = IO(new TrapEntryEventInput) 42 val out = IO(new TrapEntryHSEventOutput) 43 44 private val current = in 45 private val iMode = current.iMode 46 private val dMode = current.dMode 47 private val satp = current.satp 48 private val vsatp = current.vsatp 49 private val hgatp = current.hgatp 50 51 private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt 52 private val isException = !in.causeNO.Interrupt.asBool 53 private val isInterrupt = in.causeNO.Interrupt.asBool 54 55 private val trapPC = genTrapVA( 56 iMode, 57 satp, 58 vsatp, 59 hgatp, 60 in.trapPc, 61 ) 62 63 private val trapPCGPA = SignExt(in.trapPcGPA, XLEN) 64 65 private val trapMemVA = genTrapVA( 66 dMode, 67 satp, 68 vsatp, 69 hgatp, 70 in.memExceptionVAddr, 71 ) 72 73 private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN) 74 75 private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U) 76 77 private val fetchIsVirt = current.iMode.isVirtual 78 private val memIsVirt = current.dMode.isVirtual 79 80 private val isFetchExcp = isException && ExceptionNO.getFetchFault.map(_.U === highPrioTrapNO).reduce(_ || _) 81 private val isMemExcp = isException && (ExceptionNO.getLoadFault ++ ExceptionNO.getStoreFault).map(_.U === highPrioTrapNO).reduce(_ || _) 82 private val isBpExcp = isException && ExceptionNO.EX_BP.U === highPrioTrapNO 83 private val isHlsExcp = isException && in.isHls 84 private val fetchCrossPage = in.isCrossPageIPF 85 private val isFetchMalAddr = in.isFetchMalAddr 86 private val isIllegalInst = isException && (ExceptionNO.EX_II.U === highPrioTrapNO || ExceptionNO.EX_VI.U === highPrioTrapNO) 87 88 private val isLSGuestExcp = isException && ExceptionNO.getLSGuestPageFault.map(_.U === highPrioTrapNO).reduce(_ || _) 89 private val isFetchGuestExcp = isException && ExceptionNO.EX_IGPF.U === highPrioTrapNO 90 // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval 91 // We fill pc here 92 private val tvalFillPc = (isFetchExcp || isFetchGuestExcp) && !fetchCrossPage || isBpExcp 93 private val tvalFillPcPlus2 = (isFetchExcp || isFetchGuestExcp) && fetchCrossPage 94 private val tvalFillMemVaddr = isMemExcp 95 private val tvalFillGVA = 96 isHlsExcp && isMemExcp || 97 isLSGuestExcp|| isFetchGuestExcp || 98 (isFetchExcp || isBpExcp) && fetchIsVirt || 99 isMemExcp && memIsVirt 100 private val tvalFillInst = isIllegalInst 101 102 private val tval = Mux1H(Seq( 103 (tvalFillPc ) -> trapPC, 104 (tvalFillPcPlus2 ) -> (trapPC + 2.U), 105 (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA, 106 (tvalFillMemVaddr && memIsVirt ) -> trapMemVA, 107 (isLSGuestExcp ) -> trapMemVA, 108 (tvalFillInst ) -> trapInst, 109 )) 110 111 private val tval2 = Mux1H(Seq( 112 (isFetchGuestExcp && isFetchMalAddr ) -> in.fetchMalTval, 113 (isFetchGuestExcp && !isFetchMalAddr && !fetchCrossPage) -> trapPCGPA, 114 (isFetchGuestExcp && !isFetchMalAddr && fetchCrossPage ) -> (trapPCGPA + 2.U), 115 (isLSGuestExcp ) -> trapMemGPA, 116 )) 117 118 private val instrAddrTransType = AddrTransType( 119 bare = satp.MODE === SatpMode.Bare, 120 sv39 = satp.MODE === SatpMode.Sv39, 121 sv48 = satp.MODE === SatpMode.Sv48, 122 sv39x4 = false.B, 123 sv48x4 = false.B 124 ) 125 126 out := DontCare 127 128 out.privState.valid := valid 129 out.mstatus .valid := valid 130 out.hstatus .valid := valid 131 out.sepc .valid := valid 132 out.scause .valid := valid 133 out.stval .valid := valid 134 out.htval .valid := valid 135 out.htinst .valid := valid 136 out.targetPc .valid := valid 137 138 out.privState.bits := PrivState.ModeHS 139 // mstatus 140 out.mstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width 141 out.mstatus.bits.SPIE := current.sstatus.SIE 142 out.mstatus.bits.SIE := 0.U 143 // hstatus 144 out.hstatus.bits.SPV := current.privState.V 145 // SPVP is not PrivMode enum type, so asUInt and shrink the width 146 out.hstatus.bits.SPVP := Mux(!current.privState.isVirtual, in.hstatus.SPVP.asUInt, current.privState.PRVM.asUInt(0, 0)) 147 out.hstatus.bits.GVA := tvalFillGVA 148 out.sepc.bits.epc := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1)) 149 out.scause.bits.Interrupt := isInterrupt 150 out.scause.bits.ExceptionCode := highPrioTrapNO 151 out.stval.bits.ALL := Mux(isFetchMalAddr, in.fetchMalTval, tval) 152 out.htval.bits.ALL := tval2 >> 2 153 out.htinst.bits.ALL := 0.U 154 out.targetPc.bits.pc := in.pcFromXtvec 155 out.targetPc.bits.raiseIPF := instrAddrTransType.checkPageFault(in.pcFromXtvec) 156 out.targetPc.bits.raiseIAF := instrAddrTransType.checkAccessFault(in.pcFromXtvec) 157 out.targetPc.bits.raiseIGPF := false.B 158 159 dontTouch(isLSGuestExcp) 160 dontTouch(tvalFillGVA) 161} 162 163trait TrapEntryHSEventSinkBundle { self: CSRModule[_] => 164 val trapToHS = IO(Flipped(new TrapEntryHSEventOutput)) 165 166 private val updateBundle: ValidIO[CSRBundle] = trapToHS.getBundleByName(self.modName.toLowerCase()) 167 168 (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) => 169 if (updateBundle.bits.eventFields.contains(source)) { 170 when(updateBundle.valid) { 171 sink := source 172 } 173 } 174 } 175} 176