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