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