xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/VirtualSupervisorLevel.scala (revision b03c55a5df5dc8793cb44b42dd60141566e57e78)
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      rdata := SignExt(Cat(reg.epc.asUInt, 0.U(1.W)), XLEN)
123    }
124  )
125    .setAddr(CSRs.vsepc)
126
127  val vscause = Module(
128    new CSRModule("VScause", new CauseBundle)
129      with TrapEntryVSEventSinkBundle
130  )
131    .setAddr(CSRs.vscause)
132
133  // Todo: shrink the width of vstval to the maximum width Virtual Address
134  val vstval = Module(
135    new CSRModule("VStval", new XtvalBundle)
136      with TrapEntryVSEventSinkBundle
137  )
138    .setAddr(CSRs.vstval)
139
140  val vsip = Module(new CSRModule("VSip", new VSipBundle)
141    with HypervisorBundle
142    with HasIpIeBundle
143  {
144    val toMip  = IO(new VSipToMip).connectZeroNonRW
145    val toMvip = IO(new VSipToMvip).connectZeroNonRW
146    val toHvip = IO(new VSipToHvip).connectZeroNonRW
147
148    val originIP = mideleg & hideleg & mip | (~mideleg & hideleg & mvien & mvip) | (~hideleg & hvien & hvip)
149    val shiftedIP = Cat(originIP(63, InterruptNO.COI), 0.U(1.W), originIP(InterruptNO.SGEI, InterruptNO.SSI))
150
151    regOut := shiftedIP
152    regOut.getM.foreach(_ := 0.U)
153    regOut.getVS.foreach(_ := 0.U)
154    regOut.SGEIP := 0.U
155
156    toHvip.VSSIP.valid := wen && hideleg.VSSI
157    toHvip.VSSIP.bits  := wdata.SSIP
158
159    wdata.getLocal lazyZip
160      (toMip.getLocal lazyZip toMvip.getLocal lazyZip toHvip.getLocal) lazyZip
161      (mideleg.getLocal lazyZip hideleg.getLocal lazyZip mvien.getLocal) foreach {
162        case (wLCIP, (toMipLCIP, toMvipLCIP, toHvipLCIP), (midelegBit, hidelegBit, mvienBit)) =>
163          toMipLCIP .valid := wen &&  midelegBit &&  hidelegBit
164          toMvipLCIP.valid := wen && !midelegBit &&  hidelegBit &&  mvienBit
165          toHvipLCIP.valid := wen &&                !hidelegBit &&  mvienBit
166          toMipLCIP .bits := wLCIP
167          toMvipLCIP.bits := wLCIP
168          toHvipLCIP.bits := wLCIP
169    }
170
171    regOut.getFields.foreach { field =>
172      if (field.isHardWired) {
173        field := field.getHardWireValue
174      }
175    }
176  }).setAddr(CSRs.vsip)
177
178  val vstimecmp = Module(new CSRModule("VStimecmp", new CSRBundle {
179    val vstimecmp = RW(63, 0).withReset(bitPatToUInt(BitPat.Y(64)))
180  }))
181    .setAddr(CSRs.vstimecmp)
182
183  val vsatp = Module(new CSRModule("VSatp", new SatpBundle) with VirtualSupervisorBundle {
184    val ppnMask = Fill(PPNLength, 1.U(1.W))
185    val ppnMaskHgatpIsBare   = ZeroExt(ppnMask.take(PAddrBits - PageOffsetWidth), PPNLength)
186    val ppnMaskHgatpIsSv39x4 = ZeroExt(ppnMask.take(39 + 2    - PageOffsetWidth), PPNLength)
187    val ppnMaskHgatpIsSv48x4 = ZeroExt(ppnMask.take(48 + 2    - PageOffsetWidth), PPNLength)
188
189    val effectivePPNMask = Mux1H(Seq(
190      (hgatp.MODE === HgatpMode.Bare)   -> ppnMaskHgatpIsBare,
191      (hgatp.MODE === HgatpMode.Sv39x4) -> ppnMaskHgatpIsSv39x4,
192      (hgatp.MODE === HgatpMode.Sv48x4) -> ppnMaskHgatpIsSv48x4,
193    ))
194    // Ref: 13.2.18. Virtual Supervisor Address Translation and Protection Register (vsatp)
195    // When V=0, a write to vsatp with an unsupported MODE value is either ignored as it is for satp, or the
196    // fields of vsatp are treated as WARL in the normal way.
197    // However, when V=1, a write to satp with an unsupported MODE value is ignored and no write to vsatp is effected.
198    // if satp is written with an unsupported MODE, the entire write has no effect; no fields in satp are modified.
199    //
200    // We treat all circumstances as if V=1. That is if vsatp is written with an unsupported MODE,
201    // the entire write has no effect; no fields in satp are modified.
202    when(wen && wdata.MODE.isLegal) {
203      reg := wdata
204      reg.PPN := wdata.PPN & effectivePPNMask
205    }.elsewhen(wen && !v && !wdata.MODE.isLegal) {
206      reg.PPN := wdata.PPN & effectivePPNMask
207      reg.ASID := wdata.ASID
208    }.otherwise {
209      reg := reg
210    }
211  }).setAddr(CSRs.vsatp)
212
213  val virtualSupervisorCSRMods = Seq(
214    vsstatus,
215    vsie,
216    vstvec,
217    vsscratch,
218    vsepc,
219    vscause,
220    vstval,
221    vsip,
222    vstimecmp,
223    vsatp,
224  )
225
226  virtualSupervisorCSRMods.foreach(mod =>
227    require(mod.addr > 0, s"The address of ${mod.modName} has not been set, you can use setAddr(CSRAddr) to set it."))
228
229  val virtualSupervisorCSRMap: SeqMap[Int, (CSRAddrWriteBundle[_], UInt)] = SeqMap.from(
230    virtualSupervisorCSRMods.map(csr => (csr.addr -> (csr.w -> csr.rdata)))
231  )
232
233  val virtualSupervisorCSROutMap: SeqMap[Int, UInt] = SeqMap.from(
234    virtualSupervisorCSRMods.map(csr => (csr.addr -> csr.regOut.asInstanceOf[CSRBundle].asUInt))
235  )
236
237  import freechips.rocketchip.rocket.CSRs
238
239  val sMapVS = SeqMap(
240    CSRs.sstatus  -> CSRs.vsstatus,
241    CSRs.sie      -> CSRs.vsie,
242    CSRs.stvec    -> CSRs.vstvec,
243    CSRs.sscratch -> CSRs.vsscratch,
244    CSRs.sepc     -> CSRs.vsepc,
245    CSRs.scause   -> CSRs.vscause,
246    CSRs.stval    -> CSRs.vstval,
247    CSRs.sip      -> CSRs.vsip,
248    CSRs.stimecmp -> CSRs.vstimecmp,
249    CSRs.siselect -> CSRs.vsiselect,
250    CSRs.sireg    -> CSRs.vsireg,
251    CSRs.stopei   -> CSRs.vstopei,
252    CSRs.satp     -> CSRs.vsatp,
253    CSRs.stopi    -> CSRs.vstopi,
254  )
255
256  val vsMapS: SeqMap[Int, Int] = SeqMap.from(sMapVS.map(x => (x._2 -> x._1)))
257}
258
259class VSipBundle extends InterruptPendingBundle {
260  // All pending bits in vsip are aliases of mip/mvip/hvip or read-only 0
261  this.getM.foreach(_.setHardWired(0.U))
262  this.getVS.foreach(_.setHardWired(0.U))
263  this.SGEIP.setHardWired(0.U)
264}
265
266class VSieBundle extends InterruptEnableBundle {
267  this.getLocal.foreach(_.setRW().withReset(0.U))
268  this.getM .foreach(_.setHardWired(0.U))
269  this.getVS.foreach(_.setHardWired(0.U))
270  this.SGEIE.setHardWired(0.U)
271}
272
273class VSipToMvip extends IpValidBundle {
274  this.getLocal.foreach(_.bits.setRW())
275}
276
277class VSipToHvip extends IpValidBundle {
278  this.VSSIP.bits.setRW()
279  this.getLocal.foreach(_.bits.setRW())
280}
281
282class VSieToMie extends IeValidBundle {
283  this.getVS.foreach(_.bits.setRW())
284  this.getLocal.foreach(_.bits.setRW())
285}
286
287class VSieToSie extends IeValidBundle {
288  this.getVS.foreach(_.bits.setRW())
289  this.getLocal.foreach(_.bits.setRW())
290}
291
292class VSipToHip extends Bundle {
293  val SSIP = ValidIO(RW(0))
294  val STIP = ValidIO(RW(0))
295  val SEIP = ValidIO(RW(0))
296}
297
298trait VirtualSupervisorBundle { self: CSRModule[_] =>
299  val v = IO(Input(Bool()))
300  val hgatp = IO(Input(new HgatpBundle))
301}
302