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