xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/TrapEntryMEvent.scala (revision 25dc4a827ee27e3ccbaf02e8e5134872cba28fcd)
1package xiangshan.backend.fu.NewCSR.CSREvents
2
3import chisel3._
4import chisel3.util._
5import org.chipsalliance.cde.config.Parameters
6import utility.{SignExt, ZeroExt}
7import xiangshan.{ExceptionNO, HasXSParameter}
8import xiangshan.ExceptionNO._
9import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState}
10import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN}
11import xiangshan.backend.fu.NewCSR.CSRDefines.SatpMode
12import xiangshan.backend.fu.NewCSR._
13
14
15class TrapEntryMEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase  {
16
17  val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.MPV, _.MPP, _.GVA, _.MPIE, _.MIE))
18  val mepc    = ValidIO((new Epc           ).addInEvent(_.ALL))
19  val mcause  = ValidIO((new CauseBundle   ).addInEvent(_.Interrupt, _.ExceptionCode))
20  val mtval   = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
21  val mtval2  = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
22  val mtinst  = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
23  val targetPc = ValidIO(UInt(VaddrMaxWidth.W))
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    }
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
43  private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt
44  private val isException = !in.causeNO.Interrupt.asBool
45  private val isInterrupt = in.causeNO.Interrupt.asBool
46
47  private val trapPC = Wire(UInt(XLEN.W))
48  private val trapMemVA = SignExt(in.memExceptionVAddr, XLEN)
49  private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN)
50  private val ivmHS = !current.iMode.isModeHS && current.satp.MODE =/= SatpMode.Bare
51  private val ivmVS = !current.iMode.isModeVS && current.vsatp.MODE =/= SatpMode.Bare
52  // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57
53  trapPC := Mux(ivmHS || ivmVS, SignExt(in.trapPc, XLEN), ZeroExt(in.trapPc, XLEN))
54
55  private val fetchIsVirt = current.iMode.isVirtual
56  private val memIsVirt   = current.dMode.isVirtual
57
58  private val isFetchExcp    = isException && Seq(/*EX_IAM, */ EX_IAF, EX_IPF).map(_.U === highPrioTrapNO).reduce(_ || _)
59  private val isMemExcp      = isException && Seq(EX_LAM, EX_LAF, EX_SAM, EX_SAF, EX_LPF, EX_SPF).map(_.U === highPrioTrapNO).reduce(_ || _)
60  private val isBpExcp       = isException && EX_BP.U === highPrioTrapNO
61  private val fetchCrossPage = in.isCrossPageIPF
62
63  private val isGuestExcp    = isException && Seq(EX_IGPF, EX_LGPF, EX_SGPF).map(_.U === highPrioTrapNO).reduce(_ || _)
64  // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval
65  // We fill pc here
66  private val tvalFillPc       = isFetchExcp && !fetchCrossPage || isBpExcp
67  private val tvalFillPcPlus2  = isFetchExcp && fetchCrossPage
68  private val tvalFillMemVaddr = isMemExcp
69  private val tvalFillGVA      = isGuestExcp ||
70    (isFetchExcp || isBpExcp) && fetchIsVirt ||
71    isMemExcp && memIsVirt
72
73  private val tval = Mux1H(Seq(
74    (tvalFillPc                     ) -> trapPC,
75    (tvalFillPcPlus2                ) -> (trapPC + 2.U),
76    (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA,
77    (tvalFillMemVaddr &&  memIsVirt ) -> trapMemVA,
78    (isGuestExcp                    ) -> trapMemVA,
79  ))
80
81  private val tval2 = Mux(isGuestExcp, trapMemGPA, 0.U)
82
83  out := DontCare
84
85  out.privState.valid := valid
86  out.mstatus  .valid := valid
87  out.mepc     .valid := valid
88  out.mcause   .valid := valid
89  out.mtval    .valid := valid
90  out.mtval2   .valid := valid
91  out.targetPc .valid := valid
92
93  out.privState.bits            := PrivState.ModeM
94  out.mstatus.bits.MPV          := current.privState.V
95  out.mstatus.bits.MPP          := current.privState.PRVM
96  out.mstatus.bits.GVA          := tvalFillGVA
97  out.mstatus.bits.MPIE         := current.mstatus.MIE
98  out.mstatus.bits.MIE          := 0.U
99  out.mepc.bits.ALL             := trapPC(trapPC.getWidth - 1, 1)
100  out.mcause.bits.Interrupt     := isInterrupt
101  out.mcause.bits.ExceptionCode := highPrioTrapNO
102  out.mtval.bits.ALL            := tval
103  out.mtval2.bits.ALL           := tval2
104  out.mtinst.bits.ALL           := 0.U
105  out.targetPc.bits             := in.pcFromXtvec
106
107  dontTouch(isGuestExcp)
108  dontTouch(tvalFillGVA)
109}
110
111trait TrapEntryMEventSinkBundle { self: CSRModule[_] =>
112  val trapToM = IO(Flipped(new TrapEntryMEventOutput))
113
114  private val updateBundle: ValidIO[CSRBundle] = trapToM.getBundleByName(self.modName.toLowerCase())
115
116  (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) =>
117    if (updateBundle.bits.eventFields.contains(source)) {
118      when(updateBundle.valid) {
119        sink := source
120      }
121    }
122  }
123}
124