xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/TrapEntryVSEvent.scala (revision 237d4cfdf1ee221ec141b1ffee983a89747b6608)
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, HasXSParameter}
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.SatpMode
12import xiangshan.backend.fu.NewCSR._
13import xiangshan.backend.fu.util.CSRConst
14
15
16class TrapEntryVSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase  {
17
18  val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE))
19  val vsepc    = ValidIO((new Epc           ).addInEvent(_.ALL))
20  val vscause  = ValidIO((new CauseBundle   ).addInEvent(_.Interrupt, _.ExceptionCode))
21  val vstval   = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
22
23  def getBundleByName(name: String): Valid[CSRBundle] = {
24    name match {
25      case "vsstatus" => this.vsstatus
26      case "vsepc"    => this.vsepc
27      case "vscause"  => this.vscause
28      case "vstval"   => this.vstval
29    }
30  }
31}
32
33class TrapEntryVSEventModule(implicit val p: Parameters) extends Module with CSREventBase {
34  val in = IO(new TrapEntryEventInput)
35  val out = IO(new TrapEntryVSEventOutput)
36
37  when (valid) {
38    assert(in.privState.isVirtual, "The mode must be VU or VS when entry VS mode")
39  }
40
41  private val current = in
42
43  private val highPrioTrapNO = in.causeNO.ExceptionCode.asUInt
44  private val isException = !in.causeNO.Interrupt.asBool
45  private val isInterrupt = in.causeNO.Interrupt.asBool
46
47  private val trapPC = Wire(UInt(XLEN.W))
48  private val trapMemVA = SignExt(in.memExceptionVAddr, XLEN)
49  private val trapMemGPA = SignExt(in.memExceptionGPAddr, XLEN)
50  private val ivmVS = !current.iMode.isModeVS && current.vsatp.MODE =/= SatpMode.Bare
51  // When enable virtual memory, the higher bit should fill with the msb of address of Sv39/Sv48/Sv57
52  trapPC := Mux(ivmVS, SignExt(in.trapPc, XLEN), ZeroExt(in.trapPc, XLEN))
53
54  private val fetchIsVirt = current.iMode.isVirtual
55  private val memIsVirt   = current.dMode.isVirtual
56
57  when (valid && isInterrupt) {
58    import InterruptNO._
59    assert(Seq(SEI, STI, SSI).map(_.U === highPrioTrapNO).reduce(_ || _), "The VS mode can only handle SEI, STI, SSI")
60  }
61
62  private val isFetchExcp    = isException && Seq(/*EX_IAM, */ EX_IAF, EX_IPF).map(_.U === highPrioTrapNO).reduce(_ || _)
63  private val isMemExcp      = isException && Seq(EX_LAM, EX_LAF, EX_SAM, EX_SAF, EX_LPF, EX_SPF).map(_.U === highPrioTrapNO).reduce(_ || _)
64  private val isBpExcp       = isException && EX_BP.U === highPrioTrapNO
65  private val fetchCrossPage = in.isCrossPageIPF
66
67  // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval
68  // We fill pc here
69  private val tvalFillPc       = isFetchExcp && !fetchCrossPage || isBpExcp
70  private val tvalFillPcPlus2  = isFetchExcp && fetchCrossPage
71  private val tvalFillMemVaddr = isMemExcp
72  private val tvalFillGVA      =
73    (isFetchExcp || isBpExcp) && fetchIsVirt ||
74    isMemExcp && memIsVirt
75
76  private val tval = Mux1H(Seq(
77    (tvalFillPc                     ) -> trapPC,
78    (tvalFillPcPlus2                ) -> (trapPC + 2.U),
79    (tvalFillMemVaddr && !memIsVirt ) -> trapMemVA,
80    (tvalFillMemVaddr &&  memIsVirt ) -> trapMemVA,
81  ))
82
83  out := DontCare
84
85  out.privState.valid := valid
86
87  out.vsstatus .valid := valid
88  out.vsepc    .valid := valid
89  out.vscause  .valid := valid
90  out.vstval   .valid := valid
91
92  out.privState.bits             := PrivState.ModeVS
93  // vsstatus
94  out.vsstatus.bits.SPP          := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
95  out.vsstatus.bits.SPIE         := current.vsstatus.SIE
96  out.vsstatus.bits.SIE          := 0.U
97  // SPVP is not PrivMode enum type, so asUInt and shrink the width
98  out.vsepc.bits.ALL             := trapPC(trapPC.getWidth - 1, 1)
99  out.vscause.bits.Interrupt     := isInterrupt
100  out.vscause.bits.ExceptionCode := highPrioTrapNO
101  out.vstval.bits.ALL            := tval
102
103  dontTouch(tvalFillGVA)
104}
105
106trait TrapEntryVSEventSinkBundle { self: CSRModule[_] =>
107  val trapToVS = IO(Flipped(new TrapEntryVSEventOutput))
108
109  private val updateBundle: ValidIO[CSRBundle] = trapToVS.getBundleByName(self.modName.toLowerCase())
110
111  (reg.asInstanceOf[CSRBundle].getFields zip updateBundle.bits.getFields).foreach { case (sink, source) =>
112    if (updateBundle.bits.eventFields.contains(source)) {
113      when(updateBundle.valid) {
114        sink := source
115      }
116    }
117  }
118}
119