xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/SretEvent.scala (revision 237d4cfdf1ee221ec141b1ffee983a89747b6608)
1package xiangshan.backend.fu.NewCSR.CSREvents
2
3import chisel3._
4import chisel3.util._
5import utility.{SignExt, ZeroExt}
6import xiangshan.ExceptionNO
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.{PrivMode, SatpMode, VirtMode}
11import xiangshan.backend.fu.NewCSR._
12import xiangshan.backend.fu.util.CSRConst
13
14
15class SretEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase {
16  // Todo: write sstatus instead of mstatus
17  val mstatus = ValidIO((new MstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP, _.MPRV))
18  val hstatus = ValidIO((new HstatusBundle).addInEvent(_.SPV))
19  val vsstatus = ValidIO((new SstatusBundle).addInEvent(_.SIE, _.SPIE, _.SPP))
20  val targetPc = ValidIO(new Epc().addInEvent(_.ALL))
21
22  override def getBundleByName(name: String): ValidIO[CSRBundle] = {
23    name match {
24      case "mstatus" => this.mstatus
25      case "hstatus" => this.hstatus
26      case "vsstatus" => this.vsstatus
27    }
28  }
29}
30
31class SretEventInput extends Bundle {
32  val privState = Input(new PrivState)
33  val sstatus   = Input(new SstatusBundle)
34  val hstatus   = Input(new HstatusBundle)
35  val vsstatus  = Input(new SstatusBundle)
36  val sepc      = Input(new Epc())
37  val vsepc     = Input(new Epc())
38}
39
40class SretEventModule extends Module with CSREventBase {
41  val in = IO(new SretEventInput)
42  val out = IO(new SretEventOutput)
43
44  val sretInHSorM = in.privState.isModeM || in.privState.isModeHS
45  val sretInVS    = in.privState.isModeVS
46
47  out := DontCare
48
49  out.privState.valid := valid
50  out.targetPc .valid := valid
51
52  out.privState.bits.PRVM := Mux1H(Seq(
53    // SPP is not PrivMode enum type, so asUInt
54    sretInHSorM -> in.sstatus.SPP.asUInt,
55    sretInVS    -> in.vsstatus.SPP.asUInt,
56  ))
57  out.privState.bits.V    := Mux1H(Seq(
58    sretInHSorM -> in.hstatus.SPV,
59    sretInVS    -> in.privState.V, // keep
60  ))
61
62  // hstatus
63  out.hstatus.valid       := valid && sretInHSorM
64  out.hstatus.bits.SPV    := VirtMode.Off
65
66  // sstatus
67  out.mstatus.valid       := valid && sretInHSorM
68  out.mstatus.bits.SPP    := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
69  out.mstatus.bits.SIE    := in.sstatus.SPIE
70  out.mstatus.bits.SPIE   := 1.U
71  out.mstatus.bits.MPRV   := 0.U // sret will always leave M mode
72
73  // vsstatus
74  out.vsstatus.valid      := valid && sretInVS
75  out.vsstatus.bits.SPP   := PrivMode.U.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
76  out.vsstatus.bits.SIE   := in.vsstatus.SPIE
77  out.vsstatus.bits.SPIE  := 1.U
78
79  out.targetPc.bits       := Mux1H(Seq(
80    sretInHSorM -> in.sepc,
81    sretInVS    -> in.vsepc,
82  ))
83
84  // for better verilog
85  dontTouch(sretInHSorM)
86  dontTouch(sretInVS)
87}
88
89trait SretEventSinkBundle { self: CSRModule[_] =>
90  val retFromS = IO(Flipped(new SretEventOutput))
91
92  private val updateBundle: ValidIO[CSRBundle] = retFromS.getBundleByName(self.modName.toLowerCase())
93
94  (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) =>
95    if (updateBundle.bits.eventFields.contains(source)) {
96      when(updateBundle.valid) {
97        sink := source
98      }
99    }
100  }
101}
102