xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision 5f28e66678ef83e5df43f866bf2fcadb75c2f68c)
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._
31730cfbc0SXuan Huimport xiangshan.backend.Bundles.ExceptionInfo
3262a2cb19SXuan Huimport xiangshan.backend.fu.util.CSR.CSRNamedConstant.ContextStatus
3362a2cb19SXuan Huimport utils.MathUtils.{BigIntGenMask, BigIntNot}
34c84054caSLinJiawei
352225d46eSJiawei Linclass FpuCsrIO extends Bundle {
367f1506e3SLinJiawei  val fflags = Output(Valid(UInt(5.W)))
37c84054caSLinJiawei  val isIllegal = Output(Bool())
38c84054caSLinJiawei  val dirty_fs = Output(Bool())
39c84054caSLinJiawei  val frm = Input(UInt(3.W))
40c84054caSLinJiawei}
41c84054caSLinJiawei
42daa01159SZiyue Zhangclass VpuCsrIO(implicit p: Parameters) extends XSBundle {
43daa01159SZiyue Zhang  val vstart = Input(UInt(XLEN.W))
44daa01159SZiyue Zhang  val vxsat = Input(UInt(1.W))
45daa01159SZiyue Zhang  val vxrm = Input(UInt(2.W))
4635d1557aSZiyue Zhang  val vcsr = Input(UInt(XLEN.W))
47daa01159SZiyue Zhang  val vl = Input(UInt(XLEN.W))
4835d1557aSZiyue Zhang  val vtype = Input(UInt(XLEN.W))
49daa01159SZiyue Zhang  val vlenb = Input(UInt(XLEN.W))
50daa01159SZiyue Zhang
51daa01159SZiyue Zhang  val vill = Input(UInt(1.W))
52daa01159SZiyue Zhang  val vma = Input(UInt(1.W))
53daa01159SZiyue Zhang  val vta = Input(UInt(1.W))
54daa01159SZiyue Zhang  val vsew = Input(UInt(3.W))
55daa01159SZiyue Zhang  val vlmul = Input(UInt(3.W))
56daa01159SZiyue Zhang
5735d1557aSZiyue Zhang  val set_vstart = Output(Valid(UInt(XLEN.W)))
58daa01159SZiyue Zhang  val set_vl = Output(Valid(UInt(XLEN.W)))
5935d1557aSZiyue Zhang  val set_vtype = Output(Valid(UInt(XLEN.W)))
606355a2b7Sczw  val set_vxsat = Output(Valid(UInt(1.W)))
61daa01159SZiyue Zhang
62daa01159SZiyue Zhang  val dirty_vs = Output(Bool())
63daa01159SZiyue Zhang}
64daa01159SZiyue Zhang
65b2e234ebSLinJiawei
662225d46eSJiawei Linclass PerfCounterIO(implicit p: Parameters) extends XSBundle {
671ca0e4f3SYinan Xu  val perfEventsFrontend  = Vec(numCSRPCntFrontend, new PerfEvent)
681ca0e4f3SYinan Xu  val perfEventsCtrl      = Vec(numCSRPCntCtrl, new PerfEvent)
691ca0e4f3SYinan Xu  val perfEventsLsu       = Vec(numCSRPCntLsu, new PerfEvent)
701ca0e4f3SYinan Xu  val perfEventsHc        = Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent)
71edd6ddbcSwakafa  val retiredInstr = UInt(3.W)
72edd6ddbcSwakafa  val frontendInfo = new Bundle {
73edd6ddbcSwakafa    val ibufFull  = Bool()
74e0d9a9f0SLingrui98    val bpuInfo = new Bundle {
75e0d9a9f0SLingrui98      val bpRight = UInt(XLEN.W)
76e0d9a9f0SLingrui98      val bpWrong = UInt(XLEN.W)
77e0d9a9f0SLingrui98    }
78edd6ddbcSwakafa  }
79edd6ddbcSwakafa  val ctrlInfo = new Bundle {
809aca92b9SYinan Xu    val robFull   = Bool()
81edd6ddbcSwakafa    val intdqFull = Bool()
82edd6ddbcSwakafa    val fpdqFull  = Bool()
83edd6ddbcSwakafa    val lsdqFull  = Bool()
84edd6ddbcSwakafa  }
85edd6ddbcSwakafa  val memInfo = new Bundle {
86edd6ddbcSwakafa    val sqFull = Bool()
87edd6ddbcSwakafa    val lqFull = Bool()
88edd6ddbcSwakafa    val dcacheMSHRFull = Bool()
89edd6ddbcSwakafa  }
9062ab1317SYinan Xu}
9162ab1317SYinan Xu
922225d46eSJiawei Linclass CSRFileIO(implicit p: Parameters) extends XSBundle {
93f57f7f2aSYangyu Chen  val hartId = Input(UInt(hartIdLen.W))
94129a273eSYinan Xu  // output (for func === CSROpType.jmp)
95edd6ddbcSwakafa  val perf = Input(new PerfCounterIO)
968635f18fSwangkaifan  val isPerfCnt = Output(Bool())
97129a273eSYinan Xu  // to FPU
98129a273eSYinan Xu  val fpu = Flipped(new FpuCsrIO)
99daa01159SZiyue Zhang  // to VPU
100daa01159SZiyue Zhang  val vpu = Flipped(new VpuCsrIO)
101bf9968b2SYinan Xu  // from rob
1023a474d38SYinan Xu  val exception = Flipped(ValidIO(new ExceptionInfo))
103129a273eSYinan Xu  // to ROB
104ac5a5d53SLinJiawei  val isXRet = Output(Bool())
105129a273eSYinan Xu  val trapTarget = Output(UInt(VAddrBits.W))
106129a273eSYinan Xu  val interrupt = Output(Bool())
1075c95ea2eSYinan Xu  val wfi_event = Output(Bool())
108129a273eSYinan Xu  // from LSQ
109129a273eSYinan Xu  val memExceptionVAddr = Input(UInt(VAddrBits.W))
110d0de7e4aSpeixiaokun  val memExceptionGPAddr = Input(UInt(GPAddrBits.W))
111129a273eSYinan Xu  // from outside cpu,externalInterrupt
112129a273eSYinan Xu  val externalInterrupt = new ExternalInterruptIO
113129a273eSYinan Xu  // TLB
114129a273eSYinan Xu  val tlb = Output(new TlbCsrBundle)
115d4aca96cSlqre  // Debug Mode
116d7dd1af1SLi Qianruo  // val singleStep = Output(Bool())
117d4aca96cSlqre  val debugMode = Output(Bool())
118e5adbe81SLemover  // to Fence to disable sfence
119e5adbe81SLemover  val disableSfence = Output(Bool())
120d0de7e4aSpeixiaokun  // to Fence to disable hfence.gvma
121d0de7e4aSpeixiaokun  val disableHfenceg = Output(Bool())
122d0de7e4aSpeixiaokun  // to Fence to disable hfence.vvma
123d0de7e4aSpeixiaokun  val disableHfencev = Output(Bool())
124e377d77eSWilliam Wang  // Custom microarchiture ctrl signal
125e377d77eSWilliam Wang  val customCtrl = Output(new CustomCSRCtrlIO)
126e377d77eSWilliam Wang  // distributed csr write
12770899835SWilliam Wang  val distributedUpdate = Vec(2, Flipped(new DistributedCSRUpdateReq))
12835a47a38SYinan Xu}
12935a47a38SYinan Xu
130a8db15d8Sfdyclass VtypeStruct(implicit p: Parameters) extends XSBundle {
131a8db15d8Sfdy  val vill = UInt(1.W)
132a8db15d8Sfdy  val reserved = UInt((XLEN - 9).W)
133a8db15d8Sfdy  val vma = UInt(1.W)
134a8db15d8Sfdy  val vta = UInt(1.W)
135a8db15d8Sfdy  val vsew = UInt(3.W)
136a8db15d8Sfdy  val vlmul = UInt(3.W)
137a8db15d8Sfdy}
138a8db15d8Sfdy
139d91483a6Sfdyclass CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
1403b739f49SXuan Hu  with HasCSRConst
1413b739f49SXuan Hu  with PMPMethod
1423b739f49SXuan Hu  with PMAMethod
1433b739f49SXuan Hu  with HasXSParameter
144f7af4c74Schengguanghui  with SdtrigExt
145f7af4c74Schengguanghui  with DebugCSR
14635a47a38SYinan Xu{
1473b739f49SXuan Hu  val csrio = io.csrio.get
148c84054caSLinJiawei
149e18c367fSLinJiawei  val flushPipe = Wire(Bool())
150c84054caSLinJiawei
151e18c367fSLinJiawei  val (valid, src1, src2, func) = (
152e18c367fSLinJiawei    io.in.valid,
1536a35d972SXuan Hu    io.in.bits.data.src(0),
1546a35d972SXuan Hu    io.in.bits.data.imm,
1556a35d972SXuan Hu    io.in.bits.ctrl.fuOpType
156e18c367fSLinJiawei  )
157c84054caSLinJiawei
158c84054caSLinJiawei  // CSR define
159d0de7e4aSpeixiaokun  val virtMode = RegInit(false.B)
160d0de7e4aSpeixiaokun  csrio.customCtrl.virtMode := virtMode
161c84054caSLinJiawei
162c84054caSLinJiawei  class Priv extends Bundle {
163c84054caSLinJiawei    val m = Output(Bool())
164d0de7e4aSpeixiaokun    val h = Output(Bool()) // unused
165c84054caSLinJiawei    val s = Output(Bool())
166c84054caSLinJiawei    val u = Output(Bool())
167c84054caSLinJiawei  }
168c84054caSLinJiawei
169c84054caSLinJiawei  class MstatusStruct extends Bundle {
170c84054caSLinJiawei    val sd = Output(UInt(1.W))
1718e7b11e5SWilliam Wang
172d0de7e4aSpeixiaokun    val pad1 = if (XLEN == 64 && HasHExtension) Output(UInt(23.W)) else if (XLEN == 64) Output(UInt(25.W)) else null
173d0de7e4aSpeixiaokun    val mpv  = if (XLEN == 64 && HasHExtension) Output(UInt(1.W)) else null
174d0de7e4aSpeixiaokun    val gva  = if (XLEN == 64 && HasHExtension) Output(UInt(1.W)) else null
1757d9edc86SLemover    val mbe  = if (XLEN == 64) Output(UInt(1.W)) else null
1767d9edc86SLemover    val sbe  = if (XLEN == 64) Output(UInt(1.W)) else null
1778e7b11e5SWilliam Wang    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
1788e7b11e5SWilliam Wang    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
1798e7b11e5SWilliam Wang    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
1808e7b11e5SWilliam Wang
181c84054caSLinJiawei    val tsr = Output(UInt(1.W))
182c84054caSLinJiawei    val tw = Output(UInt(1.W))
1838e7b11e5SWilliam Wang    val tvm = Output(UInt(1.W))
184c84054caSLinJiawei    val mxr = Output(UInt(1.W))
185c84054caSLinJiawei    val sum = Output(UInt(1.W))
186c84054caSLinJiawei    val mprv = Output(UInt(1.W))
187c84054caSLinJiawei    val xs = Output(UInt(2.W))
188c84054caSLinJiawei    val fs = Output(UInt(2.W))
189c84054caSLinJiawei    val mpp = Output(UInt(2.W))
190daa01159SZiyue Zhang    val vs = Output(UInt(2.W))
191c84054caSLinJiawei    val spp = Output(UInt(1.W))
192c84054caSLinJiawei    val pie = new Priv
193c84054caSLinJiawei    val ie = new Priv
194c84054caSLinJiawei    assert(this.getWidth == XLEN)
1957d9edc86SLemover
1967d9edc86SLemover    def ube = pie.h // a little ugly
1977d9edc86SLemover    def ube_(r: UInt): Unit = {
1987d9edc86SLemover      pie.h := r(0)
1997d9edc86SLemover    }
200c84054caSLinJiawei  }
201c84054caSLinJiawei
202d0de7e4aSpeixiaokun  class HstatusStruct extends Bundle {
203d0de7e4aSpeixiaokun    val pad4 = if (HSXLEN == 64) Output(UInt(30.W)) else null
204d0de7e4aSpeixiaokun    val vsxl = if (HSXLEN == 64) Output(UInt(2.W)) else null
205d0de7e4aSpeixiaokun    val pad3 = Output(UInt(9.W))
206d0de7e4aSpeixiaokun    val vtsr = Output(UInt(1.W))
207d0de7e4aSpeixiaokun    val vtw = Output(UInt(1.W))
208d0de7e4aSpeixiaokun    val vtvm = Output(UInt(1.W))
209d0de7e4aSpeixiaokun    val pad2 = Output(UInt(2.W))
210d0de7e4aSpeixiaokun    val vgein = Output(UInt(6.W))
211d0de7e4aSpeixiaokun    val pad1 = Output(UInt(2.W))
212d0de7e4aSpeixiaokun    val hu = Output(UInt(1.W))
213d0de7e4aSpeixiaokun    val spvp = Output(UInt(1.W))
214d0de7e4aSpeixiaokun    val spv = Output(UInt(1.W))
215d0de7e4aSpeixiaokun    val gva = Output(UInt(1.W))
216d0de7e4aSpeixiaokun    val vsbe = Output(UInt(1.W))
217d0de7e4aSpeixiaokun    val pad0 = Output(UInt(5.W))
218d0de7e4aSpeixiaokun    assert(this.getWidth == XLEN)
219d0de7e4aSpeixiaokun  }
220d0de7e4aSpeixiaokun
221c84054caSLinJiawei  class Interrupt extends Bundle {
222d4aca96cSlqre//  val d = Output(Bool())    // Debug
223c84054caSLinJiawei    val e = new Priv
224c84054caSLinJiawei    val t = new Priv
225c84054caSLinJiawei    val s = new Priv
226c84054caSLinJiawei  }
227c84054caSLinJiawei
228d4aca96cSlqre  // Debug CSRs
229f7af4c74Schengguanghui  val dcsr = RegInit(UInt(32.W), DcsrStruct.init)
230d4aca96cSlqre  val dpc = Reg(UInt(64.W))
231f7af4c74Schengguanghui  val dscratch0 = Reg(UInt(64.W))
232d4aca96cSlqre  val dscratch1 = Reg(UInt(64.W))
233d4aca96cSlqre  val debugMode = RegInit(false.B)
234f7af4c74Schengguanghui  val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable
235d4aca96cSlqre  csrio.debugMode := debugMode
236d4aca96cSlqre
237d4aca96cSlqre  val dpcPrev = RegNext(dpc)
2381097f021SLi Qianruo  XSDebug(dpcPrev =/= dpc, "Debug Mode: dpc is altered! Current is %x, previous is %x\n", dpc, dpcPrev)
239d4aca96cSlqre
240d4aca96cSlqre  val dcsrData = Wire(new DcsrStruct)
241d4aca96cSlqre  dcsrData := dcsr.asTypeOf(new DcsrStruct)
242d7dd1af1SLi Qianruo  val dcsrMask = ZeroExt(GenMask(15) | GenMask(13, 11) | GenMask(4) | GenMask(2, 0), XLEN)// Dcsr write mask
243d4aca96cSlqre  def dcsrUpdateSideEffect(dcsr: UInt): UInt = {
244d4aca96cSlqre    val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct))
245d4aca96cSlqre    val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11
246d4aca96cSlqre    dcsrNew
247d4aca96cSlqre  }
248d7dd1af1SLi Qianruo  // csrio.singleStep := dcsrData.step
249d7dd1af1SLi Qianruo  csrio.customCtrl.singlestep := dcsrData.step && !debugMode
250d4aca96cSlqre
25172951335SLi Qianruo  // Trigger CSRs
252f7af4c74Schengguanghui  private val tselectPhy = RegInit(0.U(log2Up(TriggerNum).W))
25372951335SLi Qianruo
254f7af4c74Schengguanghui  private val tdata1RegVec = RegInit(VecInit(Seq.fill(TriggerNum)(Tdata1Bundle.default)))
255f7af4c74Schengguanghui  private val tdata2RegVec = RegInit(VecInit(Seq.fill(TriggerNum)(0.U(64.W))))
256f7af4c74Schengguanghui  private val tdata1WireVec = tdata1RegVec.map(_.asTypeOf(new Tdata1Bundle))
257f7af4c74Schengguanghui  private val tdata2WireVec = tdata2RegVec
258f7af4c74Schengguanghui  private val tdata1Selected = tdata1RegVec(tselectPhy).asTypeOf(new Tdata1Bundle)
259f7af4c74Schengguanghui  private val tdata2Selected = tdata2RegVec(tselectPhy)
260f7af4c74Schengguanghui  private val newTriggerChainVec = UIntToOH(tselectPhy, TriggerNum).asBools | tdata1WireVec.map(_.data.asTypeOf(new MControlData).chain)
261f7af4c74Schengguanghui  private val newTriggerChainIsLegal = TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength)
262f7af4c74Schengguanghui  val tinfo = RegInit((BigInt(1) << TrigTypeEnum.MCONTROL.litValue.toInt).U(XLEN.W)) // This value should be 4.U
263716f717fSLi Qianruo
26472951335SLi Qianruo
26572951335SLi Qianruo  def WriteTselect(wdata: UInt) = {
266*5f28e666Schengguanghui    Mux(wdata < TriggerNum.U, wdata(log2Up(TriggerNum) - 1, 0), tselectPhy)
26772951335SLi Qianruo  }
26872951335SLi Qianruo
269f7af4c74Schengguanghui  def GenTdataDistribute(tdata1: Tdata1Bundle, tdata2: UInt): MatchTriggerIO = {
27072951335SLi Qianruo    val res = Wire(new MatchTriggerIO)
271f7af4c74Schengguanghui    val mcontrol: MControlData = WireInit(tdata1.data.asTypeOf(new MControlData))
272f7af4c74Schengguanghui    res.matchType := mcontrol.match_.asUInt
273f7af4c74Schengguanghui    res.select    := mcontrol.select
274f7af4c74Schengguanghui    res.timing    := mcontrol.timing
275f7af4c74Schengguanghui    res.action    := mcontrol.action.asUInt
276f7af4c74Schengguanghui    res.chain     := mcontrol.chain
277f7af4c74Schengguanghui    res.execute   := mcontrol.execute
278f7af4c74Schengguanghui    res.load      := mcontrol.load
279f7af4c74Schengguanghui    res.store     := mcontrol.store
28072951335SLi Qianruo    res.tdata2    := tdata2
28172951335SLi Qianruo    res
28272951335SLi Qianruo  }
28372951335SLi Qianruo
284f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tUpdate.bits.addr := tselectPhy
285f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tUpdate.bits.addr := tselectPhy
286f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tUpdate.bits.tdata := GenTdataDistribute(tdata1Selected, tdata2Selected)
287f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tUpdate.bits.tdata := GenTdataDistribute(tdata1Selected, tdata2Selected)
28872951335SLi Qianruo
289c84054caSLinJiawei  // Machine-Level CSRs
290a4e57ea3SLi Qianruo  // mtvec: {BASE (WARL), MODE (WARL)} where mode is 0 or 1
291a4e57ea3SLi Qianruo  val mtvecMask = ~(0x2.U(XLEN.W))
292c84054caSLinJiawei  val mtvec = RegInit(UInt(XLEN.W), 0.U)
293c84054caSLinJiawei  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
294e4b1ccacSxuzefan  // Currently, XiangShan don't support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
295e4b1ccacSxuzefan  val mcounterenMask = 0.U(XLEN.W)
296c84054caSLinJiawei  val mcause = RegInit(UInt(XLEN.W), 0.U)
297c84054caSLinJiawei  val mtval = RegInit(UInt(XLEN.W), 0.U)
298d0de7e4aSpeixiaokun  val mtval2 = RegInit(UInt(XLEN.W), 0.U)
299d0de7e4aSpeixiaokun  val mtinst = RegInit(UInt(XLEN.W), 0.U)
300d0de7e4aSpeixiaokun  val mepc = RegInit(UInt(XLEN.W), 0.U)
301e30fd06aSYinan Xu  // Page 36 in riscv-priv: The low bit of mepc (mepc[0]) is always zero.
302e30fd06aSYinan Xu  val mepcMask = ~(0x1.U(XLEN.W))
303c84054caSLinJiawei
304c84054caSLinJiawei  val mie = RegInit(0.U(XLEN.W))
305c84054caSLinJiawei  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
3065dabf2dfSYinan Xu  val mipReg  = RegInit(0.U(XLEN.W))
307d7e392d1Sxuzefan  val mipMask = ZeroExt(Array(
308d7e392d1Sxuzefan    1,  // SSIP
309d7e392d1Sxuzefan    2,  // VSSIP
310d7e392d1Sxuzefan    3,  // MSIP
311d7e392d1Sxuzefan    5,  // STIP
312d7e392d1Sxuzefan    6,  // VSTIP
313d7e392d1Sxuzefan    7,  // MTIP
314d7e392d1Sxuzefan    9,  // SEIP
315d7e392d1Sxuzefan    10, // VSEIP
316d7e392d1Sxuzefan    11, // MEIP
317d7e392d1Sxuzefan    12, // SGEIP
318d7e392d1Sxuzefan  ).map(GenMask(_)).reduce(_ | _), XLEN)
319c84054caSLinJiawei  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
320c84054caSLinJiawei
321d0de7e4aSpeixiaokun  val mip_mie_WMask_H = if(HasHExtension){((1 << 2) | (1 << 6) | (1 << 10) | (1 << 12)).U(XLEN.W)}else{0.U(XLEN.W)}
322d0de7e4aSpeixiaokun  val vssip_Mask = (1 << 2).U(XLEN.W)
323d0de7e4aSpeixiaokun
324d0de7e4aSpeixiaokun  val mipWMask = vssip_Mask | ((1 << 9) | (1 << 5) | (1 << 1)).U(XLEN.W)
32544f8e3e4Speixiaokun  val mieWMask = mip_mie_WMask_H | "haaa".U(XLEN.W)
326d0de7e4aSpeixiaokun
32767ba96b4SYinan Xu  def getMisaMxl(mxl: BigInt): BigInt = mxl << (XLEN - 2)
32867ba96b4SYinan Xu  def getMisaExt(ext: Char): Long = 1 << (ext.toInt - 'a'.toInt)
329c84054caSLinJiawei  var extList = List('a', 's', 'i', 'u')
330c84054caSLinJiawei  if (HasMExtension) { extList = extList :+ 'm' }
331c84054caSLinJiawei  if (HasCExtension) { extList = extList :+ 'c' }
332d0de7e4aSpeixiaokun  if (HasHExtension) { extList = extList :+ 'h' }
333c84054caSLinJiawei  if (HasFPU) { extList = extList ++ List('f', 'd') }
3340ba52110SZiyue Zhang  if (HasVPU) { extList = extList :+ 'v' }
335d0de7e4aSpeixiaokun  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0L)((sum, i) => sum | getMisaExt(i)) //"h8000000000141185".U
33667ba96b4SYinan Xu  val misa = RegInit(UInt(XLEN.W), misaInitVal.U)
337ddb6dcf0SXuan Hu  println(s"[CSR] supported isa ext: $extList")
338bc5ff277Swangkaifan
339c84054caSLinJiawei  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
340c84054caSLinJiawei  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
341c84054caSLinJiawei
34206490c40Speixiaokun  // Machine Configuration
34306490c40Speixiaokun  val menvcfg = RegInit(UInt(XLEN.W), 0.U)
34406490c40Speixiaokun
345c84054caSLinJiawei  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
346e1b773eaSLuo 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
347c84054caSLinJiawei  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
34867ba96b4SYinan Xu  val mhartid = Reg(UInt(XLEN.W)) // the hardware thread running the code
34967ba96b4SYinan Xu  when (RegNext(RegNext(reset.asBool) && !reset.asBool)) {
35067ba96b4SYinan Xu    mhartid := csrio.hartId
35167ba96b4SYinan Xu  }
3527d9edc86SLemover  val mconfigptr = RegInit(UInt(XLEN.W), 0.U) // the read-only pointer pointing to the platform config structure, 0 for not supported.
35362a2cb19SXuan Hu  val mstatus = RegInit("ha00002200".U(XLEN.W))
354bc5ff277Swangkaifan
355c84054caSLinJiawei  // mstatus Value Table
35662a2cb19SXuan Hu  // | sd   | Read Only
35762a2cb19SXuan Hu  // | pad1 | WPRI
358c84054caSLinJiawei  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
359e30fd06aSYinan Xu  // | uxl  | hardlinked to 10
360c84054caSLinJiawei  // | pad0 |
361c84054caSLinJiawei  // | tsr  |
362c84054caSLinJiawei  // | tw   |
3638e7b11e5SWilliam Wang  // | tvm  |
364c84054caSLinJiawei  // | mxr  |
365c84054caSLinJiawei  // | sum  |
366c84054caSLinJiawei  // | mprv |
367c84054caSLinJiawei  // | xs   | 00 |
36880dd83d8SYinan Xu  // | fs   | 01 |
369c84054caSLinJiawei  // | mpp  | 00 |
37062a2cb19SXuan Hu  // | vs   | 01 |
371c84054caSLinJiawei  // | spp  | 0 |
3728e7b11e5SWilliam Wang  // | pie  | 0000 | pie.h is used as UBE
373c84054caSLinJiawei  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
374bc5ff277Swangkaifan
375c84054caSLinJiawei  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
376c84054caSLinJiawei  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
377c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
37862a2cb19SXuan Hu    // Cat(sd, other)
37962a2cb19SXuan Hu    val mstatusNew = Cat(
38062a2cb19SXuan Hu      mstatusOld.xs === ContextStatus.dirty || mstatusOld.fs === ContextStatus.dirty || mstatusOld.vs === ContextStatus.dirty,
38162a2cb19SXuan Hu      mstatus(XLEN-2, 0)
38262a2cb19SXuan Hu    )
383c84054caSLinJiawei    mstatusNew
384c84054caSLinJiawei  }
38585052be5Speixiaokun  def vsstatusUpdateSideEffect(vsstatus: UInt): UInt = {
38685052be5Speixiaokun    val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
38785052be5Speixiaokun    val vsstatusNew = Cat(vsstatusOld.xs === "b11".U || vsstatusOld.fs === "b11".U, vsstatus(XLEN-2, 0))
38885052be5Speixiaokun    vsstatusNew
38985052be5Speixiaokun  }
390e30fd06aSYinan Xu  val mstatusWMask = (~ZeroExt((
391d0de7e4aSpeixiaokun    (if(HasHExtension) {
392d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 40) |
393d0de7e4aSpeixiaokun      GenMask(37, 36)          // MBE SBE
394d0de7e4aSpeixiaokun    } else
39562a2cb19SXuan Hu      GenMask(63)           | // SD is read-only
396e25e4d90SXuan Hu    GenMask(62, 36)      ) | // WPRI
397e30fd06aSYinan Xu    GenMask(35, 32)       | // SXL and UXL cannot be changed
398e30fd06aSYinan Xu    GenMask(31, 23)       | // WPRI
399705cbec3SLemover    GenMask(16, 15)       | // XS is read-only
400443741b9SYinan Xu    GenMask(6)            | // UBE, always little-endian (0)
401d0de7e4aSpeixiaokun    GenMask(2)              // WPRI
402d0de7e4aSpeixiaokun  ), 64)).asUInt
403d0de7e4aSpeixiaokun  val mstatusMask = (~ZeroExt((
404d0de7e4aSpeixiaokun    (if (HasHExtension) {
405d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 40) |
406d0de7e4aSpeixiaokun        GenMask(37, 36) // MBE SBE
407d0de7e4aSpeixiaokun    } else
408d0de7e4aSpeixiaokun      GenMask(XLEN - 2, 36)) | // WPRI
409d0de7e4aSpeixiaokun    GenMask(31, 23)       | // WPRI
410d0de7e4aSpeixiaokun    GenMask(10, 9)        | // WPRI
411d0de7e4aSpeixiaokun    GenMask(6)            | // WPRI
412443741b9SYinan Xu    GenMask(4)            | // WPRI
413443741b9SYinan Xu    GenMask(2)            | // WPRI
414443741b9SYinan Xu    GenMask(0)              // WPRI
4155d669833SYinan Xu  ), 64)).asUInt
4168e7b11e5SWilliam Wang
417c84054caSLinJiawei  val medeleg = RegInit(UInt(XLEN.W), 0.U)
418d0de7e4aSpeixiaokun  val midelegInit = if(HasHExtension){((1 << 12) | (1 << 10) | (1 << 6) | (1 << 2)).U}else{0.U}
419d0de7e4aSpeixiaokun  val medelegWMask = if(HasHExtension) {
420e20ac1e1Sxuzefan    "hf0b7ff".U(XLEN.W)
421d0de7e4aSpeixiaokun  }else {
422d0de7e4aSpeixiaokun    "hb3ff".U(XLEN.W)
423d0de7e4aSpeixiaokun  }
424d0de7e4aSpeixiaokun
425d0de7e4aSpeixiaokun
426d0de7e4aSpeixiaokun  val mideleg = RegInit(UInt(XLEN.W), midelegInit)
427c84054caSLinJiawei  val mscratch = RegInit(UInt(XLEN.W), 0.U)
428c84054caSLinJiawei
429d0de7e4aSpeixiaokun  val midelegWMask = "h222".U(XLEN.W)
430b6982e83SLemover  // PMP Mapping
431ca2f90a6SLemover  val pmp = Wire(Vec(NumPMP, new PMPEntry())) // just used for method parameter
432ca2f90a6SLemover  val pma = Wire(Vec(NumPMA, new PMPEntry())) // just used for method parameter
433ca2f90a6SLemover  val pmpMapping = pmp_gen_mapping(pmp_init, NumPMP, PmpcfgBase, PmpaddrBase, pmp)
434ca2f90a6SLemover  val pmaMapping = pmp_gen_mapping(pma_init, NumPMA, PmacfgBase, PmaaddrBase, pma)
435672c4648Sceba  // !WARNNING: pmp and pma CSRs are not checked in difftest.
436c84054caSLinJiawei
437d0de7e4aSpeixiaokun  // Supervisor-Level CSRs
438c84054caSLinJiawei
43962a2cb19SXuan Hu  val sstatusWNmask: BigInt = (
44062a2cb19SXuan Hu    BigIntGenMask(63)     | // SD is read-only
44162a2cb19SXuan Hu    BigIntGenMask(62, 34) | // WPRI
44262a2cb19SXuan Hu    BigIntGenMask(33, 32) | // UXL is hard-wired to 64(b10)
44362a2cb19SXuan Hu    BigIntGenMask(31, 20) | // WPRI
44462a2cb19SXuan Hu    BigIntGenMask(17)     | // WPRI
44562a2cb19SXuan Hu    BigIntGenMask(16, 15) | // XS is read-only to zero
44662a2cb19SXuan Hu    BigIntGenMask(12, 11) | // WPRI
44762a2cb19SXuan Hu    BigIntGenMask(7)      | // WPRI
44862a2cb19SXuan Hu    BigIntGenMask(6)      | // UBE is always little-endian (0)
44962a2cb19SXuan Hu    BigIntGenMask(4, 2)   | // WPRI
45062a2cb19SXuan Hu    BigIntGenMask(0)        // WPRI
45162a2cb19SXuan Hu  )
45262a2cb19SXuan Hu
45362a2cb19SXuan Hu  val sstatusWmask = BigIntNot(sstatusWNmask).U(XLEN.W)
45462a2cb19SXuan Hu  val sstatusRmask = (
45562a2cb19SXuan Hu    BigIntGenMask(63)     | // SD
45662a2cb19SXuan Hu    BigIntGenMask(33, 32) | // UXL
45762a2cb19SXuan Hu    BigIntGenMask(19)     | // MXR
45862a2cb19SXuan Hu    BigIntGenMask(18)     | // SUM
45962a2cb19SXuan Hu    BigIntGenMask(16, 15) | // XS
46062a2cb19SXuan Hu    BigIntGenMask(14, 13) | // FS
46162a2cb19SXuan Hu    BigIntGenMask(10, 9 ) | // VS
46262a2cb19SXuan Hu    BigIntGenMask(8)      | // SPP
46362a2cb19SXuan Hu    BigIntGenMask(6)      | // UBE: hard wired to 0
46462a2cb19SXuan Hu    BigIntGenMask(5)      | // SPIE
46562a2cb19SXuan Hu    BigIntGenMask(1)
46662a2cb19SXuan Hu  ).U(XLEN.W)
46762a2cb19SXuan Hu
46862a2cb19SXuan Hu  println(s"sstatusWNmask: 0x${sstatusWNmask.toString(16)}")
46962a2cb19SXuan Hu  println(s"sstatusWmask: 0x${sstatusWmask.litValue.toString(16)}")
47062a2cb19SXuan Hu  println(s"sstatusRmask: 0x${sstatusRmask.litValue.toString(16)}")
47162a2cb19SXuan Hu
472a4e57ea3SLi Qianruo  // stvec: {BASE (WARL), MODE (WARL)} where mode is 0 or 1
473a4e57ea3SLi Qianruo  val stvecMask = ~(0x2.U(XLEN.W))
474c84054caSLinJiawei  val stvec = RegInit(UInt(XLEN.W), 0.U)
475c84054caSLinJiawei  // val sie = RegInit(0.U(XLEN.W))
476c84054caSLinJiawei  val sieMask = "h222".U & mideleg
477c84054caSLinJiawei  val sipMask = "h222".U & mideleg
4785dabf2dfSYinan Xu  val sipWMask = "h2".U(XLEN.W) // ssip is writeable in smode
47934230194Sjinyue110  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
480df2b1479SZhangZifei  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
48145f497a4Shappy-lx  // val satpMask = "h80000fffffffffff".U(XLEN.W) // disable asid, mode can only be 8 / 0
48245f497a4Shappy-lx  // TODO: use config to control the length of asid
48345f497a4Shappy-lx  // val satpMask = "h8fffffffffffffff".U(XLEN.W) // enable asid, mode can only be 8 / 0
484705cbec3SLemover  val satpMask = Cat("h8".U(Satp_Mode_len.W), satp_part_wmask(Satp_Asid_len, AsidLength), satp_part_wmask(Satp_Addr_len, PAddrBits-12))
485c84054caSLinJiawei  val sepc = RegInit(UInt(XLEN.W), 0.U)
486e30fd06aSYinan Xu  // Page 60 in riscv-priv: The low bit of sepc (sepc[0]) is always zero.
487e30fd06aSYinan Xu  val sepcMask = ~(0x1.U(XLEN.W))
488c84054caSLinJiawei  val scause = RegInit(UInt(XLEN.W), 0.U)
489d0de7e4aSpeixiaokun  val stval = RegInit(UInt(XLEN.W), 0.U)
490c84054caSLinJiawei  val sscratch = RegInit(UInt(XLEN.W), 0.U)
491c84054caSLinJiawei  val scounteren = RegInit(UInt(XLEN.W), 0.U)
4926ade72d9Sxuzefan  val senvcfg = RegInit(UInt(XLEN.W), 0.U)  // !WARNING: there is no logic about this CSR.
493e4b1ccacSxuzefan  // Currently, XiangShan don't support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
494e4b1ccacSxuzefan  val scounterenMask = 0.U(XLEN.W)
495fcff7e94SZhangZifei
496eedc2e58SSteve Gou  // sbpctl
497eedc2e58SSteve Gou  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
498eedc2e58SSteve Gou  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
499eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
500eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
501eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
502eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
503eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
504eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
505eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
5062b8b2e7aSWilliam Wang
507ecccf78fSJay  // spfctl Bit 0: L1I Cache Prefetcher Enable
5082b8b2e7aSWilliam Wang  // spfctl Bit 1: L2Cache Prefetcher Enable
50985de5caeSLinJiawei  // spfctl Bit 2: L1D Cache Prefetcher Enable
51085de5caeSLinJiawei  // spfctl Bit 3: L1D train prefetch on hit
51185de5caeSLinJiawei  // spfctl Bit 4: L1D prefetch enable agt
51285de5caeSLinJiawei  // spfctl Bit 5: L1D prefetch enable pht
513c65495a4SLinJiawei  // spfctl Bit [9:6]: L1D prefetch active page threshold
514c65495a4SLinJiawei  // spfctl Bit [15:10]: L1D prefetch active page stride
5155d13017eSLinJiawei  // turn off L2 BOP, turn on L1 SMS by default
516c65495a4SLinJiawei  val spfctl = RegInit(UInt(XLEN.W), Seq(
517edbf1204SLinJiawei    0 << 17,    // L2 pf store only [17] init: false
518edbf1204SLinJiawei    1 << 16,    // L1D pf enable stride [16] init: true
519f1d78cf7SLinJiawei    30 << 10,   // L1D active page stride [15:10] init: 30
520f1d78cf7SLinJiawei    12 << 6,    // L1D active page threshold [9:6] init: 12
521f1d78cf7SLinJiawei    1  << 5,    // L1D enable pht [5] init: true
522f1d78cf7SLinJiawei    1  << 4,    // L1D enable agt [4] init: true
523f1d78cf7SLinJiawei    0  << 3,    // L1D train on hit [3] init: false
524f1d78cf7SLinJiawei    1  << 2,    // L1D pf enable [2] init: true
525f1d78cf7SLinJiawei    1  << 1,    // L2 pf enable [1] init: true
526f1d78cf7SLinJiawei    1  << 0,    // L1I pf enable [0] init: true
527c65495a4SLinJiawei  ).reduce(_|_).U(XLEN.W))
528ecccf78fSJay  csrio.customCtrl.l1I_pf_enable := spfctl(0)
52935a47a38SYinan Xu  csrio.customCtrl.l2_pf_enable := spfctl(1)
53085de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable := spfctl(2)
53185de5caeSLinJiawei  csrio.customCtrl.l1D_pf_train_on_hit := spfctl(3)
53285de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable_agt := spfctl(4)
53385de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable_pht := spfctl(5)
5345d13017eSLinJiawei  csrio.customCtrl.l1D_pf_active_threshold := spfctl(9, 6)
535c65495a4SLinJiawei  csrio.customCtrl.l1D_pf_active_stride := spfctl(15, 10)
536edbf1204SLinJiawei  csrio.customCtrl.l1D_pf_enable_stride := spfctl(16)
537edbf1204SLinJiawei  csrio.customCtrl.l2_pf_store_only := spfctl(17)
5382b8b2e7aSWilliam Wang
539ecccf78fSJay  // sfetchctl Bit 0: L1I Cache Parity check enable
540ecccf78fSJay  val sfetchctl = RegInit(UInt(XLEN.W), "b0".U)
541ecccf78fSJay  csrio.customCtrl.icache_parity_enable := sfetchctl(0)
542ecccf78fSJay
5432b8b2e7aSWilliam Wang  // sdsid: Differentiated Services ID
5442b8b2e7aSWilliam Wang  val sdsid = RegInit(UInt(XLEN.W), 0.U)
54535a47a38SYinan Xu  csrio.customCtrl.dsid := sdsid
54635a47a38SYinan Xu
5472b8b2e7aSWilliam Wang  // slvpredctl: load violation predict settings
5486ef4f6f6SYinan Xu  // Default reset period: 2^16
5496ef4f6f6SYinan Xu  // Why this number: reset more frequently while keeping the overhead low
5506ef4f6f6SYinan Xu  // Overhead: extra two redirections in every 64K cycles => ~0.1% overhead
551560b69b7SHaojin Tang  val slvpredctl = Reg(UInt(XLEN.W))
552560b69b7SHaojin Tang  when(reset.asBool) {
553560b69b7SHaojin Tang    slvpredctl := Constantin.createRecord("slvpredctl", "h60".U)
554560b69b7SHaojin Tang  }
5552b8b2e7aSWilliam Wang  csrio.customCtrl.lvpred_disable := slvpredctl(0)
5562b8b2e7aSWilliam Wang  csrio.customCtrl.no_spec_load := slvpredctl(1)
557c7160cd3SWilliam Wang  csrio.customCtrl.storeset_wait_store := slvpredctl(2)
558c7160cd3SWilliam Wang  csrio.customCtrl.storeset_no_fast_wakeup := slvpredctl(3)
559c7160cd3SWilliam Wang  csrio.customCtrl.lvpred_timeout := slvpredctl(8, 4)
5602b8b2e7aSWilliam Wang
561f3f22d72SYinan Xu  //  smblockctl: memory block configurations
56237225120Ssfencevma  //  +------------------------------+---+----+----+-----+--------+
56337225120Ssfencevma  //  |XLEN-1                       8| 7 | 6  | 5  |  4  |3      0|
56437225120Ssfencevma  //  +------------------------------+---+----+----+-----+--------+
56537225120Ssfencevma  //  |           Reserved           | O | CE | SP | LVC |   Th   |
56637225120Ssfencevma  //  +------------------------------+---+----+----+-----+--------+
56737225120Ssfencevma  //  Description:
56837225120Ssfencevma  //  Bit 3-0   : Store buffer flush threshold (Th).
56937225120Ssfencevma  //  Bit 4     : Enable load violation check after reset (LVC).
57037225120Ssfencevma  //  Bit 5     : Enable soft-prefetch after reset (SP).
57137225120Ssfencevma  //  Bit 6     : Enable cache error after reset (CE).
57237225120Ssfencevma  //  Bit 7     : Enable uncache write outstanding (O).
57337225120Ssfencevma  //  Others    : Reserved.
57437225120Ssfencevma
57567682d05SWilliam Wang  val smblockctl_init_val =
57667ba96b4SYinan Xu    (0xf & StoreBufferThreshold) |
57767ba96b4SYinan Xu    (EnableLdVioCheckAfterReset.toInt << 4) |
57867ba96b4SYinan Xu    (EnableSoftPrefetchAfterReset.toInt << 5) |
579dcfaba1dSczw    (EnableCacheErrorAfterReset.toInt << 6) |
58067ba96b4SYinan Xu    (EnableUncacheWriteOutstanding.toInt << 7)
58167ba96b4SYinan Xu  val smblockctl = RegInit(UInt(XLEN.W), smblockctl_init_val.U)
582f3f22d72SYinan Xu  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
58367682d05SWilliam Wang  // bits 4: enable load load violation check
584a4e57ea3SLi Qianruo  csrio.customCtrl.ldld_vio_check_enable := smblockctl(4)
585a4e57ea3SLi Qianruo  csrio.customCtrl.soft_prefetch_enable := smblockctl(5)
586a4e57ea3SLi Qianruo  csrio.customCtrl.cache_error_enable := smblockctl(6)
58737225120Ssfencevma  csrio.customCtrl.uncache_write_outstanding_enable := smblockctl(7)
588a4e57ea3SLi Qianruo
589a4e57ea3SLi Qianruo  println("CSR smblockctl init value:")
590a4e57ea3SLi Qianruo  println("  Store buffer replace threshold: " + StoreBufferThreshold)
591a4e57ea3SLi Qianruo  println("  Enable ld-ld vio check after reset: " + EnableLdVioCheckAfterReset)
592a4e57ea3SLi Qianruo  println("  Enable soft prefetch after reset: " + EnableSoftPrefetchAfterReset)
593a4e57ea3SLi Qianruo  println("  Enable cache error after reset: " + EnableCacheErrorAfterReset)
59437225120Ssfencevma  println("  Enable uncache write outstanding: " + EnableUncacheWriteOutstanding)
595f3f22d72SYinan Xu
5965b47c58cSYinan Xu  val srnctl = RegInit(UInt(XLEN.W), "h7".U)
5975b47c58cSYinan Xu  csrio.customCtrl.fusion_enable := srnctl(0)
598af2f7849Shappy-lx  csrio.customCtrl.svinval_enable := srnctl(1)
5995b47c58cSYinan Xu  csrio.customCtrl.wfi_enable := srnctl(2)
600aac4464eSYinan Xu
601d0de7e4aSpeixiaokun  // Hypervisor CSRs
602d0de7e4aSpeixiaokun  val hstatusWMask = "h7003c0".U(XLEN.W)
603d0de7e4aSpeixiaokun  // hstatus: vtsr, vtw, vtvm, hu, spvp, spv, gva,
604d0de7e4aSpeixiaokun  val hstatus = RegInit("h200000000".U(XLEN.W))
605d0de7e4aSpeixiaokun  val hstatusStruct = hstatus.asTypeOf(new HstatusStruct)
606d0de7e4aSpeixiaokun  val hedeleg = RegInit(UInt(XLEN.W), 0.U)
607d0de7e4aSpeixiaokun  val hideleg = RegInit(UInt(XLEN.W), 0.U)
608d0de7e4aSpeixiaokun  val hidelegRMask = mideleg
609d0de7e4aSpeixiaokun  val hidelegWMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
610d0de7e4aSpeixiaokun  val hgeie   = RegInit(UInt(XLEN.W), 0.U)
611d0de7e4aSpeixiaokun  val htval = RegInit(UInt(XLEN.W), 0.U)
612d0de7e4aSpeixiaokun  // hvip hip hie is part of mip or mie
613d0de7e4aSpeixiaokun  val hvipMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
614d0de7e4aSpeixiaokun  val hipRMask = (((1 << 12).U | hvipMask) & mideleg)
615d0de7e4aSpeixiaokun  val hipWMask = ((1 << 2).U & mideleg)// vssip
616d0de7e4aSpeixiaokun  val hieMask = hipRMask
617d0de7e4aSpeixiaokun  val htinst = RegInit(UInt(XLEN.W), 0.U)
618d0de7e4aSpeixiaokun  val hgeip = RegInit(UInt(XLEN.W), 0.U)
619d0de7e4aSpeixiaokun  val henvcfg = RegInit(UInt(XLEN.W), 0.U)
620d0de7e4aSpeixiaokun  val hgatp = RegInit(UInt(XLEN.W), 0.U)
621d0de7e4aSpeixiaokun  val hgatpMask = Cat("h8".U(Hgatp_Mode_len.W), satp_part_wmask(Hgatp_Vmid_len, VmidLength), satp_part_wmask(Hgatp_Addr_len, PAddrBits-12))
622d0de7e4aSpeixiaokun  val htimedelta = RegInit(UInt(XLEN.W), 0.U)
623d0de7e4aSpeixiaokun  val hcounteren = RegInit(UInt(XLEN.W), 0.U)
624e4b1ccacSxuzefan  // Currently, XiangShan don't support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
625e4b1ccacSxuzefan  val hcounterenMask = 0.U(XLEN.W)
626d0de7e4aSpeixiaokun
627f2a38010Sxuzefan  val vsstatus = RegInit("h200002000".U(XLEN.W))
628d0de7e4aSpeixiaokun  val vsstatusStruct = vsstatus.asTypeOf(new MstatusStruct)
629d0de7e4aSpeixiaokun  //vsie vsip
630d0de7e4aSpeixiaokun  val vsMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
631d0de7e4aSpeixiaokun  val vsip_ie_Mask = ZeroExt((hideleg & mideleg & vsMask), XLEN)
632d0de7e4aSpeixiaokun  val vsip_WMask = ZeroExt((hideleg & mideleg & vssip_Mask), XLEN)
633d0de7e4aSpeixiaokun  val vstvec = RegInit(UInt(XLEN.W), 0.U)
634d0de7e4aSpeixiaokun  val vsscratch = RegInit(UInt(XLEN.W), 0.U)
635d0de7e4aSpeixiaokun  val vsepc = RegInit(UInt(XLEN.W), 0.U)
636d0de7e4aSpeixiaokun  val vscause = RegInit(UInt(XLEN.W), 0.U)
637d0de7e4aSpeixiaokun  val vstval = RegInit(UInt(XLEN.W), 0.U)
638d0de7e4aSpeixiaokun  val vsatp = RegInit(UInt(XLEN.W), 0.U)
6392b8b2e7aSWilliam Wang  val tlbBundle = Wire(new TlbCsrBundle)
64045f497a4Shappy-lx  tlbBundle.satp.apply(satp)
641d0de7e4aSpeixiaokun  tlbBundle.vsatp.apply(vsatp)
642d0de7e4aSpeixiaokun  tlbBundle.hgatp.apply(hgatp)
6432b8b2e7aSWilliam Wang  csrio.tlb := tlbBundle
6442b8b2e7aSWilliam Wang
645c84054caSLinJiawei  // User-Level CSRs
646c84054caSLinJiawei  val uepc = Reg(UInt(XLEN.W))
647c84054caSLinJiawei
648c84054caSLinJiawei  // fcsr
649c84054caSLinJiawei  class FcsrStruct extends Bundle {
650c84054caSLinJiawei    val reserved = UInt((XLEN-3-5).W)
651c84054caSLinJiawei    val frm = UInt(3.W)
652c84054caSLinJiawei    val fflags = UInt(5.W)
653c84054caSLinJiawei    assert(this.getWidth == XLEN)
654c84054caSLinJiawei  }
655c84054caSLinJiawei  val fcsr = RegInit(0.U(XLEN.W))
656c84054caSLinJiawei  // set mstatus->sd and mstatus->fs when true
657c84054caSLinJiawei  val csrw_dirty_fp_state = WireInit(false.B)
658c84054caSLinJiawei
659c84054caSLinJiawei  def frm_wfn(wdata: UInt): UInt = {
660c84054caSLinJiawei    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
661c84054caSLinJiawei    csrw_dirty_fp_state := true.B
662c84054caSLinJiawei    fcsrOld.frm := wdata(2,0)
6635d669833SYinan Xu    fcsrOld.asUInt
664c84054caSLinJiawei  }
665c84054caSLinJiawei  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
666c84054caSLinJiawei
6677132faa5SLinJiawei  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
6687132faa5SLinJiawei    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
6697132faa5SLinJiawei    val fcsrNew = WireInit(fcsrOld)
6707132faa5SLinJiawei    if (update) {
6717132faa5SLinJiawei      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
6727132faa5SLinJiawei    } else {
6737132faa5SLinJiawei      fcsrNew.fflags := wdata(4,0)
6747132faa5SLinJiawei    }
6755d669833SYinan Xu    fcsrNew.asUInt
676c84054caSLinJiawei  }
677c84054caSLinJiawei  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
678c84054caSLinJiawei
679c84054caSLinJiawei  def fcsr_wfn(wdata: UInt): UInt = {
680c84054caSLinJiawei    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
681c84054caSLinJiawei    csrw_dirty_fp_state := true.B
682c84054caSLinJiawei    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
683c84054caSLinJiawei  }
684c84054caSLinJiawei
685c84054caSLinJiawei  val fcsrMapping = Map(
6867132faa5SLinJiawei    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
687c84054caSLinJiawei    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
688c84054caSLinJiawei    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
689c84054caSLinJiawei  )
690c84054caSLinJiawei
6910ba52110SZiyue Zhang  // Vector extension CSRs
6927f733d3dSxiaofeibao-xjtu  val vstart = RegInit(0.U(XLEN.W))
6930ba52110SZiyue Zhang  val vcsr = RegInit(0.U(XLEN.W))
6940ba52110SZiyue Zhang  val vl = Reg(UInt(XLEN.W))
6950ba52110SZiyue Zhang  val vtype = Reg(UInt(XLEN.W))
696*5f28e666Schengguanghui  val vlenb = RegInit(VDataBytes.U(XLEN.W))
697daa01159SZiyue Zhang
698daa01159SZiyue Zhang  // set mstatus->sd and mstatus->vs when true
699daa01159SZiyue Zhang  val csrw_dirty_vs_state = WireInit(false.B)
7000ba52110SZiyue Zhang
7010ba52110SZiyue Zhang  // vcsr is mapped to vxrm and vxsat
7020ba52110SZiyue Zhang  class VcsrStruct extends Bundle {
7030ba52110SZiyue Zhang    val reserved = UInt((XLEN-3).W)
7040ba52110SZiyue Zhang    val vxrm = UInt(2.W)
7050ba52110SZiyue Zhang    val vxsat = UInt(1.W)
7060ba52110SZiyue Zhang    assert(this.getWidth == XLEN)
7070ba52110SZiyue Zhang  }
7080ba52110SZiyue Zhang
7090ba52110SZiyue Zhang  def vxrm_wfn(wdata: UInt): UInt = {
7100ba52110SZiyue Zhang    val vcsrOld = WireInit(vcsr.asTypeOf(new VcsrStruct))
711daa01159SZiyue Zhang    csrw_dirty_vs_state := true.B
7120ba52110SZiyue Zhang    vcsrOld.vxrm := wdata(1,0)
7130ba52110SZiyue Zhang    vcsrOld.asUInt
7140ba52110SZiyue Zhang  }
7150ba52110SZiyue Zhang  def vxrm_rfn(rdata: UInt): UInt = rdata(2,1)
7160ba52110SZiyue Zhang
7176355a2b7Sczw  def vxsat_wfn(update: Boolean)(wdata: UInt): UInt = {
7180ba52110SZiyue Zhang    val vcsrOld = WireInit(vcsr.asTypeOf(new VcsrStruct))
7196355a2b7Sczw    val vcsrNew = WireInit(vcsrOld)
720daa01159SZiyue Zhang    csrw_dirty_vs_state := true.B
7216355a2b7Sczw    if (update) {
7226355a2b7Sczw      vcsrNew.vxsat := wdata(0) | vcsrOld.vxsat
7236355a2b7Sczw    } else {
7246355a2b7Sczw      vcsrNew.vxsat := wdata(0)
7256355a2b7Sczw    }
7266355a2b7Sczw    vcsrNew.asUInt
7270ba52110SZiyue Zhang  }
7280ba52110SZiyue Zhang  def vxsat_rfn(rdata: UInt): UInt = rdata(0)
7290ba52110SZiyue Zhang
7300ba52110SZiyue Zhang  def vcsr_wfn(wdata: UInt): UInt = {
7310ba52110SZiyue Zhang    val vcsrOld = WireInit(vcsr.asTypeOf(new VcsrStruct))
732daa01159SZiyue Zhang    csrw_dirty_vs_state := true.B
7330ba52110SZiyue Zhang    vcsrOld.vxrm := wdata.asTypeOf(vcsrOld).vxrm
7340ba52110SZiyue Zhang    vcsrOld.vxsat := wdata.asTypeOf(vcsrOld).vxsat
7350ba52110SZiyue Zhang    vcsrOld.asUInt
7360ba52110SZiyue Zhang  }
7370ba52110SZiyue Zhang
7380ba52110SZiyue Zhang  val vcsrMapping = Map(
7390ba52110SZiyue Zhang    MaskedRegMap(Vstart, vstart),
7400ba52110SZiyue Zhang    MaskedRegMap(Vxrm, vcsr, wfn = vxrm_wfn, rfn = vxrm_rfn),
7416355a2b7Sczw    MaskedRegMap(Vxsat, vcsr, wfn = vxsat_wfn(false), rfn = vxsat_rfn),
7420ba52110SZiyue Zhang    MaskedRegMap(Vcsr, vcsr, wfn = vcsr_wfn),
7430ba52110SZiyue Zhang    MaskedRegMap(Vl, vl),
74435d1557aSZiyue Zhang    MaskedRegMap(Vtype, vtype),
74535d1557aSZiyue Zhang    MaskedRegMap(Vlenb, vlenb),
7460ba52110SZiyue Zhang  )
7470ba52110SZiyue Zhang
748321934c7SKunlin You  // Hart Privilege Mode
749321934c7SKunlin You  val privilegeMode = RegInit(UInt(2.W), ModeM)
750c84054caSLinJiawei
751cd365d4cSrvcoresjw  //val perfEventscounten = List.fill(nrPerfCnts)(RegInit(false(Bool())))
7528635f18fSwangkaifan  // Perf Counter
7538635f18fSwangkaifan  val nrPerfCnts = 29  // 3...31
754321934c7SKunlin You  val privilegeModeOH = UIntToOH(privilegeMode)
755cd365d4cSrvcoresjw  val perfEventscounten = RegInit(0.U.asTypeOf(Vec(nrPerfCnts, Bool())))
7568635f18fSwangkaifan  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
7578c7b0b2fSrvcoresjw  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
75812c44ce5Srvcoresjw                   List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
75912c44ce5Srvcoresjw                   List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
76012c44ce5Srvcoresjw                   List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
761cd365d4cSrvcoresjw  for (i <-0 until nrPerfCnts) {
762321934c7SKunlin You    perfEventscounten(i) := (perfEvents(i)(63,60) & privilegeModeOH).orR
763cd365d4cSrvcoresjw  }
764cd365d4cSrvcoresjw
7651ca0e4f3SYinan Xu  val hpmEvents = Wire(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
766cd365d4cSrvcoresjw  for (i <- 0 until numPCntHc * coreParams.L2NBanks) {
7671ca0e4f3SYinan Xu    hpmEvents(i) := csrio.perf.perfEventsHc(i)
768cd365d4cSrvcoresjw  }
769cd365d4cSrvcoresjw
7709a128342SHaoyuan Feng  // print perfEvents
7719a128342SHaoyuan Feng  val allPerfEvents = hpmEvents.map(x => (s"Hc", x.value))
7729a128342SHaoyuan Feng  if (printEventCoding) {
7739a128342SHaoyuan Feng    for (((name, inc), i) <- allPerfEvents.zipWithIndex) {
7749a128342SHaoyuan Feng      println("CSR perfEvents Set", name, inc, i)
7759a128342SHaoyuan Feng    }
7769a128342SHaoyuan Feng  }
7779a128342SHaoyuan Feng
77812c44ce5Srvcoresjw  val csrevents = perfEvents.slice(24, 29)
7791ca0e4f3SYinan Xu  val hpm_hc = HPerfMonitor(csrevents, hpmEvents)
7808635f18fSwangkaifan  val mcountinhibit = RegInit(0.U(XLEN.W))
781b03ddc86Swangkaifan  val mcycle = RegInit(0.U(XLEN.W))
782b03ddc86Swangkaifan  mcycle := mcycle + 1.U
783b03ddc86Swangkaifan  val minstret = RegInit(0.U(XLEN.W))
7841ca0e4f3SYinan Xu  val perf_events = csrio.perf.perfEventsFrontend ++
7851ca0e4f3SYinan Xu                    csrio.perf.perfEventsCtrl ++
7861ca0e4f3SYinan Xu                    csrio.perf.perfEventsLsu ++
7871ca0e4f3SYinan Xu                    hpm_hc.getPerf
788b03ddc86Swangkaifan  minstret := minstret + RegNext(csrio.perf.retiredInstr)
7895fd90906Srvcoresjw  for(i <- 0 until 29){
7901ca0e4f3SYinan Xu    perfCnts(i) := Mux(mcountinhibit(i+3) | !perfEventscounten(i), perfCnts(i), perfCnts(i) + perf_events(i).value)
7915fd90906Srvcoresjw  }
7928635f18fSwangkaifan
793c84054caSLinJiawei  // CSR reg map
79421fa8708Swangkaifan  val basicPrivMapping = Map(
795c84054caSLinJiawei
796f7af4c74Schengguanghui    // Unprivileged Floating-Point CSRs
797f7af4c74Schengguanghui    // Has been mapped above
798c84054caSLinJiawei
799e4b1ccacSxuzefan    // TODO: support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
800f7af4c74Schengguanghui    // Unprivileged Counter/Timers
801f7af4c74Schengguanghui    MaskedRegMap(Cycle, mcycle),
802f7af4c74Schengguanghui    // We don't support read time CSR.
803f7af4c74Schengguanghui    // MaskedRegMap(Time, mtime),
804f7af4c74Schengguanghui    MaskedRegMap(Instret, minstret),
805c84054caSLinJiawei
80621fa8708Swangkaifan    //--- Supervisor Trap Setup ---
807c84054caSLinJiawei    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
808c84054caSLinJiawei    // MaskedRegMap(Sedeleg, Sedeleg),
809c84054caSLinJiawei    // MaskedRegMap(Sideleg, Sideleg),
810c84054caSLinJiawei    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
811a4e57ea3SLi Qianruo    MaskedRegMap(Stvec, stvec, stvecMask, MaskedRegMap.NoSideEffect, stvecMask),
812e4b1ccacSxuzefan    MaskedRegMap(Scounteren, scounteren, scounterenMask),
813c84054caSLinJiawei
8146ade72d9Sxuzefan    //--- Supervisor Configuration ---
8156ade72d9Sxuzefan    MaskedRegMap(Senvcfg, senvcfg),
8166ade72d9Sxuzefan
81721fa8708Swangkaifan    //--- Supervisor Trap Handling ---
818c84054caSLinJiawei    MaskedRegMap(Sscratch, sscratch),
819e30fd06aSYinan Xu    MaskedRegMap(Sepc, sepc, sepcMask, MaskedRegMap.NoSideEffect, sepcMask),
820c84054caSLinJiawei    MaskedRegMap(Scause, scause),
821c84054caSLinJiawei    MaskedRegMap(Stval, stval),
8225390caa7Speixiaokun    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask, x => (mipWire.asUInt | x) & sipMask),
823c84054caSLinJiawei
82421fa8708Swangkaifan    //--- Supervisor Protection and Translation ---
825c5334b11SZhangZifei    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
826c84054caSLinJiawei
82735a47a38SYinan Xu    //--- Supervisor Custom Read/Write Registers
828eedc2e58SSteve Gou    MaskedRegMap(Sbpctl, sbpctl),
82935a47a38SYinan Xu    MaskedRegMap(Spfctl, spfctl),
830ecccf78fSJay    MaskedRegMap(Sfetchctl, sfetchctl),
83135a47a38SYinan Xu    MaskedRegMap(Sdsid, sdsid),
8322b8b2e7aSWilliam Wang    MaskedRegMap(Slvpredctl, slvpredctl),
833f3f22d72SYinan Xu    MaskedRegMap(Smblockctl, smblockctl),
834aac4464eSYinan Xu    MaskedRegMap(Srnctl, srnctl),
83535a47a38SYinan Xu
83621fa8708Swangkaifan    //--- Machine Information Registers ---
8375dabf2dfSYinan Xu    MaskedRegMap(Mvendorid, mvendorid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8385dabf2dfSYinan Xu    MaskedRegMap(Marchid, marchid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8395dabf2dfSYinan Xu    MaskedRegMap(Mimpid, mimpid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8405dabf2dfSYinan Xu    MaskedRegMap(Mhartid, mhartid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8417d9edc86SLemover    MaskedRegMap(Mconfigptr, mconfigptr, 0.U(XLEN.W), MaskedRegMap.Unwritable),
842c84054caSLinJiawei
84306490c40Speixiaokun    //--- Machine Configuration Registers ---
84406490c40Speixiaokun    MaskedRegMap(Menvcfg, menvcfg),
84506490c40Speixiaokun
84621fa8708Swangkaifan    //--- Machine Trap Setup ---
847443741b9SYinan Xu    MaskedRegMap(Mstatus, mstatus, mstatusWMask, mstatusUpdateSideEffect),
8485e4ec482SWilliam Wang    MaskedRegMap(Misa, misa, 0.U, MaskedRegMap.Unwritable), // now whole misa is unchangeable
849d0de7e4aSpeixiaokun    MaskedRegMap(Medeleg, medeleg, medelegWMask),
850b436d3b6Speixiaokun    MaskedRegMap(Mideleg, mideleg, midelegWMask),
851b436d3b6Speixiaokun    MaskedRegMap(Mie, mie, mieWMask),
852a4e57ea3SLi Qianruo    MaskedRegMap(Mtvec, mtvec, mtvecMask, MaskedRegMap.NoSideEffect, mtvecMask),
853e4b1ccacSxuzefan    MaskedRegMap(Mcounteren, mcounteren, mcounterenMask),
854c84054caSLinJiawei
85521fa8708Swangkaifan    //--- Machine Trap Handling ---
856c84054caSLinJiawei    MaskedRegMap(Mscratch, mscratch),
857e30fd06aSYinan Xu    MaskedRegMap(Mepc, mepc, mepcMask, MaskedRegMap.NoSideEffect, mepcMask),
858c84054caSLinJiawei    MaskedRegMap(Mcause, mcause),
859c84054caSLinJiawei    MaskedRegMap(Mtval, mtval),
8605390caa7Speixiaokun    MaskedRegMap(Mip, mipReg.asUInt, mipWMask, MaskedRegMap.NoSideEffect, mipMask, x => (mipWire.asUInt | x) & mipMask),
8616ade72d9Sxuzefan
86272951335SLi Qianruo    //--- Trigger ---
863716f717fSLi Qianruo    MaskedRegMap(Tselect, tselectPhy, WritableMask, WriteTselect),
864f7af4c74Schengguanghui    // Todo: support chain length = 2
865f7af4c74Schengguanghui    MaskedRegMap(Tdata1, tdata1RegVec(tselectPhy),
866f7af4c74Schengguanghui      WritableMask,
867f7af4c74Schengguanghui      x => Tdata1Bundle.Write(x, tdata1RegVec(tselectPhy), newTriggerChainIsLegal, debug_mode = debugMode),
868f7af4c74Schengguanghui      WritableMask,
869f7af4c74Schengguanghui      x => Tdata1Bundle.Read(x)),
870f7af4c74Schengguanghui    MaskedRegMap(Tdata2, tdata2RegVec(tselectPhy)),
871716f717fSLi Qianruo    MaskedRegMap(Tinfo, tinfo, 0.U(XLEN.W), MaskedRegMap.Unwritable),
87272951335SLi Qianruo
873d4aca96cSlqre    //--- Debug Mode ---
874d4aca96cSlqre    MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
875d4aca96cSlqre    MaskedRegMap(Dpc, dpc),
876f7af4c74Schengguanghui    MaskedRegMap(Dscratch0, dscratch0),
87712c44ce5Srvcoresjw    MaskedRegMap(Dscratch1, dscratch1),
878b03ddc86Swangkaifan    MaskedRegMap(Mcountinhibit, mcountinhibit),
879b03ddc86Swangkaifan    MaskedRegMap(Mcycle, mcycle),
880b03ddc86Swangkaifan    MaskedRegMap(Minstret, minstret),
881b03ddc86Swangkaifan  )
88212c44ce5Srvcoresjw
883d0de7e4aSpeixiaokun  // hypervisor csr map
884d0de7e4aSpeixiaokun  val hcsrMapping = Map(
885d0de7e4aSpeixiaokun    //--- Hypervisor Trap Setup ---
886d0de7e4aSpeixiaokun    MaskedRegMap(Hstatus, hstatus, hstatusWMask),
887d0de7e4aSpeixiaokun    MaskedRegMap(Hedeleg, hedeleg),
888d0de7e4aSpeixiaokun    MaskedRegMap(Hideleg, hideleg, hidelegWMask, MaskedRegMap.NoSideEffect, hidelegRMask),
889d0de7e4aSpeixiaokun    MaskedRegMap(Hie, mie, hieMask, MaskedRegMap.NoSideEffect, hieMask),
890cc063a70Speixiaokun    MaskedRegMap(Hcounteren, hcounteren, hcounterenMask),
891d0de7e4aSpeixiaokun    MaskedRegMap(Hgeie, hgeie),
892d0de7e4aSpeixiaokun
893d0de7e4aSpeixiaokun    //--- Hypervisor Trap Handling ---
894d0de7e4aSpeixiaokun    MaskedRegMap(Htval, htval),
8955390caa7Speixiaokun    MaskedRegMap(Hip, mipReg.asUInt, hipWMask, MaskedRegMap.NoSideEffect, hipRMask, x => (mipWire.asUInt | x) & hipRMask),
8965390caa7Speixiaokun    MaskedRegMap(Hvip, mipReg.asUInt, hvipMask, MaskedRegMap.NoSideEffect, hvipMask, x => (mipWire.asUInt | x) & hvipMask),
897d0de7e4aSpeixiaokun    MaskedRegMap(Htinst, htinst),
898d0de7e4aSpeixiaokun    MaskedRegMap(Hgeip, hgeip),
899d0de7e4aSpeixiaokun
900d0de7e4aSpeixiaokun    //--- Hypervisor Configuration ---
901d0de7e4aSpeixiaokun    MaskedRegMap(Henvcfg, henvcfg),
902d0de7e4aSpeixiaokun
903d0de7e4aSpeixiaokun    //--- Hypervisor Protection and Translation ---
904a1d4b4bfSpeixiaokun    MaskedRegMap(Hgatp, hgatp, hgatpMask, MaskedRegMap.NoSideEffect, hgatpMask),
905d0de7e4aSpeixiaokun
906d0de7e4aSpeixiaokun    //--- Hypervisor Counter/Timer Virtualization Registers ---
907d0de7e4aSpeixiaokun    MaskedRegMap(Htimedelta, htimedelta),
908d0de7e4aSpeixiaokun
909d0de7e4aSpeixiaokun    //--- Virtual Supervisor Registers ---
91085052be5Speixiaokun    MaskedRegMap(Vsstatus, vsstatus, rmask = sstatusRmask, wmask = sstatusWmask, wfn = vsstatusUpdateSideEffect),
911d0de7e4aSpeixiaokun    MaskedRegMap(Vsie, mie, rmask = vsip_ie_Mask, wmask = vsip_ie_Mask),
912d0de7e4aSpeixiaokun    MaskedRegMap(Vstvec, vstvec),
913d0de7e4aSpeixiaokun    MaskedRegMap(Vsscratch, vsscratch),
914d0de7e4aSpeixiaokun    MaskedRegMap(Vsepc, vsepc),
915d0de7e4aSpeixiaokun    MaskedRegMap(Vscause, vscause),
916d0de7e4aSpeixiaokun    MaskedRegMap(Vstval, vstval),
917d7e392d1Sxuzefan    MaskedRegMap(Vsip, mipReg.asUInt, vsip_WMask, MaskedRegMap.NoSideEffect, vsip_ie_Mask, x => mipWire.asUInt | x),
918d0de7e4aSpeixiaokun    MaskedRegMap(Vsatp, vsatp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
919d0de7e4aSpeixiaokun
920d0de7e4aSpeixiaokun    //--- Machine Registers ---
921d0de7e4aSpeixiaokun    MaskedRegMap(Mtval2, mtval2),
922d0de7e4aSpeixiaokun    MaskedRegMap(Mtinst, mtinst),
923d0de7e4aSpeixiaokun  )
924d0de7e4aSpeixiaokun
92512c44ce5Srvcoresjw  val perfCntMapping = (0 until 29).map(i => {Map(
92612c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmevent3 +i,
92712c44ce5Srvcoresjw                 reg  = perfEvents(i),
92812c44ce5Srvcoresjw                 wmask = "hf87fff3fcff3fcff".U(XLEN.W)),
92912c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmcounter3 +i,
930f7af4c74Schengguanghui                 reg = perfCnts(i)),
931f7af4c74Schengguanghui    MaskedRegMap(addr = Hpmcounter3 + i,
93212c44ce5Srvcoresjw                 reg  = perfCnts(i))
93312c44ce5Srvcoresjw  )}).fold(Map())((a,b) => a ++ b)
9346d96ebcdSwakafa  // TODO: mechanism should be implemented later
9356d96ebcdSwakafa  // val MhpmcounterStart = Mhpmcounter3
9366d96ebcdSwakafa  // val MhpmeventStart   = Mhpmevent3
9376d96ebcdSwakafa  // for (i <- 0 until nrPerfCnts) {
9386d96ebcdSwakafa  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
9396d96ebcdSwakafa  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
9406d96ebcdSwakafa  // }
9418635f18fSwangkaifan
942e19f7967SWilliam Wang  val cacheopRegs = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
943e19f7967SWilliam Wang    name -> RegInit(0.U(attribute("width").toInt.W))
944e19f7967SWilliam Wang  }}
945ad3ba452Szhanglinjuan  val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
946ad3ba452Szhanglinjuan    MaskedRegMap(
947ad3ba452Szhanglinjuan      Scachebase + attribute("offset").toInt,
948e19f7967SWilliam Wang      cacheopRegs(name)
949ad3ba452Szhanglinjuan    )
950ad3ba452Szhanglinjuan  }}
951b6982e83SLemover
95221fa8708Swangkaifan  val mapping = basicPrivMapping ++
9538635f18fSwangkaifan                perfCntMapping ++
95421fa8708Swangkaifan                pmpMapping ++
955ca2f90a6SLemover                pmaMapping ++
956ad3ba452Szhanglinjuan                (if (HasFPU) fcsrMapping else Nil) ++
9570ba52110SZiyue Zhang                (if (HasVPU) vcsrMapping else Nil) ++
958d0de7e4aSpeixiaokun                (if (HasCustomCSRCacheOp) cacheopMapping else Nil) ++
959d0de7e4aSpeixiaokun                (if (HasHExtension) hcsrMapping else Nil)
960c84054caSLinJiawei
961f7af4c74Schengguanghui
962f7af4c74Schengguanghui  println("XiangShan CSR Lists")
963f7af4c74Schengguanghui
964f7af4c74Schengguanghui  for (addr <- mapping.keys.toSeq.sorted) {
965f7af4c74Schengguanghui    println(f"$addr%#03x ${mapping(addr)._1}")
966f7af4c74Schengguanghui  }
967f7af4c74Schengguanghui
968d0de7e4aSpeixiaokun  val vs_s_csr_map = Map(
969d0de7e4aSpeixiaokun    Sstatus.U  -> Vsstatus.U,
970d0de7e4aSpeixiaokun    Sie.U      -> Vsie.U,
971d0de7e4aSpeixiaokun    Stvec.U    -> Vstvec.U,
972d0de7e4aSpeixiaokun    Sscratch.U -> Vsscratch.U,
973d0de7e4aSpeixiaokun    Sepc.U     -> Vsepc.U,
974d0de7e4aSpeixiaokun    Scause.U   -> Vscause.U,
975d0de7e4aSpeixiaokun    Stval.U    -> Vstval.U,
976d0de7e4aSpeixiaokun    Sip.U      -> Vsip.U,
977d0de7e4aSpeixiaokun    Satp.U     -> Vsatp.U
978d0de7e4aSpeixiaokun  )
979d0de7e4aSpeixiaokun  val addr = Wire(UInt(12.W))
980d0de7e4aSpeixiaokun  val vscsr_addr = LookupTreeDefault(src2(11, 0), src2(11, 0), vs_s_csr_map)
981d0de7e4aSpeixiaokun  when(virtMode){
982d0de7e4aSpeixiaokun    addr := vscsr_addr
983d0de7e4aSpeixiaokun  }.otherwise{
984d0de7e4aSpeixiaokun    addr := src2(11, 0)
985d0de7e4aSpeixiaokun  }
986b1860798SZhangfw  val csri = ZeroExt(src2(16, 12), XLEN)
987c84054caSLinJiawei  val rdata = Wire(UInt(XLEN.W))
988d0de7e4aSpeixiaokun  val rdata_tmp = Wire(UInt(XLEN.W))
989d0de7e4aSpeixiaokun  val wdata_tmp = LookupTree(func, List(
990c84054caSLinJiawei    CSROpType.wrt  -> src1,
991c84054caSLinJiawei    CSROpType.set  -> (rdata | src1),
9925d669833SYinan Xu    CSROpType.clr  -> (rdata & (~src1).asUInt),
993b0ae3ac4SLinJiawei    CSROpType.wrti -> csri,
994c84054caSLinJiawei    CSROpType.seti -> (rdata | csri),
9955d669833SYinan Xu    CSROpType.clri -> (rdata & (~csri).asUInt)
996c84054caSLinJiawei  ))
997d0de7e4aSpeixiaokun  val is_vsip_ie = addr === Vsip.U || addr === Vsie.U
998a1d4b4bfSpeixiaokun  // for the difftest with NEMU(stay consistent with Spike)
999a1d4b4bfSpeixiaokun  val is_satp  = addr === Satp.U
1000a1d4b4bfSpeixiaokun  val is_vsatp = addr === Vsatp.U
1001a1d4b4bfSpeixiaokun  val is_hgatp = addr === Hgatp.U
1002a1d4b4bfSpeixiaokun  val check_apt_mode = wdata_tmp(wdata_tmp.getWidth-1, 64-Satp_Mode_len) === 8.U || wdata_tmp(wdata_tmp.getWidth-1, 64-Satp_Mode_len) === 0.U
1003a1d4b4bfSpeixiaokun  val wdata = MuxCase(wdata_tmp, Seq(
1004a1d4b4bfSpeixiaokun    is_vsip_ie -> ZeroExt(wdata_tmp << 1, XLEN),
1005a1d4b4bfSpeixiaokun    (is_satp && !check_apt_mode) -> satp,
1006a1d4b4bfSpeixiaokun    (is_vsatp && !check_apt_mode) -> vsatp,
1007a1d4b4bfSpeixiaokun    (is_hgatp && !check_apt_mode) -> hgatp
1008a1d4b4bfSpeixiaokun  ))
1009e377d77eSWilliam Wang  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) ||
10104d5d2702Swakafa    (addr >= Mcountinhibit.U) && (addr <= Mhpmevent31.U) ||
1011f7af4c74Schengguanghui    (addr >= Cycle.U) && (addr <= Hpmcounter31.U) ||
10124d5d2702Swakafa    addr === Mip.U
1013e377d77eSWilliam Wang  csrio.isPerfCnt := addrInPerfCnt && valid && func =/= CSROpType.jmp
10148635f18fSwangkaifan
101547a386bfSZhangZifei  // satp wen check
101647a386bfSZhangZifei  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
10172f5f05fdSWilliam Wang
1018e5adbe81SLemover  // csr access check, special case
1019d0de7e4aSpeixiaokun  val tvmNotPermit = (privilegeMode === ModeS && !virtMode && mstatusStruct.tvm.asBool)
1020e5adbe81SLemover  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
1021d0de7e4aSpeixiaokun  val vtvmNotPermit = (privilegeMode === ModeS && virtMode && hstatusStruct.vtvm.asBool)
1022d0de7e4aSpeixiaokun  val vaccessPermitted = !(addr === Vsatp.U && vtvmNotPermit)
1023d0de7e4aSpeixiaokun  csrio.disableSfence := (tvmNotPermit || !virtMode && privilegeMode < ModeS) || (vtvmNotPermit || virtMode && privilegeMode < ModeS)
1024d0de7e4aSpeixiaokun  csrio.disableHfenceg := !((!virtMode && privilegeMode === ModeS && !mstatusStruct.tvm.asBool) || (privilegeMode === ModeM)) // only valid in HS and mstatus.tvm == 0 or in M
1025d0de7e4aSpeixiaokun  csrio.disableHfencev :=  !(privilegeMode === ModeM || (!virtMode && privilegeMode === ModeS))
1026e5adbe81SLemover
10272f5f05fdSWilliam Wang  // general CSR wen check
1028d0de7e4aSpeixiaokun  val wen = valid && CSROpType.needAccess(func) && ((addr=/=Satp.U && addr =/= Vsatp.U) || satpLegalMode)
102972951335SLi Qianruo  val dcsrPermitted = dcsrPermissionCheck(addr, false.B, debugMode)
103072951335SLi Qianruo  val triggerPermitted = triggerPermissionCheck(addr, true.B, debugMode) // todo dmode
10310214776eSpeixiaokun  val HasH = (HasHExtension == true).asBool
1032d0de7e4aSpeixiaokun  val csrAccess = csrAccessPermissionCheck(addr, false.B, privilegeMode, virtMode, HasH)
1033d0de7e4aSpeixiaokun  val modePermitted = csrAccess === 0.U && dcsrPermitted && triggerPermitted
1034321934c7SKunlin You  val perfcntPermitted = perfcntPermissionCheck(addr, privilegeMode, mcounteren, scounteren)
1035d0de7e4aSpeixiaokun  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && Mux(virtMode, vaccessPermitted, accessPermitted)
1036d0de7e4aSpeixiaokun  MaskedRegMap.generate(mapping, addr, rdata_tmp, wen && permitted, wdata)
1037d0de7e4aSpeixiaokun  rdata := Mux(is_vsip_ie, ZeroExt(rdata_tmp >> 1, XLEN), rdata_tmp)
10386a35d972SXuan Hu  io.out.bits.res.data := rdata
10396a35d972SXuan Hu  io.out.bits.ctrl.flushPipe.get := flushPipe
1040c1e19666Sxiaofeibao-xjtu  connect0LatencyCtrlSingal
1041c84054caSLinJiawei
1042b6982e83SLemover  // send distribute csr a w signal
1043b6982e83SLemover  csrio.customCtrl.distribute_csr.w.valid := wen && permitted
1044b6982e83SLemover  csrio.customCtrl.distribute_csr.w.bits.data := wdata
1045b6982e83SLemover  csrio.customCtrl.distribute_csr.w.bits.addr := addr
1046b6982e83SLemover
1047a4e57ea3SLi Qianruo  when (RegNext(csrio.fpu.fflags.valid)) {
1048577fcf2aSZhaoyang You    fcsr := fflags_wfn(update = true)(RegEnable(csrio.fpu.fflags.bits, csrio.fpu.fflags.valid))
1049c84054caSLinJiawei  }
10506355a2b7Sczw  when(RegNext(csrio.vpu.set_vxsat.valid)) {
1051c84054caSLinJiawei    fcsr := fflags_wfn(update = true)(RegNext(csrio.fpu.fflags.bits))
10526355a2b7Sczw  }
1053c84054caSLinJiawei  // set fs and sd in mstatus
1054a4e57ea3SLi Qianruo  when (csrw_dirty_fp_state || RegNext(csrio.fpu.dirty_fs)) {
1055c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1056c84054caSLinJiawei    mstatusNew.fs := "b11".U
1057c84054caSLinJiawei    mstatusNew.sd := true.B
10585d669833SYinan Xu    mstatus := mstatusNew.asUInt
1059cf025d06Speixiaokun    when(virtMode){
1060cf025d06Speixiaokun      val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1061cf025d06Speixiaokun      vsstatusNew.fs := "b11".U
1062cf025d06Speixiaokun      vsstatusNew.sd := true.B
1063cf025d06Speixiaokun      vsstatus := vsstatusNew.asUInt
1064c84054caSLinJiawei    }
1065c84054caSLinJiawei  }
1066c84054caSLinJiawei  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
1067c84054caSLinJiawei
106835d1557aSZiyue Zhang  when (RegNext(csrio.vpu.set_vstart.valid)) {
1069577fcf2aSZhaoyang You    vstart := RegEnable(csrio.vpu.set_vstart.bits, csrio.vpu.set_vstart.valid)
1070daa01159SZiyue Zhang  }
107135d1557aSZiyue Zhang  when (RegNext(csrio.vpu.set_vtype.valid)) {
1072577fcf2aSZhaoyang You    vtype := RegEnable(csrio.vpu.set_vtype.bits, csrio.vpu.set_vtype.valid)
1073daa01159SZiyue Zhang  }
1074daa01159SZiyue Zhang  when (RegNext(csrio.vpu.set_vl.valid)) {
1075c04d0602SZiyue Zhang    vl := RegEnable(csrio.vpu.set_vl.bits, csrio.vpu.set_vl.valid)
1076daa01159SZiyue Zhang  }
1077daa01159SZiyue Zhang  // set vs and sd in mstatus
107862a2cb19SXuan Hu  when(csrw_dirty_vs_state || RegNext(csrio.vpu.dirty_vs)) {
107962a2cb19SXuan Hu    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
108062a2cb19SXuan Hu    mstatusNew.vs := ContextStatus.dirty
108162a2cb19SXuan Hu    mstatusNew.sd := true.B
108262a2cb19SXuan Hu    mstatus := mstatusNew.asUInt
108362a2cb19SXuan Hu  }
1084daa01159SZiyue Zhang
1085daa01159SZiyue Zhang  csrio.vpu.vstart := vstart
1086daa01159SZiyue Zhang  csrio.vpu.vxrm := vcsr.asTypeOf(new VcsrStruct).vxrm
1087daa01159SZiyue Zhang  csrio.vpu.vxsat := vcsr.asTypeOf(new VcsrStruct).vxsat
108835d1557aSZiyue Zhang  csrio.vpu.vcsr := vcsr
108935d1557aSZiyue Zhang  csrio.vpu.vtype := vtype
1090daa01159SZiyue Zhang  csrio.vpu.vl := vl
1091daa01159SZiyue Zhang  csrio.vpu.vlenb := vlenb
1092daa01159SZiyue Zhang  csrio.vpu.vill := vtype.asTypeOf(new VtypeStruct).vill
1093daa01159SZiyue Zhang  csrio.vpu.vma := vtype.asTypeOf(new VtypeStruct).vma
1094daa01159SZiyue Zhang  csrio.vpu.vta := vtype.asTypeOf(new VtypeStruct).vta
1095daa01159SZiyue Zhang  csrio.vpu.vsew := vtype.asTypeOf(new VtypeStruct).vsew
1096daa01159SZiyue Zhang  csrio.vpu.vlmul := vtype.asTypeOf(new VtypeStruct).vlmul
109772951335SLi Qianruo
109872951335SLi Qianruo  // Trigger Ctrl
1099f7af4c74Schengguanghui  val triggerEnableVec = tdata1RegVec.map { tdata1 =>
1100f7af4c74Schengguanghui    val mcontrolData = tdata1.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData)
1101f7af4c74Schengguanghui    tdata1.asTypeOf(new Tdata1Bundle).type_.asUInt === TrigTypeEnum.MCONTROL && (
11020ffeff0dSXuan Hu      mcontrolData.m && privilegeMode === ModeM ||
11030ffeff0dSXuan Hu        mcontrolData.s && privilegeMode === ModeS ||
11040ffeff0dSXuan Hu        mcontrolData.u && privilegeMode === ModeU)
110572951335SLi Qianruo  }
1106f7af4c74Schengguanghui  val fetchTriggerEnableVec = triggerEnableVec.zip(tdata1WireVec).map {
1107f7af4c74Schengguanghui    case (tEnable, tdata1) => tEnable && tdata1.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isFetchTrigger
1108f7af4c74Schengguanghui  }
1109f7af4c74Schengguanghui  val memAccTriggerEnableVec = triggerEnableVec.zip(tdata1WireVec).map {
1110f7af4c74Schengguanghui    case (tEnable, tdata1) => tEnable && tdata1.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isMemAccTrigger
1111f7af4c74Schengguanghui  }
1112f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tEnableVec := fetchTriggerEnableVec
1113f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tEnableVec := memAccTriggerEnableVec
1114f7af4c74Schengguanghui
1115f7af4c74Schengguanghui  val tdata1Update = wen && (addr === Tdata1.U)
1116f7af4c74Schengguanghui  val tdata2Update = wen && (addr === Tdata2.U)
1117f7af4c74Schengguanghui  val triggerUpdate = wen && (addr === Tdata1.U || addr === Tdata2.U)
1118f7af4c74Schengguanghui  val frontendTriggerUpdate =
1119f7af4c74Schengguanghui    tdata1Update && wdata.asTypeOf(new Tdata1Bundle).type_.asUInt === TrigTypeEnum.MCONTROL &&
1120f7af4c74Schengguanghui      wdata.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isFetchTrigger ||
1121f7af4c74Schengguanghui      tdata1Selected.data.asTypeOf(new MControlData).isFetchTrigger && triggerUpdate
1122f7af4c74Schengguanghui  val memTriggerUpdate =
1123f7af4c74Schengguanghui    tdata1Update && wdata.asTypeOf(new Tdata1Bundle).type_.asUInt === TrigTypeEnum.MCONTROL &&
1124f7af4c74Schengguanghui      wdata.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isMemAccTrigger ||
1125f7af4c74Schengguanghui      tdata1Selected.data.asTypeOf(new MControlData).isMemAccTrigger && triggerUpdate
1126f7af4c74Schengguanghui
1127f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tUpdate.valid := RegNext(RegNext(frontendTriggerUpdate))
1128f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tUpdate.valid := RegNext(RegNext(memTriggerUpdate))
1129f7af4c74Schengguanghui  XSDebug(triggerEnableVec.reduce(_ || _), p"Debug Mode: At least 1 trigger is enabled," +
1130f7af4c74Schengguanghui    p"trigger enable is ${Binary(triggerEnableVec.asUInt)}\n")
113172951335SLi Qianruo
1132c84054caSLinJiawei  // CSR inst decode
1133c84054caSLinJiawei  val isEbreak = addr === privEbreak && func === CSROpType.jmp
1134c84054caSLinJiawei  val isEcall  = addr === privEcall  && func === CSROpType.jmp
1135c84054caSLinJiawei  val isMret   = addr === privMret   && func === CSROpType.jmp
1136c84054caSLinJiawei  val isSret   = addr === privSret   && func === CSROpType.jmp
1137c84054caSLinJiawei  val isUret   = addr === privUret   && func === CSROpType.jmp
1138d4aca96cSlqre  val isDret   = addr === privDret   && func === CSROpType.jmp
11395d669833SYinan Xu  val isWFI    = func === CSROpType.wfi
1140c84054caSLinJiawei
1141321934c7SKunlin You  // Illegal privileged operation list
1142321934c7SKunlin You  val illegalMret = valid && isMret && privilegeMode < ModeM
1143321934c7SKunlin You  val illegalSret = valid && isSret && privilegeMode < ModeS
1144d0de7e4aSpeixiaokun  val illegalSModeSret = valid && isSret && privilegeMode === ModeS && virtMode === false.B && mstatusStruct.tsr.asBool
1145d0de7e4aSpeixiaokun  // when hstatus.vtsr == 1, if sret is executed in VS-mode, it will cause virtual instruction
1146d0de7e4aSpeixiaokun  val illegalVSModeSret = valid && isSret && privilegeMode === ModeS && virtMode && hstatusStruct.vtsr.asBool
11475d669833SYinan Xu  // When TW=1, then if WFI is executed in any less-privileged mode,
11485d669833SYinan Xu  // and it does not complete within an implementation-specific, bounded time limit,
11495d669833SYinan Xu  // the WFI instruction causes an illegal instruction exception.
11505d669833SYinan Xu  // The time limit may always be 0, in which case WFI always causes
11515d669833SYinan Xu  // an illegal instruction exception in less-privileged modes when TW=1.
1152d0de7e4aSpeixiaokun  val illegalWFI = valid && isWFI && (privilegeMode < ModeM && mstatusStruct.tw === 1.U ||  privilegeMode === ModeU && !virtMode)
1153d0de7e4aSpeixiaokun  val illegalVWFI = valid && isWFI && ((virtMode && privilegeMode === ModeS && hstatusStruct.vtw === 1.U && mstatusStruct.tw === 0.U)||
1154d0de7e4aSpeixiaokun      (virtMode && privilegeMode === ModeU && mstatusStruct.tw === 0.U))
1155321934c7SKunlin You  // Illegal privileged instruction check
11565d669833SYinan Xu  val isIllegalAddr = valid && CSROpType.needAccess(func) && MaskedRegMap.isIllegalAddr(mapping, addr)
1157d0de7e4aSpeixiaokun  val isIllegalAccess = !virtMode && wen && !(Mux(addrInPerfCnt, perfcntPermitted, csrAccess === 0.U && dcsrPermitted && triggerPermitted) && accessPermitted)
11585d669833SYinan Xu  val isIllegalPrivOp = illegalMret || illegalSret || illegalSModeSret || illegalWFI
1159c84054caSLinJiawei
1160d0de7e4aSpeixiaokun  val isIllegalVAccess = virtMode && wen && (csrAccess === 2.U || !vaccessPermitted)
1161d0de7e4aSpeixiaokun  val isIllegalVPrivOp = illegalVSModeSret || illegalVWFI
1162ad3ba452Szhanglinjuan  // expose several csr bits for tlb
1163fcff7e94SZhangZifei  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
1164fcff7e94SZhangZifei  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
1165d0de7e4aSpeixiaokun  tlbBundle.priv.vmxr := vsstatusStruct.mxr.asBool
1166d0de7e4aSpeixiaokun  tlbBundle.priv.vsum := vsstatusStruct.sum.asBool
1167d0de7e4aSpeixiaokun  tlbBundle.priv.spvp := hstatusStruct.spvp
1168d0de7e4aSpeixiaokun  tlbBundle.priv.virt  := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpv & (mstatusStruct.mpp =/= ModeM), virtMode)
1169321934c7SKunlin You  tlbBundle.priv.imode := privilegeMode
11700ffeff0dSXuan Hu  tlbBundle.priv.dmode := Mux((debugMode && dcsr.asTypeOf(new DcsrStruct).mprven || !debugMode) && mstatusStruct.mprv.asBool, mstatusStruct.mpp, privilegeMode)
1171c84054caSLinJiawei
1172e9341afdSYinan Xu  // Branch control
1173f7af4c74Schengguanghui  val retTarget = WireInit(0.U)
117482e4705bSpeixiaokun  val resetSatp = (addr === Satp.U || addr === Hgatp.U || addr === Vsatp.U) && wen // write to satp will cause the pipeline be flushed
1175c84054caSLinJiawei
1176f7af4c74Schengguanghui  val w_fcsr_change_rm = wen && addr === Fcsr.U && wdata(7, 5) =/= fcsr(7, 5)
1177f7af4c74Schengguanghui  val w_frm_change_rm = wen && addr === Frm.U && wdata(2, 0) =/= fcsr(7, 5)
1178f7af4c74Schengguanghui  val frm_change = w_fcsr_change_rm || w_frm_change_rm
1179f7af4c74Schengguanghui  val isXRet = valid && func === CSROpType.jmp && !isEcall && !isEbreak
1180f7af4c74Schengguanghui  flushPipe := resetSatp || frm_change || isXRet || frontendTriggerUpdate
1181c84054caSLinJiawei
1182f7af4c74Schengguanghui  private val illegalRetTarget = WireInit(false.B)
1183f7af4c74Schengguanghui  when(valid) {
1184f7af4c74Schengguanghui    when(isDret) {
1185d4aca96cSlqre      retTarget := dpc(VAddrBits - 1, 0)
1186f7af4c74Schengguanghui    }.elsewhen(isMret && !illegalMret) {
1187f7af4c74Schengguanghui      retTarget := mepc(VAddrBits - 1, 0)
1188d0de7e4aSpeixiaokun    }.elsewhen(isSret && !illegalSret && !illegalSModeSret && !illegalVSModeSret) {
1189d0de7e4aSpeixiaokun      retTarget := Mux(virtMode, vsepc(VAddrBits - 1, 0), sepc(VAddrBits - 1, 0))
1190f7af4c74Schengguanghui    }.elsewhen(isUret) {
1191f7af4c74Schengguanghui      retTarget := uepc(VAddrBits - 1, 0)
1192f7af4c74Schengguanghui    }.otherwise {
1193f7af4c74Schengguanghui      illegalRetTarget := true.B
1194f7af4c74Schengguanghui    }
1195f7af4c74Schengguanghui  }.otherwise {
1196f7af4c74Schengguanghui    illegalRetTarget := true.B // when illegalRetTarget setted, retTarget should never be used
1197f7af4c74Schengguanghui  }
1198f7af4c74Schengguanghui
1199f7af4c74Schengguanghui  // Mux tree for regs
1200f7af4c74Schengguanghui  when(valid) {
1201f7af4c74Schengguanghui    when(isDret) {
1202f7af4c74Schengguanghui      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1203f7af4c74Schengguanghui      val debugModeNew = WireInit(debugMode)
1204f7af4c74Schengguanghui      when(dcsr.asTypeOf(new DcsrStruct).prv =/= ModeM) {
1205f7af4c74Schengguanghui        mstatusNew.mprv := 0.U
1206f7af4c74Schengguanghui      } //If the new privilege mode is less privileged than M-mode, MPRV in mstatus is cleared.
1207f7af4c74Schengguanghui      mstatus := mstatusNew.asUInt
12080ffeff0dSXuan Hu      privilegeMode := dcsr.asTypeOf(new DcsrStruct).prv
1209d4aca96cSlqre      debugModeNew := false.B
1210d4aca96cSlqre      debugIntrEnable := true.B
1211d4aca96cSlqre      debugMode := debugModeNew
1212d4aca96cSlqre      XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget)
1213f7af4c74Schengguanghui    }.elsewhen(isMret && !illegalMret) {
1214c84054caSLinJiawei      val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1215c84054caSLinJiawei      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1216c84054caSLinJiawei      mstatusNew.ie.m := mstatusOld.pie.m
1217321934c7SKunlin You      privilegeMode := mstatusOld.mpp
1218d0de7e4aSpeixiaokun      if (HasHExtension) {
1219d0de7e4aSpeixiaokun        virtMode := mstatusOld.mpv
1220d0de7e4aSpeixiaokun        mstatusNew.mpv := 0.U
1221d0de7e4aSpeixiaokun      }
1222c84054caSLinJiawei      mstatusNew.pie.m := true.B
1223c84054caSLinJiawei      mstatusNew.mpp := ModeU
1224f7af4c74Schengguanghui      when(mstatusOld.mpp =/= ModeM) {
1225f7af4c74Schengguanghui        mstatusNew.mprv := 0.U
1226c84054caSLinJiawei      }
1227f7af4c74Schengguanghui      mstatus := mstatusNew.asUInt
122878233deeSXuan Hu    }.elsewhen(isSret && !illegalSret && !illegalSModeSret && !illegalVSModeSret) {
1229c84054caSLinJiawei      val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1230c84054caSLinJiawei      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1231d0de7e4aSpeixiaokun      val hstatusOld = WireInit(hstatus.asTypeOf(new HstatusStruct))
1232d0de7e4aSpeixiaokun      val hstatusNew = WireInit(hstatus.asTypeOf(new HstatusStruct))
1233d0de7e4aSpeixiaokun      val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1234d0de7e4aSpeixiaokun      val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1235d0de7e4aSpeixiaokun      when(virtMode === 0.U) {
1236d0de7e4aSpeixiaokun        virtMode := hstatusOld.spv
1237d0de7e4aSpeixiaokun        hstatusNew.spv := 0.U
1238c84054caSLinJiawei        mstatusNew.ie.s := mstatusOld.pie.s
1239321934c7SKunlin You        privilegeMode := Cat(0.U(1.W), mstatusOld.spp)
1240c84054caSLinJiawei        mstatusNew.pie.s := true.B
1241c84054caSLinJiawei        mstatusNew.spp := ModeU
1242f7af4c74Schengguanghui        when(mstatusOld.spp =/= ModeM) {
1243f7af4c74Schengguanghui          mstatusNew.mprv := 0.U
1244c84054caSLinJiawei        }
1245c84054caSLinJiawei        mstatus := mstatusNew.asUInt
1246d0de7e4aSpeixiaokun        hstatus := hstatusNew.asUInt
1247d0de7e4aSpeixiaokun      }.otherwise {
1248d0de7e4aSpeixiaokun        privilegeMode := vsstatusOld.spp
1249d0de7e4aSpeixiaokun        vsstatusNew.spp := ModeU
1250d0de7e4aSpeixiaokun        vsstatusNew.ie.s := vsstatusOld.pie.s
1251d0de7e4aSpeixiaokun        vsstatusNew.pie.s := 1.U
1252d0de7e4aSpeixiaokun        vsstatus := vsstatusNew.asUInt
1253d0de7e4aSpeixiaokun      }
1254f7af4c74Schengguanghui    }.elsewhen(isUret) {
1255c84054caSLinJiawei      val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1256c84054caSLinJiawei      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1257c84054caSLinJiawei      // mstatusNew.mpp.m := ModeU //TODO: add mode U
1258c84054caSLinJiawei      mstatusNew.ie.u := mstatusOld.pie.u
1259321934c7SKunlin You      privilegeMode := ModeU
1260c84054caSLinJiawei      mstatusNew.pie.u := true.B
1261c84054caSLinJiawei      mstatus := mstatusNew.asUInt
1262f7af4c74Schengguanghui    }
1263c84054caSLinJiawei  }
1264c84054caSLinJiawei
1265e9341afdSYinan Xu  io.in.ready := true.B
1266e9341afdSYinan Xu  io.out.valid := valid
1267e9341afdSYinan Xu
1268f7af4c74Schengguanghui  // In this situation, hart will enter debug mode instead of handling a breakpoint exception simply.
1269f7af4c74Schengguanghui  // Ebreak block instructions backwards, so it's ok to not keep extra info to distinguish between breakpoint
1270f7af4c74Schengguanghui  // exception and enter-debug-mode exception.
1271f7af4c74Schengguanghui  val ebreakEnterDebugMode =
12725b0f0029SXuan Hu    (privilegeMode === ModeM && dcsrData.ebreakm) ||
12735b0f0029SXuan Hu    (privilegeMode === ModeS && dcsrData.ebreaks) ||
12745b0f0029SXuan Hu    (privilegeMode === ModeU && dcsrData.ebreaku)
1275f7af4c74Schengguanghui
1276f7af4c74Schengguanghui  // raise a debug exception waiting to enter debug mode, instead of a breakpoint exception
1277f7af4c74Schengguanghui  val raiseDebugException = !debugMode && isEbreak && ebreakEnterDebugMode
1278d4aca96cSlqre
12793b739f49SXuan Hu  val csrExceptionVec = WireInit(0.U.asTypeOf(ExceptionVec()))
1280f7af4c74Schengguanghui  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
1281321934c7SKunlin You  csrExceptionVec(ecallM) := privilegeMode === ModeM && io.in.valid && isEcall
1282d0de7e4aSpeixiaokun  csrExceptionVec(ecallVS) := privilegeMode === ModeS && virtMode && io.in.valid && isEcall
1283d0de7e4aSpeixiaokun  csrExceptionVec(ecallS) := privilegeMode === ModeS && !virtMode && io.in.valid && isEcall
1284321934c7SKunlin You  csrExceptionVec(ecallU) := privilegeMode === ModeU && io.in.valid && isEcall
1285baf8def6SYinan Xu  // Trigger an illegal instr exception when:
1286baf8def6SYinan Xu  // * unimplemented csr is being read/written
1287baf8def6SYinan Xu  // * csr access is illegal
12885d669833SYinan Xu  csrExceptionVec(illegalInstr) := isIllegalAddr || isIllegalAccess || isIllegalPrivOp
1289d0de7e4aSpeixiaokun  csrExceptionVec(virtualInstr) := isIllegalVAccess || isIllegalVPrivOp
12906a35d972SXuan Hu  io.out.bits.ctrl.exceptionVec.get := csrExceptionVec
1291baf8def6SYinan Xu
1292f7af4c74Schengguanghui  XSDebug(io.in.valid, s"Debug Mode: an Ebreak is executed, ebreak cause enter-debug-mode exception ? ${raiseDebugException}\n")
129384e47f35SLi Qianruo
1294e9341afdSYinan Xu  /**
1295e9341afdSYinan Xu    * Exception and Intr
1296e9341afdSYinan Xu    */
1297d0de7e4aSpeixiaokun  val idelegS =  (mideleg & mip.asUInt)
1298d0de7e4aSpeixiaokun  val idelegVS = (hideleg & mideleg & mip.asUInt)
1299d0de7e4aSpeixiaokun  def privilegedEnableDetect(idelegS: Bool, idelegVS: Bool): Bool = Mux(idelegS,
1300d0de7e4aSpeixiaokun    Mux(idelegVS, (virtMode && privilegeMode === ModeS && vsstatusStruct.ie.s) || (virtMode && privilegeMode < ModeS),
1301d0de7e4aSpeixiaokun      ((privilegeMode === ModeS) && mstatusStruct.ie.s) || (privilegeMode < ModeS) || virtMode),
1302321934c7SKunlin You    ((privilegeMode === ModeM) && mstatusStruct.ie.m) || (privilegeMode < ModeM))
1303e9341afdSYinan Xu
1304d4aca96cSlqre  val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable
1305d4aca96cSlqre  XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!")
13069aca92b9SYinan Xu  // send interrupt information to ROB
1307d0de7e4aSpeixiaokun  val intrVecEnable = Wire(Vec(13, Bool()))
1308052ee9a1SLi Qianruo  val disableInterrupt = debugMode || (dcsrData.step && !dcsrData.stepie)
1309d0de7e4aSpeixiaokun  intrVecEnable.zip(idelegS.asBools).zip(idelegVS.asBools).map{case((x,y),z) => x := privilegedEnableDetect(y, z) && !disableInterrupt}
1310d7dd1af1SLi Qianruo  val intrVec = Cat(debugIntr && !debugMode, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt))
13115d669833SYinan Xu  val intrBitSet = intrVec.orR
1312e9341afdSYinan Xu  csrio.interrupt := intrBitSet
13135c95ea2eSYinan Xu  // Page 45 in RISC-V Privileged Specification
13145c95ea2eSYinan Xu  // The WFI instruction can also be executed when interrupts are disabled. The operation of WFI
13155c95ea2eSYinan Xu  // must be unaffected by the global interrupt bits in mstatus (MIE and SIE) and the delegation
13165c95ea2eSYinan Xu  // register mideleg, but should honor the individual interrupt enables (e.g, MTIE).
13174ede3fe2SLi Qianruo  csrio.wfi_event := debugIntr || (mie(11, 0) & mip.asUInt).orR
1318e9341afdSYinan Xu  mipWire.t.m := csrio.externalInterrupt.mtip
1319e9341afdSYinan Xu  mipWire.s.m := csrio.externalInterrupt.msip
1320e9341afdSYinan Xu  mipWire.e.m := csrio.externalInterrupt.meip
1321b3d79b37SYinan Xu  mipWire.e.s := csrio.externalInterrupt.seip
1322e9341afdSYinan Xu
1323e9341afdSYinan Xu  // interrupts
1324e9341afdSYinan Xu  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
1325f7af4c74Schengguanghui  val hasIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
1326a4e57ea3SLi Qianruo  val ivmEnable = tlbBundle.priv.imode < ModeM && satp.asTypeOf(new SatpStruct).mode === 8.U
13273b739f49SXuan Hu  val iexceptionPC = Mux(ivmEnable, SignExt(csrio.exception.bits.pc, XLEN), csrio.exception.bits.pc)
1328e25e4d90SXuan Hu  val iexceptionGPAddr = Mux(ivmEnable, SignExt(csrio.exception.bits.gpaddr, XLEN), csrio.exception.bits.gpaddr)
1329a4e57ea3SLi Qianruo  val dvmEnable = tlbBundle.priv.dmode < ModeM && satp.asTypeOf(new SatpStruct).mode === 8.U
13303b739f49SXuan Hu  val dexceptionPC = Mux(dvmEnable, SignExt(csrio.exception.bits.pc, XLEN), csrio.exception.bits.pc)
1331f7af4c74Schengguanghui  XSDebug(hasIntr, "interrupt: pc=0x%x, %d\n", dexceptionPC, intrNO)
1332f7af4c74Schengguanghui  val hasDebugIntr = intrNO === IRQ_DEBUG.U && hasIntr
1333e9341afdSYinan Xu
1334f7af4c74Schengguanghui  // exceptions from rob need to handle
1335f7af4c74Schengguanghui  val exceptionVecFromRob    = csrio.exception.bits.exceptionVec
1336f7af4c74Schengguanghui  val hasException           = csrio.exception.valid && !csrio.exception.bits.isInterrupt
1337f7af4c74Schengguanghui  val hasInstrPageFault      = hasException && exceptionVecFromRob(instrPageFault)
1338f7af4c74Schengguanghui  val hasLoadPageFault       = hasException && exceptionVecFromRob(loadPageFault)
1339f7af4c74Schengguanghui  val hasStorePageFault      = hasException && exceptionVecFromRob(storePageFault)
1340f7af4c74Schengguanghui  val hasStoreAddrMisalign   = hasException && exceptionVecFromRob(storeAddrMisaligned)
1341f7af4c74Schengguanghui  val hasLoadAddrMisalign    = hasException && exceptionVecFromRob(loadAddrMisaligned)
1342f7af4c74Schengguanghui  val hasInstrAccessFault    = hasException && exceptionVecFromRob(instrAccessFault)
1343f7af4c74Schengguanghui  val hasLoadAccessFault     = hasException && exceptionVecFromRob(loadAccessFault)
1344f7af4c74Schengguanghui  val hasStoreAccessFault    = hasException && exceptionVecFromRob(storeAccessFault)
1345f7af4c74Schengguanghui  val hasBreakPoint          = hasException && exceptionVecFromRob(breakPoint)
13461f518b57SXuan Hu  val hasInstGuestPageFault  = hasException && exceptionVecFromRob(instrGuestPageFault)
13471f518b57SXuan Hu  val hasLoadGuestPageFault  = hasException && exceptionVecFromRob(loadGuestPageFault)
13481f518b57SXuan Hu  val hasStoreGuestPageFault = hasException && exceptionVecFromRob(storeGuestPageFault)
1349f7af4c74Schengguanghui  val hasSingleStep          = hasException && csrio.exception.bits.singleStep
1350f7af4c74Schengguanghui  val hasTriggerFire         = hasException && csrio.exception.bits.trigger.canFire
1351f7af4c74Schengguanghui  val triggerFrontendHitVec = csrio.exception.bits.trigger.frontendHit
1352f7af4c74Schengguanghui  val triggerMemHitVec = csrio.exception.bits.trigger.backendHit
1353f7af4c74Schengguanghui  val triggerHitVec = triggerFrontendHitVec | triggerMemHitVec // Todo: update mcontrol.hit
1354f7af4c74Schengguanghui  val triggerCanFireVec = csrio.exception.bits.trigger.frontendCanFire | csrio.exception.bits.trigger.backendCanFire
1355f7af4c74Schengguanghui  // More than one triggers can hit at the same time, but only fire one
1356f7af4c74Schengguanghui  // We select the first hit trigger to fire
1357f7af4c74Schengguanghui  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
1358f7af4c74Schengguanghui  val triggerFireAction = PriorityMux(triggerFireOH, tdata1WireVec.map(_.getTriggerAction)).asUInt
1359f7af4c74Schengguanghui
136084e47f35SLi Qianruo
136184e47f35SLi Qianruo  XSDebug(hasSingleStep, "Debug Mode: single step exception\n")
1362f7af4c74Schengguanghui  XSDebug(hasTriggerFire, p"Debug Mode: trigger fire, frontend hit vec ${Binary(csrio.exception.bits.trigger.frontendHit.asUInt)} " +
1363f7af4c74Schengguanghui    p"backend hit vec ${Binary(csrio.exception.bits.trigger.backendHit.asUInt)}\n")
1364e9341afdSYinan Xu
1365f7af4c74Schengguanghui  val hasExceptionVec = csrio.exception.bits.exceptionVec
1366f7af4c74Schengguanghui  val regularExceptionNO = ExceptionNO.priorities.foldRight(0.U)((i: Int, sum: UInt) => Mux(hasExceptionVec(i), i.U, sum))
1367f7af4c74Schengguanghui  val exceptionNO = Mux(hasSingleStep || hasTriggerFire, 3.U, regularExceptionNO)
1368f7af4c74Schengguanghui  val causeNO = (hasIntr << (XLEN - 1)).asUInt | Mux(hasIntr, intrNO, exceptionNO)
1369e9341afdSYinan Xu
1370f7af4c74Schengguanghui  val hasExceptionIntr = csrio.exception.valid
1371d4aca96cSlqre
1372f7af4c74Schengguanghui  val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode
1373f7af4c74Schengguanghui  val hasDebugTriggerException = hasTriggerFire && triggerFireAction === TrigActionEnum.DEBUG_MODE
1374f7af4c74Schengguanghui  val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep
1375f7af4c74Schengguanghui  val hasDebugTrap = hasDebugException || hasDebugIntr
1376f7af4c74Schengguanghui  val ebreakEnterParkLoop = debugMode && hasExceptionIntr
1377f7af4c74Schengguanghui
1378f7af4c74Schengguanghui  XSDebug(hasExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
1379f7af4c74Schengguanghui    dexceptionPC, intrNO, intrVec, exceptionNO, hasExceptionVec.asUInt
1380e9341afdSYinan Xu  )
1381f7af4c74Schengguanghui  XSDebug(hasExceptionIntr,
1382e9341afdSYinan Xu    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
1383a4e57ea3SLi Qianruo    dexceptionPC,
1384e9341afdSYinan Xu    mstatus,
1385e9341afdSYinan Xu    mideleg,
1386e9341afdSYinan Xu    medeleg,
1387321934c7SKunlin You    privilegeMode
1388e9341afdSYinan Xu  )
1389e9341afdSYinan Xu
1390e9341afdSYinan Xu  // mtval write logic
13918a33de1fSYinan Xu  // Due to timing reasons of memExceptionVAddr, we delay the write of mtval and stval
1392e9341afdSYinan Xu  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
1393d0de7e4aSpeixiaokun  val memExceptionGPAddr = SignExt(csrio.memExceptionGPAddr, XLEN)
1394a4e57ea3SLi Qianruo  val updateTval = VecInit(Seq(
1395a4e57ea3SLi Qianruo    hasInstrPageFault,
1396a4e57ea3SLi Qianruo    hasLoadPageFault,
1397a4e57ea3SLi Qianruo    hasStorePageFault,
1398a4e57ea3SLi Qianruo    hasInstrAccessFault,
1399a4e57ea3SLi Qianruo    hasLoadAccessFault,
1400a4e57ea3SLi Qianruo    hasStoreAccessFault,
1401f7af4c74Schengguanghui    hasLoadAddrMisalign,
14025b0f0029SXuan Hu    hasStoreAddrMisalign,
1403d0de7e4aSpeixiaokun    hasInstGuestPageFault,
1404d0de7e4aSpeixiaokun    hasLoadGuestPageFault,
14051797fef6SXuan Hu    hasStoreGuestPageFault,
14061797fef6SXuan Hu    hasBreakPoint,
1407d0de7e4aSpeixiaokun  )).asUInt.orR
1408d0de7e4aSpeixiaokun  val updateTval_h = VecInit(Seq(
1409d0de7e4aSpeixiaokun    hasInstGuestPageFault,
1410d0de7e4aSpeixiaokun    hasLoadGuestPageFault,
1411d0de7e4aSpeixiaokun    hasStoreGuestPageFault
1412a4e57ea3SLi Qianruo  )).asUInt.orR
1413a4e57ea3SLi Qianruo  when (RegNext(RegNext(updateTval))) {
141495fbbc80SYinan Xu      val tval = Mux(
14151797fef6SXuan Hu        RegNext(RegNext(hasInstrPageFault || hasInstrAccessFault || hasInstGuestPageFault || hasBreakPoint)),
141695fbbc80SYinan Xu        RegNext(RegNext(Mux(
14173b739f49SXuan Hu          csrio.exception.bits.crossPageIPFFix,
14183b739f49SXuan Hu          SignExt(csrio.exception.bits.pc + 2.U, XLEN),
1419a4e57ea3SLi Qianruo          iexceptionPC
142095fbbc80SYinan Xu        ))),
1421e9341afdSYinan Xu        memExceptionAddr
142295fbbc80SYinan Xu    )
1423d0de7e4aSpeixiaokun    // because we update tval two beats later, we can choose xtval according to the privilegeMode which has been updated
1424321934c7SKunlin You    when (RegNext(privilegeMode === ModeM)) {
1425e9341afdSYinan Xu      mtval := tval
1426e9341afdSYinan Xu    }.otherwise {
1427d0de7e4aSpeixiaokun      when (virtMode){
1428d0de7e4aSpeixiaokun        vstval := tval
1429d0de7e4aSpeixiaokun      }.otherwise{
1430e9341afdSYinan Xu        stval := tval
1431e9341afdSYinan Xu      }
1432e9341afdSYinan Xu    }
1433d0de7e4aSpeixiaokun  }
1434d0de7e4aSpeixiaokun
1435d0de7e4aSpeixiaokun  when(RegNext(RegNext(updateTval_h))) {
1436d0de7e4aSpeixiaokun    val tval_tmp = Mux(
1437d0de7e4aSpeixiaokun      RegNext(RegNext(hasInstGuestPageFault)),
1438d0de7e4aSpeixiaokun      RegNext(RegNext(Mux(
1439e25e4d90SXuan Hu        csrio.exception.bits.crossPageIPFFix,
1440e25e4d90SXuan Hu        SignExt(csrio.exception.bits.gpaddr + 2.U, XLEN),
1441d0de7e4aSpeixiaokun        iexceptionGPAddr
1442d0de7e4aSpeixiaokun      ))),
1443d0de7e4aSpeixiaokun      memExceptionGPAddr
1444d0de7e4aSpeixiaokun    )
1445d0de7e4aSpeixiaokun    val tval = tval_tmp >> 2
1446d0de7e4aSpeixiaokun    when(RegNext(privilegeMode === ModeM)) {
1447d0de7e4aSpeixiaokun      mtval2 := tval
1448d0de7e4aSpeixiaokun    }.otherwise {
1449d0de7e4aSpeixiaokun      htval := tval
1450d0de7e4aSpeixiaokun    }
1451d0de7e4aSpeixiaokun  }
1452e9341afdSYinan Xu
1453d4aca96cSlqre  val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec
1454f7af4c74Schengguanghui  val deleg = Mux(hasIntr, mideleg , medeleg)
14551f518b57SXuan Hu  val hdeleg = Mux(hasIntr, hideleg, hedeleg)
1456321934c7SKunlin You  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (privilegeMode < ModeM);
14575b0f0029SXuan Hu  val delegS = deleg(causeNO(7,0)) && (privilegeMode < ModeM)
1458d0de7e4aSpeixiaokun  val delegVS = virtMode && delegS && hdeleg(causeNO(7, 0)) && (privilegeMode < ModeM)
1459f7af4c74Schengguanghui  val clearTval = !updateTval || hasIntr
146013096f7eSYinan Xu
14611f518b57SXuan Hu  val clearTval_h = !updateTval_h || hasIntr
1462e25e4d90SXuan Hu  val isHyperInst = csrio.exception.bits.isHls
146313096f7eSYinan Xu  // ctrl block will use theses later for flush
146413096f7eSYinan Xu  val isXRetFlag = RegInit(false.B)
14653b739f49SXuan Hu  when (DelayN(io.flush.valid, 5)) {
146613096f7eSYinan Xu    isXRetFlag := false.B
146713096f7eSYinan Xu  }.elsewhen (isXRet) {
146813096f7eSYinan Xu    isXRetFlag := true.B
146913096f7eSYinan Xu  }
147013096f7eSYinan Xu  csrio.isXRet := isXRetFlag
1471f7af4c74Schengguanghui  private val retTargetReg = RegEnable(retTarget, isXRet && !illegalRetTarget)
1472d0de7e4aSpeixiaokun  private val illegalXret = RegEnable(illegalMret || illegalSret || illegalSModeSret || illegalVSModeSret, isXRet)
1473a4e57ea3SLi Qianruo
1474e25e4d90SXuan Hu  private val xtvec = Mux(delegS, Mux(delegVS, vstvec, stvec), mtvec)
1475f7af4c74Schengguanghui  private val xtvecBase = xtvec(VAddrBits - 1, 2)
1476a4e57ea3SLi Qianruo  // When MODE=Vectored, all synchronous exceptions into M/S mode
1477a4e57ea3SLi Qianruo  // cause the pc to be set to the address in the BASE field, whereas
1478a4e57ea3SLi Qianruo  // interrupts cause the pc to be set to the address in the BASE field
1479a4e57ea3SLi Qianruo  // plus four times the interrupt cause number.
1480f7af4c74Schengguanghui  private val pcFromXtvec = Cat(xtvecBase + Mux(xtvec(0) && hasIntr, causeNO(3, 0), 0.U), 0.U(2.W))
1481e9341afdSYinan Xu
1482f7af4c74Schengguanghui  // XRet sends redirect instead of Flush and isXRetFlag is true.B before redirect.valid.
1483f7af4c74Schengguanghui  // ROB sends exception at T0 while CSR receives at T2.
1484f7af4c74Schengguanghui  // We add a RegNext here and trapTarget is valid at T3.
1485f7af4c74Schengguanghui  csrio.trapTarget := RegEnable(
1486f7af4c74Schengguanghui    MuxCase(pcFromXtvec, Seq(
1487f7af4c74Schengguanghui      (isXRetFlag && !illegalXret) -> retTargetReg,
1488f7af4c74Schengguanghui      ((hasDebugTrap && !debugMode) || ebreakEnterParkLoop) -> debugTrapTarget
1489f7af4c74Schengguanghui    )),
1490f7af4c74Schengguanghui    isXRetFlag || csrio.exception.valid)
1491f7af4c74Schengguanghui
1492f7af4c74Schengguanghui  when(hasExceptionIntr) {
1493c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1494c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1495d0de7e4aSpeixiaokun    val hstatusOld = WireInit(hstatus.asTypeOf(new HstatusStruct))
1496d0de7e4aSpeixiaokun    val hstatusNew = WireInit(hstatus.asTypeOf(new HstatusStruct))
1497d0de7e4aSpeixiaokun    val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1498d0de7e4aSpeixiaokun    val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1499d4aca96cSlqre    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
1500d4aca96cSlqre    val debugModeNew = WireInit(debugMode)
1501f7af4c74Schengguanghui    when(hasDebugTrap && !debugMode) {
1502f7af4c74Schengguanghui      import DcsrStruct._
1503d4aca96cSlqre      debugModeNew := true.B
15040ffeff0dSXuan Hu      dcsrNew.prv := privilegeMode
15050ffeff0dSXuan Hu      privilegeMode := ModeM
1506f7af4c74Schengguanghui      when(hasDebugIntr) {
1507a4e57ea3SLi Qianruo        dpc := iexceptionPC
1508f7af4c74Schengguanghui        dcsrNew.cause := CAUSE_HALTREQ
1509f7af4c74Schengguanghui        XSDebug(hasDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc)
1510f7af4c74Schengguanghui      }.otherwise { // hasDebugException
1511f7af4c74Schengguanghui        dpc := iexceptionPC // TODO: check it when hasSingleStep
1512f7af4c74Schengguanghui        dcsrNew.cause := MuxCase(0.U, Seq(
1513f7af4c74Schengguanghui          hasTriggerFire -> CAUSE_TRIGGER,
1514*5f28e666Schengguanghui          raiseDebugException -> CAUSE_EBREAK,
1515f7af4c74Schengguanghui          hasBreakPoint -> CAUSE_HALTREQ,
1516f7af4c74Schengguanghui          hasSingleStep -> CAUSE_STEP
1517f7af4c74Schengguanghui        ))
1518d4aca96cSlqre      }
1519d4aca96cSlqre      dcsr := dcsrNew.asUInt
1520d4aca96cSlqre      debugIntrEnable := false.B
1521d7dd1af1SLi Qianruo    }.elsewhen (debugMode) {
1522d7dd1af1SLi Qianruo      //do nothing
1523d61cd5eeSpeixiaokun    }.elsewhen (delegVS) {
152496544367Speixiaokun      vscause := (hasIntr << (XLEN-1)).asUInt | Mux(hasIntr, intrNO - 1.U, exceptionNO)
1525d0de7e4aSpeixiaokun      vsepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1526d0de7e4aSpeixiaokun      vsstatusNew.spp := privilegeMode
1527d0de7e4aSpeixiaokun      vsstatusNew.pie.s := vsstatusOld.ie.s
1528d0de7e4aSpeixiaokun      vsstatusNew.ie.s := false.B
1529d0de7e4aSpeixiaokun      when (clearTval) {vstval := 0.U}
1530d0de7e4aSpeixiaokun      virtMode := true.B
1531d0de7e4aSpeixiaokun      privilegeMode := ModeS
1532d4aca96cSlqre    }.elsewhen (delegS) {
15330214776eSpeixiaokun      val virt = Mux(mstatusOld.mprv.asBool, mstatusOld.mpv, virtMode)
1534d0de7e4aSpeixiaokun      // to do hld st
1535d0de7e4aSpeixiaokun      hstatusNew.gva := (hasInstGuestPageFault || hasLoadGuestPageFault || hasStoreGuestPageFault ||
15361f518b57SXuan Hu                      ((virt.asBool || isHyperInst) && ((hasException && 0.U <= exceptionNO && exceptionNO <= 7.U && exceptionNO =/= 2.U)
1537d0de7e4aSpeixiaokun                      || hasInstrPageFault || hasLoadPageFault || hasStorePageFault)))
1538d0de7e4aSpeixiaokun      hstatusNew.spv := virtMode
1539d0de7e4aSpeixiaokun      when(virtMode){
1540d0de7e4aSpeixiaokun        hstatusNew.spvp := privilegeMode
1541d0de7e4aSpeixiaokun      }
1542d0de7e4aSpeixiaokun      virtMode := false.B
1543c84054caSLinJiawei      scause := causeNO
1544a4e57ea3SLi Qianruo      sepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1545321934c7SKunlin You      mstatusNew.spp := privilegeMode
1546c84054caSLinJiawei      mstatusNew.pie.s := mstatusOld.ie.s
1547c84054caSLinJiawei      mstatusNew.ie.s := false.B
1548321934c7SKunlin You      privilegeMode := ModeS
1549a4e57ea3SLi Qianruo      when (clearTval) { stval := 0.U }
1550d0de7e4aSpeixiaokun      when (clearTval_h) {htval := 0.U}
1551c84054caSLinJiawei    }.otherwise {
15520214776eSpeixiaokun      val virt = Mux(mstatusOld.mprv.asBool, mstatusOld.mpv, virtMode)
1553d0de7e4aSpeixiaokun      // to do hld st
1554d0de7e4aSpeixiaokun      mstatusNew.gva := (hasInstGuestPageFault || hasLoadGuestPageFault || hasStoreGuestPageFault ||
15551f518b57SXuan Hu      ((virt.asBool || isHyperInst) && ((hasException && 0.U <= exceptionNO && exceptionNO <= 7.U && exceptionNO =/= 2.U)
1556d0de7e4aSpeixiaokun        || hasInstrPageFault || hasLoadPageFault || hasStorePageFault)))
1557d0de7e4aSpeixiaokun      mstatusNew.mpv := virtMode
1558d0de7e4aSpeixiaokun      virtMode := false.B
1559c84054caSLinJiawei      mcause := causeNO
1560a4e57ea3SLi Qianruo      mepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1561321934c7SKunlin You      mstatusNew.mpp := privilegeMode
1562c84054caSLinJiawei      mstatusNew.pie.m := mstatusOld.ie.m
1563c84054caSLinJiawei      mstatusNew.ie.m := false.B
1564321934c7SKunlin You      privilegeMode := ModeM
1565a4e57ea3SLi Qianruo      when (clearTval) { mtval := 0.U }
1566d0de7e4aSpeixiaokun      when (clearTval_h) {mtval2 := 0.U}
1567c84054caSLinJiawei    }
1568c84054caSLinJiawei    mstatus := mstatusNew.asUInt
1569d0de7e4aSpeixiaokun    vsstatus := vsstatusNew.asUInt
1570d0de7e4aSpeixiaokun    hstatus := hstatusNew.asUInt
1571d4aca96cSlqre    debugMode := debugModeNew
1572c84054caSLinJiawei  }
1573c84054caSLinJiawei
1574e19f7967SWilliam Wang  // Distributed CSR update req
1575e19f7967SWilliam Wang  //
1576e19f7967SWilliam Wang  // For now we use it to implement customized cache op
157770899835SWilliam Wang  // It can be delayed if necessary
1578e19f7967SWilliam Wang
157970899835SWilliam Wang  val delayedUpdate0 = DelayN(csrio.distributedUpdate(0), 2)
158070899835SWilliam Wang  val delayedUpdate1 = DelayN(csrio.distributedUpdate(1), 2)
158170899835SWilliam Wang  val distributedUpdateValid = delayedUpdate0.w.valid || delayedUpdate1.w.valid
158270899835SWilliam Wang  val distributedUpdateAddr = Mux(delayedUpdate0.w.valid,
158370899835SWilliam Wang    delayedUpdate0.w.bits.addr,
158470899835SWilliam Wang    delayedUpdate1.w.bits.addr
158570899835SWilliam Wang  )
158670899835SWilliam Wang  val distributedUpdateData = Mux(delayedUpdate0.w.valid,
158770899835SWilliam Wang    delayedUpdate0.w.bits.data,
158870899835SWilliam Wang    delayedUpdate1.w.bits.data
158970899835SWilliam Wang  )
159070899835SWilliam Wang
159170899835SWilliam Wang  assert(!(delayedUpdate0.w.valid && delayedUpdate1.w.valid))
159270899835SWilliam Wang
159370899835SWilliam Wang  when(distributedUpdateValid){
1594e19f7967SWilliam Wang    // cacheopRegs can be distributed updated
1595e19f7967SWilliam Wang    CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
159670899835SWilliam Wang      when((Scachebase + attribute("offset").toInt).U === distributedUpdateAddr){
159770899835SWilliam Wang        cacheopRegs(name) := distributedUpdateData
1598e19f7967SWilliam Wang      }
1599e19f7967SWilliam Wang    }}
1600e19f7967SWilliam Wang  }
1601e19f7967SWilliam Wang
16029ef181f4SWilliam Wang  // Cache error debug support
16039ef181f4SWilliam Wang  if(HasCustomCSRCacheOp){
16049ef181f4SWilliam Wang    val cache_error_decoder = Module(new CSRCacheErrorDecoder)
16059ef181f4SWilliam Wang    cache_error_decoder.io.encoded_cache_error := cacheopRegs("CACHE_ERROR")
16069ef181f4SWilliam Wang  }
16079ef181f4SWilliam Wang
1608e30fd06aSYinan Xu  // Implicit add reset values for mepc[0] and sepc[0]
1609e30fd06aSYinan Xu  // TODO: rewrite mepc and sepc using a struct-like style with the LSB always being 0
161067ba96b4SYinan Xu  when (RegNext(RegNext(reset.asBool) && !reset.asBool)) {
1611e30fd06aSYinan Xu    mepc := Cat(mepc(XLEN - 1, 1), 0.U(1.W))
1612e30fd06aSYinan Xu    sepc := Cat(sepc(XLEN - 1, 1), 0.U(1.W))
161321ae6bc4Speixiaokun    vsepc := Cat(vsepc(XLEN - 1, 1), 0.U(1.W))
1614e30fd06aSYinan Xu  }
1615e30fd06aSYinan Xu
1616c84054caSLinJiawei  def readWithScala(addr: Int): UInt = mapping(addr)._1
1617c84054caSLinJiawei
1618f7af4c74Schengguanghui  val difftestIntrNO = Mux(hasIntr, causeNO, 0.U)
1619a165bd69Swangkaifan
1620cbe9a847SYinan Xu  // Always instantiate basic difftest modules.
1621cbe9a847SYinan Xu  if (env.AlwaysBasicDiff || env.EnableDifftest) {
16227d45a146SYinan Xu    val difftest = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true)
16237d45a146SYinan Xu    difftest.coreid      := csrio.hartId
16247d45a146SYinan Xu    difftest.valid       := csrio.exception.valid
1625f7af4c74Schengguanghui    difftest.interrupt   := Mux(hasIntr, causeNO, 0.U)
1626f7af4c74Schengguanghui    difftest.exception   := Mux(hasException, causeNO, 0.U)
16277d45a146SYinan Xu    difftest.exceptionPC := dexceptionPC
1628a4e57ea3SLi Qianruo    if (env.EnableDifftest) {
16294b0d80d8SXuan Hu      difftest.exceptionInst := csrio.exception.bits.instr
1630a4e57ea3SLi Qianruo    }
16312225d46eSJiawei Lin  }
16322225d46eSJiawei Lin
1633cbe9a847SYinan Xu  // Always instantiate basic difftest modules.
1634cbe9a847SYinan Xu  if (env.AlwaysBasicDiff || env.EnableDifftest) {
16357d45a146SYinan Xu    val difftest = DifftestModule(new DiffCSRState)
16367d45a146SYinan Xu    difftest.coreid := csrio.hartId
1637321934c7SKunlin You    difftest.privilegeMode := privilegeMode
16387d45a146SYinan Xu    difftest.mstatus := mstatus
16397d45a146SYinan Xu    difftest.sstatus := mstatus & sstatusRmask
16407d45a146SYinan Xu    difftest.mepc := mepc
16417d45a146SYinan Xu    difftest.sepc := sepc
16427d45a146SYinan Xu    difftest.mtval:= mtval
16437d45a146SYinan Xu    difftest.stval:= stval
16447d45a146SYinan Xu    difftest.mtvec := mtvec
16457d45a146SYinan Xu    difftest.stvec := stvec
16467d45a146SYinan Xu    difftest.mcause := mcause
16477d45a146SYinan Xu    difftest.scause := scause
16487d45a146SYinan Xu    difftest.satp := satp
16497d45a146SYinan Xu    difftest.mip := mipReg
16507d45a146SYinan Xu    difftest.mie := mie
16517d45a146SYinan Xu    difftest.mscratch := mscratch
16527d45a146SYinan Xu    difftest.sscratch := sscratch
16537d45a146SYinan Xu    difftest.mideleg := mideleg
16547d45a146SYinan Xu    difftest.medeleg := medeleg
1655a165bd69Swangkaifan  }
1656a4e57ea3SLi Qianruo
1657a4e57ea3SLi Qianruo  if (env.AlwaysBasicDiff || env.EnableDifftest) {
165887d0ba30Speixiaokun    val difftest = DifftestModule(new DiffHCSRState)
165987d0ba30Speixiaokun    difftest.coreid := csrio.hartId
166087d0ba30Speixiaokun    difftest.virtMode := virtMode
166187d0ba30Speixiaokun    difftest.mtval2 := mtval2
166287d0ba30Speixiaokun    difftest.mtinst := mtinst
166387d0ba30Speixiaokun    difftest.hstatus := hstatus
166487d0ba30Speixiaokun    difftest.hideleg := hideleg
166587d0ba30Speixiaokun    difftest.hedeleg := hedeleg
166687d0ba30Speixiaokun    difftest.hcounteren := hcounteren
166787d0ba30Speixiaokun    difftest.htval := htval
166887d0ba30Speixiaokun    difftest.htinst := htinst
166987d0ba30Speixiaokun    difftest.hgatp := hgatp
167087d0ba30Speixiaokun    difftest.vsstatus := vsstatus
167187d0ba30Speixiaokun    difftest.vstvec := vstvec
167287d0ba30Speixiaokun    difftest.vsepc := vsepc
167387d0ba30Speixiaokun    difftest.vscause := vscause
167487d0ba30Speixiaokun    difftest.vstval := vstval
167587d0ba30Speixiaokun    difftest.vsatp := vsatp
167687d0ba30Speixiaokun    difftest.vsscratch := vsscratch
1677d0de7e4aSpeixiaokun  }
1678d0de7e4aSpeixiaokun
1679d0de7e4aSpeixiaokun  if(env.AlwaysBasicDiff || env.EnableDifftest) {
16807d45a146SYinan Xu    val difftest = DifftestModule(new DiffDebugMode)
16817d45a146SYinan Xu    difftest.coreid := csrio.hartId
16827d45a146SYinan Xu    difftest.debugMode := debugMode
16837d45a146SYinan Xu    difftest.dcsr := dcsr
16847d45a146SYinan Xu    difftest.dpc := dpc
1685f7af4c74Schengguanghui    difftest.dscratch0 := dscratch0
16867d45a146SYinan Xu    difftest.dscratch1 := dscratch1
1687a4e57ea3SLi Qianruo  }
168835d1557aSZiyue Zhang
168935d1557aSZiyue Zhang  if (env.AlwaysBasicDiff || env.EnableDifftest) {
169083ba63b3SXuan Hu    val difftest = DifftestModule(new DiffVecCSRState)
169183ba63b3SXuan Hu    difftest.coreid := csrio.hartId
169283ba63b3SXuan Hu    difftest.vstart := vstart
169383ba63b3SXuan Hu    difftest.vxsat := vcsr.asTypeOf(new VcsrStruct).vxsat
169483ba63b3SXuan Hu    difftest.vxrm := vcsr.asTypeOf(new VcsrStruct).vxrm
169583ba63b3SXuan Hu    difftest.vcsr := vcsr
169683ba63b3SXuan Hu    difftest.vl := vl
169783ba63b3SXuan Hu    difftest.vtype := vtype
169883ba63b3SXuan Hu    difftest.vlenb := vlenb
169935d1557aSZiyue Zhang  }
1700c84054caSLinJiawei}
17011545277aSYinan Xu
1702cd365d4cSrvcoresjwclass PFEvent(implicit p: Parameters) extends XSModule with HasCSRConst  {
1703cd365d4cSrvcoresjw  val io = IO(new Bundle {
1704cd365d4cSrvcoresjw    val distribute_csr = Flipped(new DistributedCSRIO())
1705cd365d4cSrvcoresjw    val hpmevent = Output(Vec(29, UInt(XLEN.W)))
1706cd365d4cSrvcoresjw  })
1707cd365d4cSrvcoresjw
1708cd365d4cSrvcoresjw  val w = io.distribute_csr.w
1709cd365d4cSrvcoresjw
17105fd90906Srvcoresjw  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
17115fd90906Srvcoresjw                   List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
17125fd90906Srvcoresjw                   List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
17135fd90906Srvcoresjw                   List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
1714cd365d4cSrvcoresjw
171512c44ce5Srvcoresjw  val perfEventMapping = (0 until 29).map(i => {Map(
171612c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmevent3 +i,
171712c44ce5Srvcoresjw                 reg  = perfEvents(i),
171812c44ce5Srvcoresjw                 wmask = "hf87fff3fcff3fcff".U(XLEN.W))
171912c44ce5Srvcoresjw  )}).fold(Map())((a,b) => a ++ b)
1720cd365d4cSrvcoresjw
1721cd365d4cSrvcoresjw  val rdata = Wire(UInt(XLEN.W))
1722cd365d4cSrvcoresjw  MaskedRegMap.generate(perfEventMapping, w.bits.addr, rdata, w.valid, w.bits.data)
17235fd90906Srvcoresjw  for(i <- 0 until 29){
17245fd90906Srvcoresjw    io.hpmevent(i) := perfEvents(i)
17255fd90906Srvcoresjw  }
1726cd365d4cSrvcoresjw}
1727