xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSREvents/TrapEntryVSEvent.scala (revision 21e8685b69102452bb454870742496551ca56ad2)
1237d4cfdSXuan Hupackage xiangshan.backend.fu.NewCSR.CSREvents
2237d4cfdSXuan Hu
3237d4cfdSXuan Huimport chisel3._
4237d4cfdSXuan Huimport chisel3.util._
5237d4cfdSXuan Huimport org.chipsalliance.cde.config.Parameters
6237d4cfdSXuan Huimport utility.{SignExt, ZeroExt}
7237d4cfdSXuan Huimport xiangshan.ExceptionNO._
8237d4cfdSXuan Huimport xiangshan.backend.fu.NewCSR.CSRBundles.{CauseBundle, OneFieldBundle, PrivState}
9237d4cfdSXuan Huimport xiangshan.backend.fu.NewCSR.CSRConfig.{VaddrMaxWidth, XLEN}
10c1b28b66STang Haojinimport xiangshan.backend.fu.NewCSR.CSRDefines.{HgatpMode, SatpMode}
11237d4cfdSXuan Huimport xiangshan.backend.fu.NewCSR._
12c1b28b66STang Haojinimport xiangshan.AddrTransType
13237d4cfdSXuan Hu
14237d4cfdSXuan Hu
15237d4cfdSXuan Huclass TrapEntryVSEventOutput extends Bundle with EventUpdatePrivStateOutput with EventOutputBase  {
16237d4cfdSXuan Hu
176808b803SZehao Liu  val vsstatus = ValidIO((new SstatusBundle ).addInEvent(_.SPP, _.SPIE, _.SIE, _.SDT))
18260a087dSXuan Hu  val vsepc    = ValidIO((new Epc           ).addInEvent(_.epc))
19237d4cfdSXuan Hu  val vscause  = ValidIO((new CauseBundle   ).addInEvent(_.Interrupt, _.ExceptionCode))
20237d4cfdSXuan Hu  val vstval   = ValidIO((new OneFieldBundle).addInEvent(_.ALL))
21c1b28b66STang Haojin  val targetPc = ValidIO(new TargetPCBundle)
22237d4cfdSXuan Hu}
23237d4cfdSXuan Hu
24237d4cfdSXuan Huclass TrapEntryVSEventModule(implicit val p: Parameters) extends Module with CSREventBase {
25237d4cfdSXuan Hu  val in = IO(new TrapEntryEventInput)
26237d4cfdSXuan Hu  val out = IO(new TrapEntryVSEventOutput)
27237d4cfdSXuan Hu
28237d4cfdSXuan Hu  when (valid) {
29237d4cfdSXuan Hu    assert(in.privState.isVirtual, "The mode must be VU or VS when entry VS mode")
30237d4cfdSXuan Hu  }
31237d4cfdSXuan Hu
32237d4cfdSXuan Hu  private val current = in
33260a087dSXuan Hu  private val iMode = current.iMode
34260a087dSXuan Hu  private val dMode = current.dMode
35260a087dSXuan Hu  private val satp = current.satp
36260a087dSXuan Hu  private val vsatp = current.vsatp
37260a087dSXuan Hu  private val hgatp = current.hgatp
38237d4cfdSXuan Hu
3973e616deSXuan Hu  private val trapCode = in.causeNO.ExceptionCode.asUInt
40237d4cfdSXuan Hu  private val isException = !in.causeNO.Interrupt.asBool
41237d4cfdSXuan Hu  private val isInterrupt = in.causeNO.Interrupt.asBool
429205730dSsinceforYy  private val virtualInterruptIsHvictlInject = in.virtualInterruptIsHvictlInject
439205730dSsinceforYy  private val hvictlIID = in.hvictlIID
44237d4cfdSXuan Hu
459205730dSsinceforYy  when(valid && isInterrupt && !virtualInterruptIsHvictlInject) {
4673e616deSXuan Hu    assert(
4737e0d55eSsinceforYy      (InterruptNO.getVS ++ InterruptNO.getLocal).map(_.U === trapCode).reduce(_ || _),
4873e616deSXuan Hu      "The VS mode can only handle VSEI, VSTI, VSSI and local interrupts"
4973e616deSXuan Hu    )
5073e616deSXuan Hu  }
5173e616deSXuan Hu
5273e616deSXuan Hu  private val highPrioTrapNO = Mux(
5356f793a7Slewislzh    InterruptNO.getVS.map(_.U === trapCode).reduce(_ || _) && isInterrupt,
5473e616deSXuan Hu    trapCode - 1.U, // map VSSIP, VSTIP, VSEIP to SSIP, STIP, SEIP
5573e616deSXuan Hu    trapCode,
5673e616deSXuan Hu  )
5773e616deSXuan Hu
58260a087dSXuan Hu  private val trapPC = genTrapVA(
59260a087dSXuan Hu    iMode,
60260a087dSXuan Hu    satp,
61260a087dSXuan Hu    vsatp,
62260a087dSXuan Hu    hgatp,
63260a087dSXuan Hu    in.trapPc,
64260a087dSXuan Hu  )
65260a087dSXuan Hu
66db6cfb5aSHaoyuan Feng  private val trapMemVA = in.memExceptionVAddr
67db6cfb5aSHaoyuan Feng
68db6cfb5aSHaoyuan Feng  private val trapMemGPA = in.memExceptionGPAddr
69237d4cfdSXuan Hu
7092c61038SXuan Hu  private val trapInst = Mux(in.trapInst.valid, in.trapInst.bits, 0.U)
7192c61038SXuan Hu
72237d4cfdSXuan Hu  private val fetchIsVirt = current.iMode.isVirtual
73237d4cfdSXuan Hu  private val memIsVirt   = current.dMode.isVirtual
74237d4cfdSXuan Hu
75237d4cfdSXuan Hu  private val isFetchExcp    = isException && Seq(/*EX_IAM, */ EX_IAF, EX_IPF).map(_.U === highPrioTrapNO).reduce(_ || _)
76237d4cfdSXuan Hu  private val isMemExcp      = isException && Seq(EX_LAM, EX_LAF, EX_SAM, EX_SAF, EX_LPF, EX_SPF).map(_.U === highPrioTrapNO).reduce(_ || _)
77237d4cfdSXuan Hu  private val isBpExcp       = isException && EX_BP.U === highPrioTrapNO
78fe52823cSXuan Hu  private val isFetchBkpt    = isBpExcp && in.isFetchBkpt
79fe52823cSXuan Hu  private val isMemBkpt      = isBpExcp && !in.isFetchBkpt
80237d4cfdSXuan Hu  private val fetchCrossPage = in.isCrossPageIPF
81c1b28b66STang Haojin  private val isFetchMalAddr = in.isFetchMalAddr
82*21e8685bSZhaoyang You  private val isFetchMalAddrExcp = isException && isFetchMalAddr
83e0bc5040Slewislzh  private val isIllegalInst  = isException && (EX_II.U === highPrioTrapNO || EX_VI.U === highPrioTrapNO)
84237d4cfdSXuan Hu
85237d4cfdSXuan Hu  // Software breakpoint exceptions are permitted to write either 0 or the pc to xtval
86237d4cfdSXuan Hu  // We fill pc here
87fe52823cSXuan Hu  private val tvalFillPc       = isFetchExcp && !fetchCrossPage || isFetchBkpt
88237d4cfdSXuan Hu  private val tvalFillPcPlus2  = isFetchExcp && fetchCrossPage
89be29197cSchengguanghui  private val tvalFillMemVaddr = isMemExcp || isMemBkpt
90237d4cfdSXuan Hu  private val tvalFillGVA      =
91fe52823cSXuan Hu    (isFetchExcp || isFetchBkpt) && fetchIsVirt ||
92fe52823cSXuan Hu    (isMemExcp || isMemBkpt) && memIsVirt
93fa16cf81Slewislzh  private val tvalFillInst     = isIllegalInst
94237d4cfdSXuan Hu
95237d4cfdSXuan Hu  private val tval = Mux1H(Seq(
96cfa16394Schengguanghui    tvalFillPc       -> trapPC,
97cfa16394Schengguanghui    tvalFillPcPlus2  -> (trapPC + 2.U),
98cfa16394Schengguanghui    tvalFillMemVaddr -> trapMemVA,
99cfa16394Schengguanghui    tvalFillInst     -> trapInst,
100237d4cfdSXuan Hu  ))
101237d4cfdSXuan Hu
102c1b28b66STang Haojin  private val instrAddrTransType = AddrTransType(
103c1b28b66STang Haojin    bare = vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Bare,
104c1b28b66STang Haojin    sv39 = vsatp.MODE === SatpMode.Sv39,
105c1b28b66STang Haojin    sv48 = vsatp.MODE === SatpMode.Sv48,
106c1b28b66STang Haojin    sv39x4 = vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv39x4,
107c1b28b66STang Haojin    sv48x4 = vsatp.MODE === SatpMode.Bare && hgatp.MODE === HgatpMode.Sv48x4
108c1b28b66STang Haojin  )
109c1b28b66STang Haojin
110237d4cfdSXuan Hu  out := DontCare
111237d4cfdSXuan Hu
112237d4cfdSXuan Hu  out.privState.valid := valid
113237d4cfdSXuan Hu
114237d4cfdSXuan Hu  out.vsstatus .valid := valid
115237d4cfdSXuan Hu  out.vsepc    .valid := valid
116237d4cfdSXuan Hu  out.vscause  .valid := valid
117237d4cfdSXuan Hu  out.vstval   .valid := valid
1180c2ba7aeSXuan Hu  out.targetPc .valid := valid
119237d4cfdSXuan Hu
120237d4cfdSXuan Hu  out.privState.bits             := PrivState.ModeVS
121237d4cfdSXuan Hu  // vsstatus
122237d4cfdSXuan Hu  out.vsstatus.bits.SPP          := current.privState.PRVM.asUInt(0, 0) // SPP is not PrivMode enum type, so asUInt and shrink the width
123237d4cfdSXuan Hu  out.vsstatus.bits.SPIE         := current.vsstatus.SIE
124237d4cfdSXuan Hu  out.vsstatus.bits.SIE          := 0.U
1256808b803SZehao Liu  out.vsstatus.bits.SDT          := in.henvcfg.DTE.asBool // when DTE open set SDT to 1, else SDT is readonly 0
126237d4cfdSXuan Hu  // SPVP is not PrivMode enum type, so asUInt and shrink the width
127c1b28b66STang Haojin  out.vsepc.bits.epc             := Mux(isFetchMalAddr, in.fetchMalTval(63, 1), trapPC(63, 1))
128237d4cfdSXuan Hu  out.vscause.bits.Interrupt     := isInterrupt
1299205730dSsinceforYy  out.vscause.bits.ExceptionCode := Mux(virtualInterruptIsHvictlInject, hvictlIID, highPrioTrapNO)
130*21e8685bSZhaoyang You  out.vstval.bits.ALL            := Mux(isFetchMalAddrExcp, in.fetchMalTval, tval)
131c1b28b66STang Haojin  out.targetPc.bits.pc           := in.pcFromXtvec
132c1b28b66STang Haojin  out.targetPc.bits.raiseIPF     := instrAddrTransType.checkPageFault(in.pcFromXtvec)
133c1b28b66STang Haojin  out.targetPc.bits.raiseIAF     := instrAddrTransType.checkAccessFault(in.pcFromXtvec)
134c1b28b66STang Haojin  out.targetPc.bits.raiseIGPF    := instrAddrTransType.checkGuestPageFault(in.pcFromXtvec)
135237d4cfdSXuan Hu
136237d4cfdSXuan Hu  dontTouch(tvalFillGVA)
137237d4cfdSXuan Hu}
138237d4cfdSXuan Hu
139cb36ac0fSXuan Hutrait TrapEntryVSEventSinkBundle extends EventSinkBundle { self: CSRModule[_ <: CSRBundle] =>
140237d4cfdSXuan Hu  val trapToVS = IO(Flipped(new TrapEntryVSEventOutput))
141237d4cfdSXuan Hu
142cb36ac0fSXuan Hu  addUpdateBundleInCSREnumType(trapToVS.getBundleByName(self.modName.toLowerCase()))
143237d4cfdSXuan Hu
144cb36ac0fSXuan Hu  reconnectReg()
145237d4cfdSXuan Hu}
146