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