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