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