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