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