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