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, HasXSParameter} 8import xiangshan.ExceptionNO._ 9import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState} 10import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN} 11import xiangshan.backend.fu.NewCSR.CSRDefines.SatpMode 12import xiangshan.backend.fu.NewCSR._ 13import xiangshan.backend.fu.util.CSRConst 14 15 16class TrapEntryVSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase { 17 18 val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE)) 19 val vsepc = ValidIO((new Epc ).addInEvent(_.ALL)) 20 val vscause = ValidIO((new CauseBundle ).addInEvent(_.Interrupt, _.ExceptionCode)) 21 val vstval = ValidIO((new OneFieldBundle).addInEvent(_.ALL)) 22 val targetPc = ValidIO(UInt(VaddrMaxWidth.W)) 23 24 def getBundleByName(name: String): Valid[CSRBundle] = { 25 name match { 26 case "vsstatus" => this.vsstatus 27 case "vsepc" => this.vsepc 28 case "vscause" => this.vscause 29 case "vstval" => this.vstval 30 } 31 } 32} 33 34class TrapEntryVSEventModule(implicit val p: Parameters) extends Module with CSREventBase { 35 val in = IO(new TrapEntryEventInput) 36 val out = IO(new TrapEntryVSEventOutput) 37 38 when (valid) { 39 assert(in.privState.isVirtual, "The mode must be VU or VS when entry VS mode") 40 } 41 42 private val current = in 43 44 private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt 45 private val isException = !in.causeNO.Interrupt.asBool 46 private val isInterrupt = in.causeNO.Interrupt.asBool 47 48 private val trapPC = Wire(UInt(XLEN.W)) 49 private val trapMemVA = SignExt(in.memExceptionVAddr, XLEN) 50 private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN) 51 private val ivmVS = !current.iMode.isModeVS && current.vsatp.MODE =/= SatpMode.Bare 52 // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57 53 trapPC := Mux(ivmVS, SignExt(in.trapPc, XLEN), ZeroExt(in.trapPc, XLEN)) 54 55 private val fetchIsVirt = current.iMode.isVirtual 56 private val memIsVirt = current.dMode.isVirtual 57 58 when (valid && isInterrupt) { 59 import InterruptNO._ 60 assert(Seq(SEI, STI, SSI).map(_.U === highPrioTrapNO).reduce(_ || _), "The VS mode can only handle SEI, STI, SSI") 61 } 62 63 private val isFetchExcp = isException && Seq(/*EX_IAM, */ EX_IAF, EX_IPF).map(_.U === highPrioTrapNO).reduce(_ || _) 64 private val isMemExcp = isException && Seq(EX_LAM, EX_LAF, EX_SAM, EX_SAF, EX_LPF, EX_SPF).map(_.U === highPrioTrapNO).reduce(_ || _) 65 private val isBpExcp = isException && EX_BP.U === highPrioTrapNO 66 private val fetchCrossPage = in.isCrossPageIPF 67 68 // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval 69 // We fill pc here 70 private val tvalFillPc = isFetchExcp && !fetchCrossPage || isBpExcp 71 private val tvalFillPcPlus2 = isFetchExcp && fetchCrossPage 72 private val tvalFillMemVaddr = isMemExcp 73 private val tvalFillGVA = 74 (isFetchExcp || isBpExcp) && fetchIsVirt || 75 isMemExcp && memIsVirt 76 77 private val tval = Mux1H(Seq( 78 (tvalFillPc ) -> trapPC, 79 (tvalFillPcPlus2 ) -> (trapPC + 2.U), 80 (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA, 81 (tvalFillMemVaddr && memIsVirt ) -> trapMemVA, 82 )) 83 84 out := DontCare 85 86 out.privState.valid := valid 87 88 out.vsstatus .valid := valid 89 out.vsepc .valid := valid 90 out.vscause .valid := valid 91 out.vstval .valid := valid 92 out.targetPc .valid := valid 93 94 out.privState.bits := PrivState.ModeVS 95 // vsstatus 96 out.vsstatus.bits.SPP := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width 97 out.vsstatus.bits.SPIE := current.vsstatus.SIE 98 out.vsstatus.bits.SIE := 0.U 99 // SPVP is not PrivMode enum type, so asUInt and shrink the width 100 out.vsepc.bits.ALL := trapPC(trapPC.getWidth - 1, 1) 101 out.vscause.bits.Interrupt := isInterrupt 102 out.vscause.bits.ExceptionCode := highPrioTrapNO 103 out.vstval.bits.ALL := tval 104 out.targetPc.bits := in.pcFromXtvec 105 106 dontTouch(tvalFillGVA) 107} 108 109trait TrapEntryVSEventSinkBundle { self: CSRModule[_] => 110 val trapToVS = IO(Flipped(new TrapEntryVSEventOutput)) 111 112 private val updateBundle: ValidIO[CSRBundle] = trapToVS.getBundleByName(self.modName.toLowerCase()) 113 114 (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) => 115 if (updateBundle.bits.eventFields.contains(source)) { 116 when(updateBundle.valid) { 117 sink := source 118 } 119 } 120 } 121} 122