xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision ec148c37adee6eae2382ea15824c7a2b4016fd40)
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  val hasInstrAccessFault = csrio.exception.bits.cf.exceptionVec(instrAccessFault) && raiseException
613  val hasLoadAccessFault = csrio.exception.bits.cf.exceptionVec(loadAccessFault) && raiseException
614  val hasStoreAccessFault = csrio.exception.bits.cf.exceptionVec(storeAccessFault) && raiseException
615
616  val csrExceptionVec = Wire(Vec(16, Bool()))
617  csrExceptionVec.map(_ := false.B)
618  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
619  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
620  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
621  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
622  // Trigger an illegal instr exception when:
623  // * unimplemented csr is being read/written
624  // * csr access is illegal
625  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
626  csrExceptionVec(loadPageFault) := hasLoadPageFault
627  csrExceptionVec(storePageFault) := hasStorePageFault
628  csrExceptionVec(loadAccessFault) := hasLoadAccessFault
629  csrExceptionVec(storeAccessFault) := hasStoreAccessFault
630  val iduExceptionVec = cfIn.exceptionVec
631  val exceptionVec = csrExceptionVec.asUInt() | iduExceptionVec.asUInt()
632  cfOut.exceptionVec.zipWithIndex.map{case (e, i) => e := exceptionVec(i) }
633
634  val raiseExceptionVec = csrio.exception.bits.cf.exceptionVec.asUInt()
635  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
636  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
637
638  val raiseExceptionIntr = csrio.exception.valid
639  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
640    csrio.exception.bits.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
641  )
642  XSDebug(raiseExceptionIntr,
643    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
644    csrio.exception.bits.cf.pc,
645    mstatus,
646    mideleg,
647    medeleg,
648    priviledgeMode
649  )
650
651  // mtval write logic
652  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
653  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
654    val tval = Mux(
655      hasInstrPageFault,
656      Mux(
657        csrio.exception.bits.cf.crossPageIPFFix,
658        SignExt(csrio.exception.bits.cf.pc + 2.U, XLEN),
659        SignExt(csrio.exception.bits.cf.pc, XLEN)
660      ),
661      memExceptionAddr
662    )
663    when (priviledgeMode === ModeM) {
664      mtval := tval
665    }.otherwise {
666      stval := tval
667    }
668  }
669
670  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
671    mtval := memExceptionAddr
672  }
673
674  val deleg = Mux(raiseIntr, mideleg , medeleg)
675  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
676  val delegS = (deleg(causeNO(3,0))) && (priviledgeMode < ModeM)
677  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
678  csrio.trapTarget := Mux(delegS, stvec, mtvec)(VAddrBits-1, 0)
679
680  when (raiseExceptionIntr) {
681    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
682    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
683
684    when (delegS) {
685      scause := causeNO
686      sepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
687      mstatusNew.spp := priviledgeMode
688      mstatusNew.pie.s := mstatusOld.ie.s
689      mstatusNew.ie.s := false.B
690      priviledgeMode := ModeS
691      when (tvalWen) { stval := 0.U }
692    }.otherwise {
693      mcause := causeNO
694      mepc := SignExt(csrio.exception.bits.cf.pc, XLEN)
695      mstatusNew.mpp := priviledgeMode
696      mstatusNew.pie.m := mstatusOld.ie.m
697      mstatusNew.ie.m := false.B
698      priviledgeMode := ModeM
699      when (tvalWen) { mtval := 0.U }
700    }
701
702    mstatus := mstatusNew.asUInt
703  }
704
705  XSDebug(raiseExceptionIntr && delegS,
706    "Red(%d, %x) raiseExcepIntr:%d isSret:%d sepc:%x delegs:%d deleg:%x\n",
707    csrio.redirectOut.valid, csrio.redirectOut.bits, raiseExceptionIntr,
708    isSret, sepc, delegS, deleg
709  )
710  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
711
712
713  /**
714    * Emu Performance counters
715    */
716  val emuPerfCntList = Map(
717    // "Mcycle"    -> (0x1000, "perfCntCondMcycle"     ),
718    // "Minstret"  -> (0x1002, "perfCntCondMinstret"   ),
719    "BpInstr"     -> (0x1003, "perfCntCondBpInstr" ),
720    "BpRight"     -> (0x1004, "perfCntCondBpRight" ),
721    "BpWrong"     -> (0x1005, "perfCntCondBpWrong" ),
722    "BpBRight"    -> (0x1006, "perfCntCondBpBRight"),
723    "BpBWrong"    -> (0x1007, "perfCntCondBpBWrong"),
724    "BpJRight"    -> (0x1008, "perfCntCondBpJRight"),
725    "BpJWrong"    -> (0x1009, "perfCntCondBpJWrong"),
726    "BpIRight"    -> (0x100a, "perfCntCondBpIRight"),
727    "BpIWrong"    -> (0x100b, "perfCntCondBpIWrong"),
728    "BpRRight"    -> (0x100c, "perfCntCondBpRRight"),
729    "BpRWrong"    -> (0x100d, "perfCntCondBpRWrong"),
730    "RoqWalk"     -> (0x100f, "perfCntCondRoqWalk"  ),
731    "DTlbReqCnt0" -> (0x1015, "perfCntDtlbReqCnt0"  ),
732    "DTlbReqCnt1" -> (0x1016, "perfCntDtlbReqCnt1"  ),
733    "DTlbReqCnt2" -> (0x1017, "perfCntDtlbReqCnt2"  ),
734    "DTlbReqCnt3" -> (0x1018, "perfCntDtlbReqCnt3"  ),
735    "DTlbMissCnt0"-> (0x1019, "perfCntDtlbMissCnt0" ),
736    "DTlbMissCnt1"-> (0x1020, "perfCntDtlbMissCnt1" ),
737    "DTlbMissCnt2"-> (0x1021, "perfCntDtlbMissCnt2" ),
738    "DTlbMissCnt3"-> (0x1022, "perfCntDtlbMissCnt3" ),
739    "ITlbReqCnt0" -> (0x1023, "perfCntItlbReqCnt0"  ),
740    "ITlbMissCnt0"-> (0x1024, "perfCntItlbMissCnt0" ),
741    "PtwReqCnt"   -> (0x1025, "perfCntPtwReqCnt"    ),
742    "PtwCycleCnt" -> (0x1026, "perfCntPtwCycleCnt"  ),
743    "PtwL2TlbHit" -> (0x1027, "perfCntPtwL2TlbHit"  ),
744    "ICacheReq"   -> (0x1028, "perfCntIcacheReqCnt" ),
745    "ICacheMiss"  -> (0x1029, "perfCntIcacheMissCnt"),
746
747    "ubtbRight"   -> (0x1030, "perfCntubtbRight"),
748    "ubtbWrong"   -> (0x1031, "perfCntubtbWrong"),
749    "btbRight"    -> (0x1032, "perfCntbtbRight"),
750    "btbWrong"    -> (0x1033, "perfCntbtbWrong"),
751    "tageRight"   -> (0x1034, "perfCnttageRight"),
752    "tageWrong"   -> (0x1035, "perfCnttageWrong"),
753    "loopRight"   -> (0x1036, "perfCntloopRight"),
754    "loopWrong"   -> (0x1037, "perfCntloopWrong")
755    // "L2cacheHit" -> (0x1023, "perfCntCondL2cacheHit")
756  ) ++ (
757    (0 until dcacheParameters.nMissEntries).map(i =>
758      ("DCacheMissQueuePenalty" + Integer.toString(i, 10), (0x102a + i, "perfCntDCacheMissQueuePenaltyEntry" + Integer.toString(i, 10)))
759    ).toMap
760  ) ++ (
761    (0 until icacheParameters.nMissEntries).map(i =>
762      ("ICacheMissQueuePenalty" + Integer.toString(i, 10), (0x102a + dcacheParameters.nMissEntries + i, "perfCntICacheMissQueuePenaltyEntry" + Integer.toString(i, 10)))
763    ).toMap
764  ) ++ (
765    (0 until l1plusPrefetcherParameters.nEntries).map(i =>
766      ("L1+PrefetchPenalty" + Integer.toString(i, 10), (0x102a + dcacheParameters.nMissEntries + icacheParameters.nMissEntries + i, "perfCntL1plusPrefetchPenaltyEntry" + Integer.toString(i, 10)))
767    ).toMap
768  ) ++ (
769    (0 until l2PrefetcherParameters.nEntries).map(i =>
770      ("L2PrefetchPenalty" + Integer.toString(i, 10), (0x102a + dcacheParameters.nMissEntries + icacheParameters.nMissEntries + l1plusPrefetcherParameters.nEntries + i, "perfCntL2PrefetchPenaltyEntry" + Integer.toString(i, 10)))
771    ).toMap
772  )
773
774  emuPerfCntList.foreach {
775    case (_, (address, boringId)) =>
776      if (hasEmuPerfCnt) {
777        ExcitingUtils.addSink(emuPerfCntCond(address & 0x7f), boringId, ConnectionType.Perf)
778      }
779      // if (!hasEmuPerfCnt) {
780      //   // do not enable perfcnts except for Mcycle and Minstret
781      //   if (address != emuPerfCntList("Mcycle")._1 && address != emuPerfCntList("Minstret")._1) {
782      //     perfCntCond(address & 0x7f) := false.B
783      //   }
784      // }
785  }
786
787  val xstrap = WireInit(false.B)
788  if (!env.FPGAPlatform && EnableBPU) {
789    ExcitingUtils.addSink(xstrap, "XSTRAP", ConnectionType.Debug)
790  }
791  def readWithScala(addr: Int): UInt = mapping(addr)._1
792
793  if (!env.FPGAPlatform) {
794
795    // display all perfcnt when nooptrap is executed
796    when (xstrap) {
797      printf("======== PerfCnt =========\n")
798      emuPerfCntList.toSeq.sortBy(_._2._1).foreach { case (str, (address, _)) =>
799        printf("%d <- " + str + "\n", readWithScala(address))
800      }
801    }
802
803    val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
804    ExcitingUtils.addSource(difftestIntrNO, "difftestIntrNOfromCSR")
805    ExcitingUtils.addSource(causeNO, "difftestCausefromCSR")
806    ExcitingUtils.addSource(priviledgeMode, "difftestMode", Debug)
807    ExcitingUtils.addSource(mstatus, "difftestMstatus", Debug)
808    ExcitingUtils.addSource(mstatus & sstatusRmask, "difftestSstatus", Debug)
809    ExcitingUtils.addSource(mepc, "difftestMepc", Debug)
810    ExcitingUtils.addSource(sepc, "difftestSepc", Debug)
811    ExcitingUtils.addSource(mtval, "difftestMtval", Debug)
812    ExcitingUtils.addSource(stval, "difftestStval", Debug)
813    ExcitingUtils.addSource(mtvec, "difftestMtvec", Debug)
814    ExcitingUtils.addSource(stvec, "difftestStvec", Debug)
815    ExcitingUtils.addSource(mcause, "difftestMcause", Debug)
816    ExcitingUtils.addSource(scause, "difftestScause", Debug)
817    ExcitingUtils.addSource(satp, "difftestSatp", Debug)
818    ExcitingUtils.addSource(mipReg, "difftestMip", Debug)
819    ExcitingUtils.addSource(mie, "difftestMie", Debug)
820    ExcitingUtils.addSource(mscratch, "difftestMscratch", Debug)
821    ExcitingUtils.addSource(sscratch, "difftestSscratch", Debug)
822    ExcitingUtils.addSource(mideleg, "difftestMideleg", Debug)
823    ExcitingUtils.addSource(medeleg, "difftestMedeleg", Debug)
824  }
825}
826