xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala (revision 5cfbb4960116bda40828fc388c78a9133bd2be59)
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 (sFSIsOff, sVSIsOff, sOrVsFSIsOff, sOrVsVSIsOff) = (
67    io.in.status.mstatusFSOff,
68    io.in.status.mstatusVSOff,
69    io.in.status.mstatusFSOff || io.in.status.vsstatusFSOff,
70    io.in.status.mstatusVSOff || io.in.status.vsstatusVSOff,
71  )
72
73  private val csrIsRO = addr(11, 10) === "b11".U
74  private val csrIsUnpriv = addr(9, 8) === "b00".U
75  private val csrIsM = addr(9, 8) === "b11".U
76  private val csrIsHPM = addr >= CSRs.cycle.U && addr <= CSRs.hpmcounter31.U
77  private val csrIsFp = Seq(CSRs.fflags, CSRs.frm, CSRs.fcsr).map(_.U === addr).reduce(_ || _)
78  private val csrIsVec = Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr, CSRs.vl, CSRs.vtype, CSRs.vlenb).map(_.U === addr).reduce(_ || _)
79  private val csrIsWritableVec = Seq(CSRs.vstart, CSRs.vxsat, CSRs.vxrm, CSRs.vcsr).map(_.U === addr).reduce(_ || _)
80  private val counterAddr = addr(4, 0) // 32 counters
81
82  private val accessTable = TruthTable(Seq(
83    //       V PRVM ADDR
84    BitPat("b0__00___00") -> BitPat.Y(), // HU access U
85    BitPat("b1__00___00") -> BitPat.Y(), // VU access U
86    BitPat("b0__01___00") -> BitPat.Y(), // HS access U
87    BitPat("b0__01___01") -> BitPat.Y(), // HS access S
88    BitPat("b0__01___10") -> BitPat.Y(), // HS access H
89    BitPat("b1__01___00") -> BitPat.Y(), // VS access U
90    BitPat("b1__01___01") -> BitPat.Y(), // VS access S
91    BitPat("b0__11___00") -> BitPat.Y(), // M  access HU
92    BitPat("b0__11___01") -> BitPat.Y(), // M  access HS
93    BitPat("b0__11___10") -> BitPat.Y(), // M  access H
94    BitPat("b0__11___11") -> BitPat.Y(), // M  access M
95  ), BitPat.N())
96
97  private val regularPrivilegeLegal = chisel3.util.experimental.decode.decoder(
98    privState.V.asUInt ## privState.PRVM.asUInt ## addr(9, 8),
99    accessTable
100  ).asBool
101
102  private val isDebugReg   = addr(11, 4) === "h7b".U
103  private val privilegeLegal = Mux(isDebugReg, debugMode, regularPrivilegeLegal || debugMode)
104
105  private val rwIllegal = csrIsRO && wen
106
107  private val mret_EX_II = mret && !privState.isModeM
108  private val mret_EX_VI = false.B
109  private val mretIllegal = mret_EX_II || mret_EX_VI
110
111  private val sret_EX_II = sret && (privState.isModeHU || privState.isModeHS && tsr)
112  private val sret_EX_VI = sret && (privState.isModeVU || privState.isModeVS && vtsr)
113  private val sretIllegal = sret_EX_II || sret_EX_VI
114
115  private val rwSatp_EX_II = csrAccess && privState.isModeHS &&  tvm && (addr === CSRs.satp.U || addr === CSRs.hgatp.U)
116  private val rwSatp_EX_VI = csrAccess && privState.isModeVS && vtvm && (addr === CSRs.satp.U)
117
118  private val rwCustom_EX_II = csrAccess && privState.isModeVS && csrIsCustom
119
120  private val accessHPM = ren && csrIsHPM
121  private val accessHPM_EX_II = accessHPM && (
122    !privState.isModeM && !mcounteren(counterAddr) ||
123    privState.isModeHU && !scounteren(counterAddr)
124  )
125  private val accessHPM_EX_VI = accessHPM && mcounteren(counterAddr) && (
126    privState.isModeVS && !hcounteren(counterAddr) ||
127    privState.isModeVU && (!hcounteren(counterAddr) || !scounteren(counterAddr))
128  )
129
130  private val rwStimecmp_EX_II = csrAccess && ((privState.isModeHS && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.vstimecmp.U ||
131    ((privState.isModeHS || privState.isModeVS) && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.stimecmp.U)
132  private val rwStimecmp_EX_VI = csrAccess && privState.isModeVS && (mcounterenTM && !hcounterenTM || menvcfgSTCE && !henvcfgSTCE) && addr === CSRs.stimecmp.U
133
134  private val fsEffectiveOff = sFSIsOff && !privState.isVirtual || sOrVsFSIsOff && privState.isVirtual
135  private val vsEffectiveOff = sVSIsOff && !privState.isVirtual || sOrVsVSIsOff && privState.isVirtual
136
137  private val fpOff_EX_II  = csrAccess && csrIsFp  && fsEffectiveOff
138  private val vecOff_EX_II = csrAccess && csrIsVec && vsEffectiveOff
139
140  private val fpVec_EX_II = fpOff_EX_II || vecOff_EX_II
141
142  private val csrAccessIllegal = (!privilegeLegal || rwIllegal)
143
144  // Todo: check correct
145  io.out.EX_II :=  csrAccess && !privilegeLegal && (!privState.isVirtual || privState.isVirtual && csrIsM) ||
146    rwIllegal || mret_EX_II || sret_EX_II || rwSatp_EX_II || accessHPM_EX_II ||
147    rwStimecmp_EX_II || rwCustom_EX_II || fpVec_EX_II
148  io.out.EX_VI := (csrAccess && !privilegeLegal && privState.isVirtual && !csrIsM ||
149    mret_EX_VI || sret_EX_VI || rwSatp_EX_VI || accessHPM_EX_VI || rwStimecmp_EX_VI) && !rwIllegal
150
151  io.out.hasLegalWen  := wen  && !csrAccessIllegal
152  io.out.hasLegalMret := mret && !mretIllegal
153  io.out.hasLegalSret := sret && !sretIllegal
154
155  io.out.hasLegalWriteFcsr := wen && csrIsFp && !fsEffectiveOff
156  io.out.hasLegalWriteVcsr := wen && csrIsWritableVec && !vsEffectiveOff
157
158  dontTouch(regularPrivilegeLegal)
159}
160
161class CSRPermitIO extends Bundle {
162  val in = Input(new Bundle {
163    val csrAccess = new Bundle {
164      val ren = Bool()
165      val wen = Bool()
166      val addr = UInt(12.W)
167    }
168    val privState = new PrivState
169    val debugMode = Bool()
170    val mret = Bool()
171    val sret = Bool()
172    val csrIsCustom = Bool()
173    val status = new Bundle {
174      // Trap SRET
175      val tsr = Bool()
176      // Virtual Trap SRET
177      val vtsr = Bool()
178      // Timeout Wait
179      val tw = Bool()
180      // Virtual Timeout Wait
181      val vtw = Bool()
182      // Trap Virtual Memory
183      val tvm = Bool()
184      // Virtual Trap Virtual Memory
185      val vtvm = Bool()
186      // Machine level counter enable, access PMC from the level less than M will trap EX_II
187      val mcounteren = UInt(32.W)
188      // Hypervisor level counter enable.
189      // Accessing PMC from VS/VU level will trap EX_VI, if m[x]=1 && h[x]=0
190      val hcounteren = UInt(32.W)
191      // Supervisor level counter enable.
192      // Accessing PMC from **HU level** will trap EX_II, if s[x]=0
193      // Accessing PMC from **VU level** will trap EX_VI, if m[x]=1 && h[x]=1 && s[x]=0
194      val scounteren = UInt(32.W)
195      // Machine environment configuration register.
196      // Accessing stimecmp or vstimecmp from **Non-M level** will trap EX_II, if menvcfg.STCE=0
197      val menvcfg = UInt(64.W)
198      // Hypervisor environment configuration register.
199      // Accessing vstimecmp from ** V level** will trap EX_VI, if menvcfg.STCE=1 && henvcfg.STCE=0
200      val henvcfg = UInt(64.W)
201
202      val mstatusFSOff = Bool()
203      val vsstatusFSOff = Bool()
204      val mstatusVSOff = Bool()
205      val vsstatusVSOff = Bool()
206    }
207  })
208
209  val out = Output(new Bundle {
210    val hasLegalWen  = Bool()
211    val hasLegalMret = Bool()
212    val hasLegalSret = Bool()
213    val hasLegalWriteFcsr   = Bool()
214    val hasLegalWriteVcsr  = Bool()
215    val EX_II = Bool()
216    val EX_VI = Bool()
217  })
218}
219