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