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