xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision 735cbcf493c404ef921af2f1c163ded53a3bc078)
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
680  val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec
681  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
682  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
683
684  val raiseExceptionIntr = csrio.exception.valid
685  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
686    csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
687  )
688  XSDebug(raiseExceptionIntr,
689    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
690    csrio.exception.bits.cf.pc,
691    mstatus,
692    mideleg,
693    medeleg,
694    priviledgeMode
695  )
696
697  // mtval write logic
698  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
699  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
700    val tval = Mux(
701      hasInstrPageFault,
702      Mux(
703        csrio.exception.bits.cf.crossPageIPFFix,
704        SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN),
705        SignExt(csrio.exception.bits.cf.pc, XLEN)
706      ),
707      memExceptionAddr
708    )
709    when (priviledgeMode === ModeM) {
710      mtval := tval
711    }.otherwise {
712      stval := tval
713    }
714  }
715
716  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
717    mtval := memExceptionAddr
718  }
719
720  val deleg = Mux(raiseIntr, mideleg , medeleg)
721  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
722  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
723  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
724  csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
725
726  when (raiseExceptionIntr) {
727    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
728    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
729
730    when (delegS) {
731      scause := causeNO
732      sepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
733      mstatusNew.spp := priviledgeMode
734      mstatusNew.pie.s := mstatusOld.ie.s
735      mstatusNew.ie.s := false.B
736      priviledgeMode := ModeS
737      when (tvalWen) { stval := 0.U }
738    }.otherwise {
739      mcause := causeNO
740      mepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
741      mstatusNew.mpp := priviledgeMode
742      mstatusNew.pie.m := mstatusOld.ie.m
743      mstatusNew.ie.m := false.B
744      priviledgeMode := ModeM
745      when (tvalWen) { mtval := 0.U }
746    }
747
748    mstatus := mstatusNew.asUInt
749  }
750
751  XSDebug(raiseExceptionIntr && delegS,
752    "Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n",
753    csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr,
754    isSret, sepc, delegS, deleg
755  )
756  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
757
758
759  /**
760    * Emu Performance counters
761    */
762  val emuPerfCntList = Map(
763    // "Mcycle"    -> (0x1000, "perfCntCondMcycle"     ),
764    // "Minstret"  -> (0x1002, "perfCntCondMinstret"   ),
765    "BpInstr"     -> (0x1003, "perfCntCondBpInstr" ),
766    "BpRight"     -> (0x1004, "perfCntCondBpRight" ),
767    "BpWrong"     -> (0x1005, "perfCntCondBpWrong" ),
768    "BpBRight"    -> (0x1006, "perfCntCondBpBRight"),
769    "BpBWrong"    -> (0x1007, "perfCntCondBpBWrong"),
770    "BpJRight"    -> (0x1008, "perfCntCondBpJRight"),
771    "BpJWrong"    -> (0x1009, "perfCntCondBpJWrong"),
772    "BpIRight"    -> (0x100a, "perfCntCondBpIRight"),
773    "BpIWrong"    -> (0x100b, "perfCntCondBpIWrong"),
774    "BpRRight"    -> (0x100c, "perfCntCondBpRRight"),
775    "BpRWrong"    -> (0x100d, "perfCntCondBpRWrong"),
776    "RoqWalk"     -> (0x100f, "perfCntCondRoqWalk"  ),
777    "DTlbReqCnt0" -> (0x1015, "perfCntDtlbReqCnt0"  ),
778    "DTlbReqCnt1" -> (0x1016, "perfCntDtlbReqCnt1"  ),
779    "DTlbReqCnt2" -> (0x1017, "perfCntDtlbReqCnt2"  ),
780    "DTlbReqCnt3" -> (0x1018, "perfCntDtlbReqCnt3"  ),
781    "DTlbMissCnt0"-> (0x1019, "perfCntDtlbMissCnt0" ),
782    "DTlbMissCnt1"-> (0x1020, "perfCntDtlbMissCnt1" ),
783    "DTlbMissCnt2"-> (0x1021, "perfCntDtlbMissCnt2" ),
784    "DTlbMissCnt3"-> (0x1022, "perfCntDtlbMissCnt3" ),
785    "ITlbReqCnt0" -> (0x1023, "perfCntItlbReqCnt0"  ),
786    "ITlbMissCnt0"-> (0x1024, "perfCntItlbMissCnt0" ),
787    "PtwReqCnt"   -> (0x1025, "perfCntPtwReqCnt"    ),
788    "PtwCycleCnt" -> (0x1026, "perfCntPtwCycleCnt"  ),
789    "PtwL2TlbHit" -> (0x1027, "perfCntPtwL2TlbHit"  ),
790    "ICacheReq"   -> (0x1028, "perfCntIcacheReqCnt" ),
791    "ICacheMiss"  -> (0x1029, "perfCntIcacheMissCnt")
792    // "FetchFromICache" -> (0x102a, "CntFetchFromICache"),
793    // "FetchFromLoopBuffer" -> (0x102b, "CntFetchFromLoopBuffer"),
794    // "ExitLoop1" -> (0x102c, "CntExitLoop1"),
795    // "ExitLoop2" -> (0x102d, "CntExitLoop2"),
796    // "ExitLoop3" -> (0x102e, "CntExitLoop3")
797    // "L2cacheHit" -> (0x1023, "perfCntCondL2cacheHit")
798  ) ++ (
799    (0 until dcacheParameters.nMissEntries).map(i =>
800      ("DCacheMissQueuePenalty" + Integer.toString(i, 10), (0x102d + i, "perfCntDCacheMissQueuePenaltyEntry" + Integer.toString(i, 10)))
801    ).toMap
802  ) ++ (
803    (0 until icacheParameters.nMissEntries).map(i =>
804      ("ICacheMissQueuePenalty" + Integer.toString(i, 10), (0x102d + dcacheParameters.nMissEntries + i, "perfCntICacheMissQueuePenaltyEntry" + Integer.toString(i, 10)))
805    ).toMap
806  ) ++ (
807    (0 until l1plusPrefetcherParameters.nEntries).map(i =>
808      ("L1+PrefetchPenalty" + Integer.toString(i, 10), (0x102d + dcacheParameters.nMissEntries + icacheParameters.nMissEntries + i, "perfCntL1plusPrefetchPenaltyEntry" + Integer.toString(i, 10)))
809    ).toMap
810  ) ++ (
811    (0 until l2PrefetcherParameters.nEntries).map(i =>
812      ("L2PrefetchPenalty" + Integer.toString(i, 10), (0x102d + dcacheParameters.nMissEntries + icacheParameters.nMissEntries + l1plusPrefetcherParameters.nEntries + i, "perfCntL2PrefetchPenaltyEntry" + Integer.toString(i, 10)))
813    ).toMap
814  )
815
816  emuPerfCntList.foreach {
817    case (_, (address, boringId)) =>
818      if (hasEmuPerfCnt) {
819        ExcitingUtils.addSink(emuPerfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
820      }
821      // if (!hasEmuPerfCnt) {
822      //   // do not enable perfcnts except for Mcycle and Minstret
823      //   if (address != emuPerfCntList("Mcycle")._1 && address != emuPerfCntList("Minstret")._1) {
824      //     perfCntCond(address & 0x7f) := false.B
825      //   }
826      // }
827  }
828
829  val xstrap = WireInit(false.B)
830  if (!env.FPGAPlatform && EnableBPU) {
831    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
832  }
833  def readWithScala(addr: Int): UInt = mapping(addr)._1
834
835  if (!env.FPGAPlatform) {
836
837    // display all perfcnt when nooptrap is executed
838    when (xstrap) {
839      printf("======== PerfCnt =========\n")
840      emuPerfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, _)) =>
841        printf("%d <- " + str + "\n", readWithScala(address))
842      }
843    }
844
845    val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
846    ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
847    ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
848    ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug)
849    ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug)
850    ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug)
851    ExcitingUtils.addSource(mepc, "difftestMepc", Debug)
852    ExcitingUtils.addSource(sepc, "difftestSepc", Debug)
853    ExcitingUtils.addSource(mtval, "difftestMtval", Debug)
854    ExcitingUtils.addSource(stval, "difftestStval", Debug)
855    ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug)
856    ExcitingUtils.addSource(stvec, "difftestStvec", Debug)
857    ExcitingUtils.addSource(mcause, "difftestMcause", Debug)
858    ExcitingUtils.addSource(scause, "difftestScause", Debug)
859    ExcitingUtils.addSource(satp, "difftestSatp", Debug)
860    ExcitingUtils.addSource(mipReg, "difftestMip", Debug)
861    ExcitingUtils.addSource(mie, "difftestMie", Debug)
862    ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug)
863    ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug)
864    ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug)
865    ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug)
866  }
867}
868