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