xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala (revision 26033c52423227b765eaa12b5d2a2a1dd983ff14)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import chisel3.util.experimental.decode.TruthTable
6import freechips.rocketchip.rocket.CSRs
7import xiangshan.backend.fu.NewCSR.CSRBundles.{Counteren, PrivState}
8import xiangshan.backend.fu.NewCSR.CSRDefines._
9
10class CSRPermitModule extends Module {
11  val io = IO(new CSRPermitIO)
12
13  private val (ren, wen, addr, privState, debugMode) = (
14    io.in.csrAccess.ren,
15    io.in.csrAccess.wen,
16    io.in.csrAccess.addr,
17    io.in.privState,
18    io.in.debugMode
19  )
20
21  private val csrAccess = WireInit(ren || wen)
22
23  private val (mret, sret, dret) = (
24    io.in.mret,
25    io.in.sret,
26    io.in.dret,
27  )
28
29  private val (tsr, vtsr) = (
30    io.in.status.tsr,
31    io.in.status.vtsr,
32  )
33
34  private val (tw, vtw) = (
35    io.in.status.tw,
36    io.in.status.vtw
37  )
38
39  private val (tvm, vtvm) = (
40    io.in.status.tvm,
41    io.in.status.vtvm,
42  )
43
44  private val csrIsCustom = io.in.csrIsCustom
45
46  private val (mcounteren, hcounteren, scounteren) = (
47    io.in.status.mcounteren,
48    io.in.status.hcounteren,
49    io.in.status.scounteren,
50  )
51
52  private val (mstateen0, hstateen0, sstateen0) = (
53    io.in.status.mstateen0,
54    io.in.status.hstateen0,
55    io.in.status.sstateen0,
56  )
57
58  private val (mcounterenTM, hcounterenTM) = (
59    mcounteren(1),
60    hcounteren(1),
61  )
62
63  private val (menvcfg, henvcfg) = (
64    io.in.status.menvcfg,
65    io.in.status.henvcfg,
66  )
67
68  private val (menvcfgSTCE, henvcfgSTCE) = (
69    menvcfg(63),
70    henvcfg(63),
71  )
72
73  private val (sFSIsOff, sVSIsOff, sOrVsFSIsOff, sOrVsVSIsOff) = (
74    io.in.status.mstatusFSOff,
75    io.in.status.mstatusVSOff,
76    io.in.status.mstatusFSOff || io.in.status.vsstatusFSOff,
77    io.in.status.mstatusVSOff || io.in.status.vsstatusVSOff,
78  )
79
80  private val csrIsRO = addr(11, 10) === "b11".U
81  private val csrIsUnpriv = addr(9, 8) === "b00".U
82  private val csrIsM = addr(9, 8) === "b11".U
83  private val csrIsHPM = addr >= CSRs.cycle.U && addr <= CSRs.hpmcounter31.U
84  private val csrIsFp = Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _)
85  private val csrIsVec = Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr, CSRs.vl, CSRs.vtype, CSRs.vlenb).map(_.U === addr).reduce(_ || _)
86  private val csrIsWritableVec = Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _)
87  private val counterAddr = addr(4, 0) // 32 counters
88
89  private val accessTable = TruthTable(Seq(
90    //       V PRVM ADDR
91    BitPat("b0__00___00") -> BitPat.Y(), // HU access U
92    BitPat("b1__00___00") -> BitPat.Y(), // VU access U
93    BitPat("b0__01___00") -> BitPat.Y(), // HS access U
94    BitPat("b0__01___01") -> BitPat.Y(), // HS access S
95    BitPat("b0__01___10") -> BitPat.Y(), // HS access H
96    BitPat("b1__01___00") -> BitPat.Y(), // VS access U
97    BitPat("b1__01___01") -> BitPat.Y(), // VS access S
98    BitPat("b0__11___00") -> BitPat.Y(), // M  access HU
99    BitPat("b0__11___01") -> BitPat.Y(), // M  access HS
100    BitPat("b0__11___10") -> BitPat.Y(), // M  access H
101    BitPat("b0__11___11") -> BitPat.Y(), // M  access M
102  ), BitPat.N())
103
104  private val regularPrivilegeLegal = chisel3.util.experimental.decode.decoder(
105    privState.V.asUInt ## privState.PRVM.asUInt ## addr(9, 8),
106    accessTable
107  ).asBool
108
109  private val isDebugReg   = addr(11, 4) === "h7b".U
110  private val privilegeLegal = Mux(isDebugReg, debugMode, regularPrivilegeLegal || debugMode)
111
112  private val rwIllegal = csrIsRO && wen
113
114  private val mret_EX_II = mret && !privState.isModeM
115  private val mret_EX_VI = false.B
116  private val mretIllegal = mret_EX_II || mret_EX_VI
117
118  private val sret_EX_II = sret && (privState.isModeHU || privState.isModeHS && tsr)
119  private val sret_EX_VI = sret && (privState.isModeVU || privState.isModeVS && vtsr)
120  private val sretIllegal = sret_EX_II || sret_EX_VI
121
122  private val dret_EX_II = dret && !debugMode
123  private val dretIllegal = dret_EX_II
124
125  private val rwSatp_EX_II = csrAccess && privState.isModeHS &&  tvm && (addr === CSRs.satp.U || addr === CSRs.hgatp.U)
126  private val rwSatp_EX_VI = csrAccess && privState.isModeVS && vtvm && (addr === CSRs.satp.U)
127
128  private val rwCustom_EX_II = csrAccess && privState.isModeVS && csrIsCustom
129
130  private val accessHPM = ren && csrIsHPM
131  private val accessHPM_EX_II = accessHPM && (
132    !privState.isModeM && !mcounteren(counterAddr) ||
133    privState.isModeHU && !scounteren(counterAddr)
134  )
135  private val accessHPM_EX_VI = accessHPM && mcounteren(counterAddr) && (
136    privState.isModeVS && !hcounteren(counterAddr) ||
137    privState.isModeVU && (!hcounteren(counterAddr) || !scounteren(counterAddr))
138  )
139
140  /**
141   * Sm/Ssstateen0 begin
142   */
143  // SE0 bit 63
144  private val csrIsHstateen0 = (addr === CSRs.hstateen0.U)
145  private val csrIsSstateen0 = (addr === CSRs.sstateen0.U)
146  private val csrIsStateen0 = csrIsHstateen0 || csrIsSstateen0
147  private val accessStateen0_EX_II = csrIsStateen0 && !privState.isModeM && !mstateen0.SE0.asBool
148  private val accessStateen0_EX_VI = csrIsSstateen0 && mstateen0.SE0.asBool && privState.isVirtual && !hstateen0.SE0.asBool ||
149    csrIsHstateen0 && mstateen0.SE0.asBool && privState.isVirtual
150
151  // ENVCFG bit 62
152  private val csrIsHenvcfg = (addr === CSRs.henvcfg.U)
153  private val csrIsSenvcfg = (addr === CSRs.senvcfg.U)
154  private val csrIsEnvcfg = csrIsHenvcfg || csrIsSenvcfg
155  private val accessEnvcfg_EX_II = csrIsEnvcfg && !privState.isModeM && !mstateen0.ENVCFG.asBool
156  private val accessEnvcfg_EX_VI = csrIsSenvcfg && mstateen0.ENVCFG.asBool && privState.isVirtual && !hstateen0.ENVCFG.asBool ||
157    csrIsHenvcfg && mstateen0.ENVCFG.asBool && privState.isVirtual
158
159  // CSRIND bit 60 indirect reg (Sscsrind extensions), this is not implemented
160  // csr addr S: [0x150, 0x157]     VS: [0x250, 0x257]
161  private val csrIsSi = addr.head(9) === CSRs.siselect.U.head(9)
162  private val csrIsVSi = addr.head(9) === CSRs.vsiselect.U.head(9)
163  private val csrIsIND = csrIsSi || csrIsVSi
164  private val accessIND_EX_II = csrIsIND && !privState.isModeM && !mstateen0.CSRIND.asBool
165  private val accessIND_EX_VI = csrIsSi && mstateen0.CSRIND.asBool && privState.isVirtual && !hstateen0.CSRIND.asBool ||
166    csrIsVSi && mstateen0.CSRIND.asBool && privState.isVirtual
167
168  // AIA bit 59
169  private val ssAiaHaddr = Seq(CSRs.hvien.U, CSRs.hvictl.U, CSRs.hviprio1.U, CSRs.hviprio2.U)
170  private val ssAiaVSaddr = addr === CSRs.vstopi.U
171  private val csrIsAIA = ssAiaHaddr.map(_ === addr).reduce(_ || _) || ssAiaVSaddr
172  private val accessAIA_EX_II = csrIsAIA && !privState.isModeM && !mstateen0.AIA.asBool
173  private val accessAIA_EX_VI = csrIsAIA && mstateen0.AIA.asBool && privState.isVirtual
174
175  // IMSIC bit 58 (Ssaia extension)
176  private val csrIsStopei = addr === CSRs.stopei.U
177  private val csrIsVStopei = addr === CSRs.vstopei.U
178  private val csrIsTpoie = csrIsStopei || csrIsVStopei
179  private val accessTopie_EX_II = csrIsTpoie && !privState.isModeM && !mstateen0.IMSIC.asBool
180  private val accessTopie_EX_VI = csrIsStopei && mstateen0.IMSIC.asBool && privState.isVirtual && !hstateen0.IMSIC.asBool ||
181    csrIsVStopei && mstateen0.IMSIC.asBool && privState.isVirtual
182
183  // CONTEXT bit 57 context reg (Sdtrig extensions), this is not implemented
184  private val csrIsHcontext = (addr === CSRs.hcontext.U)
185  private val csrIsScontext = (addr === CSRs.scontext.U)
186  private val csrIsContext = csrIsHcontext || csrIsScontext
187  private val accessContext_EX_II = csrIsContext && !privState.isModeM && !mstateen0.CONTEXT.asBool
188  private val accessContext_EX_VI = csrIsScontext && mstateen0.CONTEXT.asBool && privState.isVirtual && !hstateen0.CONTEXT.asBool ||
189    csrIsHcontext && mstateen0.CONTEXT.asBool && privState.isVirtual
190
191  // P1P13 bit 56, Read-only 0
192
193  // Custom bit 0
194  // csr addr HVS: [0x6c0, 0x6ff], [0xac0, 0xaff], [0xec0, 0xeff]
195  private val csrIsHVSCustom = (addr(11, 10) =/= "b00".U) && (addr(9, 8) === "b10".U) && (addr(7, 6) === "b11".U)
196  // [0x5c0, 0x5ff], [0x9c0, 0x9ff], [0xdc0, 0xdff]
197  private val csrIsSCustom   = (addr(11, 10) =/= "b00".U) && (addr(9, 8) === "b01".U) && (addr(7, 6) === "b11".U)
198  // [0x800, 0x8ff], [0xcc0, 0xcff]
199  private val csrIsUCustom   = (addr(11, 8) =/= "b1000".U) || (addr(11, 6) =/= "b100011".U)
200  private val allCustom      = csrIsHVSCustom || csrIsSCustom || csrIsUCustom
201  private val accessCustom_EX_II = allCustom && (
202    !privState.isModeM && !mstateen0.C.asBool ||
203      privState.isModeHU && !sstateen0.C.asBool
204  )
205  private val accessCustom_EX_VI = mstateen0.C.asBool && (
206    (csrIsSCustom || csrIsUCustom) && privState.isVirtual && !hstateen0.C.asBool ||
207      csrIsUCustom && privState.isModeVU && hstateen0.C.asBool && !sstateen0.C.asBool
208  )
209
210  val xstateControlAccess_EX_II = csrAccess && (accessStateen0_EX_II || accessEnvcfg_EX_II || accessIND_EX_II || accessAIA_EX_II ||
211    accessTopie_EX_II || accessContext_EX_II || accessCustom_EX_II)
212  val xstateControlAccess_EX_VI = csrAccess && (accessStateen0_EX_VI || accessEnvcfg_EX_VI || accessIND_EX_VI || accessAIA_EX_VI ||
213    accessTopie_EX_VI || accessContext_EX_VI || accessCustom_EX_VI)
214  /**
215   * Sm/Ssstateen end
216   */
217
218  private val rwStimecmp_EX_II = csrAccess && ((privState.isModeHS && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.vstimecmp.U ||
219    ((privState.isModeHS || privState.isModeVS) && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.stimecmp.U)
220  private val rwStimecmp_EX_VI = csrAccess && privState.isModeVS && (mcounterenTM && !hcounterenTM || menvcfgSTCE && !henvcfgSTCE) && addr === CSRs.stimecmp.U
221
222  private val fsEffectiveOff = sFSIsOff && !privState.isVirtual || sOrVsFSIsOff && privState.isVirtual
223  private val vsEffectiveOff = sVSIsOff && !privState.isVirtual || sOrVsVSIsOff && privState.isVirtual
224
225  private val fpOff_EX_II  = csrAccess && csrIsFp  && fsEffectiveOff
226  private val vecOff_EX_II = csrAccess && csrIsVec && vsEffectiveOff
227
228  private val fpVec_EX_II = fpOff_EX_II || vecOff_EX_II
229
230  private val csrAccessIllegal = (!privilegeLegal || rwIllegal)
231
232  // Todo: check correct
233  io.out.EX_II :=  csrAccess && !privilegeLegal && (!privState.isVirtual || privState.isVirtual && csrIsM) ||
234    rwIllegal || mret_EX_II || sret_EX_II || rwSatp_EX_II || accessHPM_EX_II ||
235    rwStimecmp_EX_II || rwCustom_EX_II || fpVec_EX_II || dret_EX_II || xstateControlAccess_EX_II
236  io.out.EX_VI := (csrAccess && !privilegeLegal && privState.isVirtual && !csrIsM ||
237    mret_EX_VI || sret_EX_VI || rwSatp_EX_VI || accessHPM_EX_VI || rwStimecmp_EX_VI) && !rwIllegal || xstateControlAccess_EX_VI
238
239  io.out.hasLegalWen  := wen  && !csrAccessIllegal
240  io.out.hasLegalMret := mret && !mretIllegal
241  io.out.hasLegalSret := sret && !sretIllegal
242  io.out.hasLegalDret := dret && !dretIllegal
243
244  io.out.hasLegalWriteFcsr := wen && csrIsFp && !fsEffectiveOff
245  io.out.hasLegalWriteVcsr := wen && csrIsWritableVec && !vsEffectiveOff
246
247  dontTouch(regularPrivilegeLegal)
248}
249
250class CSRPermitIO extends Bundle {
251  val in = Input(new Bundle {
252    val csrAccess = new Bundle {
253      val ren = Bool()
254      val wen = Bool()
255      val addr = UInt(12.W)
256    }
257    val privState = new PrivState
258    val debugMode = Bool()
259    val mret = Bool()
260    val sret = Bool()
261    val dret = Bool()
262    val csrIsCustom = Bool()
263    val status = new Bundle {
264      // Trap SRET
265      val tsr = Bool()
266      // Virtual Trap SRET
267      val vtsr = Bool()
268      // Timeout Wait
269      val tw = Bool()
270      // Virtual Timeout Wait
271      val vtw = Bool()
272      // Trap Virtual Memory
273      val tvm = Bool()
274      // Virtual Trap Virtual Memory
275      val vtvm = Bool()
276      // Machine level counter enable, access PMC from the level less than M will trap EX_II
277      val mcounteren = UInt(32.W)
278      // Hypervisor level counter enable.
279      // Accessing PMC from VS/VU level will trap EX_VI, if m[x]=1 && h[x]=0
280      val hcounteren = UInt(32.W)
281      // Supervisor level counter enable.
282      // Accessing PMC from **HU level** will trap EX_II, if s[x]=0
283      // Accessing PMC from **VU level** will trap EX_VI, if m[x]=1 && h[x]=1 && s[x]=0
284      val scounteren = UInt(32.W)
285      // Machine environment configuration register.
286      // Accessing stimecmp or vstimecmp from **Non-M level** will trap EX_II, if menvcfg.STCE=0
287      val menvcfg = UInt(64.W)
288      // Hypervisor environment configuration register.
289      // Accessing vstimecmp from ** V level** will trap EX_VI, if menvcfg.STCE=1 && henvcfg.STCE=0
290      val henvcfg = UInt(64.W)
291
292      val mstatusFSOff = Bool()
293      val vsstatusFSOff = Bool()
294      val mstatusVSOff = Bool()
295      val vsstatusVSOff = Bool()
296      // Sm/Ssstateen: to control state access
297      val mstateen0 = new MstateenBundle0
298      val hstateen0 = new HstateenBundle0
299      val sstateen0 = new SstateenBundle0
300    }
301  })
302
303  val out = Output(new Bundle {
304    val hasLegalWen  = Bool()
305    val hasLegalMret = Bool()
306    val hasLegalSret = Bool()
307    val hasLegalDret = Bool()
308    val hasLegalWriteFcsr = Bool()
309    val hasLegalWriteVcsr = Bool()
310    val EX_II = Bool()
311    val EX_VI = Bool()
312  })
313}
314