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