xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision a273862e37f1d43bee748f2a6353320a2f52f6f4)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package xiangshan.backend.fu
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import freechips.rocketchip.util._
23import utils.MaskedRegMap.WritableMask
24import utils._
25import xiangshan._
26import xiangshan.backend._
27import xiangshan.cache._
28import xiangshan.frontend.BPUCtrl
29import xiangshan.backend.fu.util._
30import difftest._
31
32trait HasExceptionNO {
33  def instrAddrMisaligned = 0
34  def instrAccessFault    = 1
35  def illegalInstr        = 2
36  def breakPoint          = 3
37  def loadAddrMisaligned  = 4
38  def loadAccessFault     = 5
39  def storeAddrMisaligned = 6
40  def storeAccessFault    = 7
41  def ecallU              = 8
42  def ecallS              = 9
43  def ecallM              = 11
44  def instrPageFault      = 12
45  def loadPageFault       = 13
46  def storePageFault      = 15
47
48  def singleStep          = 14
49
50  val ExcPriority = Seq(
51    breakPoint, // TODO: different BP has different priority
52    singleStep,
53    instrPageFault,
54    instrAccessFault,
55    illegalInstr,
56    instrAddrMisaligned,
57    ecallM, ecallS, ecallU,
58    storePageFault,
59    loadPageFault,
60    storeAccessFault,
61    loadAccessFault,
62    storeAddrMisaligned,
63    loadAddrMisaligned
64  )
65  val frontendSet = List(
66    // instrAddrMisaligned,
67    instrAccessFault,
68    illegalInstr,
69    instrPageFault
70  )
71  val csrSet = List(
72    illegalInstr,
73    breakPoint,
74    ecallU,
75    ecallS,
76    ecallM
77  )
78  val loadUnitSet = List(
79    loadAddrMisaligned,
80    loadAccessFault,
81    loadPageFault
82  )
83  val storeUnitSet = List(
84    storeAddrMisaligned,
85    storeAccessFault,
86    storePageFault
87  )
88  val atomicsUnitSet = (loadUnitSet ++ storeUnitSet).distinct
89  val allPossibleSet = (frontendSet ++ csrSet ++ loadUnitSet ++ storeUnitSet).distinct
90  val csrWbCount = (0 until 16).map(i => if (csrSet.contains(i)) 1 else 0)
91  val loadWbCount = (0 until 16).map(i => if (loadUnitSet.contains(i)) 1 else 0)
92  val storeWbCount = (0 until 16).map(i => if (storeUnitSet.contains(i)) 1 else 0)
93  val atomicsWbCount = (0 until 16).map(i => if (atomicsUnitSet.contains(i)) 1 else 0)
94  val writebackCount = (0 until 16).map(i => csrWbCount(i) + atomicsWbCount(i) + loadWbCount(i) + 2 * storeWbCount(i))
95  def partialSelect(vec: Vec[Bool], select: Seq[Int], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = {
96    if (dontCareBits) {
97      val new_vec = Wire(ExceptionVec())
98      new_vec := DontCare
99      select.map(i => new_vec(i) := vec(i))
100      return new_vec
101    }
102    else if (falseBits) {
103      val new_vec = Wire(ExceptionVec())
104      new_vec.map(_ := false.B)
105      select.map(i => new_vec(i) := vec(i))
106      return new_vec
107    }
108    else {
109      val new_vec = Wire(Vec(select.length, Bool()))
110      select.zipWithIndex.map{ case(s, i) => new_vec(i) := vec(s) }
111      return new_vec
112    }
113  }
114  def selectFrontend(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
115    partialSelect(vec, frontendSet, dontCareBits, falseBits)
116  def selectCSR(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
117    partialSelect(vec, csrSet, dontCareBits, falseBits)
118  def selectLoad(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
119    partialSelect(vec, loadUnitSet, dontCareBits, falseBits)
120  def selectStore(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
121    partialSelect(vec, storeUnitSet, dontCareBits, falseBits)
122  def selectAtomics(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
123    partialSelect(vec, atomicsUnitSet, dontCareBits, falseBits)
124  def selectAll(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
125    partialSelect(vec, allPossibleSet, dontCareBits, falseBits)
126}
127
128class FpuCsrIO extends Bundle {
129  val fflags = Output(Valid(UInt(5.W)))
130  val isIllegal = Output(Bool())
131  val dirty_fs = Output(Bool())
132  val frm = Input(UInt(3.W))
133}
134
135
136class PerfCounterIO(implicit p: Parameters) extends XSBundle {
137  val perfEventsFrontend  = (new PerfEventsBundle(numCSRPCntFrontend ))
138  val perfEventsCtrl      = (new PerfEventsBundle(numCSRPCntCtrl     ))
139  val perfEventsLsu       = (new PerfEventsBundle(numCSRPCntLsu      ))
140  val perfEventsHc        = Vec(numPCntHc * coreParams.L2NBanks,(UInt(6.W)))
141  val retiredInstr = UInt(3.W)
142  val frontendInfo = new Bundle {
143    val ibufFull  = Bool()
144    val bpuInfo = new Bundle {
145      val bpRight = UInt(XLEN.W)
146      val bpWrong = UInt(XLEN.W)
147    }
148  }
149  val ctrlInfo = new Bundle {
150    val robFull   = Bool()
151    val intdqFull = Bool()
152    val fpdqFull  = Bool()
153    val lsdqFull  = Bool()
154  }
155  val memInfo = new Bundle {
156    val sqFull = Bool()
157    val lqFull = Bool()
158    val dcacheMSHRFull = Bool()
159  }
160
161  val cacheInfo = new Bundle {
162    val l2MSHRFull = Bool()
163    val l3MSHRFull = Bool()
164    val l2nAcquire = UInt(XLEN.W)
165    val l2nAcquireMiss = UInt(XLEN.W)
166    val l3nAcquire = UInt(XLEN.W)
167    val l3nAcquireMiss = UInt(XLEN.W)
168  }
169}
170
171class CSRFileIO(implicit p: Parameters) extends XSBundle {
172  val hartId = Input(UInt(64.W))
173  // output (for func === CSROpType.jmp)
174  val perf = Input(new PerfCounterIO)
175  val isPerfCnt = Output(Bool())
176  // to FPU
177  val fpu = Flipped(new FpuCsrIO)
178  // from rob
179  val exception = Flipped(ValidIO(new ExceptionInfo))
180  // to ROB
181  val isXRet = Output(Bool())
182  val trapTarget = Output(UInt(VAddrBits.W))
183  val interrupt = Output(Bool())
184  // from LSQ
185  val memExceptionVAddr = Input(UInt(VAddrBits.W))
186  // from outside cpu,externalInterrupt
187  val externalInterrupt = new ExternalInterruptIO
188  // TLB
189  val tlb = Output(new TlbCsrBundle)
190  // Debug Mode
191  val singleStep = Output(Bool())
192  val debugMode = Output(Bool())
193  // Custom microarchiture ctrl signal
194  val customCtrl = Output(new CustomCSRCtrlIO)
195  val distributedUpdate = Flipped(new DistributedCSRUpdateReq)
196  // to Fence to disable sfence
197  val disableSfence = Output(Bool())
198  // distributed csr w
199}
200
201class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMPMethod with PMAMethod
202{
203  val csrio = IO(new CSRFileIO)
204
205  val cfIn = io.in.bits.uop.cf
206  val cfOut = Wire(new CtrlFlow)
207  cfOut := cfIn
208  val flushPipe = Wire(Bool())
209
210  val (valid, src1, src2, func) = (
211    io.in.valid,
212    io.in.bits.src(0),
213    io.in.bits.uop.ctrl.imm,
214    io.in.bits.uop.ctrl.fuOpType
215  )
216
217  // CSR define
218
219  class Priv extends Bundle {
220    val m = Output(Bool())
221    val h = Output(Bool())
222    val s = Output(Bool())
223    val u = Output(Bool())
224  }
225
226  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
227
228  class DcsrStruct extends Bundle {
229    val xdebugver = Output(UInt(2.W))
230    val zero4 = Output(UInt(2.W))
231    val zero3 = Output(UInt(12.W))
232    val ebreakm = Output(Bool())
233    val ebreakh = Output(Bool())
234    val ebreaks = Output(Bool())
235    val ebreaku = Output(Bool())
236    val zero2 = Output(Bool())
237    val stopcycle = Output(Bool())
238    val stoptime = Output(Bool())
239    val cause = Output(UInt(3.W))
240    val zero1 = Output(UInt(3.W))
241    val step = Output(Bool())
242    val prv = Output(UInt(2.W))
243  }
244
245  class MstatusStruct extends Bundle {
246    val sd = Output(UInt(1.W))
247
248    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
249    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
250    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
251    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
252
253    val tsr = Output(UInt(1.W))
254    val tw = Output(UInt(1.W))
255    val tvm = Output(UInt(1.W))
256    val mxr = Output(UInt(1.W))
257    val sum = Output(UInt(1.W))
258    val mprv = Output(UInt(1.W))
259    val xs = Output(UInt(2.W))
260    val fs = Output(UInt(2.W))
261    val mpp = Output(UInt(2.W))
262    val hpp = Output(UInt(2.W))
263    val spp = Output(UInt(1.W))
264    val pie = new Priv
265    val ie = new Priv
266    assert(this.getWidth == XLEN)
267  }
268
269  class Interrupt extends Bundle {
270//  val d = Output(Bool())    // Debug
271    val e = new Priv
272    val t = new Priv
273    val s = new Priv
274  }
275
276  // Debug CSRs
277  val dcsr = RegInit(UInt(32.W), 0x4000b010.U)
278  val dpc = Reg(UInt(64.W))
279  val dscratch = Reg(UInt(64.W))
280  val dscratch1 = Reg(UInt(64.W))
281  val debugMode = RegInit(false.B)
282  val debugIntrEnable = RegInit(true.B)
283  csrio.debugMode := debugMode
284
285  val dpcPrev = RegNext(dpc)
286  XSDebug(dpcPrev =/= dpc, "Debug Mode: dpc is altered! Current is %x, previous is %x.", dpc, dpcPrev)
287
288  // dcsr value table
289  // | debugver | 0100
290  // | zero     | 10 bits of 0
291  // | ebreakvs | 0
292  // | ebreakvu | 0
293  // | ebreakm  | 1 if ebreak enters debug
294  // | zero     | 0
295  // | ebreaks  |
296  // | ebreaku  |
297  // | stepie   | 0 disable interrupts in singlestep
298  // | stopcount| stop counter, 0
299  // | stoptime | stop time, 0
300  // | cause    | 3 bits read only
301  // | v        | 0
302  // | mprven   | 1
303  // | nmip     | read only
304  // | step     |
305  // | prv      | 2 bits
306
307  val dcsrData = Wire(new DcsrStruct)
308  dcsrData := dcsr.asTypeOf(new DcsrStruct)
309  val dcsrMask = ZeroExt(GenMask(15) | GenMask(13, 11) | GenMask(2, 0), XLEN)// Dcsr write mask
310  def dcsrUpdateSideEffect(dcsr: UInt): UInt = {
311    val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct))
312    val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11
313    dcsrNew
314  }
315  csrio.singleStep := dcsrData.step
316
317  // Machine-Level CSRs
318
319  val mtvec = RegInit(UInt(XLEN.W), 0.U)
320  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
321  val mcause = RegInit(UInt(XLEN.W), 0.U)
322  val mtval = RegInit(UInt(XLEN.W), 0.U)
323  val mepc = Reg(UInt(XLEN.W))
324
325  val mie = RegInit(0.U(XLEN.W))
326  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
327  val mipReg  = RegInit(0.U(XLEN.W))
328  val mipFixMask = ZeroExt(GenMask(9) | GenMask(5) | GenMask(1), XLEN)
329  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
330
331  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt()
332  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt()
333  var extList = List('a', 's', 'i', 'u')
334  if (HasMExtension) { extList = extList :+ 'm' }
335  if (HasCExtension) { extList = extList :+ 'c' }
336  if (HasFPU) { extList = extList ++ List('f', 'd') }
337  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
338  val misa = RegInit(UInt(XLEN.W), misaInitVal)
339
340  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
341  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
342
343  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
344  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
345  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
346  val mhartid = RegInit(UInt(XLEN.W), csrio.hartId) // the hardware thread running the code
347  val mstatus = RegInit(UInt(XLEN.W), 0.U)
348
349  // mstatus Value Table
350  // | sd   |
351  // | pad1 |
352  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
353  // | uxl  | hardlinked to 00
354  // | pad0 |
355  // | tsr  |
356  // | tw   |
357  // | tvm  |
358  // | mxr  |
359  // | sum  |
360  // | mprv |
361  // | xs   | 00 |
362  // | fs   | 00 |
363  // | mpp  | 00 |
364  // | hpp  | 00 |
365  // | spp  | 0 |
366  // | pie  | 0000 | pie.h is used as UBE
367  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
368
369  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
370  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
371    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
372    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
373    mstatusNew
374  }
375
376  val mstatusMask = (~ZeroExt((
377    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
378    GenMask(37) | // MBE
379    GenMask(36) | // SBE
380    GenMask(6)    // UBE
381  ), 64)).asUInt()
382
383  val medeleg = RegInit(UInt(XLEN.W), 0.U)
384  val mideleg = RegInit(UInt(XLEN.W), 0.U)
385  val mscratch = RegInit(UInt(XLEN.W), 0.U)
386
387  // PMP Mapping
388  val pmp = Wire(Vec(NumPMP, new PMPEntry())) // just used for method parameter
389  val pma = Wire(Vec(NumPMA, new PMPEntry())) // just used for method parameter
390  val pmpMapping = pmp_gen_mapping(pmp_init, NumPMP, PmpcfgBase, PmpaddrBase, pmp)
391  val pmaMapping = pmp_gen_mapping(pma_init, NumPMA, PmacfgBase, PmaaddrBase, pma)
392
393  // Superviser-Level CSRs
394
395  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
396  val sstatusWmask = "hc6122".U(XLEN.W)
397  // Sstatus Write Mask
398  // -------------------------------------------------------
399  //    19           9   5     2
400  // 0  1100 0000 0001 0010 0010
401  // 0  c    0    1    2    2
402  // -------------------------------------------------------
403  val sstatusRmask = sstatusWmask | "h8000000300018000".U
404  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
405  val stvec = RegInit(UInt(XLEN.W), 0.U)
406  // val sie = RegInit(0.U(XLEN.W))
407  val sieMask = "h222".U & mideleg
408  val sipMask = "h222".U & mideleg
409  val sipWMask = "h2".U(XLEN.W) // ssip is writeable in smode
410  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
411  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
412  // val satpMask = "h80000fffffffffff".U(XLEN.W) // disable asid, mode can only be 8 / 0
413  // TODO: use config to control the length of asid
414  // val satpMask = "h8fffffffffffffff".U(XLEN.W) // enable asid, mode can only be 8 / 0
415  val satpMask = Cat("h8".U(4.W),Asid_true_mask(AsidLength),"hfffffffffff".U((XLEN - 4 - 16).W))
416  val sepc = RegInit(UInt(XLEN.W), 0.U)
417  val scause = RegInit(UInt(XLEN.W), 0.U)
418  val stval = Reg(UInt(XLEN.W))
419  val sscratch = RegInit(UInt(XLEN.W), 0.U)
420  val scounteren = RegInit(UInt(XLEN.W), 0.U)
421
422  // sbpctl
423  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
424  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
425  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
426  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
427  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
428  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
429  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
430  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
431  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
432
433  // spfctl Bit 0: L1plusCache Prefetcher Enable
434  // spfctl Bit 1: L2Cache Prefetcher Enable
435  val spfctl = RegInit(UInt(XLEN.W), "h3".U)
436  csrio.customCtrl.l1plus_pf_enable := spfctl(0)
437  csrio.customCtrl.l2_pf_enable := spfctl(1)
438
439  // sdsid: Differentiated Services ID
440  val sdsid = RegInit(UInt(XLEN.W), 0.U)
441  csrio.customCtrl.dsid := sdsid
442
443  // slvpredctl: load violation predict settings
444  val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17
445  csrio.customCtrl.lvpred_disable := slvpredctl(0)
446  csrio.customCtrl.no_spec_load := slvpredctl(1)
447  csrio.customCtrl.storeset_wait_store := slvpredctl(2)
448  csrio.customCtrl.storeset_no_fast_wakeup := slvpredctl(3)
449  csrio.customCtrl.lvpred_timeout := slvpredctl(8, 4)
450
451  // smblockctl: memory block configurations
452  // bits 0-3: store buffer flush threshold (default: 8 entries)
453  val smblockctl_init_val =
454    ("hf".U & StoreBufferThreshold.U) |
455    (EnableLdVioCheckAfterReset.B.asUInt << 4)
456  val smblockctl = RegInit(UInt(XLEN.W), smblockctl_init_val)
457  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
458  // bits 4: enable load load violation check
459  csrio.customCtrl.ldld_vio_check := smblockctl(4)
460
461  val srnctl = RegInit(UInt(XLEN.W), "h3".U)
462  csrio.customCtrl.move_elim_enable := srnctl(0)
463  csrio.customCtrl.svinval_enable := srnctl(1)
464
465  val tlbBundle = Wire(new TlbCsrBundle)
466  tlbBundle.satp.apply(satp)
467
468  csrio.tlb := tlbBundle
469
470  // User-Level CSRs
471  val uepc = Reg(UInt(XLEN.W))
472
473  // fcsr
474  class FcsrStruct extends Bundle {
475    val reserved = UInt((XLEN-3-5).W)
476    val frm = UInt(3.W)
477    val fflags = UInt(5.W)
478    assert(this.getWidth == XLEN)
479  }
480  val fcsr = RegInit(0.U(XLEN.W))
481  // set mstatus->sd and mstatus->fs when true
482  val csrw_dirty_fp_state = WireInit(false.B)
483
484  def frm_wfn(wdata: UInt): UInt = {
485    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
486    csrw_dirty_fp_state := true.B
487    fcsrOld.frm := wdata(2,0)
488    fcsrOld.asUInt()
489  }
490  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
491
492  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
493    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
494    val fcsrNew = WireInit(fcsrOld)
495    csrw_dirty_fp_state := true.B
496    if (update) {
497      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
498    } else {
499      fcsrNew.fflags := wdata(4,0)
500    }
501    fcsrNew.asUInt()
502  }
503  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
504
505  def fcsr_wfn(wdata: UInt): UInt = {
506    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
507    csrw_dirty_fp_state := true.B
508    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
509  }
510
511  val fcsrMapping = Map(
512    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
513    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
514    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
515  )
516
517  // Hart Priviledge Mode
518  val priviledgeMode = RegInit(UInt(2.W), ModeM)
519
520  // Emu perfcnt
521  val hasEmuPerfCnt = !env.FPGAPlatform
522  val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3
523
524  val emuPerfCnts    = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W)))
525  val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B))
526  (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
527
528  val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i)))
529  val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32)))
530  println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}")
531
532  //val perfEventscounten = List.fill(nrPerfCnts)(RegInit(false(Bool())))
533  // Perf Counter
534  val nrPerfCnts = 29  // 3...31
535  val priviledgeModeOH = UIntToOH(priviledgeMode)
536  val perfEventscounten = RegInit(0.U.asTypeOf(Vec(nrPerfCnts, Bool())))
537  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
538  val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
539  for (i <-0 until nrPerfCnts) {
540    perfEventscounten(i) := (Cat(perfEvents(i)(62),perfEvents(i)(61),(perfEvents(i)(61,60))) & priviledgeModeOH).orR
541  }
542
543  val hpmEvents = Wire(new PerfEventsBundle(numPCntHc * coreParams.L2NBanks))
544  val pfevent = Module(new PFEvent)
545  pfevent.io.distribute_csr := csrio.customCtrl.distribute_csr
546  for(i <- 0 until numPCntHc * coreParams.L2NBanks) {
547    hpmEvents.perf_events(i).incr_step := csrio.perf.perfEventsHc(i)
548  }
549
550  val hpm_hc = Module(new HPerfmonitor(numPCntHc * coreParams.L2NBanks,numCSRPCntHc))
551  val csrevents = pfevent.io.hpmevent.slice(24,29)
552  hpm_hc.io.hpm_event := csrevents
553  hpm_hc.io.events_sets := hpmEvents
554  val mcountinhibit = RegInit(0.U(XLEN.W))
555  val mcycle = RegInit(0.U(XLEN.W))
556  mcycle := mcycle + 1.U
557  val minstret = RegInit(0.U(XLEN.W))
558  minstret := minstret + RegNext(csrio.perf.retiredInstr)
559  perfCnts( 0)  := Mux((mcountinhibit( 3) | perfEventscounten( 0)),perfCnts( 0) , (perfCnts( 0) + RegNext(csrio.perf.perfEventsFrontend.perf_events(0 ).incr_step)))
560  perfCnts( 1)  := Mux((mcountinhibit( 4) | perfEventscounten( 1)),perfCnts( 1) , (perfCnts( 1) + RegNext(csrio.perf.perfEventsFrontend.perf_events(1 ).incr_step)))
561  perfCnts( 2)  := Mux((mcountinhibit( 5) | perfEventscounten( 2)),perfCnts( 2) , (perfCnts( 2) + RegNext(csrio.perf.perfEventsFrontend.perf_events(2 ).incr_step)))
562  perfCnts( 3)  := Mux((mcountinhibit( 6) | perfEventscounten( 3)),perfCnts( 3) , (perfCnts( 3) + RegNext(csrio.perf.perfEventsFrontend.perf_events(3 ).incr_step)))
563  perfCnts( 4)  := Mux((mcountinhibit( 7) | perfEventscounten( 4)),perfCnts( 4) , (perfCnts( 4) + RegNext(csrio.perf.perfEventsFrontend.perf_events(4 ).incr_step)))
564  perfCnts( 5)  := Mux((mcountinhibit( 8) | perfEventscounten( 5)),perfCnts( 5) , (perfCnts( 5) + RegNext(csrio.perf.perfEventsFrontend.perf_events(5 ).incr_step)))
565  perfCnts( 6)  := Mux((mcountinhibit( 9) | perfEventscounten( 6)),perfCnts( 6) , (perfCnts( 6) + RegNext(csrio.perf.perfEventsFrontend.perf_events(6 ).incr_step)))
566  perfCnts( 7)  := Mux((mcountinhibit(10) | perfEventscounten( 7)),perfCnts( 7) , (perfCnts( 7) + RegNext(csrio.perf.perfEventsFrontend.perf_events(7 ).incr_step)))
567  perfCnts( 8)  := Mux((mcountinhibit(11) | perfEventscounten( 8)),perfCnts( 8) , (perfCnts( 8) + RegNext(csrio.perf.perfEventsCtrl.perf_events(0 ).incr_step)))
568  perfCnts( 9)  := Mux((mcountinhibit(12) | perfEventscounten( 9)),perfCnts( 9) , (perfCnts( 9) + RegNext(csrio.perf.perfEventsCtrl.perf_events(1 ).incr_step)))
569  perfCnts(10)  := Mux((mcountinhibit(13) | perfEventscounten(10)),perfCnts(10) , (perfCnts(10) + RegNext(csrio.perf.perfEventsCtrl.perf_events(2 ).incr_step)))
570  perfCnts(11)  := Mux((mcountinhibit(14) | perfEventscounten(11)),perfCnts(11) , (perfCnts(11) + RegNext(csrio.perf.perfEventsCtrl.perf_events(3 ).incr_step)))
571  perfCnts(12)  := Mux((mcountinhibit(15) | perfEventscounten(12)),perfCnts(12) , (perfCnts(12) + RegNext(csrio.perf.perfEventsCtrl.perf_events(4 ).incr_step)))
572  perfCnts(13)  := Mux((mcountinhibit(16) | perfEventscounten(13)),perfCnts(13) , (perfCnts(13) + RegNext(csrio.perf.perfEventsCtrl.perf_events(5 ).incr_step)))
573  perfCnts(14)  := Mux((mcountinhibit(17) | perfEventscounten(14)),perfCnts(14) , (perfCnts(14) + RegNext(csrio.perf.perfEventsCtrl.perf_events(6 ).incr_step)))
574  perfCnts(15)  := Mux((mcountinhibit(18) | perfEventscounten(15)),perfCnts(15) , (perfCnts(15) + RegNext(csrio.perf.perfEventsCtrl.perf_events(7 ).incr_step)))
575  perfCnts(16)  := Mux((mcountinhibit(19) | perfEventscounten(16)),perfCnts(16) , (perfCnts(16) + RegNext(csrio.perf.perfEventsLsu.perf_events(0 ).incr_step)))
576  perfCnts(17)  := Mux((mcountinhibit(20) | perfEventscounten(17)),perfCnts(17) , (perfCnts(17) + RegNext(csrio.perf.perfEventsLsu.perf_events(1 ).incr_step)))
577  perfCnts(18)  := Mux((mcountinhibit(21) | perfEventscounten(18)),perfCnts(18) , (perfCnts(18) + RegNext(csrio.perf.perfEventsLsu.perf_events(2 ).incr_step)))
578  perfCnts(19)  := Mux((mcountinhibit(22) | perfEventscounten(19)),perfCnts(19) , (perfCnts(19) + RegNext(csrio.perf.perfEventsLsu.perf_events(3 ).incr_step)))
579  perfCnts(20)  := Mux((mcountinhibit(23) | perfEventscounten(20)),perfCnts(20) , (perfCnts(20) + RegNext(csrio.perf.perfEventsLsu.perf_events(4 ).incr_step)))
580  perfCnts(21)  := Mux((mcountinhibit(24) | perfEventscounten(21)),perfCnts(21) , (perfCnts(21) + RegNext(csrio.perf.perfEventsLsu.perf_events(5 ).incr_step)))
581  perfCnts(22)  := Mux((mcountinhibit(25) | perfEventscounten(22)),perfCnts(22) , (perfCnts(22) + RegNext(csrio.perf.perfEventsLsu.perf_events(6 ).incr_step)))
582  perfCnts(23)  := Mux((mcountinhibit(26) | perfEventscounten(23)),perfCnts(23) , (perfCnts(23) + RegNext(csrio.perf.perfEventsLsu.perf_events(7 ).incr_step)))
583  perfCnts(24)  := Mux((mcountinhibit(27) | perfEventscounten(24)),perfCnts(24) , (perfCnts(24) + RegNext(hpm_hc.io.events_selected.perf_events(0 ).incr_step)))
584  perfCnts(25)  := Mux((mcountinhibit(28) | perfEventscounten(25)),perfCnts(25) , (perfCnts(25) + RegNext(hpm_hc.io.events_selected.perf_events(1 ).incr_step)))
585  perfCnts(26)  := Mux((mcountinhibit(29) | perfEventscounten(26)),perfCnts(26) , (perfCnts(26) + RegNext(hpm_hc.io.events_selected.perf_events(2 ).incr_step)))
586  perfCnts(27)  := Mux((mcountinhibit(30) | perfEventscounten(27)),perfCnts(27) , (perfCnts(27) + RegNext(hpm_hc.io.events_selected.perf_events(3 ).incr_step)))
587  perfCnts(28)  := Mux((mcountinhibit(31) | perfEventscounten(28)),perfCnts(28) , (perfCnts(28) + RegNext(hpm_hc.io.events_selected.perf_events(4 ).incr_step)))
588
589  // CSR reg map
590  val basicPrivMapping = Map(
591
592    //--- User Trap Setup ---
593    // MaskedRegMap(Ustatus, ustatus),
594    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
595    // MaskedRegMap(Utvec, utvec),
596
597    //--- User Trap Handling ---
598    // MaskedRegMap(Uscratch, uscratch),
599    // MaskedRegMap(Uepc, uepc),
600    // MaskedRegMap(Ucause, ucause),
601    // MaskedRegMap(Utval, utval),
602    // MaskedRegMap(Uip, uip),
603
604    //--- User Counter/Timers ---
605    // MaskedRegMap(Cycle, cycle),
606    // MaskedRegMap(Time, time),
607    // MaskedRegMap(Instret, instret),
608
609    //--- Supervisor Trap Setup ---
610    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
611    // MaskedRegMap(Sedeleg, Sedeleg),
612    // MaskedRegMap(Sideleg, Sideleg),
613    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
614    MaskedRegMap(Stvec, stvec),
615    MaskedRegMap(Scounteren, scounteren),
616
617    //--- Supervisor Trap Handling ---
618    MaskedRegMap(Sscratch, sscratch),
619    MaskedRegMap(Sepc, sepc),
620    MaskedRegMap(Scause, scause),
621    MaskedRegMap(Stval, stval),
622    MaskedRegMap(Sip, mip.asUInt, sipWMask, MaskedRegMap.Unwritable, sipMask),
623
624    //--- Supervisor Protection and Translation ---
625    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
626
627    //--- Supervisor Custom Read/Write Registers
628    MaskedRegMap(Sbpctl, sbpctl),
629    MaskedRegMap(Spfctl, spfctl),
630    MaskedRegMap(Sdsid, sdsid),
631    MaskedRegMap(Slvpredctl, slvpredctl),
632    MaskedRegMap(Smblockctl, smblockctl),
633    MaskedRegMap(Srnctl, srnctl),
634
635    //--- Machine Information Registers ---
636    MaskedRegMap(Mvendorid, mvendorid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
637    MaskedRegMap(Marchid, marchid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
638    MaskedRegMap(Mimpid, mimpid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
639    MaskedRegMap(Mhartid, mhartid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
640
641    //--- Machine Trap Setup ---
642    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
643    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
644    MaskedRegMap(Medeleg, medeleg, "hf3ff".U(XLEN.W)),
645    MaskedRegMap(Mideleg, mideleg, "h222".U(XLEN.W)),
646    MaskedRegMap(Mie, mie),
647    MaskedRegMap(Mtvec, mtvec),
648    MaskedRegMap(Mcounteren, mcounteren),
649
650    //--- Machine Trap Handling ---
651    MaskedRegMap(Mscratch, mscratch),
652    MaskedRegMap(Mepc, mepc),
653    MaskedRegMap(Mcause, mcause),
654    MaskedRegMap(Mtval, mtval),
655    MaskedRegMap(Mip, mip.asUInt, 0.U(XLEN.W), MaskedRegMap.Unwritable),
656
657    //--- Debug Mode ---
658    MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
659    MaskedRegMap(Dpc, dpc),
660    MaskedRegMap(Dscratch, dscratch),
661    MaskedRegMap(Dscratch1, dscratch1)
662  )
663
664  var perfCntMapping = Map(
665    MaskedRegMap(Mcountinhibit, mcountinhibit),
666    MaskedRegMap(Mcycle, mcycle),
667    MaskedRegMap(Minstret, minstret),
668    MaskedRegMap(Mhpmevent3 , perfEvents( 0)),
669    MaskedRegMap(Mhpmevent4 , perfEvents( 1)),
670    MaskedRegMap(Mhpmevent5 , perfEvents( 2)),
671    MaskedRegMap(Mhpmevent6 , perfEvents( 3)),
672    MaskedRegMap(Mhpmevent7 , perfEvents( 4)),
673    MaskedRegMap(Mhpmevent8 , perfEvents( 5)),
674    MaskedRegMap(Mhpmevent9 , perfEvents( 6)),
675    MaskedRegMap(Mhpmevent10, perfEvents( 7)),
676    MaskedRegMap(Mhpmevent11, perfEvents( 8)),
677    MaskedRegMap(Mhpmevent12, perfEvents( 9)),
678    MaskedRegMap(Mhpmevent13, perfEvents(10)),
679    MaskedRegMap(Mhpmevent14, perfEvents(11)),
680    MaskedRegMap(Mhpmevent15, perfEvents(12)),
681    MaskedRegMap(Mhpmevent16, perfEvents(13)),
682    MaskedRegMap(Mhpmevent17, perfEvents(14)),
683    MaskedRegMap(Mhpmevent18, perfEvents(15)),
684    MaskedRegMap(Mhpmevent19, perfEvents(16)),
685    MaskedRegMap(Mhpmevent20, perfEvents(17)),
686    MaskedRegMap(Mhpmevent21, perfEvents(18)),
687    MaskedRegMap(Mhpmevent22, perfEvents(19)),
688    MaskedRegMap(Mhpmevent23, perfEvents(20)),
689    MaskedRegMap(Mhpmevent24, perfEvents(21)),
690    MaskedRegMap(Mhpmevent25, perfEvents(22)),
691    MaskedRegMap(Mhpmevent26, perfEvents(23)),
692    MaskedRegMap(Mhpmevent27, perfEvents(24)),
693    MaskedRegMap(Mhpmevent28, perfEvents(25)),
694    MaskedRegMap(Mhpmevent29, perfEvents(26)),
695    MaskedRegMap(Mhpmevent30, perfEvents(27)),
696    MaskedRegMap(Mhpmevent31, perfEvents(28)),
697    MaskedRegMap(Mhpmcounter3 , perfCnts( 0)),
698    MaskedRegMap(Mhpmcounter4 , perfCnts( 1)),
699    MaskedRegMap(Mhpmcounter5 , perfCnts( 2)),
700    MaskedRegMap(Mhpmcounter6 , perfCnts( 3)),
701    MaskedRegMap(Mhpmcounter7 , perfCnts( 4)),
702    MaskedRegMap(Mhpmcounter8 , perfCnts( 5)),
703    MaskedRegMap(Mhpmcounter9 , perfCnts( 6)),
704    MaskedRegMap(Mhpmcounter10, perfCnts( 7)),
705    MaskedRegMap(Mhpmcounter11, perfCnts( 8)),
706    MaskedRegMap(Mhpmcounter12, perfCnts( 9)),
707    MaskedRegMap(Mhpmcounter13, perfCnts(10)),
708    MaskedRegMap(Mhpmcounter14, perfCnts(11)),
709    MaskedRegMap(Mhpmcounter15, perfCnts(12)),
710    MaskedRegMap(Mhpmcounter16, perfCnts(13)),
711    MaskedRegMap(Mhpmcounter17, perfCnts(14)),
712    MaskedRegMap(Mhpmcounter18, perfCnts(15)),
713    MaskedRegMap(Mhpmcounter19, perfCnts(16)),
714    MaskedRegMap(Mhpmcounter20, perfCnts(17)),
715    MaskedRegMap(Mhpmcounter21, perfCnts(18)),
716    MaskedRegMap(Mhpmcounter22, perfCnts(19)),
717    MaskedRegMap(Mhpmcounter23, perfCnts(20)),
718    MaskedRegMap(Mhpmcounter24, perfCnts(21)),
719    MaskedRegMap(Mhpmcounter25, perfCnts(22)),
720    MaskedRegMap(Mhpmcounter26, perfCnts(23)),
721    MaskedRegMap(Mhpmcounter27, perfCnts(24)),
722    MaskedRegMap(Mhpmcounter28, perfCnts(25)),
723    MaskedRegMap(Mhpmcounter29, perfCnts(26)),
724    MaskedRegMap(Mhpmcounter30, perfCnts(27)),
725    MaskedRegMap(Mhpmcounter31, perfCnts(28)),
726  )
727  // TODO: mechanism should be implemented later
728  // val MhpmcounterStart = Mhpmcounter3
729  // val MhpmeventStart   = Mhpmevent3
730  // for (i <- 0 until nrPerfCnts) {
731  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
732  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
733  // }
734
735  val cacheopRegs = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
736    name -> RegInit(0.U(attribute("width").toInt.W))
737  }}
738  val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
739    MaskedRegMap(
740      Scachebase + attribute("offset").toInt,
741      cacheopRegs(name)
742    )
743  }}
744
745  val mapping = basicPrivMapping ++
746                perfCntMapping ++
747                pmpMapping ++
748                pmaMapping ++
749                emuPerfCntsLoMapping ++
750                (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++
751                (if (HasFPU) fcsrMapping else Nil) ++
752                (if (HasCustomCSRCacheOp) cacheopMapping else Nil)
753
754  val addr = src2(11, 0)
755  val csri = ZeroExt(src2(16, 12), XLEN)
756  val rdata = Wire(UInt(XLEN.W))
757  val wdata = LookupTree(func, List(
758    CSROpType.wrt  -> src1,
759    CSROpType.set  -> (rdata | src1),
760    CSROpType.clr  -> (rdata & (~src1).asUInt()),
761    CSROpType.wrti -> csri,
762    CSROpType.seti -> (rdata | csri),
763    CSROpType.clri -> (rdata & (~csri).asUInt())
764  ))
765
766  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U)
767  csrio.isPerfCnt := addrInPerfCnt
768
769  // satp wen check
770  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
771
772  // csr access check, special case
773  val tvmNotPermit = (priviledgeMode === ModeS && mstatusStruct.tvm.asBool)
774  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
775  csrio.disableSfence := tvmNotPermit
776
777  // general CSR wen check
778  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
779  val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
780  val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren)
781  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && accessPermitted
782
783  // Writeable check is ingored.
784  // Currently, write to illegal csr addr will be ignored
785  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
786  io.out.bits.data := rdata
787  io.out.bits.uop := io.in.bits.uop
788  io.out.bits.uop.cf := cfOut
789  io.out.bits.uop.ctrl.flushPipe := flushPipe
790
791  // send distribute csr a w signal
792  csrio.customCtrl.distribute_csr.w.valid := wen && permitted
793  csrio.customCtrl.distribute_csr.w.bits.data := wdata
794  csrio.customCtrl.distribute_csr.w.bits.addr := addr
795
796  // Fix Mip/Sip write
797  val fixMapping = Map(
798    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
799    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask)
800  )
801  val rdataFix = Wire(UInt(XLEN.W))
802  val wdataFix = LookupTree(func, List(
803    CSROpType.wrt  -> src1,
804    CSROpType.set  -> (rdataFix | src1),
805    CSROpType.clr  -> (rdataFix & (~src1).asUInt()),
806    CSROpType.wrti -> csri,
807    CSROpType.seti -> (rdataFix | csri),
808    CSROpType.clri -> (rdataFix & (~csri).asUInt())
809  ))
810  MaskedRegMap.generate(fixMapping, addr, rdataFix, wen && permitted, wdataFix)
811
812  when (csrio.fpu.fflags.valid) {
813    fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits)
814  }
815  // set fs and sd in mstatus
816  when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) {
817    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
818    mstatusNew.fs := "b11".U
819    mstatusNew.sd := true.B
820    mstatus := mstatusNew.asUInt()
821  }
822  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
823
824  // CSR inst decode
825  val isEbreak = addr === privEbreak && func === CSROpType.jmp
826  val isEcall  = addr === privEcall  && func === CSROpType.jmp
827  val isMret   = addr === privMret   && func === CSROpType.jmp
828  val isSret   = addr === privSret   && func === CSROpType.jmp
829  val isUret   = addr === privUret   && func === CSROpType.jmp
830  val isDret   = addr === privDret   && func === CSROpType.jmp
831
832  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
833  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
834
835  // Illegal priviledged operation list
836  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
837
838  // Illegal priviledged instruction check
839  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
840  val isIllegalAccess = !permitted
841  val isIllegalPrivOp = illegalSModeSret
842
843  // expose several csr bits for tlb
844  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
845  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
846  tlbBundle.priv.imode := priviledgeMode
847  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
848
849  // Branch control
850  val retTarget = Wire(UInt(VAddrBits.W))
851  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
852  flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall)
853
854  retTarget := DontCare
855  // val illegalEret = TODO
856
857  when (valid && isDret) {
858    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
859    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
860    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
861    val debugModeNew = WireInit(debugMode)
862    when (dcsr.asTypeOf(new DcsrStruct).prv =/= ModeM) {mstatusNew.mprv := 0.U} //If the new privilege mode is less privileged than M-mode, MPRV in mstatus is cleared.
863    mstatus := mstatusNew.asUInt
864    priviledgeMode := dcsrNew.prv
865    retTarget := dpc(VAddrBits-1, 0)
866    debugModeNew := false.B
867    debugIntrEnable := true.B
868    debugMode := debugModeNew
869    XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget)
870  }
871
872  when (valid && isMret) {
873    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
874    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
875    mstatusNew.ie.m := mstatusOld.pie.m
876    priviledgeMode := mstatusOld.mpp
877    mstatusNew.pie.m := true.B
878    mstatusNew.mpp := ModeU
879    when (mstatusOld.mpp =/= ModeM) { mstatusNew.mprv := 0.U }
880    mstatus := mstatusNew.asUInt
881    // lr := false.B
882    retTarget := mepc(VAddrBits-1, 0)
883  }
884
885  when (valid && isSret && !illegalSModeSret) {
886    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
887    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
888    mstatusNew.ie.s := mstatusOld.pie.s
889    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
890    mstatusNew.pie.s := true.B
891    mstatusNew.spp := ModeU
892    mstatus := mstatusNew.asUInt
893    mstatusNew.mprv := 0.U
894    // lr := false.B
895    retTarget := sepc(VAddrBits-1, 0)
896  }
897
898  when (valid && isUret) {
899    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
900    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
901    // mstatusNew.mpp.m := ModeU //TODO: add mode U
902    mstatusNew.ie.u := mstatusOld.pie.u
903    priviledgeMode := ModeU
904    mstatusNew.pie.u := true.B
905    mstatus := mstatusNew.asUInt
906    retTarget := uepc(VAddrBits-1, 0)
907  }
908
909  io.in.ready := true.B
910  io.out.valid := valid
911
912  val ebreakCauseException = (priviledgeMode === ModeM && dcsrData.ebreakm) || (priviledgeMode === ModeS && dcsrData.ebreaks) || (priviledgeMode === ModeU && dcsrData.ebreaku)
913
914  val csrExceptionVec = WireInit(cfIn.exceptionVec)
915  csrExceptionVec(breakPoint) := io.in.valid && isEbreak && ebreakCauseException
916  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
917  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
918  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
919  // Trigger an illegal instr exception when:
920  // * unimplemented csr is being read/written
921  // * csr access is illegal
922  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
923  cfOut.exceptionVec := csrExceptionVec
924
925  /**
926    * Exception and Intr
927    */
928  val ideleg =  (mideleg & mip.asUInt)
929  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
930    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
931
932  val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable
933  XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!")
934  // send interrupt information to ROB
935  val intrVecEnable = Wire(Vec(12, Bool()))
936  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
937  val intrVec = Cat(debugIntr, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt))
938  val intrBitSet = intrVec.orR()
939  csrio.interrupt := intrBitSet
940  mipWire.t.m := csrio.externalInterrupt.mtip
941  mipWire.s.m := csrio.externalInterrupt.msip
942  mipWire.e.m := csrio.externalInterrupt.meip
943  mipWire.e.s := csrio.externalInterrupt.meip
944
945  // interrupts
946  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
947  val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
948  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO)
949  val raiseDebugIntr = intrNO === IRQ_DEBUG.U && raiseIntr
950
951  // exceptions
952  val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt
953  val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException
954  val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException
955  val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException
956  val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException
957  val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException
958  val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException
959  val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
960  val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
961  val hasbreakPoint = csrio.exception.bits.uop.cf.exceptionVec(breakPoint) && raiseException
962  val hasSingleStep = csrio.exception.bits.uop.cf.exceptionVec(singleStep) && raiseException
963
964  val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
965  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
966  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
967
968  val raiseExceptionIntr = csrio.exception.valid
969
970  val raiseDebugExceptionIntr = !debugMode && hasbreakPoint || raiseDebugIntr || hasSingleStep
971  val ebreakEnterParkLoop = debugMode && raiseExceptionIntr // exception in debug mode (except ebrk) changes cmderr. how ???
972
973  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
974    csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
975  )
976  XSDebug(raiseExceptionIntr,
977    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
978    csrio.exception.bits.uop.cf.pc,
979    mstatus,
980    mideleg,
981    medeleg,
982    priviledgeMode
983  )
984
985  // mtval write logic
986  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
987  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
988    val tval = Mux(
989      hasInstrPageFault,
990      Mux(
991        csrio.exception.bits.uop.cf.crossPageIPFFix,
992        SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN),
993        SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
994      ),
995      memExceptionAddr
996    )
997    when (priviledgeMode === ModeM) {
998      mtval := tval
999    }.otherwise {
1000      stval := tval
1001    }
1002  }
1003
1004  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
1005    mtval := memExceptionAddr
1006  }
1007
1008  val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec
1009  val deleg = Mux(raiseIntr, mideleg , medeleg)
1010  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
1011  val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM)
1012  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
1013  val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall && !isEbreak
1014
1015  // ctrl block will use theses later for flush
1016  val isXRetFlag = RegInit(false.B)
1017  val retTargetReg = Reg(retTarget.cloneType)
1018  when (io.redirectIn.valid) {
1019    isXRetFlag := false.B
1020  }.elsewhen (isXRet) {
1021    isXRetFlag := true.B
1022    retTargetReg := retTarget
1023  }
1024  csrio.isXRet := isXRetFlag
1025  csrio.trapTarget := Mux(isXRetFlag,
1026    retTargetReg,
1027    Mux(raiseDebugExceptionIntr || ebreakEnterParkLoop, debugTrapTarget,
1028      Mux(delegS, stvec, mtvec))(VAddrBits-1, 0)
1029  )
1030
1031  when (raiseExceptionIntr) {
1032    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1033    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1034    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
1035    val debugModeNew = WireInit(debugMode)
1036
1037    when (raiseDebugExceptionIntr) {
1038      when (raiseDebugIntr) {
1039        debugModeNew := true.B
1040        mstatusNew.mprv := false.B
1041        dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1042        dcsrNew.cause := 1.U
1043        dcsrNew.prv := priviledgeMode
1044        priviledgeMode := ModeM
1045        XSDebug(raiseDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc)
1046      }.elsewhen ((hasbreakPoint || hasSingleStep) && !debugMode) {
1047        // ebreak or ss in running hart
1048        debugModeNew := true.B
1049        dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1050        dcsrNew.cause := Mux(hasbreakPoint, 3.U, 0.U)
1051        dcsrNew.prv := priviledgeMode // TODO
1052        priviledgeMode := ModeM
1053        mstatusNew.mprv := false.B
1054      }
1055      dcsr := dcsrNew.asUInt
1056      debugIntrEnable := false.B
1057    }.elsewhen (delegS) {
1058      scause := causeNO
1059      sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1060      mstatusNew.spp := priviledgeMode
1061      mstatusNew.pie.s := mstatusOld.ie.s
1062      mstatusNew.ie.s := false.B
1063      priviledgeMode := ModeS
1064      when (tvalWen) { stval := 0.U }
1065    }.otherwise {
1066      mcause := causeNO
1067      mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1068      mstatusNew.mpp := priviledgeMode
1069      mstatusNew.pie.m := mstatusOld.ie.m
1070      mstatusNew.ie.m := false.B
1071      priviledgeMode := ModeM
1072      when (tvalWen) { mtval := 0.U }
1073    }
1074    mstatus := mstatusNew.asUInt
1075    debugMode := debugModeNew
1076  }
1077
1078  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
1079
1080  // Distributed CSR update req
1081  //
1082  // For now we use it to implement customized cache op
1083
1084  when(csrio.distributedUpdate.w.valid){
1085    // cacheopRegs can be distributed updated
1086    CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
1087      when((Scachebase + attribute("offset").toInt).U === csrio.distributedUpdate.w.bits.addr){
1088        cacheopRegs(name) := csrio.distributedUpdate.w.bits.data
1089      }
1090    }}
1091  }
1092
1093  def readWithScala(addr: Int): UInt = mapping(addr)._1
1094
1095  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
1096
1097  if (!env.FPGAPlatform) {
1098    val difftest = Module(new DifftestArchEvent)
1099    difftest.io.clock := clock
1100    difftest.io.coreid := hardId.U
1101    difftest.io.intrNO := RegNext(difftestIntrNO)
1102    difftest.io.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U))
1103    difftest.io.exceptionPC := RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN))
1104  }
1105
1106  if (!env.FPGAPlatform) {
1107    val difftest = Module(new DifftestCSRState)
1108    difftest.io.clock := clock
1109    difftest.io.coreid := hardId.U
1110    difftest.io.priviledgeMode := priviledgeMode
1111    difftest.io.mstatus := mstatus
1112    difftest.io.sstatus := mstatus & sstatusRmask
1113    difftest.io.mepc := mepc
1114    difftest.io.sepc := sepc
1115    difftest.io.mtval:= mtval
1116    difftest.io.stval:= stval
1117    difftest.io.mtvec := mtvec
1118    difftest.io.stvec := stvec
1119    difftest.io.mcause := mcause
1120    difftest.io.scause := scause
1121    difftest.io.satp := satp
1122    difftest.io.mip := mipReg
1123    difftest.io.mie := mie
1124    difftest.io.mscratch := mscratch
1125    difftest.io.sscratch := sscratch
1126    difftest.io.mideleg := mideleg
1127    difftest.io.medeleg := medeleg
1128  }
1129}
1130class PFEvent(implicit p: Parameters) extends XSModule with HasCSRConst  {
1131  val io = IO(new Bundle {
1132    val distribute_csr = Flipped(new DistributedCSRIO())
1133    val hpmevent = Output(Vec(29, UInt(XLEN.W)))
1134  })
1135
1136  val w = io.distribute_csr.w
1137
1138  //val csrevents = Vec(29,RegInit(UInt(XLEN.W), 0.U))
1139  val csrevent3  = RegInit(UInt(XLEN.W), 0.U)
1140  val csrevent4  = RegInit(UInt(XLEN.W), 0.U)
1141  val csrevent5  = RegInit(UInt(XLEN.W), 0.U)
1142  val csrevent6  = RegInit(UInt(XLEN.W), 0.U)
1143  val csrevent7  = RegInit(UInt(XLEN.W), 0.U)
1144  val csrevent8  = RegInit(UInt(XLEN.W), 0.U)
1145  val csrevent9  = RegInit(UInt(XLEN.W), 0.U)
1146  val csrevent10 = RegInit(UInt(XLEN.W), 0.U)
1147  val csrevent11 = RegInit(UInt(XLEN.W), 0.U)
1148  val csrevent12 = RegInit(UInt(XLEN.W), 0.U)
1149  val csrevent13 = RegInit(UInt(XLEN.W), 0.U)
1150  val csrevent14 = RegInit(UInt(XLEN.W), 0.U)
1151  val csrevent15 = RegInit(UInt(XLEN.W), 0.U)
1152  val csrevent16 = RegInit(UInt(XLEN.W), 0.U)
1153  val csrevent17 = RegInit(UInt(XLEN.W), 0.U)
1154  val csrevent18 = RegInit(UInt(XLEN.W), 0.U)
1155  val csrevent19 = RegInit(UInt(XLEN.W), 0.U)
1156  val csrevent20 = RegInit(UInt(XLEN.W), 0.U)
1157  val csrevent21 = RegInit(UInt(XLEN.W), 0.U)
1158  val csrevent22 = RegInit(UInt(XLEN.W), 0.U)
1159  val csrevent23 = RegInit(UInt(XLEN.W), 0.U)
1160  val csrevent24 = RegInit(UInt(XLEN.W), 0.U)
1161  val csrevent25 = RegInit(UInt(XLEN.W), 0.U)
1162  val csrevent26 = RegInit(UInt(XLEN.W), 0.U)
1163  val csrevent27 = RegInit(UInt(XLEN.W), 0.U)
1164  val csrevent28 = RegInit(UInt(XLEN.W), 0.U)
1165  val csrevent29 = RegInit(UInt(XLEN.W), 0.U)
1166  val csrevent30 = RegInit(UInt(XLEN.W), 0.U)
1167  val csrevent31 = RegInit(UInt(XLEN.W), 0.U)
1168
1169  var perfEventMapping = Map(
1170    MaskedRegMap(Mhpmevent3, csrevent3 ),
1171    MaskedRegMap(Mhpmevent4, csrevent4 ),
1172    MaskedRegMap(Mhpmevent5, csrevent5 ),
1173    MaskedRegMap(Mhpmevent6, csrevent6 ),
1174    MaskedRegMap(Mhpmevent7, csrevent7 ),
1175    MaskedRegMap(Mhpmevent8, csrevent8 ),
1176    MaskedRegMap(Mhpmevent9, csrevent9 ),
1177    MaskedRegMap(Mhpmevent10,csrevent10),
1178    MaskedRegMap(Mhpmevent11,csrevent11),
1179    MaskedRegMap(Mhpmevent12,csrevent12),
1180    MaskedRegMap(Mhpmevent13,csrevent13),
1181    MaskedRegMap(Mhpmevent14,csrevent14),
1182    MaskedRegMap(Mhpmevent15,csrevent15),
1183    MaskedRegMap(Mhpmevent16,csrevent16),
1184    MaskedRegMap(Mhpmevent17,csrevent17),
1185    MaskedRegMap(Mhpmevent18,csrevent18),
1186    MaskedRegMap(Mhpmevent19,csrevent19),
1187    MaskedRegMap(Mhpmevent20,csrevent20),
1188    MaskedRegMap(Mhpmevent21,csrevent21),
1189    MaskedRegMap(Mhpmevent22,csrevent22),
1190    MaskedRegMap(Mhpmevent23,csrevent23),
1191    MaskedRegMap(Mhpmevent24,csrevent24),
1192    MaskedRegMap(Mhpmevent25,csrevent25),
1193    MaskedRegMap(Mhpmevent26,csrevent26),
1194    MaskedRegMap(Mhpmevent27,csrevent27),
1195    MaskedRegMap(Mhpmevent28,csrevent28),
1196    MaskedRegMap(Mhpmevent29,csrevent29),
1197    MaskedRegMap(Mhpmevent30,csrevent30),
1198    MaskedRegMap(Mhpmevent31,csrevent31),
1199  )
1200
1201  val rdata = Wire(UInt(XLEN.W))
1202  MaskedRegMap.generate(perfEventMapping, w.bits.addr, rdata, w.valid, w.bits.data)
1203  io.hpmevent( 0) := csrevent3
1204  io.hpmevent( 1) := csrevent4
1205  io.hpmevent( 2) := csrevent5
1206  io.hpmevent( 3) := csrevent6
1207  io.hpmevent( 4) := csrevent7
1208  io.hpmevent( 5) := csrevent8
1209  io.hpmevent( 6) := csrevent9
1210  io.hpmevent( 7) := csrevent10
1211  io.hpmevent( 8) := csrevent11
1212  io.hpmevent( 9) := csrevent12
1213  io.hpmevent(10) := csrevent13
1214  io.hpmevent(11) := csrevent14
1215  io.hpmevent(12) := csrevent15
1216  io.hpmevent(13) := csrevent16
1217  io.hpmevent(14) := csrevent17
1218  io.hpmevent(15) := csrevent18
1219  io.hpmevent(16) := csrevent19
1220  io.hpmevent(17) := csrevent20
1221  io.hpmevent(18) := csrevent21
1222  io.hpmevent(19) := csrevent22
1223  io.hpmevent(20) := csrevent23
1224  io.hpmevent(21) := csrevent24
1225  io.hpmevent(22) := csrevent25
1226  io.hpmevent(23) := csrevent26
1227  io.hpmevent(24) := csrevent27
1228  io.hpmevent(25) := csrevent28
1229  io.hpmevent(26) := csrevent29
1230  io.hpmevent(27) := csrevent30
1231  io.hpmevent(28) := csrevent31
1232}
1233
1234