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