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