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