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 TrapEntryVSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase { 15 16 val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE)) 17 val vsepc = ValidIO((new Epc ).addInEvent(_.epc)) 18 val vscause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode)) 19 val vstval = ValidIO((new OneFieldBundle).addInEvent(_.ALL)) 20 val targetPc = ValidIO(UInt(VaddrMaxWidth.W)) 21 22 def getBundleByName(name: String): Valid[CSRBundle] = { 23 name match { 24 case "vsstatus" => this.vsstatus 25 case "vsepc" => this.vsepc 26 case "vscause" => this.vscause 27 case "vstval" => this.vstval 28 } 29 } 30} 31 32class TrapEntryVSEventModule(implicit val p: Parameters) extends Module with CSREventBase { 33 val in = IO(new TrapEntryEventInput) 34 val out = IO(new TrapEntryVSEventOutput) 35 36 when (valid) { 37 assert(in.privState.isVirtual, "The mode must be VU or VS when entry VS mode") 38 } 39 40 private val current = in 41 private val iMode = current.iMode 42 private val dMode = current.dMode 43 private val satp = current.satp 44 private val vsatp = current.vsatp 45 private val hgatp = current.hgatp 46 47 private val trapCode = in.causeNO.ExceptionCode.asUInt 48 private val isException = !in.causeNO.Interrupt.asBool 49 private val isInterrupt = in.causeNO.Interrupt.asBool 50 private val virtualInterruptIsHvictlInject = in.virtualInterruptIsHvictlInject 51 private val hvictlIID = in.hvictlIID 52 53 when(valid && isInterrupt && !virtualInterruptIsHvictlInject) { 54 assert( 55 (InterruptNO.getVS ++ InterruptNO.getLocal).map(_.U === trapCode).reduce(_ || _), 56 "The VS mode can only handle VSEI, VSTI, VSSI and local interrupts" 57 ) 58 } 59 60 private val highPrioTrapNO = Mux( 61 InterruptNO.getVS.map(_.U === trapCode).reduce(_ || _) && isInterrupt, 62 trapCode - 1.U, // map VSSIP, VSTIP, VSEIP to SSIP, STIP, SEIP 63 trapCode, 64 ) 65 66 private val trapPC = genTrapVA( 67 iMode, 68 satp, 69 vsatp, 70 hgatp, 71 in.trapPc, 72 ) 73 74 private val trapMemVA = genTrapVA( 75 dMode, 76 satp, 77 vsatp, 78 hgatp, 79 in.memExceptionVAddr, 80 ) 81 private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN) 82 83 private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U) 84 85 private val fetchIsVirt = current.iMode.isVirtual 86 private val memIsVirt = current.dMode.isVirtual 87 88 private val isFetchExcp = isException && Seq(/*EX_IAM, */ EX_IAF, EX_IPF).map(_.U === highPrioTrapNO).reduce(_ || _) 89 private val isMemExcp = isException && Seq(EX_LAM, EX_LAF, EX_SAM, EX_SAF, EX_LPF, EX_SPF).map(_.U === highPrioTrapNO).reduce(_ || _) 90 private val isBpExcp = isException && EX_BP.U === highPrioTrapNO 91 private val fetchCrossPage = in.isCrossPageIPF 92 private val isIllegalInst = isException && (EX_II.U === highPrioTrapNO || EX_VI.U === highPrioTrapNO) 93 94 // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval 95 // We fill pc here 96 private val tvalFillPc = isFetchExcp && !fetchCrossPage || isBpExcp 97 private val tvalFillPcPlus2 = isFetchExcp && fetchCrossPage 98 private val tvalFillMemVaddr = isMemExcp 99 private val tvalFillGVA = 100 (isFetchExcp || isBpExcp) && fetchIsVirt || 101 isMemExcp && memIsVirt 102 private val tvalFillInst = isIllegalInst 103 104 private val tval = Mux1H(Seq( 105 (tvalFillPc ) -> trapPC, 106 (tvalFillPcPlus2 ) -> (trapPC + 2.U), 107 (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA, 108 (tvalFillMemVaddr && memIsVirt ) -> trapMemVA, 109 (tvalFillInst ) -> trapInst, 110 )) 111 112 out := DontCare 113 114 out.privState.valid := valid 115 116 out.vsstatus .valid := valid 117 out.vsepc .valid := valid 118 out.vscause .valid := valid 119 out.vstval .valid := valid 120 out.targetPc .valid := valid 121 122 out.privState.bits := PrivState.ModeVS 123 // vsstatus 124 out.vsstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width 125 out.vsstatus.bits.SPIE := current.vsstatus.SIE 126 out.vsstatus.bits.SIE := 0.U 127 // SPVP is not PrivMode enum type, so asUInt and shrink the width 128 out.vsepc.bits.epc := trapPC(63, 1) 129 out.vscause.bits.Interrupt := isInterrupt 130 out.vscause.bits.ExceptionCode := Mux(virtualInterruptIsHvictlInject, hvictlIID, highPrioTrapNO) 131 out.vstval.bits.ALL := tval 132 out.targetPc.bits := in.pcFromXtvec 133 134 dontTouch(tvalFillGVA) 135} 136 137trait TrapEntryVSEventSinkBundle { self: CSRModule[_] => 138 val trapToVS = IO(Flipped(new TrapEntryVSEventOutput)) 139 140 private val updateBundle: ValidIO[CSRBundle] = trapToVS.getBundleByName(self.modName.toLowerCase()) 141 142 (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) => 143 if (updateBundle.bits.eventFields.contains(source)) { 144 when(updateBundle.valid) { 145 sink := source 146 } 147 } 148 } 149} 150