xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRPermitModule.scala (revision 94895e779404b84119bcdb1ed911d357636b3105)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util._
5import chisel3.util.experimental.decode.TruthTable
6import xiangshan.backend.fu.NewCSR.CSRBundles.{Counteren, PrivState}
7import freechips.rocketchip.rocket.CSRs
8
9class CSRPermitModule extends Module {
10  val io = IO(new CSRPermitIO)
11
12  private val (ren, wen, addr, privState, debugMode) = (
13    io.in.csrAccess.ren,
14    io.in.csrAccess.wen,
15    io.in.csrAccess.addr,
16    io.in.privState,
17    io.in.debugMode
18  )
19
20  private val csrAccess = WireInit(ren || wen)
21
22  private val (mret, sret) = (
23    io.in.mret,
24    io.in.sret,
25  )
26
27  private val (tsr, vtsr) = (
28    io.in.status.tsr,
29    io.in.status.vtsr,
30  )
31
32  private val (tw, vtw) = (
33    io.in.status.tw,
34    io.in.status.vtw
35  )
36
37  private val (tvm, vtvm) = (
38    io.in.status.tvm,
39    io.in.status.vtvm,
40  )
41
42  private val csrIsCustom = io.in.csrIsCustom
43
44  private val (mcounteren, hcounteren, scounteren) = (
45    io.in.status.mcounteren,
46    io.in.status.hcounteren,
47    io.in.status.scounteren,
48  )
49
50  private val (mcounterenTM, hcounterenTM) = (
51    mcounteren(1),
52    hcounteren(1),
53  )
54
55  private val (menvcfg, henvcfg) = (
56    io.in.status.menvcfg,
57    io.in.status.henvcfg,
58  )
59
60  private val (menvcfgSTCE, henvcfgSTCE) = (
61    menvcfg(63),
62    henvcfg(63),
63  )
64
65  private val csrIsRO = addr(11, 10) === "b11".U
66  private val csrIsUnpriv = addr(9, 8) === "b00".U
67  private val csrIsHPM = addr >= CSRs.cycle.U && addr <= CSRs.hpmcounter31.U
68  private val counterAddr = addr(4, 0) // 32 counters
69
70  private val accessTable = TruthTable(Seq(
71    //       V PRVM ADDR
72    BitPat("b0__00___00") -> BitPat.Y(), // HU access U
73    BitPat("b1__00___00") -> BitPat.Y(), // VU access U
74    BitPat("b0__01___00") -> BitPat.Y(), // HS access U
75    BitPat("b0__01___01") -> BitPat.Y(), // HS access S
76    BitPat("b0__01___10") -> BitPat.Y(), // HS access H
77    BitPat("b1__01___00") -> BitPat.Y(), // VS access U
78    BitPat("b1__01___01") -> BitPat.Y(), // VS access S
79    BitPat("b0__11___00") -> BitPat.Y(), // M  access HU
80    BitPat("b0__11___01") -> BitPat.Y(), // M  access HS
81    BitPat("b0__11___10") -> BitPat.Y(), // M  access H
82    BitPat("b0__11___11") -> BitPat.Y(), // M  access M
83  ), BitPat.N())
84
85  private val isDebugReg   = addr(11, 4) === "h7b".U
86  private val isTriggerReg = addr(11, 4) === "h7a".U
87
88  private val regularPrivilegeLegal = chisel3.util.experimental.decode.decoder(
89    privState.V.asUInt ## privState.PRVM.asUInt ## addr(9, 8),
90    accessTable
91  ).asBool
92
93  private val privilegeLegal = MuxCase(
94    regularPrivilegeLegal,
95    Seq(
96      isDebugReg   -> debugMode,
97      isTriggerReg -> (debugMode || privState.isModeM),
98    )
99  )
100
101  private val rwIllegal = csrIsRO && wen
102
103  private val csrAccessIllegal = (!privilegeLegal || rwIllegal)
104
105  private val mret_EX_II = mret && !privState.isModeM
106  private val mret_EX_VI = false.B
107  private val mretIllegal = mret_EX_II || mret_EX_VI
108
109  private val sret_EX_II = sret && (privState.isModeHU || privState.isModeHS && tsr)
110  private val sret_EX_VI = sret && (privState.isModeVU || privState.isModeVS && vtsr)
111  private val sretIllegal = sret_EX_II || sret_EX_VI
112
113  private val rwSatp_EX_II = csrAccess && privState.isModeHS &&  tvm && (addr === CSRs.satp.U || addr === CSRs.hgatp.U)
114  private val rwSatp_EX_VI = csrAccess && privState.isModeVS && vtvm && (addr === CSRs.satp.U)
115
116  private val rwCustom_EX_II = csrAccess && privState.isModeVS && csrIsCustom
117
118  private val accessHPM = ren && csrIsHPM
119  private val accessHPM_EX_II = accessHPM && (
120    !privState.isModeM && !mcounteren(counterAddr) ||
121    privState.isModeHU && !scounteren(counterAddr)
122  )
123  private val accessHPM_EX_VI = accessHPM && mcounteren(counterAddr) && (
124    privState.isModeVS && !hcounteren(counterAddr) ||
125    privState.isModeVU && (!hcounteren(counterAddr) || !scounteren(counterAddr))
126  )
127
128  private val rwStimecmp_EX_II = csrAccess && ((privState.isModeHS && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.vstimecmp.U ||
129    ((privState.isModeHS || privState.isModeVS) && !mcounterenTM || !privState.isModeM && !menvcfgSTCE) && addr === CSRs.stimecmp.U)
130  private val rwStimecmp_EX_VI = csrAccess && privState.isModeVS && (mcounterenTM && !hcounterenTM || menvcfgSTCE && !henvcfgSTCE) && addr === CSRs.stimecmp.U
131
132  io.out.illegal := csrAccess && csrAccessIllegal || mretIllegal
133
134  // Todo: check correct
135  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
136  io.out.EX_VI := io.out.illegal &&  privState.isVirtual || mret_EX_VI || sret_EX_VI || rwSatp_EX_VI || accessHPM_EX_VI || rwStimecmp_EX_VI
137
138  io.out.hasLegalWen := io.in.csrAccess.wen && !csrAccessIllegal
139  io.out.hasLegalMret := mret && !mretIllegal
140  io.out.hasLegalSret := sret && !sretIllegal
141
142  dontTouch(regularPrivilegeLegal)
143}
144
145class CSRPermitIO extends Bundle {
146  val in = Input(new Bundle {
147    val csrAccess = new Bundle {
148      val ren = Bool()
149      val wen = Bool()
150      val addr = UInt(12.W)
151    }
152    val privState = new PrivState
153    val debugMode = Bool()
154    val mret = Bool()
155    val sret = Bool()
156    val csrIsCustom = Bool()
157    val status = new Bundle {
158      // Trap SRET
159      val tsr = Bool()
160      // Virtual Trap SRET
161      val vtsr = Bool()
162      // Timeout Wait
163      val tw = Bool()
164      // Virtual Timeout Wait
165      val vtw = Bool()
166      // Trap Virtual Memory
167      val tvm = Bool()
168      // Virtual Trap Virtual Memory
169      val vtvm = Bool()
170      // Machine level counter enable, access PMC from the level less than M will trap EX_II
171      val mcounteren = UInt(32.W)
172      // Hypervisor level counter enable.
173      // Accessing PMC from VS/VU level will trap EX_VI, if m[x]=1 && h[x]=0
174      val hcounteren = UInt(32.W)
175      // Supervisor level counter enable.
176      // Accessing PMC from **HU level** will trap EX_II, if s[x]=0
177      // Accessing PMC from **VU level** will trap EX_VI, if m[x]=1 && h[x]=1 && s[x]=0
178      val scounteren = UInt(32.W)
179      // Machine environment configuration register.
180      // Accessing stimecmp or vstimecmp from **Non-M level** will trap EX_II, if menvcfg.STCE=0
181      val menvcfg = UInt(64.W)
182      // Hypervisor environment configuration register.
183      // Accessing vstimecmp from ** V level** will trap EX_VI, if menvcfg.STCE=1 && henvcfg.STCE=0
184      val henvcfg = UInt(64.W)
185    }
186  })
187
188  val out = Output(new Bundle {
189    val hasLegalWen = Bool()
190    val hasLegalMret = Bool()
191    val hasLegalSret = Bool()
192    // Todo: split illegal into EX_II and EX_VI
193    val illegal = Bool()
194    val EX_II = Bool()
195    val EX_VI = Bool()
196  })
197}
198