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 interruptGroups: Seq[(Seq[Int], String)] = Seq( 38 InterruptNO.customHighestGroup -> "customHighest", 39 InterruptNO.localHighGroup -> "localHigh", 40 InterruptNO.customMiddleHighGroup -> "customMiddleHigh", 41 InterruptNO.interruptDefaultPrio -> "privArch", 42 InterruptNO.customMiddleLowGroup -> "customMiddleLow", 43 InterruptNO.localLowGroup -> "localLow", 44 InterruptNO.customLowestGroup -> "customLowest", 45 ) 46 47 private val filteredIRQs: Seq[UInt] = interruptGroups.map { 48 case (irqGroup, name) => (getMaskFromIRQGroup(irqGroup) & hasIRVec).suggestName(s"filteredIRQs_$name") 49 } 50 private val hasIRQinGroup: Seq[Bool] = interruptGroups.map { 51 case (irqGroup, name) => dontTouch(Cat(filterIRQs(irqGroup, hasIRVec)).orR.suggestName(s"hasIRQinGroup_$name")) 52 } 53 54 private val highestIRQinGroup: Seq[Vec[Bool]] = interruptGroups zip filteredIRQs map { 55 case ((irqGroup: Seq[Int], name), filteredIRQ: UInt) => 56 produceHighIRInGroup(irqGroup, filteredIRQ).suggestName(s"highestIRQinGroup_$name") 57 } 58 59 private val highestPrioIRVec: Vec[Bool] = MuxCase( 60 0.U.asTypeOf(Vec(64, Bool())), 61 hasIRQinGroup zip highestIRQinGroup map{ case (hasIRQ: Bool, highestIRQ: Vec[Bool]) => hasIRQ -> highestIRQ } 62 ) 63 private val highestPrioNMIVec = Wire(Vec(64, Bool())) 64 highestPrioNMIVec.zipWithIndex.foreach { case (irq, i) => 65 if (NonMaskableIRNO.interruptDefaultPrio.contains(i)) { 66 val higherIRSeq = NonMaskableIRNO.getIRQHigherThan(i) 67 irq := ( 68 higherIRSeq.nonEmpty.B && Cat(higherIRSeq.map(num => !hasIRVec(num))).andR || 69 higherIRSeq.isEmpty.B 70 ) && hasIRVec(i) 71 dontTouch(irq) 72 } else 73 irq := false.B 74 } 75 76 private val highestPrioEXVec = Wire(Vec(64, Bool())) 77 highestPrioEXVec.zipWithIndex.foreach { case (excp, i) => 78 if (ExceptionNO.priorities.contains(i)) { 79 val higherEXSeq = ExceptionNO.getHigherExcpThan(i) 80 excp := ( 81 higherEXSeq.nonEmpty.B && Cat(higherEXSeq.map(num => !hasEXVec(num))).andR || 82 higherEXSeq.isEmpty.B 83 ) && hasEXVec(i) 84 } else 85 excp := false.B 86 } 87 88 private val highestPrioIR = highestPrioIRVec.asUInt 89 private val highestPrioNMI = highestPrioNMIVec.asUInt 90 private val highestPrioEX = highestPrioEXVec.asUInt 91 92 93 private val mIRVec = dontTouch(WireInit(highestPrioIR)) 94 private val hsIRVec = (mIRVec & mideleg) | (mIRVec & mvien & ~mideleg) 95 private val vsIRVec = (hsIRVec & hideleg) | (hsIRVec & hvien & ~hideleg) 96 97 private val mEXVec = highestPrioEX 98 private val hsEXVec = highestPrioEX & medeleg 99 private val vsEXVec = highestPrioEX & medeleg & hedeleg 100 101 // nmi handle in MMode only and default handler is mtvec 102 private val mHasIR = mIRVec.orR 103 private val hsHasIR = hsIRVec.orR & !hasNMI 104 private val vsHasIR = (vsIRVec.orR || hasIR && virtualInterruptIsHvictlInject) & !hasNMI 105 106 private val mHasEX = mEXVec.orR 107 private val hsHasEX = hsEXVec.orR 108 private val vsHasEX = vsEXVec.orR 109 110 private val mHasTrap = mHasEX || mHasIR 111 private val hsHasTrap = hsHasEX || hsHasIR 112 private val vsHasTrap = vsHasEX || vsHasIR 113 114 private val handleTrapUnderHS = !privState.isModeM && hsHasTrap 115 private val handleTrapUnderVS = privState.isVirtual && vsHasTrap 116 private val handleTrapUnderM = !handleTrapUnderVS && !handleTrapUnderHS 117 118 // Todo: support more interrupt and exception 119 private val exceptionRegular = OHToUInt(highestPrioEX) 120 private val interruptNO = OHToUInt(Mux(hasNMI, highestPrioNMI, highestPrioIR)) 121 private val exceptionNO = Mux(trapInfo.bits.singleStep, ExceptionNO.breakPoint.U, exceptionRegular) 122 123 private val causeNO = Mux(hasIR, interruptNO, exceptionNO) 124 125 // sm/ssdbltrp 126 private val m_EX_DT = handleTrapUnderM && mstatus.MDT.asBool && hasTrap 127 private val s_EX_DT = handleTrapUnderHS && mstatus.SDT.asBool && hasTrap 128 private val vs_EX_DT = handleTrapUnderVS && vsstatus.SDT.asBool && hasTrap 129 130 private val dbltrpToMN = m_EX_DT && mnstatus.NMIE.asBool // NMI not allow double trap 131 private val hasDTExcp = m_EX_DT || s_EX_DT || vs_EX_DT 132 133 private val trapToHS = handleTrapUnderHS && !s_EX_DT && !vs_EX_DT 134 private val traptoVS = handleTrapUnderVS && !vs_EX_DT 135 136 private val xtvec = MuxCase(io.in.mtvec, Seq( 137 traptoVS -> io.in.vstvec, 138 trapToHS -> io.in.stvec 139 )) 140 private val pcFromXtvec = Cat(xtvec.addr.asUInt + Mux(xtvec.mode === XtvecMode.Vectored && hasIR, interruptNO(5, 0), 0.U), 0.U(2.W)) 141 142 io.out.entryPrivState := MuxCase(default = PrivState.ModeM, mapping = Seq( 143 traptoVS -> PrivState.ModeVS, 144 trapToHS -> PrivState.ModeHS, 145 )) 146 147 io.out.causeNO.Interrupt := hasIR 148 io.out.causeNO.ExceptionCode := causeNO 149 io.out.pcFromXtvec := pcFromXtvec 150 io.out.hasDTExcp := hasDTExcp 151 io.out.dbltrpToMN := dbltrpToMN 152 153 def filterIRQs(group: Seq[Int], originIRQ: UInt): Seq[Bool] = { 154 group.map(irqNum => originIRQ(irqNum)) 155 } 156 157 def getIRQHigherThanInGroup(group: Seq[Int])(irq: Int): Seq[Int] = { 158 val idx = group.indexOf(irq, 0) 159 require(idx != -1, s"The irq($irq) does not exists in IntPriority Seq") 160 group.slice(0, idx) 161 } 162 163 def getMaskFromIRQGroup(group: Seq[Int]): UInt = { 164 group.map(irq => BigInt(1) << irq).reduce(_ | _).U 165 } 166 167 def produceHighIRInGroup(irqGroup: Seq[Int], filteredIRVec: UInt): Vec[Bool] = { 168 val irVec = Wire(Vec(64, Bool())) 169 irVec.zipWithIndex.foreach { case (irq, i) => 170 if (irqGroup.contains(i)) { 171 val higherIRSeq: Seq[Int] = getIRQHigherThanInGroup(irqGroup)(i) 172 irq := ( 173 higherIRSeq.nonEmpty.B && Cat(higherIRSeq.map(num => !filteredIRVec(num))).andR || 174 higherIRSeq.isEmpty.B 175 ) && filteredIRVec(i) 176 } else 177 irq := false.B 178 } 179 irVec 180 } 181} 182 183class TrapHandleIO extends Bundle { 184 val in = Input(new Bundle { 185 val trapInfo = ValidIO(new Bundle { 186 val trapVec = UInt(64.W) 187 val nmi = Bool() 188 val intrVec = UInt(64.W) 189 val isInterrupt = Bool() 190 val singleStep = Bool() 191 }) 192 val privState = new PrivState 193 val mstatus = new MstatusBundle 194 val vsstatus = new SstatusBundle 195 val mnstatus = new MnstatusBundle 196 val mideleg = new MidelegBundle 197 val medeleg = new MedelegBundle 198 val hideleg = new HidelegBundle 199 val hedeleg = new HedelegBundle 200 val mvien = new MvienBundle 201 val hvien = new HvienBundle 202 // trap vector 203 val mtvec = Input(new XtvecBundle) 204 val stvec = Input(new XtvecBundle) 205 val vstvec = Input(new XtvecBundle) 206 // virtual interrupt is hvictl inject 207 val virtualInterruptIsHvictlInject = Input(Bool()) 208 }) 209 210 val out = new Bundle { 211 val entryPrivState = new PrivState 212 val causeNO = new CauseBundle 213 val dbltrpToMN = Bool() 214 val hasDTExcp = Bool() 215 val pcFromXtvec = UInt() 216 } 217}