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