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