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