xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision d4aca96cccdcdafa80dd344996e18d1978a01af7)
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 utils._
23import xiangshan._
24import xiangshan.backend._
25import xiangshan.frontend.BPUCtrl
26import xiangshan.backend.fu.util._
27import difftest._
28
29trait HasExceptionNO {
30  def instrAddrMisaligned = 0
31  def instrAccessFault    = 1
32  def illegalInstr        = 2
33  def breakPoint          = 3
34  def loadAddrMisaligned  = 4
35  def loadAccessFault     = 5
36  def storeAddrMisaligned = 6
37  def storeAccessFault    = 7
38  def ecallU              = 8
39  def ecallS              = 9
40  def ecallM              = 11
41  def instrPageFault      = 12
42  def loadPageFault       = 13
43  def storePageFault      = 15
44
45  def singleStep          = 14
46
47  val ExcPriority = Seq(
48    breakPoint, // TODO: different BP has different priority
49    singleStep,
50    instrPageFault,
51    instrAccessFault,
52    illegalInstr,
53    instrAddrMisaligned,
54    ecallM, ecallS, ecallU,
55    storePageFault,
56    loadPageFault,
57    storeAccessFault,
58    loadAccessFault,
59    storeAddrMisaligned,
60    loadAddrMisaligned
61  )
62  val frontendSet = List(
63    // instrAddrMisaligned,
64    instrAccessFault,
65    illegalInstr,
66    instrPageFault
67  )
68  val csrSet = List(
69    illegalInstr,
70    breakPoint,
71    ecallU,
72    ecallS,
73    ecallM
74  )
75  val loadUnitSet = List(
76    loadAddrMisaligned,
77    loadAccessFault,
78    loadPageFault
79  )
80  val storeUnitSet = List(
81    storeAddrMisaligned,
82    storeAccessFault,
83    storePageFault
84  )
85  val atomicsUnitSet = (loadUnitSet ++ storeUnitSet).distinct
86  val allPossibleSet = (frontendSet ++ csrSet ++ loadUnitSet ++ storeUnitSet).distinct
87  val csrWbCount = (0 until 16).map(i => if (csrSet.contains(i)) 1 else 0)
88  val loadWbCount = (0 until 16).map(i => if (loadUnitSet.contains(i)) 1 else 0)
89  val storeWbCount = (0 until 16).map(i => if (storeUnitSet.contains(i)) 1 else 0)
90  val atomicsWbCount = (0 until 16).map(i => if (atomicsUnitSet.contains(i)) 1 else 0)
91  val writebackCount = (0 until 16).map(i => csrWbCount(i) + atomicsWbCount(i) + loadWbCount(i) + 2 * storeWbCount(i))
92  def partialSelect(vec: Vec[Bool], select: Seq[Int], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] = {
93    if (dontCareBits) {
94      val new_vec = Wire(ExceptionVec())
95      new_vec := DontCare
96      select.map(i => new_vec(i) := vec(i))
97      return new_vec
98    }
99    else if (falseBits) {
100      val new_vec = Wire(ExceptionVec())
101      new_vec.map(_ := false.B)
102      select.map(i => new_vec(i) := vec(i))
103      return new_vec
104    }
105    else {
106      val new_vec = Wire(Vec(select.length, Bool()))
107      select.zipWithIndex.map{ case(s, i) => new_vec(i) := vec(s) }
108      return new_vec
109    }
110  }
111  def selectFrontend(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
112    partialSelect(vec, frontendSet, dontCareBits, falseBits)
113  def selectCSR(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
114    partialSelect(vec, csrSet, dontCareBits, falseBits)
115  def selectLoad(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
116    partialSelect(vec, loadUnitSet, dontCareBits, falseBits)
117  def selectStore(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
118    partialSelect(vec, storeUnitSet, dontCareBits, falseBits)
119  def selectAtomics(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
120    partialSelect(vec, atomicsUnitSet, dontCareBits, falseBits)
121  def selectAll(vec: Vec[Bool], dontCareBits: Boolean = true, falseBits: Boolean = false): Vec[Bool] =
122    partialSelect(vec, allPossibleSet, dontCareBits, falseBits)
123}
124
125class FpuCsrIO extends Bundle {
126  val fflags = Output(Valid(UInt(5.W)))
127  val isIllegal = Output(Bool())
128  val dirty_fs = Output(Bool())
129  val frm = Input(UInt(3.W))
130}
131
132
133class PerfCounterIO(implicit p: Parameters) extends XSBundle {
134  val retiredInstr = UInt(3.W)
135  val frontendInfo = new Bundle {
136    val ibufFull  = Bool()
137  }
138  val ctrlInfo = new Bundle {
139    val roqFull   = Bool()
140    val intdqFull = Bool()
141    val fpdqFull  = Bool()
142    val lsdqFull  = Bool()
143  }
144  val memInfo = new Bundle {
145    val sqFull = Bool()
146    val lqFull = Bool()
147    val dcacheMSHRFull = Bool()
148  }
149  val bpuInfo = new Bundle {
150    val bpRight = UInt(XLEN.W)
151    val bpWrong = UInt(XLEN.W)
152  }
153  val cacheInfo = new Bundle {
154    val l2MSHRFull = Bool()
155    val l3MSHRFull = Bool()
156    val l2nAcquire = UInt(XLEN.W)
157    val l2nAcquireMiss = UInt(XLEN.W)
158    val l3nAcquire = UInt(XLEN.W)
159    val l3nAcquireMiss = UInt(XLEN.W)
160  }
161}
162
163class CSRFileIO(implicit p: Parameters) extends XSBundle {
164  val hartId = Input(UInt(64.W))
165  // output (for func === CSROpType.jmp)
166  val perf = Input(new PerfCounterIO)
167  val isPerfCnt = Output(Bool())
168  // to FPU
169  val fpu = Flipped(new FpuCsrIO)
170  // from rob
171  val exception = Flipped(ValidIO(new ExceptionInfo))
172  // to ROB
173  val isXRet = Output(Bool())
174  val trapTarget = Output(UInt(VAddrBits.W))
175  val interrupt = Output(Bool())
176  // from LSQ
177  val memExceptionVAddr = Input(UInt(VAddrBits.W))
178  // from outside cpu,externalInterrupt
179  val externalInterrupt = new ExternalInterruptIO
180  // TLB
181  val tlb = Output(new TlbCsrBundle)
182  // Debug Mode
183  val singleStep = Output(Bool())
184  val debugMode = Output(Bool())
185  // Custom microarchiture ctrl signal
186  val customCtrl = Output(new CustomCSRCtrlIO)
187  // to Fence to disable sfence
188  val disableSfence = Output(Bool())
189}
190
191class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst
192{
193  val csrio = IO(new CSRFileIO)
194
195  val cfIn = io.in.bits.uop.cf
196  val cfOut = Wire(new CtrlFlow)
197  cfOut := cfIn
198  val flushPipe = Wire(Bool())
199
200  val (valid, src1, src2, func) = (
201    io.in.valid,
202    io.in.bits.src(0),
203    io.in.bits.uop.ctrl.imm,
204    io.in.bits.uop.ctrl.fuOpType
205  )
206
207  // CSR define
208
209  class Priv extends Bundle {
210    val m = Output(Bool())
211    val h = Output(Bool())
212    val s = Output(Bool())
213    val u = Output(Bool())
214  }
215
216  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
217
218  class DcsrStruct extends Bundle {
219    val xdebugver = Output(UInt(2.W))
220    val zero4 = Output(UInt(2.W))
221    val zero3 = Output(UInt(12.W))
222    val ebreakm = Output(Bool())
223    val ebreakh = Output(Bool())
224    val ebreaks = Output(Bool())
225    val ebreaku = Output(Bool())
226    val zero2 = Output(Bool())
227    val stopcycle = Output(Bool())
228    val stoptime = Output(Bool())
229    val cause = Output(UInt(3.W))
230    val zero1 = Output(UInt(3.W))
231    val step = Output(Bool())
232    val prv = Output(UInt(2.W))
233  }
234
235  class MstatusStruct extends Bundle {
236    val sd = Output(UInt(1.W))
237
238    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
239    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
240    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
241    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
242
243    val tsr = Output(UInt(1.W))
244    val tw = Output(UInt(1.W))
245    val tvm = Output(UInt(1.W))
246    val mxr = Output(UInt(1.W))
247    val sum = Output(UInt(1.W))
248    val mprv = Output(UInt(1.W))
249    val xs = Output(UInt(2.W))
250    val fs = Output(UInt(2.W))
251    val mpp = Output(UInt(2.W))
252    val hpp = Output(UInt(2.W))
253    val spp = Output(UInt(1.W))
254    val pie = new Priv
255    val ie = new Priv
256    assert(this.getWidth == XLEN)
257  }
258
259  class SatpStruct extends Bundle {
260    val mode = UInt(4.W)
261    val asid = UInt(16.W)
262    val ppn  = UInt(44.W)
263  }
264
265  class Interrupt extends Bundle {
266//  val d = Output(Bool())    // Debug
267    val e = new Priv
268    val t = new Priv
269    val s = new Priv
270  }
271
272  // Debug CSRs
273  val dcsr = RegInit(UInt(32.W), 0x4000b010.U)
274  val dpc = Reg(UInt(64.W))
275  val dscratch = Reg(UInt(64.W))
276  val dscratch1 = Reg(UInt(64.W))
277  val debugMode = RegInit(false.B)
278  val debugIntrEnable = RegInit(true.B)
279  csrio.debugMode := debugMode
280
281  val dpcPrev = RegNext(dpc)
282  XSDebug(dpcPrev =/= dpc, "Debug Mode: dpc is altered! Current is %x, previous is %x.", dpc, dpcPrev)
283
284// dcsr value table
285// | debugver | 0100
286// | zero     | 10 bits of 0
287// | ebreakvs | 0
288// | ebreakvu | 0
289// | ebreakm  | 1 if ebreak enters debug
290// | zero     | 0
291// | ebreaks  |
292// | ebreaku  |
293// | stepie   | 0 disable interrupts in singlestep
294// | stopcount| stop counter, 0
295// | stoptime | stop time, 0
296// | cause    | 3 bits read only
297// | v        | 0
298// | mprven   | 1
299// | nmip     | read only
300// | step     |
301// | prv      | 2 bits
302  val dcsrData = Wire(new DcsrStruct)
303  dcsrData := dcsr.asTypeOf(new DcsrStruct)
304  val dcsrMask = GenMask(15) | GenMask(13, 11) | GenMask(2, 0)// Dcsr write mask
305  def dcsrUpdateSideEffect(dcsr: UInt): UInt = {
306    val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct))
307    val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11
308    dcsrNew
309  }
310  csrio.singleStep := dcsrData.step
311
312  // Machine-Level CSRs
313
314  val mtvec = RegInit(UInt(XLEN.W), 0.U)
315  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
316  val mcause = RegInit(UInt(XLEN.W), 0.U)
317  val mtval = RegInit(UInt(XLEN.W), 0.U)
318  val mepc = Reg(UInt(XLEN.W))
319
320  val mie = RegInit(0.U(XLEN.W))
321  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
322  val mipReg  = RegInit(0.U.asTypeOf(new Interrupt).asUInt)
323  val mipFixMask = GenMask(9) | GenMask(5) | GenMask(1)
324  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
325
326  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt()
327  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt()
328  var extList = List('a', 's', 'i', 'u')
329  if (HasMExtension) { extList = extList :+ 'm' }
330  if (HasCExtension) { extList = extList :+ 'c' }
331  if (HasFPU) { extList = extList ++ List('f', 'd') }
332  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
333  val misa = RegInit(UInt(XLEN.W), misaInitVal)
334
335  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
336  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
337
338  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
339  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
340  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
341  val mhartid = RegInit(UInt(XLEN.W), csrio.hartId) // the hardware thread running the code
342  val mstatus = RegInit(UInt(XLEN.W), 0.U)
343
344  // mstatus Value Table
345  // | sd   |
346  // | pad1 |
347  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
348  // | uxl  | hardlinked to 00
349  // | pad0 |
350  // | tsr  |
351  // | tw   |
352  // | tvm  |
353  // | mxr  |
354  // | sum  |
355  // | mprv |
356  // | xs   | 00 |
357  // | fs   | 00 |
358  // | mpp  | 00 |
359  // | hpp  | 00 |
360  // | spp  | 0 |
361  // | pie  | 0000 | pie.h is used as UBE
362  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
363
364  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
365  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
366    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
367    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
368    mstatusNew
369  }
370
371  val mstatusMask = (~ZeroExt((
372    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
373    GenMask(37) | // MBE
374    GenMask(36) | // SBE
375    GenMask(6)    // UBE
376  ), 64)).asUInt()
377
378  val medeleg = RegInit(UInt(XLEN.W), 0.U)
379  val mideleg = RegInit(UInt(XLEN.W), 0.U)
380  val mscratch = RegInit(UInt(XLEN.W), 0.U)
381
382  val pmpcfg0 = RegInit(UInt(XLEN.W), 0.U)
383  val pmpcfg1 = RegInit(UInt(XLEN.W), 0.U)
384  val pmpcfg2 = RegInit(UInt(XLEN.W), 0.U)
385  val pmpcfg3 = RegInit(UInt(XLEN.W), 0.U)
386  val pmpaddr0 = RegInit(UInt(XLEN.W), 0.U)
387  val pmpaddr1 = RegInit(UInt(XLEN.W), 0.U)
388  val pmpaddr2 = RegInit(UInt(XLEN.W), 0.U)
389  val pmpaddr3 = RegInit(UInt(XLEN.W), 0.U)
390
391  // Superviser-Level CSRs
392
393  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
394  val sstatusWmask = "hc6122".U
395  // Sstatus Write Mask
396  // -------------------------------------------------------
397  //    19           9   5     2
398  // 0  1100 0000 0001 0010 0010
399  // 0  c    0    1    2    2
400  // -------------------------------------------------------
401  val sstatusRmask = sstatusWmask | "h8000000300018000".U
402  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
403  val stvec = RegInit(UInt(XLEN.W), 0.U)
404  // val sie = RegInit(0.U(XLEN.W))
405  val sieMask = "h222".U & mideleg
406  val sipMask = "h222".U & mideleg
407  val sipWMask = "h2".U // ssip is writeable in smode
408  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
409  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
410  val satpMask = "h80000fffffffffff".U // disable asid, mode can only be 8 / 0
411  val sepc = RegInit(UInt(XLEN.W), 0.U)
412  val scause = RegInit(UInt(XLEN.W), 0.U)
413  val stval = Reg(UInt(XLEN.W))
414  val sscratch = RegInit(UInt(XLEN.W), 0.U)
415  val scounteren = RegInit(UInt(XLEN.W), 0.U)
416
417  // sbpctl
418  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
419  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
420  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
421  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
422  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
423  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
424  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
425  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
426  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
427
428  // spfctl Bit 0: L1plusCache Prefetcher Enable
429  // spfctl Bit 1: L2Cache Prefetcher Enable
430  val spfctl = RegInit(UInt(XLEN.W), "h3".U)
431  csrio.customCtrl.l1plus_pf_enable := spfctl(0)
432  csrio.customCtrl.l2_pf_enable := spfctl(1)
433
434  // sdsid: Differentiated Services ID
435  val sdsid = RegInit(UInt(XLEN.W), 0.U)
436  csrio.customCtrl.dsid := sdsid
437
438  // slvpredctl: load violation predict settings
439  val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17
440  csrio.customCtrl.lvpred_disable := slvpredctl(0)
441  csrio.customCtrl.no_spec_load := slvpredctl(1)
442  csrio.customCtrl.waittable_timeout := slvpredctl(8, 4)
443
444  // smblockctl: memory block configurations
445  // bits 0-3: store buffer flush threshold (default: 8 entries)
446  val smblockctl = RegInit(UInt(XLEN.W), "hf".U & StoreBufferThreshold.U)
447  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
448
449  val srnctl = RegInit(UInt(XLEN.W), "h1".U)
450  csrio.customCtrl.move_elim_enable := srnctl(0)
451
452  val tlbBundle = Wire(new TlbCsrBundle)
453  tlbBundle.satp := satp.asTypeOf(new SatpStruct)
454  csrio.tlb := tlbBundle
455
456  // User-Level CSRs
457  val uepc = Reg(UInt(XLEN.W))
458
459  // fcsr
460  class FcsrStruct extends Bundle {
461    val reserved = UInt((XLEN-3-5).W)
462    val frm = UInt(3.W)
463    val fflags = UInt(5.W)
464    assert(this.getWidth == XLEN)
465  }
466  val fcsr = RegInit(0.U(XLEN.W))
467  // set mstatus->sd and mstatus->fs when true
468  val csrw_dirty_fp_state = WireInit(false.B)
469
470  def frm_wfn(wdata: UInt): UInt = {
471    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
472    csrw_dirty_fp_state := true.B
473    fcsrOld.frm := wdata(2,0)
474    fcsrOld.asUInt()
475  }
476  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
477
478  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
479    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
480    val fcsrNew = WireInit(fcsrOld)
481    csrw_dirty_fp_state := true.B
482    if (update) {
483      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
484    } else {
485      fcsrNew.fflags := wdata(4,0)
486    }
487    fcsrNew.asUInt()
488  }
489  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
490
491  def fcsr_wfn(wdata: UInt): UInt = {
492    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
493    csrw_dirty_fp_state := true.B
494    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
495  }
496
497  val fcsrMapping = Map(
498    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
499    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
500    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
501  )
502
503  // Atom LR/SC Control Bits
504  //  val setLr = WireInit(Bool(), false.B)
505  //  val setLrVal = WireInit(Bool(), false.B)
506  //  val setLrAddr = WireInit(UInt(AddrBits.W), DontCare) //TODO : need check
507  //  val lr = RegInit(Bool(), false.B)
508  //  val lrAddr = RegInit(UInt(AddrBits.W), 0.U)
509  //
510  //  when (setLr) {
511  //    lr := setLrVal
512  //    lrAddr := setLrAddr
513  //  }
514
515  // Hart Priviledge Mode
516  val priviledgeMode = RegInit(UInt(2.W), ModeM)
517
518  // Emu perfcnt
519  val hasEmuPerfCnt = !env.FPGAPlatform
520  val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3
521
522  val emuPerfCnts    = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W)))
523  val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B))
524  (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
525
526  val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i)))
527  val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32)))
528  println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}")
529
530  // Perf Counter
531  val nrPerfCnts = 29  // 3...31
532  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
533  val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
534  val mcountinhibit = RegInit(0.U(XLEN.W))
535  val mcycle = RegInit(0.U(XLEN.W))
536  mcycle := mcycle + 1.U
537  val minstret = RegInit(0.U(XLEN.W))
538  minstret := minstret + RegNext(csrio.perf.retiredInstr)
539  val ibufFull  = RegInit(0.U(XLEN.W))
540  ibufFull := ibufFull + RegNext(csrio.perf.frontendInfo.ibufFull)
541  val roqFull   = RegInit(0.U(XLEN.W))
542  roqFull := roqFull + RegNext(csrio.perf.ctrlInfo.roqFull)
543  val intdqFull = RegInit(0.U(XLEN.W))
544  intdqFull := intdqFull + RegNext(csrio.perf.ctrlInfo.intdqFull)
545  val fpdqFull  = RegInit(0.U(XLEN.W))
546  fpdqFull := fpdqFull + RegNext(csrio.perf.ctrlInfo.fpdqFull)
547  val lsdqFull  = RegInit(0.U(XLEN.W))
548  lsdqFull := lsdqFull + RegNext(csrio.perf.ctrlInfo.lsdqFull)
549  val sqFull    = RegInit(0.U(XLEN.W))
550  sqFull := sqFull + RegNext(csrio.perf.memInfo.sqFull)
551  val lqFull    = RegInit(0.U(XLEN.W))
552  lqFull := lqFull + RegNext(csrio.perf.memInfo.lqFull)
553  val dcacheMSHRFull = RegInit(0.U(XLEN.W))
554  dcacheMSHRFull := dcacheMSHRFull + RegNext(csrio.perf.memInfo.dcacheMSHRFull)
555  val bpRight   = RegInit(0.U(XLEN.W))
556  bpRight := bpRight + RegNext(csrio.perf.bpuInfo.bpRight)
557  val bpWrong   = RegInit(0.U(XLEN.W))
558  bpWrong := bpWrong + RegNext(csrio.perf.bpuInfo.bpWrong)
559
560  // CSR reg map
561  val basicPrivMapping = Map(
562
563    //--- User Trap Setup ---
564    // MaskedRegMap(Ustatus, ustatus),
565    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
566    // MaskedRegMap(Utvec, utvec),
567
568    //--- User Trap Handling ---
569    // MaskedRegMap(Uscratch, uscratch),
570    // MaskedRegMap(Uepc, uepc),
571    // MaskedRegMap(Ucause, ucause),
572    // MaskedRegMap(Utval, utval),
573    // MaskedRegMap(Uip, uip),
574
575    //--- User Counter/Timers ---
576    // MaskedRegMap(Cycle, cycle),
577    // MaskedRegMap(Time, time),
578    // MaskedRegMap(Instret, instret),
579
580    //--- Supervisor Trap Setup ---
581    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
582    // MaskedRegMap(Sedeleg, Sedeleg),
583    // MaskedRegMap(Sideleg, Sideleg),
584    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
585    MaskedRegMap(Stvec, stvec),
586    MaskedRegMap(Scounteren, scounteren),
587
588    //--- Supervisor Trap Handling ---
589    MaskedRegMap(Sscratch, sscratch),
590    MaskedRegMap(Sepc, sepc),
591    MaskedRegMap(Scause, scause),
592    MaskedRegMap(Stval, stval),
593    MaskedRegMap(Sip, mip.asUInt, sipWMask, MaskedRegMap.Unwritable, sipMask),
594
595    //--- Supervisor Protection and Translation ---
596    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
597
598    //--- Supervisor Custom Read/Write Registers
599    MaskedRegMap(Sbpctl, sbpctl),
600    MaskedRegMap(Spfctl, spfctl),
601    MaskedRegMap(Sdsid, sdsid),
602    MaskedRegMap(Slvpredctl, slvpredctl),
603    MaskedRegMap(Smblockctl, smblockctl),
604    MaskedRegMap(Srnctl, srnctl),
605
606    //--- Machine Information Registers ---
607    MaskedRegMap(Mvendorid, mvendorid, 0.U, MaskedRegMap.Unwritable),
608    MaskedRegMap(Marchid, marchid, 0.U, MaskedRegMap.Unwritable),
609    MaskedRegMap(Mimpid, mimpid, 0.U, MaskedRegMap.Unwritable),
610    MaskedRegMap(Mhartid, mhartid, 0.U, MaskedRegMap.Unwritable),
611
612    //--- Machine Trap Setup ---
613    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
614    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
615    MaskedRegMap(Medeleg, medeleg, "hf3ff".U),
616    MaskedRegMap(Mideleg, mideleg, "h222".U),
617    MaskedRegMap(Mie, mie),
618    MaskedRegMap(Mtvec, mtvec),
619    MaskedRegMap(Mcounteren, mcounteren),
620
621    //--- Machine Trap Handling ---
622    MaskedRegMap(Mscratch, mscratch),
623    MaskedRegMap(Mepc, mepc),
624    MaskedRegMap(Mcause, mcause),
625    MaskedRegMap(Mtval, mtval),
626    MaskedRegMap(Mip, mip.asUInt, 0.U, MaskedRegMap.Unwritable),
627
628    //--- Debug Mode ---
629    MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
630    MaskedRegMap(Dpc, dpc),
631    MaskedRegMap(Dscratch, dscratch),
632    MaskedRegMap(Dscratch1, dscratch1)
633  )
634
635  // PMP is unimplemented yet
636  val pmpMapping = Map(
637    MaskedRegMap(Pmpcfg0, pmpcfg0),
638    MaskedRegMap(Pmpcfg1, pmpcfg1),
639    MaskedRegMap(Pmpcfg2, pmpcfg2),
640    MaskedRegMap(Pmpcfg3, pmpcfg3),
641    MaskedRegMap(PmpaddrBase + 0, pmpaddr0),
642    MaskedRegMap(PmpaddrBase + 1, pmpaddr1),
643    MaskedRegMap(PmpaddrBase + 2, pmpaddr2),
644    MaskedRegMap(PmpaddrBase + 3, pmpaddr3)
645  )
646
647  var perfCntMapping = Map(
648    MaskedRegMap(Mcountinhibit, mcountinhibit),
649    MaskedRegMap(Mcycle, mcycle),
650    MaskedRegMap(Minstret, minstret),
651    MaskedRegMap(Mhpmevent3, ibufFull),
652    MaskedRegMap(Mhpmevent4, roqFull),
653    MaskedRegMap(Mhpmevent5, intdqFull),
654    MaskedRegMap(Mhpmevent6, fpdqFull),
655    MaskedRegMap(Mhpmevent7, lsdqFull),
656    MaskedRegMap(Mhpmevent8, sqFull),
657    MaskedRegMap(Mhpmevent9, lqFull),
658    MaskedRegMap(Mhpmevent10, dcacheMSHRFull),
659    MaskedRegMap(Mhpmevent11, bpRight),
660    MaskedRegMap(Mhpmevent12, bpWrong),
661  )
662  // TODO: mechanism should be implemented later
663  // val MhpmcounterStart = Mhpmcounter3
664  // val MhpmeventStart   = Mhpmevent3
665  // for (i <- 0 until nrPerfCnts) {
666  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
667  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
668  // }
669
670  val mapping = basicPrivMapping ++
671                perfCntMapping ++
672                pmpMapping ++
673                emuPerfCntsLoMapping ++
674                (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++
675                (if (HasFPU) fcsrMapping else Nil)
676
677  val addr = src2(11, 0)
678  val csri = ZeroExt(src2(16, 12), XLEN)
679  val rdata = Wire(UInt(XLEN.W))
680  val wdata = LookupTree(func, List(
681    CSROpType.wrt  -> src1,
682    CSROpType.set  -> (rdata | src1),
683    CSROpType.clr  -> (rdata & (~src1).asUInt()),
684    CSROpType.wrti -> csri,
685    CSROpType.seti -> (rdata | csri),
686    CSROpType.clri -> (rdata & (~csri).asUInt())
687  ))
688
689  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U)
690  csrio.isPerfCnt := addrInPerfCnt
691
692  // satp wen check
693  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
694
695  // csr access check, special case
696  val tvmNotPermit = (priviledgeMode === ModeS && mstatusStruct.tvm.asBool)
697  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
698  csrio.disableSfence := tvmNotPermit
699
700  // general CSR wen check
701  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
702  val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
703  val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren)
704  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && accessPermitted
705
706  // Writeable check is ingored.
707  // Currently, write to illegal csr addr will be ignored
708  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
709  io.out.bits.data := rdata
710  io.out.bits.uop := io.in.bits.uop
711  io.out.bits.uop.cf := cfOut
712  io.out.bits.uop.ctrl.flushPipe := flushPipe
713
714  // Fix Mip/Sip write
715  val fixMapping = Map(
716    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
717    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask)
718  )
719  val rdataFix = Wire(UInt(XLEN.W))
720  val wdataFix = LookupTree(func, List(
721    CSROpType.wrt  -> src1,
722    CSROpType.set  -> (rdataFix | src1),
723    CSROpType.clr  -> (rdataFix & (~src1).asUInt()),
724    CSROpType.wrti -> csri,
725    CSROpType.seti -> (rdataFix | csri),
726    CSROpType.clri -> (rdataFix & (~csri).asUInt())
727  ))
728  MaskedRegMap.generate(fixMapping, addr, rdataFix, wen && permitted, wdataFix)
729
730  when (csrio.fpu.fflags.valid) {
731    fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits)
732  }
733  // set fs and sd in mstatus
734  when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) {
735    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
736    mstatusNew.fs := "b11".U
737    mstatusNew.sd := true.B
738    mstatus := mstatusNew.asUInt()
739  }
740  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
741
742  // CSR inst decode
743  val isEbreak = addr === privEbreak && func === CSROpType.jmp
744  val isEcall  = addr === privEcall  && func === CSROpType.jmp
745  val isMret   = addr === privMret   && func === CSROpType.jmp
746  val isSret   = addr === privSret   && func === CSROpType.jmp
747  val isUret   = addr === privUret   && func === CSROpType.jmp
748  val isDret   = addr === privDret   && func === CSROpType.jmp
749
750  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
751  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
752
753  // Illegal priviledged operation list
754  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
755
756  // Illegal priviledged instruction check
757  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
758  val isIllegalAccess = !permitted
759  val isIllegalPrivOp = illegalSModeSret
760
761  // def MMUPermissionCheck(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool)
762  // def MMUPermissionCheckLoad(ptev: Bool, pteu: Bool): Bool = ptev && !(priviledgeMode === ModeU && !pteu) && !(priviledgeMode === ModeS && pteu && mstatusStruct.sum.asBool) && (pter || (mstatusStruct.mxr && ptex))
763  // imem
764  // val imemPtev = true.B
765  // val imemPteu = true.B
766  // val imemPtex = true.B
767  // val imemReq = true.B
768  // val imemPermissionCheckPassed = MMUPermissionCheck(imemPtev, imemPteu)
769  // val hasInstrPageFault = imemReq && !(imemPermissionCheckPassed && imemPtex)
770  // assert(!hasInstrPageFault)
771
772  // dmem
773  // val dmemPtev = true.B
774  // val dmemPteu = true.B
775  // val dmemReq = true.B
776  // val dmemPermissionCheckPassed = MMUPermissionCheck(dmemPtev, dmemPteu)
777  // val dmemIsStore = true.B
778
779  // val hasLoadPageFault  = dmemReq && !dmemIsStore && !(dmemPermissionCheckPassed)
780  // val hasStorePageFault = dmemReq &&  dmemIsStore && !(dmemPermissionCheckPassed)
781  // assert(!hasLoadPageFault)
782  // assert(!hasStorePageFault)
783
784  //TODO: Havn't test if io.dmemMMU.priviledgeMode is correct yet
785  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
786  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
787  tlbBundle.priv.imode := priviledgeMode
788  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
789
790  // Branch control
791  val retTarget = Wire(UInt(VAddrBits.W))
792  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
793  flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall)
794
795  retTarget := DontCare
796  // val illegalEret = TODO
797
798  when (valid && isDret) {
799    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
800    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
801    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
802    val debugModeNew = WireInit(debugMode)
803    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.
804    mstatus := mstatusNew.asUInt
805    priviledgeMode := dcsrNew.prv
806    retTarget := dpc(VAddrBits-1, 0)
807    debugModeNew := false.B
808    debugIntrEnable := true.B
809    debugMode := debugModeNew
810    XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget)
811  }
812
813  when (valid && isMret) {
814    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
815    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
816    mstatusNew.ie.m := mstatusOld.pie.m
817    priviledgeMode := mstatusOld.mpp
818    mstatusNew.pie.m := true.B
819    mstatusNew.mpp := ModeU
820    mstatusNew.mprv := 0.U
821    mstatus := mstatusNew.asUInt
822    // lr := false.B
823    retTarget := mepc(VAddrBits-1, 0)
824  }
825
826  when (valid && isSret && !illegalSModeSret) {
827    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
828    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
829    mstatusNew.ie.s := mstatusOld.pie.s
830    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
831    mstatusNew.pie.s := true.B
832    mstatusNew.spp := ModeU
833    mstatus := mstatusNew.asUInt
834    mstatusNew.mprv := 0.U
835    // lr := false.B
836    retTarget := sepc(VAddrBits-1, 0)
837  }
838
839  when (valid && isUret) {
840    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
841    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
842    // mstatusNew.mpp.m := ModeU //TODO: add mode U
843    mstatusNew.ie.u := mstatusOld.pie.u
844    priviledgeMode := ModeU
845    mstatusNew.pie.u := true.B
846    mstatus := mstatusNew.asUInt
847    retTarget := uepc(VAddrBits-1, 0)
848  }
849
850  io.in.ready := true.B
851  io.out.valid := valid
852
853  val ebreakCauseException = (priviledgeMode === ModeM && dcsrData.ebreakm) || (priviledgeMode === ModeS && dcsrData.ebreaks) || (priviledgeMode === ModeU && dcsrData.ebreaku)
854
855  val csrExceptionVec = WireInit(cfIn.exceptionVec)
856  csrExceptionVec(breakPoint) := io.in.valid && isEbreak && ebreakCauseException
857  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
858  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
859  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
860  // Trigger an illegal instr exception when:
861  // * unimplemented csr is being read/written
862  // * csr access is illegal
863  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
864  cfOut.exceptionVec := csrExceptionVec
865
866  /**
867    * Exception and Intr
868    */
869  val ideleg =  (mideleg & mip.asUInt)
870  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
871    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
872
873  val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable
874  XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!")
875  // send interrupt information to ROQ
876  val intrVecEnable = Wire(Vec(12, Bool()))
877  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
878  val intrVec = Cat(debugIntr, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt))
879  val intrBitSet = intrVec.orR()
880  csrio.interrupt := intrBitSet
881  mipWire.t.m := csrio.externalInterrupt.mtip
882  mipWire.s.m := csrio.externalInterrupt.msip
883  mipWire.e.m := csrio.externalInterrupt.meip
884  mipWire.e.s := csrio.externalInterrupt.meip
885
886  // interrupts
887  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
888  val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
889  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO)
890  val raiseDebugIntr = intrNO === IRQ_DEBUG.U && raiseIntr
891
892  // exceptions
893  val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt
894  val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException
895  val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException
896  val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException
897  val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException
898  val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException
899  val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException
900  val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
901  val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
902  val hasbreakPoint = csrio.exception.bits.uop.cf.exceptionVec(breakPoint) && raiseException
903  val hasSingleStep = csrio.exception.bits.uop.cf.exceptionVec(singleStep) && raiseException
904
905  val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
906  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
907  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
908
909  val raiseExceptionIntr = csrio.exception.valid
910
911  val raiseDebugExceptionIntr = !debugMode && hasbreakPoint || raiseDebugIntr || hasSingleStep
912  val ebreakEnterParkLoop = debugMode && raiseExceptionIntr // exception in debug mode (except ebrk) changes cmderr. how ???
913
914  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
915    csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
916  )
917  XSDebug(raiseExceptionIntr,
918    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
919    csrio.exception.bits.uop.cf.pc,
920    mstatus,
921    mideleg,
922    medeleg,
923    priviledgeMode
924  )
925
926  // mtval write logic
927  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
928  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
929    val tval = Mux(
930      hasInstrPageFault,
931      Mux(
932        csrio.exception.bits.uop.cf.crossPageIPFFix,
933        SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN),
934        SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
935      ),
936      memExceptionAddr
937    )
938    when (priviledgeMode === ModeM) {
939      mtval := tval
940    }.otherwise {
941      stval := tval
942    }
943  }
944
945  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
946    mtval := memExceptionAddr
947  }
948
949  val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec
950  val deleg = Mux(raiseIntr, mideleg , medeleg)
951  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
952  val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM)
953  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
954  val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall && !isEbreak
955
956  // ctrl block will use theses later for flush
957  val isXRetFlag = RegInit(false.B)
958  val retTargetReg = Reg(retTarget.cloneType)
959  when (io.flushIn) {
960    isXRetFlag := false.B
961  }.elsewhen (isXRet) {
962    isXRetFlag := true.B
963    retTargetReg := retTarget
964  }
965  csrio.isXRet := isXRetFlag
966  csrio.trapTarget := Mux(isXRetFlag,
967    retTargetReg,
968    Mux(raiseDebugExceptionIntr || ebreakEnterParkLoop, debugTrapTarget,
969      Mux(delegS, stvec, mtvec))(VAddrBits-1, 0)
970  )
971
972  when (raiseExceptionIntr) {
973    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
974    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
975    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
976    val debugModeNew = WireInit(debugMode)
977
978    when (raiseDebugExceptionIntr) {
979      when (raiseDebugIntr) {
980        debugModeNew := true.B
981        mstatusNew.mprv := false.B
982        dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
983        dcsrNew.cause := 1.U
984        dcsrNew.prv := priviledgeMode
985        priviledgeMode := ModeM
986        XSDebug(raiseDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc)
987      }.elsewhen ((hasbreakPoint || hasSingleStep) && !debugMode) {
988        // ebreak or ss in running hart
989        debugModeNew := true.B
990        dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
991        dcsrNew.cause := Mux(hasbreakPoint, 3.U, 0.U)
992        dcsrNew.prv := priviledgeMode // TODO
993        priviledgeMode := ModeM
994        mstatusNew.mprv := false.B
995      }
996      dcsr := dcsrNew.asUInt
997      debugIntrEnable := false.B
998    }.elsewhen (delegS) {
999      scause := causeNO
1000      sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1001      mstatusNew.spp := priviledgeMode
1002      mstatusNew.pie.s := mstatusOld.ie.s
1003      mstatusNew.ie.s := false.B
1004      priviledgeMode := ModeS
1005      when (tvalWen) { stval := 0.U }
1006    }.otherwise {
1007      mcause := causeNO
1008      mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1009      mstatusNew.mpp := priviledgeMode
1010      mstatusNew.pie.m := mstatusOld.ie.m
1011      mstatusNew.ie.m := false.B
1012      priviledgeMode := ModeM
1013      when (tvalWen) { mtval := 0.U }
1014    }
1015    mstatus := mstatusNew.asUInt
1016    debugMode := debugModeNew
1017  }
1018
1019  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
1020
1021  def readWithScala(addr: Int): UInt = mapping(addr)._1
1022
1023  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
1024
1025  if (!env.FPGAPlatform) {
1026    val difftest = Module(new DifftestArchEvent)
1027    difftest.io.clock := clock
1028    difftest.io.coreid := hardId.U
1029    difftest.io.intrNO := RegNext(difftestIntrNO)
1030    difftest.io.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U))
1031    difftest.io.exceptionPC := RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN))
1032  }
1033
1034  if (!env.FPGAPlatform) {
1035    val difftest = Module(new DifftestCSRState)
1036    difftest.io.clock := clock
1037    difftest.io.coreid := hardId.U
1038    difftest.io.priviledgeMode := priviledgeMode
1039    difftest.io.mstatus := mstatus
1040    difftest.io.sstatus := mstatus & sstatusRmask
1041    difftest.io.mepc := mepc
1042    difftest.io.sepc := sepc
1043    difftest.io.mtval:= mtval
1044    difftest.io.stval:= stval
1045    difftest.io.mtvec := mtvec
1046    difftest.io.stvec := stvec
1047    difftest.io.mcause := mcause
1048    difftest.io.scause := scause
1049    difftest.io.satp := satp
1050    difftest.io.mip := mipReg
1051    difftest.io.mie := mie
1052    difftest.io.mscratch := mscratch
1053    difftest.io.sscratch := sscratch
1054    difftest.io.mideleg := mideleg
1055    difftest.io.medeleg := medeleg
1056  }
1057}
1058