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