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