xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala (revision 4d2be3d2958a62ef325ed813d1a12c12971d6572)
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) = (
24    io.in.mret,
25    io.in.sret,
26  )
27
28  private val (tsr, vtsr) = (
29    io.in.status.tsr,
30    io.in.status.vtsr,
31  )
32
33  private val (tw, vtw) = (
34    io.in.status.tw,
35    io.in.status.vtw
36  )
37
38  private val (tvm, vtvm) = (
39    io.in.status.tvm,
40    io.in.status.vtvm,
41  )
42
43  private val csrIsCustom = io.in.csrIsCustom
44
45  private val (mcounteren, hcounteren, scounteren) = (
46    io.in.status.mcounteren,
47    io.in.status.hcounteren,
48    io.in.status.scounteren,
49  )
50
51  private val (mcounterenTM, hcounterenTM) = (
52    mcounteren(1),
53    hcounteren(1),
54  )
55
56  private val (menvcfg, henvcfg) = (
57    io.in.status.menvcfg,
58    io.in.status.henvcfg,
59  )
60
61  private val (menvcfgSTCE, henvcfgSTCE) = (
62    menvcfg(63),
63    henvcfg(63),
64  )
65
66  private val (sFS, vsFS) = (
67    io.in.status.sstatusFS,
68    io.in.status.vsstatusFS,
69  )
70
71  private val (sVS, vsVS) = (
72    io.in.status.sstatusVS,
73    io.in.status.vsstatusVS,
74  )
75
76  private val fsDirty = io.in.status.fsDirty
77  private val vsDirty = io.in.status.vsDirty
78
79  private val (sFSIsOff, sVSIsOff) = (
80    sFS === ContextStatus.Off.asUInt,
81    sVS === ContextStatus.Off.asUInt,
82  )
83  private val (sOrVsFSIsOff, sOrVsVSIsOff) = (
84    sFSIsOff || vsFS === ContextStatus.Off.asUInt,
85    sVSIsOff || vsVS === ContextStatus.Off.asUInt,
86  )
87
88  private val csrIsRO = addr(11, 10) === "b11".U
89  private val csrIsUnpriv = addr(9, 8) === "b00".U
90  private val csrIsHPM = addr >= CSRs.cycle.U && addr <= CSRs.hpmcounter31.U
91  private val wenFpCsr  = wen && Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _)
92  private val wenVecCsr = wen && Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _)
93  private val counterAddr = addr(4, 0) // 32 counters
94
95  private val accessTable = TruthTable(Seq(
96    //       V PRVM ADDR
97    BitPat("b0__00___00") -> BitPat.Y(), // HU access U
98    BitPat("b1__00___00") -> BitPat.Y(), // VU access U
99    BitPat("b0__01___00") -> BitPat.Y(), // HS access U
100    BitPat("b0__01___01") -> BitPat.Y(), // HS access S
101    BitPat("b0__01___10") -> BitPat.Y(), // HS access H
102    BitPat("b1__01___00") -> BitPat.Y(), // VS access U
103    BitPat("b1__01___01") -> BitPat.Y(), // VS access S
104    BitPat("b0__11___00") -> BitPat.Y(), // M  access HU
105    BitPat("b0__11___01") -> BitPat.Y(), // M  access HS
106    BitPat("b0__11___10") -> BitPat.Y(), // M  access H
107    BitPat("b0__11___11") -> BitPat.Y(), // M  access M
108  ), BitPat.N())
109
110  private val regularPrivilegeLegal = chisel3.util.experimental.decode.decoder(
111    privState.V.asUInt ## privState.PRVM.asUInt ## addr(9, 8),
112    accessTable
113  ).asBool
114
115  private val isDebugReg   = addr(11, 4) === "h7b".U
116  private val privilegeLegal = Mux(isDebugReg, debugMode, regularPrivilegeLegal || debugMode)
117
118  private val rwIllegal = csrIsRO && wen
119
120  private val csrAccessIllegal = (!privilegeLegal || rwIllegal)
121
122  private val mret_EX_II = mret && !privState.isModeM
123  private val mret_EX_VI = false.B
124  private val mretIllegal = mret_EX_II || mret_EX_VI
125
126  private val sret_EX_II = sret && (privState.isModeHU || privState.isModeHS && tsr)
127  private val sret_EX_VI = sret && (privState.isModeVU || privState.isModeVS && vtsr)
128  private val sretIllegal = sret_EX_II || sret_EX_VI
129
130  private val rwSatp_EX_II = csrAccess && privState.isModeHS &&  tvm && (addr === CSRs.satp.U || addr === CSRs.hgatp.U)
131  private val rwSatp_EX_VI = csrAccess && privState.isModeVS && vtvm && (addr === CSRs.satp.U)
132
133  private val rwCustom_EX_II = csrAccess && privState.isModeVS && csrIsCustom
134
135  private val accessHPM = ren && csrIsHPM
136  private val accessHPM_EX_II = accessHPM && (
137    !privState.isModeM && !mcounteren(counterAddr) ||
138    privState.isModeHU && !scounteren(counterAddr)
139  )
140  private val accessHPM_EX_VI = accessHPM && mcounteren(counterAddr) && (
141    privState.isModeVS && !hcounteren(counterAddr) ||
142    privState.isModeVU && (!hcounteren(counterAddr) || !scounteren(counterAddr))
143  )
144
145  private val rwStimecmp_EX_II = csrAccess && ((privState.isModeHS && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.vstimecmp.U ||
146    ((privState.isModeHS || privState.isModeVS) && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.stimecmp.U)
147  private val rwStimecmp_EX_VI = csrAccess && privState.isModeVS && (mcounterenTM && !hcounterenTM || menvcfgSTCE && !henvcfgSTCE) && addr === CSRs.stimecmp.U
148
149  private val FSIsOFF_EX_II = fsDirty && (!privState.isVirtual && sFSIsOff || privState.isVirtual && sOrVsFSIsOff)
150  private val VSIsOFF_EX_II = vsDirty && (!privState.isVirtual && sVSIsOff || privState.isVirtual && sOrVsVSIsOff)
151
152  private val FSOrVS_EX_II = FSIsOFF_EX_II || VSIsOFF_EX_II
153
154  private val wFp_EX_II  = wenFpCsr  && sOrVsFSIsOff
155  private val wVec_EX_II = wenVecCsr && sOrVsVSIsOff
156
157  private val wFpOrVec_EX_II = wFp_EX_II || wVec_EX_II
158
159  io.out.illegal := csrAccess && csrAccessIllegal || mretIllegal
160
161  // Todo: check correct
162  io.out.EX_II := io.out.illegal && !privState.isVirtual || mret_EX_II || sret_EX_II || rwSatp_EX_II || accessHPM_EX_II || rwStimecmp_EX_II || rwCustom_EX_II || FSOrVS_EX_II || wFpOrVec_EX_II
163  io.out.EX_VI := io.out.illegal &&  privState.isVirtual || mret_EX_VI || sret_EX_VI || rwSatp_EX_VI || accessHPM_EX_VI || rwStimecmp_EX_VI
164
165  io.out.hasLegalWen := wen && !csrAccessIllegal
166  io.out.hasLegalMret := mret && !mretIllegal
167  io.out.hasLegalSret := sret && !sretIllegal
168
169  io.out.hasLegalFp  := wenFpCsr  && !wFp_EX_II
170  io.out.hasLegalVec := wenVecCsr && !wVec_EX_II
171  dontTouch(regularPrivilegeLegal)
172}
173
174class CSRPermitIO extends Bundle {
175  val in = Input(new Bundle {
176    val csrAccess = new Bundle {
177      val ren = Bool()
178      val wen = Bool()
179      val addr = UInt(12.W)
180    }
181    val privState = new PrivState
182    val debugMode = Bool()
183    val mret = Bool()
184    val sret = Bool()
185    val csrIsCustom = Bool()
186    val status = new Bundle {
187      // Trap SRET
188      val tsr = Bool()
189      // Virtual Trap SRET
190      val vtsr = Bool()
191      // Timeout Wait
192      val tw = Bool()
193      // Virtual Timeout Wait
194      val vtw = Bool()
195      // Trap Virtual Memory
196      val tvm = Bool()
197      // Virtual Trap Virtual Memory
198      val vtvm = Bool()
199      // Machine level counter enable, access PMC from the level less than M will trap EX_II
200      val mcounteren = UInt(32.W)
201      // Hypervisor level counter enable.
202      // Accessing PMC from VS/VU level will trap EX_VI, if m[x]=1 && h[x]=0
203      val hcounteren = UInt(32.W)
204      // Supervisor level counter enable.
205      // Accessing PMC from **HU level** will trap EX_II, if s[x]=0
206      // Accessing PMC from **VU level** will trap EX_VI, if m[x]=1 && h[x]=1 && s[x]=0
207      val scounteren = UInt(32.W)
208      // Machine environment configuration register.
209      // Accessing stimecmp or vstimecmp from **Non-M level** will trap EX_II, if menvcfg.STCE=0
210      val menvcfg = UInt(64.W)
211      // Hypervisor environment configuration register.
212      // Accessing vstimecmp from ** V level** will trap EX_VI, if menvcfg.STCE=1 && henvcfg.STCE=0
213      val henvcfg = UInt(64.W)
214      // sstatus.FS
215      val sstatusFS = UInt(2.W)
216      // vsstatus.FS
217      val vsstatusFS = UInt(2.W)
218      // sstatus.VS
219      val sstatusVS = UInt(2.W)
220      // vsstatus.VS
221      val vsstatusVS = UInt(2.W)
222      // execute fp inst
223      val fsDirty = Bool()
224      // execute vec inst
225      val vsDirty = Bool()
226    }
227  })
228
229  val out = Output(new Bundle {
230    val hasLegalWen  = Bool()
231    val hasLegalMret = Bool()
232    val hasLegalSret = Bool()
233    val hasLegalFp   = Bool()
234    val hasLegalVec  = Bool()
235    // Todo: split illegal into EX_II and EX_VI
236    val illegal = Bool()
237    val EX_II = Bool()
238    val EX_VI = Bool()
239  })
240}
241