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