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