xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/TrapEntryMEvent.scala (revision a38d1eab87777ed93b417106a7dfd58a062cee18)
1package xiangshan.backend.fu.NewCSR.CSREvents
2
3import chisel3._
4import chisel3.util._
5import org.chipsalliance.cde.config.Parameters
6import utility.SignExt
7import xiangshan.ExceptionNO
8import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState}
9import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN}
10import xiangshan.backend.fu.NewCSR._
11import xiangshan.AddrTransType
12
13
14class TrapEntryMEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase  {
15
16  val mstatus   = ValidIO((new MstatusBundle ).addInEvent(_.MPV, _.MPP, _.GVA, _.MPIE, _.MIE))
17  val mepc      = ValidIO((new Epc           ).addInEvent(_.epc))
18  val mcause    = ValidIO((new CauseBundle   ).addInEvent(_.Interrupt, _.ExceptionCode))
19  val mtval     = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
20  val mtval2    = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
21  val mtinst    = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
22  val targetPc  = ValidIO(new TargetPCBundle)
23}
24
25class TrapEntryMEventModule(implicit val p: Parameters) extends Module with CSREventBase {
26  val in = IO(new TrapEntryEventInput)
27  val out = IO(new TrapEntryMEventOutput)
28
29  private val current = in
30  private val iMode = current.iMode
31  private val dMode = current.dMode
32  private val satp  = current.satp
33  private val vsatp = current.vsatp
34  private val hgatp = current.hgatp
35
36  private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt
37  private val isException = !in.causeNO.Interrupt.asBool
38  private val isInterrupt = in.causeNO.Interrupt.asBool
39
40  private val trapPC = genTrapVA(
41    iMode,
42    satp,
43    vsatp,
44    hgatp,
45    in.trapPc,
46  )
47
48  private val trapPCGPA = SignExt(in.trapPcGPA, XLEN)
49
50  private val trapMemVA = in.memExceptionVAddr
51
52  private val trapMemGPA = in.memExceptionGPAddr
53
54  private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U)
55
56  private val fetchIsVirt = iMode.isVirtual
57  private val memIsVirt   = dMode.isVirtual
58
59  private val isFetchExcp    = isException && ExceptionNO.getFetchFault.map(_.U === highPrioTrapNO).reduce(_ || _)
60  private val isMemExcp      = isException && (ExceptionNO.getLoadFault ++ ExceptionNO.getStoreFault).map(_.U === highPrioTrapNO).reduce(_ || _)
61  private val isBpExcp       = isException && ExceptionNO.EX_BP.U === highPrioTrapNO
62  private val isFetchBkpt = isBpExcp && in.isFetchBkpt
63  private val isMemBkpt = isBpExcp && !in.isFetchBkpt
64  private val isHlsExcp      = isException && in.isHls
65  private val fetchCrossPage = in.isCrossPageIPF
66  private val isFetchMalAddr = in.isFetchMalAddr
67  private val isIllegalInst  = isException && (ExceptionNO.EX_II.U === highPrioTrapNO || ExceptionNO.EX_VI.U === highPrioTrapNO)
68
69  private val isLSGuestExcp    = isException && ExceptionNO.getLSGuestPageFault.map(_.U === highPrioTrapNO).reduce(_ || _)
70  private val isFetchGuestExcp = isException && ExceptionNO.EX_IGPF.U === highPrioTrapNO
71  // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval
72  // We fill pc here
73  private val tvalFillPc       = (isFetchExcp || isFetchGuestExcp) && !fetchCrossPage || isFetchBkpt
74  private val tvalFillPcPlus2  = (isFetchExcp || isFetchGuestExcp) && fetchCrossPage
75  private val tvalFillMemVaddr = isMemExcp || isMemBkpt
76  private val tvalFillGVA      =
77    isHlsExcp && isMemExcp ||
78    isLSGuestExcp|| isFetchGuestExcp ||
79    (isFetchExcp || isFetchBkpt) && fetchIsVirt ||
80    (isMemExcp || isMemBkpt) && memIsVirt
81  private val tvalFillInst     = isIllegalInst
82
83  private val tval = Mux1H(Seq(
84    (tvalFillPc                     ) -> trapPC,
85    (tvalFillPcPlus2                ) -> (trapPC + 2.U),
86    (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA,
87    (tvalFillMemVaddr &&  memIsVirt ) -> trapMemVA,
88    (isLSGuestExcp                  ) -> trapMemVA,
89    (tvalFillInst                   ) -> trapInst,
90  ))
91
92  private val tval2 = Mux1H(Seq(
93    (isFetchGuestExcp && isFetchMalAddr                    ) -> in.fetchMalTval,
94    (isFetchGuestExcp && !isFetchMalAddr && !fetchCrossPage) -> trapPCGPA,
95    (isFetchGuestExcp && !isFetchMalAddr && fetchCrossPage ) -> (trapPCGPA + 2.U),
96    (isLSGuestExcp                                         ) -> trapMemGPA,
97  ))
98
99  out := DontCare
100
101  out.privState.valid := valid
102  out.mstatus  .valid := valid
103  out.mepc     .valid := valid
104  out.mcause   .valid := valid
105  out.mtval    .valid := valid
106  out.mtval2   .valid := valid
107  out.mtinst   .valid := valid
108  out.targetPc .valid := valid
109
110  out.privState.bits            := PrivState.ModeM
111  out.mstatus.bits.MPV          := current.privState.V
112  out.mstatus.bits.MPP          := current.privState.PRVM
113  out.mstatus.bits.GVA          := tvalFillGVA
114  out.mstatus.bits.MPIE         := current.mstatus.MIE
115  out.mstatus.bits.MIE          := 0.U
116  out.mepc.bits.epc             := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1))
117  out.mcause.bits.Interrupt     := isInterrupt
118  out.mcause.bits.ExceptionCode := highPrioTrapNO
119  out.mtval.bits.ALL            := Mux(isFetchMalAddr, in.fetchMalTval, tval)
120  out.mtval2.bits.ALL           := tval2 >> 2
121  out.mtinst.bits.ALL           := Mux(isFetchGuestExcp && in.trapIsForVSnonLeafPTE || isLSGuestExcp && in.memExceptionIsForVSnonLeafPTE, 0x3000.U, 0.U)
122  out.targetPc.bits.pc          := in.pcFromXtvec
123  out.targetPc.bits.raiseIPF    := false.B
124  out.targetPc.bits.raiseIAF    := AddrTransType(bare = true).checkAccessFault(in.pcFromXtvec)
125  out.targetPc.bits.raiseIGPF   := false.B
126
127  dontTouch(isLSGuestExcp)
128  dontTouch(tvalFillGVA)
129}
130
131trait TrapEntryMEventSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] =>
132  val trapToM = IO(Flipped(new TrapEntryMEventOutput))
133
134  addUpdateBundleInCSREnumType(trapToM.getBundleByName(self.modName.toLowerCase()))
135
136  reconnectReg()
137}
138