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