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