xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision f320e0f01bd645f0a3045a8a740e60dd770734a9)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.backend.fu
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import utils._
23import xiangshan._
24import xiangshan.backend._
25import xiangshan.frontend.BPUCtrl
26import xiangshan.backend.fu.util._
27import difftest._
28
29trait HasExceptionNO {
30  def instrAddrMisaligned = 0
31  def instrAccessFault    = 1
32  def illegalInstr        = 2
33  def breakPoint          = 3
34  def loadAddrMisaligned  = 4
35  def loadAccessFault     = 5
36  def storeAddrMisaligned = 6
37  def storeAccessFault    = 7
38  def ecallU              = 8
39  def ecallS              = 9
40  def ecallM              = 11
41  def instrPageFault      = 12
42  def loadPageFault       = 13
43  def storePageFault      = 15
44
45  val ExcPriority = Seq(
46    breakPoint, // TODO: different BP has different priority
47    instrPageFault,
48    instrAccessFault,
49    illegalInstr,
50    instrAddrMisaligned,
51    ecallM, ecallS, ecallU,
52    storePageFault,
53    loadPageFault,
54    storeAccessFault,
55    loadAccessFault,
56    storeAddrMisaligned,
57    loadAddrMisaligned
58  )
59  val frontendSet = List(
60    // instrAddrMisaligned,
61    instrAccessFault,
62    illegalInstr,
63    instrPageFault
64  )
65  val csrSet = List(
66    illegalInstr,
67    breakPoint,
68    ecallU,
69    ecallS,
70    ecallM
71  )
72  val loadUnitSet = List(
73    loadAddrMisaligned,
74    loadAccessFault,
75    loadPageFault
76  )
77  val storeUnitSet = List(
78    storeAddrMisaligned,
79    storeAccessFault,
80    storePageFault
81  )
82  val atomicsUnitSet = (loadUnitSet ++ storeUnitSet).distinct
83  val allPossibleSet = (frontendSet ++ csrSet ++ loadUnitSet ++ storeUnitSet).distinct
84  val csrWbCount = (0 until 16).map(i => if (csrSet.contains(i)) 1 else 0)
85  val loadWbCount = (0 until 16).map(i => if (loadUnitSet.contains(i)) 1 else 0)
86  val storeWbCount = (0 until 16).map(i => if (storeUnitSet.contains(i)) 1 else 0)
87  val atomicsWbCount = (0 until 16).map(i => if (atomicsUnitSet.contains(i)) 1 else 0)
88  val writebackCount = (0 until 16).map(i => csrWbCount(i) + atomicsWbCount(i) + loadWbCount(i) + 2 * storeWbCount(i))
89  def partialSelect(vec: Vec[Bool], select: Seq[Int], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = {
90    if (dontCareBits) {
91      val new_vec = Wire(ExceptionVec())
92      new_vec := DontCare
93      select.map(i => new_vec(i) := vec(i))
94      return new_vec
95    }
96    else if (falseBits) {
97      val new_vec = Wire(ExceptionVec())
98      new_vec.map(_ := false.B)
99      select.map(i => new_vec(i) := vec(i))
100      return new_vec
101    }
102    else {
103      val new_vec = Wire(Vec(select.length, Bool()))
104      select.zipWithIndex.map{ case(s, i) => new_vec(i) := vec(s) }
105      return new_vec
106    }
107  }
108  def selectFrontend(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
109    partialSelect(vec, frontendSet, dontCareBits, falseBits)
110  def selectCSR(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
111    partialSelect(vec, csrSet, dontCareBits, falseBits)
112  def selectLoad(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
113    partialSelect(vec, loadUnitSet, dontCareBits, falseBits)
114  def selectStore(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
115    partialSelect(vec, storeUnitSet, dontCareBits, falseBits)
116  def selectAtomics(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
117    partialSelect(vec, atomicsUnitSet, dontCareBits, falseBits)
118  def selectAll(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
119    partialSelect(vec, allPossibleSet, dontCareBits, falseBits)
120}
121
122class FpuCsrIO extends Bundle {
123  val fflags = Output(Valid(UInt(5.W)))
124  val isIllegal = Output(Bool())
125  val dirty_fs = Output(Bool())
126  val frm = Input(UInt(3.W))
127}
128
129
130class PerfCounterIO(implicit p: Parameters) extends XSBundle {
131  val retiredInstr = UInt(3.W)
132  val frontendInfo = new Bundle {
133    val ibufFull  = Bool()
134  }
135  val ctrlInfo = new Bundle {
136    val roqFull   = Bool()
137    val intdqFull = Bool()
138    val fpdqFull  = Bool()
139    val lsdqFull  = Bool()
140  }
141  val memInfo = new Bundle {
142    val sqFull = Bool()
143    val lqFull = Bool()
144    val dcacheMSHRFull = Bool()
145  }
146  val bpuInfo = new Bundle {
147    val bpRight = UInt(XLEN.W)
148    val bpWrong = UInt(XLEN.W)
149  }
150  val cacheInfo = new Bundle {
151    val l2MSHRFull = Bool()
152    val l3MSHRFull = Bool()
153    val l2nAcquire = UInt(XLEN.W)
154    val l2nAcquireMiss = UInt(XLEN.W)
155    val l3nAcquire = UInt(XLEN.W)
156    val l3nAcquireMiss = UInt(XLEN.W)
157  }
158}
159
160class CSRFileIO(implicit p: Parameters) extends XSBundle {
161  val hartId = Input(UInt(64.W))
162  // output (for func === CSROpType.jmp)
163  val perf = Input(new PerfCounterIO)
164  val isPerfCnt = Output(Bool())
165  // to FPU
166  val fpu = Flipped(new FpuCsrIO)
167  // from rob
168  val exception = Flipped(ValidIO(new ExceptionInfo))
169  // to ROB
170  val isXRet = Output(Bool())
171  val trapTarget = Output(UInt(VAddrBits.W))
172  val interrupt = Output(Bool())
173  // from LSQ
174  val memExceptionVAddr = Input(UInt(VAddrBits.W))
175  // from outside cpu,externalInterrupt
176  val externalInterrupt = new ExternalInterruptIO
177  // TLB
178  val tlb = Output(new TlbCsrBundle)
179  // Custom microarchiture ctrl signal
180  val customCtrl = Output(new CustomCSRCtrlIO)
181  // to Fence to disable sfence
182  val disableSfence = Output(Bool())
183}
184
185class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst
186{
187  val csrio = IO(new CSRFileIO)
188
189  val cfIn = io.in.bits.uop.cf
190  val cfOut = Wire(new CtrlFlow)
191  cfOut := cfIn
192  val flushPipe = Wire(Bool())
193
194  val (valid, src1, src2, func) = (
195    io.in.valid,
196    io.in.bits.src(0),
197    io.in.bits.uop.ctrl.imm,
198    io.in.bits.uop.ctrl.fuOpType
199  )
200
201  // CSR define
202
203  class Priv extends Bundle {
204    val m = Output(Bool())
205    val h = Output(Bool())
206    val s = Output(Bool())
207    val u = Output(Bool())
208  }
209
210  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
211
212  class MstatusStruct extends Bundle {
213    val sd = Output(UInt(1.W))
214
215    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
216    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
217    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
218    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
219
220    val tsr = Output(UInt(1.W))
221    val tw = Output(UInt(1.W))
222    val tvm = Output(UInt(1.W))
223    val mxr = Output(UInt(1.W))
224    val sum = Output(UInt(1.W))
225    val mprv = Output(UInt(1.W))
226    val xs = Output(UInt(2.W))
227    val fs = Output(UInt(2.W))
228    val mpp = Output(UInt(2.W))
229    val hpp = Output(UInt(2.W))
230    val spp = Output(UInt(1.W))
231    val pie = new Priv
232    val ie = new Priv
233    assert(this.getWidth == XLEN)
234  }
235
236  class SatpStruct extends Bundle {
237    val mode = UInt(4.W)
238    val asid = UInt(16.W)
239    val ppn  = UInt(44.W)
240  }
241
242  class Interrupt extends Bundle {
243    val e = new Priv
244    val t = new Priv
245    val s = new Priv
246  }
247
248  // Machine-Level CSRs
249
250  val mtvec = RegInit(UInt(XLEN.W), 0.U)
251  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
252  val mcause = RegInit(UInt(XLEN.W), 0.U)
253  val mtval = RegInit(UInt(XLEN.W), 0.U)
254  val mepc = Reg(UInt(XLEN.W))
255
256  val mie = RegInit(0.U(XLEN.W))
257  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
258  val mipReg  = RegInit(0.U.asTypeOf(new Interrupt).asUInt)
259  val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1)
260  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
261
262  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt()
263  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt()
264  var extList = List('a', 's', 'i', 'u')
265  if (HasMExtension) { extList = extList :+ 'm' }
266  if (HasCExtension) { extList = extList :+ 'c' }
267  if (HasFPU) { extList = extList ++ List('f', 'd') }
268  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
269  val misa = RegInit(UInt(XLEN.W), misaInitVal)
270
271  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
272  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
273
274  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
275  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
276  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
277  val mhartid = RegInit(UInt(XLEN.W), csrio.hartId) // the hardware thread running the code
278  val mstatus = RegInit(UInt(XLEN.W), 0.U)
279
280  // mstatus Value Table
281  // | sd   |
282  // | pad1 |
283  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
284  // | uxl  | hardlinked to 00
285  // | pad0 |
286  // | tsr  |
287  // | tw   |
288  // | tvm  |
289  // | mxr  |
290  // | sum  |
291  // | mprv |
292  // | xs   | 00 |
293  // | fs   | 00 |
294  // | mpp  | 00 |
295  // | hpp  | 00 |
296  // | spp  | 0 |
297  // | pie  | 0000 | pie.h is used as UBE
298  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
299
300  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
301  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
302    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
303    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
304    mstatusNew
305  }
306
307  val mstatusMask = (~ZeroExt((
308    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
309    GenMask(37) | // MBE
310    GenMask(36) | // SBE
311    GenMask(6)    // UBE
312  ), 64)).asUInt()
313
314  val medeleg = RegInit(UInt(XLEN.W), 0.U)
315  val mideleg = RegInit(UInt(XLEN.W), 0.U)
316  val mscratch = RegInit(UInt(XLEN.W), 0.U)
317
318  val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U)
319  val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U)
320  val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U)
321  val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U)
322  val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U)
323  val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U)
324  val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U)
325  val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U)
326
327  // Superviser-Level CSRs
328
329  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
330  val sstatusWmask = "hc6122".U
331  // Sstatus Write Mask
332  // -------------------------------------------------------
333  //    19           9   5     2
334  // 0  1100 0000 0001 0010 0010
335  // 0  c    0    1    2    2
336  // -------------------------------------------------------
337  val sstatusRmask = sstatusWmask | "h8000000300018000".U
338  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
339  val stvec = RegInit(UInt(XLEN.W), 0.U)
340  // val sie = RegInit(0.U(XLEN.W))
341  val sieMask = "h222".U & mideleg
342  val sipMask = "h222".U & mideleg
343  val sipWMask = "h2".U // ssip is writeable in smode
344  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
345  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
346  val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0
347  val sepc = RegInit(UInt(XLEN.W), 0.U)
348  val scause = RegInit(UInt(XLEN.W), 0.U)
349  val stval = Reg(UInt(XLEN.W))
350  val sscratch = RegInit(UInt(XLEN.W), 0.U)
351  val scounteren = RegInit(UInt(XLEN.W), 0.U)
352
353  // sbpctl
354  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
355  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
356  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
357  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
358  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
359  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
360  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
361  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
362  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
363
364  // spfctl Bit 0: L1plusCache Prefetcher Enable
365  // spfctl Bit 1: L2Cache Prefetcher Enable
366  val spfctl = RegInit(UInt(XLEN.W), "h3".U)
367  csrio.customCtrl.l1plus_pf_enable := spfctl(0)
368  csrio.customCtrl.l2_pf_enable := spfctl(1)
369
370  // sdsid: Differentiated Services ID
371  val sdsid = RegInit(UInt(XLEN.W), 0.U)
372  csrio.customCtrl.dsid := sdsid
373
374  // slvpredctl: load violation predict settings
375  val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17
376  csrio.customCtrl.lvpred_disable := slvpredctl(0)
377  csrio.customCtrl.no_spec_load := slvpredctl(1)
378  csrio.customCtrl.waittable_timeout := slvpredctl(8, 4)
379
380  // smblockctl: memory block configurations
381  // bits 0-3: store buffer flush threshold (default: 8 entries)
382  val smblockctl = RegInit(UInt(XLEN.W), "hf".U & StoreBufferThreshold.U)
383  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
384
385  val srnctl = RegInit(UInt(XLEN.W), "h1".U)
386  csrio.customCtrl.move_elim_enable := srnctl(0)
387
388  val tlbBundle = Wire(new TlbCsrBundle)
389  tlbBundle.satp := satp.asTypeOf(new SatpStruct)
390  csrio.tlb := tlbBundle
391
392  // User-Level CSRs
393  val uepc = Reg(UInt(XLEN.W))
394
395  // fcsr
396  class FcsrStruct extends Bundle {
397    val reserved = UInt((XLEN-3-5).W)
398    val frm = UInt(3.W)
399    val fflags = UInt(5.W)
400    assert(this.getWidth == XLEN)
401  }
402  val fcsr = RegInit(0.U(XLEN.W))
403  // set mstatus->sd and mstatus->fs when true
404  val csrw_dirty_fp_state = WireInit(false.B)
405
406  def frm_wfn(wdata: UInt): UInt = {
407    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
408    csrw_dirty_fp_state := true.B
409    fcsrOld.frm := wdata(2,0)
410    fcsrOld.asUInt()
411  }
412  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
413
414  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
415    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
416    val fcsrNew = WireInit(fcsrOld)
417    csrw_dirty_fp_state := true.B
418    if (update) {
419      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
420    } else {
421      fcsrNew.fflags := wdata(4,0)
422    }
423    fcsrNew.asUInt()
424  }
425  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
426
427  def fcsr_wfn(wdata: UInt): UInt = {
428    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
429    csrw_dirty_fp_state := true.B
430    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
431  }
432
433  val fcsrMapping = Map(
434    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
435    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
436    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
437  )
438
439  // Atom LR/SC Control Bits
440  //  val setLr = WireInit(Bool(), false.B)
441  //  val setLrVal = WireInit(Bool(), false.B)
442  //  val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
443  //  val lr = RegInit(Bool(), false.B)
444  //  val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
445  //
446  //  when (setLr) {
447  //    lr := setLrVal
448  //    lrAddr := setLrAddr
449  //  }
450
451  // Hart Priviledge Mode
452  val priviledgeMode = RegInit(UInt(2.W), ModeM)
453
454  // Emu perfcnt
455  val hasEmuPerfCnt = !env.FPGAPlatform
456  val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3
457
458  val emuPerfCnts    = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W)))
459  val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B))
460  (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
461
462  val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i)))
463  val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32)))
464  println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}")
465
466  // Perf Counter
467  val nrPerfCnts = 29  // 3...31
468  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
469  val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
470  val mcountinhibit = RegInit(0.U(XLEN.W))
471  val mcycle = RegInit(0.U(XLEN.W))
472  mcycle := mcycle + 1.U
473  val minstret = RegInit(0.U(XLEN.W))
474  minstret := minstret + RegNext(csrio.perf.retiredInstr)
475  val ibufFull  = RegInit(0.U(XLEN.W))
476  ibufFull := ibufFull + RegNext(csrio.perf.frontendInfo.ibufFull)
477  val roqFull   = RegInit(0.U(XLEN.W))
478  roqFull := roqFull + RegNext(csrio.perf.ctrlInfo.roqFull)
479  val intdqFull = RegInit(0.U(XLEN.W))
480  intdqFull := intdqFull + RegNext(csrio.perf.ctrlInfo.intdqFull)
481  val fpdqFull  = RegInit(0.U(XLEN.W))
482  fpdqFull := fpdqFull + RegNext(csrio.perf.ctrlInfo.fpdqFull)
483  val lsdqFull  = RegInit(0.U(XLEN.W))
484  lsdqFull := lsdqFull + RegNext(csrio.perf.ctrlInfo.lsdqFull)
485  val sqFull    = RegInit(0.U(XLEN.W))
486  sqFull := sqFull + RegNext(csrio.perf.memInfo.sqFull)
487  val lqFull    = RegInit(0.U(XLEN.W))
488  lqFull := lqFull + RegNext(csrio.perf.memInfo.lqFull)
489  val dcacheMSHRFull = RegInit(0.U(XLEN.W))
490  dcacheMSHRFull := dcacheMSHRFull + RegNext(csrio.perf.memInfo.dcacheMSHRFull)
491  val bpRight   = RegInit(0.U(XLEN.W))
492  bpRight := bpRight + RegNext(csrio.perf.bpuInfo.bpRight)
493  val bpWrong   = RegInit(0.U(XLEN.W))
494  bpWrong := bpWrong + RegNext(csrio.perf.bpuInfo.bpWrong)
495
496  // CSR reg map
497  val basicPrivMapping = Map(
498
499    //--- User Trap Setup ---
500    // MaskedRegMap(Ustatus, ustatus),
501    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
502    // MaskedRegMap(Utvec, utvec),
503
504    //--- User Trap Handling ---
505    // MaskedRegMap(Uscratch, uscratch),
506    // MaskedRegMap(Uepc, uepc),
507    // MaskedRegMap(Ucause, ucause),
508    // MaskedRegMap(Utval, utval),
509    // MaskedRegMap(Uip, uip),
510
511    //--- User Counter/Timers ---
512    // MaskedRegMap(Cycle, cycle),
513    // MaskedRegMap(Time, time),
514    // MaskedRegMap(Instret, instret),
515
516    //--- Supervisor Trap Setup ---
517    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
518    // MaskedRegMap(Sedeleg, Sedeleg),
519    // MaskedRegMap(Sideleg, Sideleg),
520    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
521    MaskedRegMap(Stvec, stvec),
522    MaskedRegMap(Scounteren, scounteren),
523
524    //--- Supervisor Trap Handling ---
525    MaskedRegMap(Sscratch, sscratch),
526    MaskedRegMap(Sepc, sepc),
527    MaskedRegMap(Scause, scause),
528    MaskedRegMap(Stval, stval),
529    MaskedRegMap(Sip, mip.asUInt, sipWMask, MaskedRegMap.Unwritable, sipMask),
530
531    //--- Supervisor Protection and Translation ---
532    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
533
534    //--- Supervisor Custom Read/Write Registers
535    MaskedRegMap(Sbpctl, sbpctl),
536    MaskedRegMap(Spfctl, spfctl),
537    MaskedRegMap(Sdsid, sdsid),
538    MaskedRegMap(Slvpredctl, slvpredctl),
539    MaskedRegMap(Smblockctl, smblockctl),
540    MaskedRegMap(Srnctl, srnctl),
541
542    //--- Machine Information Registers ---
543    MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable),
544    MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable),
545    MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable),
546    MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable),
547
548    //--- Machine Trap Setup ---
549    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
550    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
551    MaskedRegMap(Medeleg, medeleg, "hf3ff".U),
552    MaskedRegMap(Mideleg, mideleg, "h222".U),
553    MaskedRegMap(Mie, mie),
554    MaskedRegMap(Mtvec, mtvec),
555    MaskedRegMap(Mcounteren, mcounteren),
556
557    //--- Machine Trap Handling ---
558    MaskedRegMap(Mscratch, mscratch),
559    MaskedRegMap(Mepc, mepc),
560    MaskedRegMap(Mcause, mcause),
561    MaskedRegMap(Mtval, mtval),
562    MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable),
563  )
564
565  // PMP is unimplemented yet
566  val pmpMapping = Map(
567    MaskedRegMap(Pmpcfg0, pmpcfg0),
568    MaskedRegMap(Pmpcfg1, pmpcfg1),
569    MaskedRegMap(Pmpcfg2, pmpcfg2),
570    MaskedRegMap(Pmpcfg3, pmpcfg3),
571    MaskedRegMap(PmpaddrBase + 0, pmpaddr0),
572    MaskedRegMap(PmpaddrBase + 1, pmpaddr1),
573    MaskedRegMap(PmpaddrBase + 2, pmpaddr2),
574    MaskedRegMap(PmpaddrBase + 3, pmpaddr3)
575  )
576
577  var perfCntMapping = Map(
578    MaskedRegMap(Mcountinhibit, mcountinhibit),
579    MaskedRegMap(Mcycle, mcycle),
580    MaskedRegMap(Minstret, minstret),
581    MaskedRegMap(Mhpmevent3, ibufFull),
582    MaskedRegMap(Mhpmevent4, roqFull),
583    MaskedRegMap(Mhpmevent5, intdqFull),
584    MaskedRegMap(Mhpmevent6, fpdqFull),
585    MaskedRegMap(Mhpmevent7, lsdqFull),
586    MaskedRegMap(Mhpmevent8, sqFull),
587    MaskedRegMap(Mhpmevent9, lqFull),
588    MaskedRegMap(Mhpmevent10, dcacheMSHRFull),
589    MaskedRegMap(Mhpmevent11, bpRight),
590    MaskedRegMap(Mhpmevent12, bpWrong),
591  )
592  // TODO: mechanism should be implemented later
593  // val MhpmcounterStart = Mhpmcounter3
594  // val MhpmeventStart   = Mhpmevent3
595  // for (i <- 0 until nrPerfCnts) {
596  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
597  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
598  // }
599
600  val mapping = basicPrivMapping ++
601                perfCntMapping ++
602                pmpMapping ++
603                emuPerfCntsLoMapping ++
604                (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++
605                (if (HasFPU) fcsrMapping else Nil)
606
607  val addr = src2(11, 0)
608  val csri = ZeroExt(src2(16, 12), XLEN)
609  val rdata = Wire(UInt(XLEN.W))
610  val wdata = LookupTree(func, List(
611    CSROpType.wrt  -> src1,
612    CSROpType.set  -> (rdata | src1),
613    CSROpType.clr  -> (rdata & (~src1).asUInt()),
614    CSROpType.wrti -> csri,
615    CSROpType.seti -> (rdata | csri),
616    CSROpType.clri -> (rdata & (~csri).asUInt())
617  ))
618
619  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U)
620  csrio.isPerfCnt := addrInPerfCnt
621
622  // satp wen check
623  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
624
625  // csr access check, special case
626  val tvmNotPermit = (priviledgeMode === ModeS && mstatusStruct.tvm.asBool)
627  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
628  csrio.disableSfence := tvmNotPermit
629
630  // general CSR wen check
631  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
632  val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
633  val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren)
634  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && accessPermitted
635
636  // Writeable check is ingored.
637  // Currently, write to illegal csr addr will be ignored
638  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
639  io.out.bits.data := rdata
640  io.out.bits.uop := io.in.bits.uop
641  io.out.bits.uop.cf := cfOut
642  io.out.bits.uop.ctrl.flushPipe := flushPipe
643
644  // Fix Mip/Sip write
645  val fixMapping = Map(
646    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
647    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask)
648  )
649  val rdataFix = Wire(UInt(XLEN.W))
650  val wdataFix = LookupTree(func, List(
651    CSROpType.wrt  -> src1,
652    CSROpType.set  -> (rdataFix | src1),
653    CSROpType.clr  -> (rdataFix & (~src1).asUInt()),
654    CSROpType.wrti -> csri,
655    CSROpType.seti -> (rdataFix | csri),
656    CSROpType.clri -> (rdataFix & (~csri).asUInt())
657  ))
658  MaskedRegMap.generate(fixMapping, addr, rdataFix, wen && permitted, wdataFix)
659
660  when (csrio.fpu.fflags.valid) {
661    fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits)
662  }
663  // set fs and sd in mstatus
664  when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) {
665    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
666    mstatusNew.fs := "b11".U
667    mstatusNew.sd := true.B
668    mstatus := mstatusNew.asUInt()
669  }
670  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
671
672  // CSR inst decode
673  val isEbreak = addr === privEbreak && func === CSROpType.jmp
674  val isEcall  = addr === privEcall  && func === CSROpType.jmp
675  val isMret   = addr === privMret   && func === CSROpType.jmp
676  val isSret   = addr === privSret   && func === CSROpType.jmp
677  val isUret   = addr === privUret   && func === CSROpType.jmp
678
679  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
680  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
681
682  // Illegal priviledged operation list
683  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
684
685  // Illegal priviledged instruction check
686  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
687  val isIllegalAccess = !permitted
688  val isIllegalPrivOp = illegalSModeSret
689
690  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
691  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
692  // imem
693  // val imemPtev = true.B
694  // val imemPteu = true.B
695  // val imemPtex = true.B
696  // val imemReq = true.B
697  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
698  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
699  // assert(!hasInstrPageFault)
700
701  // dmem
702  // val dmemPtev = true.B
703  // val dmemPteu = true.B
704  // val dmemReq = true.B
705  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
706  // val dmemIsStore = true.B
707
708  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
709  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
710  // assert(!hasLoadPageFault)
711  // assert(!hasStorePageFault)
712
713  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
714  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
715  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
716  tlbBundle.priv.imode := priviledgeMode
717  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
718
719  // Branch control
720  val retTarget = Wire(UInt(VAddrBits.W))
721  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
722  flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall)
723
724  retTarget := DontCare
725  // val illegalEret = TODO
726
727  when (valid && isMret) {
728    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
729    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
730    mstatusNew.ie.m := mstatusOld.pie.m
731    priviledgeMode := mstatusOld.mpp
732    mstatusNew.pie.m := true.B
733    mstatusNew.mpp := ModeU
734    mstatusNew.mprv := 0.U
735    mstatus := mstatusNew.asUInt
736    // lr := false.B
737    retTarget := mepc(VAddrBits-1, 0)
738  }
739
740  when (valid && isSret && !illegalSModeSret) {
741    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
742    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
743    mstatusNew.ie.s := mstatusOld.pie.s
744    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
745    mstatusNew.pie.s := true.B
746    mstatusNew.spp := ModeU
747    mstatus := mstatusNew.asUInt
748    mstatusNew.mprv := 0.U
749    // lr := false.B
750    retTarget := sepc(VAddrBits-1, 0)
751  }
752
753  when (valid && isUret) {
754    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
755    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
756    // mstatusNew.mpp.m := ModeU //TODO: add mode U
757    mstatusNew.ie.u := mstatusOld.pie.u
758    priviledgeMode := ModeU
759    mstatusNew.pie.u := true.B
760    mstatus := mstatusNew.asUInt
761    retTarget := uepc(VAddrBits-1, 0)
762  }
763
764  io.in.ready := true.B
765  io.out.valid := valid
766
767  val csrExceptionVec = WireInit(cfIn.exceptionVec)
768  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
769  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
770  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
771  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
772  // Trigger an illegal instr exception when:
773  // * unimplemented csr is being read/written
774  // * csr access is illegal
775  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
776  cfOut.exceptionVec := csrExceptionVec
777
778  /**
779    * Exception and Intr
780    */
781  val ideleg =  (mideleg & mip.asUInt)
782  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
783    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
784
785  // send interrupt information to ROQ
786  val intrVecEnable = Wire(Vec(12, Bool()))
787  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
788  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
789  val intrBitSet = intrVec.orR()
790  csrio.interrupt := intrBitSet
791  mipWire.t.m := csrio.externalInterrupt.mtip
792  mipWire.s.m := csrio.externalInterrupt.msip
793  mipWire.e.m := csrio.externalInterrupt.meip
794  mipWire.e.s := csrio.externalInterrupt.meip
795
796  // interrupts
797  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
798  val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
799  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO)
800
801  // exceptions
802  val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt
803  val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException
804  val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException
805  val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException
806  val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException
807  val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException
808  val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException
809  val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
810  val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
811
812  val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
813  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
814  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
815
816  val raiseExceptionIntr = csrio.exception.valid
817  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
818    csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
819  )
820  XSDebug(raiseExceptionIntr,
821    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
822    csrio.exception.bits.uop.cf.pc,
823    mstatus,
824    mideleg,
825    medeleg,
826    priviledgeMode
827  )
828
829  // mtval write logic
830  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
831  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
832    val tval = Mux(
833      hasInstrPageFault,
834      Mux(
835        csrio.exception.bits.uop.cf.crossPageIPFFix,
836        SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN),
837        SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
838      ),
839      memExceptionAddr
840    )
841    when (priviledgeMode === ModeM) {
842      mtval := tval
843    }.otherwise {
844      stval := tval
845    }
846  }
847
848  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
849    mtval := memExceptionAddr
850  }
851
852  val deleg = Mux(raiseIntr, mideleg , medeleg)
853  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
854  val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM)
855  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
856  val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall
857
858  // ctrl block will use theses later for flush
859  val isXRetFlag = RegInit(false.B)
860  val retTargetReg = Reg(retTarget.cloneType)
861  when (io.flushIn) {
862    isXRetFlag := false.B
863  }.elsewhen (isXRet) {
864    isXRetFlag := true.B
865    retTargetReg := retTarget
866  }
867  csrio.isXRet := isXRetFlag
868  csrio.trapTarget := Mux(isXRetFlag,
869    retTargetReg,
870    Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
871  )
872
873  when (raiseExceptionIntr) {
874    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
875    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
876
877    when (delegS) {
878      scause := causeNO
879      sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
880      mstatusNew.spp := priviledgeMode
881      mstatusNew.pie.s := mstatusOld.ie.s
882      mstatusNew.ie.s := false.B
883      priviledgeMode := ModeS
884      when (tvalWen) { stval := 0.U }
885    }.otherwise {
886      mcause := causeNO
887      mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
888      mstatusNew.mpp := priviledgeMode
889      mstatusNew.pie.m := mstatusOld.ie.m
890      mstatusNew.ie.m := false.B
891      priviledgeMode := ModeM
892      when (tvalWen) { mtval := 0.U }
893    }
894
895    mstatus := mstatusNew.asUInt
896  }
897
898  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
899
900  def readWithScala(addr: Int): UInt = mapping(addr)._1
901
902  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
903
904  if (!env.FPGAPlatform) {
905    val difftest = Module(new DifftestArchEvent)
906    difftest.io.clock := clock
907    difftest.io.coreid := hardId.U
908    difftest.io.intrNO := RegNext(difftestIntrNO)
909    difftest.io.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U))
910    difftest.io.exceptionPC := RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN))
911  }
912
913  if (!env.FPGAPlatform) {
914    val difftest = Module(new DifftestCSRState)
915    difftest.io.clock := clock
916    difftest.io.coreid := hardId.U
917    difftest.io.priviledgeMode := priviledgeMode
918    difftest.io.mstatus := mstatus
919    difftest.io.sstatus := mstatus & sstatusRmask
920    difftest.io.mepc := mepc
921    difftest.io.sepc := sepc
922    difftest.io.mtval:= mtval
923    difftest.io.stval:= stval
924    difftest.io.mtvec := mtvec
925    difftest.io.stvec := stvec
926    difftest.io.mcause := mcause
927    difftest.io.scause := scause
928    difftest.io.satp := satp
929    difftest.io.mip := mipReg
930    difftest.io.mie := mie
931    difftest.io.mscratch := mscratch
932    difftest.io.sscratch := sscratch
933    difftest.io.mideleg := mideleg
934    difftest.io.medeleg := medeleg
935  }
936}
937