xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/TrapEntryMEvent.scala (revision c1b28b66879239a5b3a44741376f3b002e8ac834)
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 tcontrol  = ValidIO((new TcontrolBundle).addInEvent(_.MPTE, _.MTE))
23  val targetPc  = ValidIO(new TargetPCBundle)
24
25  def getBundleByName(name: String): Valid[CSRBundle] = {
26    name match {
27      case "mstatus"  => this.mstatus
28      case "mepc"     => this.mepc
29      case "mcause"   => this.mcause
30      case "mtval"    => this.mtval
31      case "mtval2"   => this.mtval2
32      case "mtinst"   => this.mtinst
33      case "tcontrol" => this.tcontrol
34    }
35  }
36}
37
38class TrapEntryMEventModule(implicit val p: Parameters) extends Module with CSREventBase {
39  val in = IO(new TrapEntryEventInput)
40  val out = IO(new TrapEntryMEventOutput)
41
42  private val current = in
43  private val iMode = current.iMode
44  private val dMode = current.dMode
45  private val satp  = current.satp
46  private val vsatp = current.vsatp
47  private val hgatp = current.hgatp
48
49  private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt
50  private val isException = !in.causeNO.Interrupt.asBool
51  private val isInterrupt = in.causeNO.Interrupt.asBool
52
53  private val trapPC = genTrapVA(
54    iMode,
55    satp,
56    vsatp,
57    hgatp,
58    in.trapPc,
59  )
60
61  private val trapPCGPA = SignExt(in.trapPcGPA, XLEN)
62
63  private val trapMemVA = genTrapVA(
64    dMode,
65    satp,
66    vsatp,
67    hgatp,
68    in.memExceptionVAddr,
69  )
70
71  private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN)
72
73  private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U)
74
75  private val fetchIsVirt = iMode.isVirtual
76  private val memIsVirt   = dMode.isVirtual
77
78  private val isFetchExcp    = isException && ExceptionNO.getFetchFault.map(_.U === highPrioTrapNO).reduce(_ || _)
79  private val isMemExcp      = isException && (ExceptionNO.getLoadFault ++ ExceptionNO.getStoreFault).map(_.U === highPrioTrapNO).reduce(_ || _)
80  private val isBpExcp       = isException && ExceptionNO.EX_BP.U === highPrioTrapNO
81  private val isHlsExcp      = isException && in.isHls
82  private val fetchCrossPage = in.isCrossPageIPF
83  private val isFetchMalAddr = in.isFetchMalAddr
84  private val isIllegalInst  = isException && (ExceptionNO.EX_II.U === highPrioTrapNO || ExceptionNO.EX_VI.U === highPrioTrapNO)
85
86  private val isLSGuestExcp    = isException && ExceptionNO.getLSGuestPageFault.map(_.U === highPrioTrapNO).reduce(_ || _)
87  private val isFetchGuestExcp = isException && ExceptionNO.EX_IGPF.U === highPrioTrapNO
88  // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval
89  // We fill pc here
90  private val tvalFillPc       = (isFetchExcp || isFetchGuestExcp) && !fetchCrossPage || isBpExcp
91  private val tvalFillPcPlus2  = (isFetchExcp || isFetchGuestExcp) && fetchCrossPage
92  private val tvalFillMemVaddr = isMemExcp
93  private val tvalFillGVA      =
94    isHlsExcp && isMemExcp ||
95    isLSGuestExcp|| isFetchGuestExcp ||
96    (isFetchExcp || isBpExcp) && fetchIsVirt ||
97    isMemExcp && memIsVirt
98  private val tvalFillInst     = isIllegalInst
99
100  private val tval = Mux1H(Seq(
101    (tvalFillPc                     ) -> trapPC,
102    (tvalFillPcPlus2                ) -> (trapPC + 2.U),
103    (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA,
104    (tvalFillMemVaddr &&  memIsVirt ) -> trapMemVA,
105    (isLSGuestExcp                  ) -> trapMemVA,
106    (tvalFillInst                   ) -> trapInst,
107  ))
108
109  private val tval2 = Mux1H(Seq(
110    (isFetchGuestExcp && isFetchMalAddr                    ) -> in.fetchMalTval,
111    (isFetchGuestExcp && !isFetchMalAddr && !fetchCrossPage) -> trapPCGPA,
112    (isFetchGuestExcp && !isFetchMalAddr && fetchCrossPage ) -> (trapPCGPA + 2.U),
113    (isLSGuestExcp                                         ) -> trapMemGPA,
114  ))
115
116  out := DontCare
117
118  out.privState.valid := valid
119  out.mstatus  .valid := valid
120  out.mepc     .valid := valid
121  out.mcause   .valid := valid
122  out.mtval    .valid := valid
123  out.mtval2   .valid := valid
124  out.mtinst   .valid := valid
125  out.tcontrol .valid := valid
126  out.targetPc .valid := valid
127
128  out.privState.bits            := PrivState.ModeM
129  out.mstatus.bits.MPV          := current.privState.V
130  out.mstatus.bits.MPP          := current.privState.PRVM
131  out.mstatus.bits.GVA          := tvalFillGVA
132  out.mstatus.bits.MPIE         := current.mstatus.MIE
133  out.mstatus.bits.MIE          := 0.U
134  out.mepc.bits.epc             := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1))
135  out.mcause.bits.Interrupt     := isInterrupt
136  out.mcause.bits.ExceptionCode := highPrioTrapNO
137  out.mtval.bits.ALL            := Mux(isFetchMalAddr, in.fetchMalTval, tval)
138  out.mtval2.bits.ALL           := tval2 >> 2
139  out.mtinst.bits.ALL           := 0.U
140  out.tcontrol.bits.MPTE        := in.tcontrol.MTE
141  out.tcontrol.bits.MTE         := 0.U
142  out.targetPc.bits.pc          := in.pcFromXtvec
143  out.targetPc.bits.raiseIPF    := false.B
144  out.targetPc.bits.raiseIAF    := AddrTransType(bare = true).checkAccessFault(in.pcFromXtvec)
145  out.targetPc.bits.raiseIGPF   := false.B
146
147  dontTouch(isLSGuestExcp)
148  dontTouch(tvalFillGVA)
149}
150
151trait TrapEntryMEventSinkBundle { self: CSRModule[_] =>
152  val trapToM = IO(Flipped(new TrapEntryMEventOutput))
153
154  private val updateBundle: ValidIO[CSRBundle] = trapToM.getBundleByName(self.modName.toLowerCase())
155
156  (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) =>
157    if (updateBundle.bits.eventFields.contains(source)) {
158      when(updateBundle.valid) {
159        sink := source
160      }
161    }
162  }
163}
164