xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/VirtualSupervisorLevel.scala (revision 211d620b07edb797ba35b635d24fef4e7294bae2)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util.BitPat.bitPatToUInt
5import chisel3.util._
6import freechips.rocketchip.rocket.CSRs
7import utility.{SignExt, ZeroExt}
8import xiangshan.backend.fu.NewCSR.CSRBundles._
9import xiangshan.backend.fu.NewCSR.CSRDefines.{VirtMode, CSRROField => RO, CSRRWField => RW, CSRWARLField => WARL, CSRWLRLField => WLRL, _}
10import xiangshan.backend.fu.NewCSR.CSREvents.{SretEventSinkBundle, MretEventSinkBundle, MNretEventSinkBundle, TrapEntryVSEventSinkBundle}
11import xiangshan.backend.fu.NewCSR.CSREnumTypeImplicitCast._
12import xiangshan.backend.fu.NewCSR.CSRBundleImplicitCast._
13import xiangshan.backend.fu.NewCSR.CSRConfig.PPNLength
14import xiangshan.backend.fu.NewCSR.ChiselRecordForField._
15
16import scala.collection.immutable.SeqMap
17
18trait VirtualSupervisorLevel { self: NewCSR with SupervisorLevel with HypervisorLevel =>
19
20  val vsstatus = Module(
21    new CSRModule("VSstatus", new SstatusBundle)
22      with SretEventSinkBundle
23      with MretEventSinkBundle
24      with MNretEventSinkBundle
25      with TrapEntryVSEventSinkBundle
26      with HasRobCommitBundle
27      with HasVirtualSupervisorEnvBundle
28    {
29      when ((robCommit.fsDirty || writeFCSR) && isVirtMode) {
30        assert(reg.FS =/= ContextStatus.Off, "The vsstatus.FS should not be Off when set dirty, please check decode")
31        reg.FS := ContextStatus.Dirty
32      }
33
34      when ((robCommit.vsDirty || writeVCSR) && isVirtMode) {
35        assert(reg.VS =/= ContextStatus.Off, "The vsstatus.VS should not be Off when set dirty, please check decode")
36        reg.VS := ContextStatus.Dirty
37      }
38      // when menvcfg or henvcfg.DTE close,  vsstatus.SDT is read-only
39      val writeSDT = Wire(Bool())
40      writeSDT := Mux(this.menvcfg.DTE && this.henvcfg.DTE, w.wdataFields.SDT.asBool, 0.U)
41      when (!(this.menvcfg.DTE && this.henvcfg.DTE)) {
42        regOut.SDT := false.B
43      }
44      // SDT and SIE is the same as mstatus
45      when (writeSDT && w.wen ) {
46        reg.SIE := false.B
47      }
48
49    }
50  )
51    .setAddr(CSRs.vsstatus)
52
53  val vsie = Module(new CSRModule("VSie", new VSieBundle)
54    with HypervisorBundle
55    with HasIpIeBundle
56  {
57    val toMie = IO(new VSieToMie)
58    val toSie = IO(new VSieToSie)
59
60    val mieIsAlias =  hideleg &  mideleg
61    val sieIsAlias =  hideleg & ~mideleg & mvien
62    val usingReg   = ~hideleg &            hvien
63
64    val originAliasIE = (mieIsAlias & mie) | (sieIsAlias & sie)
65    val shiftedIE = Cat(originAliasIE(63, InterruptNO.COI), 0.U(1.W), originAliasIE(InterruptNO.SGEI, InterruptNO.SSI))
66    val shiftedUsingReg = Cat(usingReg(63, InterruptNO.COI), 0.U(1.W), usingReg(InterruptNO.SGEI, InterruptNO.SSI))
67
68    regOut :=
69      shiftedIE |
70      (shiftedUsingReg & reg)
71
72    bundle.getVS.map(_.lsb).foreach { vsNum =>
73      // vsie.SSIE(1) map mie.VSSIE(1)
74      val sNum = vsNum - 1
75      val wtMie = toMie.getByNum(vsNum)
76      val wtSie = toSie.getByNum(vsNum)
77      val r = reg(sNum)
78
79      wtMie.specifyField(
80        _.valid := mieIsAlias(vsNum) && wtMie.bits.isRW.B && wen,
81        _.bits  := mieIsAlias(vsNum) && wtMie.bits.isRW.B && wen &< wdata(sNum),
82      )
83
84      wtSie.specifyField(
85        _.valid := sieIsAlias(vsNum) && wtSie.bits.isRW.B && wen,
86        _.bits  := sieIsAlias(vsNum) && wtSie.bits.isRW.B && wen &< wdata(sNum),
87      )
88
89      when (wen && usingReg(vsNum) && r.isRW.B) {
90        r := wdata(sNum)
91      }.otherwise {
92        r := r
93      }
94    }
95
96    bundle.getNonVS.map(_.lsb).foreach { num =>
97      val wtMie = toMie.getByNum(num)
98      val wtSie = toSie.getByNum(num)
99
100      val r = reg(num)
101
102      wtMie.specifyField(
103        _.valid := mieIsAlias(num) && wtMie.bits.isRW.B && wen,
104        _.bits  := mieIsAlias(num) && wtMie.bits.isRW.B && wen &< wdata(num),
105      )
106
107      wtSie.specifyField(
108        _.valid := sieIsAlias(num) && wtSie.bits.isRW.B && wen,
109        _.bits  := sieIsAlias(num) && wtSie.bits.isRW.B && wen &< wdata(num),
110      )
111
112      when(wen && usingReg(num) && r.isRW.B) {
113        r := wdata(num)
114      }.otherwise {
115        r := r
116      }
117    }
118
119    regOut.getFields.foreach { field =>
120      if (field.isHardWired) {
121        field := field.getHardWireValue
122      }
123    }
124  }).setAddr(CSRs.vsie)
125
126  val vstvec = Module(new CSRModule("VStvec", new XtvecBundle))
127    .setAddr(CSRs.vstvec)
128
129  val vsscratch = Module(new CSRModule("VSscratch"))
130    .setAddr(CSRs.vsscratch)
131
132  val vsepc = Module(
133    new CSRModule("VSepc", new Epc)
134      with TrapEntryVSEventSinkBundle
135  )
136    .setAddr(CSRs.vsepc)
137
138  val vscause = Module(
139    new CSRModule("VScause", new CauseBundle)
140      with TrapEntryVSEventSinkBundle
141  )
142    .setAddr(CSRs.vscause)
143
144  // Todo: shrink the width of vstval to the maximum width Virtual Address
145  val vstval = Module(
146    new CSRModule("VStval", new XtvalBundle)
147      with TrapEntryVSEventSinkBundle
148  )
149    .setAddr(CSRs.vstval)
150
151  val vsip = Module(new CSRModule("VSip", new VSipBundle)
152    with HypervisorBundle
153    with HasIpIeBundle
154  {
155    val toMip  = IO(new VSipToMip).connectZeroNonRW
156    val toMvip = IO(new VSipToMvip).connectZeroNonRW
157    val toHvip = IO(new VSipToHvip).connectZeroNonRW
158
159    val originIP = mideleg & hideleg & mip | (~mideleg & hideleg & mvien & mvip) | (~hideleg & hvien & hvip)
160    val shiftedIP = Cat(originIP(63, InterruptNO.COI), 0.U(1.W), originIP(InterruptNO.SGEI, InterruptNO.SSI))
161
162    regOut := shiftedIP
163    regOut.getM.foreach(_ := 0.U)
164    regOut.getVS.foreach(_ := 0.U)
165    regOut.SGEIP := 0.U
166
167    toHvip.VSSIP.valid := wen && hideleg.VSSI
168    toHvip.VSSIP.bits  := wdata.SSIP
169
170    wdata.getLocal lazyZip
171      (toMip.getLocal lazyZip toMvip.getLocal lazyZip toHvip.getLocal) lazyZip
172      (mideleg.getLocal lazyZip hideleg.getLocal lazyZip mvien.getLocal lazyZip hvien.getLocal) foreach {
173        case (wLCIP, (toMipLCIP, toMvipLCIP, toHvipLCIP), (midelegBit, hidelegBit, mvienBit, hvienBit)) =>
174          toMipLCIP .valid := wen &&  hidelegBit &&  midelegBit
175          toMvipLCIP.valid := wen &&  hidelegBit && !midelegBit &&  mvienBit
176          toHvipLCIP.valid := wen && !hidelegBit &&                 hvienBit
177          toMipLCIP .bits := wLCIP
178          toMvipLCIP.bits := wLCIP
179          toHvipLCIP.bits := wLCIP
180    }
181
182    regOut.getFields.foreach { field =>
183      if (field.isHardWired) {
184        field := field.getHardWireValue
185      }
186    }
187  }).setAddr(CSRs.vsip)
188
189  val vstimecmp = Module(new CSRModule("VStimecmp", new CSRBundle {
190    val vstimecmp = RW(63, 0).withReset(bitPatToUInt(BitPat.Y(64)))
191  }))
192    .setAddr(CSRs.vstimecmp)
193
194  val vsatp = Module(new CSRModule("VSatp", new SatpBundle) with VirtualSupervisorBundle {
195    val ppnMask = Fill(PPNLength, 1.U(1.W))
196    val ppnMaskHgatpIsBare   = ZeroExt(ppnMask.take(PAddrBits - PageOffsetWidth), PPNLength)
197    val ppnMaskHgatpIsSv39x4 = ZeroExt(ppnMask.take(39 + 2    - PageOffsetWidth), PPNLength)
198    val ppnMaskHgatpIsSv48x4 = ZeroExt(ppnMask.take(48 + 2    - PageOffsetWidth), PPNLength)
199
200    val effectivePPNMask = Mux1H(Seq(
201      (hgatp.MODE === HgatpMode.Bare)   -> ppnMaskHgatpIsBare,
202      (hgatp.MODE === HgatpMode.Sv39x4) -> ppnMaskHgatpIsSv39x4,
203      (hgatp.MODE === HgatpMode.Sv48x4) -> ppnMaskHgatpIsSv48x4,
204    ))
205    // Ref: 13.2.18. Virtual Supervisor Address Translation and Protection Register (vsatp)
206    // When V=0, a write to vsatp with an unsupported MODE value is either ignored as it is for satp, or the
207    // fields of vsatp are treated as WARL in the normal way.
208    // However, when V=1, a write to satp with an unsupported MODE value is ignored and no write to vsatp is effected.
209    // if satp is written with an unsupported MODE, the entire write has no effect; no fields in satp are modified.
210    //
211    // We treat all circumstances as if V=1. That is if vsatp is written with an unsupported MODE,
212    // the entire write has no effect; no fields in satp are modified.
213    when(wen && wdata.MODE.isLegal) {
214      reg := wdata
215      reg.PPN := wdata.PPN & effectivePPNMask
216    }.elsewhen(wen && !v && !wdata.MODE.isLegal) {
217      reg.PPN := wdata.PPN & effectivePPNMask
218      reg.ASID := wdata.ASID
219    }.otherwise {
220      reg := reg
221    }
222  }).setAddr(CSRs.vsatp)
223
224  val virtualSupervisorCSRMods = Seq(
225    vsstatus,
226    vsie,
227    vstvec,
228    vsscratch,
229    vsepc,
230    vscause,
231    vstval,
232    vsip,
233    vstimecmp,
234    vsatp,
235  )
236
237  virtualSupervisorCSRMods.foreach(mod =>
238    require(mod.addr > 0, s"The address of ${mod.modName} has not been set, you can use setAddr(CSRAddr) to set it."))
239
240  val virtualSupervisorCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from(
241    virtualSupervisorCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata)))
242  )
243
244  val virtualSupervisorCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
245    virtualSupervisorCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt))
246  )
247
248  import freechips.rocketchip.rocket.CSRs
249
250  val sMapVS = SeqMap(
251    CSRs.sstatus  -> CSRs.vsstatus,
252    CSRs.sie      -> CSRs.vsie,
253    CSRs.stvec    -> CSRs.vstvec,
254    CSRs.sscratch -> CSRs.vsscratch,
255    CSRs.sepc     -> CSRs.vsepc,
256    CSRs.scause   -> CSRs.vscause,
257    CSRs.stval    -> CSRs.vstval,
258    CSRs.sip      -> CSRs.vsip,
259    CSRs.stimecmp -> CSRs.vstimecmp,
260    CSRs.siselect -> CSRs.vsiselect,
261    CSRs.sireg    -> CSRs.vsireg,
262    CSRs.stopei   -> CSRs.vstopei,
263    CSRs.satp     -> CSRs.vsatp,
264    CSRs.stopi    -> CSRs.vstopi,
265  )
266
267  val vsMapS: SeqMap[Int, Int] = SeqMap.from(sMapVS.map(x => (x._2 -> x._1)))
268}
269
270class VSipBundle extends InterruptPendingBundle {
271  // All pending bits in vsip are aliases of mip/mvip/hvip or read-only 0
272  this.getM.foreach(_.setHardWired(0.U))
273  this.getVS.foreach(_.setHardWired(0.U))
274  this.SGEIP.setHardWired(0.U)
275}
276
277class VSieBundle extends InterruptEnableBundle {
278  this.getLocal.foreach(_.setRW().withReset(0.U))
279  this.getM .foreach(_.setHardWired(0.U))
280  this.getVS.foreach(_.setHardWired(0.U))
281  this.SGEIE.setHardWired(0.U)
282}
283
284class VSipToMvip extends IpValidBundle {
285  this.getLocal.foreach(_.bits.setRW())
286}
287
288class VSipToHvip extends IpValidBundle {
289  this.VSSIP.bits.setRW()
290  this.getLocal.foreach(_.bits.setRW())
291}
292
293class VSieToMie extends IeValidBundle {
294  this.getVS.foreach(_.bits.setRW())
295  this.getLocal.foreach(_.bits.setRW())
296}
297
298class VSieToSie extends IeValidBundle {
299  this.getVS.foreach(_.bits.setRW())
300  this.getLocal.foreach(_.bits.setRW())
301}
302
303class VSipToHip extends Bundle {
304  val SSIP = ValidIO(RW(0))
305  val STIP = ValidIO(RW(0))
306  val SEIP = ValidIO(RW(0))
307}
308
309trait VirtualSupervisorBundle { self: CSRModule[_] =>
310  val v = IO(Input(Bool()))
311  val hgatp = IO(Input(new HgatpBundle))
312}
313
314trait HasVirtualSupervisorEnvBundle { self: CSRModule[_] =>
315  val menvcfg = IO(Input(new MEnvCfg))
316  val henvcfg = IO(Input(new HEnvCfg))
317}
318