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