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