xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/SretEvent.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.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))
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  override def getBundleByName(name: String): ValidIO[CSRBundle] = {
24    name match {
25      case "mstatus" => this.mstatus
26      case "hstatus" => this.hstatus
27      case "vsstatus" => this.vsstatus
28    }
29  }
30}
31
32class SretEventInput extends Bundle {
33  val privState = Input(new PrivState)
34  val sstatus   = Input(new SstatusBundle)
35  val hstatus   = Input(new HstatusBundle)
36  val vsstatus  = Input(new SstatusBundle)
37  val sepc      = Input(new Epc())
38  val vsepc     = Input(new Epc())
39  val satp      = Input(new SatpBundle)
40  val vsatp     = Input(new SatpBundle)
41  val hgatp     = Input(new HgatpBundle)
42}
43
44class SretEventModule(implicit p: Parameters) extends Module with CSREventBase {
45  val in = IO(new SretEventInput)
46  val out = IO(new SretEventOutput)
47
48  private val satp = in.satp
49  private val vsatp = in.vsatp
50  private val hgatp = in.hgatp
51  private val nextPrivState = out.privState.bits
52
53  private val instrAddrTransType = AddrTransType(
54    bare = (!nextPrivState.isVirtual && satp.MODE === SatpMode.Bare) ||
55           (nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Bare),
56    sv39 = !nextPrivState.isVirtual && satp.MODE === SatpMode.Sv39 ||
57           nextPrivState.isVirtual && vsatp.MODE === SatpMode.Sv39,
58    sv48 = !nextPrivState.isVirtual && satp.MODE === SatpMode.Sv48 ||
59           nextPrivState.isVirtual && vsatp.MODE === SatpMode.Sv48,
60    sv39x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv39x4,
61    sv48x4 = nextPrivState.isVirtual && vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4
62  )
63
64  private val sretInHSorM = in.privState.isModeM || in.privState.isModeHS
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  out := DontCare
73
74  out.privState.valid := valid
75  out.targetPc .valid := valid
76
77  out.privState.bits.PRVM     := Mux1H(Seq(
78    // SPP is not PrivMode enum type, so asUInt
79    sretInHSorM -> in.sstatus.SPP.asUInt,
80    sretInVS    -> in.vsstatus.SPP.asUInt,
81  ))
82  out.privState.bits.V        := Mux1H(Seq(
83    sretInHSorM -> in.hstatus.SPV,
84    sretInVS    -> in.privState.V, // keep
85  ))
86
87  // hstatus
88  out.hstatus.valid           := valid && sretInHSorM
89  out.hstatus.bits.SPV        := VirtMode.Off
90
91  // sstatus
92  out.mstatus.valid           := valid && sretInHSorM
93  out.mstatus.bits.SPP        := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
94  out.mstatus.bits.SIE        := in.sstatus.SPIE
95  out.mstatus.bits.SPIE       := 1.U
96  out.mstatus.bits.MPRV       := 0.U // sret will always leave M mode
97
98  // vsstatus
99  out.vsstatus.valid          := valid && sretInVS
100  out.vsstatus.bits.SPP       := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
101  out.vsstatus.bits.SIE       := in.vsstatus.SPIE
102  out.vsstatus.bits.SPIE      := 1.U
103
104  out.targetPc.bits.pc        := xepc
105  out.targetPc.bits.raiseIPF  := instrAddrTransType.checkPageFault(xepc)
106  out.targetPc.bits.raiseIAF  := instrAddrTransType.checkAccessFault(xepc)
107  out.targetPc.bits.raiseIGPF := instrAddrTransType.checkGuestPageFault(xepc)
108
109  // for better verilog
110  dontTouch(sretInHSorM)
111  dontTouch(sretInVS)
112}
113
114trait SretEventSinkBundle { self: CSRModule[_] =>
115  val retFromS = IO(Flipped(new SretEventOutput))
116
117  private val updateBundle: ValidIO[CSRBundle] = retFromS.getBundleByName(self.modName.toLowerCase())
118
119  (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) =>
120    if (updateBundle.bits.eventFields.contains(source)) {
121      when(updateBundle.valid) {
122        sink := source
123      }
124    }
125  }
126}
127