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