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