xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision d0de7e4a4bcd4633260dda99dfedc2a5e543b8b4)
1c6d43980SLemover/***************************************************************************************
2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory
4c6d43980SLemover*
5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2.
6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2.
7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at:
8c6d43980SLemover*          http://license.coscl.org.cn/MulanPSL2
9c6d43980SLemover*
10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13c6d43980SLemover*
14c6d43980SLemover* See the Mulan PSL v2 for more details.
15c6d43980SLemover***************************************************************************************/
16c6d43980SLemover
17c84054caSLinJiaweipackage xiangshan.backend.fu
18c84054caSLinJiawei
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
20c84054caSLinJiaweiimport chisel3._
21c84054caSLinJiaweiimport chisel3.util._
226ab6918fSYinan Xuimport difftest._
23b6982e83SLemoverimport freechips.rocketchip.util._
243c02ee8fSwakafaimport utility.MaskedRegMap.WritableMask
25c84054caSLinJiaweiimport utils._
263c02ee8fSwakafaimport utility._
276ab6918fSYinan Xuimport xiangshan.ExceptionNO._
28c84054caSLinJiaweiimport xiangshan._
29db988794Swangkaifanimport xiangshan.backend.fu.util._
306ab6918fSYinan Xuimport xiangshan.cache._
31c84054caSLinJiawei
3272951335SLi Qianruo// Trigger Tdata1 bundles
3372951335SLi Qianruotrait HasTriggerConst {
3472951335SLi Qianruo  def I_Trigger = 0.U
3572951335SLi Qianruo  def S_Trigger = 1.U
3672951335SLi Qianruo  def L_Trigger = 2.U
37bc63e578SLi Qianruo  def GenESL(triggerType: UInt) = Cat((triggerType === I_Trigger), (triggerType === S_Trigger), (triggerType === L_Trigger))
3872951335SLi Qianruo}
3972951335SLi Qianruo
4072951335SLi Qianruoclass TdataBundle extends Bundle {
41716f717fSLi Qianruo  val ttype = UInt(4.W)
42716f717fSLi Qianruo  val dmode = Bool()
43716f717fSLi Qianruo  val maskmax = UInt(6.W)
44716f717fSLi Qianruo  val zero1 = UInt(30.W)
45716f717fSLi Qianruo  val sizehi = UInt(2.W)
46716f717fSLi Qianruo  val hit = Bool()
4772951335SLi Qianruo  val select = Bool()
4872951335SLi Qianruo  val timing = Bool()
49716f717fSLi Qianruo  val sizelo = UInt(2.W)
50716f717fSLi Qianruo  val action = UInt(4.W)
5172951335SLi Qianruo  val chain = Bool()
52716f717fSLi Qianruo  val matchType = UInt(4.W)
5372951335SLi Qianruo  val m = Bool()
54716f717fSLi Qianruo  val zero2 = Bool()
5572951335SLi Qianruo  val s = Bool()
5672951335SLi Qianruo  val u = Bool()
57716f717fSLi Qianruo  val execute = Bool()
58716f717fSLi Qianruo  val store = Bool()
59716f717fSLi Qianruo  val load = Bool()
6072951335SLi Qianruo}
6172951335SLi Qianruo
622225d46eSJiawei Linclass FpuCsrIO extends Bundle {
637f1506e3SLinJiawei  val fflags = Output(Valid(UInt(5.W)))
64c84054caSLinJiawei  val isIllegal = Output(Bool())
65c84054caSLinJiawei  val dirty_fs = Output(Bool())
66c84054caSLinJiawei  val frm = Input(UInt(3.W))
67c84054caSLinJiawei}
68c84054caSLinJiawei
69b2e234ebSLinJiawei
702225d46eSJiawei Linclass PerfCounterIO(implicit p: Parameters) extends XSBundle {
711ca0e4f3SYinan Xu  val perfEventsFrontend  = Vec(numCSRPCntFrontend, new PerfEvent)
721ca0e4f3SYinan Xu  val perfEventsCtrl      = Vec(numCSRPCntCtrl, new PerfEvent)
731ca0e4f3SYinan Xu  val perfEventsLsu       = Vec(numCSRPCntLsu, new PerfEvent)
741ca0e4f3SYinan Xu  val perfEventsHc        = Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent)
75edd6ddbcSwakafa  val retiredInstr = UInt(3.W)
76edd6ddbcSwakafa  val frontendInfo = new Bundle {
77edd6ddbcSwakafa    val ibufFull  = Bool()
78e0d9a9f0SLingrui98    val bpuInfo = new Bundle {
79e0d9a9f0SLingrui98      val bpRight = UInt(XLEN.W)
80e0d9a9f0SLingrui98      val bpWrong = UInt(XLEN.W)
81e0d9a9f0SLingrui98    }
82edd6ddbcSwakafa  }
83edd6ddbcSwakafa  val ctrlInfo = new Bundle {
849aca92b9SYinan Xu    val robFull   = Bool()
85edd6ddbcSwakafa    val intdqFull = Bool()
86edd6ddbcSwakafa    val fpdqFull  = Bool()
87edd6ddbcSwakafa    val lsdqFull  = Bool()
88edd6ddbcSwakafa  }
89edd6ddbcSwakafa  val memInfo = new Bundle {
90edd6ddbcSwakafa    val sqFull = Bool()
91edd6ddbcSwakafa    val lqFull = Bool()
92edd6ddbcSwakafa    val dcacheMSHRFull = Bool()
93edd6ddbcSwakafa  }
94e0d9a9f0SLingrui98
95edd6ddbcSwakafa  val cacheInfo = new Bundle {
96edd6ddbcSwakafa    val l2MSHRFull = Bool()
97edd6ddbcSwakafa    val l3MSHRFull = Bool()
98edd6ddbcSwakafa    val l2nAcquire = UInt(XLEN.W)
99edd6ddbcSwakafa    val l2nAcquireMiss = UInt(XLEN.W)
100edd6ddbcSwakafa    val l3nAcquire = UInt(XLEN.W)
101edd6ddbcSwakafa    val l3nAcquireMiss = UInt(XLEN.W)
102edd6ddbcSwakafa  }
10362ab1317SYinan Xu}
10462ab1317SYinan Xu
1052225d46eSJiawei Linclass CSRFileIO(implicit p: Parameters) extends XSBundle {
106f57f7f2aSYangyu Chen  val hartId = Input(UInt(hartIdLen.W))
107129a273eSYinan Xu  // output (for func === CSROpType.jmp)
108edd6ddbcSwakafa  val perf = Input(new PerfCounterIO)
1098635f18fSwangkaifan  val isPerfCnt = Output(Bool())
110129a273eSYinan Xu  // to FPU
111129a273eSYinan Xu  val fpu = Flipped(new FpuCsrIO)
112bf9968b2SYinan Xu  // from rob
1133a474d38SYinan Xu  val exception = Flipped(ValidIO(new ExceptionInfo))
114129a273eSYinan Xu  // to ROB
115ac5a5d53SLinJiawei  val isXRet = Output(Bool())
116129a273eSYinan Xu  val trapTarget = Output(UInt(VAddrBits.W))
117129a273eSYinan Xu  val interrupt = Output(Bool())
1185c95ea2eSYinan Xu  val wfi_event = Output(Bool())
119129a273eSYinan Xu  // from LSQ
120129a273eSYinan Xu  val memExceptionVAddr = Input(UInt(VAddrBits.W))
121*d0de7e4aSpeixiaokun  val memExceptionGPAddr = Input(UInt(GPAddrBits.W))
122129a273eSYinan Xu  // from outside cpu,externalInterrupt
123129a273eSYinan Xu  val externalInterrupt = new ExternalInterruptIO
124129a273eSYinan Xu  // TLB
125129a273eSYinan Xu  val tlb = Output(new TlbCsrBundle)
126d4aca96cSlqre  // Debug Mode
127d7dd1af1SLi Qianruo  // val singleStep = Output(Bool())
128d4aca96cSlqre  val debugMode = Output(Bool())
129e5adbe81SLemover  // to Fence to disable sfence
130e5adbe81SLemover  val disableSfence = Output(Bool())
131*d0de7e4aSpeixiaokun  // to Fence to disable hfence.gvma
132*d0de7e4aSpeixiaokun  val disableHfenceg = Output(Bool())
133*d0de7e4aSpeixiaokun  // to Fence to disable hfence.vvma
134*d0de7e4aSpeixiaokun  val disableHfencev = Output(Bool())
135e377d77eSWilliam Wang  // Custom microarchiture ctrl signal
136e377d77eSWilliam Wang  val customCtrl = Output(new CustomCSRCtrlIO)
137e377d77eSWilliam Wang  // distributed csr write
13870899835SWilliam Wang  val distributedUpdate = Vec(2, Flipped(new DistributedCSRUpdateReq))
13935a47a38SYinan Xu}
14035a47a38SYinan Xu
14172951335SLi Qianruoclass CSR(implicit p: Parameters) extends FunctionUnit with HasCSRConst with PMPMethod with PMAMethod with HasTriggerConst
14235a47a38SYinan Xu{
14335a47a38SYinan Xu  val csrio = IO(new CSRFileIO)
144c84054caSLinJiawei
145e18c367fSLinJiawei  val cfIn = io.in.bits.uop.cf
146e18c367fSLinJiawei  val cfOut = Wire(new CtrlFlow)
147e18c367fSLinJiawei  cfOut := cfIn
148e18c367fSLinJiawei  val flushPipe = Wire(Bool())
149c84054caSLinJiawei
150e18c367fSLinJiawei  val (valid, src1, src2, func) = (
151e18c367fSLinJiawei    io.in.valid,
152e18c367fSLinJiawei    io.in.bits.src(0),
153e18c367fSLinJiawei    io.in.bits.uop.ctrl.imm,
154e18c367fSLinJiawei    io.in.bits.uop.ctrl.fuOpType
155e18c367fSLinJiawei  )
156c84054caSLinJiawei
157c84054caSLinJiawei  // CSR define
158*d0de7e4aSpeixiaokun  val virtMode = RegInit(false.B)
159*d0de7e4aSpeixiaokun  csrio.customCtrl.virtMode := virtMode
160c84054caSLinJiawei
161c84054caSLinJiawei  class Priv extends Bundle {
162c84054caSLinJiawei    val m = Output(Bool())
163*d0de7e4aSpeixiaokun    val h = Output(Bool()) // unused
164c84054caSLinJiawei    val s = Output(Bool())
165c84054caSLinJiawei    val u = Output(Bool())
166c84054caSLinJiawei  }
167c84054caSLinJiawei
168c84054caSLinJiawei  val csrNotImplemented = RegInit(UInt(XLEN.W), 0.U)
169c84054caSLinJiawei
170d4aca96cSlqre  class DcsrStruct extends Bundle {
1715b0f0029SXuan Hu    val debugver  = Output(UInt(4.W)) // 28
1725b0f0029SXuan Hu    val pad1      = Output(UInt(10.W))// 18
1735b0f0029SXuan Hu    val ebreakvs  = Output(Bool())    // 17 reserved for Hypervisor debug
1745b0f0029SXuan Hu    val ebreakvu  = Output(Bool())    // 16 reserved for Hypervisor debug
1755b0f0029SXuan Hu    val ebreakm   = Output(Bool())    // 15
1765b0f0029SXuan Hu    val pad0      = Output(Bool())    // 14 ebreakh has been removed
1775b0f0029SXuan Hu    val ebreaks   = Output(Bool())    // 13
1785b0f0029SXuan Hu    val ebreaku   = Output(Bool())    // 12
1795b0f0029SXuan Hu    val stepie    = Output(Bool())    // 11
1805b0f0029SXuan Hu    val stopcount = Output(Bool())    // 10
1815b0f0029SXuan Hu    val stoptime  = Output(Bool())    // 9
1825b0f0029SXuan Hu    val cause     = Output(UInt(3.W)) // 6
1835b0f0029SXuan Hu    val v         = Output(Bool())    // 5
1845b0f0029SXuan Hu    val mprven    = Output(Bool())    // 4
1855b0f0029SXuan Hu    val nmip      = Output(Bool())    // 3
1865b0f0029SXuan Hu    val step      = Output(Bool())    // 2
1875b0f0029SXuan Hu    val prv       = Output(UInt(2.W)) // 0
188d4aca96cSlqre  }
189d4aca96cSlqre
1905b0f0029SXuan Hu  object DcsrStruct extends DcsrStruct {
1915b0f0029SXuan Hu    private def debugver_offset   = 28
1925b0f0029SXuan Hu    private def stopcount_offset  = 10
1935b0f0029SXuan Hu    private def stoptime_offset   = 9
1945b0f0029SXuan Hu    private def mprven_offset     = 5
1955b0f0029SXuan Hu    private def prv_offset        = 0
1965b0f0029SXuan Hu    def init: UInt = (
1975b0f0029SXuan Hu      (4L << debugver_offset) |   /* Debug implementation as it described in 0.13 draft */
1985b0f0029SXuan Hu      (0L << stopcount_offset) |  /* Stop count updating has not been supported */
1995b0f0029SXuan Hu      (0L << stoptime_offset) |   /* Stop time updating has not been supported */
2005b0f0029SXuan Hu      (0L << mprven_offset) |     /* Whether use mstatus.perven mprven */
2015b0f0029SXuan Hu      (3L << prv_offset)          /* Hart was operating in Privilege M when Debug Mode was entered */
2025b0f0029SXuan Hu    ).U
2035b0f0029SXuan Hu  }
2045b0f0029SXuan Hu  require(new DcsrStruct().getWidth == 32)
2055b0f0029SXuan Hu
206c84054caSLinJiawei  class MstatusStruct extends Bundle {
207c84054caSLinJiawei    val sd = Output(UInt(1.W))
2088e7b11e5SWilliam Wang
209*d0de7e4aSpeixiaokun    val pad1 = if (XLEN == 64 && HasHExtension) Output(UInt(23.W)) else if (XLEN == 64) Output(UInt(25.W)) else null
210*d0de7e4aSpeixiaokun    val mpv  = if (XLEN == 64 && HasHExtension) Output(UInt(1.W)) else null
211*d0de7e4aSpeixiaokun    val gva  = if (XLEN == 64 && HasHExtension) Output(UInt(1.W)) else null
2127d9edc86SLemover    val mbe  = if (XLEN == 64) Output(UInt(1.W)) else null
2137d9edc86SLemover    val sbe  = if (XLEN == 64) Output(UInt(1.W)) else null
2148e7b11e5SWilliam Wang    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
2158e7b11e5SWilliam Wang    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
2168e7b11e5SWilliam Wang    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
2178e7b11e5SWilliam Wang
218c84054caSLinJiawei    val tsr = Output(UInt(1.W))
219c84054caSLinJiawei    val tw = Output(UInt(1.W))
2208e7b11e5SWilliam Wang    val tvm = Output(UInt(1.W))
221c84054caSLinJiawei    val mxr = Output(UInt(1.W))
222c84054caSLinJiawei    val sum = Output(UInt(1.W))
223c84054caSLinJiawei    val mprv = Output(UInt(1.W))
224c84054caSLinJiawei    val xs = Output(UInt(2.W))
225c84054caSLinJiawei    val fs = Output(UInt(2.W))
226c84054caSLinJiawei    val mpp = Output(UInt(2.W))
227*d0de7e4aSpeixiaokun    val vs = Output(UInt(2.W))
228c84054caSLinJiawei    val spp = Output(UInt(1.W))
229c84054caSLinJiawei    val pie = new Priv
230c84054caSLinJiawei    val ie = new Priv
231c84054caSLinJiawei    assert(this.getWidth == XLEN)
2327d9edc86SLemover
2337d9edc86SLemover    def ube = pie.h // a little ugly
2347d9edc86SLemover    def ube_(r: UInt): Unit = {
2357d9edc86SLemover      pie.h := r(0)
2367d9edc86SLemover    }
237c84054caSLinJiawei  }
238c84054caSLinJiawei
239*d0de7e4aSpeixiaokun  class HstatusStruct extends Bundle {
240*d0de7e4aSpeixiaokun    val pad4 = if (HSXLEN == 64) Output(UInt(30.W)) else null
241*d0de7e4aSpeixiaokun    val vsxl = if (HSXLEN == 64) Output(UInt(2.W)) else null
242*d0de7e4aSpeixiaokun    val pad3 = Output(UInt(9.W))
243*d0de7e4aSpeixiaokun    val vtsr = Output(UInt(1.W))
244*d0de7e4aSpeixiaokun    val vtw = Output(UInt(1.W))
245*d0de7e4aSpeixiaokun    val vtvm = Output(UInt(1.W))
246*d0de7e4aSpeixiaokun    val pad2 = Output(UInt(2.W))
247*d0de7e4aSpeixiaokun    val vgein = Output(UInt(6.W))
248*d0de7e4aSpeixiaokun    val pad1 = Output(UInt(2.W))
249*d0de7e4aSpeixiaokun    val hu = Output(UInt(1.W))
250*d0de7e4aSpeixiaokun    val spvp = Output(UInt(1.W))
251*d0de7e4aSpeixiaokun    val spv = Output(UInt(1.W))
252*d0de7e4aSpeixiaokun    val gva = Output(UInt(1.W))
253*d0de7e4aSpeixiaokun    val vsbe = Output(UInt(1.W))
254*d0de7e4aSpeixiaokun    val pad0 = Output(UInt(5.W))
255*d0de7e4aSpeixiaokun    assert(this.getWidth == XLEN)
256*d0de7e4aSpeixiaokun  }
257*d0de7e4aSpeixiaokun
258c84054caSLinJiawei  class Interrupt extends Bundle {
259d4aca96cSlqre//  val d = Output(Bool())    // Debug
260c84054caSLinJiawei    val e = new Priv
261c84054caSLinJiawei    val t = new Priv
262c84054caSLinJiawei    val s = new Priv
263c84054caSLinJiawei  }
264c84054caSLinJiawei
265d4aca96cSlqre  // Debug CSRs
2665b0f0029SXuan Hu  val dcsr = RegInit(UInt(32.W), DcsrStruct.init)
267d4aca96cSlqre  val dpc = Reg(UInt(64.W))
2685b0f0029SXuan Hu  val dscratch0 = Reg(UInt(64.W))
269d4aca96cSlqre  val dscratch1 = Reg(UInt(64.W))
270d4aca96cSlqre  val debugMode = RegInit(false.B)
2715b0f0029SXuan Hu  val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable
272d4aca96cSlqre  csrio.debugMode := debugMode
273d4aca96cSlqre
274d4aca96cSlqre  val dpcPrev = RegNext(dpc)
2751097f021SLi Qianruo  XSDebug(dpcPrev =/= dpc, "Debug Mode: dpc is altered! Current is %x, previous is %x\n", dpc, dpcPrev)
276d4aca96cSlqre
277d4aca96cSlqre  // dcsr value table
278d4aca96cSlqre  // | debugver | 0100
279d4aca96cSlqre  // | zero     | 10 bits of 0
280d4aca96cSlqre  // | ebreakvs | 0
281d4aca96cSlqre  // | ebreakvu | 0
282d4aca96cSlqre  // | ebreakm  | 1 if ebreak enters debug
283d4aca96cSlqre  // | zero     | 0
284d4aca96cSlqre  // | ebreaks  |
285d4aca96cSlqre  // | ebreaku  |
286052ee9a1SLi Qianruo  // | stepie   | disable interrupts in singlestep
287d4aca96cSlqre  // | stopcount| stop counter, 0
288d4aca96cSlqre  // | stoptime | stop time, 0
289d4aca96cSlqre  // | cause    | 3 bits read only
290d4aca96cSlqre  // | v        | 0
291d4aca96cSlqre  // | mprven   | 1
292d4aca96cSlqre  // | nmip     | read only
293d4aca96cSlqre  // | step     |
294d4aca96cSlqre  // | prv      | 2 bits
295ad3ba452Szhanglinjuan
296d4aca96cSlqre  val dcsrData = Wire(new DcsrStruct)
297d4aca96cSlqre  dcsrData := dcsr.asTypeOf(new DcsrStruct)
298d7dd1af1SLi Qianruo  val dcsrMask = ZeroExt(GenMask(15) | GenMask(13, 11) | GenMask(4) | GenMask(2, 0), XLEN)// Dcsr write mask
299d4aca96cSlqre  def dcsrUpdateSideEffect(dcsr: UInt): UInt = {
300d4aca96cSlqre    val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct))
301d4aca96cSlqre    val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11
302d4aca96cSlqre    dcsrNew
303d4aca96cSlqre  }
304d7dd1af1SLi Qianruo  // csrio.singleStep := dcsrData.step
305d7dd1af1SLi Qianruo  csrio.customCtrl.singlestep := dcsrData.step && !debugMode
306d4aca96cSlqre
30772951335SLi Qianruo  // Trigger CSRs
30872951335SLi Qianruo
309716f717fSLi Qianruo  val type_config = Array(
310716f717fSLi Qianruo    0.U -> I_Trigger, 1.U -> I_Trigger,
311716f717fSLi Qianruo    2.U -> S_Trigger, 3.U -> S_Trigger,
312716f717fSLi Qianruo    4.U -> L_Trigger, 5.U -> L_Trigger, // No.5 Load Trigger
313716f717fSLi Qianruo    6.U -> I_Trigger, 7.U -> S_Trigger,
314716f717fSLi Qianruo    8.U -> I_Trigger, 9.U -> L_Trigger
315716f717fSLi Qianruo  )
31645f43e6eSTang Haojin  def TypeLookup(select: UInt) = MuxLookup(select, I_Trigger)(type_config)
317716f717fSLi Qianruo
318ddb65c47SLi Qianruo  val tdata1Phy = RegInit(VecInit(List.fill(10) {(2L << 60L).U(64.W)})) // init ttype 2
31972951335SLi Qianruo  val tdata2Phy = Reg(Vec(10, UInt(64.W)))
32072951335SLi Qianruo  val tselectPhy = RegInit(0.U(4.W))
321716f717fSLi Qianruo  val tinfo = RegInit(2.U(64.W))
32272951335SLi Qianruo  val tControlPhy = RegInit(0.U(64.W))
32384e47f35SLi Qianruo  val triggerAction = RegInit(false.B)
324716f717fSLi Qianruo
325ba762693SYinan Xu  def ReadTdata1(rdata: UInt) = rdata | Cat(triggerAction, 0.U(12.W)) // fix action
326ba762693SYinan Xu  def WriteTdata1(wdata: UInt): UInt = {
327ba762693SYinan Xu    val tdata1 = WireInit(tdata1Phy(tselectPhy).asTypeOf(new TdataBundle))
328716f717fSLi Qianruo    val wdata_wire = WireInit(wdata.asTypeOf(new TdataBundle))
329716f717fSLi Qianruo    val tdata1_new = WireInit(wdata.asTypeOf(new TdataBundle))
330716f717fSLi Qianruo    XSDebug(src2(11, 0) === Tdata1.U && valid && func =/= CSROpType.jmp, p"Debug Mode: tdata1(${tselectPhy})is written, the actual value is ${wdata}\n")
33184e47f35SLi Qianruo//    tdata1_new.hit := wdata(20)
332ddb65c47SLi Qianruo    tdata1_new.ttype := tdata1.ttype
333d7dd1af1SLi Qianruo    tdata1_new.dmode := 0.U // Mux(debugMode, wdata_wire.dmode, tdata1.dmode)
334ddb65c47SLi Qianruo    tdata1_new.maskmax := 0.U
335ddb65c47SLi Qianruo    tdata1_new.hit := 0.U
336716f717fSLi Qianruo    tdata1_new.select := (TypeLookup(tselectPhy) === I_Trigger) && wdata_wire.select
337716f717fSLi Qianruo    when(wdata_wire.action <= 1.U){
338716f717fSLi Qianruo      triggerAction := tdata1_new.action(0)
339716f717fSLi Qianruo    } .otherwise{
340716f717fSLi Qianruo      tdata1_new.action := tdata1.action
341716f717fSLi Qianruo    }
342ddb65c47SLi Qianruo    tdata1_new.timing := false.B // hardwire this because we have singlestep
343716f717fSLi Qianruo    tdata1_new.zero1 := 0.U
344716f717fSLi Qianruo    tdata1_new.zero2 := 0.U
345716f717fSLi Qianruo    tdata1_new.chain := !tselectPhy(0) && wdata_wire.chain
346716f717fSLi Qianruo    when(wdata_wire.matchType =/= 0.U && wdata_wire.matchType =/= 2.U && wdata_wire.matchType =/= 3.U) {
347716f717fSLi Qianruo      tdata1_new.matchType := tdata1.matchType
348716f717fSLi Qianruo    }
349ddb65c47SLi Qianruo    tdata1_new.sizehi := Mux(wdata_wire.select && TypeLookup(tselectPhy) === I_Trigger, 0.U, 1.U)
350ddb65c47SLi Qianruo    tdata1_new.sizelo:= Mux(wdata_wire.select && TypeLookup(tselectPhy) === I_Trigger, 3.U, 1.U)
351716f717fSLi Qianruo    tdata1_new.execute := TypeLookup(tselectPhy) === I_Trigger
352716f717fSLi Qianruo    tdata1_new.store := TypeLookup(tselectPhy) === S_Trigger
353716f717fSLi Qianruo    tdata1_new.load := TypeLookup(tselectPhy) === L_Trigger
354ba762693SYinan Xu    tdata1_new.asUInt
35572951335SLi Qianruo  }
35672951335SLi Qianruo
35772951335SLi Qianruo  def WriteTselect(wdata: UInt) = {
358716f717fSLi Qianruo    Mux(wdata < 10.U, wdata(3, 0), tselectPhy)
35972951335SLi Qianruo  }
36072951335SLi Qianruo
36172951335SLi Qianruo  val tcontrolWriteMask = ZeroExt(GenMask(3) | GenMask(7), XLEN)
36272951335SLi Qianruo
36372951335SLi Qianruo
36472951335SLi Qianruo  def GenTdataDistribute(tdata1: TdataBundle, tdata2: UInt): MatchTriggerIO = {
36572951335SLi Qianruo    val res = Wire(new MatchTriggerIO)
36672951335SLi Qianruo    res.matchType := tdata1.matchType
36772951335SLi Qianruo    res.select := tdata1.select
36872951335SLi Qianruo    res.timing := tdata1.timing
36984e47f35SLi Qianruo    res.action := triggerAction
37072951335SLi Qianruo    res.chain := tdata1.chain
37172951335SLi Qianruo    res.tdata2 := tdata2
37272951335SLi Qianruo    res
37372951335SLi Qianruo  }
37472951335SLi Qianruo
37545f43e6eSTang Haojin  csrio.customCtrl.frontend_trigger.t.bits.addr := MuxLookup(tselectPhy, 0.U)(Seq(
37672951335SLi Qianruo    0.U -> 0.U,
37772951335SLi Qianruo    1.U -> 1.U,
37872951335SLi Qianruo    6.U -> 2.U,
37972951335SLi Qianruo    8.U -> 3.U
38072951335SLi Qianruo  ))
38145f43e6eSTang Haojin  csrio.customCtrl.mem_trigger.t.bits.addr := MuxLookup(tselectPhy, 0.U)(Seq(
38272951335SLi Qianruo    2.U -> 0.U,
38372951335SLi Qianruo    3.U -> 1.U,
38472951335SLi Qianruo    4.U -> 2.U,
38572951335SLi Qianruo    5.U -> 3.U,
38672951335SLi Qianruo    7.U -> 4.U,
38772951335SLi Qianruo    9.U -> 5.U
38872951335SLi Qianruo  ))
389716f717fSLi Qianruo  csrio.customCtrl.frontend_trigger.t.bits.tdata := GenTdataDistribute(tdata1Phy(tselectPhy).asTypeOf(new TdataBundle), tdata2Phy(tselectPhy))
390716f717fSLi Qianruo  csrio.customCtrl.mem_trigger.t.bits.tdata := GenTdataDistribute(tdata1Phy(tselectPhy).asTypeOf(new TdataBundle), tdata2Phy(tselectPhy))
39172951335SLi Qianruo
392c84054caSLinJiawei  // Machine-Level CSRs
393a4e57ea3SLi Qianruo  // mtvec: {BASE (WARL), MODE (WARL)} where mode is 0 or 1
394a4e57ea3SLi Qianruo  val mtvecMask = ~(0x2.U(XLEN.W))
395c84054caSLinJiawei  val mtvec = RegInit(UInt(XLEN.W), 0.U)
396c84054caSLinJiawei  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
397c84054caSLinJiawei  val mcause = RegInit(UInt(XLEN.W), 0.U)
398c84054caSLinJiawei  val mtval = RegInit(UInt(XLEN.W), 0.U)
399*d0de7e4aSpeixiaokun  val mtval2 = RegInit(UInt(XLEN.W), 0.U)
400*d0de7e4aSpeixiaokun  val mtinst = RegInit(UInt(XLEN.W), 0.U)
401*d0de7e4aSpeixiaokun  val mepc = RegInit(UInt(XLEN.W), 0.U)
402e30fd06aSYinan Xu  // Page 36 in riscv-priv: The low bit of mepc (mepc[0]) is always zero.
403e30fd06aSYinan Xu  val mepcMask = ~(0x1.U(XLEN.W))
404c84054caSLinJiawei
405c84054caSLinJiawei  val mie = RegInit(0.U(XLEN.W))
406c84054caSLinJiawei  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
4075dabf2dfSYinan Xu  val mipReg  = RegInit(0.U(XLEN.W))
408*d0de7e4aSpeixiaokun  val mipMask = ZeroExt(GenMask(9) | GenMask(5) | GenMask(1), XLEN)
409c84054caSLinJiawei  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
410c84054caSLinJiawei
411*d0de7e4aSpeixiaokun  val mip_mie_WMask_H = if(HasHExtension){((1 << 2) | (1 << 6) | (1 << 10) | (1 << 12)).U(XLEN.W)}else{0.U(XLEN.W)}
412*d0de7e4aSpeixiaokun  val vssip_Mask = (1 << 2).U(XLEN.W)
413*d0de7e4aSpeixiaokun
414*d0de7e4aSpeixiaokun  val mipWMask = vssip_Mask | ((1 << 9) | (1 << 5) | (1 << 1)).U(XLEN.W)
415*d0de7e4aSpeixiaokun  val mieWMask = mip_mie_WMask_H | ((1 << 11) | (1 << 9) | (1 << 7) | (1 << 5) | (1 << 3) | (1 << 1)).U(XLEN.W)
416*d0de7e4aSpeixiaokun
41767ba96b4SYinan Xu  def getMisaMxl(mxl: BigInt): BigInt = mxl << (XLEN - 2)
41867ba96b4SYinan Xu  def getMisaExt(ext: Char): Long = 1 << (ext.toInt - 'a'.toInt)
419c84054caSLinJiawei  var extList = List('a', 's', 'i', 'u')
420c84054caSLinJiawei  if (HasMExtension) { extList = extList :+ 'm' }
421c84054caSLinJiawei  if (HasCExtension) { extList = extList :+ 'c' }
422*d0de7e4aSpeixiaokun  if (HasHExtension) { extList = extList :+ 'h' }
423c84054caSLinJiawei  if (HasFPU) { extList = extList ++ List('f', 'd') }
424*d0de7e4aSpeixiaokun  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0L)((sum, i) => sum | getMisaExt(i)) //"h8000000000141185".U
42567ba96b4SYinan Xu  val misa = RegInit(UInt(XLEN.W), misaInitVal.U)
426bc5ff277Swangkaifan
427c84054caSLinJiawei  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
428c84054caSLinJiawei  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
429c84054caSLinJiawei
430c84054caSLinJiawei  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
431e1b773eaSLuo Jia  val marchid = RegInit(UInt(XLEN.W), 25.U) // architecture id for XiangShan is 25; see https://github.com/riscv/riscv-isa-manual/blob/master/marchid.md
432c84054caSLinJiawei  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
43367ba96b4SYinan Xu  val mhartid = Reg(UInt(XLEN.W)) // the hardware thread running the code
43467ba96b4SYinan Xu  when (RegNext(RegNext(reset.asBool) && !reset.asBool)) {
43567ba96b4SYinan Xu    mhartid := csrio.hartId
43667ba96b4SYinan Xu  }
4377d9edc86SLemover  val mconfigptr = RegInit(UInt(XLEN.W), 0.U) // the read-only pointer pointing to the platform config structure, 0 for not supported.
43880dd83d8SYinan Xu  val mstatus = RegInit("ha00002000".U(XLEN.W))
439bc5ff277Swangkaifan
440c84054caSLinJiawei  // mstatus Value Table
441c84054caSLinJiawei  // | sd   |
442c84054caSLinJiawei  // | pad1 |
443c84054caSLinJiawei  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
444e30fd06aSYinan Xu  // | uxl  | hardlinked to 10
445c84054caSLinJiawei  // | pad0 |
446c84054caSLinJiawei  // | tsr  |
447c84054caSLinJiawei  // | tw   |
4488e7b11e5SWilliam Wang  // | tvm  |
449c84054caSLinJiawei  // | mxr  |
450c84054caSLinJiawei  // | sum  |
451c84054caSLinJiawei  // | mprv |
452c84054caSLinJiawei  // | xs   | 00 |
45380dd83d8SYinan Xu  // | fs   | 01 |
454c84054caSLinJiawei  // | mpp  | 00 |
455c84054caSLinJiawei  // | hpp  | 00 |
456c84054caSLinJiawei  // | spp  | 0 |
4578e7b11e5SWilliam Wang  // | pie  | 0000 | pie.h is used as UBE
458c84054caSLinJiawei  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
459bc5ff277Swangkaifan
460c84054caSLinJiawei  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
461c84054caSLinJiawei  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
462c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
4638e7b11e5SWilliam Wang    val mstatusNew = Cat(mstatusOld.xs === "b11".U || mstatusOld.fs === "b11".U, mstatus(XLEN-2, 0))
464c84054caSLinJiawei    mstatusNew
465c84054caSLinJiawei  }
466c84054caSLinJiawei
467e30fd06aSYinan Xu  val mstatusWMask = (~ZeroExt((
468*d0de7e4aSpeixiaokun    (if(HasHExtension) {
469*d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 40) |
470*d0de7e4aSpeixiaokun      GenMask(37, 36)          // MBE SBE
471*d0de7e4aSpeixiaokun    } else
472*d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 36)) | // WPRI
473e30fd06aSYinan Xu    GenMask(35, 32)       | // SXL and UXL cannot be changed
474e30fd06aSYinan Xu    GenMask(31, 23)       | // WPRI
475705cbec3SLemover    GenMask(16, 15)       | // XS is read-only
476*d0de7e4aSpeixiaokun    GenMask(10, 9)        | // WPRI
477*d0de7e4aSpeixiaokun    GenMask(6)            | // WPRI
478*d0de7e4aSpeixiaokun    GenMask(2)              // WPRI
479*d0de7e4aSpeixiaokun  ), 64)).asUInt
480*d0de7e4aSpeixiaokun  val mstatusMask = (~ZeroExt((
481*d0de7e4aSpeixiaokun    (if (HasHExtension) {
482*d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 40) |
483*d0de7e4aSpeixiaokun        GenMask(37, 36) // MBE SBE
484*d0de7e4aSpeixiaokun    } else
485*d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 36)) | // WPRI
486*d0de7e4aSpeixiaokun    GenMask(31, 23)       | // WPRI
487*d0de7e4aSpeixiaokun    GenMask(10, 9)        | // WPRI
488*d0de7e4aSpeixiaokun    GenMask(6)            | // WPRI
489*d0de7e4aSpeixiaokun    GenMask(2)              // WPRI
4905d669833SYinan Xu  ), 64)).asUInt
4918e7b11e5SWilliam Wang
492c84054caSLinJiawei  val medeleg = RegInit(UInt(XLEN.W), 0.U)
493*d0de7e4aSpeixiaokun  val midelegInit = if(HasHExtension){((1 << 12) | (1 << 10) | (1 << 6) | (1 << 2)).U}else{0.U}
494*d0de7e4aSpeixiaokun  val medelegWMask = if(HasHExtension) {
495*d0de7e4aSpeixiaokun      ((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20) | (1 << 15) | (1 << 13) | (1 << 12) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 3) | (1 << 0)).U(XLEN.W)
496*d0de7e4aSpeixiaokun  }else {
497*d0de7e4aSpeixiaokun    "hb3ff".U(XLEN.W)
498*d0de7e4aSpeixiaokun  }
499*d0de7e4aSpeixiaokun
500*d0de7e4aSpeixiaokun
501*d0de7e4aSpeixiaokun  val mideleg = RegInit(UInt(XLEN.W), midelegInit)
502c84054caSLinJiawei  val mscratch = RegInit(UInt(XLEN.W), 0.U)
503c84054caSLinJiawei
5046ade72d9Sxuzefan  val menvcfg = RegInit(UInt(XLEN.W), 0.U)  // !WARNING: there is no logic about this CSR.
5056ade72d9Sxuzefan
506*d0de7e4aSpeixiaokun  val midelegWMask = "h222".U(XLEN.W)
507b6982e83SLemover  // PMP Mapping
508ca2f90a6SLemover  val pmp = Wire(Vec(NumPMP, new PMPEntry())) // just used for method parameter
509ca2f90a6SLemover  val pma = Wire(Vec(NumPMA, new PMPEntry())) // just used for method parameter
510ca2f90a6SLemover  val pmpMapping = pmp_gen_mapping(pmp_init, NumPMP, PmpcfgBase, PmpaddrBase, pmp)
511ca2f90a6SLemover  val pmaMapping = pmp_gen_mapping(pma_init, NumPMA, PmacfgBase, PmaaddrBase, pma)
512672c4648Sceba  // !WARNNING: pmp and pma CSRs are not checked in difftest.
513c84054caSLinJiawei
514*d0de7e4aSpeixiaokun  // Supervisor-Level CSRs
515c84054caSLinJiawei
516c84054caSLinJiawei  // val sstatus = RegInit(UInt(XLEN.W), "h00000000".U)
5175dabf2dfSYinan Xu  val sstatusWmask = "hc6122".U(XLEN.W)
518c84054caSLinJiawei  // Sstatus Write Mask
519c84054caSLinJiawei  // -------------------------------------------------------
520c84054caSLinJiawei  //    19           9   5     2
521c84054caSLinJiawei  // 0  1100 0000 0001 0010 0010
522c84054caSLinJiawei  // 0  c    0    1    2    2
523c84054caSLinJiawei  // -------------------------------------------------------
524c84054caSLinJiawei  val sstatusRmask = sstatusWmask | "h8000000300018000".U
525c84054caSLinJiawei  // Sstatus Read Mask = (SSTATUS_WMASK | (0xf << 13) | (1ull << 63) | (3ull << 32))
526a4e57ea3SLi Qianruo  // stvec: {BASE (WARL), MODE (WARL)} where mode is 0 or 1
527a4e57ea3SLi Qianruo  val stvecMask = ~(0x2.U(XLEN.W))
528c84054caSLinJiawei  val stvec = RegInit(UInt(XLEN.W), 0.U)
529c84054caSLinJiawei  // val sie = RegInit(0.U(XLEN.W))
530c84054caSLinJiawei  val sieMask = "h222".U & mideleg
531c84054caSLinJiawei  val sipMask = "h222".U & mideleg
5325dabf2dfSYinan Xu  val sipWMask = "h2".U(XLEN.W) // ssip is writeable in smode
53334230194Sjinyue110  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
534df2b1479SZhangZifei  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
53545f497a4Shappy-lx  // val satpMask = "h80000fffffffffff".U(XLEN.W) // disable asid, mode can only be 8 / 0
53645f497a4Shappy-lx  // TODO: use config to control the length of asid
53745f497a4Shappy-lx  // val satpMask = "h8fffffffffffffff".U(XLEN.W) // enable asid, mode can only be 8 / 0
538705cbec3SLemover  val satpMask = Cat("h8".U(Satp_Mode_len.W), satp_part_wmask(Satp_Asid_len, AsidLength), satp_part_wmask(Satp_Addr_len, PAddrBits-12))
539c84054caSLinJiawei  val sepc = RegInit(UInt(XLEN.W), 0.U)
540e30fd06aSYinan Xu  // Page 60 in riscv-priv: The low bit of sepc (sepc[0]) is always zero.
541e30fd06aSYinan Xu  val sepcMask = ~(0x1.U(XLEN.W))
542c84054caSLinJiawei  val scause = RegInit(UInt(XLEN.W), 0.U)
543*d0de7e4aSpeixiaokun  val stval = RegInit(UInt(XLEN.W), 0.U)
544c84054caSLinJiawei  val sscratch = RegInit(UInt(XLEN.W), 0.U)
545c84054caSLinJiawei  val scounteren = RegInit(UInt(XLEN.W), 0.U)
5466ade72d9Sxuzefan  val senvcfg = RegInit(UInt(XLEN.W), 0.U)  // !WARNING: there is no logic about this CSR.
547fcff7e94SZhangZifei
548eedc2e58SSteve Gou  // sbpctl
549eedc2e58SSteve Gou  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
550eedc2e58SSteve Gou  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
551eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
552eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
553eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
554eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
555eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
556eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
557eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
5582b8b2e7aSWilliam Wang
559ecccf78fSJay  // spfctl Bit 0: L1I Cache Prefetcher Enable
5602b8b2e7aSWilliam Wang  // spfctl Bit 1: L2Cache Prefetcher Enable
56185de5caeSLinJiawei  // spfctl Bit 2: L1D Cache Prefetcher Enable
56285de5caeSLinJiawei  // spfctl Bit 3: L1D train prefetch on hit
56385de5caeSLinJiawei  // spfctl Bit 4: L1D prefetch enable agt
56485de5caeSLinJiawei  // spfctl Bit 5: L1D prefetch enable pht
565c65495a4SLinJiawei  // spfctl Bit [9:6]: L1D prefetch active page threshold
566c65495a4SLinJiawei  // spfctl Bit [15:10]: L1D prefetch active page stride
5675d13017eSLinJiawei  // turn off L2 BOP, turn on L1 SMS by default
568c65495a4SLinJiawei  val spfctl = RegInit(UInt(XLEN.W), Seq(
569edbf1204SLinJiawei    0 << 17,    // L2 pf store only [17] init: false
570edbf1204SLinJiawei    1 << 16,    // L1D pf enable stride [16] init: true
571f1d78cf7SLinJiawei    30 << 10,   // L1D active page stride [15:10] init: 30
572f1d78cf7SLinJiawei    12 << 6,    // L1D active page threshold [9:6] init: 12
573f1d78cf7SLinJiawei    1  << 5,    // L1D enable pht [5] init: true
574f1d78cf7SLinJiawei    1  << 4,    // L1D enable agt [4] init: true
575f1d78cf7SLinJiawei    0  << 3,    // L1D train on hit [3] init: false
576f1d78cf7SLinJiawei    1  << 2,    // L1D pf enable [2] init: true
577f1d78cf7SLinJiawei    1  << 1,    // L2 pf enable [1] init: true
578f1d78cf7SLinJiawei    1  << 0,    // L1I pf enable [0] init: true
579c65495a4SLinJiawei  ).reduce(_|_).U(XLEN.W))
580ecccf78fSJay  csrio.customCtrl.l1I_pf_enable := spfctl(0)
58135a47a38SYinan Xu  csrio.customCtrl.l2_pf_enable := spfctl(1)
58285de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable := spfctl(2)
58385de5caeSLinJiawei  csrio.customCtrl.l1D_pf_train_on_hit := spfctl(3)
58485de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable_agt := spfctl(4)
58585de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable_pht := spfctl(5)
5865d13017eSLinJiawei  csrio.customCtrl.l1D_pf_active_threshold := spfctl(9, 6)
587c65495a4SLinJiawei  csrio.customCtrl.l1D_pf_active_stride := spfctl(15, 10)
588edbf1204SLinJiawei  csrio.customCtrl.l1D_pf_enable_stride := spfctl(16)
589edbf1204SLinJiawei  csrio.customCtrl.l2_pf_store_only := spfctl(17)
5902b8b2e7aSWilliam Wang
591ecccf78fSJay  // sfetchctl Bit 0: L1I Cache Parity check enable
592ecccf78fSJay  val sfetchctl = RegInit(UInt(XLEN.W), "b0".U)
593ecccf78fSJay  csrio.customCtrl.icache_parity_enable := sfetchctl(0)
594ecccf78fSJay
5952b8b2e7aSWilliam Wang  // sdsid: Differentiated Services ID
5962b8b2e7aSWilliam Wang  val sdsid = RegInit(UInt(XLEN.W), 0.U)
59735a47a38SYinan Xu  csrio.customCtrl.dsid := sdsid
59835a47a38SYinan Xu
5992b8b2e7aSWilliam Wang  // slvpredctl: load violation predict settings
6006ef4f6f6SYinan Xu  // Default reset period: 2^16
6016ef4f6f6SYinan Xu  // Why this number: reset more frequently while keeping the overhead low
6026ef4f6f6SYinan Xu  // Overhead: extra two redirections in every 64K cycles => ~0.1% overhead
6036ef4f6f6SYinan Xu  val slvpredctl = RegInit(UInt(XLEN.W), "h60".U)
6042b8b2e7aSWilliam Wang  csrio.customCtrl.lvpred_disable := slvpredctl(0)
6052b8b2e7aSWilliam Wang  csrio.customCtrl.no_spec_load := slvpredctl(1)
606c7160cd3SWilliam Wang  csrio.customCtrl.storeset_wait_store := slvpredctl(2)
607c7160cd3SWilliam Wang  csrio.customCtrl.storeset_no_fast_wakeup := slvpredctl(3)
608c7160cd3SWilliam Wang  csrio.customCtrl.lvpred_timeout := slvpredctl(8, 4)
6092b8b2e7aSWilliam Wang
610f3f22d72SYinan Xu  //  smblockctl: memory block configurations
61137225120Ssfencevma  //  +------------------------------+---+----+----+-----+--------+
61237225120Ssfencevma  //  |XLEN-1                       8| 7 | 6  | 5  |  4  |3      0|
61337225120Ssfencevma  //  +------------------------------+---+----+----+-----+--------+
61437225120Ssfencevma  //  |           Reserved           | O | CE | SP | LVC |   Th   |
61537225120Ssfencevma  //  +------------------------------+---+----+----+-----+--------+
61637225120Ssfencevma  //  Description:
61737225120Ssfencevma  //  Bit 3-0   : Store buffer flush threshold (Th).
61837225120Ssfencevma  //  Bit 4     : Enable load violation check after reset (LVC).
61937225120Ssfencevma  //  Bit 5     : Enable soft-prefetch after reset (SP).
62037225120Ssfencevma  //  Bit 6     : Enable cache error after reset (CE).
62137225120Ssfencevma  //  Bit 7     : Enable uncache write outstanding (O).
62237225120Ssfencevma  //  Others    : Reserved.
62337225120Ssfencevma
62467682d05SWilliam Wang  val smblockctl_init_val =
62567ba96b4SYinan Xu    (0xf & StoreBufferThreshold) |
62667ba96b4SYinan Xu    (EnableLdVioCheckAfterReset.toInt << 4) |
62767ba96b4SYinan Xu    (EnableSoftPrefetchAfterReset.toInt << 5) |
62867ba96b4SYinan Xu    (EnableCacheErrorAfterReset.toInt << 6)
62967ba96b4SYinan Xu    (EnableUncacheWriteOutstanding.toInt << 7)
63067ba96b4SYinan Xu  val smblockctl = RegInit(UInt(XLEN.W), smblockctl_init_val.U)
631f3f22d72SYinan Xu  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
63267682d05SWilliam Wang  // bits 4: enable load load violation check
633a4e57ea3SLi Qianruo  csrio.customCtrl.ldld_vio_check_enable := smblockctl(4)
634a4e57ea3SLi Qianruo  csrio.customCtrl.soft_prefetch_enable := smblockctl(5)
635a4e57ea3SLi Qianruo  csrio.customCtrl.cache_error_enable := smblockctl(6)
63637225120Ssfencevma  csrio.customCtrl.uncache_write_outstanding_enable := smblockctl(7)
637a4e57ea3SLi Qianruo
638a4e57ea3SLi Qianruo  println("CSR smblockctl init value:")
639a4e57ea3SLi Qianruo  println("  Store buffer replace threshold: " + StoreBufferThreshold)
640a4e57ea3SLi Qianruo  println("  Enable ld-ld vio check after reset: " + EnableLdVioCheckAfterReset)
641a4e57ea3SLi Qianruo  println("  Enable soft prefetch after reset: " + EnableSoftPrefetchAfterReset)
642a4e57ea3SLi Qianruo  println("  Enable cache error after reset: " + EnableCacheErrorAfterReset)
64337225120Ssfencevma  println("  Enable uncache write outstanding: " + EnableUncacheWriteOutstanding)
644f3f22d72SYinan Xu
6455b47c58cSYinan Xu  val srnctl = RegInit(UInt(XLEN.W), "h7".U)
6465b47c58cSYinan Xu  csrio.customCtrl.fusion_enable := srnctl(0)
647af2f7849Shappy-lx  csrio.customCtrl.svinval_enable := srnctl(1)
6485b47c58cSYinan Xu  csrio.customCtrl.wfi_enable := srnctl(2)
649aac4464eSYinan Xu
650*d0de7e4aSpeixiaokun  // Hypervisor CSRs
651*d0de7e4aSpeixiaokun  val hstatusWMask = "h7003c0".U(XLEN.W)
652*d0de7e4aSpeixiaokun  // hstatus: vtsr, vtw, vtvm, hu, spvp, spv, gva,
653*d0de7e4aSpeixiaokun  val hstatus = RegInit("h200000000".U(XLEN.W))
654*d0de7e4aSpeixiaokun  val hstatusStruct = hstatus.asTypeOf(new HstatusStruct)
655*d0de7e4aSpeixiaokun  val hedeleg = RegInit(UInt(XLEN.W), 0.U)
656*d0de7e4aSpeixiaokun  val hideleg = RegInit(UInt(XLEN.W), 0.U)
657*d0de7e4aSpeixiaokun  val hidelegRMask = mideleg
658*d0de7e4aSpeixiaokun  val hidelegWMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
659*d0de7e4aSpeixiaokun  val hgeie   = RegInit(UInt(XLEN.W), 0.U)
660*d0de7e4aSpeixiaokun  val htval = RegInit(UInt(XLEN.W), 0.U)
661*d0de7e4aSpeixiaokun  // hvip hip hie is part of mip or mie
662*d0de7e4aSpeixiaokun  val hvipMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
663*d0de7e4aSpeixiaokun  val hipRMask = (((1 << 12).U | hvipMask) & mideleg)
664*d0de7e4aSpeixiaokun  val hipWMask = ((1 << 2).U & mideleg)// vssip
665*d0de7e4aSpeixiaokun  val hieMask = hipRMask
666*d0de7e4aSpeixiaokun  val htinst = RegInit(UInt(XLEN.W), 0.U)
667*d0de7e4aSpeixiaokun  val hgeip = RegInit(UInt(XLEN.W), 0.U)
668*d0de7e4aSpeixiaokun  val henvcfg = RegInit(UInt(XLEN.W), 0.U)
669*d0de7e4aSpeixiaokun  val hgatp = RegInit(UInt(XLEN.W), 0.U)
670*d0de7e4aSpeixiaokun  val hgatpMask = Cat("h8".U(Hgatp_Mode_len.W), satp_part_wmask(Hgatp_Vmid_len, VmidLength), satp_part_wmask(Hgatp_Addr_len, PAddrBits-12))
671*d0de7e4aSpeixiaokun  val htimedelta = RegInit(UInt(XLEN.W), 0.U)
672*d0de7e4aSpeixiaokun  val hcounteren = RegInit(UInt(XLEN.W), 0.U)
673*d0de7e4aSpeixiaokun
674*d0de7e4aSpeixiaokun  val vsstatus = RegInit("ha00002000".U(XLEN.W))
675*d0de7e4aSpeixiaokun  val vsstatusStruct = vsstatus.asTypeOf(new MstatusStruct)
676*d0de7e4aSpeixiaokun  //vsie vsip
677*d0de7e4aSpeixiaokun  val vsMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
678*d0de7e4aSpeixiaokun  val vsip_ie_Mask = ZeroExt((hideleg & mideleg & vsMask), XLEN)
679*d0de7e4aSpeixiaokun  val vsip_WMask = ZeroExt((hideleg & mideleg & vssip_Mask), XLEN)
680*d0de7e4aSpeixiaokun  val vstvec = RegInit(UInt(XLEN.W), 0.U)
681*d0de7e4aSpeixiaokun  val vsscratch = RegInit(UInt(XLEN.W), 0.U)
682*d0de7e4aSpeixiaokun  val vsepc = RegInit(UInt(XLEN.W), 0.U)
683*d0de7e4aSpeixiaokun  val vscause = RegInit(UInt(XLEN.W), 0.U)
684*d0de7e4aSpeixiaokun  val vstval = RegInit(UInt(XLEN.W), 0.U)
685*d0de7e4aSpeixiaokun  val vsatp = RegInit(UInt(XLEN.W), 0.U)
6862b8b2e7aSWilliam Wang  val tlbBundle = Wire(new TlbCsrBundle)
68745f497a4Shappy-lx  tlbBundle.satp.apply(satp)
688*d0de7e4aSpeixiaokun  tlbBundle.vsatp.apply(vsatp)
689*d0de7e4aSpeixiaokun  tlbBundle.hgatp.apply(hgatp)
6902b8b2e7aSWilliam Wang  csrio.tlb := tlbBundle
6912b8b2e7aSWilliam Wang
692c84054caSLinJiawei  // User-Level CSRs
693c84054caSLinJiawei  val uepc = Reg(UInt(XLEN.W))
694c84054caSLinJiawei
695c84054caSLinJiawei  // fcsr
696c84054caSLinJiawei  class FcsrStruct extends Bundle {
697c84054caSLinJiawei    val reserved = UInt((XLEN-3-5).W)
698c84054caSLinJiawei    val frm = UInt(3.W)
699c84054caSLinJiawei    val fflags = UInt(5.W)
700c84054caSLinJiawei    assert(this.getWidth == XLEN)
701c84054caSLinJiawei  }
702c84054caSLinJiawei  val fcsr = RegInit(0.U(XLEN.W))
703c84054caSLinJiawei  // set mstatus->sd and mstatus->fs when true
704c84054caSLinJiawei  val csrw_dirty_fp_state = WireInit(false.B)
705c84054caSLinJiawei
706c84054caSLinJiawei  def frm_wfn(wdata: UInt): UInt = {
707c84054caSLinJiawei    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
708c84054caSLinJiawei    csrw_dirty_fp_state := true.B
709c84054caSLinJiawei    fcsrOld.frm := wdata(2,0)
7105d669833SYinan Xu    fcsrOld.asUInt
711c84054caSLinJiawei  }
712c84054caSLinJiawei  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
713c84054caSLinJiawei
7147132faa5SLinJiawei  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
7157132faa5SLinJiawei    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
7167132faa5SLinJiawei    val fcsrNew = WireInit(fcsrOld)
717c84054caSLinJiawei    csrw_dirty_fp_state := true.B
7187132faa5SLinJiawei    if (update) {
7197132faa5SLinJiawei      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
7207132faa5SLinJiawei    } else {
7217132faa5SLinJiawei      fcsrNew.fflags := wdata(4,0)
7227132faa5SLinJiawei    }
7235d669833SYinan Xu    fcsrNew.asUInt
724c84054caSLinJiawei  }
725c84054caSLinJiawei  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
726c84054caSLinJiawei
727c84054caSLinJiawei  def fcsr_wfn(wdata: UInt): UInt = {
728c84054caSLinJiawei    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
729c84054caSLinJiawei    csrw_dirty_fp_state := true.B
730c84054caSLinJiawei    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
731c84054caSLinJiawei  }
732c84054caSLinJiawei
733c84054caSLinJiawei  val fcsrMapping = Map(
7347132faa5SLinJiawei    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
735c84054caSLinJiawei    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
736c84054caSLinJiawei    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
737c84054caSLinJiawei  )
738c84054caSLinJiawei
739321934c7SKunlin You  // Hart Privilege Mode
740321934c7SKunlin You  val privilegeMode = RegInit(UInt(2.W), ModeM)
741c84054caSLinJiawei
742cd365d4cSrvcoresjw  //val perfEventscounten = List.fill(nrPerfCnts)(RegInit(false(Bool())))
7438635f18fSwangkaifan  // Perf Counter
7448635f18fSwangkaifan  val nrPerfCnts = 29  // 3...31
745321934c7SKunlin You  val privilegeModeOH = UIntToOH(privilegeMode)
746cd365d4cSrvcoresjw  val perfEventscounten = RegInit(0.U.asTypeOf(Vec(nrPerfCnts, Bool())))
7478635f18fSwangkaifan  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
7488c7b0b2fSrvcoresjw  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
74912c44ce5Srvcoresjw                   List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
75012c44ce5Srvcoresjw                   List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
75112c44ce5Srvcoresjw                   List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
752cd365d4cSrvcoresjw  for (i <-0 until nrPerfCnts) {
753321934c7SKunlin You    perfEventscounten(i) := (perfEvents(i)(63,60) & privilegeModeOH).orR
754cd365d4cSrvcoresjw  }
755cd365d4cSrvcoresjw
7561ca0e4f3SYinan Xu  val hpmEvents = Wire(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
757cd365d4cSrvcoresjw  for (i <- 0 until numPCntHc * coreParams.L2NBanks) {
7581ca0e4f3SYinan Xu    hpmEvents(i) := csrio.perf.perfEventsHc(i)
759cd365d4cSrvcoresjw  }
760cd365d4cSrvcoresjw
7619a128342SHaoyuan Feng  // print perfEvents
7629a128342SHaoyuan Feng  val allPerfEvents = hpmEvents.map(x => (s"Hc", x.value))
7639a128342SHaoyuan Feng  if (printEventCoding) {
7649a128342SHaoyuan Feng    for (((name, inc), i) <- allPerfEvents.zipWithIndex) {
7659a128342SHaoyuan Feng      println("CSR perfEvents Set", name, inc, i)
7669a128342SHaoyuan Feng    }
7679a128342SHaoyuan Feng  }
7689a128342SHaoyuan Feng
76912c44ce5Srvcoresjw  val csrevents = perfEvents.slice(24, 29)
7701ca0e4f3SYinan Xu  val hpm_hc = HPerfMonitor(csrevents, hpmEvents)
7718635f18fSwangkaifan  val mcountinhibit = RegInit(0.U(XLEN.W))
772b03ddc86Swangkaifan  val mcycle = RegInit(0.U(XLEN.W))
773b03ddc86Swangkaifan  mcycle := mcycle + 1.U
774b03ddc86Swangkaifan  val minstret = RegInit(0.U(XLEN.W))
7751ca0e4f3SYinan Xu  val perf_events = csrio.perf.perfEventsFrontend ++
7761ca0e4f3SYinan Xu                    csrio.perf.perfEventsCtrl ++
7771ca0e4f3SYinan Xu                    csrio.perf.perfEventsLsu ++
7781ca0e4f3SYinan Xu                    hpm_hc.getPerf
779b03ddc86Swangkaifan  minstret := minstret + RegNext(csrio.perf.retiredInstr)
7805fd90906Srvcoresjw  for(i <- 0 until 29){
7811ca0e4f3SYinan Xu    perfCnts(i) := Mux(mcountinhibit(i+3) | !perfEventscounten(i), perfCnts(i), perfCnts(i) + perf_events(i).value)
7825fd90906Srvcoresjw  }
7838635f18fSwangkaifan
784c84054caSLinJiawei  // CSR reg map
78521fa8708Swangkaifan  val basicPrivMapping = Map(
786c84054caSLinJiawei
78721fa8708Swangkaifan    //--- User Trap Setup ---
788c84054caSLinJiawei    // MaskedRegMap(Ustatus, ustatus),
789c84054caSLinJiawei    // MaskedRegMap(Uie, uie, 0.U, MaskedRegMap.Unwritable),
790c84054caSLinJiawei    // MaskedRegMap(Utvec, utvec),
791c84054caSLinJiawei
79221fa8708Swangkaifan    //--- User Trap Handling ---
793c84054caSLinJiawei    // MaskedRegMap(Uscratch, uscratch),
794c84054caSLinJiawei    // MaskedRegMap(Uepc, uepc),
795c84054caSLinJiawei    // MaskedRegMap(Ucause, ucause),
796c84054caSLinJiawei    // MaskedRegMap(Utval, utval),
797c84054caSLinJiawei    // MaskedRegMap(Uip, uip),
798c84054caSLinJiawei
79921fa8708Swangkaifan    //--- User Counter/Timers ---
800c84054caSLinJiawei    // MaskedRegMap(Cycle, cycle),
801c84054caSLinJiawei    // MaskedRegMap(Time, time),
802c84054caSLinJiawei    // MaskedRegMap(Instret, instret),
803c84054caSLinJiawei
80421fa8708Swangkaifan    //--- Supervisor Trap Setup ---
805c84054caSLinJiawei    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
806c84054caSLinJiawei    // MaskedRegMap(Sedeleg, Sedeleg),
807c84054caSLinJiawei    // MaskedRegMap(Sideleg, Sideleg),
808c84054caSLinJiawei    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
809a4e57ea3SLi Qianruo    MaskedRegMap(Stvec, stvec, stvecMask, MaskedRegMap.NoSideEffect, stvecMask),
810c84054caSLinJiawei    MaskedRegMap(Scounteren, scounteren),
811c84054caSLinJiawei
8126ade72d9Sxuzefan    //--- Supervisor Configuration ---
8136ade72d9Sxuzefan    MaskedRegMap(Senvcfg, senvcfg),
8146ade72d9Sxuzefan
81521fa8708Swangkaifan    //--- Supervisor Trap Handling ---
816c84054caSLinJiawei    MaskedRegMap(Sscratch, sscratch),
817e30fd06aSYinan Xu    MaskedRegMap(Sepc, sepc, sepcMask, MaskedRegMap.NoSideEffect, sepcMask),
818c84054caSLinJiawei    MaskedRegMap(Scause, scause),
819c84054caSLinJiawei    MaskedRegMap(Stval, stval),
820*d0de7e4aSpeixiaokun    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask),
821c84054caSLinJiawei
82221fa8708Swangkaifan    //--- Supervisor Protection and Translation ---
823c5334b11SZhangZifei    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
824c84054caSLinJiawei
82535a47a38SYinan Xu    //--- Supervisor Custom Read/Write Registers
826eedc2e58SSteve Gou    MaskedRegMap(Sbpctl, sbpctl),
82735a47a38SYinan Xu    MaskedRegMap(Spfctl, spfctl),
828ecccf78fSJay    MaskedRegMap(Sfetchctl, sfetchctl),
82935a47a38SYinan Xu    MaskedRegMap(Sdsid, sdsid),
8302b8b2e7aSWilliam Wang    MaskedRegMap(Slvpredctl, slvpredctl),
831f3f22d72SYinan Xu    MaskedRegMap(Smblockctl, smblockctl),
832aac4464eSYinan Xu    MaskedRegMap(Srnctl, srnctl),
83335a47a38SYinan Xu
83421fa8708Swangkaifan    //--- Machine Information Registers ---
8355dabf2dfSYinan Xu    MaskedRegMap(Mvendorid, mvendorid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8365dabf2dfSYinan Xu    MaskedRegMap(Marchid, marchid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8375dabf2dfSYinan Xu    MaskedRegMap(Mimpid, mimpid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8385dabf2dfSYinan Xu    MaskedRegMap(Mhartid, mhartid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8397d9edc86SLemover    MaskedRegMap(Mconfigptr, mconfigptr, 0.U(XLEN.W), MaskedRegMap.Unwritable),
840c84054caSLinJiawei
84121fa8708Swangkaifan    //--- Machine Trap Setup ---
842443741b9SYinan Xu    MaskedRegMap(Mstatus, mstatus, mstatusWMask, mstatusUpdateSideEffect),
8435e4ec482SWilliam Wang    MaskedRegMap(Misa, misa, 0.U, MaskedRegMap.Unwritable), // now whole misa is unchangeable
844*d0de7e4aSpeixiaokun    MaskedRegMap(Medeleg, medeleg, medelegWMask),
845*d0de7e4aSpeixiaokun    MaskedRegMap(Mideleg, mideleg, midelegWMask, MaskedRegMap.NoSideEffect),
846*d0de7e4aSpeixiaokun    MaskedRegMap(Mie, mie, mieWMask, MaskedRegMap.NoSideEffect),
847a4e57ea3SLi Qianruo    MaskedRegMap(Mtvec, mtvec, mtvecMask, MaskedRegMap.NoSideEffect, mtvecMask),
848c84054caSLinJiawei    MaskedRegMap(Mcounteren, mcounteren),
849c84054caSLinJiawei
85021fa8708Swangkaifan    //--- Machine Trap Handling ---
851c84054caSLinJiawei    MaskedRegMap(Mscratch, mscratch),
852e30fd06aSYinan Xu    MaskedRegMap(Mepc, mepc, mepcMask, MaskedRegMap.NoSideEffect, mepcMask),
853c84054caSLinJiawei    MaskedRegMap(Mcause, mcause),
854c84054caSLinJiawei    MaskedRegMap(Mtval, mtval),
855*d0de7e4aSpeixiaokun    MaskedRegMap(Mip, mipReg.asUInt, mipWMask, MaskedRegMap.NoSideEffect, mipMask),
856d4aca96cSlqre
8576ade72d9Sxuzefan    //--- Machine Configuration ---
8586ade72d9Sxuzefan    MaskedRegMap(Menvcfg, menvcfg),
85972951335SLi Qianruo    //--- Trigger ---
860716f717fSLi Qianruo    MaskedRegMap(Tselect, tselectPhy, WritableMask, WriteTselect),
861ba762693SYinan Xu    MaskedRegMap(Tdata1, tdata1Phy(tselectPhy), WritableMask, WriteTdata1, WritableMask, ReadTdata1),
862ba762693SYinan Xu    MaskedRegMap(Tdata2, tdata2Phy(tselectPhy)),
863716f717fSLi Qianruo    MaskedRegMap(Tinfo, tinfo, 0.U(XLEN.W), MaskedRegMap.Unwritable),
86472951335SLi Qianruo    MaskedRegMap(Tcontrol, tControlPhy, tcontrolWriteMask),
86572951335SLi Qianruo
866d4aca96cSlqre    //--- Debug Mode ---
867d4aca96cSlqre    MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
868d4aca96cSlqre    MaskedRegMap(Dpc, dpc),
8695b0f0029SXuan Hu    MaskedRegMap(Dscratch0, dscratch0),
87012c44ce5Srvcoresjw    MaskedRegMap(Dscratch1, dscratch1),
871b03ddc86Swangkaifan    MaskedRegMap(Mcountinhibit, mcountinhibit),
872b03ddc86Swangkaifan    MaskedRegMap(Mcycle, mcycle),
873b03ddc86Swangkaifan    MaskedRegMap(Minstret, minstret),
874b03ddc86Swangkaifan  )
87512c44ce5Srvcoresjw
876*d0de7e4aSpeixiaokun  // hypervisor csr map
877*d0de7e4aSpeixiaokun  val hcsrMapping = Map(
878*d0de7e4aSpeixiaokun    //--- Hypervisor Trap Setup ---
879*d0de7e4aSpeixiaokun    MaskedRegMap(Hstatus, hstatus, hstatusWMask),
880*d0de7e4aSpeixiaokun    MaskedRegMap(Hedeleg, hedeleg),
881*d0de7e4aSpeixiaokun    MaskedRegMap(Hideleg, hideleg, hidelegWMask, MaskedRegMap.NoSideEffect, hidelegRMask),
882*d0de7e4aSpeixiaokun    MaskedRegMap(Hie, mie, hieMask, MaskedRegMap.NoSideEffect, hieMask),
883*d0de7e4aSpeixiaokun    MaskedRegMap(Hcounteren, hcounteren),
884*d0de7e4aSpeixiaokun    MaskedRegMap(Hgeie, hgeie),
885*d0de7e4aSpeixiaokun
886*d0de7e4aSpeixiaokun    //--- Hypervisor Trap Handling ---
887*d0de7e4aSpeixiaokun    MaskedRegMap(Htval, htval),
888*d0de7e4aSpeixiaokun    MaskedRegMap(Hip, mipReg.asUInt, hipWMask, MaskedRegMap.NoSideEffect, hipRMask),
889*d0de7e4aSpeixiaokun    MaskedRegMap(Hvip, mipReg.asUInt, hvipMask, MaskedRegMap.NoSideEffect, hvipMask),
890*d0de7e4aSpeixiaokun    MaskedRegMap(Htinst, htinst),
891*d0de7e4aSpeixiaokun    MaskedRegMap(Hgeip, hgeip),
892*d0de7e4aSpeixiaokun
893*d0de7e4aSpeixiaokun    //--- Hypervisor Configuration ---
894*d0de7e4aSpeixiaokun    MaskedRegMap(Henvcfg, henvcfg),
895*d0de7e4aSpeixiaokun
896*d0de7e4aSpeixiaokun    //--- Hypervisor Protection and Translation ---
897*d0de7e4aSpeixiaokun    MaskedRegMap(Hgatp, hgatp),
898*d0de7e4aSpeixiaokun
899*d0de7e4aSpeixiaokun    //--- Hypervisor Counter/Timer Virtualization Registers ---
900*d0de7e4aSpeixiaokun    MaskedRegMap(Htimedelta, htimedelta),
901*d0de7e4aSpeixiaokun
902*d0de7e4aSpeixiaokun    //--- Virtual Supervisor Registers ---
903*d0de7e4aSpeixiaokun    MaskedRegMap(Vsstatus, vsstatus, rmask = sstatusRmask, wmask = sstatusWmask),
904*d0de7e4aSpeixiaokun    MaskedRegMap(Vsie, mie, rmask = vsip_ie_Mask, wmask = vsip_ie_Mask),
905*d0de7e4aSpeixiaokun    MaskedRegMap(Vstvec, vstvec),
906*d0de7e4aSpeixiaokun    MaskedRegMap(Vsscratch, vsscratch),
907*d0de7e4aSpeixiaokun    MaskedRegMap(Vsepc, vsepc),
908*d0de7e4aSpeixiaokun    MaskedRegMap(Vscause, vscause),
909*d0de7e4aSpeixiaokun    MaskedRegMap(Vstval, vstval),
910*d0de7e4aSpeixiaokun    MaskedRegMap(Vsip, mipReg.asUInt, vsip_WMask, MaskedRegMap.NoSideEffect, vsip_ie_Mask),
911*d0de7e4aSpeixiaokun    MaskedRegMap(Vsatp, vsatp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
912*d0de7e4aSpeixiaokun
913*d0de7e4aSpeixiaokun    //--- Machine Registers ---
914*d0de7e4aSpeixiaokun    MaskedRegMap(Mtval2, mtval2),
915*d0de7e4aSpeixiaokun    MaskedRegMap(Mtinst, mtinst),
916*d0de7e4aSpeixiaokun  )
917*d0de7e4aSpeixiaokun
91812c44ce5Srvcoresjw  val perfCntMapping = (0 until 29).map(i => {Map(
91912c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmevent3 +i,
92012c44ce5Srvcoresjw                 reg  = perfEvents(i),
92112c44ce5Srvcoresjw                 wmask = "hf87fff3fcff3fcff".U(XLEN.W)),
92212c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmcounter3 +i,
92312c44ce5Srvcoresjw                 reg  = perfCnts(i))
92412c44ce5Srvcoresjw  )}).fold(Map())((a,b) => a ++ b)
9256d96ebcdSwakafa  // TODO: mechanism should be implemented later
9266d96ebcdSwakafa  // val MhpmcounterStart = Mhpmcounter3
9276d96ebcdSwakafa  // val MhpmeventStart   = Mhpmevent3
9286d96ebcdSwakafa  // for (i <- 0 until nrPerfCnts) {
9296d96ebcdSwakafa  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
9306d96ebcdSwakafa  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
9316d96ebcdSwakafa  // }
9328635f18fSwangkaifan
933e19f7967SWilliam Wang  val cacheopRegs = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
934e19f7967SWilliam Wang    name -> RegInit(0.U(attribute("width").toInt.W))
935e19f7967SWilliam Wang  }}
936ad3ba452Szhanglinjuan  val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
937ad3ba452Szhanglinjuan    MaskedRegMap(
938ad3ba452Szhanglinjuan      Scachebase + attribute("offset").toInt,
939e19f7967SWilliam Wang      cacheopRegs(name)
940ad3ba452Szhanglinjuan    )
941ad3ba452Szhanglinjuan  }}
942b6982e83SLemover
94321fa8708Swangkaifan  val mapping = basicPrivMapping ++
9448635f18fSwangkaifan                perfCntMapping ++
94521fa8708Swangkaifan                pmpMapping ++
946ca2f90a6SLemover                pmaMapping ++
947ad3ba452Szhanglinjuan                (if (HasFPU) fcsrMapping else Nil) ++
948*d0de7e4aSpeixiaokun                 (if (HasCustomCSRCacheOp) cacheopMapping else Nil) ++
949*d0de7e4aSpeixiaokun                (if (HasHExtension) hcsrMapping else Nil)
950c84054caSLinJiawei
951*d0de7e4aSpeixiaokun
952*d0de7e4aSpeixiaokun  val vs_s_csr_map = Map(
953*d0de7e4aSpeixiaokun    Sstatus.U  -> Vsstatus.U,
954*d0de7e4aSpeixiaokun    Sie.U      -> Vsie.U,
955*d0de7e4aSpeixiaokun    Stvec.U    -> Vstvec.U,
956*d0de7e4aSpeixiaokun    Sscratch.U -> Vsscratch.U,
957*d0de7e4aSpeixiaokun    Sepc.U     -> Vsepc.U,
958*d0de7e4aSpeixiaokun    Scause.U   -> Vscause.U,
959*d0de7e4aSpeixiaokun    Stval.U    -> Vstval.U,
960*d0de7e4aSpeixiaokun    Sip.U      -> Vsip.U,
961*d0de7e4aSpeixiaokun    Satp.U     -> Vsatp.U
962*d0de7e4aSpeixiaokun  )
963*d0de7e4aSpeixiaokun  val addr = Wire(UInt(12.W))
964*d0de7e4aSpeixiaokun  val vscsr_addr = LookupTreeDefault(src2(11, 0), src2(11, 0), vs_s_csr_map)
965*d0de7e4aSpeixiaokun  when(virtMode){
966*d0de7e4aSpeixiaokun    addr := vscsr_addr
967*d0de7e4aSpeixiaokun  }.otherwise{
968*d0de7e4aSpeixiaokun    addr := src2(11, 0)
969*d0de7e4aSpeixiaokun  }
970b1860798SZhangfw  val csri = ZeroExt(src2(16, 12), XLEN)
971*d0de7e4aSpeixiaokun  val rdata_tmp = Wire(UInt(XLEN.W))
972*d0de7e4aSpeixiaokun  val wdata_tmp = LookupTree(func, List(
973c84054caSLinJiawei    CSROpType.wrt  -> src1,
974c84054caSLinJiawei    CSROpType.set  -> (rdata | src1),
9755d669833SYinan Xu    CSROpType.clr  -> (rdata & (~src1).asUInt),
976b0ae3ac4SLinJiawei    CSROpType.wrti -> csri,
977c84054caSLinJiawei    CSROpType.seti -> (rdata | csri),
9785d669833SYinan Xu    CSROpType.clri -> (rdata & (~csri).asUInt)
979c84054caSLinJiawei  ))
980*d0de7e4aSpeixiaokun  val is_vsip_ie = addr === Vsip.U || addr === Vsie.U
981*d0de7e4aSpeixiaokun  val wdata = Mux(is_vsip_ie, ZeroExt(wdata_tmp << 1, XLEN), wdata_tmp)
982c84054caSLinJiawei
983e377d77eSWilliam Wang  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) ||
9844d5d2702Swakafa    (addr >= Mcountinhibit.U) && (addr <= Mhpmevent31.U) ||
9854d5d2702Swakafa    addr === Mip.U
986e377d77eSWilliam Wang  csrio.isPerfCnt := addrInPerfCnt && valid && func =/= CSROpType.jmp
9878635f18fSwangkaifan
98847a386bfSZhangZifei  // satp wen check
98947a386bfSZhangZifei  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
9902f5f05fdSWilliam Wang
991e5adbe81SLemover  // csr access check, special case
992*d0de7e4aSpeixiaokun  val tvmNotPermit = (privilegeMode === ModeS && !virtMode && mstatusStruct.tvm.asBool)
993e5adbe81SLemover  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
994*d0de7e4aSpeixiaokun  val vtvmNotPermit = (privilegeMode === ModeS && virtMode && hstatusStruct.vtvm.asBool)
995*d0de7e4aSpeixiaokun  val vaccessPermitted = !(addr === Vsatp.U && vtvmNotPermit)
996*d0de7e4aSpeixiaokun  csrio.disableSfence := (tvmNotPermit || !virtMode && privilegeMode < ModeS) || (vtvmNotPermit || virtMode && privilegeMode < ModeS)
997*d0de7e4aSpeixiaokun  csrio.disableHfenceg := !((!virtMode && privilegeMode === ModeS && !mstatusStruct.tvm.asBool) || (privilegeMode === ModeM)) // only valid in HS and mstatus.tvm == 0 or in M
998*d0de7e4aSpeixiaokun  csrio.disableHfencev :=  !(privilegeMode === ModeM || (!virtMode && privilegeMode === ModeS))
999e5adbe81SLemover
10002f5f05fdSWilliam Wang  // general CSR wen check
1001*d0de7e4aSpeixiaokun  val wen = valid && CSROpType.needAccess(func) && ((addr=/=Satp.U && addr =/= Vsatp.U) || satpLegalMode)
100272951335SLi Qianruo  val dcsrPermitted = dcsrPermissionCheck(addr, false.B, debugMode)
100372951335SLi Qianruo  val triggerPermitted = triggerPermissionCheck(addr, true.B, debugMode) // todo dmode
1004*d0de7e4aSpeixiaokun  val HasH = (HasHExtension == true).asBool()
1005*d0de7e4aSpeixiaokun  val csrAccess = csrAccessPermissionCheck(addr, false.B, privilegeMode, virtMode, HasH)
1006*d0de7e4aSpeixiaokun  val modePermitted = csrAccess === 0.U && dcsrPermitted && triggerPermitted
1007321934c7SKunlin You  val perfcntPermitted = perfcntPermissionCheck(addr, privilegeMode, mcounteren, scounteren)
1008*d0de7e4aSpeixiaokun  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && Mux(virtMode, vaccessPermitted, accessPermitted)
1009*d0de7e4aSpeixiaokun  MaskedRegMap.generate(mapping, addr, rdata_tmp, wen && permitted, wdata)
1010*d0de7e4aSpeixiaokun  rdata := Mux(is_vsip_ie, ZeroExt(rdata_tmp >> 1, XLEN), rdata_tmp)
1011ead41f51SLinJiawei  io.out.bits.data := rdata
1012ead41f51SLinJiawei  io.out.bits.uop := io.in.bits.uop
1013e18c367fSLinJiawei  io.out.bits.uop.cf := cfOut
1014e18c367fSLinJiawei  io.out.bits.uop.ctrl.flushPipe := flushPipe
1015c84054caSLinJiawei
1016b6982e83SLemover  // send distribute csr a w signal
1017b6982e83SLemover  csrio.customCtrl.distribute_csr.w.valid := wen && permitted
1018b6982e83SLemover  csrio.customCtrl.distribute_csr.w.bits.data := wdata
1019b6982e83SLemover  csrio.customCtrl.distribute_csr.w.bits.addr := addr
1020b6982e83SLemover
1021a4e57ea3SLi Qianruo  when (RegNext(csrio.fpu.fflags.valid)) {
1022a4e57ea3SLi Qianruo    fcsr := fflags_wfn(update = true)(RegNext(csrio.fpu.fflags.bits))
1023c84054caSLinJiawei  }
1024c84054caSLinJiawei  // set fs and sd in mstatus
1025a4e57ea3SLi Qianruo  when (csrw_dirty_fp_state || RegNext(csrio.fpu.dirty_fs)) {
1026c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1027c84054caSLinJiawei    mstatusNew.fs := "b11".U
1028c84054caSLinJiawei    mstatusNew.sd := true.B
10295d669833SYinan Xu    mstatus := mstatusNew.asUInt
1030c84054caSLinJiawei  }
1031129a273eSYinan Xu  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
1032c84054caSLinJiawei
103372951335SLi Qianruo
103472951335SLi Qianruo  // Trigger Ctrl
1035716f717fSLi Qianruo  csrio.customCtrl.trigger_enable := tdata1Phy.map{t =>
1036716f717fSLi Qianruo    def tdata1 = t.asTypeOf(new TdataBundle)
1037321934c7SKunlin You    tdata1.m && privilegeMode === ModeM ||
1038321934c7SKunlin You    tdata1.s && privilegeMode === ModeS || tdata1.u && privilegeMode === ModeU
103972951335SLi Qianruo  }
1040ddb65c47SLi Qianruo  csrio.customCtrl.frontend_trigger.t.valid := RegNext(wen && (addr === Tdata1.U || addr === Tdata2.U) && TypeLookup(tselectPhy) === I_Trigger)
1041ddb65c47SLi Qianruo  csrio.customCtrl.mem_trigger.t.valid := RegNext(wen && (addr === Tdata1.U || addr === Tdata2.U) && TypeLookup(tselectPhy) =/= I_Trigger)
10425d669833SYinan Xu  XSDebug(csrio.customCtrl.trigger_enable.asUInt.orR, p"Debug Mode: At least 1 trigger is enabled," +
10435d669833SYinan Xu    p"trigger enable is ${Binary(csrio.customCtrl.trigger_enable.asUInt)}\n")
104472951335SLi Qianruo
1045c84054caSLinJiawei  // CSR inst decode
10468e7b11e5SWilliam Wang  val isEbreak = addr === privEbreak && func === CSROpType.jmp
1047c84054caSLinJiawei  val isEcall  = addr === privEcall  && func === CSROpType.jmp
1048c84054caSLinJiawei  val isMret   = addr === privMret   && func === CSROpType.jmp
1049c84054caSLinJiawei  val isSret   = addr === privSret   && func === CSROpType.jmp
1050c84054caSLinJiawei  val isUret   = addr === privUret   && func === CSROpType.jmp
1051d4aca96cSlqre  val isDret   = addr === privDret   && func === CSROpType.jmp
10525d669833SYinan Xu  val isWFI    = func === CSROpType.wfi
1053c84054caSLinJiawei
1054e18c367fSLinJiawei  XSDebug(wen, "csr write: pc %x addr %x rdata %x wdata %x func %x\n", cfIn.pc, addr, rdata, wdata, func)
1055321934c7SKunlin You  XSDebug(wen, "pc %x mstatus %x mideleg %x medeleg %x mode %x\n", cfIn.pc, mstatus, mideleg , medeleg, privilegeMode)
1056bf9968b2SYinan Xu
1057321934c7SKunlin You  // Illegal privileged operation list
1058321934c7SKunlin You  val illegalMret = valid && isMret && privilegeMode < ModeM
1059321934c7SKunlin You  val illegalSret = valid && isSret && privilegeMode < ModeS
1060*d0de7e4aSpeixiaokun  val illegalSModeSret = valid && isSret && privilegeMode === ModeS && virtMode === false.B && mstatusStruct.tsr.asBool
1061*d0de7e4aSpeixiaokun  // when hstatus.vtsr == 1, if sret is executed in VS-mode, it will cause virtual instruction
1062*d0de7e4aSpeixiaokun  val illegalVSModeSret = valid && isSret && privilegeMode === ModeS && virtMode && hstatusStruct.vtsr.asBool
10635d669833SYinan Xu  // When TW=1, then if WFI is executed in any less-privileged mode,
10645d669833SYinan Xu  // and it does not complete within an implementation-specific, bounded time limit,
10655d669833SYinan Xu  // the WFI instruction causes an illegal instruction exception.
10665d669833SYinan Xu  // The time limit may always be 0, in which case WFI always causes
10675d669833SYinan Xu  // an illegal instruction exception in less-privileged modes when TW=1.
1068*d0de7e4aSpeixiaokun  val illegalWFI = valid && isWFI && (privilegeMode < ModeM && mstatusStruct.tw === 1.U ||  privilegeMode === ModeU && !virtMode)
1069*d0de7e4aSpeixiaokun  val illegalVWFI = valid && isWFI && ((virtMode && privilegeMode === ModeS && hstatusStruct.vtw === 1.U && mstatusStruct.tw === 0.U)||
1070*d0de7e4aSpeixiaokun      (virtMode && privilegeMode === ModeU && mstatusStruct.tw === 0.U))
1071321934c7SKunlin You  // Illegal privileged instruction check
10725d669833SYinan Xu  val isIllegalAddr = valid && CSROpType.needAccess(func) && MaskedRegMap.isIllegalAddr(mapping, addr)
1073*d0de7e4aSpeixiaokun  val isIllegalAccess = !virtMode && wen && !(Mux(addrInPerfCnt, perfcntPermitted, csrAccess === 0.U && dcsrPermitted && triggerPermitted) && accessPermitted)
10745d669833SYinan Xu  val isIllegalPrivOp = illegalMret || illegalSret || illegalSModeSret || illegalWFI
1075c84054caSLinJiawei
1076*d0de7e4aSpeixiaokun  val isIllegalVAccess = virtMode && wen && (csrAccess === 2.U || !vaccessPermitted)
1077*d0de7e4aSpeixiaokun  val isIllegalVPrivOp = illegalVSModeSret || illegalVWFI
1078ad3ba452Szhanglinjuan  // expose several csr bits for tlb
1079fcff7e94SZhangZifei  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
1080fcff7e94SZhangZifei  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
1081*d0de7e4aSpeixiaokun  tlbBundle.priv.vmxr := vsstatusStruct.mxr.asBool
1082*d0de7e4aSpeixiaokun  tlbBundle.priv.vsum := vsstatusStruct.sum.asBool
1083*d0de7e4aSpeixiaokun  tlbBundle.priv.spvp := hstatusStruct.spvp
1084*d0de7e4aSpeixiaokun  tlbBundle.priv.virt  := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpv & (mstatusStruct.mpp =/= ModeM), virtMode)
1085321934c7SKunlin You  tlbBundle.priv.imode := privilegeMode
1086321934c7SKunlin You  tlbBundle.priv.dmode := Mux(debugMode && dcsr.asTypeOf(new DcsrStruct).mprven, ModeM, Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpp, privilegeMode))
1087c84054caSLinJiawei
1088e9341afdSYinan Xu  // Branch control
10895b0f0029SXuan Hu  val retTarget = WireInit(0.U)
10908e7b11e5SWilliam Wang  val resetSatp = addr === Satp.U && wen // write to satp will cause the pipeline be flushed
1091bc63e578SLi Qianruo  flushPipe := resetSatp || (valid && func === CSROpType.jmp && !isEcall && !isEbreak)
1092c84054caSLinJiawei
10935b0f0029SXuan Hu  private val illegalRetTarget = WireInit(false.B)
10945b0f0029SXuan Hu  when(valid) {
10955b0f0029SXuan Hu    when(isDret) {
10965b0f0029SXuan Hu      retTarget := dpc(VAddrBits - 1, 0)
10975b0f0029SXuan Hu    }.elsewhen(isMret && !illegalMret) {
10985b0f0029SXuan Hu      retTarget := mepc(VAddrBits - 1, 0)
1099*d0de7e4aSpeixiaokun    }.elsewhen(isSret && !illegalSret && !illegalSModeSret && !illegalVSModeSret) {
1100*d0de7e4aSpeixiaokun      retTarget := Mux(virtMode, vsepc(VAddrBits - 1, 0), sepc(VAddrBits - 1, 0))
11015b0f0029SXuan Hu    }.elsewhen(isUret) {
11025b0f0029SXuan Hu      retTarget := uepc(VAddrBits - 1, 0)
11035b0f0029SXuan Hu    }.otherwise {
11045b0f0029SXuan Hu      illegalRetTarget := true.B
11055b0f0029SXuan Hu    }
11065b0f0029SXuan Hu  }.otherwise {
11075b0f0029SXuan Hu    illegalRetTarget := true.B // when illegalRetTarget setted, retTarget should never be used
11085b0f0029SXuan Hu  }
1109c84054caSLinJiawei
1110d4aca96cSlqre  when (valid && isDret) {
1111d4aca96cSlqre    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1112d4aca96cSlqre    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1113d4aca96cSlqre    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
1114d4aca96cSlqre    val debugModeNew = WireInit(debugMode)
1115d4aca96cSlqre    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.
1116d4aca96cSlqre    mstatus := mstatusNew.asUInt
1117321934c7SKunlin You    privilegeMode := dcsrNew.prv
1118d4aca96cSlqre    retTarget := dpc(VAddrBits-1, 0)
1119d4aca96cSlqre    debugModeNew := false.B
1120d4aca96cSlqre    debugIntrEnable := true.B
1121d4aca96cSlqre    debugMode := debugModeNew
1122d4aca96cSlqre    XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget)
1123d4aca96cSlqre  }
1124d4aca96cSlqre
1125cb8f1780SWilliam Wang  when (valid && isMret && !illegalMret) {
1126c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1127c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1128c84054caSLinJiawei    mstatusNew.ie.m := mstatusOld.pie.m
1129321934c7SKunlin You    privilegeMode := mstatusOld.mpp
1130*d0de7e4aSpeixiaokun    if(HasHExtension) {
1131*d0de7e4aSpeixiaokun      virtMode := mstatusOld.mpv
1132*d0de7e4aSpeixiaokun      mstatusNew.mpv := 0.U
1133*d0de7e4aSpeixiaokun    }
1134c84054caSLinJiawei    mstatusNew.pie.m := true.B
1135c84054caSLinJiawei    mstatusNew.mpp := ModeU
1136c266a93bSLemover    when (mstatusOld.mpp =/= ModeM) { mstatusNew.mprv := 0.U }
1137c84054caSLinJiawei    mstatus := mstatusNew.asUInt
1138c84054caSLinJiawei  }
1139c84054caSLinJiawei
1140*d0de7e4aSpeixiaokun  when (valid && isSret && !illegalSret && !illegalSModeSret && !illegalVSModeSret) {
1141c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1142c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1143*d0de7e4aSpeixiaokun    val hstatusOld = WireInit(hstatus.asTypeOf(new HstatusStruct))
1144*d0de7e4aSpeixiaokun    val hstatusNew = WireInit(hstatus.asTypeOf(new HstatusStruct))
1145*d0de7e4aSpeixiaokun    val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1146*d0de7e4aSpeixiaokun    val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1147*d0de7e4aSpeixiaokun    when (virtMode === 0.U) {
1148*d0de7e4aSpeixiaokun      virtMode := hstatusOld.spv
1149*d0de7e4aSpeixiaokun      hstatusNew.spv := 0.U
1150c84054caSLinJiawei      mstatusNew.ie.s := mstatusOld.pie.s
1151321934c7SKunlin You      privilegeMode := Cat(0.U(1.W), mstatusOld.spp)
1152c84054caSLinJiawei      mstatusNew.pie.s := true.B
1153c84054caSLinJiawei      mstatusNew.spp := ModeU
1154*d0de7e4aSpeixiaokun      when(mstatusOld.spp =/= ModeM) {
1155*d0de7e4aSpeixiaokun        mstatusNew.mprv := 0.U
1156*d0de7e4aSpeixiaokun      }
1157c84054caSLinJiawei      mstatus := mstatusNew.asUInt
1158*d0de7e4aSpeixiaokun      hstatus := hstatusNew.asUInt
1159*d0de7e4aSpeixiaokun    }.otherwise{
1160*d0de7e4aSpeixiaokun      privilegeMode := vsstatusOld.spp
1161*d0de7e4aSpeixiaokun      vsstatusNew.spp := ModeU
1162*d0de7e4aSpeixiaokun      vsstatusNew.ie.s := vsstatusOld.pie.s
1163*d0de7e4aSpeixiaokun      vsstatusNew.pie.s := 1.U
1164*d0de7e4aSpeixiaokun      vsstatus := vsstatusNew.asUInt
1165*d0de7e4aSpeixiaokun    }
1166c84054caSLinJiawei  }
1167c84054caSLinJiawei
1168c84054caSLinJiawei  when (valid && isUret) {
1169c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1170c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1171c84054caSLinJiawei    // mstatusNew.mpp.m := ModeU //TODO: add mode U
1172c84054caSLinJiawei    mstatusNew.ie.u := mstatusOld.pie.u
1173321934c7SKunlin You    privilegeMode := ModeU
1174c84054caSLinJiawei    mstatusNew.pie.u := true.B
1175c84054caSLinJiawei    mstatus := mstatusNew.asUInt
1176c84054caSLinJiawei  }
1177c84054caSLinJiawei
1178e9341afdSYinan Xu  io.in.ready := true.B
1179e9341afdSYinan Xu  io.out.valid := valid
1180e9341afdSYinan Xu
11815b0f0029SXuan Hu  // In this situation, hart will enter debug mode instead of handling a breakpoint exception simply.
11825b0f0029SXuan Hu  // Ebreak block instructions backwards, so it's ok to not keep extra info to distinguish between breakpoint
11835b0f0029SXuan Hu  // exception and enter-debug-mode exception.
11845b0f0029SXuan Hu  val ebreakEnterDebugMode =
11855b0f0029SXuan Hu    (privilegeMode === ModeM && dcsrData.ebreakm) ||
11865b0f0029SXuan Hu    (privilegeMode === ModeS && dcsrData.ebreaks) ||
11875b0f0029SXuan Hu    (privilegeMode === ModeU && dcsrData.ebreaku)
11885b0f0029SXuan Hu
11895b0f0029SXuan Hu  // raise a debug exception waiting to enter debug mode, instead of a breakpoint exception
11905b0f0029SXuan Hu  val raiseDebugException = !debugMode && isEbreak && ebreakEnterDebugMode
1191d4aca96cSlqre
1192baf8def6SYinan Xu  val csrExceptionVec = WireInit(cfIn.exceptionVec)
1193*d0de7e4aSpeixiaokun  csrExceptionVec(breakPoint) := io.in.valid && isEbreak && (ebreakCauseException || debugMode)
1194321934c7SKunlin You  csrExceptionVec(ecallM) := privilegeMode === ModeM && io.in.valid && isEcall
1195*d0de7e4aSpeixiaokun  csrExceptionVec(ecallVS) := privilegeMode === ModeS && virtMode && io.in.valid && isEcall
1196*d0de7e4aSpeixiaokun  csrExceptionVec(ecallS) := privilegeMode === ModeS && !virtMode && io.in.valid && isEcall
1197321934c7SKunlin You  csrExceptionVec(ecallU) := privilegeMode === ModeU && io.in.valid && isEcall
1198baf8def6SYinan Xu  // Trigger an illegal instr exception when:
1199baf8def6SYinan Xu  // * unimplemented csr is being read/written
1200baf8def6SYinan Xu  // * csr access is illegal
12015d669833SYinan Xu  csrExceptionVec(illegalInstr) := isIllegalAddr || isIllegalAccess || isIllegalPrivOp
1202*d0de7e4aSpeixiaokun  csrExceptionVec(virtualInstr) := isIllegalVAccess || isIllegalVPrivOp
1203baf8def6SYinan Xu  cfOut.exceptionVec := csrExceptionVec
1204baf8def6SYinan Xu
12055b0f0029SXuan Hu  XSDebug(io.in.valid, s"Debug Mode: an Ebreak is executed, ebreak cause enter-debug-mode exception ? ${raiseDebugException}\n")
120684e47f35SLi Qianruo
1207e9341afdSYinan Xu  /**
1208e9341afdSYinan Xu    * Exception and Intr
1209e9341afdSYinan Xu    */
1210*d0de7e4aSpeixiaokun  val idelegS =  (mideleg & mip.asUInt)
1211*d0de7e4aSpeixiaokun  val idelegVS = (hideleg & mideleg & mip.asUInt)
1212*d0de7e4aSpeixiaokun  def privilegedEnableDetect(idelegS: Bool, idelegVS: Bool): Bool = Mux(idelegS,
1213*d0de7e4aSpeixiaokun    Mux(idelegVS, (virtMode && privilegeMode === ModeS && vsstatusStruct.ie.s) || (virtMode && privilegeMode < ModeS),
1214*d0de7e4aSpeixiaokun      ((privilegeMode === ModeS) && mstatusStruct.ie.s) || (privilegeMode < ModeS) || virtMode),
1215321934c7SKunlin You    ((privilegeMode === ModeM) && mstatusStruct.ie.m) || (privilegeMode < ModeM))
1216e9341afdSYinan Xu
1217d4aca96cSlqre  val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable
1218d4aca96cSlqre  XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!")
12199aca92b9SYinan Xu  // send interrupt information to ROB
1220*d0de7e4aSpeixiaokun  val intrVecEnable = Wire(Vec(13, Bool()))
1221052ee9a1SLi Qianruo  val disableInterrupt = debugMode || (dcsrData.step && !dcsrData.stepie)
1222*d0de7e4aSpeixiaokun  intrVecEnable.zip(idelegS.asBools).zip(idelegVS.asBools).map{case((x,y),z) => x := privilegedEnableDetect(y, z) && !disableInterrupt}
1223d7dd1af1SLi Qianruo  val intrVec = Cat(debugIntr && !debugMode, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt))
12245d669833SYinan Xu  val intrBitSet = intrVec.orR
1225e9341afdSYinan Xu  csrio.interrupt := intrBitSet
12265c95ea2eSYinan Xu  // Page 45 in RISC-V Privileged Specification
12275c95ea2eSYinan Xu  // The WFI instruction can also be executed when interrupts are disabled. The operation of WFI
12285c95ea2eSYinan Xu  // must be unaffected by the global interrupt bits in mstatus (MIE and SIE) and the delegation
12295c95ea2eSYinan Xu  // register mideleg, but should honor the individual interrupt enables (e.g, MTIE).
12304ede3fe2SLi Qianruo  csrio.wfi_event := debugIntr || (mie(11, 0) & mip.asUInt).orR
1231e9341afdSYinan Xu  mipWire.t.m := csrio.externalInterrupt.mtip
1232e9341afdSYinan Xu  mipWire.s.m := csrio.externalInterrupt.msip
1233e9341afdSYinan Xu  mipWire.e.m := csrio.externalInterrupt.meip
1234b3d79b37SYinan Xu  mipWire.e.s := csrio.externalInterrupt.seip
1235e9341afdSYinan Xu
1236e9341afdSYinan Xu  // interrupts
1237e9341afdSYinan Xu  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
12385b0f0029SXuan Hu  val hasIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
1239a4e57ea3SLi Qianruo  val ivmEnable = tlbBundle.priv.imode < ModeM && satp.asTypeOf(new SatpStruct).mode === 8.U
1240a4e57ea3SLi Qianruo  val iexceptionPC = Mux(ivmEnable, SignExt(csrio.exception.bits.uop.cf.pc, XLEN), csrio.exception.bits.uop.cf.pc)
1241*d0de7e4aSpeixiaokun  val iexceptionGPAddr = Mux(ivmEnable, SignExt(csrio.exception.bits.uop.cf.gpaddr, XLEN), csrio.exception.bits.uop.cf.gpaddr)
1242a4e57ea3SLi Qianruo  val dvmEnable = tlbBundle.priv.dmode < ModeM && satp.asTypeOf(new SatpStruct).mode === 8.U
1243a4e57ea3SLi Qianruo  val dexceptionPC = Mux(dvmEnable, SignExt(csrio.exception.bits.uop.cf.pc, XLEN), csrio.exception.bits.uop.cf.pc)
12445b0f0029SXuan Hu  XSDebug(hasIntr, "interrupt: pc=0x%x, %d\n", dexceptionPC, intrNO)
12455b0f0029SXuan Hu  val hasDebugIntr = intrNO === IRQ_DEBUG.U && hasIntr
1246e9341afdSYinan Xu
1247*d0de7e4aSpeixiaokun  // exceptions
1248*d0de7e4aSpeixiaokun  val raiseException = csrio.exception.valid && !csrio.exception.bits.isInterrupt
1249*d0de7e4aSpeixiaokun  val hasInstrPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrPageFault) && raiseException
1250*d0de7e4aSpeixiaokun  val hasLoadPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadPageFault) && raiseException
1251*d0de7e4aSpeixiaokun  val hasStorePageFault = csrio.exception.bits.uop.cf.exceptionVec(storePageFault) && raiseException
1252*d0de7e4aSpeixiaokun  val hasStoreAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(storeAddrMisaligned) && raiseException
1253*d0de7e4aSpeixiaokun  val hasLoadAddrMisaligned = csrio.exception.bits.uop.cf.exceptionVec(loadAddrMisaligned) && raiseException
1254*d0de7e4aSpeixiaokun  val hasInstrAccessFault = csrio.exception.bits.uop.cf.exceptionVec(instrAccessFault) && raiseException
1255*d0de7e4aSpeixiaokun  val hasLoadAccessFault = csrio.exception.bits.uop.cf.exceptionVec(loadAccessFault) && raiseException
1256*d0de7e4aSpeixiaokun  val hasStoreAccessFault = csrio.exception.bits.uop.cf.exceptionVec(storeAccessFault) && raiseException
1257*d0de7e4aSpeixiaokun  val hasbreakPoint = csrio.exception.bits.uop.cf.exceptionVec(breakPoint) && raiseException
1258*d0de7e4aSpeixiaokun  val hasSingleStep = csrio.exception.bits.uop.ctrl.singleStep && raiseException
1259*d0de7e4aSpeixiaokun  val hasTriggerHit = (csrio.exception.bits.uop.cf.trigger.hit) && raiseException
1260*d0de7e4aSpeixiaokun  val hasInstGuestPageFault = csrio.exception.bits.uop.cf.exceptionVec(instrGuestPageFault) && raiseException
1261*d0de7e4aSpeixiaokun  val hasLoadGuestPageFault = csrio.exception.bits.uop.cf.exceptionVec(loadGuestPageFault) && raiseException
1262*d0de7e4aSpeixiaokun  val hasStoreGuestPageFault = csrio.exception.bits.uop.cf.exceptionVec(storeGuestPageFault) && raiseException
126384e47f35SLi Qianruo
126484e47f35SLi Qianruo  XSDebug(hasSingleStep, "Debug Mode: single step exception\n")
1265ddb65c47SLi Qianruo  XSDebug(hasTriggerHit, p"Debug Mode: trigger hit, is frontend? ${Binary(csrio.exception.bits.uop.cf.trigger.frontendHit.asUInt)} " +
1266068bf978SLi Qianruo    p"backend hit vec ${Binary(csrio.exception.bits.uop.cf.trigger.backendHit.asUInt)}\n")
1267e9341afdSYinan Xu
12685b0f0029SXuan Hu  val hasExceptionVec = csrio.exception.bits.uop.cf.exceptionVec
12695b0f0029SXuan Hu  val regularExceptionNO = ExceptionNO.priorities.foldRight(0.U)((i: Int, sum: UInt) => Mux(hasExceptionVec(i), i.U, sum))
127072951335SLi Qianruo  val exceptionNO = Mux(hasSingleStep || hasTriggerHit, 3.U, regularExceptionNO)
12715b0f0029SXuan Hu  val causeNO = (hasIntr << (XLEN-1)).asUInt | Mux(hasIntr, intrNO, exceptionNO)
1272e9341afdSYinan Xu
12735b0f0029SXuan Hu  val hasExceptionIntr = csrio.exception.valid
1274d4aca96cSlqre
12755b0f0029SXuan Hu  val hasDebugException = hasBreakPoint && !debugMode && ebreakEnterDebugMode
12765b0f0029SXuan Hu  val hasDebugExceptionIntr = !debugMode && (hasDebugException || hasDebugIntr || hasSingleStep || hasTriggerHit && triggerAction) // TODO
12775b0f0029SXuan Hu  val ebreakEnterParkLoop = debugMode && hasExceptionIntr
1278d4aca96cSlqre
12795b0f0029SXuan Hu  XSDebug(hasExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
12805b0f0029SXuan Hu    dexceptionPC, intrNO, intrVec, exceptionNO, hasExceptionVec.asUInt
1281e9341afdSYinan Xu  )
12825b0f0029SXuan Hu  XSDebug(hasExceptionIntr,
1283e9341afdSYinan Xu    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
1284a4e57ea3SLi Qianruo    dexceptionPC,
1285e9341afdSYinan Xu    mstatus,
1286e9341afdSYinan Xu    mideleg,
1287e9341afdSYinan Xu    medeleg,
1288321934c7SKunlin You    privilegeMode
1289e9341afdSYinan Xu  )
1290e9341afdSYinan Xu
1291e9341afdSYinan Xu  // mtval write logic
12928a33de1fSYinan Xu  // Due to timing reasons of memExceptionVAddr, we delay the write of mtval and stval
1293e9341afdSYinan Xu  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
1294*d0de7e4aSpeixiaokun  val memExceptionGPAddr = SignExt(csrio.memExceptionGPAddr, XLEN)
1295a4e57ea3SLi Qianruo  val updateTval = VecInit(Seq(
1296a4e57ea3SLi Qianruo    hasInstrPageFault,
1297a4e57ea3SLi Qianruo    hasLoadPageFault,
1298a4e57ea3SLi Qianruo    hasStorePageFault,
1299a4e57ea3SLi Qianruo    hasInstrAccessFault,
1300a4e57ea3SLi Qianruo    hasLoadAccessFault,
1301a4e57ea3SLi Qianruo    hasStoreAccessFault,
1302*d0de7e4aSpeixiaokun    hasLoadAddrMisaligned,
1303*d0de7e4aSpeixiaokun    hasStoreAddrMisaligned,
1304*d0de7e4aSpeixiaokun    hasInstGuestPageFault,
1305*d0de7e4aSpeixiaokun    hasLoadGuestPageFault,
1306*d0de7e4aSpeixiaokun    hasStoreGuestPageFault
1307*d0de7e4aSpeixiaokun  )).asUInt.orR
1308*d0de7e4aSpeixiaokun  val updateTval_h = VecInit(Seq(
1309*d0de7e4aSpeixiaokun    hasInstGuestPageFault,
1310*d0de7e4aSpeixiaokun    hasLoadGuestPageFault,
1311*d0de7e4aSpeixiaokun    hasStoreGuestPageFault
1312a4e57ea3SLi Qianruo  )).asUInt.orR
1313a4e57ea3SLi Qianruo  when (RegNext(RegNext(updateTval))) {
131495fbbc80SYinan Xu      val tval = Mux(
1315*d0de7e4aSpeixiaokun        RegNext(RegNext(hasInstrPageFault || hasInstrAccessFault || hasInstGuestPageFault)),
131695fbbc80SYinan Xu        RegNext(RegNext(Mux(
13172d7c7105SYinan Xu          csrio.exception.bits.uop.cf.crossPageIPFFix,
13182d7c7105SYinan Xu          SignExt(csrio.exception.bits.uop.cf.pc + 2.U, XLEN),
1319a4e57ea3SLi Qianruo          iexceptionPC
132095fbbc80SYinan Xu        ))),
1321e9341afdSYinan Xu        memExceptionAddr
132295fbbc80SYinan Xu    )
1323*d0de7e4aSpeixiaokun    // because we update tval two beats later, we can choose xtval according to the privilegeMode which has been updated
1324321934c7SKunlin You    when (RegNext(privilegeMode === ModeM)) {
1325e9341afdSYinan Xu      mtval := tval
1326e9341afdSYinan Xu    }.otherwise {
1327*d0de7e4aSpeixiaokun      when (virtMode){
1328*d0de7e4aSpeixiaokun        vstval := tval
1329*d0de7e4aSpeixiaokun      }.otherwise{
1330e9341afdSYinan Xu        stval := tval
1331e9341afdSYinan Xu      }
1332e9341afdSYinan Xu    }
1333*d0de7e4aSpeixiaokun  }
1334*d0de7e4aSpeixiaokun
1335*d0de7e4aSpeixiaokun  when(RegNext(RegNext(updateTval_h))) {
1336*d0de7e4aSpeixiaokun    val tval_tmp = Mux(
1337*d0de7e4aSpeixiaokun      RegNext(RegNext(hasInstGuestPageFault)),
1338*d0de7e4aSpeixiaokun      RegNext(RegNext(Mux(
1339*d0de7e4aSpeixiaokun        csrio.exception.bits.uop.cf.crossPageIPFFix,
1340*d0de7e4aSpeixiaokun        SignExt(csrio.exception.bits.uop.cf.gpaddr + 2.U, XLEN),
1341*d0de7e4aSpeixiaokun        iexceptionGPAddr
1342*d0de7e4aSpeixiaokun      ))),
1343*d0de7e4aSpeixiaokun      memExceptionGPAddr
1344*d0de7e4aSpeixiaokun    )
1345*d0de7e4aSpeixiaokun    val tval = tval_tmp >> 2
1346*d0de7e4aSpeixiaokun    when(RegNext(privilegeMode === ModeM)) {
1347*d0de7e4aSpeixiaokun      mtval2 := tval
1348*d0de7e4aSpeixiaokun    }.otherwise {
1349*d0de7e4aSpeixiaokun      htval := tval
1350*d0de7e4aSpeixiaokun    }
1351*d0de7e4aSpeixiaokun  }
1352e9341afdSYinan Xu
1353d4aca96cSlqre  val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec
1354*d0de7e4aSpeixiaokun  val deleg = Mux(raiseIntr, mideleg , medeleg)
1355*d0de7e4aSpeixiaokun  val hdeleg = Mux(raiseIntr, hideleg, hedeleg)
1356321934c7SKunlin You  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (privilegeMode < ModeM);
13575b0f0029SXuan Hu  val delegS = deleg(causeNO(7,0)) && (privilegeMode < ModeM)
1358*d0de7e4aSpeixiaokun  val delegVS = virtMode && delegS && hdeleg(causeNO(7, 0)) && (privilegeMode < ModeM)
1359*d0de7e4aSpeixiaokun  val clearTval = !updateTval || raiseIntr
1360*d0de7e4aSpeixiaokun  val clearTval_h = !updateTval_h || raiseIntr
1361d4aca96cSlqre  val isXRet = io.in.valid && func === CSROpType.jmp && !isEcall && !isEbreak
1362*d0de7e4aSpeixiaokun  val isHyperInst = csrio.exception.bits.uop.ctrl.isHyperInst
136313096f7eSYinan Xu  // ctrl block will use theses later for flush
136413096f7eSYinan Xu  val isXRetFlag = RegInit(false.B)
1365a4e57ea3SLi Qianruo  when (DelayN(io.redirectIn.valid, 5)) {
136613096f7eSYinan Xu    isXRetFlag := false.B
136713096f7eSYinan Xu  }.elsewhen (isXRet) {
136813096f7eSYinan Xu    isXRetFlag := true.B
136913096f7eSYinan Xu  }
137013096f7eSYinan Xu  csrio.isXRet := isXRetFlag
13715b0f0029SXuan Hu  private val retTargetReg = RegEnable(retTarget, isXRet && !illegalRetTarget)
1372*d0de7e4aSpeixiaokun  private val illegalXret = RegEnable(illegalMret || illegalSret || illegalSModeSret || illegalVSModeSret, isXRet)
1373*d0de7e4aSpeixiaokun  val xtvec = Mux(delegS, Mux(delegVS, vstvec, stvec), mtvec)
13745b0f0029SXuan Hu  val xtvecBase = xtvec(VAddrBits - 1, 2)
1375a4e57ea3SLi Qianruo  // When MODE=Vectored, all synchronous exceptions into M/S mode
1376a4e57ea3SLi Qianruo  // cause the pc to be set to the address in the BASE field, whereas
1377a4e57ea3SLi Qianruo  // interrupts cause the pc to be set to the address in the BASE field
1378a4e57ea3SLi Qianruo  // plus four times the interrupt cause number.
1379*d0de7e4aSpeixiaokun  private val pcFromXtvec = Cat(xtvecBase + Mux(xtvec(0) && raiseIntr, causeNO(3, 0), 0.U), 0.U(2.W))
13805b0f0029SXuan Hu  // XRet sends redirect instead of Flush and isXRetFlag is true.B before redirect.valid.
13815b0f0029SXuan Hu  // ROB sends exception at T0 while CSR receives at T2.
13825b0f0029SXuan Hu  // We add a RegNext here and trapTarget is valid at T3.
13835b0f0029SXuan Hu  csrio.trapTarget := RegEnable(
13845b0f0029SXuan Hu    MuxCase(pcFromXtvec, Seq(
13855b0f0029SXuan Hu      (isXRetFlag && !illegalXret) -> retTargetReg,
1386*d0de7e4aSpeixiaokun      (raiseDebugExceptionIntr || ebreakEnterParkLoop) -> debugTrapTarget
13875b0f0029SXuan Hu    )),
13885b0f0029SXuan Hu    isXRetFlag || csrio.exception.valid)
1389e9341afdSYinan Xu
13905b0f0029SXuan Hu  when (hasExceptionIntr) {
1391c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1392c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1393*d0de7e4aSpeixiaokun    val hstatusOld = WireInit(hstatus.asTypeOf(new HstatusStruct))
1394*d0de7e4aSpeixiaokun    val hstatusNew = WireInit(hstatus.asTypeOf(new HstatusStruct))
1395*d0de7e4aSpeixiaokun    val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1396*d0de7e4aSpeixiaokun    val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1397d4aca96cSlqre    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
1398d4aca96cSlqre    val debugModeNew = WireInit(debugMode)
1399c84054caSLinJiawei
14005b0f0029SXuan Hu    when (hasDebugExceptionIntr) {
14015b0f0029SXuan Hu      when (hasDebugIntr) {
1402d4aca96cSlqre        debugModeNew := true.B
1403a4e57ea3SLi Qianruo        dpc := iexceptionPC
1404d7dd1af1SLi Qianruo        dcsrNew.cause := 3.U
1405321934c7SKunlin You        dcsrNew.prv := privilegeMode
1406321934c7SKunlin You        privilegeMode := ModeM
14075b0f0029SXuan Hu        XSDebug(hasDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc)
14085b0f0029SXuan Hu      }.elsewhen ((hasBreakPoint || hasSingleStep || hasTriggerHit && triggerAction) && !debugMode) {
1409d4aca96cSlqre        // ebreak or ss in running hart
1410d4aca96cSlqre        debugModeNew := true.B
14115b0f0029SXuan Hu        dpc := iexceptionPC // TODO: check it when hasSingleStep
14125b0f0029SXuan Hu        dcsrNew.cause := Mux(hasTriggerHit, 2.U, Mux(hasBreakPoint, 1.U, 4.U))
14135b0f0029SXuan Hu        dcsrNew.prv := privilegeMode
1414321934c7SKunlin You        privilegeMode := ModeM
1415d4aca96cSlqre      }
1416d4aca96cSlqre      dcsr := dcsrNew.asUInt
1417d4aca96cSlqre      debugIntrEnable := false.B
1418d7dd1af1SLi Qianruo    }.elsewhen (debugMode) {
1419d7dd1af1SLi Qianruo      //do nothing
1420*d0de7e4aSpeixiaokun    }}.elsewhen (delegVS) {
1421*d0de7e4aSpeixiaokun      vscause := (raiseIntr << (XLEN-1)).asUInt | Mux(raiseIntr, intrNO >> 1.U, exceptionNO)
1422*d0de7e4aSpeixiaokun      vsepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1423*d0de7e4aSpeixiaokun      vsstatusNew.spp := privilegeMode
1424*d0de7e4aSpeixiaokun      vsstatusNew.pie.s := vsstatusOld.ie.s
1425*d0de7e4aSpeixiaokun      vsstatusNew.ie.s := false.B
1426*d0de7e4aSpeixiaokun      when (clearTval) {vstval := 0.U}
1427*d0de7e4aSpeixiaokun      virtMode := true.B
1428*d0de7e4aSpeixiaokun      privilegeMode := ModeS
1429d4aca96cSlqre    }.elsewhen (delegS) {
1430*d0de7e4aSpeixiaokun      val virt = Mux(mstatusOld.mprv.asBool(), mstatusOld.mpv, virtMode)
1431*d0de7e4aSpeixiaokun      // to do hld st
1432*d0de7e4aSpeixiaokun      hstatusNew.gva := (hasInstGuestPageFault || hasLoadGuestPageFault || hasStoreGuestPageFault ||
1433*d0de7e4aSpeixiaokun                      ((virt.asBool() || isHyperInst) && ((raiseException && 0.U <= exceptionNO && exceptionNO <= 7.U && exceptionNO =/= 2.U)
1434*d0de7e4aSpeixiaokun                      || hasInstrPageFault || hasLoadPageFault || hasStorePageFault)))
1435*d0de7e4aSpeixiaokun      hstatusNew.spv := virtMode
1436*d0de7e4aSpeixiaokun      when(virtMode){
1437*d0de7e4aSpeixiaokun        hstatusNew.spvp := privilegeMode
1438*d0de7e4aSpeixiaokun      }
1439*d0de7e4aSpeixiaokun      virtMode := false.B
1440c84054caSLinJiawei      scause := causeNO
1441a4e57ea3SLi Qianruo      sepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1442321934c7SKunlin You      mstatusNew.spp := privilegeMode
1443c84054caSLinJiawei      mstatusNew.pie.s := mstatusOld.ie.s
1444c84054caSLinJiawei      mstatusNew.ie.s := false.B
1445321934c7SKunlin You      privilegeMode := ModeS
1446a4e57ea3SLi Qianruo      when (clearTval) { stval := 0.U }
1447*d0de7e4aSpeixiaokun      when (clearTval_h) {htval := 0.U}
1448c84054caSLinJiawei    }.otherwise {
1449*d0de7e4aSpeixiaokun      val virt = Mux(mstatusOld.mprv.asBool(), mstatusOld.mpv, virtMode)
1450*d0de7e4aSpeixiaokun      // to do hld st
1451*d0de7e4aSpeixiaokun      mstatusNew.gva := (hasInstGuestPageFault || hasLoadGuestPageFault || hasStoreGuestPageFault ||
1452*d0de7e4aSpeixiaokun      ((virt.asBool() || isHyperInst) && ((raiseException && 0.U <= exceptionNO && exceptionNO <= 7.U && exceptionNO =/= 2.U)
1453*d0de7e4aSpeixiaokun        || hasInstrPageFault || hasLoadPageFault || hasStorePageFault)))
1454*d0de7e4aSpeixiaokun      mstatusNew.mpv := virtMode
1455*d0de7e4aSpeixiaokun      virtMode := false.B
1456c84054caSLinJiawei      mcause := causeNO
1457a4e57ea3SLi Qianruo      mepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1458321934c7SKunlin You      mstatusNew.mpp := privilegeMode
1459c84054caSLinJiawei      mstatusNew.pie.m := mstatusOld.ie.m
1460c84054caSLinJiawei      mstatusNew.ie.m := false.B
1461321934c7SKunlin You      privilegeMode := ModeM
1462a4e57ea3SLi Qianruo      when (clearTval) { mtval := 0.U }
1463*d0de7e4aSpeixiaokun      when (clearTval_h) {mtval2 := 0.U}
1464c84054caSLinJiawei    }
1465c84054caSLinJiawei    mstatus := mstatusNew.asUInt
1466*d0de7e4aSpeixiaokun    vsstatus := vsstatusNew.asUInt
1467*d0de7e4aSpeixiaokun    hstatus := hstatusNew.asUInt
1468d4aca96cSlqre    debugMode := debugModeNew
1469c84054caSLinJiawei  }
1470c84054caSLinJiawei
14715b0f0029SXuan Hu  XSDebug(hasExceptionIntr && delegS, "sepc is written!!! pc:%x\n", cfIn.pc)
1472bf9968b2SYinan Xu
1473e19f7967SWilliam Wang  // Distributed CSR update req
1474e19f7967SWilliam Wang  //
1475e19f7967SWilliam Wang  // For now we use it to implement customized cache op
147670899835SWilliam Wang  // It can be delayed if necessary
1477e19f7967SWilliam Wang
147870899835SWilliam Wang  val delayedUpdate0 = DelayN(csrio.distributedUpdate(0), 2)
147970899835SWilliam Wang  val delayedUpdate1 = DelayN(csrio.distributedUpdate(1), 2)
148070899835SWilliam Wang  val distributedUpdateValid = delayedUpdate0.w.valid || delayedUpdate1.w.valid
148170899835SWilliam Wang  val distributedUpdateAddr = Mux(delayedUpdate0.w.valid,
148270899835SWilliam Wang    delayedUpdate0.w.bits.addr,
148370899835SWilliam Wang    delayedUpdate1.w.bits.addr
148470899835SWilliam Wang  )
148570899835SWilliam Wang  val distributedUpdateData = Mux(delayedUpdate0.w.valid,
148670899835SWilliam Wang    delayedUpdate0.w.bits.data,
148770899835SWilliam Wang    delayedUpdate1.w.bits.data
148870899835SWilliam Wang  )
148970899835SWilliam Wang
149070899835SWilliam Wang  assert(!(delayedUpdate0.w.valid && delayedUpdate1.w.valid))
149170899835SWilliam Wang
149270899835SWilliam Wang  when(distributedUpdateValid){
1493e19f7967SWilliam Wang    // cacheopRegs can be distributed updated
1494e19f7967SWilliam Wang    CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
149570899835SWilliam Wang      when((Scachebase + attribute("offset").toInt).U === distributedUpdateAddr){
149670899835SWilliam Wang        cacheopRegs(name) := distributedUpdateData
1497e19f7967SWilliam Wang      }
1498e19f7967SWilliam Wang    }}
1499e19f7967SWilliam Wang  }
1500e19f7967SWilliam Wang
15019ef181f4SWilliam Wang  // Cache error debug support
15029ef181f4SWilliam Wang  if(HasCustomCSRCacheOp){
15039ef181f4SWilliam Wang    val cache_error_decoder = Module(new CSRCacheErrorDecoder)
15049ef181f4SWilliam Wang    cache_error_decoder.io.encoded_cache_error := cacheopRegs("CACHE_ERROR")
15059ef181f4SWilliam Wang  }
15069ef181f4SWilliam Wang
1507e30fd06aSYinan Xu  // Implicit add reset values for mepc[0] and sepc[0]
1508e30fd06aSYinan Xu  // TODO: rewrite mepc and sepc using a struct-like style with the LSB always being 0
150967ba96b4SYinan Xu  when (RegNext(RegNext(reset.asBool) && !reset.asBool)) {
1510e30fd06aSYinan Xu    mepc := Cat(mepc(XLEN - 1, 1), 0.U(1.W))
1511e30fd06aSYinan Xu    sepc := Cat(sepc(XLEN - 1, 1), 0.U(1.W))
1512e30fd06aSYinan Xu  }
1513e30fd06aSYinan Xu
1514c84054caSLinJiawei  def readWithScala(addr: Int): UInt = mapping(addr)._1
1515c84054caSLinJiawei
15165b0f0029SXuan Hu  val difftestIntrNO = Mux(hasIntr, causeNO, 0.U)
1517a165bd69Swangkaifan
1518cbe9a847SYinan Xu  // Always instantiate basic difftest modules.
1519cbe9a847SYinan Xu  if (env.AlwaysBasicDiff || env.EnableDifftest) {
15207d45a146SYinan Xu    val difftest = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true)
15217d45a146SYinan Xu    difftest.coreid      := csrio.hartId
15227d45a146SYinan Xu    difftest.valid       := csrio.exception.valid
15235b0f0029SXuan Hu    difftest.interrupt   := Mux(hasIntr, causeNO, 0.U)
15245b0f0029SXuan Hu    difftest.exception   := Mux(hasException, causeNO, 0.U)
15257d45a146SYinan Xu    difftest.exceptionPC := dexceptionPC
1526a4e57ea3SLi Qianruo    if (env.EnableDifftest) {
15277d45a146SYinan Xu      difftest.exceptionInst := csrio.exception.bits.uop.cf.instr
1528a4e57ea3SLi Qianruo    }
15292225d46eSJiawei Lin  }
15302225d46eSJiawei Lin
1531cbe9a847SYinan Xu  // Always instantiate basic difftest modules.
1532cbe9a847SYinan Xu  if (env.AlwaysBasicDiff || env.EnableDifftest) {
15337d45a146SYinan Xu    val difftest = DifftestModule(new DiffCSRState)
15347d45a146SYinan Xu    difftest.coreid := csrio.hartId
1535321934c7SKunlin You    difftest.privilegeMode := privilegeMode
15367d45a146SYinan Xu    difftest.mstatus := mstatus
15377d45a146SYinan Xu    difftest.sstatus := mstatus & sstatusRmask
15387d45a146SYinan Xu    difftest.mepc := mepc
15397d45a146SYinan Xu    difftest.sepc := sepc
15407d45a146SYinan Xu    difftest.mtval:= mtval
15417d45a146SYinan Xu    difftest.stval:= stval
15427d45a146SYinan Xu    difftest.mtvec := mtvec
15437d45a146SYinan Xu    difftest.stvec := stvec
15447d45a146SYinan Xu    difftest.mcause := mcause
15457d45a146SYinan Xu    difftest.scause := scause
15467d45a146SYinan Xu    difftest.satp := satp
15477d45a146SYinan Xu    difftest.mip := mipReg
15487d45a146SYinan Xu    difftest.mie := mie
15497d45a146SYinan Xu    difftest.mscratch := mscratch
15507d45a146SYinan Xu    difftest.sscratch := sscratch
15517d45a146SYinan Xu    difftest.mideleg := mideleg
15527d45a146SYinan Xu    difftest.medeleg := medeleg
1553a165bd69Swangkaifan  }
1554a4e57ea3SLi Qianruo
1555a4e57ea3SLi Qianruo  if (env.AlwaysBasicDiff || env.EnableDifftest) {
1556*d0de7e4aSpeixiaokun    val difftest = Module(new DifftestHCSRState)
1557*d0de7e4aSpeixiaokun    difftest.io.clock := clock
1558*d0de7e4aSpeixiaokun    difftest.io.coreid := csrio.hartId
1559*d0de7e4aSpeixiaokun    difftest.io.virtMode := virtMode
1560*d0de7e4aSpeixiaokun    difftest.io.mtval2 := mtval2
1561*d0de7e4aSpeixiaokun    difftest.io.mtinst := mtinst
1562*d0de7e4aSpeixiaokun    difftest.io.hstatus := hstatus
1563*d0de7e4aSpeixiaokun    difftest.io.hideleg := hideleg
1564*d0de7e4aSpeixiaokun    difftest.io.hedeleg := hedeleg
1565*d0de7e4aSpeixiaokun    difftest.io.hcounteren := hcounteren
1566*d0de7e4aSpeixiaokun    difftest.io.htval := htval
1567*d0de7e4aSpeixiaokun    difftest.io.htinst := htinst
1568*d0de7e4aSpeixiaokun    difftest.io.hgatp := hgatp
1569*d0de7e4aSpeixiaokun    difftest.io.vsstatus := vsstatus
1570*d0de7e4aSpeixiaokun    difftest.io.vstvec := vstvec
1571*d0de7e4aSpeixiaokun    difftest.io.vsepc := vsepc
1572*d0de7e4aSpeixiaokun    difftest.io.vscause := vscause
1573*d0de7e4aSpeixiaokun    difftest.io.vstval := vstval
1574*d0de7e4aSpeixiaokun    difftest.io.vsatp := vsatp
1575*d0de7e4aSpeixiaokun    difftest.io.vsscratch := vsscratch
1576*d0de7e4aSpeixiaokun  }
1577*d0de7e4aSpeixiaokun
1578*d0de7e4aSpeixiaokun  if(env.AlwaysBasicDiff || env.EnableDifftest) {
15797d45a146SYinan Xu    val difftest = DifftestModule(new DiffDebugMode)
15807d45a146SYinan Xu    difftest.coreid := csrio.hartId
15817d45a146SYinan Xu    difftest.debugMode := debugMode
15827d45a146SYinan Xu    difftest.dcsr := dcsr
15837d45a146SYinan Xu    difftest.dpc := dpc
15845b0f0029SXuan Hu    difftest.dscratch0 := dscratch0
15857d45a146SYinan Xu    difftest.dscratch1 := dscratch1
1586a4e57ea3SLi Qianruo  }
1587c84054caSLinJiawei}
15881545277aSYinan Xu
1589cd365d4cSrvcoresjwclass PFEvent(implicit p: Parameters) extends XSModule with HasCSRConst  {
1590cd365d4cSrvcoresjw  val io = IO(new Bundle {
1591cd365d4cSrvcoresjw    val distribute_csr = Flipped(new DistributedCSRIO())
1592cd365d4cSrvcoresjw    val hpmevent = Output(Vec(29, UInt(XLEN.W)))
1593cd365d4cSrvcoresjw  })
1594cd365d4cSrvcoresjw
1595cd365d4cSrvcoresjw  val w = io.distribute_csr.w
1596cd365d4cSrvcoresjw
15975fd90906Srvcoresjw  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
15985fd90906Srvcoresjw                   List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
15995fd90906Srvcoresjw                   List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
16005fd90906Srvcoresjw                   List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
1601cd365d4cSrvcoresjw
160212c44ce5Srvcoresjw  val perfEventMapping = (0 until 29).map(i => {Map(
160312c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmevent3 +i,
160412c44ce5Srvcoresjw                 reg  = perfEvents(i),
160512c44ce5Srvcoresjw                 wmask = "hf87fff3fcff3fcff".U(XLEN.W))
160612c44ce5Srvcoresjw  )}).fold(Map())((a,b) => a ++ b)
1607cd365d4cSrvcoresjw
1608cd365d4cSrvcoresjw  val rdata = Wire(UInt(XLEN.W))
1609cd365d4cSrvcoresjw  MaskedRegMap.generate(perfEventMapping, w.bits.addr, rdata, w.valid, w.bits.data)
16105fd90906Srvcoresjw  for(i <- 0 until 29){
16115fd90906Srvcoresjw    io.hpmevent(i) := perfEvents(i)
16125fd90906Srvcoresjw  }
1613cd365d4cSrvcoresjw}
1614