xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision b7b0d6c1ab6c9f4501f56975a1b95c01c7ec5983)
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  // TODO: mechanism should be implemented later
596  // val MhpmcounterStart = Mhpmcounter3
597  // val MhpmeventStart   = Mhpmevent3
598  // for (i <- 0 until nrPerfCnts) {
599  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
600  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
601  // }
602
603  val mapping = basicPrivMapping ++
604                perfCntMapping ++
605                pmpMapping ++
606                emuPerfCntsLoMapping ++
607                (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++
608                (if (HasFPU) fcsrMapping else Nil)
609
610  val addr = src2(11, 0)
611  val csri = ZeroExt(src2(16, 12), XLEN)
612  val rdata = Wire(UInt(XLEN.W))
613  val wdata = LookupTree(func, List(
614    CSROpType.wrt  -> src1,
615    CSROpType.set  -> (rdata | src1),
616    CSROpType.clr  -> (rdata & (~src1).asUInt()),
617    CSROpType.wrti -> csri,
618    CSROpType.seti -> (rdata | csri),
619    CSROpType.clri -> (rdata & (~csri).asUInt())
620  ))
621
622  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U)
623  csrio.isPerfCnt := addrInPerfCnt
624
625  // satp wen check
626  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
627
628  // general CSR wen check
629  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
630  val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
631  val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren)
632  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted)
633  // Writeable check is ingored.
634  // Currently, write to illegal csr addr will be ignored
635  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
636  io.out.bits.data := rdata
637  io.out.bits.uop := io.in.bits.uop
638  io.out.bits.uop.cf := cfOut
639  io.out.bits.uop.ctrl.flushPipe := flushPipe
640
641  // Fix Mip/Sip write
642  val fixMapping = Map(
643    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
644    MaskedRegMap(Sip, mipReg.asUInt, sipMask, MaskedRegMap.NoSideEffect, sipMask)
645  )
646  val rdataDummy = Wire(UInt(XLEN.W))
647  MaskedRegMap.generate(fixMapping, addr, rdataDummy, wen, wdata)
648
649  when (csrio.fpu.fflags.valid) {
650    fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits)
651  }
652  // set fs and sd in mstatus
653  when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) {
654    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
655    mstatusNew.fs := "b11".U
656    mstatusNew.sd := true.B
657    mstatus := mstatusNew.asUInt()
658  }
659  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
660
661  // CSR inst decode
662  val isEbreak = addr === privEbreak && func === CSROpType.jmp
663  val isEcall  = addr === privEcall  && func === CSROpType.jmp
664  val isMret   = addr === privMret   && func === CSROpType.jmp
665  val isSret   = addr === privSret   && func === CSROpType.jmp
666  val isUret   = addr === privUret   && func === CSROpType.jmp
667
668  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
669  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
670
671  // Illegal priviledged operation list
672  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
673
674  // Illegal priviledged instruction check
675  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
676  val isIllegalAccess = !permitted
677  val isIllegalPrivOp = illegalSModeSret
678
679  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
680  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
681  // imem
682  // val imemPtev = true.B
683  // val imemPteu = true.B
684  // val imemPtex = true.B
685  // val imemReq = true.B
686  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
687  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
688  // assert(!hasInstrPageFault)
689
690  // dmem
691  // val dmemPtev = true.B
692  // val dmemPteu = true.B
693  // val dmemReq = true.B
694  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
695  // val dmemIsStore = true.B
696
697  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
698  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
699  // assert(!hasLoadPageFault)
700  // assert(!hasStorePageFault)
701
702  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
703  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
704  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
705  tlbBundle.priv.imode := priviledgeMode
706  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
707
708  // Branch control
709  val retTarget = Wire(UInt(VAddrBits.W))
710  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
711  flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall)
712
713  retTarget := DontCare
714  // val illegalEret = TODO
715
716  when (valid && isMret) {
717    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
718    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
719    mstatusNew.ie.m := mstatusOld.pie.m
720    priviledgeMode := mstatusOld.mpp
721    mstatusNew.pie.m := true.B
722    mstatusNew.mpp := ModeU
723    mstatusNew.mprv := 0.U
724    mstatus := mstatusNew.asUInt
725    // lr := false.B
726    retTarget := mepc(VAddrBits-1, 0)
727  }
728
729  when (valid && isSret && !illegalSModeSret) {
730    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
731    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
732    mstatusNew.ie.s := mstatusOld.pie.s
733    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
734    mstatusNew.pie.s := true.B
735    mstatusNew.spp := ModeU
736    mstatus := mstatusNew.asUInt
737    mstatusNew.mprv := 0.U
738    // lr := false.B
739    retTarget := sepc(VAddrBits-1, 0)
740  }
741
742  when (valid && isUret) {
743    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
744    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
745    // mstatusNew.mpp.m := ModeU //TODO: add mode U
746    mstatusNew.ie.u := mstatusOld.pie.u
747    priviledgeMode := ModeU
748    mstatusNew.pie.u := true.B
749    mstatus := mstatusNew.asUInt
750    retTarget := uepc(VAddrBits-1, 0)
751  }
752
753  io.in.ready := true.B
754  io.out.valid := valid
755
756  val csrExceptionVec = WireInit(cfIn.exceptionVec)
757  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
758  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
759  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
760  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
761  // Trigger an illegal instr exception when:
762  // * unimplemented csr is being read/written
763  // * csr access is illegal
764  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
765  cfOut.exceptionVec := csrExceptionVec
766
767  /**
768    * Exception and Intr
769    */
770  val ideleg =  (mideleg & mip.asUInt)
771  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
772    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
773
774  // send interrupt information to ROQ
775  val intrVecEnable = Wire(Vec(12, Bool()))
776  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
777  val intrVec = mie(11,0) & mip.asUInt & intrVecEnable.asUInt
778  val intrBitSet = intrVec.orR()
779  csrio.interrupt := intrBitSet
780  mipWire.t.m := csrio.externalInterrupt.mtip
781  mipWire.s.m := csrio.externalInterrupt.msip
782  mipWire.e.m := csrio.externalInterrupt.meip
783
784  // interrupts
785  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
786  val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
787  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO)
788
789  // exceptions
790  val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt
791  val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException
792  val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException
793  val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException
794  val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException
795  val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException
796  val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException
797  val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
798  val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
799
800  val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
801  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
802  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
803
804  val raiseExceptionIntr = csrio.exception.valid
805  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
806    csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
807  )
808  XSDebug(raiseExceptionIntr,
809    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
810    csrio.exception.bits.uop.cf.pc,
811    mstatus,
812    mideleg,
813    medeleg,
814    priviledgeMode
815  )
816
817  // mtval write logic
818  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
819  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
820    val tval = Mux(
821      hasInstrPageFault,
822      Mux(
823        csrio.exception.bits.uop.cf.crossPageIPFFix,
824        SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN),
825        SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
826      ),
827      memExceptionAddr
828    )
829    when (priviledgeMode === ModeM) {
830      mtval := tval
831    }.otherwise {
832      stval := tval
833    }
834  }
835
836  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
837    mtval := memExceptionAddr
838  }
839
840  val deleg = Mux(raiseIntr, mideleg , medeleg)
841  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
842  val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM)
843  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
844  val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall
845
846  // ctrl block will use theses later for flush
847  val isXRetFlag = RegInit(false.B)
848  val retTargetReg = Reg(retTarget.cloneType)
849  when (io.flushIn) {
850    isXRetFlag := false.B
851  }.elsewhen (isXRet) {
852    isXRetFlag := true.B
853    retTargetReg := retTarget
854  }
855  csrio.isXRet := isXRetFlag
856  csrio.trapTarget := Mux(isXRetFlag,
857    retTargetReg,
858    Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
859  )
860
861  when (raiseExceptionIntr) {
862    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
863    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
864
865    when (delegS) {
866      scause := causeNO
867      sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
868      mstatusNew.spp := priviledgeMode
869      mstatusNew.pie.s := mstatusOld.ie.s
870      mstatusNew.ie.s := false.B
871      priviledgeMode := ModeS
872      when (tvalWen) { stval := 0.U }
873    }.otherwise {
874      mcause := causeNO
875      mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
876      mstatusNew.mpp := priviledgeMode
877      mstatusNew.pie.m := mstatusOld.ie.m
878      mstatusNew.ie.m := false.B
879      priviledgeMode := ModeM
880      when (tvalWen) { mtval := 0.U }
881    }
882
883    mstatus := mstatusNew.asUInt
884  }
885
886  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
887
888  def readWithScala(addr: Int): UInt = mapping(addr)._1
889
890  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
891
892  if (!env.FPGAPlatform) {
893    difftestIO.intrNO := RegNext(difftestIntrNO)
894    difftestIO.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U))
895    difftestIO.priviledgeMode := priviledgeMode
896    difftestIO.mstatus := mstatus
897    difftestIO.sstatus := mstatus & sstatusRmask
898    difftestIO.mepc := mepc
899    difftestIO.sepc := sepc
900    difftestIO.mtval:= mtval
901    difftestIO.stval:= stval
902    difftestIO.mtvec := mtvec
903    difftestIO.stvec := stvec
904    difftestIO.mcause := mcause
905    difftestIO.scause := scause
906    difftestIO.satp := satp
907    difftestIO.mip := mipReg
908    difftestIO.mie := mie
909    difftestIO.mscratch := mscratch
910    difftestIO.sscratch := sscratch
911    difftestIO.mideleg := mideleg
912    difftestIO.medeleg := medeleg
913  }
914}
915