xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/SretEvent.scala (revision eca6983f19d9c20aa907987dff616649c3d204a2)
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.ExceptionNO._
9import xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState}
10import xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN}
11import xiangshan.backend.fu.NewCSR.CSRDefines.{HgatpMode, PrivMode, SatpMode, VirtMode}
12import xiangshan.backend.fu.NewCSR._
13import xiangshan.AddrTransType
14
15
16class SretEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {
17  // Todo: write sstatus instead of mstatus
18  val mstatus = ValidIO((new MstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP, _.MPRV, _.MDT, _.SDT))
19  val hstatus = ValidIO((new HstatusBundle).addInEvent(_.SPV))
20  val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP))
21  val targetPc = ValidIO(new TargetPCBundle)
22}
23
24class SretEventSDTOutput extends Bundle with EventOutputBase {
25  val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SDT))
26}
27
28class SretEventInput extends Bundle {
29  val privState = Input(new PrivState)
30  val mstatus   = Input(new MstatusBundle)
31  val hstatus   = Input(new HstatusBundle)
32  val vsstatus  = Input(new SstatusBundle)
33  val sepc      = Input(new Epc())
34  val vsepc     = Input(new Epc())
35  val satp      = Input(new SatpBundle)
36  val vsatp     = Input(new SatpBundle)
37  val hgatp     = Input(new HgatpBundle)
38}
39
40class SretEventModule(implicit p: Parameters) extends Module with CSREventBase {
41  val in = IO(new SretEventInput)
42  val out = IO(new SretEventOutput)
43
44  val outSDT = IO(new SretEventSDTOutput)
45
46  private val satp = in.satp
47  private val vsatp = in.vsatp
48  private val hgatp = in.hgatp
49  private val nextPrivState = out.privState.bits
50
51  private val instrAddrTransType = AddrTransType(
52    bare = (!nextPrivState.isVirtual && satp.MODE === SatpMode.Bare) ||
53           (nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Bare),
54    sv39 = !nextPrivState.isVirtual && satp.MODE === SatpMode.Sv39 ||
55           nextPrivState.isVirtual && vsatp.MODE === SatpMode.Sv39,
56    sv48 = !nextPrivState.isVirtual && satp.MODE === SatpMode.Sv48 ||
57           nextPrivState.isVirtual && vsatp.MODE === SatpMode.Sv48,
58    sv39x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv39x4,
59    sv48x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4
60  )
61
62  private val sretInM     = in.privState.isModeM
63  private val sretInHS    = in.privState.isModeHS
64  private val sretInHSorM = sretInM || sretInHS
65  private val sretInVS    = in.privState.isModeVS
66
67  private val xepc = Mux1H(Seq(
68    sretInHSorM -> in.sepc,
69    sretInVS    -> in.vsepc,
70  )).asUInt
71
72
73  private val outPrivState   = Wire(new PrivState)
74  outPrivState.PRVM := Mux1H(Seq(
75    // SPP is not PrivMode enum type, so asUInt
76    sretInHSorM -> in.mstatus.SPP.asUInt,
77    sretInVS    -> in.vsstatus.SPP.asUInt,
78  ))
79  outPrivState.V := Mux1H(Seq(
80    sretInHSorM -> in.hstatus.SPV,
81    sretInVS    -> in.privState.V, // keep
82  ))
83
84  private val sretToVU    = outPrivState.isModeVU
85  private val sretToVS    = outPrivState.isModeVS
86  private val sretToU     = outPrivState.isModeHU
87
88  out := DontCare
89  outSDT := DontCare
90
91  out.privState.valid := valid
92  out.targetPc .valid := valid
93
94  out.privState.bits      := outPrivState
95
96  // hstatus
97  out.hstatus.valid           := valid && sretInHSorM
98  out.hstatus.bits.SPV        := VirtMode.Off
99
100  // sstatus
101  out.mstatus.valid           := valid && sretInHSorM
102  out.mstatus.bits.SPP        := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
103  out.mstatus.bits.SIE        := in.mstatus.SPIE
104  out.mstatus.bits.SPIE       := 1.U
105  out.mstatus.bits.MPRV       := 0.U // sret will always leave M mode
106  out.mstatus.bits.MDT        := Mux(sretInM, 0.U, in.mstatus.MDT.asBool) // when execute return in M mode, set MDT 0
107  out.mstatus.bits.SDT        := MuxCase(in.mstatus.SDT.asBool, Seq(
108    sretInHS   -> 0.U, // sret will alway leave M mode
109    (sretInM && (sretToU || sretToVS || sretToVU))    -> 0.U
110  ))
111
112
113  // vsstatus
114  out.vsstatus.valid          := valid && sretInVS
115  out.vsstatus.bits.SPP       := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
116  out.vsstatus.bits.SIE       := in.vsstatus.SPIE
117  out.vsstatus.bits.SPIE      := 1.U
118
119  outSDT.vsstatus.valid       := valid && (sretToVU || sretInVS) // clear SDT when return to VU or sret in vs
120  outSDT.vsstatus.bits.SDT    := 0.U
121
122  out.targetPc.bits.pc        := xepc
123  out.targetPc.bits.raiseIPF  := instrAddrTransType.checkPageFault(xepc)
124  out.targetPc.bits.raiseIAF  := instrAddrTransType.checkAccessFault(xepc)
125  out.targetPc.bits.raiseIGPF := instrAddrTransType.checkGuestPageFault(xepc)
126
127  // for better verilog
128  dontTouch(sretInHSorM)
129  dontTouch(sretInVS)
130}
131
132trait SretEventSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] =>
133  val retFromS = IO(Flipped(new SretEventOutput))
134
135  addUpdateBundleInCSREnumType(retFromS.getBundleByName(self.modName.toLowerCase()))
136
137  reconnectReg()
138}
139
140trait SretEventSDTSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] =>
141  val retFromSSDT = IO(Flipped(new SretEventSDTOutput))
142
143  addUpdateBundleInCSREnumType(retFromSSDT.getBundleByName(self.modName.toLowerCase()))
144
145  reconnectReg()
146}
147
148