xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/HypervisorLevel.scala (revision 24bb726d80e7b0ea2ad2c685838b3a749ec0178d)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import freechips.rocketchip.rocket.CSRs
6import org.chipsalliance.cde.config.Parameters
7import utility.ZeroExt
8import xiangshan.backend.fu.NewCSR.CSRBundles._
9import xiangshan.backend.fu.NewCSR.CSRConfig._
10import xiangshan.backend.fu.NewCSR.CSRDefines.{CSRROField => RO, CSRRWField => RW, _}
11import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._
12import xiangshan.backend.fu.NewCSR.CSREvents.{SretEventSinkBundle, TrapEntryHSEventSinkBundle}
13import xiangshan.backend.fu.NewCSR.CSRFunc._
14import xiangshan.backend.fu.NewCSR.ChiselRecordForField._
15
16import scala.collection.immutable.SeqMap
17
18trait HypervisorLevel { self: NewCSR =>
19
20  val hstatus = Module(new HstatusModule)
21    .setAddr(CSRs.hstatus)
22
23  val hedeleg = Module(new CSRModule("Hedeleg", new HedelegBundle))
24    .setAddr(CSRs.hedeleg)
25
26  val hideleg = Module(new CSRModule("Hideleg", new HidelegBundle))
27    .setAddr(CSRs.hideleg)
28
29  val hie = Module(new CSRModule("Hie", new HieBundle)
30    with HasIpIeBundle
31    with HypervisorBundle
32  {
33    val toMie = IO(new HieToMie)
34
35    val mieIsAlias = mideleg
36
37    bundle.getFields.map(_.lsb).foreach { num =>
38      val wtMie  = toMie.getByNum(num)
39      wtMie.specifyField(
40        _.valid := wen && mieIsAlias(num) && wtMie.bits.isRW.B,
41        _.bits  := wen && mieIsAlias(num) && wtMie.bits.isRW.B &< wdata(num),
42      )
43
44      regOut(num) := mieIsAlias(num) && wtMie.bits.isRW.B &< mie(num)
45    }
46  })
47    .setAddr(CSRs.hie)
48
49  val htimedelta = Module(new CSRModule("Htimedelta"))
50    .setAddr(CSRs.htimedelta)
51
52  val hcounteren = Module(new CSRModule("Hcounteren", new Counteren))
53    .setAddr(CSRs.hcounteren)
54
55  val hgeie = Module(new CSRModule("Hgeie", new HgeieBundle))
56    .setAddr(CSRs.hgeie)
57
58  val hvien = Module(new CSRModule("Hvien", new HvienBundle))
59    .setAddr(CSRs.hvien)
60
61  val hvictl = Module(new CSRModule("Hvictl", new HvictlBundle))
62    .setAddr(CSRs.hvictl)
63
64  val henvcfg = Module(new CSRModule("Henvcfg", new HEnvCfg) with HasHypervisorEnvBundle {
65    when (!menvcfg.STCE.asBool) {
66      regOut.STCE := 0.U
67    }
68    when (!menvcfg.PBMTE) {
69      regOut.PBMTE := 0.U
70    }
71  })
72    .setAddr(CSRs.henvcfg)
73
74  val htval = Module(new CSRModule("Htval", new XtvalBundle) with TrapEntryHSEventSinkBundle)
75    .setAddr(CSRs.htval)
76
77  val hip = Module(new CSRModule("Hip", new HipBundle)
78    with HypervisorBundle
79    with HasExternalInterruptBundle
80    with HasIpIeBundle
81  {
82    val toHvip = IO(new HipToHvip)
83
84    // hip.VSEIP is read-only alias of mip.VSEIP, mip.VSEIP := hvip.VSEIP|hgeip(VGEIN)|platIR.VSEIP
85    // hip.VSTIP is read-only alias of mip.VSTIP, mip.VSTIP := hvip.VSTIP|time+htimedelta>=vstimecmp
86    // hip.SGEIP is read-only alias of mip.SGEIP, mip.SGEIP := |(hgeip&hgeie)
87    regOut.VSTIP := mip.VSTIP
88    regOut.VSEIP := mip.VSEIP
89    regOut.SGEIP := mip.SGEIP
90
91    // hip.VSSIP is alias of hvip.VSSIP, writable
92    toHvip.VSSIP.valid := wen
93    toHvip.VSSIP.bits  := wdata.VSSIP
94    regOut.VSSIP := this.hvip.VSSIP
95    // vsip.SSIP is alias of hip.VSSIP, so vsip.SSIP is alias of hvip.VSSIP.
96    // vsip.SSIP write throuth to hvip.VSSIP
97  })
98    .setAddr(CSRs.hip)
99
100  val hvip = Module(new CSRModule("Hvip", new HvipBundle) {
101    val fromMip  = IO(Flipped(new MipToHvip))
102    val fromHip  = IO(Flipped(new HipToHvip))
103    val fromVSip = IO(Flipped(new VSipToHvip))
104
105    when (fromMip.VSSIP.valid || fromHip.VSSIP.valid || fromVSip.VSSIP.valid) {
106      reg.VSSIP := Mux1H(Seq(
107        fromMip.VSSIP.valid -> fromMip.VSSIP.bits,
108        fromHip.VSSIP.valid -> fromHip.VSSIP.bits,
109        fromVSip.VSSIP.valid -> fromVSip.VSSIP.bits,
110      ))
111    }
112
113    reg.getLocal zip fromVSip.getLocal foreach { case (rLCIP, vsipLCIP) =>
114      // sip should assert valid when hideleg=0 && hvien=1
115      when(vsipLCIP.valid) {
116        rLCIP := vsipLCIP.bits
117      }
118    }
119  })
120    .setAddr(CSRs.hvip)
121
122  val hviprio1 = Module(new CSRModule("Hviprio1", new Hviprio1Bundle))
123    .setAddr(CSRs.hviprio1)
124
125  val hviprio2 = Module(new CSRModule("Hviprio2", new Hviprio2Bundle))
126    .setAddr(CSRs.hviprio2)
127
128  val htinst = Module(new CSRModule("Htinst", new XtinstBundle) with TrapEntryHSEventSinkBundle)
129    .setAddr(CSRs.htinst)
130
131  val hgatp = Module(new CSRModule("Hgatp", new HgatpBundle) {
132    // Ref: 13.2.10. Hypervisor Guest Address Translation and Protection Register (hgatp)
133    // A write to hgatp with an unsupported MODE value is not ignored as it is for satp. Instead, the fields of
134    // hgatp are WARL in the normal way, when so indicated.
135
136    // The length of ppn is 44 bits.
137    // make PPN[1:0] read-only zero.
138    val ppnMask = ZeroExt((Fill(PPNLength - 2, 1.U(1.W)) ## 0.U(2.W)).take(PAddrBits - PageOffsetWidth), PPNLength)
139
140    when (wen) {
141      reg.VMID := wdata.VMID
142      reg.PPN  := wdata.PPN & ppnMask
143      when (wdata.MODE.isLegal) {
144        reg.MODE := wdata.MODE
145      }.otherwise {
146        reg.MODE := reg.MODE
147      }
148    }.otherwise {
149      reg := reg
150    }
151  })
152    .setAddr(CSRs.hgatp)
153
154  val hgeip = Module(new CSRModule("Hgeip", new HgeipBundle) with HasAIABundle {
155    regOut.ip := aiaToCSR.vseip
156  })
157    .setAddr(CSRs.hgeip)
158
159  val hstateen0 = Module(new CSRModule("Hstateen", new HstateenBundle0) with HasStateen0Bundle {
160    // For every bit in an mstateen CSR that is zero (whether read-only zero or set to zero), the same bit
161    // appears as read-only zero in the matching hstateen and sstateen CSRs.
162    regOut := reg.asUInt & fromMstateen0.asUInt
163  }).setAddr(CSRs.hstateen0)
164
165  val hypervisorCSRMods: Seq[CSRModule[_]] = Seq(
166    hstatus,
167    hedeleg,
168    hideleg,
169    hie,
170    htimedelta,
171    hcounteren,
172    hgeie,
173    hvien,
174    hvictl,
175    henvcfg,
176    htval,
177    hip,
178    hvip,
179    hviprio1,
180    hviprio2,
181    htinst,
182    hgatp,
183    hgeip,
184    hstateen0,
185  )
186
187  val hypervisorCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from(
188    hypervisorCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata))).iterator
189  )
190
191  val hypervisorCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
192    hypervisorCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt)).iterator
193  )
194}
195
196class HstatusBundle extends CSRBundle {
197
198  val VSBE  = RO(5).withReset(0.U)
199  val GVA   = RW(6)
200  val SPV   = VirtMode(7)
201  val SPVP  = RW(8)
202  val HU    = RW(9)
203  val VGEIN = HstatusVgeinField(17, 12, wNoFilter, rNoFilter).withReset(0.U)
204  val VTVM  = RW(20).withReset(0.U)
205  val VTW   = RW(21).withReset(0.U)
206  val VTSR  = RW(22).withReset(0.U)
207  val VSXL  = XLENField(33, 32).withReset(XLENField.XLEN64)
208
209}
210
211object HstatusVgeinField extends CSREnum with WLRLApply {
212  override def isLegal(enumeration: CSREnumType): Bool = enumeration.asUInt <= GEILEN.U
213}
214
215class HstatusModule(implicit p: Parameters) extends CSRModule("Hstatus", new HstatusBundle)
216  with SretEventSinkBundle
217  with TrapEntryHSEventSinkBundle
218
219class HvipBundle extends InterruptPendingBundle {
220  // VSSIP, VSTIP, VSEIP, localIP is writable
221  this.getVS.foreach(_.setRW().withReset(0.U))
222  this.getLocal.foreach(_.setRW().withReset(0.U))
223}
224
225class HieBundle extends InterruptEnableBundle {
226  // All bits in hie are RO, since all registers implemented in mie.
227}
228
229class HipBundle extends InterruptPendingBundle {
230  this.VSSIP.setRW().withReset(0.U) // aliasRW of mip.VSSIP when mideleg=1.
231  this.VSTIP.setRO().withReset(0.U) // aliasRO of mip.VSTIP when mideleg=1. (hvip.VSTIP | PLIC.VSTIP)
232  this.VSEIP.setRO().withReset(0.U) // aliasRO of mip.VSEIP when mideleg=1. (hvip.VSEIP | hgeip(hstatus.VGEIN) | PLIC.VSEIP)
233  this.SGEIP.setRO().withReset(0.U) // aliasRO of mip.SGEIP (|(hgeip & hegie))
234}
235
236class HvienBundle extends InterruptEnableBundle {
237  // Ref: riscv interrupt spec - 6.3.2 Virtual interrupts for VS level
238  // Bits 12:0 of hvien are reserved and must be read-only zeros.
239  // For interrupt numbers 13–63, implementations may freely choose which bits of hvien are writable
240  // and which bits are read-only zero or one.
241  this.getLocal.foreach(_.setRW().withReset(0.U))
242
243}
244
245class HgeieBundle extends CSRBundle {
246  val ie = RW(GEILEN, 1).withReset(0.U)
247  // bit 0 is read only 0
248}
249
250class HgeipBundle extends CSRBundle {
251  val ip = RO(GEILEN, 1)
252  // bit 0 is read only 0
253}
254
255class HedelegBundle extends ExceptionBundle {
256  this.getALL.foreach(_.setRW().withReset(0.U))
257  // The default configs are RW
258  this.EX_HSCALL.setRO().withReset(0.U)
259  this.EX_VSCALL.setRO().withReset(0.U)
260  this.EX_MCALL .setRO().withReset(0.U)
261  this.EX_IGPF  .setRO().withReset(0.U)
262  this.EX_LGPF  .setRO().withReset(0.U)
263  this.EX_VI    .setRO().withReset(0.U)
264  this.EX_SGPF  .setRO().withReset(0.U)
265}
266
267class HidelegBundle extends InterruptBundle {
268  this.getALL.foreach(_.setRW().withReset(0.U))
269  // default RW
270  this.SSI .setRO().withReset(0.U)
271  this.MSI .setRO().withReset(0.U)
272  this.STI .setRO().withReset(0.U)
273  this.MTI .setRO().withReset(0.U)
274  this.SEI .setRO().withReset(0.U)
275  this.MEI .setRO().withReset(0.U)
276  this.SGEI.setRO().withReset(0.U)
277  this.getLocal.foreach(_.setRO().withReset(0.U))
278  this.LCOFI.setRW().withReset(0.U)
279}
280
281class HipToHvip extends Bundle {
282  val VSSIP = ValidIO(RW(0))
283}
284
285class SipToHvip extends ToAliasIpLocalPart {
286
287}
288
289class HieToMie extends IeValidBundle {
290  this.getVS.foreach(_.bits.setRW())
291  this.SGEIE.bits.setRW()
292}
293
294class HvictlBundle extends CSRBundle {
295  // Virtual Trap Interrupt control
296  val VTI = RW(30).withReset(0.U)
297  // WARL in AIA spec.
298  // RW, since we support max width of IID
299  val IID = RW(15 + HIIDWidth, 16).withReset(0.U)
300  // determines the interrupt’s presumed default priority order relative to a (virtual) supervisor external interrupt (SEI), major identity 9
301  // 0 = interrupt has higher default priority than an SEI
302  // 1 = interrupt has lower default priority than an SEI
303  // When hvictl.IID = 9, DPR is ignored.
304  // Todo: sort the interrupt specified by hvictl with DPR
305  val DPR = RW(9).withReset(0.U)
306  val IPRIOM = RW(8).withReset(0.U)
307  val IPRIO = RW(7, 0).withReset(0.U)
308}
309
310class Hviprio1Bundle extends CSRBundle {
311  val PrioSSI = RW(15,  8).withReset(0.U)
312  val PrioSTI = RW(31, 24).withReset(0.U)
313  val PrioCOI = RW(47, 40).withReset(0.U)
314  val Prio14  = RO(55, 48).withReset(0.U)
315  val Prio15  = RO(63, 56).withReset(0.U)
316}
317
318class Hviprio2Bundle extends CSRBundle {
319  val Prio16 = RO(7, 0).withReset(0.U)
320  val Prio17 = RO(15, 8).withReset(0.U)
321  val Prio18 = RO(23, 16).withReset(0.U)
322  val Prio19 = RO(31, 24).withReset(0.U)
323  val Prio20 = RO(39, 32).withReset(0.U)
324  val Prio21 = RO(47, 40).withReset(0.U)
325  val Prio22 = RO(55, 48).withReset(0.U)
326  val Prio23 = RO(63, 56).withReset(0.U)
327}
328
329class HgatpBundle extends CSRBundle {
330  val MODE = HgatpMode(63, 60, wNoFilter).withReset(HgatpMode.Bare)
331  // WARL in privileged spec.
332  // RW, since we support max width of VMID
333  val VMID = RW(44 - 1 + VMIDLEN, 44).withReset(0.U)
334  val PPN = RW(43, 0).withReset(0.U)
335}
336
337class HEnvCfg extends EnvCfg {
338  if (CSRConfig.EXT_SSTC) {
339    this.STCE.setRW().withReset(1.U)
340  }
341  // Always enable PBMT
342  this.PBMTE.setRO().withReset(1.U)
343}
344
345trait HypervisorBundle { self: CSRModule[_] =>
346  val hstatus = IO(Input(new HstatusBundle))
347}
348
349trait HasHypervisorEnvBundle { self: CSRModule[_] =>
350  val menvcfg = IO(Input(new MEnvCfg))
351  val privState = IO(Input(new PrivState))
352  val accessStimecmp = IO(Input(Bool()))
353}