xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision c3abb8b6b92c14ec0f3dbbac60a8caa531994a95)
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  val distributedUpdate = Flipped(new DistributedCSRUpdateReq)
192  // to Fence to disable sfence
193  val disableSfence = Output(Bool())
194  // distributed csr w
195}
196
197class CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMPConst
198{
199  val csrio = IO(new CSRFileIO)
200
201  val cfIn = io.in.bits.uop.cf
202  val cfOut = Wire(new CtrlFlow)
203  cfOut := cfIn
204  val flushPipe = Wire(Bool())
205
206  val (valid, src1, src2, func) = (
207    io.in.valid,
208    io.in.bits.src(0),
209    io.in.bits.uop.ctrl.imm,
210    io.in.bits.uop.ctrl.fuOpType
211  )
212
213  // CSR define
214
215  class Priv extends Bundle {
216    val m = Output(Bool())
217    val h = Output(Bool())
218    val s = Output(Bool())
219    val u = Output(Bool())
220  }
221
222  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
223
224  class DcsrStruct extends Bundle {
225    val xdebugver = Output(UInt(2.W))
226    val zero4 = Output(UInt(2.W))
227    val zero3 = Output(UInt(12.W))
228    val ebreakm = Output(Bool())
229    val ebreakh = Output(Bool())
230    val ebreaks = Output(Bool())
231    val ebreaku = Output(Bool())
232    val zero2 = Output(Bool())
233    val stopcycle = Output(Bool())
234    val stoptime = Output(Bool())
235    val cause = Output(UInt(3.W))
236    val zero1 = Output(UInt(3.W))
237    val step = Output(Bool())
238    val prv = Output(UInt(2.W))
239  }
240
241  class MstatusStruct extends Bundle {
242    val sd = Output(UInt(1.W))
243
244    val pad1 = if (XLEN == 64) Output(UInt(27.W)) else null
245    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
246    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
247    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
248
249    val tsr = Output(UInt(1.W))
250    val tw = Output(UInt(1.W))
251    val tvm = Output(UInt(1.W))
252    val mxr = Output(UInt(1.W))
253    val sum = Output(UInt(1.W))
254    val mprv = Output(UInt(1.W))
255    val xs = Output(UInt(2.W))
256    val fs = Output(UInt(2.W))
257    val mpp = Output(UInt(2.W))
258    val hpp = Output(UInt(2.W))
259    val spp = Output(UInt(1.W))
260    val pie = new Priv
261    val ie = new Priv
262    assert(this.getWidth == XLEN)
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
303  val dcsrData = Wire(new DcsrStruct)
304  dcsrData := dcsr.asTypeOf(new DcsrStruct)
305  val dcsrMask = ZeroExt(GenMask(15) | GenMask(13, 11) | GenMask(2, 0), XLEN)// Dcsr write mask
306  def dcsrUpdateSideEffect(dcsr: UInt): UInt = {
307    val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct))
308    val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11
309    dcsrNew
310  }
311  csrio.singleStep := dcsrData.step
312
313  // Machine-Level CSRs
314
315  val mtvec = RegInit(UInt(XLEN.W), 0.U)
316  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
317  val mcause = RegInit(UInt(XLEN.W), 0.U)
318  val mtval = RegInit(UInt(XLEN.W), 0.U)
319  val mepc = Reg(UInt(XLEN.W))
320
321  val mie = RegInit(0.U(XLEN.W))
322  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
323  val mipReg  = RegInit(0.U(XLEN.W))
324  val mipFixMask = ZeroExt(GenMask(9) | GenMask(5) | GenMask(1), XLEN)
325  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
326
327  def getMisaMxl(mxl: Int): UInt = {mxl.U << (XLEN-2)}.asUInt()
328  def getMisaExt(ext: Char): UInt = {1.U << (ext.toInt - 'a'.toInt)}.asUInt()
329  var extList = List('a', 's', 'i', 'u')
330  if (HasMExtension) { extList = extList :+ 'm' }
331  if (HasCExtension) { extList = extList :+ 'c' }
332  if (HasFPU) { extList = extList ++ List('f', 'd') }
333  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0.U)((sum, i) => sum | getMisaExt(i)) //"h8000000000141105".U
334  val misa = RegInit(UInt(XLEN.W), misaInitVal)
335
336  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
337  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
338
339  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
340  val marchid = RegInit(UInt(XLEN.W), 0.U) // return 0 to indicate the field is not implemented
341  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
342  val mhartid = RegInit(UInt(XLEN.W), csrio.hartId) // the hardware thread running the code
343  val mstatus = RegInit(UInt(XLEN.W), 0.U)
344
345  // mstatus Value Table
346  // | sd   |
347  // | pad1 |
348  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
349  // | uxl  | hardlinked to 00
350  // | pad0 |
351  // | tsr  |
352  // | tw   |
353  // | tvm  |
354  // | mxr  |
355  // | sum  |
356  // | mprv |
357  // | xs   | 00 |
358  // | fs   | 00 |
359  // | mpp  | 00 |
360  // | hpp  | 00 |
361  // | spp  | 0 |
362  // | pie  | 0000 | pie.h is used as UBE
363  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
364
365  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
366  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
367    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
368    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
369    mstatusNew
370  }
371
372  val mstatusMask = (~ZeroExt((
373    GenMask(XLEN-2, 38) | GenMask(31, 23) | GenMask(10, 9) | GenMask(2) |
374    GenMask(37) | // MBE
375    GenMask(36) | // SBE
376    GenMask(6)    // UBE
377  ), 64)).asUInt()
378
379  val medeleg = RegInit(UInt(XLEN.W), 0.U)
380  val mideleg = RegInit(UInt(XLEN.W), 0.U)
381  val mscratch = RegInit(UInt(XLEN.W), 0.U)
382
383  // PMP Mapping
384  val pmp = Wire(Vec(NumPMP, new PMPBase()))
385  val pmpMapping = if (NumPMP > 0) { // TODO: remove duplicate codes
386    val pmpCfgPerCSR = XLEN / new PMPConfig().getWidth
387    def pmpCfgIndex(i: Int) = (XLEN / 32) * (i / pmpCfgPerCSR)
388
389    /** to fit MaskedRegMap's write, declare cfgs as Merged CSRs and split them into each pmp */
390    val cfgMerged = RegInit(VecInit(Seq.fill(NumPMP / pmpCfgPerCSR)(0.U(XLEN.W))))
391    val cfgs = WireInit(cfgMerged).asTypeOf(Vec(NumPMP, new PMPConfig()))
392    val addr = Reg(Vec(NumPMP, UInt((PAddrBits-PMPOffBits).W)))
393    for (i <- pmp.indices) {
394      pmp(i).gen(cfgs(i), addr(i))
395    }
396
397    val cfg_mapping = (0 until NumPMP by pmpCfgPerCSR).map(i => {Map(
398      MaskedRegMap(
399        addr = PmpcfgBase + pmpCfgIndex(i),
400        reg = cfgMerged(i/pmpCfgPerCSR),
401        wmask = WritableMask,
402        wfn = new PMPConfig().write_cfg_vec
403      ))
404    }).fold(Map())((a, b) => a ++ b) // ugly code, hit me if u have better codes
405    val addr_mapping = (0 until NumPMP).map(i => {Map(
406      MaskedRegMap(
407        addr = PmpaddrBase + i,
408        reg = addr(i),
409        wmask = WritableMask,
410        wfn = { if (i != NumPMP-1) pmp(i).write_addr(pmp(i+1)) else pmp(i).write_addr },
411        rmask = WritableMask,
412        rfn = new PMPBase().read_addr(pmp(i).cfg)
413      ))
414    }).fold(Map())((a, b) => a ++ b) // ugly code, hit me if u have better codes.
415    cfg_mapping ++ addr_mapping
416  } else {
417    Map()
418  }
419  // Superviser-Level CSRs
420
421  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
422  val sstatusWmask = "hc6122".U(XLEN.W)
423  // Sstatus Write Mask
424  // -------------------------------------------------------
425  //    19           9   5     2
426  // 0  1100 0000 0001 0010 0010
427  // 0  c    0    1    2    2
428  // -------------------------------------------------------
429  val sstatusRmask = sstatusWmask | "h8000000300018000".U
430  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
431  val stvec = RegInit(UInt(XLEN.W), 0.U)
432  // val sie = RegInit(0.U(XLEN.W))
433  val sieMask = "h222".U & mideleg
434  val sipMask = "h222".U & mideleg
435  val sipWMask = "h2".U(XLEN.W) // ssip is writeable in smode
436  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
437  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
438  // val satpMask = "h80000fffffffffff".U(XLEN.W) // disable asid, mode can only be 8 / 0
439  // TODO: use config to control the length of asid
440  // val satpMask = "h8fffffffffffffff".U(XLEN.W) // enable asid, mode can only be 8 / 0
441  val satpMask = Cat("h8".U(4.W),Asid_true_mask(AsidLength),"hfffffffffff".U((XLEN - 4 - 16).W))
442  val sepc = RegInit(UInt(XLEN.W), 0.U)
443  val scause = RegInit(UInt(XLEN.W), 0.U)
444  val stval = Reg(UInt(XLEN.W))
445  val sscratch = RegInit(UInt(XLEN.W), 0.U)
446  val scounteren = RegInit(UInt(XLEN.W), 0.U)
447
448  // sbpctl
449  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
450  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
451  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
452  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
453  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
454  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
455  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
456  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
457  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
458
459  // spfctl Bit 0: L1plusCache Prefetcher Enable
460  // spfctl Bit 1: L2Cache Prefetcher Enable
461  val spfctl = RegInit(UInt(XLEN.W), "h3".U)
462  csrio.customCtrl.l1plus_pf_enable := spfctl(0)
463  csrio.customCtrl.l2_pf_enable := spfctl(1)
464
465  // sdsid: Differentiated Services ID
466  val sdsid = RegInit(UInt(XLEN.W), 0.U)
467  csrio.customCtrl.dsid := sdsid
468
469  // slvpredctl: load violation predict settings
470  val slvpredctl = RegInit(UInt(XLEN.W), "h70".U) // default reset period: 2^17
471  csrio.customCtrl.lvpred_disable := slvpredctl(0)
472  csrio.customCtrl.no_spec_load := slvpredctl(1)
473  csrio.customCtrl.storeset_wait_store := slvpredctl(2)
474  csrio.customCtrl.storeset_no_fast_wakeup := slvpredctl(3)
475  csrio.customCtrl.lvpred_timeout := slvpredctl(8, 4)
476
477  // smblockctl: memory block configurations
478  // bits 0-3: store buffer flush threshold (default: 8 entries)
479  val smblockctl_init_val =
480    ("hf".U & StoreBufferThreshold.U) |
481    (EnableLdVioCheckAfterReset.B.asUInt << 4)
482  val smblockctl = RegInit(UInt(XLEN.W), smblockctl_init_val)
483  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
484  // bits 4: enable load load violation check
485  csrio.customCtrl.ldld_vio_check := smblockctl(4)
486
487  val srnctl = RegInit(UInt(XLEN.W), "h1".U)
488  csrio.customCtrl.move_elim_enable := srnctl(0)
489
490  val tlbBundle = Wire(new TlbCsrBundle)
491  tlbBundle.satp.apply(satp)
492
493  csrio.tlb := tlbBundle
494
495  // User-Level CSRs
496  val uepc = Reg(UInt(XLEN.W))
497
498  // fcsr
499  class FcsrStruct extends Bundle {
500    val reserved = UInt((XLEN-3-5).W)
501    val frm = UInt(3.W)
502    val fflags = UInt(5.W)
503    assert(this.getWidth == XLEN)
504  }
505  val fcsr = RegInit(0.U(XLEN.W))
506  // set mstatus->sd and mstatus->fs when true
507  val csrw_dirty_fp_state = WireInit(false.B)
508
509  def frm_wfn(wdata: UInt): UInt = {
510    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
511    csrw_dirty_fp_state := true.B
512    fcsrOld.frm := wdata(2,0)
513    fcsrOld.asUInt()
514  }
515  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
516
517  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
518    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
519    val fcsrNew = WireInit(fcsrOld)
520    csrw_dirty_fp_state := true.B
521    if (update) {
522      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
523    } else {
524      fcsrNew.fflags := wdata(4,0)
525    }
526    fcsrNew.asUInt()
527  }
528  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
529
530  def fcsr_wfn(wdata: UInt): UInt = {
531    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
532    csrw_dirty_fp_state := true.B
533    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
534  }
535
536  val fcsrMapping = Map(
537    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
538    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
539    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
540  )
541
542  // Hart Priviledge Mode
543  val priviledgeMode = RegInit(UInt(2.W), ModeM)
544
545  // Emu perfcnt
546  val hasEmuPerfCnt = !env.FPGAPlatform
547  val nrEmuPerfCnts = if (hasEmuPerfCnt) 0x80 else 0x3
548
549  val emuPerfCnts    = List.fill(nrEmuPerfCnts)(RegInit(0.U(XLEN.W)))
550  val emuPerfCntCond = List.fill(nrEmuPerfCnts)(WireInit(false.B))
551  (emuPerfCnts zip emuPerfCntCond).map { case (c, e) => when (e) { c := c + 1.U } }
552
553  val emuPerfCntsLoMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1000 + i, emuPerfCnts(i)))
554  val emuPerfCntsHiMapping = (0 until nrEmuPerfCnts).map(i => MaskedRegMap(0x1080 + i, emuPerfCnts(i)(63, 32)))
555  println(s"CSR: hasEmuPerfCnt:${hasEmuPerfCnt}")
556
557  // Perf Counter
558  val nrPerfCnts = 29  // 3...31
559  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
560  val perfEvents = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
561  val mcountinhibit = RegInit(0.U(XLEN.W))
562  val mcycle = RegInit(0.U(XLEN.W))
563  mcycle := mcycle + 1.U
564  val minstret = RegInit(0.U(XLEN.W))
565  minstret := minstret + RegNext(csrio.perf.retiredInstr)
566  val ibufFull  = RegInit(0.U(XLEN.W))
567  ibufFull := ibufFull + RegNext(csrio.perf.frontendInfo.ibufFull)
568  val robFull   = RegInit(0.U(XLEN.W))
569  robFull := robFull + RegNext(csrio.perf.ctrlInfo.robFull)
570  val intdqFull = RegInit(0.U(XLEN.W))
571  intdqFull := intdqFull + RegNext(csrio.perf.ctrlInfo.intdqFull)
572  val fpdqFull  = RegInit(0.U(XLEN.W))
573  fpdqFull := fpdqFull + RegNext(csrio.perf.ctrlInfo.fpdqFull)
574  val lsdqFull  = RegInit(0.U(XLEN.W))
575  lsdqFull := lsdqFull + RegNext(csrio.perf.ctrlInfo.lsdqFull)
576  val sqFull    = RegInit(0.U(XLEN.W))
577  sqFull := sqFull + RegNext(csrio.perf.memInfo.sqFull)
578  val lqFull    = RegInit(0.U(XLEN.W))
579  lqFull := lqFull + RegNext(csrio.perf.memInfo.lqFull)
580  val dcacheMSHRFull = RegInit(0.U(XLEN.W))
581  dcacheMSHRFull := dcacheMSHRFull + RegNext(csrio.perf.memInfo.dcacheMSHRFull)
582  val bpRight   = RegInit(0.U(XLEN.W))
583  bpRight := bpRight + RegNext(csrio.perf.frontendInfo.bpuInfo.bpRight)
584  val bpWrong   = RegInit(0.U(XLEN.W))
585  bpWrong := bpWrong + RegNext(csrio.perf.frontendInfo.bpuInfo.bpWrong)
586
587  // CSR reg map
588  val basicPrivMapping = Map(
589
590    //--- User Trap Setup ---
591    // MaskedRegMap(Ustatus, ustatus),
592    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
593    // MaskedRegMap(Utvec, utvec),
594
595    //--- User Trap Handling ---
596    // MaskedRegMap(Uscratch, uscratch),
597    // MaskedRegMap(Uepc, uepc),
598    // MaskedRegMap(Ucause, ucause),
599    // MaskedRegMap(Utval, utval),
600    // MaskedRegMap(Uip, uip),
601
602    //--- User Counter/Timers ---
603    // MaskedRegMap(Cycle, cycle),
604    // MaskedRegMap(Time, time),
605    // MaskedRegMap(Instret, instret),
606
607    //--- Supervisor Trap Setup ---
608    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
609    // MaskedRegMap(Sedeleg, Sedeleg),
610    // MaskedRegMap(Sideleg, Sideleg),
611    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
612    MaskedRegMap(Stvec, stvec),
613    MaskedRegMap(Scounteren, scounteren),
614
615    //--- Supervisor Trap Handling ---
616    MaskedRegMap(Sscratch, sscratch),
617    MaskedRegMap(Sepc, sepc),
618    MaskedRegMap(Scause, scause),
619    MaskedRegMap(Stval, stval),
620    MaskedRegMap(Sip, mip.asUInt, sipWMask, MaskedRegMap.Unwritable, sipMask),
621
622    //--- Supervisor Protection and Translation ---
623    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
624
625    //--- Supervisor Custom Read/Write Registers
626    MaskedRegMap(Sbpctl, sbpctl),
627    MaskedRegMap(Spfctl, spfctl),
628    MaskedRegMap(Sdsid, sdsid),
629    MaskedRegMap(Slvpredctl, slvpredctl),
630    MaskedRegMap(Smblockctl, smblockctl),
631    MaskedRegMap(Srnctl, srnctl),
632
633    //--- Machine Information Registers ---
634    MaskedRegMap(Mvendorid, mvendorid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
635    MaskedRegMap(Marchid, marchid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
636    MaskedRegMap(Mimpid, mimpid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
637    MaskedRegMap(Mhartid, mhartid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
638
639    //--- Machine Trap Setup ---
640    MaskedRegMap(Mstatus, mstatus, mstatusMask, mstatusUpdateSideEffect, mstatusMask),
641    MaskedRegMap(Misa, misa), // now MXL, EXT is not changeable
642    MaskedRegMap(Medeleg, medeleg, "hf3ff".U(XLEN.W)),
643    MaskedRegMap(Mideleg, mideleg, "h222".U(XLEN.W)),
644    MaskedRegMap(Mie, mie),
645    MaskedRegMap(Mtvec, mtvec),
646    MaskedRegMap(Mcounteren, mcounteren),
647
648    //--- Machine Trap Handling ---
649    MaskedRegMap(Mscratch, mscratch),
650    MaskedRegMap(Mepc, mepc),
651    MaskedRegMap(Mcause, mcause),
652    MaskedRegMap(Mtval, mtval),
653    MaskedRegMap(Mip, mip.asUInt, 0.U(XLEN.W), MaskedRegMap.Unwritable),
654
655    //--- Debug Mode ---
656    MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
657    MaskedRegMap(Dpc, dpc),
658    MaskedRegMap(Dscratch, dscratch),
659    MaskedRegMap(Dscratch1, dscratch1)
660  )
661
662  var perfCntMapping = Map(
663    MaskedRegMap(Mcountinhibit, mcountinhibit),
664    MaskedRegMap(Mcycle, mcycle),
665    MaskedRegMap(Minstret, minstret),
666    MaskedRegMap(Mhpmevent3, ibufFull),
667    MaskedRegMap(Mhpmevent4, robFull),
668    MaskedRegMap(Mhpmevent5, intdqFull),
669    MaskedRegMap(Mhpmevent6, fpdqFull),
670    MaskedRegMap(Mhpmevent7, lsdqFull),
671    MaskedRegMap(Mhpmevent8, sqFull),
672    MaskedRegMap(Mhpmevent9, lqFull),
673    MaskedRegMap(Mhpmevent10, dcacheMSHRFull),
674    MaskedRegMap(Mhpmevent11, bpRight),
675    MaskedRegMap(Mhpmevent12, bpWrong),
676  )
677  // TODO: mechanism should be implemented later
678  // val MhpmcounterStart = Mhpmcounter3
679  // val MhpmeventStart   = Mhpmevent3
680  // for (i <- 0 until nrPerfCnts) {
681  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
682  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
683  // }
684
685  val cacheopRegs = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
686    name -> RegInit(0.U(attribute("width").toInt.W))
687  }}
688  val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
689    MaskedRegMap(
690      Scachebase + attribute("offset").toInt,
691      cacheopRegs(name)
692    )
693  }}
694
695  val mapping = basicPrivMapping ++
696                perfCntMapping ++
697                pmpMapping ++
698                emuPerfCntsLoMapping ++
699                (if (XLEN == 32) emuPerfCntsHiMapping else Nil) ++
700                (if (HasFPU) fcsrMapping else Nil) ++
701                (if (HasCustomCSRCacheOp) cacheopMapping else Nil)
702
703  val addr = src2(11, 0)
704  val csri = ZeroExt(src2(16, 12), XLEN)
705  val rdata = Wire(UInt(XLEN.W))
706  val wdata = LookupTree(func, List(
707    CSROpType.wrt  -> src1,
708    CSROpType.set  -> (rdata | src1),
709    CSROpType.clr  -> (rdata & (~src1).asUInt()),
710    CSROpType.wrti -> csri,
711    CSROpType.seti -> (rdata | csri),
712    CSROpType.clri -> (rdata & (~csri).asUInt())
713  ))
714
715  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U)
716  csrio.isPerfCnt := addrInPerfCnt
717
718  // satp wen check
719  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
720
721  // csr access check, special case
722  val tvmNotPermit = (priviledgeMode === ModeS && mstatusStruct.tvm.asBool)
723  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
724  csrio.disableSfence := tvmNotPermit
725
726  // general CSR wen check
727  val wen = valid && func =/= CSROpType.jmp && (addr=/=Satp.U || satpLegalMode)
728  val modePermitted = csrAccessPermissionCheck(addr, false.B, priviledgeMode)
729  val perfcntPermitted = perfcntPermissionCheck(addr, priviledgeMode, mcounteren, scounteren)
730  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && accessPermitted
731
732  // Writeable check is ingored.
733  // Currently, write to illegal csr addr will be ignored
734  MaskedRegMap.generate(mapping, addr, rdata, wen && permitted, wdata)
735  io.out.bits.data := rdata
736  io.out.bits.uop := io.in.bits.uop
737  io.out.bits.uop.cf := cfOut
738  io.out.bits.uop.ctrl.flushPipe := flushPipe
739
740  // send distribute csr a w signal
741  csrio.customCtrl.distribute_csr.w.valid := wen && permitted
742  csrio.customCtrl.distribute_csr.w.bits.data := wdata
743  csrio.customCtrl.distribute_csr.w.bits.addr := addr
744
745  // Fix Mip/Sip write
746  val fixMapping = Map(
747    MaskedRegMap(Mip, mipReg.asUInt, mipFixMask),
748    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask)
749  )
750  val rdataFix = Wire(UInt(XLEN.W))
751  val wdataFix = LookupTree(func, List(
752    CSROpType.wrt  -> src1,
753    CSROpType.set  -> (rdataFix | src1),
754    CSROpType.clr  -> (rdataFix & (~src1).asUInt()),
755    CSROpType.wrti -> csri,
756    CSROpType.seti -> (rdataFix | csri),
757    CSROpType.clri -> (rdataFix & (~csri).asUInt())
758  ))
759  MaskedRegMap.generate(fixMapping, addr, rdataFix, wen && permitted, wdataFix)
760
761  when (csrio.fpu.fflags.valid) {
762    fcsr := fflags_wfn(update = true)(csrio.fpu.fflags.bits)
763  }
764  // set fs and sd in mstatus
765  when (csrw_dirty_fp_state || csrio.fpu.dirty_fs) {
766    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
767    mstatusNew.fs := "b11".U
768    mstatusNew.sd := true.B
769    mstatus := mstatusNew.asUInt()
770  }
771  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
772
773  // CSR inst decode
774  val isEbreak = addr === privEbreak && func === CSROpType.jmp
775  val isEcall  = addr === privEcall  && func === CSROpType.jmp
776  val isMret   = addr === privMret   && func === CSROpType.jmp
777  val isSret   = addr === privSret   && func === CSROpType.jmp
778  val isUret   = addr === privUret   && func === CSROpType.jmp
779  val isDret   = addr === privDret   && func === CSROpType.jmp
780
781  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
782  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, priviledgeMode)
783
784  // Illegal priviledged operation list
785  val illegalSModeSret = valid && isSret && priviledgeMode === ModeS && mstatusStruct.tsr.asBool
786
787  // Illegal priviledged instruction check
788  val isIllegalAddr = MaskedRegMap.isIllegalAddr(mapping, addr)
789  val isIllegalAccess = !permitted
790  val isIllegalPrivOp = illegalSModeSret
791
792  // expose several csr bits for tlb
793  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
794  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
795  tlbBundle.priv.imode := priviledgeMode
796  tlbBundle.priv.dmode := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, priviledgeMode)
797
798  // Branch control
799  val retTarget = Wire(UInt(VAddrBits.W))
800  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
801  flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall)
802
803  retTarget := DontCare
804  // val illegalEret = TODO
805
806  when (valid && isDret) {
807    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
808    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
809    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
810    val debugModeNew = WireInit(debugMode)
811    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.
812    mstatus := mstatusNew.asUInt
813    priviledgeMode := dcsrNew.prv
814    retTarget := dpc(VAddrBits-1, 0)
815    debugModeNew := false.B
816    debugIntrEnable := true.B
817    debugMode := debugModeNew
818    XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget)
819  }
820
821  when (valid && isMret) {
822    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
823    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
824    mstatusNew.ie.m := mstatusOld.pie.m
825    priviledgeMode := mstatusOld.mpp
826    mstatusNew.pie.m := true.B
827    mstatusNew.mpp := ModeU
828    when (mstatusOld.mpp =/= ModeM) { mstatusNew.mprv := 0.U }
829    mstatus := mstatusNew.asUInt
830    // lr := false.B
831    retTarget := mepc(VAddrBits-1, 0)
832  }
833
834  when (valid && isSret && !illegalSModeSret) {
835    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
836    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
837    mstatusNew.ie.s := mstatusOld.pie.s
838    priviledgeMode := Cat(0.U(1.W), mstatusOld.spp)
839    mstatusNew.pie.s := true.B
840    mstatusNew.spp := ModeU
841    mstatus := mstatusNew.asUInt
842    mstatusNew.mprv := 0.U
843    // lr := false.B
844    retTarget := sepc(VAddrBits-1, 0)
845  }
846
847  when (valid && isUret) {
848    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
849    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
850    // mstatusNew.mpp.m := ModeU //TODO: add mode U
851    mstatusNew.ie.u := mstatusOld.pie.u
852    priviledgeMode := ModeU
853    mstatusNew.pie.u := true.B
854    mstatus := mstatusNew.asUInt
855    retTarget := uepc(VAddrBits-1, 0)
856  }
857
858  io.in.ready := true.B
859  io.out.valid := valid
860
861  val ebreakCauseException = (priviledgeMode === ModeM && dcsrData.ebreakm) || (priviledgeMode === ModeS && dcsrData.ebreaks) || (priviledgeMode === ModeU && dcsrData.ebreaku)
862
863  val csrExceptionVec = WireInit(cfIn.exceptionVec)
864  csrExceptionVec(breakPoint) := io.in.valid && isEbreak && ebreakCauseException
865  csrExceptionVec(ecallM) := priviledgeMode === ModeM && io.in.valid && isEcall
866  csrExceptionVec(ecallS) := priviledgeMode === ModeS && io.in.valid && isEcall
867  csrExceptionVec(ecallU) := priviledgeMode === ModeU && io.in.valid && isEcall
868  // Trigger an illegal instr exception when:
869  // * unimplemented csr is being read/written
870  // * csr access is illegal
871  csrExceptionVec(illegalInstr) := (isIllegalAddr || isIllegalAccess) && wen
872  cfOut.exceptionVec := csrExceptionVec
873
874  /**
875    * Exception and Intr
876    */
877  val ideleg =  (mideleg & mip.asUInt)
878  def priviledgedEnableDetect(x: Bool): Bool = Mux(x, ((priviledgeMode === ModeS) && mstatusStruct.ie.s) || (priviledgeMode < ModeS),
879    ((priviledgeMode === ModeM) && mstatusStruct.ie.m) || (priviledgeMode < ModeM))
880
881  val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable
882  XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!")
883  // send interrupt information to ROB
884  val intrVecEnable = Wire(Vec(12, Bool()))
885  intrVecEnable.zip(ideleg.asBools).map{case(x,y) => x := priviledgedEnableDetect(y)}
886  val intrVec = Cat(debugIntr, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt))
887  val intrBitSet = intrVec.orR()
888  csrio.interrupt := intrBitSet
889  mipWire.t.m := csrio.externalInterrupt.mtip
890  mipWire.s.m := csrio.externalInterrupt.msip
891  mipWire.e.m := csrio.externalInterrupt.meip
892  mipWire.e.s := csrio.externalInterrupt.meip
893
894  // interrupts
895  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
896  val raiseIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
897  XSDebug(raiseIntr, "interrupt: pc=0x%x, %d\n", csrio.exception.bits.uop.cf.pc, intrNO)
898  val raiseDebugIntr = intrNO === IRQ_DEBUG.U && raiseIntr
899
900  // exceptions
901  val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt
902  val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException
903  val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException
904  val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException
905  val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException
906  val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException
907  val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException
908  val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
909  val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
910  val hasbreakPoint = csrio.exception.bits.uop.cf.exceptionVec(breakPoint) && raiseException
911  val hasSingleStep = csrio.exception.bits.uop.cf.exceptionVec(singleStep) && raiseException
912
913  val raiseExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
914  val exceptionNO = ExcPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(raiseExceptionVec(i), i.U, sum))
915  val causeNO = (raiseIntr << (XLEN-1)).asUInt() | Mux(raiseIntr, intrNO, exceptionNO)
916
917  val raiseExceptionIntr = csrio.exception.valid
918
919  val raiseDebugExceptionIntr = !debugMode && hasbreakPoint || raiseDebugIntr || hasSingleStep
920  val ebreakEnterParkLoop = debugMode && raiseExceptionIntr // exception in debug mode (except ebrk) changes cmderr. how ???
921
922  XSDebug(raiseExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
923    csrio.exception.bits.uop.cf.pc, intrNO, intrVec, exceptionNO, raiseExceptionVec.asUInt
924  )
925  XSDebug(raiseExceptionIntr,
926    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
927    csrio.exception.bits.uop.cf.pc,
928    mstatus,
929    mideleg,
930    medeleg,
931    priviledgeMode
932  )
933
934  // mtval write logic
935  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
936  when (hasInstrPageFault || hasLoadPageFault || hasStorePageFault) {
937    val tval = Mux(
938      hasInstrPageFault,
939      Mux(
940        csrio.exception.bits.uop.cf.crossPageIPFFix,
941        SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN),
942        SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
943      ),
944      memExceptionAddr
945    )
946    when (priviledgeMode === ModeM) {
947      mtval := tval
948    }.otherwise {
949      stval := tval
950    }
951  }
952
953  when (hasLoadAddrMisaligned || hasStoreAddrMisaligned) {
954    mtval := memExceptionAddr
955  }
956
957  val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec
958  val deleg = Mux(raiseIntr, mideleg , medeleg)
959  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (priviledgeMode < ModeM);
960  val delegS = deleg(causeNO(3,0)) && (priviledgeMode < ModeM)
961  val tvalWen = !(hasInstrPageFault || hasLoadPageFault || hasStorePageFault || hasLoadAddrMisaligned || hasStoreAddrMisaligned) || raiseIntr // TODO: need check
962  val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall && !isEbreak
963
964  // ctrl block will use theses later for flush
965  val isXRetFlag = RegInit(false.B)
966  val retTargetReg = Reg(retTarget.cloneType)
967  when (io.redirectIn.valid) {
968    isXRetFlag := false.B
969  }.elsewhen (isXRet) {
970    isXRetFlag := true.B
971    retTargetReg := retTarget
972  }
973  csrio.isXRet := isXRetFlag
974  csrio.trapTarget := Mux(isXRetFlag,
975    retTargetReg,
976    Mux(raiseDebugExceptionIntr || ebreakEnterParkLoop, debugTrapTarget,
977      Mux(delegS, stvec, mtvec))(VAddrBits-1, 0)
978  )
979
980  when (raiseExceptionIntr) {
981    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
982    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
983    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
984    val debugModeNew = WireInit(debugMode)
985
986    when (raiseDebugExceptionIntr) {
987      when (raiseDebugIntr) {
988        debugModeNew := true.B
989        mstatusNew.mprv := false.B
990        dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
991        dcsrNew.cause := 1.U
992        dcsrNew.prv := priviledgeMode
993        priviledgeMode := ModeM
994        XSDebug(raiseDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc)
995      }.elsewhen ((hasbreakPoint || hasSingleStep) && !debugMode) {
996        // ebreak or ss in running hart
997        debugModeNew := true.B
998        dpc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
999        dcsrNew.cause := Mux(hasbreakPoint, 3.U, 0.U)
1000        dcsrNew.prv := priviledgeMode // TODO
1001        priviledgeMode := ModeM
1002        mstatusNew.mprv := false.B
1003      }
1004      dcsr := dcsrNew.asUInt
1005      debugIntrEnable := false.B
1006    }.elsewhen (delegS) {
1007      scause := causeNO
1008      sepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1009      mstatusNew.spp := priviledgeMode
1010      mstatusNew.pie.s := mstatusOld.ie.s
1011      mstatusNew.ie.s := false.B
1012      priviledgeMode := ModeS
1013      when (tvalWen) { stval := 0.U }
1014    }.otherwise {
1015      mcause := causeNO
1016      mepc := SignExt(csrio.exception.bits.uop.cf.pc, XLEN)
1017      mstatusNew.mpp := priviledgeMode
1018      mstatusNew.pie.m := mstatusOld.ie.m
1019      mstatusNew.ie.m := false.B
1020      priviledgeMode := ModeM
1021      when (tvalWen) { mtval := 0.U }
1022    }
1023    mstatus := mstatusNew.asUInt
1024    debugMode := debugModeNew
1025  }
1026
1027  XSDebug(raiseExceptionIntr && delegS, "sepc is writen!!! pc:%x\n", cfIn.pc)
1028
1029  // Distributed CSR update req
1030  //
1031  // For now we use it to implement customized cache op
1032
1033  when(csrio.distributedUpdate.w.valid){
1034    // cacheopRegs can be distributed updated
1035    CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
1036      when((Scachebase + attribute("offset").toInt).U === csrio.distributedUpdate.w.bits.addr){
1037        cacheopRegs(name) := csrio.distributedUpdate.w.bits.data
1038      }
1039    }}
1040  }
1041
1042  def readWithScala(addr: Int): UInt = mapping(addr)._1
1043
1044  val difftestIntrNO = Mux(raiseIntr, causeNO, 0.U)
1045
1046  if (!env.FPGAPlatform) {
1047    val difftest = Module(new DifftestArchEvent)
1048    difftest.io.clock := clock
1049    difftest.io.coreid := hardId.U
1050    difftest.io.intrNO := RegNext(difftestIntrNO)
1051    difftest.io.cause := RegNext(Mux(csrio.exception.valid, causeNO, 0.U))
1052    difftest.io.exceptionPC := RegNext(SignExt(csrio.exception.bits.uop.cf.pc, XLEN))
1053  }
1054
1055  if (!env.FPGAPlatform) {
1056    val difftest = Module(new DifftestCSRState)
1057    difftest.io.clock := clock
1058    difftest.io.coreid := hardId.U
1059    difftest.io.priviledgeMode := priviledgeMode
1060    difftest.io.mstatus := mstatus
1061    difftest.io.sstatus := mstatus & sstatusRmask
1062    difftest.io.mepc := mepc
1063    difftest.io.sepc := sepc
1064    difftest.io.mtval:= mtval
1065    difftest.io.stval:= stval
1066    difftest.io.mtvec := mtvec
1067    difftest.io.stvec := stvec
1068    difftest.io.mcause := mcause
1069    difftest.io.scause := scause
1070    difftest.io.satp := satp
1071    difftest.io.mip := mipReg
1072    difftest.io.mie := mie
1073    difftest.io.mscratch := mscratch
1074    difftest.io.sscratch := sscratch
1075    difftest.io.mideleg := mideleg
1076    difftest.io.medeleg := medeleg
1077  }
1078}
1079