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