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