xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/TrapEntryHSEvent.scala (revision c1b28b66879239a5b3a44741376f3b002e8ac834)
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
8import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState}
9import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN}
10import xiangshan.backend.fu.NewCSR.CSRDefines.SatpMode
11import xiangshan.backend.fu.NewCSR._
12import xiangshan.AddrTransType
13
14
15class TrapEntryHSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase  {
16
17  // Todo: use sstatus instead of mstatus
18  val mstatus = ValidIO((new MstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE))
19  val hstatus = ValidIO((new HstatusBundle ).addInEvent(_.SPV, _.SPVP, _.GVA))
20  val sepc    = ValidIO((new Epc           ).addInEvent(_.epc))
21  val scause  = ValidIO((new CauseBundle   ).addInEvent(_.Interrupt, _.ExceptionCode))
22  val stval   = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
23  val htval   = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
24  val htinst  = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
25  val targetPc  = ValidIO(new TargetPCBundle)
26
27  def getBundleByName(name: String): Valid[CSRBundle] = {
28    name match {
29      case "mstatus" => this.mstatus
30      case "hstatus" => this.hstatus
31      case "sepc"    => this.sepc
32      case "scause"  => this.scause
33      case "stval"   => this.stval
34      case "htval"   => this.htval
35      case "htinst"  => this.htinst
36    }
37  }
38}
39
40class TrapEntryHSEventModule(implicit val p: Parameters) extends Module with CSREventBase {
41  val in = IO(new TrapEntryEventInput)
42  val out = IO(new TrapEntryHSEventOutput)
43
44  private val current = in
45  private val iMode = current.iMode
46  private val dMode = current.dMode
47  private val satp = current.satp
48  private val vsatp = current.vsatp
49  private val hgatp = current.hgatp
50
51  private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt
52  private val isException = !in.causeNO.Interrupt.asBool
53  private val isInterrupt = in.causeNO.Interrupt.asBool
54
55  private val trapPC = genTrapVA(
56    iMode,
57    satp,
58    vsatp,
59    hgatp,
60    in.trapPc,
61  )
62
63  private val trapPCGPA = SignExt(in.trapPcGPA, XLEN)
64
65  private val trapMemVA = genTrapVA(
66    dMode,
67    satp,
68    vsatp,
69    hgatp,
70    in.memExceptionVAddr,
71  )
72
73  private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN)
74
75  private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U)
76
77  private val fetchIsVirt = current.iMode.isVirtual
78  private val memIsVirt   = current.dMode.isVirtual
79
80  private val isFetchExcp    = isException && ExceptionNO.getFetchFault.map(_.U === highPrioTrapNO).reduce(_ || _)
81  private val isMemExcp      = isException && (ExceptionNO.getLoadFault ++ ExceptionNO.getStoreFault).map(_.U === highPrioTrapNO).reduce(_ || _)
82  private val isBpExcp       = isException && ExceptionNO.EX_BP.U === highPrioTrapNO
83  private val isHlsExcp      = isException && in.isHls
84  private val fetchCrossPage = in.isCrossPageIPF
85  private val isFetchMalAddr = in.isFetchMalAddr
86  private val isIllegalInst  = isException && (ExceptionNO.EX_II.U === highPrioTrapNO || ExceptionNO.EX_VI.U === highPrioTrapNO)
87
88  private val isLSGuestExcp    = isException && ExceptionNO.getLSGuestPageFault.map(_.U === highPrioTrapNO).reduce(_ || _)
89  private val isFetchGuestExcp = isException && ExceptionNO.EX_IGPF.U === highPrioTrapNO
90  // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval
91  // We fill pc here
92  private val tvalFillPc       = (isFetchExcp || isFetchGuestExcp) && !fetchCrossPage || isBpExcp
93  private val tvalFillPcPlus2  = (isFetchExcp || isFetchGuestExcp) && fetchCrossPage
94  private val tvalFillMemVaddr = isMemExcp
95  private val tvalFillGVA      =
96    isHlsExcp && isMemExcp ||
97    isLSGuestExcp|| isFetchGuestExcp ||
98    (isFetchExcp || isBpExcp) && fetchIsVirt ||
99    isMemExcp && memIsVirt
100  private val tvalFillInst     = isIllegalInst
101
102  private val tval = Mux1H(Seq(
103    (tvalFillPc                     ) -> trapPC,
104    (tvalFillPcPlus2                ) -> (trapPC + 2.U),
105    (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA,
106    (tvalFillMemVaddr &&  memIsVirt ) -> trapMemVA,
107    (isLSGuestExcp                  ) -> trapMemVA,
108    (tvalFillInst                   ) -> trapInst,
109  ))
110
111  private val tval2 = Mux1H(Seq(
112    (isFetchGuestExcp && isFetchMalAddr                    ) -> in.fetchMalTval,
113    (isFetchGuestExcp && !isFetchMalAddr && !fetchCrossPage) -> trapPCGPA,
114    (isFetchGuestExcp && !isFetchMalAddr && fetchCrossPage ) -> (trapPCGPA + 2.U),
115    (isLSGuestExcp                                         ) -> trapMemGPA,
116  ))
117
118  private val instrAddrTransType = AddrTransType(
119    bare = satp.MODE === SatpMode.Bare,
120    sv39 = satp.MODE === SatpMode.Sv39,
121    sv48 = satp.MODE === SatpMode.Sv48,
122    sv39x4 = false.B,
123    sv48x4 = false.B
124  )
125
126  out := DontCare
127
128  out.privState.valid := valid
129  out.mstatus  .valid := valid
130  out.hstatus  .valid := valid
131  out.sepc     .valid := valid
132  out.scause   .valid := valid
133  out.stval    .valid := valid
134  out.htval    .valid := valid
135  out.htinst   .valid := valid
136  out.targetPc .valid := valid
137
138  out.privState.bits            := PrivState.ModeHS
139  // mstatus
140  out.mstatus.bits.SPP          := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
141  out.mstatus.bits.SPIE         := current.sstatus.SIE
142  out.mstatus.bits.SIE          := 0.U
143  // hstatus
144  out.hstatus.bits.SPV          := current.privState.V
145    // SPVP is not PrivMode enum type, so asUInt and shrink the width
146  out.hstatus.bits.SPVP         := Mux(!current.privState.isVirtual, in.hstatus.SPVP.asUInt, current.privState.PRVM.asUInt(0, 0))
147  out.hstatus.bits.GVA          := tvalFillGVA
148  out.sepc.bits.epc             := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1))
149  out.scause.bits.Interrupt     := isInterrupt
150  out.scause.bits.ExceptionCode := highPrioTrapNO
151  out.stval.bits.ALL            := Mux(isFetchMalAddr, in.fetchMalTval, tval)
152  out.htval.bits.ALL            := tval2 >> 2
153  out.htinst.bits.ALL           := 0.U
154  out.targetPc.bits.pc          := in.pcFromXtvec
155  out.targetPc.bits.raiseIPF    := instrAddrTransType.checkPageFault(in.pcFromXtvec)
156  out.targetPc.bits.raiseIAF    := instrAddrTransType.checkAccessFault(in.pcFromXtvec)
157  out.targetPc.bits.raiseIGPF   := false.B
158
159  dontTouch(isLSGuestExcp)
160  dontTouch(tvalFillGVA)
161}
162
163trait TrapEntryHSEventSinkBundle { self: CSRModule[_] =>
164  val trapToHS = IO(Flipped(new TrapEntryHSEventOutput))
165
166  private val updateBundle: ValidIO[CSRBundle] = trapToHS.getBundleByName(self.modName.toLowerCase())
167
168  (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) =>
169    if (updateBundle.bits.eventFields.contains(source)) {
170      when(updateBundle.valid) {
171        sink := source
172      }
173    }
174  }
175}
176