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