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