xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/TrapHandleModule.scala (revision b03c55a5df5dc8793cb44b42dd60141566e57e78)
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 highestPrioIRVec = Wire(Vec(64, Bool()))
31  highestPrioIRVec.zipWithIndex.foreach { case (irq, i) =>
32    if (InterruptNO.interruptDefaultPrio.contains(i)) {
33      val higherIRSeq = InterruptNO.getIRQHigherThan(i)
34      irq := (
35        higherIRSeq.nonEmpty.B && Cat(higherIRSeq.map(num => !hasIRVec(num))).andR ||
36        higherIRSeq.isEmpty.B
37      ) && hasIRVec(i)
38      dontTouch(irq)
39    } else
40      irq := false.B
41  }
42
43  private val highestPrioEXVec = Wire(Vec(64, Bool()))
44  highestPrioEXVec.zipWithIndex.foreach { case (excp, i) =>
45    if (ExceptionNO.priorities.contains(i)) {
46      val higherEXSeq = ExceptionNO.getHigherExcpThan(i)
47      excp := (
48        higherEXSeq.nonEmpty.B && Cat(higherEXSeq.map(num => !hasEXVec(num))).andR ||
49        higherEXSeq.isEmpty.B
50      ) && hasEXVec(i)
51    } else
52      excp := false.B
53  }
54
55  private val highestPrioIR = highestPrioIRVec.asUInt
56  private val highestPrioEX = highestPrioEXVec.asUInt
57
58  private val mIRVec  = highestPrioIR
59  private val hsIRVec = highestPrioIR & mideleg
60  private val vsIRVec = highestPrioIR & mideleg & hideleg
61
62  private val mEXVec  = highestPrioEX
63  private val hsEXVec = highestPrioEX & medeleg
64  private val vsEXVec = highestPrioEX & medeleg & hedeleg
65
66  private val  mHasIR =  mIRVec.orR
67  private val hsHasIR = hsIRVec.orR
68  private val vsHasIR = vsIRVec.orR
69
70  private val  mHasEX =  mEXVec.orR
71  private val hsHasEX = hsEXVec.orR
72  private val vsHasEX = vsEXVec.orR
73
74  private val  mHasTrap =  mHasEX ||  mHasIR
75  private val hsHasTrap = hsHasEX || hsHasIR
76  private val vsHasTrap = vsHasEX || vsHasIR
77
78  private val handleTrapUnderHS = !privState.isModeM && hsHasTrap
79  private val handleTrapUnderVS = privState.isVirtual && vsHasTrap
80
81  // Todo: support more interrupt and exception
82  private val exceptionRegular = OHToUInt(highestPrioEX)
83  private val interruptNO = OHToUInt(highestPrioIR)
84  private val exceptionNO = Mux(trapInfo.bits.singleStep || trapInfo.bits.triggerFire, ExceptionNO.breakPoint.U, exceptionRegular)
85
86  private val causeNO = Mux(hasIR, interruptNO, exceptionNO)
87
88  private val xtvec = MuxCase(io.in.mtvec, Seq(
89    handleTrapUnderVS -> io.in.vstvec,
90    handleTrapUnderHS -> io.in.stvec
91  ))
92  private val pcFromXtvec = Cat(xtvec.addr.asUInt + Mux(xtvec.mode === XtvecMode.Vectored && hasIR, interruptNO(5, 0), 0.U), 0.U(2.W))
93
94  io.out.entryPrivState := MuxCase(default = PrivState.ModeM, mapping = Seq(
95    handleTrapUnderVS -> PrivState.ModeVS,
96    handleTrapUnderHS -> PrivState.ModeHS,
97  ))
98
99  io.out.causeNO.Interrupt := hasIR
100  io.out.causeNO.ExceptionCode := causeNO
101  io.out.pcFromXtvec := pcFromXtvec
102}
103
104class TrapHandleIO extends Bundle {
105  val in = Input(new Bundle {
106    val trapInfo = ValidIO(new Bundle {
107      val trapVec = UInt(64.W)
108      val intrVec = UInt(64.W)
109      val isInterrupt = Bool()
110      val singleStep = Bool()
111      val triggerFire = Bool()
112    })
113    val privState = new PrivState
114    val mideleg = new MidelegBundle
115    val medeleg = new MedelegBundle
116    val hideleg = new HidelegBundle
117    val hedeleg = new HedelegBundle
118    // trap vector
119    val mtvec = Input(new XtvecBundle)
120    val stvec = Input(new XtvecBundle)
121    val vstvec = Input(new XtvecBundle)
122  })
123
124  val out = new Bundle {
125    val entryPrivState = new PrivState
126    val causeNO = new CauseBundle
127    val pcFromXtvec = UInt()
128  }
129}