1package xiangshan.backend.fu.NewCSR 2 3import chisel3._ 4import chisel3.util._ 5import xiangshan.ExceptionNO 6import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, PrivState, XtvecBundle} 7import xiangshan.backend.fu.NewCSR.CSRDefines.XtvecMode 8import xiangshan.backend.fu.NewCSR.CSRBundleImplicitCast._ 9 10 11class TrapHandleModule extends Module { 12 val io = IO(new TrapHandleIO) 13 14 private val trapInfo = io.in.trapInfo 15 private val privState = io.in.privState 16 private val mstatus = io.in.mstatus 17 private val vsstatus = io.in.vsstatus 18 private val mnstatus = io.in.mnstatus 19 private val mideleg = io.in.mideleg.asUInt 20 private val hideleg = io.in.hideleg.asUInt 21 private val medeleg = io.in.medeleg.asUInt 22 private val hedeleg = io.in.hedeleg.asUInt 23 private val mvien = io.in.mvien.asUInt 24 private val hvien = io.in.hvien.asUInt 25 private val virtualInterruptIsHvictlInject = io.in.virtualInterruptIsHvictlInject 26 27 private val hasTrap = trapInfo.valid 28 private val hasNMI = hasTrap && trapInfo.bits.nmi 29 private val hasIR = hasTrap && trapInfo.bits.isInterrupt 30 private val hasEX = hasTrap && !trapInfo.bits.isInterrupt 31 32 private val exceptionVec = io.in.trapInfo.bits.trapVec 33 private val intrVec = io.in.trapInfo.bits.intrVec 34 private val hasEXVec = Mux(hasEX, exceptionVec, 0.U) 35 private val hasIRVec = Mux(hasIR, intrVec, 0.U) 36 37 private val irToHS = io.in.trapInfo.bits.irToHS 38 private val irToVS = io.in.trapInfo.bits.irToVS 39 40 private val highestPrioNMIVec = Wire(Vec(64, Bool())) 41 highestPrioNMIVec.zipWithIndex.foreach { case (irq, i) => 42 if (NonMaskableIRNO.interruptDefaultPrio.contains(i)) { 43 val higherIRSeq = NonMaskableIRNO.getIRQHigherThan(i) 44 irq := ( 45 higherIRSeq.nonEmpty.B && Cat(higherIRSeq.map(num => !hasIRVec(num))).andR || 46 higherIRSeq.isEmpty.B 47 ) && hasIRVec(i) 48 dontTouch(irq) 49 } else 50 irq := false.B 51 } 52 53 private val highestPrioEXVec = Wire(Vec(64, Bool())) 54 highestPrioEXVec.zipWithIndex.foreach { case (excp, i) => 55 if (ExceptionNO.priorities.contains(i)) { 56 val higherEXSeq = ExceptionNO.getHigherExcpThan(i) 57 excp := ( 58 higherEXSeq.nonEmpty.B && Cat(higherEXSeq.map(num => !hasEXVec(num))).andR || 59 higherEXSeq.isEmpty.B 60 ) && hasEXVec(i) 61 } else 62 excp := false.B 63 } 64 65 private val highestPrioIR = hasIRVec.asUInt 66 private val highestPrioNMI = highestPrioNMIVec.asUInt 67 private val highestPrioEX = highestPrioEXVec.asUInt 68 69 private val mEXVec = highestPrioEX 70 private val hsEXVec = highestPrioEX & medeleg 71 private val vsEXVec = highestPrioEX & medeleg & hedeleg 72 73 // nmi handle in MMode only and default handler is mtvec 74 private val mHasIR = hasIR 75 private val hsHasIR = hasIR && irToHS & !hasNMI 76 private val vsHasIR = hasIR && irToVS & !hasNMI 77 78 private val mHasEX = mEXVec.orR 79 private val hsHasEX = hsEXVec.orR 80 private val vsHasEX = vsEXVec.orR 81 82 private val mHasTrap = mHasEX || mHasIR 83 private val hsHasTrap = hsHasEX || hsHasIR 84 private val vsHasTrap = vsHasEX || vsHasIR 85 86 private val handleTrapUnderHS = !privState.isModeM && hsHasTrap 87 private val handleTrapUnderVS = privState.isVirtual && vsHasTrap 88 private val handleTrapUnderM = !handleTrapUnderVS && !handleTrapUnderHS 89 90 // Todo: support more interrupt and exception 91 private val exceptionRegular = OHToUInt(highestPrioEX) 92 private val interruptNO = OHToUInt(Mux(hasNMI, highestPrioNMI, highestPrioIR)) 93 private val exceptionNO = Mux(trapInfo.bits.singleStep, ExceptionNO.breakPoint.U, exceptionRegular) 94 95 private val causeNO = Mux(hasIR, interruptNO, exceptionNO) 96 97 // sm/ssdbltrp 98 private val m_EX_DT = handleTrapUnderM && mstatus.MDT.asBool && hasTrap 99 private val s_EX_DT = handleTrapUnderHS && mstatus.SDT.asBool && hasTrap 100 private val vs_EX_DT = handleTrapUnderVS && vsstatus.SDT.asBool && hasTrap 101 102 private val dbltrpToMN = m_EX_DT && mnstatus.NMIE.asBool // NMI not allow double trap 103 private val hasDTExcp = m_EX_DT || s_EX_DT || vs_EX_DT 104 105 private val trapToHS = handleTrapUnderHS && !s_EX_DT && !vs_EX_DT 106 private val traptoVS = handleTrapUnderVS && !vs_EX_DT 107 108 private val xtvec = MuxCase(io.in.mtvec, Seq( 109 traptoVS -> io.in.vstvec, 110 trapToHS -> io.in.stvec 111 )) 112 private val adjustinterruptNO = Mux( 113 InterruptNO.getVS.map(_.U === interruptNO).reduce(_ || _) && vsHasIR, 114 interruptNO - 1.U, // map VSSIP, VSTIP, VSEIP to SSIP, STIP, SEIP 115 interruptNO, 116 ) 117 private val pcFromXtvec = Cat(xtvec.addr.asUInt + Mux(xtvec.mode === XtvecMode.Vectored && hasIR, adjustinterruptNO(5, 0), 0.U), 0.U(2.W)) 118 119 io.out.entryPrivState := MuxCase(default = PrivState.ModeM, mapping = Seq( 120 traptoVS -> PrivState.ModeVS, 121 trapToHS -> PrivState.ModeHS, 122 )) 123 124 io.out.causeNO.Interrupt := hasIR 125 io.out.causeNO.ExceptionCode := causeNO 126 io.out.pcFromXtvec := pcFromXtvec 127 io.out.hasDTExcp := hasDTExcp 128 io.out.dbltrpToMN := dbltrpToMN 129 130} 131 132class TrapHandleIO extends Bundle { 133 val in = Input(new Bundle { 134 val trapInfo = ValidIO(new Bundle { 135 val trapVec = UInt(64.W) 136 val nmi = Bool() 137 val intrVec = UInt(64.W) 138 val isInterrupt = Bool() 139 val singleStep = Bool() 140 // trap to x mode 141 val irToHS = Bool() 142 val irToVS = Bool() 143 }) 144 val privState = new PrivState 145 val mstatus = new MstatusBundle 146 val vsstatus = new SstatusBundle 147 val mnstatus = new MnstatusBundle 148 val mideleg = new MidelegBundle 149 val medeleg = new MedelegBundle 150 val hideleg = new HidelegBundle 151 val hedeleg = new HedelegBundle 152 val mvien = new MvienBundle 153 val hvien = new HvienBundle 154 // trap vector 155 val mtvec = Input(new XtvecBundle) 156 val stvec = Input(new XtvecBundle) 157 val vstvec = Input(new XtvecBundle) 158 // virtual interrupt is hvictl inject 159 val virtualInterruptIsHvictlInject = Input(Bool()) 160 }) 161 162 val out = new Bundle { 163 val entryPrivState = new PrivState 164 val causeNO = new CauseBundle 165 val dbltrpToMN = Bool() 166 val hasDTExcp = Bool() 167 val pcFromXtvec = UInt() 168 } 169}