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