xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/TrapHandleModule.scala (revision 3174481be8623649d45fd8c63c59a7bfadd3bbc3)
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}