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