xref: /XiangShan/src/main/scala/xiangshan/backend/fu/CSR.scala (revision 8cfc24b28454f1915c339ce79485711f8e438f59)
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._
3192c61038SXuan Huimport xiangshan.backend.Bundles.{ExceptionInfo, TrapInstInfo}
32c1b28b66STang Haojinimport xiangshan.backend.fu.NewCSR.CSREvents.TargetPCBundle
33039cdc35SXuan Huimport xiangshan.backend.fu.NewCSR.CSRNamedConstant.ContextStatus
34c1b28b66STang Haojinimport xiangshan.backend.rob.RobPtr
3562a2cb19SXuan Huimport utils.MathUtils.{BigIntGenMask, BigIntNot}
364907ec88Schengguanghuiimport xiangshan.backend.trace._
37075d4937Sjunxiong-jiimport freechips.rocketchip.rocket.CSRs
38c84054caSLinJiawei
392225d46eSJiawei Linclass FpuCsrIO extends Bundle {
407f1506e3SLinJiawei  val fflags = Output(Valid(UInt(5.W)))
41c84054caSLinJiawei  val isIllegal = Output(Bool())
42c84054caSLinJiawei  val dirty_fs = Output(Bool())
43c84054caSLinJiawei  val frm = Input(UInt(3.W))
44c84054caSLinJiawei}
45c84054caSLinJiawei
46daa01159SZiyue Zhangclass VpuCsrIO(implicit p: Parameters) extends XSBundle {
47daa01159SZiyue Zhang  val vstart = Input(UInt(XLEN.W))
48daa01159SZiyue Zhang  val vxrm = Input(UInt(2.W))
49daa01159SZiyue Zhang
50d8a50338SZiyue Zhang  val vl = Output(UInt(XLEN.W))
51daa01159SZiyue Zhang
5235d1557aSZiyue Zhang  val set_vstart = Output(Valid(UInt(XLEN.W)))
5335d1557aSZiyue Zhang  val set_vtype = Output(Valid(UInt(XLEN.W)))
546355a2b7Sczw  val set_vxsat = Output(Valid(UInt(1.W)))
55daa01159SZiyue Zhang
56daa01159SZiyue Zhang  val dirty_vs = Output(Bool())
57daa01159SZiyue Zhang}
58daa01159SZiyue Zhang
59b2e234ebSLinJiawei
602225d46eSJiawei Linclass PerfCounterIO(implicit p: Parameters) extends XSBundle {
611ca0e4f3SYinan Xu  val perfEventsFrontend  = Vec(numCSRPCntFrontend, new PerfEvent)
62e1a85e9fSchengguanghui  val perfEventsBackend   = Vec(numCSRPCntCtrl, new PerfEvent)
631ca0e4f3SYinan Xu  val perfEventsLsu       = Vec(numCSRPCntLsu, new PerfEvent)
648bb30a57SJiru Sun  val perfEventsHc        = Vec(numPCntHc * coreParams.L2NBanks + 1, new PerfEvent)
658419d406SXuan Hu  val retiredInstr = UInt(7.W)
66edd6ddbcSwakafa  val frontendInfo = new Bundle {
67edd6ddbcSwakafa    val ibufFull  = Bool()
68e0d9a9f0SLingrui98    val bpuInfo = new Bundle {
69e0d9a9f0SLingrui98      val bpRight = UInt(XLEN.W)
70e0d9a9f0SLingrui98      val bpWrong = UInt(XLEN.W)
71e0d9a9f0SLingrui98    }
72edd6ddbcSwakafa  }
73edd6ddbcSwakafa  val ctrlInfo = new Bundle {
749aca92b9SYinan Xu    val robFull   = Bool()
75edd6ddbcSwakafa    val intdqFull = Bool()
76edd6ddbcSwakafa    val fpdqFull  = Bool()
77edd6ddbcSwakafa    val lsdqFull  = Bool()
78edd6ddbcSwakafa  }
79edd6ddbcSwakafa  val memInfo = new Bundle {
80edd6ddbcSwakafa    val sqFull = Bool()
81edd6ddbcSwakafa    val lqFull = Bool()
82edd6ddbcSwakafa    val dcacheMSHRFull = Bool()
83edd6ddbcSwakafa  }
8462ab1317SYinan Xu}
8562ab1317SYinan Xu
862225d46eSJiawei Linclass CSRFileIO(implicit p: Parameters) extends XSBundle {
87f57f7f2aSYangyu Chen  val hartId = Input(UInt(hartIdLen.W))
88129a273eSYinan Xu  // output (for func === CSROpType.jmp)
89edd6ddbcSwakafa  val perf = Input(new PerfCounterIO)
90a751b11aSchengguanghui  val criticalErrorState = Output(Bool())
918635f18fSwangkaifan  val isPerfCnt = Output(Bool())
92129a273eSYinan Xu  // to FPU
93129a273eSYinan Xu  val fpu = Flipped(new FpuCsrIO)
94daa01159SZiyue Zhang  // to VPU
95daa01159SZiyue Zhang  val vpu = Flipped(new VpuCsrIO)
96bf9968b2SYinan Xu  // from rob
973a474d38SYinan Xu  val exception = Flipped(ValidIO(new ExceptionInfo))
98c1b28b66STang Haojin  val robDeqPtr = Input(new RobPtr)
99129a273eSYinan Xu  // to ROB
100ac5a5d53SLinJiawei  val isXRet = Output(Bool())
101c1b28b66STang Haojin  val trapTarget = Output(new TargetPCBundle)
102129a273eSYinan Xu  val interrupt = Output(Bool())
1035c95ea2eSYinan Xu  val wfi_event = Output(Bool())
104c308d936Schengguanghui  //trace
105c308d936Schengguanghui  val traceCSR = Output(new TraceCSR)
106129a273eSYinan Xu  // from LSQ
107db6cfb5aSHaoyuan Feng  val memExceptionVAddr = Input(UInt(XLEN.W))
108db6cfb5aSHaoyuan Feng  val memExceptionGPAddr = Input(UInt(XLEN.W))
109ad415ae0SXiaokun-Pei  val memExceptionIsForVSnonLeafPTE = Input(Bool())
110129a273eSYinan Xu  // from outside cpu,externalInterrupt
1115f705224Sxiaofeibao-xjtu  val externalInterrupt = Input(new ExternalInterruptIO)
112129a273eSYinan Xu  // TLB
113129a273eSYinan Xu  val tlb = Output(new TlbCsrBundle)
114d4aca96cSlqre  // Debug Mode
115d7dd1af1SLi Qianruo  // val singleStep = Output(Bool())
116d4aca96cSlqre  val debugMode = Output(Bool())
117e377d77eSWilliam Wang  // Custom microarchiture ctrl signal
118e377d77eSWilliam Wang  val customCtrl = Output(new CustomCSRCtrlIO)
119c1b28b66STang Haojin  // instruction fetch address translation type
120c1b28b66STang Haojin  val instrAddrTransType = Output(new AddrTransType)
121*8cfc24b2STang Haojin  // ack for axireg from imsic. which indicates imsic can work actively
122*8cfc24b2STang Haojin  val msiAck = Output(Bool())
12335a47a38SYinan Xu}
12435a47a38SYinan Xu
125a8db15d8Sfdyclass VtypeStruct(implicit p: Parameters) extends XSBundle {
126a8db15d8Sfdy  val vill = UInt(1.W)
127a8db15d8Sfdy  val reserved = UInt((XLEN - 9).W)
128a8db15d8Sfdy  val vma = UInt(1.W)
129a8db15d8Sfdy  val vta = UInt(1.W)
130a8db15d8Sfdy  val vsew = UInt(3.W)
131a8db15d8Sfdy  val vlmul = UInt(3.W)
132a8db15d8Sfdy}
1337e0f64b0SGuanghui Cheng/*
134d91483a6Sfdyclass CSR(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg)
1353b739f49SXuan Hu  with HasCSRConst
1363b739f49SXuan Hu  with PMPMethod
1373b739f49SXuan Hu  with PMAMethod
1383b739f49SXuan Hu  with HasXSParameter
139f7af4c74Schengguanghui  with SdtrigExt
140f7af4c74Schengguanghui  with DebugCSR
14135a47a38SYinan Xu{
1423b739f49SXuan Hu  val csrio = io.csrio.get
143c84054caSLinJiawei
144e18c367fSLinJiawei  val flushPipe = Wire(Bool())
145c84054caSLinJiawei
146e18c367fSLinJiawei  val (valid, src1, src2, func) = (
147e18c367fSLinJiawei    io.in.valid,
1486a35d972SXuan Hu    io.in.bits.data.src(0),
1496a35d972SXuan Hu    io.in.bits.data.imm,
1506a35d972SXuan Hu    io.in.bits.ctrl.fuOpType
151e18c367fSLinJiawei  )
152c84054caSLinJiawei
153c84054caSLinJiawei  // CSR define
154d0de7e4aSpeixiaokun  val virtMode = RegInit(false.B)
155d0de7e4aSpeixiaokun  csrio.customCtrl.virtMode := virtMode
156c84054caSLinJiawei
157c84054caSLinJiawei  class Priv extends Bundle {
158c84054caSLinJiawei    val m = Output(Bool())
159d0de7e4aSpeixiaokun    val h = Output(Bool()) // unused
160c84054caSLinJiawei    val s = Output(Bool())
161c84054caSLinJiawei    val u = Output(Bool())
162c84054caSLinJiawei  }
163c84054caSLinJiawei
164c84054caSLinJiawei  class MstatusStruct extends Bundle {
165c84054caSLinJiawei    val sd = Output(UInt(1.W))
1668e7b11e5SWilliam Wang
167d0de7e4aSpeixiaokun    val pad1 = if (XLEN == 64 && HasHExtension) Output(UInt(23.W)) else if (XLEN == 64) Output(UInt(25.W)) else null
168d0de7e4aSpeixiaokun    val mpv  = if (XLEN == 64 && HasHExtension) Output(UInt(1.W)) else null
169d0de7e4aSpeixiaokun    val gva  = if (XLEN == 64 && HasHExtension) Output(UInt(1.W)) else null
1707d9edc86SLemover    val mbe  = if (XLEN == 64) Output(UInt(1.W)) else null
1717d9edc86SLemover    val sbe  = if (XLEN == 64) Output(UInt(1.W)) else null
1728e7b11e5SWilliam Wang    val sxl  = if (XLEN == 64) Output(UInt(2.W))  else null
1738e7b11e5SWilliam Wang    val uxl  = if (XLEN == 64) Output(UInt(2.W))  else null
1748e7b11e5SWilliam Wang    val pad0 = if (XLEN == 64) Output(UInt(9.W))  else Output(UInt(8.W))
1758e7b11e5SWilliam Wang
176c84054caSLinJiawei    val tsr = Output(UInt(1.W))
177c84054caSLinJiawei    val tw = Output(UInt(1.W))
1788e7b11e5SWilliam Wang    val tvm = Output(UInt(1.W))
179c84054caSLinJiawei    val mxr = Output(UInt(1.W))
180c84054caSLinJiawei    val sum = Output(UInt(1.W))
181c84054caSLinJiawei    val mprv = Output(UInt(1.W))
182c84054caSLinJiawei    val xs = Output(UInt(2.W))
183c84054caSLinJiawei    val fs = Output(UInt(2.W))
184c84054caSLinJiawei    val mpp = Output(UInt(2.W))
185daa01159SZiyue Zhang    val vs = Output(UInt(2.W))
186c84054caSLinJiawei    val spp = Output(UInt(1.W))
187c84054caSLinJiawei    val pie = new Priv
188c84054caSLinJiawei    val ie = new Priv
189c84054caSLinJiawei    assert(this.getWidth == XLEN)
1907d9edc86SLemover
1917d9edc86SLemover    def ube = pie.h // a little ugly
1927d9edc86SLemover    def ube_(r: UInt): Unit = {
1937d9edc86SLemover      pie.h := r(0)
1947d9edc86SLemover    }
195c84054caSLinJiawei  }
196c84054caSLinJiawei
197d0de7e4aSpeixiaokun  class HstatusStruct extends Bundle {
198d0de7e4aSpeixiaokun    val pad4 = if (HSXLEN == 64) Output(UInt(30.W)) else null
199d0de7e4aSpeixiaokun    val vsxl = if (HSXLEN == 64) Output(UInt(2.W)) else null
200d0de7e4aSpeixiaokun    val pad3 = Output(UInt(9.W))
201d0de7e4aSpeixiaokun    val vtsr = Output(UInt(1.W))
202d0de7e4aSpeixiaokun    val vtw = Output(UInt(1.W))
203d0de7e4aSpeixiaokun    val vtvm = Output(UInt(1.W))
204d0de7e4aSpeixiaokun    val pad2 = Output(UInt(2.W))
205d0de7e4aSpeixiaokun    val vgein = Output(UInt(6.W))
206d0de7e4aSpeixiaokun    val pad1 = Output(UInt(2.W))
207d0de7e4aSpeixiaokun    val hu = Output(UInt(1.W))
208d0de7e4aSpeixiaokun    val spvp = Output(UInt(1.W))
209d0de7e4aSpeixiaokun    val spv = Output(UInt(1.W))
210d0de7e4aSpeixiaokun    val gva = Output(UInt(1.W))
211d0de7e4aSpeixiaokun    val vsbe = Output(UInt(1.W))
212d0de7e4aSpeixiaokun    val pad0 = Output(UInt(5.W))
213d0de7e4aSpeixiaokun    assert(this.getWidth == XLEN)
214d0de7e4aSpeixiaokun  }
215d0de7e4aSpeixiaokun
216c84054caSLinJiawei  class Interrupt extends Bundle {
217d4aca96cSlqre//  val d = Output(Bool())    // Debug
218c84054caSLinJiawei    val e = new Priv
219c84054caSLinJiawei    val t = new Priv
220c84054caSLinJiawei    val s = new Priv
221c84054caSLinJiawei  }
222c84054caSLinJiawei
223d4aca96cSlqre  // Debug CSRs
224f7af4c74Schengguanghui  val dcsr = RegInit(UInt(32.W), DcsrStruct.init)
225d4aca96cSlqre  val dpc = Reg(UInt(64.W))
226f7af4c74Schengguanghui  val dscratch0 = Reg(UInt(64.W))
227d4aca96cSlqre  val dscratch1 = Reg(UInt(64.W))
228d4aca96cSlqre  val debugMode = RegInit(false.B)
229f7af4c74Schengguanghui  val debugIntrEnable = RegInit(true.B) // debug interrupt will be handle only when debugIntrEnable
230d4aca96cSlqre  csrio.debugMode := debugMode
231d4aca96cSlqre
232d4aca96cSlqre  val dpcPrev = RegNext(dpc)
2331097f021SLi Qianruo  XSDebug(dpcPrev =/= dpc, "Debug Mode: dpc is altered! Current is %x, previous is %x\n", dpc, dpcPrev)
234d4aca96cSlqre
235d4aca96cSlqre  val dcsrData = Wire(new DcsrStruct)
236d4aca96cSlqre  dcsrData := dcsr.asTypeOf(new DcsrStruct)
237d7dd1af1SLi Qianruo  val dcsrMask = ZeroExt(GenMask(15) | GenMask(13, 11) | GenMask(4) | GenMask(2, 0), XLEN)// Dcsr write mask
238d4aca96cSlqre  def dcsrUpdateSideEffect(dcsr: UInt): UInt = {
239d4aca96cSlqre    val dcsrOld = WireInit(dcsr.asTypeOf(new DcsrStruct))
240d4aca96cSlqre    val dcsrNew = dcsr | (dcsrOld.prv(0) | dcsrOld.prv(1)).asUInt // turn 10 priv into 11
241d4aca96cSlqre    dcsrNew
242d4aca96cSlqre  }
243d7dd1af1SLi Qianruo  // csrio.singleStep := dcsrData.step
244d7dd1af1SLi Qianruo  csrio.customCtrl.singlestep := dcsrData.step && !debugMode
245d4aca96cSlqre
24672951335SLi Qianruo  // Trigger CSRs
247f7af4c74Schengguanghui  private val tselectPhy = RegInit(0.U(log2Up(TriggerNum).W))
24872951335SLi Qianruo
249f7af4c74Schengguanghui  private val tdata1RegVec = RegInit(VecInit(Seq.fill(TriggerNum)(Tdata1Bundle.default)))
250f7af4c74Schengguanghui  private val tdata2RegVec = RegInit(VecInit(Seq.fill(TriggerNum)(0.U(64.W))))
251f7af4c74Schengguanghui  private val tdata1WireVec = tdata1RegVec.map(_.asTypeOf(new Tdata1Bundle))
252f7af4c74Schengguanghui  private val tdata2WireVec = tdata2RegVec
253f7af4c74Schengguanghui  private val tdata1Selected = tdata1RegVec(tselectPhy).asTypeOf(new Tdata1Bundle)
254f7af4c74Schengguanghui  private val tdata2Selected = tdata2RegVec(tselectPhy)
255f7af4c74Schengguanghui  private val newTriggerChainVec = UIntToOH(tselectPhy, TriggerNum).asBools | tdata1WireVec.map(_.data.asTypeOf(new MControlData).chain)
256f7af4c74Schengguanghui  private val newTriggerChainIsLegal = TriggerCheckChainLegal(newTriggerChainVec, TriggerChainMaxLength)
257f7af4c74Schengguanghui  val tinfo = RegInit((BigInt(1) << TrigTypeEnum.MCONTROL.litValue.toInt).U(XLEN.W)) // This value should be 4.U
258716f717fSLi Qianruo
25972951335SLi Qianruo
26072951335SLi Qianruo  def WriteTselect(wdata: UInt) = {
2615f28e666Schengguanghui    Mux(wdata < TriggerNum.U, wdata(log2Up(TriggerNum) - 1, 0), tselectPhy)
26272951335SLi Qianruo  }
26372951335SLi Qianruo
264f7af4c74Schengguanghui  def GenTdataDistribute(tdata1: Tdata1Bundle, tdata2: UInt): MatchTriggerIO = {
26572951335SLi Qianruo    val res = Wire(new MatchTriggerIO)
266f7af4c74Schengguanghui    val mcontrol: MControlData = WireInit(tdata1.data.asTypeOf(new MControlData))
267f7af4c74Schengguanghui    res.matchType := mcontrol.match_.asUInt
268f7af4c74Schengguanghui    res.select    := mcontrol.select
269f7af4c74Schengguanghui    res.timing    := mcontrol.timing
270f7af4c74Schengguanghui    res.action    := mcontrol.action.asUInt
271f7af4c74Schengguanghui    res.chain     := mcontrol.chain
272f7af4c74Schengguanghui    res.execute   := mcontrol.execute
273f7af4c74Schengguanghui    res.load      := mcontrol.load
274f7af4c74Schengguanghui    res.store     := mcontrol.store
27572951335SLi Qianruo    res.tdata2    := tdata2
27672951335SLi Qianruo    res
27772951335SLi Qianruo  }
27872951335SLi Qianruo
279f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tUpdate.bits.addr := tselectPhy
280f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tUpdate.bits.addr := tselectPhy
281f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tUpdate.bits.tdata := GenTdataDistribute(tdata1Selected, tdata2Selected)
282f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tUpdate.bits.tdata := GenTdataDistribute(tdata1Selected, tdata2Selected)
28372951335SLi Qianruo
284c84054caSLinJiawei  // Machine-Level CSRs
285a4e57ea3SLi Qianruo  // mtvec: {BASE (WARL), MODE (WARL)} where mode is 0 or 1
286a4e57ea3SLi Qianruo  val mtvecMask = ~(0x2.U(XLEN.W))
287c84054caSLinJiawei  val mtvec = RegInit(UInt(XLEN.W), 0.U)
288c84054caSLinJiawei  val mcounteren = RegInit(UInt(XLEN.W), 0.U)
289e4b1ccacSxuzefan  // Currently, XiangShan don't support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
290e4b1ccacSxuzefan  val mcounterenMask = 0.U(XLEN.W)
291c84054caSLinJiawei  val mcause = RegInit(UInt(XLEN.W), 0.U)
292c84054caSLinJiawei  val mtval = RegInit(UInt(XLEN.W), 0.U)
293d0de7e4aSpeixiaokun  val mtval2 = RegInit(UInt(XLEN.W), 0.U)
294d0de7e4aSpeixiaokun  val mtinst = RegInit(UInt(XLEN.W), 0.U)
295d0de7e4aSpeixiaokun  val mepc = RegInit(UInt(XLEN.W), 0.U)
296e30fd06aSYinan Xu  // Page 36 in riscv-priv: The low bit of mepc (mepc[0]) is always zero.
297e30fd06aSYinan Xu  val mepcMask = ~(0x1.U(XLEN.W))
298c84054caSLinJiawei
299c84054caSLinJiawei  val mie = RegInit(0.U(XLEN.W))
300c84054caSLinJiawei  val mipWire = WireInit(0.U.asTypeOf(new Interrupt))
3015dabf2dfSYinan Xu  val mipReg  = RegInit(0.U(XLEN.W))
302d7e392d1Sxuzefan  val mipMask = ZeroExt(Array(
303d7e392d1Sxuzefan    1,  // SSIP
304d7e392d1Sxuzefan    2,  // VSSIP
305d7e392d1Sxuzefan    3,  // MSIP
306d7e392d1Sxuzefan    5,  // STIP
307d7e392d1Sxuzefan    6,  // VSTIP
308d7e392d1Sxuzefan    7,  // MTIP
309d7e392d1Sxuzefan    9,  // SEIP
310d7e392d1Sxuzefan    10, // VSEIP
311d7e392d1Sxuzefan    11, // MEIP
312d7e392d1Sxuzefan    12, // SGEIP
313d7e392d1Sxuzefan  ).map(GenMask(_)).reduce(_ | _), XLEN)
314c84054caSLinJiawei  val mip = (mipWire.asUInt | mipReg).asTypeOf(new Interrupt)
315c84054caSLinJiawei
316d0de7e4aSpeixiaokun  val mip_mie_WMask_H = if(HasHExtension){((1 << 2) | (1 << 6) | (1 << 10) | (1 << 12)).U(XLEN.W)}else{0.U(XLEN.W)}
317d0de7e4aSpeixiaokun  val vssip_Mask = (1 << 2).U(XLEN.W)
318d0de7e4aSpeixiaokun
319d0de7e4aSpeixiaokun  val mipWMask = vssip_Mask | ((1 << 9) | (1 << 5) | (1 << 1)).U(XLEN.W)
32044f8e3e4Speixiaokun  val mieWMask = mip_mie_WMask_H | "haaa".U(XLEN.W)
321d0de7e4aSpeixiaokun
32267ba96b4SYinan Xu  def getMisaMxl(mxl: BigInt): BigInt = mxl << (XLEN - 2)
32367ba96b4SYinan Xu  def getMisaExt(ext: Char): Long = 1 << (ext.toInt - 'a'.toInt)
324c84054caSLinJiawei  var extList = List('a', 's', 'i', 'u')
325c84054caSLinJiawei  if (HasMExtension) { extList = extList :+ 'm' }
326c84054caSLinJiawei  if (HasCExtension) { extList = extList :+ 'c' }
327d0de7e4aSpeixiaokun  if (HasHExtension) { extList = extList :+ 'h' }
328c84054caSLinJiawei  if (HasFPU) { extList = extList ++ List('f', 'd') }
3290ba52110SZiyue Zhang  if (HasVPU) { extList = extList :+ 'v' }
330d0de7e4aSpeixiaokun  val misaInitVal = getMisaMxl(2) | extList.foldLeft(0L)((sum, i) => sum | getMisaExt(i)) //"h8000000000141185".U
33167ba96b4SYinan Xu  val misa = RegInit(UInt(XLEN.W), misaInitVal.U)
332ddb6dcf0SXuan Hu  println(s"[CSR] supported isa ext: $extList")
333bc5ff277Swangkaifan
334c84054caSLinJiawei  // MXL = 2          | 0 | EXT = b 00 0000 0100 0001 0001 0000 0101
335c84054caSLinJiawei  // (XLEN-1, XLEN-2) |   |(25, 0)  ZY XWVU TSRQ PONM LKJI HGFE DCBA
336c84054caSLinJiawei
33706490c40Speixiaokun  // Machine Configuration
33806490c40Speixiaokun  val menvcfg = RegInit(UInt(XLEN.W), 0.U)
33906490c40Speixiaokun
340c84054caSLinJiawei  val mvendorid = RegInit(UInt(XLEN.W), 0.U) // this is a non-commercial implementation
341e1b773eaSLuo 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
342c84054caSLinJiawei  val mimpid = RegInit(UInt(XLEN.W), 0.U) // provides a unique encoding of the version of the processor implementation
34367ba96b4SYinan Xu  val mhartid = Reg(UInt(XLEN.W)) // the hardware thread running the code
34467ba96b4SYinan Xu  when (RegNext(RegNext(reset.asBool) && !reset.asBool)) {
34567ba96b4SYinan Xu    mhartid := csrio.hartId
34667ba96b4SYinan Xu  }
3477d9edc86SLemover  val mconfigptr = RegInit(UInt(XLEN.W), 0.U) // the read-only pointer pointing to the platform config structure, 0 for not supported.
34862a2cb19SXuan Hu  val mstatus = RegInit("ha00002200".U(XLEN.W))
349bc5ff277Swangkaifan
350c84054caSLinJiawei  // mstatus Value Table
35162a2cb19SXuan Hu  // | sd   | Read Only
35262a2cb19SXuan Hu  // | pad1 | WPRI
353c84054caSLinJiawei  // | sxl  | hardlinked to 10, use 00 to pass xv6 test
354e30fd06aSYinan Xu  // | uxl  | hardlinked to 10
355c84054caSLinJiawei  // | pad0 |
356c84054caSLinJiawei  // | tsr  |
357c84054caSLinJiawei  // | tw   |
3588e7b11e5SWilliam Wang  // | tvm  |
359c84054caSLinJiawei  // | mxr  |
360c84054caSLinJiawei  // | sum  |
361c84054caSLinJiawei  // | mprv |
362c84054caSLinJiawei  // | xs   | 00 |
36380dd83d8SYinan Xu  // | fs   | 01 |
364c84054caSLinJiawei  // | mpp  | 00 |
36562a2cb19SXuan Hu  // | vs   | 01 |
366c84054caSLinJiawei  // | spp  | 0 |
3678e7b11e5SWilliam Wang  // | pie  | 0000 | pie.h is used as UBE
368c84054caSLinJiawei  // | ie   | 0000 | uie hardlinked to 0, as N ext is not implemented
369bc5ff277Swangkaifan
370c84054caSLinJiawei  val mstatusStruct = mstatus.asTypeOf(new MstatusStruct)
371c84054caSLinJiawei  def mstatusUpdateSideEffect(mstatus: UInt): UInt = {
372c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
37362a2cb19SXuan Hu    // Cat(sd, other)
37462a2cb19SXuan Hu    val mstatusNew = Cat(
37562a2cb19SXuan Hu      mstatusOld.xs === ContextStatus.dirty || mstatusOld.fs === ContextStatus.dirty || mstatusOld.vs === ContextStatus.dirty,
37662a2cb19SXuan Hu      mstatus(XLEN-2, 0)
37762a2cb19SXuan Hu    )
378c84054caSLinJiawei    mstatusNew
379c84054caSLinJiawei  }
38085052be5Speixiaokun  def vsstatusUpdateSideEffect(vsstatus: UInt): UInt = {
38185052be5Speixiaokun    val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
38285052be5Speixiaokun    val vsstatusNew = Cat(vsstatusOld.xs === "b11".U || vsstatusOld.fs === "b11".U, vsstatus(XLEN-2, 0))
38385052be5Speixiaokun    vsstatusNew
38485052be5Speixiaokun  }
385e30fd06aSYinan Xu  val mstatusWMask = (~ZeroExt((
38662a2cb19SXuan Hu    GenMask(63)           | // SD is read-only
3872c64ad7cSXiaokun-Pei    (if(HasHExtension)
3882c64ad7cSXiaokun-Pei        GenMask(62, 40)    // WPRI
3892c64ad7cSXiaokun-Pei      else
3902c64ad7cSXiaokun-Pei        GenMask(62, 38)  )| // WPRI
391e30fd06aSYinan Xu    GenMask(35, 32)       | // SXL and UXL cannot be changed
392e30fd06aSYinan Xu    GenMask(31, 23)       | // WPRI
393705cbec3SLemover    GenMask(16, 15)       | // XS is read-only
394443741b9SYinan Xu    GenMask(6)            | // UBE, always little-endian (0)
395443741b9SYinan Xu    GenMask(4)            | // WPRI
396443741b9SYinan Xu    GenMask(2)            | // WPRI
397443741b9SYinan Xu    GenMask(0)              // WPRI
3985d669833SYinan Xu  ), 64)).asUInt
3998e7b11e5SWilliam Wang
400c84054caSLinJiawei  val medeleg = RegInit(UInt(XLEN.W), 0.U)
401d0de7e4aSpeixiaokun  val midelegInit = if(HasHExtension){((1 << 12) | (1 << 10) | (1 << 6) | (1 << 2)).U}else{0.U}
402d0de7e4aSpeixiaokun  val medelegWMask = if(HasHExtension) {
403e20ac1e1Sxuzefan    "hf0b7ff".U(XLEN.W)
404d0de7e4aSpeixiaokun  }else {
405d0de7e4aSpeixiaokun    "hb3ff".U(XLEN.W)
406d0de7e4aSpeixiaokun  }
407d0de7e4aSpeixiaokun
408d0de7e4aSpeixiaokun
409d0de7e4aSpeixiaokun  val mideleg = RegInit(UInt(XLEN.W), midelegInit)
410c84054caSLinJiawei  val mscratch = RegInit(UInt(XLEN.W), 0.U)
411c84054caSLinJiawei
412d0de7e4aSpeixiaokun  val midelegWMask = "h222".U(XLEN.W)
413b6982e83SLemover  // PMP Mapping
414ca2f90a6SLemover  val pmp = Wire(Vec(NumPMP, new PMPEntry())) // just used for method parameter
415ca2f90a6SLemover  val pma = Wire(Vec(NumPMA, new PMPEntry())) // just used for method parameter
416ca2f90a6SLemover  val pmpMapping = pmp_gen_mapping(pmp_init, NumPMP, PmpcfgBase, PmpaddrBase, pmp)
417ca2f90a6SLemover  val pmaMapping = pmp_gen_mapping(pma_init, NumPMA, PmacfgBase, PmaaddrBase, pma)
418672c4648Sceba  // !WARNNING: pmp and pma CSRs are not checked in difftest.
419c84054caSLinJiawei
420d0de7e4aSpeixiaokun  // Supervisor-Level CSRs
421c84054caSLinJiawei
42262a2cb19SXuan Hu  val sstatusWNmask: BigInt = (
42362a2cb19SXuan Hu    BigIntGenMask(63)     | // SD is read-only
42462a2cb19SXuan Hu    BigIntGenMask(62, 34) | // WPRI
42562a2cb19SXuan Hu    BigIntGenMask(33, 32) | // UXL is hard-wired to 64(b10)
42662a2cb19SXuan Hu    BigIntGenMask(31, 20) | // WPRI
42762a2cb19SXuan Hu    BigIntGenMask(17)     | // WPRI
42862a2cb19SXuan Hu    BigIntGenMask(16, 15) | // XS is read-only to zero
42962a2cb19SXuan Hu    BigIntGenMask(12, 11) | // WPRI
43062a2cb19SXuan Hu    BigIntGenMask(7)      | // WPRI
43162a2cb19SXuan Hu    BigIntGenMask(6)      | // UBE is always little-endian (0)
43262a2cb19SXuan Hu    BigIntGenMask(4, 2)   | // WPRI
43362a2cb19SXuan Hu    BigIntGenMask(0)        // WPRI
43462a2cb19SXuan Hu  )
43562a2cb19SXuan Hu
43662a2cb19SXuan Hu  val sstatusWmask = BigIntNot(sstatusWNmask).U(XLEN.W)
43762a2cb19SXuan Hu  val sstatusRmask = (
43862a2cb19SXuan Hu    BigIntGenMask(63)     | // SD
43962a2cb19SXuan Hu    BigIntGenMask(33, 32) | // UXL
44062a2cb19SXuan Hu    BigIntGenMask(19)     | // MXR
44162a2cb19SXuan Hu    BigIntGenMask(18)     | // SUM
44262a2cb19SXuan Hu    BigIntGenMask(16, 15) | // XS
44362a2cb19SXuan Hu    BigIntGenMask(14, 13) | // FS
44462a2cb19SXuan Hu    BigIntGenMask(10, 9 ) | // VS
44562a2cb19SXuan Hu    BigIntGenMask(8)      | // SPP
44662a2cb19SXuan Hu    BigIntGenMask(6)      | // UBE: hard wired to 0
44762a2cb19SXuan Hu    BigIntGenMask(5)      | // SPIE
44862a2cb19SXuan Hu    BigIntGenMask(1)
44962a2cb19SXuan Hu  ).U(XLEN.W)
45062a2cb19SXuan Hu
45162a2cb19SXuan Hu  println(s"sstatusWNmask: 0x${sstatusWNmask.toString(16)}")
45262a2cb19SXuan Hu  println(s"sstatusWmask: 0x${sstatusWmask.litValue.toString(16)}")
45362a2cb19SXuan Hu  println(s"sstatusRmask: 0x${sstatusRmask.litValue.toString(16)}")
45462a2cb19SXuan Hu
455a4e57ea3SLi Qianruo  // stvec: {BASE (WARL), MODE (WARL)} where mode is 0 or 1
456a4e57ea3SLi Qianruo  val stvecMask = ~(0x2.U(XLEN.W))
457c84054caSLinJiawei  val stvec = RegInit(UInt(XLEN.W), 0.U)
458c84054caSLinJiawei  // val sie = RegInit(0.U(XLEN.W))
459c84054caSLinJiawei  val sieMask = "h222".U & mideleg
460c84054caSLinJiawei  val sipMask = "h222".U & mideleg
4615dabf2dfSYinan Xu  val sipWMask = "h2".U(XLEN.W) // ssip is writeable in smode
46234230194Sjinyue110  val satp = if(EnbaleTlbDebug) RegInit(UInt(XLEN.W), "h8000000000087fbe".U) else RegInit(0.U(XLEN.W))
463df2b1479SZhangZifei  // val satp = RegInit(UInt(XLEN.W), "h8000000000087fbe".U) // only use for tlb naive debug
46445f497a4Shappy-lx  // val satpMask = "h80000fffffffffff".U(XLEN.W) // disable asid, mode can only be 8 / 0
46545f497a4Shappy-lx  // TODO: use config to control the length of asid
46645f497a4Shappy-lx  // val satpMask = "h8fffffffffffffff".U(XLEN.W) // enable asid, mode can only be 8 / 0
467705cbec3SLemover  val satpMask = Cat("h8".U(Satp_Mode_len.W), satp_part_wmask(Satp_Asid_len, AsidLength), satp_part_wmask(Satp_Addr_len, PAddrBits-12))
468c84054caSLinJiawei  val sepc = RegInit(UInt(XLEN.W), 0.U)
469e30fd06aSYinan Xu  // Page 60 in riscv-priv: The low bit of sepc (sepc[0]) is always zero.
470e30fd06aSYinan Xu  val sepcMask = ~(0x1.U(XLEN.W))
471c84054caSLinJiawei  val scause = RegInit(UInt(XLEN.W), 0.U)
472d0de7e4aSpeixiaokun  val stval = RegInit(UInt(XLEN.W), 0.U)
473c84054caSLinJiawei  val sscratch = RegInit(UInt(XLEN.W), 0.U)
474c84054caSLinJiawei  val scounteren = RegInit(UInt(XLEN.W), 0.U)
4756ade72d9Sxuzefan  val senvcfg = RegInit(UInt(XLEN.W), 0.U)  // !WARNING: there is no logic about this CSR.
476e4b1ccacSxuzefan  // Currently, XiangShan don't support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
477e4b1ccacSxuzefan  val scounterenMask = 0.U(XLEN.W)
478fcff7e94SZhangZifei
479eedc2e58SSteve Gou  // sbpctl
480eedc2e58SSteve Gou  // Bits 0-7: {LOOP, RAS, SC, TAGE, BIM, BTB, uBTB}
481eedc2e58SSteve Gou  val sbpctl = RegInit(UInt(XLEN.W), "h7f".U)
482eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.ubtb_enable := sbpctl(0)
483eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.btb_enable  := sbpctl(1)
484eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.bim_enable  := sbpctl(2)
485eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.tage_enable := sbpctl(3)
486eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.sc_enable   := sbpctl(4)
487eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.ras_enable  := sbpctl(5)
488eedc2e58SSteve Gou  csrio.customCtrl.bp_ctrl.loop_enable := sbpctl(6)
4892b8b2e7aSWilliam Wang
490ecccf78fSJay  // spfctl Bit 0: L1I Cache Prefetcher Enable
4912b8b2e7aSWilliam Wang  // spfctl Bit 1: L2Cache Prefetcher Enable
49285de5caeSLinJiawei  // spfctl Bit 2: L1D Cache Prefetcher Enable
49385de5caeSLinJiawei  // spfctl Bit 3: L1D train prefetch on hit
49485de5caeSLinJiawei  // spfctl Bit 4: L1D prefetch enable agt
49585de5caeSLinJiawei  // spfctl Bit 5: L1D prefetch enable pht
496c65495a4SLinJiawei  // spfctl Bit [9:6]: L1D prefetch active page threshold
497c65495a4SLinJiawei  // spfctl Bit [15:10]: L1D prefetch active page stride
4985d13017eSLinJiawei  // turn off L2 BOP, turn on L1 SMS by default
499c65495a4SLinJiawei  val spfctl = RegInit(UInt(XLEN.W), Seq(
500edbf1204SLinJiawei    0 << 17,    // L2 pf store only [17] init: false
501edbf1204SLinJiawei    1 << 16,    // L1D pf enable stride [16] init: true
502f1d78cf7SLinJiawei    30 << 10,   // L1D active page stride [15:10] init: 30
503f1d78cf7SLinJiawei    12 << 6,    // L1D active page threshold [9:6] init: 12
504f1d78cf7SLinJiawei    1  << 5,    // L1D enable pht [5] init: true
505f1d78cf7SLinJiawei    1  << 4,    // L1D enable agt [4] init: true
506f1d78cf7SLinJiawei    0  << 3,    // L1D train on hit [3] init: false
507f1d78cf7SLinJiawei    1  << 2,    // L1D pf enable [2] init: true
508f1d78cf7SLinJiawei    1  << 1,    // L2 pf enable [1] init: true
509f1d78cf7SLinJiawei    1  << 0,    // L1I pf enable [0] init: true
510c65495a4SLinJiawei  ).reduce(_|_).U(XLEN.W))
511ecccf78fSJay  csrio.customCtrl.l1I_pf_enable := spfctl(0)
51235a47a38SYinan Xu  csrio.customCtrl.l2_pf_enable := spfctl(1)
51385de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable := spfctl(2)
51485de5caeSLinJiawei  csrio.customCtrl.l1D_pf_train_on_hit := spfctl(3)
51585de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable_agt := spfctl(4)
51685de5caeSLinJiawei  csrio.customCtrl.l1D_pf_enable_pht := spfctl(5)
5175d13017eSLinJiawei  csrio.customCtrl.l1D_pf_active_threshold := spfctl(9, 6)
518c65495a4SLinJiawei  csrio.customCtrl.l1D_pf_active_stride := spfctl(15, 10)
519edbf1204SLinJiawei  csrio.customCtrl.l1D_pf_enable_stride := spfctl(16)
520edbf1204SLinJiawei  csrio.customCtrl.l2_pf_store_only := spfctl(17)
5212b8b2e7aSWilliam Wang
5222b8b2e7aSWilliam Wang  // slvpredctl: load violation predict settings
5236ef4f6f6SYinan Xu  // Default reset period: 2^16
5246ef4f6f6SYinan Xu  // Why this number: reset more frequently while keeping the overhead low
5256ef4f6f6SYinan Xu  // Overhead: extra two redirections in every 64K cycles => ~0.1% overhead
526560b69b7SHaojin Tang  val slvpredctl = Reg(UInt(XLEN.W))
527560b69b7SHaojin Tang  when(reset.asBool) {
528c686adcdSYinan Xu    slvpredctl := Constantin.createRecord("slvpredctl", 0x60)
529560b69b7SHaojin Tang  }
5302b8b2e7aSWilliam Wang  csrio.customCtrl.lvpred_disable := slvpredctl(0)
5312b8b2e7aSWilliam Wang  csrio.customCtrl.no_spec_load := slvpredctl(1)
532c7160cd3SWilliam Wang  csrio.customCtrl.storeset_wait_store := slvpredctl(2)
533c7160cd3SWilliam Wang  csrio.customCtrl.storeset_no_fast_wakeup := slvpredctl(3)
534c7160cd3SWilliam Wang  csrio.customCtrl.lvpred_timeout := slvpredctl(8, 4)
5352b8b2e7aSWilliam Wang
536f3f22d72SYinan Xu  //  smblockctl: memory block configurations
53741d8d239Shappy-lx  //  +------------------------+---+---+---+----+----+-----+--------+
53841d8d239Shappy-lx  //  |XLEN-1                10| 9 | 8 | 7 | 6  | 5  |  4  |3      0|
53941d8d239Shappy-lx  //  +------------------------+---+---+---+----+----+-----+--------+
54041d8d239Shappy-lx  //  |           Reserved     | L | S | O | CE | SP | LVC |   Th   |
54141d8d239Shappy-lx  //  +------------------------+---+---+---+----+----+-----+--------+
54237225120Ssfencevma  //  Description:
54337225120Ssfencevma  //  Bit 3-0   : Store buffer flush threshold (Th).
54437225120Ssfencevma  //  Bit 4     : Enable load violation check after reset (LVC).
54537225120Ssfencevma  //  Bit 5     : Enable soft-prefetch after reset (SP).
54637225120Ssfencevma  //  Bit 6     : Enable cache error after reset (CE).
54737225120Ssfencevma  //  Bit 7     : Enable uncache write outstanding (O).
54841d8d239Shappy-lx  //  Bit 8     : Enable unaligned store (S).
54941d8d239Shappy-lx  //  Bit 9     : Enable unaligned load (L).
55037225120Ssfencevma  //  Others    : Reserved.
55137225120Ssfencevma
55267682d05SWilliam Wang  val smblockctl_init_val =
55367ba96b4SYinan Xu    (0xf & StoreBufferThreshold) |
55467ba96b4SYinan Xu    (EnableLdVioCheckAfterReset.toInt << 4) |
55567ba96b4SYinan Xu    (EnableSoftPrefetchAfterReset.toInt << 5) |
556dcfaba1dSczw    (EnableCacheErrorAfterReset.toInt << 6) |
55741d8d239Shappy-lx    (EnableUncacheWriteOutstanding.toInt << 7) |
55841d8d239Shappy-lx    (EnableHardwareStoreMisalign.toInt << 8) |
55941d8d239Shappy-lx    (EnableHardwareLoadMisalign.toInt << 9)
56067ba96b4SYinan Xu  val smblockctl = RegInit(UInt(XLEN.W), smblockctl_init_val.U)
561f3f22d72SYinan Xu  csrio.customCtrl.sbuffer_threshold := smblockctl(3, 0)
56267682d05SWilliam Wang  // bits 4: enable load load violation check
563a4e57ea3SLi Qianruo  csrio.customCtrl.ldld_vio_check_enable := smblockctl(4)
564a4e57ea3SLi Qianruo  csrio.customCtrl.soft_prefetch_enable := smblockctl(5)
565a4e57ea3SLi Qianruo  csrio.customCtrl.cache_error_enable := smblockctl(6)
56637225120Ssfencevma  csrio.customCtrl.uncache_write_outstanding_enable := smblockctl(7)
56741d8d239Shappy-lx  csrio.customCtrl.hd_misalign_st_enable := smblockctl(8)
56841d8d239Shappy-lx  csrio.customCtrl.hd_misalign_ld_enable := smblockctl(9)
569a4e57ea3SLi Qianruo
570a4e57ea3SLi Qianruo  println("CSR smblockctl init value:")
571a4e57ea3SLi Qianruo  println("  Store buffer replace threshold: " + StoreBufferThreshold)
572a4e57ea3SLi Qianruo  println("  Enable ld-ld vio check after reset: " + EnableLdVioCheckAfterReset)
573a4e57ea3SLi Qianruo  println("  Enable soft prefetch after reset: " + EnableSoftPrefetchAfterReset)
574a4e57ea3SLi Qianruo  println("  Enable cache error after reset: " + EnableCacheErrorAfterReset)
57537225120Ssfencevma  println("  Enable uncache write outstanding: " + EnableUncacheWriteOutstanding)
57641d8d239Shappy-lx  println("  Enable unaligned store: " + EnableHardwareStoreMisalign)
57741d8d239Shappy-lx  println("  Enable unaligned load: " + EnableHardwareLoadMisalign)
578f3f22d72SYinan Xu
5795b47c58cSYinan Xu  val srnctl = RegInit(UInt(XLEN.W), "h7".U)
5805b47c58cSYinan Xu  csrio.customCtrl.fusion_enable := srnctl(0)
5815b47c58cSYinan Xu  csrio.customCtrl.wfi_enable := srnctl(2)
582aac4464eSYinan Xu
583d0de7e4aSpeixiaokun  // Hypervisor CSRs
584d0de7e4aSpeixiaokun  val hstatusWMask = "h7003c0".U(XLEN.W)
585d0de7e4aSpeixiaokun  // hstatus: vtsr, vtw, vtvm, hu, spvp, spv, gva,
586d0de7e4aSpeixiaokun  val hstatus = RegInit("h200000000".U(XLEN.W))
587d0de7e4aSpeixiaokun  val hstatusStruct = hstatus.asTypeOf(new HstatusStruct)
588d0de7e4aSpeixiaokun  val hedeleg = RegInit(UInt(XLEN.W), 0.U)
589d0de7e4aSpeixiaokun  val hideleg = RegInit(UInt(XLEN.W), 0.U)
590d0de7e4aSpeixiaokun  val hidelegRMask = mideleg
591d0de7e4aSpeixiaokun  val hidelegWMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
592d0de7e4aSpeixiaokun  val hgeie   = RegInit(UInt(XLEN.W), 0.U)
593d0de7e4aSpeixiaokun  val htval = RegInit(UInt(XLEN.W), 0.U)
594d0de7e4aSpeixiaokun  // hvip hip hie is part of mip or mie
595d0de7e4aSpeixiaokun  val hvipMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
596d0de7e4aSpeixiaokun  val hipRMask = (((1 << 12).U | hvipMask) & mideleg)
597d0de7e4aSpeixiaokun  val hipWMask = ((1 << 2).U & mideleg)// vssip
598d0de7e4aSpeixiaokun  val hieMask = hipRMask
599d0de7e4aSpeixiaokun  val htinst = RegInit(UInt(XLEN.W), 0.U)
600d0de7e4aSpeixiaokun  val hgeip = RegInit(UInt(XLEN.W), 0.U)
601d0de7e4aSpeixiaokun  val henvcfg = RegInit(UInt(XLEN.W), 0.U)
602d0de7e4aSpeixiaokun  val hgatp = RegInit(UInt(XLEN.W), 0.U)
603d0de7e4aSpeixiaokun  val hgatpMask = Cat("h8".U(Hgatp_Mode_len.W), satp_part_wmask(Hgatp_Vmid_len, VmidLength), satp_part_wmask(Hgatp_Addr_len, PAddrBits-12))
604a13f171cSXu, Zefan  // val htimedelta = RegInit(UInt(XLEN.W), 0.U)
605d0de7e4aSpeixiaokun  val hcounteren = RegInit(UInt(XLEN.W), 0.U)
606e4b1ccacSxuzefan  // Currently, XiangShan don't support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
607e4b1ccacSxuzefan  val hcounterenMask = 0.U(XLEN.W)
608d0de7e4aSpeixiaokun
609f2a38010Sxuzefan  val vsstatus = RegInit("h200002000".U(XLEN.W))
610d0de7e4aSpeixiaokun  val vsstatusStruct = vsstatus.asTypeOf(new MstatusStruct)
611d0de7e4aSpeixiaokun  //vsie vsip
612d0de7e4aSpeixiaokun  val vsMask = ((1 << 10) | (1 << 6) | (1 << 2)).U(XLEN.W)
613d0de7e4aSpeixiaokun  val vsip_ie_Mask = ZeroExt((hideleg & mideleg & vsMask), XLEN)
614d0de7e4aSpeixiaokun  val vsip_WMask = ZeroExt((hideleg & mideleg & vssip_Mask), XLEN)
615d0de7e4aSpeixiaokun  val vstvec = RegInit(UInt(XLEN.W), 0.U)
616d0de7e4aSpeixiaokun  val vsscratch = RegInit(UInt(XLEN.W), 0.U)
617d0de7e4aSpeixiaokun  val vsepc = RegInit(UInt(XLEN.W), 0.U)
618d0de7e4aSpeixiaokun  val vscause = RegInit(UInt(XLEN.W), 0.U)
619d0de7e4aSpeixiaokun  val vstval = RegInit(UInt(XLEN.W), 0.U)
620d0de7e4aSpeixiaokun  val vsatp = RegInit(UInt(XLEN.W), 0.U)
6212b8b2e7aSWilliam Wang  val tlbBundle = Wire(new TlbCsrBundle)
62245f497a4Shappy-lx  tlbBundle.satp.apply(satp)
623d0de7e4aSpeixiaokun  tlbBundle.vsatp.apply(vsatp)
624d0de7e4aSpeixiaokun  tlbBundle.hgatp.apply(hgatp)
6252b8b2e7aSWilliam Wang  csrio.tlb := tlbBundle
6262b8b2e7aSWilliam Wang
627c84054caSLinJiawei  // User-Level CSRs
628c84054caSLinJiawei  val uepc = Reg(UInt(XLEN.W))
629c84054caSLinJiawei
630c84054caSLinJiawei  // fcsr
631c84054caSLinJiawei  class FcsrStruct extends Bundle {
632c84054caSLinJiawei    val reserved = UInt((XLEN-3-5).W)
633c84054caSLinJiawei    val frm = UInt(3.W)
634c84054caSLinJiawei    val fflags = UInt(5.W)
635c84054caSLinJiawei    assert(this.getWidth == XLEN)
636c84054caSLinJiawei  }
637c84054caSLinJiawei  val fcsr = RegInit(0.U(XLEN.W))
638c84054caSLinJiawei  // set mstatus->sd and mstatus->fs when true
639c84054caSLinJiawei  val csrw_dirty_fp_state = WireInit(false.B)
640c84054caSLinJiawei
641c84054caSLinJiawei  def frm_wfn(wdata: UInt): UInt = {
642c84054caSLinJiawei    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
643c84054caSLinJiawei    csrw_dirty_fp_state := true.B
644c84054caSLinJiawei    fcsrOld.frm := wdata(2,0)
6455d669833SYinan Xu    fcsrOld.asUInt
646c84054caSLinJiawei  }
647c84054caSLinJiawei  def frm_rfn(rdata: UInt): UInt = rdata(7,5)
648c84054caSLinJiawei
6497132faa5SLinJiawei  def fflags_wfn(update: Boolean)(wdata: UInt): UInt = {
6507132faa5SLinJiawei    val fcsrOld = fcsr.asTypeOf(new FcsrStruct)
6517132faa5SLinJiawei    val fcsrNew = WireInit(fcsrOld)
6527132faa5SLinJiawei    if (update) {
6537132faa5SLinJiawei      fcsrNew.fflags := wdata(4,0) | fcsrOld.fflags
6547132faa5SLinJiawei    } else {
6557132faa5SLinJiawei      fcsrNew.fflags := wdata(4,0)
6567132faa5SLinJiawei    }
6575d669833SYinan Xu    fcsrNew.asUInt
658c84054caSLinJiawei  }
659c84054caSLinJiawei  def fflags_rfn(rdata:UInt): UInt = rdata(4,0)
660c84054caSLinJiawei
661c84054caSLinJiawei  def fcsr_wfn(wdata: UInt): UInt = {
662c84054caSLinJiawei    val fcsrOld = WireInit(fcsr.asTypeOf(new FcsrStruct))
663c84054caSLinJiawei    csrw_dirty_fp_state := true.B
664c84054caSLinJiawei    Cat(fcsrOld.reserved, wdata.asTypeOf(fcsrOld).frm, wdata.asTypeOf(fcsrOld).fflags)
665c84054caSLinJiawei  }
666c84054caSLinJiawei
667c84054caSLinJiawei  val fcsrMapping = Map(
6687132faa5SLinJiawei    MaskedRegMap(Fflags, fcsr, wfn = fflags_wfn(update = false), rfn = fflags_rfn),
669c84054caSLinJiawei    MaskedRegMap(Frm, fcsr, wfn = frm_wfn, rfn = frm_rfn),
670c84054caSLinJiawei    MaskedRegMap(Fcsr, fcsr, wfn = fcsr_wfn)
671c84054caSLinJiawei  )
672c84054caSLinJiawei
6730ba52110SZiyue Zhang  // Vector extension CSRs
6747f733d3dSxiaofeibao-xjtu  val vstart = RegInit(0.U(XLEN.W))
6750ba52110SZiyue Zhang  val vcsr = RegInit(0.U(XLEN.W))
6760ba52110SZiyue Zhang  val vl = Reg(UInt(XLEN.W))
6770ba52110SZiyue Zhang  val vtype = Reg(UInt(XLEN.W))
6785f28e666Schengguanghui  val vlenb = RegInit(VDataBytes.U(XLEN.W))
679daa01159SZiyue Zhang
680daa01159SZiyue Zhang  // set mstatus->sd and mstatus->vs when true
681daa01159SZiyue Zhang  val csrw_dirty_vs_state = WireInit(false.B)
6820ba52110SZiyue Zhang
6830ba52110SZiyue Zhang  // vcsr is mapped to vxrm and vxsat
6840ba52110SZiyue Zhang  class VcsrStruct extends Bundle {
6850ba52110SZiyue Zhang    val reserved = UInt((XLEN-3).W)
6860ba52110SZiyue Zhang    val vxrm = UInt(2.W)
6870ba52110SZiyue Zhang    val vxsat = UInt(1.W)
6880ba52110SZiyue Zhang    assert(this.getWidth == XLEN)
6890ba52110SZiyue Zhang  }
6900ba52110SZiyue Zhang
6910ba52110SZiyue Zhang  def vxrm_wfn(wdata: UInt): UInt = {
6920ba52110SZiyue Zhang    val vcsrOld = WireInit(vcsr.asTypeOf(new VcsrStruct))
693daa01159SZiyue Zhang    csrw_dirty_vs_state := true.B
6940ba52110SZiyue Zhang    vcsrOld.vxrm := wdata(1,0)
6950ba52110SZiyue Zhang    vcsrOld.asUInt
6960ba52110SZiyue Zhang  }
6970ba52110SZiyue Zhang  def vxrm_rfn(rdata: UInt): UInt = rdata(2,1)
6980ba52110SZiyue Zhang
6996355a2b7Sczw  def vxsat_wfn(update: Boolean)(wdata: UInt): UInt = {
7000ba52110SZiyue Zhang    val vcsrOld = WireInit(vcsr.asTypeOf(new VcsrStruct))
7016355a2b7Sczw    val vcsrNew = WireInit(vcsrOld)
702daa01159SZiyue Zhang    csrw_dirty_vs_state := true.B
7036355a2b7Sczw    if (update) {
7046355a2b7Sczw      vcsrNew.vxsat := wdata(0) | vcsrOld.vxsat
7056355a2b7Sczw    } else {
7066355a2b7Sczw      vcsrNew.vxsat := wdata(0)
7076355a2b7Sczw    }
7086355a2b7Sczw    vcsrNew.asUInt
7090ba52110SZiyue Zhang  }
7100ba52110SZiyue Zhang  def vxsat_rfn(rdata: UInt): UInt = rdata(0)
7110ba52110SZiyue Zhang
7120ba52110SZiyue Zhang  def vcsr_wfn(wdata: UInt): UInt = {
7130ba52110SZiyue Zhang    val vcsrOld = WireInit(vcsr.asTypeOf(new VcsrStruct))
714daa01159SZiyue Zhang    csrw_dirty_vs_state := true.B
7150ba52110SZiyue Zhang    vcsrOld.vxrm := wdata.asTypeOf(vcsrOld).vxrm
7160ba52110SZiyue Zhang    vcsrOld.vxsat := wdata.asTypeOf(vcsrOld).vxsat
7170ba52110SZiyue Zhang    vcsrOld.asUInt
7180ba52110SZiyue Zhang  }
7190ba52110SZiyue Zhang
7200ba52110SZiyue Zhang  val vcsrMapping = Map(
7210ba52110SZiyue Zhang    MaskedRegMap(Vstart, vstart),
7220ba52110SZiyue Zhang    MaskedRegMap(Vxrm, vcsr, wfn = vxrm_wfn, rfn = vxrm_rfn),
7236355a2b7Sczw    MaskedRegMap(Vxsat, vcsr, wfn = vxsat_wfn(false), rfn = vxsat_rfn),
7240ba52110SZiyue Zhang    MaskedRegMap(Vcsr, vcsr, wfn = vcsr_wfn),
7250ba52110SZiyue Zhang    MaskedRegMap(Vl, vl),
72635d1557aSZiyue Zhang    MaskedRegMap(Vtype, vtype),
72735d1557aSZiyue Zhang    MaskedRegMap(Vlenb, vlenb),
7280ba52110SZiyue Zhang  )
7290ba52110SZiyue Zhang
730321934c7SKunlin You  // Hart Privilege Mode
731321934c7SKunlin You  val privilegeMode = RegInit(UInt(2.W), ModeM)
732c84054caSLinJiawei
733cd365d4cSrvcoresjw  //val perfEventscounten = List.fill(nrPerfCnts)(RegInit(false(Bool())))
7348635f18fSwangkaifan  // Perf Counter
7358635f18fSwangkaifan  val nrPerfCnts = 29  // 3...31
736321934c7SKunlin You  val privilegeModeOH = UIntToOH(privilegeMode)
737cd365d4cSrvcoresjw  val perfEventscounten = RegInit(0.U.asTypeOf(Vec(nrPerfCnts, Bool())))
7388635f18fSwangkaifan  val perfCnts   = List.fill(nrPerfCnts)(RegInit(0.U(XLEN.W)))
7398c7b0b2fSrvcoresjw  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
74012c44ce5Srvcoresjw                   List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
74112c44ce5Srvcoresjw                   List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
74212c44ce5Srvcoresjw                   List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
743cd365d4cSrvcoresjw  for (i <-0 until nrPerfCnts) {
744321934c7SKunlin You    perfEventscounten(i) := (perfEvents(i)(63,60) & privilegeModeOH).orR
745cd365d4cSrvcoresjw  }
746cd365d4cSrvcoresjw
7471ca0e4f3SYinan Xu  val hpmEvents = Wire(Vec(numPCntHc * coreParams.L2NBanks, new PerfEvent))
748cd365d4cSrvcoresjw  for (i <- 0 until numPCntHc * coreParams.L2NBanks) {
7491ca0e4f3SYinan Xu    hpmEvents(i) := csrio.perf.perfEventsHc(i)
750cd365d4cSrvcoresjw  }
751cd365d4cSrvcoresjw
7529a128342SHaoyuan Feng  // print perfEvents
7539a128342SHaoyuan Feng  val allPerfEvents = hpmEvents.map(x => (s"Hc", x.value))
7549a128342SHaoyuan Feng  if (printEventCoding) {
7559a128342SHaoyuan Feng    for (((name, inc), i) <- allPerfEvents.zipWithIndex) {
7569a128342SHaoyuan Feng      println("CSR perfEvents Set", name, inc, i)
7579a128342SHaoyuan Feng    }
7589a128342SHaoyuan Feng  }
7599a128342SHaoyuan Feng
76012c44ce5Srvcoresjw  val csrevents = perfEvents.slice(24, 29)
7611ca0e4f3SYinan Xu  val hpm_hc = HPerfMonitor(csrevents, hpmEvents)
7628635f18fSwangkaifan  val mcountinhibit = RegInit(0.U(XLEN.W))
763b03ddc86Swangkaifan  val mcycle = RegInit(0.U(XLEN.W))
764b03ddc86Swangkaifan  mcycle := mcycle + 1.U
765b03ddc86Swangkaifan  val minstret = RegInit(0.U(XLEN.W))
7661ca0e4f3SYinan Xu  val perf_events = csrio.perf.perfEventsFrontend ++
767e1a85e9fSchengguanghui                    csrio.perf.perfEventsBackend ++
7681ca0e4f3SYinan Xu                    csrio.perf.perfEventsLsu ++
7691ca0e4f3SYinan Xu                    hpm_hc.getPerf
770b03ddc86Swangkaifan  minstret := minstret + RegNext(csrio.perf.retiredInstr)
7715fd90906Srvcoresjw  for(i <- 0 until 29){
7721ca0e4f3SYinan Xu    perfCnts(i) := Mux(mcountinhibit(i+3) | !perfEventscounten(i), perfCnts(i), perfCnts(i) + perf_events(i).value)
7735fd90906Srvcoresjw  }
7748635f18fSwangkaifan
775c84054caSLinJiawei  // CSR reg map
77621fa8708Swangkaifan  val basicPrivMapping = Map(
777c84054caSLinJiawei
778f7af4c74Schengguanghui    // Unprivileged Floating-Point CSRs
779f7af4c74Schengguanghui    // Has been mapped above
780c84054caSLinJiawei
781e4b1ccacSxuzefan    // TODO: support Unprivileged Counter/Timers CSRs ("Zicntr" and "Zihpm")
782f7af4c74Schengguanghui    // Unprivileged Counter/Timers
783f7af4c74Schengguanghui    MaskedRegMap(Cycle, mcycle),
784f7af4c74Schengguanghui    // We don't support read time CSR.
785f7af4c74Schengguanghui    // MaskedRegMap(Time, mtime),
786f7af4c74Schengguanghui    MaskedRegMap(Instret, minstret),
787c84054caSLinJiawei
78821fa8708Swangkaifan    //--- Supervisor Trap Setup ---
789c84054caSLinJiawei    MaskedRegMap(Sstatus, mstatus, sstatusWmask, mstatusUpdateSideEffect, sstatusRmask),
790c84054caSLinJiawei    // MaskedRegMap(Sedeleg, Sedeleg),
791c84054caSLinJiawei    // MaskedRegMap(Sideleg, Sideleg),
792c84054caSLinJiawei    MaskedRegMap(Sie, mie, sieMask, MaskedRegMap.NoSideEffect, sieMask),
793a4e57ea3SLi Qianruo    MaskedRegMap(Stvec, stvec, stvecMask, MaskedRegMap.NoSideEffect, stvecMask),
794e4b1ccacSxuzefan    MaskedRegMap(Scounteren, scounteren, scounterenMask),
795c84054caSLinJiawei
7966ade72d9Sxuzefan    //--- Supervisor Configuration ---
7976ade72d9Sxuzefan    MaskedRegMap(Senvcfg, senvcfg),
7986ade72d9Sxuzefan
79921fa8708Swangkaifan    //--- Supervisor Trap Handling ---
800c84054caSLinJiawei    MaskedRegMap(Sscratch, sscratch),
801e30fd06aSYinan Xu    MaskedRegMap(Sepc, sepc, sepcMask, MaskedRegMap.NoSideEffect, sepcMask),
802c84054caSLinJiawei    MaskedRegMap(Scause, scause),
803c84054caSLinJiawei    MaskedRegMap(Stval, stval),
8045390caa7Speixiaokun    MaskedRegMap(Sip, mipReg.asUInt, sipWMask, MaskedRegMap.NoSideEffect, sipMask, x => (mipWire.asUInt | x) & sipMask),
805c84054caSLinJiawei
80621fa8708Swangkaifan    //--- Supervisor Protection and Translation ---
807c5334b11SZhangZifei    MaskedRegMap(Satp, satp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
808c84054caSLinJiawei
80935a47a38SYinan Xu    //--- Supervisor Custom Read/Write Registers
810eedc2e58SSteve Gou    MaskedRegMap(Sbpctl, sbpctl),
81135a47a38SYinan Xu    MaskedRegMap(Spfctl, spfctl),
8122b8b2e7aSWilliam Wang    MaskedRegMap(Slvpredctl, slvpredctl),
813f3f22d72SYinan Xu    MaskedRegMap(Smblockctl, smblockctl),
814aac4464eSYinan Xu    MaskedRegMap(Srnctl, srnctl),
81535a47a38SYinan Xu
81621fa8708Swangkaifan    //--- Machine Information Registers ---
8175dabf2dfSYinan Xu    MaskedRegMap(Mvendorid, mvendorid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8185dabf2dfSYinan Xu    MaskedRegMap(Marchid, marchid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8195dabf2dfSYinan Xu    MaskedRegMap(Mimpid, mimpid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8205dabf2dfSYinan Xu    MaskedRegMap(Mhartid, mhartid, 0.U(XLEN.W), MaskedRegMap.Unwritable),
8217d9edc86SLemover    MaskedRegMap(Mconfigptr, mconfigptr, 0.U(XLEN.W), MaskedRegMap.Unwritable),
822c84054caSLinJiawei
82306490c40Speixiaokun    //--- Machine Configuration Registers ---
82406490c40Speixiaokun    MaskedRegMap(Menvcfg, menvcfg),
82506490c40Speixiaokun
82621fa8708Swangkaifan    //--- Machine Trap Setup ---
827443741b9SYinan Xu    MaskedRegMap(Mstatus, mstatus, mstatusWMask, mstatusUpdateSideEffect),
8285e4ec482SWilliam Wang    MaskedRegMap(Misa, misa, 0.U, MaskedRegMap.Unwritable), // now whole misa is unchangeable
829d0de7e4aSpeixiaokun    MaskedRegMap(Medeleg, medeleg, medelegWMask),
830b436d3b6Speixiaokun    MaskedRegMap(Mideleg, mideleg, midelegWMask),
831b436d3b6Speixiaokun    MaskedRegMap(Mie, mie, mieWMask),
832a4e57ea3SLi Qianruo    MaskedRegMap(Mtvec, mtvec, mtvecMask, MaskedRegMap.NoSideEffect, mtvecMask),
833e4b1ccacSxuzefan    MaskedRegMap(Mcounteren, mcounteren, mcounterenMask),
834c84054caSLinJiawei
83521fa8708Swangkaifan    //--- Machine Trap Handling ---
836c84054caSLinJiawei    MaskedRegMap(Mscratch, mscratch),
837e30fd06aSYinan Xu    MaskedRegMap(Mepc, mepc, mepcMask, MaskedRegMap.NoSideEffect, mepcMask),
838c84054caSLinJiawei    MaskedRegMap(Mcause, mcause),
839c84054caSLinJiawei    MaskedRegMap(Mtval, mtval),
8405390caa7Speixiaokun    MaskedRegMap(Mip, mipReg.asUInt, mipWMask, MaskedRegMap.NoSideEffect, mipMask, x => (mipWire.asUInt | x) & mipMask),
8416ade72d9Sxuzefan
84272951335SLi Qianruo    //--- Trigger ---
843716f717fSLi Qianruo    MaskedRegMap(Tselect, tselectPhy, WritableMask, WriteTselect),
844f7af4c74Schengguanghui    // Todo: support chain length = 2
845f7af4c74Schengguanghui    MaskedRegMap(Tdata1, tdata1RegVec(tselectPhy),
846f7af4c74Schengguanghui      WritableMask,
847f7af4c74Schengguanghui      x => Tdata1Bundle.Write(x, tdata1RegVec(tselectPhy), newTriggerChainIsLegal, debug_mode = debugMode),
848f7af4c74Schengguanghui      WritableMask,
849f7af4c74Schengguanghui      x => Tdata1Bundle.Read(x)),
850f7af4c74Schengguanghui    MaskedRegMap(Tdata2, tdata2RegVec(tselectPhy)),
851716f717fSLi Qianruo    MaskedRegMap(Tinfo, tinfo, 0.U(XLEN.W), MaskedRegMap.Unwritable),
85272951335SLi Qianruo
853d4aca96cSlqre    //--- Debug Mode ---
854d4aca96cSlqre    MaskedRegMap(Dcsr, dcsr, dcsrMask, dcsrUpdateSideEffect),
855d4aca96cSlqre    MaskedRegMap(Dpc, dpc),
856f7af4c74Schengguanghui    MaskedRegMap(Dscratch0, dscratch0),
85712c44ce5Srvcoresjw    MaskedRegMap(Dscratch1, dscratch1),
858b03ddc86Swangkaifan    MaskedRegMap(Mcountinhibit, mcountinhibit),
859b03ddc86Swangkaifan    MaskedRegMap(Mcycle, mcycle),
860b03ddc86Swangkaifan    MaskedRegMap(Minstret, minstret),
861b03ddc86Swangkaifan  )
86212c44ce5Srvcoresjw
863d0de7e4aSpeixiaokun  // hypervisor csr map
864d0de7e4aSpeixiaokun  val hcsrMapping = Map(
865d0de7e4aSpeixiaokun    //--- Hypervisor Trap Setup ---
866d0de7e4aSpeixiaokun    MaskedRegMap(Hstatus, hstatus, hstatusWMask),
867d0de7e4aSpeixiaokun    MaskedRegMap(Hedeleg, hedeleg),
868d0de7e4aSpeixiaokun    MaskedRegMap(Hideleg, hideleg, hidelegWMask, MaskedRegMap.NoSideEffect, hidelegRMask),
869d0de7e4aSpeixiaokun    MaskedRegMap(Hie, mie, hieMask, MaskedRegMap.NoSideEffect, hieMask),
870cc063a70Speixiaokun    MaskedRegMap(Hcounteren, hcounteren, hcounterenMask),
871d0de7e4aSpeixiaokun    MaskedRegMap(Hgeie, hgeie),
872d0de7e4aSpeixiaokun
873d0de7e4aSpeixiaokun    //--- Hypervisor Trap Handling ---
874d0de7e4aSpeixiaokun    MaskedRegMap(Htval, htval),
8755390caa7Speixiaokun    MaskedRegMap(Hip, mipReg.asUInt, hipWMask, MaskedRegMap.NoSideEffect, hipRMask, x => (mipWire.asUInt | x) & hipRMask),
8765390caa7Speixiaokun    MaskedRegMap(Hvip, mipReg.asUInt, hvipMask, MaskedRegMap.NoSideEffect, hvipMask, x => (mipWire.asUInt | x) & hvipMask),
877d0de7e4aSpeixiaokun    MaskedRegMap(Htinst, htinst),
878d0de7e4aSpeixiaokun    MaskedRegMap(Hgeip, hgeip),
879d0de7e4aSpeixiaokun
880d0de7e4aSpeixiaokun    //--- Hypervisor Configuration ---
881d0de7e4aSpeixiaokun    MaskedRegMap(Henvcfg, henvcfg),
882d0de7e4aSpeixiaokun
883d0de7e4aSpeixiaokun    //--- Hypervisor Protection and Translation ---
884a1d4b4bfSpeixiaokun    MaskedRegMap(Hgatp, hgatp, hgatpMask, MaskedRegMap.NoSideEffect, hgatpMask),
885d0de7e4aSpeixiaokun
886d0de7e4aSpeixiaokun    //--- Hypervisor Counter/Timer Virtualization Registers ---
887a13f171cSXu, Zefan    // MaskedRegMap(Htimedelta, htimedelta),
888d0de7e4aSpeixiaokun
889d0de7e4aSpeixiaokun    //--- Virtual Supervisor Registers ---
89085052be5Speixiaokun    MaskedRegMap(Vsstatus, vsstatus, rmask = sstatusRmask, wmask = sstatusWmask, wfn = vsstatusUpdateSideEffect),
891d0de7e4aSpeixiaokun    MaskedRegMap(Vsie, mie, rmask = vsip_ie_Mask, wmask = vsip_ie_Mask),
892d0de7e4aSpeixiaokun    MaskedRegMap(Vstvec, vstvec),
893d0de7e4aSpeixiaokun    MaskedRegMap(Vsscratch, vsscratch),
894d0de7e4aSpeixiaokun    MaskedRegMap(Vsepc, vsepc),
895d0de7e4aSpeixiaokun    MaskedRegMap(Vscause, vscause),
896d0de7e4aSpeixiaokun    MaskedRegMap(Vstval, vstval),
897d7e392d1Sxuzefan    MaskedRegMap(Vsip, mipReg.asUInt, vsip_WMask, MaskedRegMap.NoSideEffect, vsip_ie_Mask, x => mipWire.asUInt | x),
898d0de7e4aSpeixiaokun    MaskedRegMap(Vsatp, vsatp, satpMask, MaskedRegMap.NoSideEffect, satpMask),
899d0de7e4aSpeixiaokun
900d0de7e4aSpeixiaokun    //--- Machine Registers ---
901d0de7e4aSpeixiaokun    MaskedRegMap(Mtval2, mtval2),
902d0de7e4aSpeixiaokun    MaskedRegMap(Mtinst, mtinst),
903d0de7e4aSpeixiaokun  )
904d0de7e4aSpeixiaokun
90512c44ce5Srvcoresjw  val perfCntMapping = (0 until 29).map(i => {Map(
90612c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmevent3 +i,
90712c44ce5Srvcoresjw                 reg  = perfEvents(i),
90812c44ce5Srvcoresjw                 wmask = "hf87fff3fcff3fcff".U(XLEN.W)),
90912c44ce5Srvcoresjw    MaskedRegMap(addr = Mhpmcounter3 +i,
910f7af4c74Schengguanghui                 reg = perfCnts(i)),
911f7af4c74Schengguanghui    MaskedRegMap(addr = Hpmcounter3 + i,
91212c44ce5Srvcoresjw                 reg  = perfCnts(i))
91312c44ce5Srvcoresjw  )}).fold(Map())((a,b) => a ++ b)
9146d96ebcdSwakafa  // TODO: mechanism should be implemented later
9156d96ebcdSwakafa  // val MhpmcounterStart = Mhpmcounter3
9166d96ebcdSwakafa  // val MhpmeventStart   = Mhpmevent3
9176d96ebcdSwakafa  // for (i <- 0 until nrPerfCnts) {
9186d96ebcdSwakafa  //   perfCntMapping += MaskedRegMap(MhpmcounterStart + i, perfCnts(i))
9196d96ebcdSwakafa  //   perfCntMapping += MaskedRegMap(MhpmeventStart + i, perfEvents(i))
9206d96ebcdSwakafa  // }
9218635f18fSwangkaifan
922e19f7967SWilliam Wang  val cacheopRegs = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
923e19f7967SWilliam Wang    name -> RegInit(0.U(attribute("width").toInt.W))
924e19f7967SWilliam Wang  }}
925ad3ba452Szhanglinjuan  val cacheopMapping = CacheInstrucion.CacheInsRegisterList.map{case (name, attribute) => {
926ad3ba452Szhanglinjuan    MaskedRegMap(
927ad3ba452Szhanglinjuan      Scachebase + attribute("offset").toInt,
928e19f7967SWilliam Wang      cacheopRegs(name)
929ad3ba452Szhanglinjuan    )
930ad3ba452Szhanglinjuan  }}
931b6982e83SLemover
93221fa8708Swangkaifan  val mapping = basicPrivMapping ++
9338635f18fSwangkaifan                perfCntMapping ++
93421fa8708Swangkaifan                pmpMapping ++
935ca2f90a6SLemover                pmaMapping ++
936ad3ba452Szhanglinjuan                (if (HasFPU) fcsrMapping else Nil) ++
9370ba52110SZiyue Zhang                (if (HasVPU) vcsrMapping else Nil) ++
938d0de7e4aSpeixiaokun                (if (HasCustomCSRCacheOp) cacheopMapping else Nil) ++
939d0de7e4aSpeixiaokun                (if (HasHExtension) hcsrMapping else Nil)
940c84054caSLinJiawei
941f7af4c74Schengguanghui
942f7af4c74Schengguanghui  println("XiangShan CSR Lists")
943f7af4c74Schengguanghui
944f7af4c74Schengguanghui  for (addr <- mapping.keys.toSeq.sorted) {
945f7af4c74Schengguanghui    println(f"$addr%#03x ${mapping(addr)._1}")
946f7af4c74Schengguanghui  }
947f7af4c74Schengguanghui
948fe73ba60SYangyu Chen  val vs_s_csr_map = List(
949d0de7e4aSpeixiaokun    Sstatus.U  -> Vsstatus.U,
950d0de7e4aSpeixiaokun    Sie.U      -> Vsie.U,
951d0de7e4aSpeixiaokun    Stvec.U    -> Vstvec.U,
952d0de7e4aSpeixiaokun    Sscratch.U -> Vsscratch.U,
953d0de7e4aSpeixiaokun    Sepc.U     -> Vsepc.U,
954d0de7e4aSpeixiaokun    Scause.U   -> Vscause.U,
955d0de7e4aSpeixiaokun    Stval.U    -> Vstval.U,
956d0de7e4aSpeixiaokun    Sip.U      -> Vsip.U,
957d0de7e4aSpeixiaokun    Satp.U     -> Vsatp.U
958d0de7e4aSpeixiaokun  )
959d0de7e4aSpeixiaokun  val addr = Wire(UInt(12.W))
960d0de7e4aSpeixiaokun  val vscsr_addr = LookupTreeDefault(src2(11, 0), src2(11, 0), vs_s_csr_map)
961d0de7e4aSpeixiaokun  when(virtMode){
962d0de7e4aSpeixiaokun    addr := vscsr_addr
963d0de7e4aSpeixiaokun  }.otherwise{
964d0de7e4aSpeixiaokun    addr := src2(11, 0)
965d0de7e4aSpeixiaokun  }
966b1860798SZhangfw  val csri = ZeroExt(src2(16, 12), XLEN)
967c84054caSLinJiawei  val rdata = Wire(UInt(XLEN.W))
968d0de7e4aSpeixiaokun  val rdata_tmp = Wire(UInt(XLEN.W))
969d0de7e4aSpeixiaokun  val wdata_tmp = LookupTree(func, List(
970c84054caSLinJiawei    CSROpType.wrt  -> src1,
971c84054caSLinJiawei    CSROpType.set  -> (rdata | src1),
9725d669833SYinan Xu    CSROpType.clr  -> (rdata & (~src1).asUInt),
973b0ae3ac4SLinJiawei    CSROpType.wrti -> csri,
974c84054caSLinJiawei    CSROpType.seti -> (rdata | csri),
9755d669833SYinan Xu    CSROpType.clri -> (rdata & (~csri).asUInt)
976c84054caSLinJiawei  ))
977d0de7e4aSpeixiaokun  val is_vsip_ie = addr === Vsip.U || addr === Vsie.U
978a1d4b4bfSpeixiaokun  // for the difftest with NEMU(stay consistent with Spike)
979a1d4b4bfSpeixiaokun  val is_satp  = addr === Satp.U
980a1d4b4bfSpeixiaokun  val is_vsatp = addr === Vsatp.U
981a1d4b4bfSpeixiaokun  val is_hgatp = addr === Hgatp.U
982a1d4b4bfSpeixiaokun  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
983a1d4b4bfSpeixiaokun  val wdata = MuxCase(wdata_tmp, Seq(
984a1d4b4bfSpeixiaokun    is_vsip_ie -> ZeroExt(wdata_tmp << 1, XLEN),
985a1d4b4bfSpeixiaokun    (is_satp && !check_apt_mode) -> satp,
986a1d4b4bfSpeixiaokun    (is_vsatp && !check_apt_mode) -> vsatp,
987a1d4b4bfSpeixiaokun    (is_hgatp && !check_apt_mode) -> hgatp
988a1d4b4bfSpeixiaokun  ))
989e377d77eSWilliam Wang  val addrInPerfCnt = (addr >= Mcycle.U) && (addr <= Mhpmcounter31.U) ||
9904d5d2702Swakafa    (addr >= Mcountinhibit.U) && (addr <= Mhpmevent31.U) ||
991f7af4c74Schengguanghui    (addr >= Cycle.U) && (addr <= Hpmcounter31.U) ||
9924d5d2702Swakafa    addr === Mip.U
993e377d77eSWilliam Wang  csrio.isPerfCnt := addrInPerfCnt && valid && func =/= CSROpType.jmp
9948635f18fSwangkaifan
99547a386bfSZhangZifei  // satp wen check
99647a386bfSZhangZifei  val satpLegalMode = (wdata.asTypeOf(new SatpStruct).mode===0.U) || (wdata.asTypeOf(new SatpStruct).mode===8.U)
9972f5f05fdSWilliam Wang
998e5adbe81SLemover  // csr access check, special case
999d0de7e4aSpeixiaokun  val tvmNotPermit = (privilegeMode === ModeS && !virtMode && mstatusStruct.tvm.asBool)
1000e5adbe81SLemover  val accessPermitted = !(addr === Satp.U && tvmNotPermit)
1001d0de7e4aSpeixiaokun  val vtvmNotPermit = (privilegeMode === ModeS && virtMode && hstatusStruct.vtvm.asBool)
1002d0de7e4aSpeixiaokun  val vaccessPermitted = !(addr === Vsatp.U && vtvmNotPermit)
10032d3ae4b4SsinceforYy//  csrio.disableSfence := (tvmNotPermit || !virtMode && privilegeMode < ModeS) || (vtvmNotPermit || virtMode && privilegeMode < ModeS)
10042d3ae4b4SsinceforYy//  csrio.disableHfenceg := !((!virtMode && privilegeMode === ModeS && !mstatusStruct.tvm.asBool) || (privilegeMode === ModeM)) // only valid in HS and mstatus.tvm == 0 or in M
10052d3ae4b4SsinceforYy//  csrio.disableHfencev :=  !(privilegeMode === ModeM || (!virtMode && privilegeMode === ModeS))
1006e5adbe81SLemover
10072f5f05fdSWilliam Wang  // general CSR wen check
10081be7b39aSXuan Hu  val wen = valid && CSROpType.isCsrAccess(func) && ((addr=/=Satp.U && addr =/= Vsatp.U) || satpLegalMode)
100972951335SLi Qianruo  val dcsrPermitted = dcsrPermissionCheck(addr, false.B, debugMode)
101072951335SLi Qianruo  val triggerPermitted = triggerPermissionCheck(addr, true.B, debugMode) // todo dmode
10110214776eSpeixiaokun  val HasH = (HasHExtension == true).asBool
1012d0de7e4aSpeixiaokun  val csrAccess = csrAccessPermissionCheck(addr, false.B, privilegeMode, virtMode, HasH)
1013d0de7e4aSpeixiaokun  val modePermitted = csrAccess === 0.U && dcsrPermitted && triggerPermitted
1014321934c7SKunlin You  val perfcntPermitted = perfcntPermissionCheck(addr, privilegeMode, mcounteren, scounteren)
1015d0de7e4aSpeixiaokun  val permitted = Mux(addrInPerfCnt, perfcntPermitted, modePermitted) && Mux(virtMode, vaccessPermitted, accessPermitted)
1016d0de7e4aSpeixiaokun  MaskedRegMap.generate(mapping, addr, rdata_tmp, wen && permitted, wdata)
1017d0de7e4aSpeixiaokun  rdata := Mux(is_vsip_ie, ZeroExt(rdata_tmp >> 1, XLEN), rdata_tmp)
10186a35d972SXuan Hu  io.out.bits.res.data := rdata
10196a35d972SXuan Hu  io.out.bits.ctrl.flushPipe.get := flushPipe
1020c1e19666Sxiaofeibao-xjtu  connect0LatencyCtrlSingal
1021c84054caSLinJiawei
1022b6982e83SLemover  // send distribute csr a w signal
1023b6982e83SLemover  csrio.customCtrl.distribute_csr.w.valid := wen && permitted
1024b6982e83SLemover  csrio.customCtrl.distribute_csr.w.bits.data := wdata
1025b6982e83SLemover  csrio.customCtrl.distribute_csr.w.bits.addr := addr
1026b6982e83SLemover
1027a4e57ea3SLi Qianruo  when (RegNext(csrio.fpu.fflags.valid)) {
1028577fcf2aSZhaoyang You    fcsr := fflags_wfn(update = true)(RegEnable(csrio.fpu.fflags.bits, csrio.fpu.fflags.valid))
1029c84054caSLinJiawei  }
10306355a2b7Sczw  when(RegNext(csrio.vpu.set_vxsat.valid)) {
103184d38341Ssinsanction    vcsr := vxsat_wfn(update = true)(RegEnable(csrio.vpu.set_vxsat.bits, csrio.vpu.set_vxsat.valid))
10326355a2b7Sczw  }
103384d38341Ssinsanction
1034c84054caSLinJiawei  // set fs and sd in mstatus
1035a4e57ea3SLi Qianruo  when (csrw_dirty_fp_state || RegNext(csrio.fpu.dirty_fs)) {
1036c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1037c84054caSLinJiawei    mstatusNew.fs := "b11".U
1038c84054caSLinJiawei    mstatusNew.sd := true.B
10395d669833SYinan Xu    mstatus := mstatusNew.asUInt
1040cf025d06Speixiaokun    when(virtMode){
1041cf025d06Speixiaokun      val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1042cf025d06Speixiaokun      vsstatusNew.fs := "b11".U
1043cf025d06Speixiaokun      vsstatusNew.sd := true.B
1044cf025d06Speixiaokun      vsstatus := vsstatusNew.asUInt
1045c84054caSLinJiawei    }
1046c84054caSLinJiawei  }
1047129a273eSYinan Xu  csrio.fpu.frm := fcsr.asTypeOf(new FcsrStruct).frm
1048c84054caSLinJiawei
104935d1557aSZiyue Zhang  when (RegNext(csrio.vpu.set_vstart.valid)) {
1050577fcf2aSZhaoyang You    vstart := RegEnable(csrio.vpu.set_vstart.bits, csrio.vpu.set_vstart.valid)
1051daa01159SZiyue Zhang  }
105235d1557aSZiyue Zhang  when (RegNext(csrio.vpu.set_vtype.valid)) {
1053577fcf2aSZhaoyang You    vtype := RegEnable(csrio.vpu.set_vtype.bits, csrio.vpu.set_vtype.valid)
1054daa01159SZiyue Zhang  }
1055d8a50338SZiyue Zhang  vl := csrio.vpu.vl
1056daa01159SZiyue Zhang  // set vs and sd in mstatus
105762a2cb19SXuan Hu  when(csrw_dirty_vs_state || RegNext(csrio.vpu.dirty_vs)) {
105862a2cb19SXuan Hu    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
105962a2cb19SXuan Hu    mstatusNew.vs := ContextStatus.dirty
106062a2cb19SXuan Hu    mstatusNew.sd := true.B
106162a2cb19SXuan Hu    mstatus := mstatusNew.asUInt
106262a2cb19SXuan Hu  }
1063daa01159SZiyue Zhang
1064daa01159SZiyue Zhang  csrio.vpu.vstart := vstart
1065daa01159SZiyue Zhang  csrio.vpu.vxrm := vcsr.asTypeOf(new VcsrStruct).vxrm
106672951335SLi Qianruo
106772951335SLi Qianruo  // Trigger Ctrl
1068f7af4c74Schengguanghui  val triggerEnableVec = tdata1RegVec.map { tdata1 =>
1069f7af4c74Schengguanghui    val mcontrolData = tdata1.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData)
1070f7af4c74Schengguanghui    tdata1.asTypeOf(new Tdata1Bundle).type_.asUInt === TrigTypeEnum.MCONTROL && (
10710ffeff0dSXuan Hu      mcontrolData.m && privilegeMode === ModeM ||
10720ffeff0dSXuan Hu        mcontrolData.s && privilegeMode === ModeS ||
10730ffeff0dSXuan Hu        mcontrolData.u && privilegeMode === ModeU)
107472951335SLi Qianruo  }
1075f7af4c74Schengguanghui  val fetchTriggerEnableVec = triggerEnableVec.zip(tdata1WireVec).map {
1076f7af4c74Schengguanghui    case (tEnable, tdata1) => tEnable && tdata1.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isFetchTrigger
1077f7af4c74Schengguanghui  }
1078f7af4c74Schengguanghui  val memAccTriggerEnableVec = triggerEnableVec.zip(tdata1WireVec).map {
1079f7af4c74Schengguanghui    case (tEnable, tdata1) => tEnable && tdata1.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isMemAccTrigger
1080f7af4c74Schengguanghui  }
1081f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tEnableVec := fetchTriggerEnableVec
1082f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tEnableVec := memAccTriggerEnableVec
1083f7af4c74Schengguanghui
1084f7af4c74Schengguanghui  val tdata1Update = wen && (addr === Tdata1.U)
1085f7af4c74Schengguanghui  val tdata2Update = wen && (addr === Tdata2.U)
1086f7af4c74Schengguanghui  val triggerUpdate = wen && (addr === Tdata1.U || addr === Tdata2.U)
1087f7af4c74Schengguanghui  val frontendTriggerUpdate =
1088f7af4c74Schengguanghui    tdata1Update && wdata.asTypeOf(new Tdata1Bundle).type_.asUInt === TrigTypeEnum.MCONTROL &&
1089f7af4c74Schengguanghui      wdata.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isFetchTrigger ||
1090f7af4c74Schengguanghui      tdata1Selected.data.asTypeOf(new MControlData).isFetchTrigger && triggerUpdate
1091f7af4c74Schengguanghui  val memTriggerUpdate =
1092f7af4c74Schengguanghui    tdata1Update && wdata.asTypeOf(new Tdata1Bundle).type_.asUInt === TrigTypeEnum.MCONTROL &&
1093f7af4c74Schengguanghui      wdata.asTypeOf(new Tdata1Bundle).data.asTypeOf(new MControlData).isMemAccTrigger ||
1094f7af4c74Schengguanghui      tdata1Selected.data.asTypeOf(new MControlData).isMemAccTrigger && triggerUpdate
1095f7af4c74Schengguanghui
1096f7af4c74Schengguanghui  csrio.customCtrl.frontend_trigger.tUpdate.valid := RegNext(RegNext(frontendTriggerUpdate))
1097f7af4c74Schengguanghui  csrio.customCtrl.mem_trigger.tUpdate.valid := RegNext(RegNext(memTriggerUpdate))
1098f7af4c74Schengguanghui  XSDebug(triggerEnableVec.reduce(_ || _), p"Debug Mode: At least 1 trigger is enabled," +
1099f7af4c74Schengguanghui    p"trigger enable is ${Binary(triggerEnableVec.asUInt)}\n")
110072951335SLi Qianruo
1101c84054caSLinJiawei  // CSR inst decode
11028e7b11e5SWilliam Wang  val isEbreak = addr === privEbreak && func === CSROpType.jmp
1103c84054caSLinJiawei  val isEcall  = addr === privEcall  && func === CSROpType.jmp
1104c84054caSLinJiawei  val isMret   = addr === privMret   && func === CSROpType.jmp
1105c84054caSLinJiawei  val isSret   = addr === privSret   && func === CSROpType.jmp
1106c84054caSLinJiawei  val isUret   = addr === privUret   && func === CSROpType.jmp
1107d4aca96cSlqre  val isDret   = addr === privDret   && func === CSROpType.jmp
11085d669833SYinan Xu  val isWFI    = func === CSROpType.wfi
1109c84054caSLinJiawei
1110321934c7SKunlin You  // Illegal privileged operation list
1111321934c7SKunlin You  val illegalMret = valid && isMret && privilegeMode < ModeM
1112321934c7SKunlin You  val illegalSret = valid && isSret && privilegeMode < ModeS
1113d0de7e4aSpeixiaokun  val illegalSModeSret = valid && isSret && privilegeMode === ModeS && virtMode === false.B && mstatusStruct.tsr.asBool
1114d0de7e4aSpeixiaokun  // when hstatus.vtsr == 1, if sret is executed in VS-mode, it will cause virtual instruction
1115d0de7e4aSpeixiaokun  val illegalVSModeSret = valid && isSret && privilegeMode === ModeS && virtMode && hstatusStruct.vtsr.asBool
11165d669833SYinan Xu  // When TW=1, then if WFI is executed in any less-privileged mode,
11175d669833SYinan Xu  // and it does not complete within an implementation-specific, bounded time limit,
11185d669833SYinan Xu  // the WFI instruction causes an illegal instruction exception.
11195d669833SYinan Xu  // The time limit may always be 0, in which case WFI always causes
11205d669833SYinan Xu  // an illegal instruction exception in less-privileged modes when TW=1.
1121d0de7e4aSpeixiaokun  val illegalWFI = valid && isWFI && (privilegeMode < ModeM && mstatusStruct.tw === 1.U ||  privilegeMode === ModeU && !virtMode)
1122d0de7e4aSpeixiaokun  val illegalVWFI = valid && isWFI && ((virtMode && privilegeMode === ModeS && hstatusStruct.vtw === 1.U && mstatusStruct.tw === 0.U)||
1123d0de7e4aSpeixiaokun      (virtMode && privilegeMode === ModeU && mstatusStruct.tw === 0.U))
1124321934c7SKunlin You  // Illegal privileged instruction check
11251be7b39aSXuan Hu  val isIllegalAddr = valid && CSROpType.isCsrAccess(func) && MaskedRegMap.isIllegalAddr(mapping, addr)
1126d0de7e4aSpeixiaokun  val isIllegalAccess = !virtMode && wen && !(Mux(addrInPerfCnt, perfcntPermitted, csrAccess === 0.U && dcsrPermitted && triggerPermitted) && accessPermitted)
11275d669833SYinan Xu  val isIllegalPrivOp = illegalMret || illegalSret || illegalSModeSret || illegalWFI
1128c84054caSLinJiawei
1129d0de7e4aSpeixiaokun  val isIllegalVAccess = virtMode && wen && (csrAccess === 2.U || !vaccessPermitted)
1130d0de7e4aSpeixiaokun  val isIllegalVPrivOp = illegalVSModeSret || illegalVWFI
1131ad3ba452Szhanglinjuan  // expose several csr bits for tlb
1132fcff7e94SZhangZifei  tlbBundle.priv.mxr   := mstatusStruct.mxr.asBool
1133fcff7e94SZhangZifei  tlbBundle.priv.sum   := mstatusStruct.sum.asBool
1134d0de7e4aSpeixiaokun  tlbBundle.priv.vmxr := vsstatusStruct.mxr.asBool
1135d0de7e4aSpeixiaokun  tlbBundle.priv.vsum := vsstatusStruct.sum.asBool
1136d0de7e4aSpeixiaokun  tlbBundle.priv.spvp := hstatusStruct.spvp
1137d0de7e4aSpeixiaokun  tlbBundle.priv.virt  := Mux(mstatusStruct.mprv.asBool, mstatusStruct.mpv & (mstatusStruct.mpp =/= ModeM), virtMode)
1138321934c7SKunlin You  tlbBundle.priv.imode := privilegeMode
11390ffeff0dSXuan Hu  tlbBundle.priv.dmode := Mux((debugMode && dcsr.asTypeOf(new DcsrStruct).mprven || !debugMode) && mstatusStruct.mprv.asBool, mstatusStruct.mpp, privilegeMode)
1140c84054caSLinJiawei
1141e9341afdSYinan Xu  // Branch control
1142f7af4c74Schengguanghui  val retTarget = WireInit(0.U)
114382e4705bSpeixiaokun  val resetSatp = (addr === Satp.U || addr === Hgatp.U || addr === Vsatp.U) && wen // write to satp will cause the pipeline be flushed
11445110577fSZiyue Zhang  val writeVstart = addr === Vstart.U && wen // write to vstart will cause the pipeline be flushed
11455110577fSZiyue Zhang  dontTouch(writeVstart)
1146c84054caSLinJiawei
1147f7af4c74Schengguanghui  val w_fcsr_change_rm = wen && addr === Fcsr.U && wdata(7, 5) =/= fcsr(7, 5)
1148f7af4c74Schengguanghui  val w_frm_change_rm = wen && addr === Frm.U && wdata(2, 0) =/= fcsr(7, 5)
1149f7af4c74Schengguanghui  val frm_change = w_fcsr_change_rm || w_frm_change_rm
1150f7af4c74Schengguanghui  val isXRet = valid && func === CSROpType.jmp && !isEcall && !isEbreak
11515110577fSZiyue Zhang  flushPipe := resetSatp || frm_change || isXRet || frontendTriggerUpdate || writeVstart
1152c84054caSLinJiawei
1153f7af4c74Schengguanghui  private val illegalRetTarget = WireInit(false.B)
1154f7af4c74Schengguanghui  when(valid) {
1155f7af4c74Schengguanghui    when(isDret) {
1156d4aca96cSlqre      retTarget := dpc(VAddrBits - 1, 0)
1157f7af4c74Schengguanghui    }.elsewhen(isMret && !illegalMret) {
1158f7af4c74Schengguanghui      retTarget := mepc(VAddrBits - 1, 0)
1159d0de7e4aSpeixiaokun    }.elsewhen(isSret && !illegalSret && !illegalSModeSret && !illegalVSModeSret) {
1160d0de7e4aSpeixiaokun      retTarget := Mux(virtMode, vsepc(VAddrBits - 1, 0), sepc(VAddrBits - 1, 0))
1161f7af4c74Schengguanghui    }.elsewhen(isUret) {
1162f7af4c74Schengguanghui      retTarget := uepc(VAddrBits - 1, 0)
1163f7af4c74Schengguanghui    }.otherwise {
1164f7af4c74Schengguanghui      illegalRetTarget := true.B
1165f7af4c74Schengguanghui    }
1166f7af4c74Schengguanghui  }.otherwise {
1167f7af4c74Schengguanghui    illegalRetTarget := true.B // when illegalRetTarget setted, retTarget should never be used
1168f7af4c74Schengguanghui  }
1169f7af4c74Schengguanghui
1170f7af4c74Schengguanghui  // Mux tree for regs
1171f7af4c74Schengguanghui  when(valid) {
1172f7af4c74Schengguanghui    when(isDret) {
1173f7af4c74Schengguanghui      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1174f7af4c74Schengguanghui      val debugModeNew = WireInit(debugMode)
1175f7af4c74Schengguanghui      when(dcsr.asTypeOf(new DcsrStruct).prv =/= ModeM) {
1176f7af4c74Schengguanghui        mstatusNew.mprv := 0.U
1177f7af4c74Schengguanghui      } //If the new privilege mode is less privileged than M-mode, MPRV in mstatus is cleared.
1178f7af4c74Schengguanghui      mstatus := mstatusNew.asUInt
11790ffeff0dSXuan Hu      privilegeMode := dcsr.asTypeOf(new DcsrStruct).prv
1180d4aca96cSlqre      debugModeNew := false.B
1181d4aca96cSlqre      debugIntrEnable := true.B
1182d4aca96cSlqre      debugMode := debugModeNew
1183d4aca96cSlqre      XSDebug("Debug Mode: Dret executed, returning to %x.", retTarget)
1184f7af4c74Schengguanghui    }.elsewhen(isMret && !illegalMret) {
1185c84054caSLinJiawei      val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1186c84054caSLinJiawei      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1187c84054caSLinJiawei      mstatusNew.ie.m := mstatusOld.pie.m
1188321934c7SKunlin You      privilegeMode := mstatusOld.mpp
1189d0de7e4aSpeixiaokun      if (HasHExtension) {
1190d0de7e4aSpeixiaokun        virtMode := mstatusOld.mpv
1191d0de7e4aSpeixiaokun        mstatusNew.mpv := 0.U
1192d0de7e4aSpeixiaokun      }
1193c84054caSLinJiawei      mstatusNew.pie.m := true.B
1194c84054caSLinJiawei      mstatusNew.mpp := ModeU
1195f7af4c74Schengguanghui      when(mstatusOld.mpp =/= ModeM) {
1196f7af4c74Schengguanghui        mstatusNew.mprv := 0.U
1197c84054caSLinJiawei      }
1198f7af4c74Schengguanghui      mstatus := mstatusNew.asUInt
119978233deeSXuan Hu    }.elsewhen(isSret && !illegalSret && !illegalSModeSret && !illegalVSModeSret) {
1200c84054caSLinJiawei      val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1201c84054caSLinJiawei      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1202d0de7e4aSpeixiaokun      val hstatusOld = WireInit(hstatus.asTypeOf(new HstatusStruct))
1203d0de7e4aSpeixiaokun      val hstatusNew = WireInit(hstatus.asTypeOf(new HstatusStruct))
1204d0de7e4aSpeixiaokun      val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1205d0de7e4aSpeixiaokun      val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1206d0de7e4aSpeixiaokun      when(virtMode === 0.U) {
1207d0de7e4aSpeixiaokun        virtMode := hstatusOld.spv
1208d0de7e4aSpeixiaokun        hstatusNew.spv := 0.U
1209c84054caSLinJiawei        mstatusNew.ie.s := mstatusOld.pie.s
1210321934c7SKunlin You        privilegeMode := Cat(0.U(1.W), mstatusOld.spp)
1211c84054caSLinJiawei        mstatusNew.pie.s := true.B
1212c84054caSLinJiawei        mstatusNew.spp := ModeU
1213f7af4c74Schengguanghui        when(mstatusOld.spp =/= ModeM) {
1214f7af4c74Schengguanghui          mstatusNew.mprv := 0.U
1215c84054caSLinJiawei        }
1216c84054caSLinJiawei        mstatus := mstatusNew.asUInt
1217d0de7e4aSpeixiaokun        hstatus := hstatusNew.asUInt
1218d0de7e4aSpeixiaokun      }.otherwise {
1219d0de7e4aSpeixiaokun        privilegeMode := vsstatusOld.spp
1220d0de7e4aSpeixiaokun        vsstatusNew.spp := ModeU
1221d0de7e4aSpeixiaokun        vsstatusNew.ie.s := vsstatusOld.pie.s
1222d0de7e4aSpeixiaokun        vsstatusNew.pie.s := 1.U
1223d0de7e4aSpeixiaokun        vsstatus := vsstatusNew.asUInt
1224d0de7e4aSpeixiaokun      }
1225f7af4c74Schengguanghui    }.elsewhen(isUret) {
1226c84054caSLinJiawei      val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1227c84054caSLinJiawei      val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1228c84054caSLinJiawei      // mstatusNew.mpp.m := ModeU //TODO: add mode U
1229c84054caSLinJiawei      mstatusNew.ie.u := mstatusOld.pie.u
1230321934c7SKunlin You      privilegeMode := ModeU
1231c84054caSLinJiawei      mstatusNew.pie.u := true.B
1232c84054caSLinJiawei      mstatus := mstatusNew.asUInt
1233f7af4c74Schengguanghui    }
1234c84054caSLinJiawei  }
1235c84054caSLinJiawei
1236e9341afdSYinan Xu  io.in.ready := true.B
1237e9341afdSYinan Xu  io.out.valid := valid
1238e9341afdSYinan Xu
1239f7af4c74Schengguanghui  // In this situation, hart will enter debug mode instead of handling a breakpoint exception simply.
1240f7af4c74Schengguanghui  // Ebreak block instructions backwards, so it's ok to not keep extra info to distinguish between breakpoint
1241f7af4c74Schengguanghui  // exception and enter-debug-mode exception.
1242f7af4c74Schengguanghui  val ebreakEnterDebugMode =
12435b0f0029SXuan Hu    (privilegeMode === ModeM && dcsrData.ebreakm) ||
12445b0f0029SXuan Hu    (privilegeMode === ModeS && dcsrData.ebreaks) ||
12455b0f0029SXuan Hu    (privilegeMode === ModeU && dcsrData.ebreaku)
1246f7af4c74Schengguanghui
1247f7af4c74Schengguanghui  // raise a debug exception waiting to enter debug mode, instead of a breakpoint exception
1248f7af4c74Schengguanghui  val raiseDebugException = !debugMode && isEbreak && ebreakEnterDebugMode
1249d4aca96cSlqre
12503b739f49SXuan Hu  val csrExceptionVec = WireInit(0.U.asTypeOf(ExceptionVec()))
1251f7af4c74Schengguanghui  csrExceptionVec(breakPoint) := io.in.valid && isEbreak
1252321934c7SKunlin You  csrExceptionVec(ecallM) := privilegeMode === ModeM && io.in.valid && isEcall
1253d0de7e4aSpeixiaokun  csrExceptionVec(ecallVS) := privilegeMode === ModeS && virtMode && io.in.valid && isEcall
1254d0de7e4aSpeixiaokun  csrExceptionVec(ecallS) := privilegeMode === ModeS && !virtMode && io.in.valid && isEcall
1255321934c7SKunlin You  csrExceptionVec(ecallU) := privilegeMode === ModeU && io.in.valid && isEcall
1256baf8def6SYinan Xu  // Trigger an illegal instr exception when:
1257baf8def6SYinan Xu  // * unimplemented csr is being read/written
1258baf8def6SYinan Xu  // * csr access is illegal
12595d669833SYinan Xu  csrExceptionVec(illegalInstr) := isIllegalAddr || isIllegalAccess || isIllegalPrivOp
1260d0de7e4aSpeixiaokun  csrExceptionVec(virtualInstr) := isIllegalVAccess || isIllegalVPrivOp
12616a35d972SXuan Hu  io.out.bits.ctrl.exceptionVec.get := csrExceptionVec
1262baf8def6SYinan Xu
1263f7af4c74Schengguanghui  XSDebug(io.in.valid, s"Debug Mode: an Ebreak is executed, ebreak cause enter-debug-mode exception ? ${raiseDebugException}\n")
126484e47f35SLi Qianruo
1265e9341afdSYinan Xu  /**
1266e9341afdSYinan Xu    * Exception and Intr
1267e9341afdSYinan Xu    */
1268d0de7e4aSpeixiaokun  val idelegS =  (mideleg & mip.asUInt)
1269d0de7e4aSpeixiaokun  val idelegVS = (hideleg & mideleg & mip.asUInt)
1270d0de7e4aSpeixiaokun  def privilegedEnableDetect(idelegS: Bool, idelegVS: Bool): Bool = Mux(idelegS,
1271d0de7e4aSpeixiaokun    Mux(idelegVS, (virtMode && privilegeMode === ModeS && vsstatusStruct.ie.s) || (virtMode && privilegeMode < ModeS),
1272d0de7e4aSpeixiaokun      ((privilegeMode === ModeS) && mstatusStruct.ie.s) || (privilegeMode < ModeS) || virtMode),
1273321934c7SKunlin You    ((privilegeMode === ModeM) && mstatusStruct.ie.m) || (privilegeMode < ModeM))
1274e9341afdSYinan Xu
1275d4aca96cSlqre  val debugIntr = csrio.externalInterrupt.debug & debugIntrEnable
1276d4aca96cSlqre  XSDebug(debugIntr, "Debug Mode: debug interrupt is asserted and valid!")
12779aca92b9SYinan Xu  // send interrupt information to ROB
1278d0de7e4aSpeixiaokun  val intrVecEnable = Wire(Vec(13, Bool()))
1279052ee9a1SLi Qianruo  val disableInterrupt = debugMode || (dcsrData.step && !dcsrData.stepie)
1280d0de7e4aSpeixiaokun  intrVecEnable.zip(idelegS.asBools).zip(idelegVS.asBools).map{case((x,y),z) => x := privilegedEnableDetect(y, z) && !disableInterrupt}
1281d7dd1af1SLi Qianruo  val intrVec = Cat(debugIntr && !debugMode, (mie(11,0) & mip.asUInt & intrVecEnable.asUInt))
12825d669833SYinan Xu  val intrBitSet = intrVec.orR
1283e9341afdSYinan Xu  csrio.interrupt := intrBitSet
12845c95ea2eSYinan Xu  // Page 45 in RISC-V Privileged Specification
12855c95ea2eSYinan Xu  // The WFI instruction can also be executed when interrupts are disabled. The operation of WFI
12865c95ea2eSYinan Xu  // must be unaffected by the global interrupt bits in mstatus (MIE and SIE) and the delegation
12875c95ea2eSYinan Xu  // register mideleg, but should honor the individual interrupt enables (e.g, MTIE).
12884ede3fe2SLi Qianruo  csrio.wfi_event := debugIntr || (mie(11, 0) & mip.asUInt).orR
1289e9341afdSYinan Xu  mipWire.t.m := csrio.externalInterrupt.mtip
1290e9341afdSYinan Xu  mipWire.s.m := csrio.externalInterrupt.msip
1291e9341afdSYinan Xu  mipWire.e.m := csrio.externalInterrupt.meip
1292b3d79b37SYinan Xu  mipWire.e.s := csrio.externalInterrupt.seip
1293e9341afdSYinan Xu
1294e9341afdSYinan Xu  // interrupts
1295e9341afdSYinan Xu  val intrNO = IntPriority.foldRight(0.U)((i: Int, sum: UInt) => Mux(intrVec(i), i.U, sum))
1296f7af4c74Schengguanghui  val hasIntr = csrio.exception.valid && csrio.exception.bits.isInterrupt
1297a4e57ea3SLi Qianruo  val ivmEnable = tlbBundle.priv.imode < ModeM && satp.asTypeOf(new SatpStruct).mode === 8.U
12983b739f49SXuan Hu  val iexceptionPC = Mux(ivmEnable, SignExt(csrio.exception.bits.pc, XLEN), csrio.exception.bits.pc)
1299e25e4d90SXuan Hu  val iexceptionGPAddr = Mux(ivmEnable, SignExt(csrio.exception.bits.gpaddr, XLEN), csrio.exception.bits.gpaddr)
1300a4e57ea3SLi Qianruo  val dvmEnable = tlbBundle.priv.dmode < ModeM && satp.asTypeOf(new SatpStruct).mode === 8.U
13013b739f49SXuan Hu  val dexceptionPC = Mux(dvmEnable, SignExt(csrio.exception.bits.pc, XLEN), csrio.exception.bits.pc)
1302f7af4c74Schengguanghui  XSDebug(hasIntr, "interrupt: pc=0x%x, %d\n", dexceptionPC, intrNO)
1303f7af4c74Schengguanghui  val hasDebugIntr = intrNO === IRQ_DEBUG.U && hasIntr
1304e9341afdSYinan Xu
1305f7af4c74Schengguanghui  // exceptions from rob need to handle
1306f7af4c74Schengguanghui  val exceptionVecFromRob    = csrio.exception.bits.exceptionVec
1307f7af4c74Schengguanghui  val hasException           = csrio.exception.valid && !csrio.exception.bits.isInterrupt
1308f7af4c74Schengguanghui  val hasInstrPageFault      = hasException && exceptionVecFromRob(instrPageFault)
1309f7af4c74Schengguanghui  val hasLoadPageFault       = hasException && exceptionVecFromRob(loadPageFault)
1310f7af4c74Schengguanghui  val hasStorePageFault      = hasException && exceptionVecFromRob(storePageFault)
1311f7af4c74Schengguanghui  val hasStoreAddrMisalign   = hasException && exceptionVecFromRob(storeAddrMisaligned)
1312f7af4c74Schengguanghui  val hasLoadAddrMisalign    = hasException && exceptionVecFromRob(loadAddrMisaligned)
1313f7af4c74Schengguanghui  val hasInstrAccessFault    = hasException && exceptionVecFromRob(instrAccessFault)
1314f7af4c74Schengguanghui  val hasLoadAccessFault     = hasException && exceptionVecFromRob(loadAccessFault)
1315f7af4c74Schengguanghui  val hasStoreAccessFault    = hasException && exceptionVecFromRob(storeAccessFault)
1316f7af4c74Schengguanghui  val hasBreakPoint          = hasException && exceptionVecFromRob(breakPoint)
13171f518b57SXuan Hu  val hasInstGuestPageFault  = hasException && exceptionVecFromRob(instrGuestPageFault)
13181f518b57SXuan Hu  val hasLoadGuestPageFault  = hasException && exceptionVecFromRob(loadGuestPageFault)
13191f518b57SXuan Hu  val hasStoreGuestPageFault = hasException && exceptionVecFromRob(storeGuestPageFault)
1320f7af4c74Schengguanghui  val hasSingleStep          = hasException && csrio.exception.bits.singleStep
1321f7af4c74Schengguanghui  val hasTriggerFire         = hasException && csrio.exception.bits.trigger.canFire
1322f7af4c74Schengguanghui  val triggerFrontendHitVec = csrio.exception.bits.trigger.frontendHit
1323f7af4c74Schengguanghui  val triggerMemHitVec = csrio.exception.bits.trigger.backendHit
1324f7af4c74Schengguanghui  val triggerHitVec = triggerFrontendHitVec | triggerMemHitVec // Todo: update mcontrol.hit
1325f7af4c74Schengguanghui  val triggerCanFireVec = csrio.exception.bits.trigger.frontendCanFire | csrio.exception.bits.trigger.backendCanFire
1326f7af4c74Schengguanghui  // More than one triggers can hit at the same time, but only fire one
1327f7af4c74Schengguanghui  // We select the first hit trigger to fire
1328f7af4c74Schengguanghui  val triggerFireOH = PriorityEncoderOH(triggerCanFireVec)
1329f7af4c74Schengguanghui  val triggerFireAction = PriorityMux(triggerFireOH, tdata1WireVec.map(_.getTriggerAction)).asUInt
1330f7af4c74Schengguanghui
133184e47f35SLi Qianruo
133284e47f35SLi Qianruo  XSDebug(hasSingleStep, "Debug Mode: single step exception\n")
1333f7af4c74Schengguanghui  XSDebug(hasTriggerFire, p"Debug Mode: trigger fire, frontend hit vec ${Binary(csrio.exception.bits.trigger.frontendHit.asUInt)} " +
1334f7af4c74Schengguanghui    p"backend hit vec ${Binary(csrio.exception.bits.trigger.backendHit.asUInt)}\n")
1335e9341afdSYinan Xu
1336f7af4c74Schengguanghui  val hasExceptionVec = csrio.exception.bits.exceptionVec
1337f7af4c74Schengguanghui  val regularExceptionNO = ExceptionNO.priorities.foldRight(0.U)((i: Int, sum: UInt) => Mux(hasExceptionVec(i), i.U, sum))
1338f7af4c74Schengguanghui  val exceptionNO = Mux(hasSingleStep || hasTriggerFire, 3.U, regularExceptionNO)
1339f7af4c74Schengguanghui  val causeNO = (hasIntr << (XLEN - 1)).asUInt | Mux(hasIntr, intrNO, exceptionNO)
1340e9341afdSYinan Xu
1341f7af4c74Schengguanghui  val hasExceptionIntr = csrio.exception.valid
1342d4aca96cSlqre
1343f7af4c74Schengguanghui  val hasDebugEbreakException = hasBreakPoint && ebreakEnterDebugMode
1344f7af4c74Schengguanghui  val hasDebugTriggerException = hasTriggerFire && triggerFireAction === TrigActionEnum.DEBUG_MODE
1345f7af4c74Schengguanghui  val hasDebugException = hasDebugEbreakException || hasDebugTriggerException || hasSingleStep
1346f7af4c74Schengguanghui  val hasDebugTrap = hasDebugException || hasDebugIntr
1347f7af4c74Schengguanghui  val ebreakEnterParkLoop = debugMode && hasExceptionIntr
1348f7af4c74Schengguanghui
1349f7af4c74Schengguanghui  XSDebug(hasExceptionIntr, "int/exc: pc %x int (%d):%x exc: (%d):%x\n",
1350f7af4c74Schengguanghui    dexceptionPC, intrNO, intrVec, exceptionNO, hasExceptionVec.asUInt
1351e9341afdSYinan Xu  )
1352f7af4c74Schengguanghui  XSDebug(hasExceptionIntr,
1353e9341afdSYinan Xu    "pc %x mstatus %x mideleg %x medeleg %x mode %x\n",
1354a4e57ea3SLi Qianruo    dexceptionPC,
1355e9341afdSYinan Xu    mstatus,
1356e9341afdSYinan Xu    mideleg,
1357e9341afdSYinan Xu    medeleg,
1358321934c7SKunlin You    privilegeMode
1359e9341afdSYinan Xu  )
1360e9341afdSYinan Xu
1361e9341afdSYinan Xu  // mtval write logic
13628a33de1fSYinan Xu  // Due to timing reasons of memExceptionVAddr, we delay the write of mtval and stval
1363e9341afdSYinan Xu  val memExceptionAddr = SignExt(csrio.memExceptionVAddr, XLEN)
1364d0de7e4aSpeixiaokun  val memExceptionGPAddr = SignExt(csrio.memExceptionGPAddr, XLEN)
1365a4e57ea3SLi Qianruo  val updateTval = VecInit(Seq(
1366a4e57ea3SLi Qianruo    hasInstrPageFault,
1367a4e57ea3SLi Qianruo    hasLoadPageFault,
1368a4e57ea3SLi Qianruo    hasStorePageFault,
1369a4e57ea3SLi Qianruo    hasInstrAccessFault,
1370a4e57ea3SLi Qianruo    hasLoadAccessFault,
1371a4e57ea3SLi Qianruo    hasStoreAccessFault,
1372f7af4c74Schengguanghui    hasLoadAddrMisalign,
13735b0f0029SXuan Hu    hasStoreAddrMisalign,
1374d0de7e4aSpeixiaokun    hasInstGuestPageFault,
1375d0de7e4aSpeixiaokun    hasLoadGuestPageFault,
13761797fef6SXuan Hu    hasStoreGuestPageFault,
13771797fef6SXuan Hu    hasBreakPoint,
1378d0de7e4aSpeixiaokun  )).asUInt.orR
1379d0de7e4aSpeixiaokun  val updateTval_h = VecInit(Seq(
1380d0de7e4aSpeixiaokun    hasInstGuestPageFault,
1381d0de7e4aSpeixiaokun    hasLoadGuestPageFault,
1382d0de7e4aSpeixiaokun    hasStoreGuestPageFault
1383a4e57ea3SLi Qianruo  )).asUInt.orR
1384a4e57ea3SLi Qianruo  when (RegNext(RegNext(updateTval))) {
138595fbbc80SYinan Xu      val tval = Mux(
13861797fef6SXuan Hu        RegNext(RegNext(hasInstrPageFault || hasInstrAccessFault || hasInstGuestPageFault || hasBreakPoint)),
138795fbbc80SYinan Xu        RegNext(RegNext(Mux(
13883b739f49SXuan Hu          csrio.exception.bits.crossPageIPFFix,
13893b739f49SXuan Hu          SignExt(csrio.exception.bits.pc + 2.U, XLEN),
1390a4e57ea3SLi Qianruo          iexceptionPC
139195fbbc80SYinan Xu        ))),
1392e9341afdSYinan Xu        memExceptionAddr
139395fbbc80SYinan Xu    )
1394d0de7e4aSpeixiaokun    // because we update tval two beats later, we can choose xtval according to the privilegeMode which has been updated
1395321934c7SKunlin You    when (RegNext(privilegeMode === ModeM)) {
1396e9341afdSYinan Xu      mtval := tval
1397e9341afdSYinan Xu    }.otherwise {
1398d0de7e4aSpeixiaokun      when (virtMode){
1399d0de7e4aSpeixiaokun        vstval := tval
1400d0de7e4aSpeixiaokun      }.otherwise{
1401e9341afdSYinan Xu        stval := tval
1402e9341afdSYinan Xu      }
1403e9341afdSYinan Xu    }
1404d0de7e4aSpeixiaokun  }
1405d0de7e4aSpeixiaokun
1406d0de7e4aSpeixiaokun  when(RegNext(RegNext(updateTval_h))) {
1407d0de7e4aSpeixiaokun    val tval_tmp = Mux(
1408d0de7e4aSpeixiaokun      RegNext(RegNext(hasInstGuestPageFault)),
1409d0de7e4aSpeixiaokun      RegNext(RegNext(Mux(
1410e25e4d90SXuan Hu        csrio.exception.bits.crossPageIPFFix,
1411e25e4d90SXuan Hu        SignExt(csrio.exception.bits.gpaddr + 2.U, XLEN),
1412d0de7e4aSpeixiaokun        iexceptionGPAddr
1413d0de7e4aSpeixiaokun      ))),
1414d0de7e4aSpeixiaokun      memExceptionGPAddr
1415d0de7e4aSpeixiaokun    )
1416d0de7e4aSpeixiaokun    val tval = tval_tmp >> 2
1417d0de7e4aSpeixiaokun    when(RegNext(privilegeMode === ModeM)) {
1418d0de7e4aSpeixiaokun      mtval2 := tval
1419d0de7e4aSpeixiaokun    }.otherwise {
1420d0de7e4aSpeixiaokun      htval := tval
1421d0de7e4aSpeixiaokun    }
1422d0de7e4aSpeixiaokun  }
1423e9341afdSYinan Xu
1424d4aca96cSlqre  val debugTrapTarget = Mux(!isEbreak && debugMode, 0x38020808.U, 0x38020800.U) // 0x808 is when an exception occurs in debug mode prog buf exec
1425f7af4c74Schengguanghui  val deleg = Mux(hasIntr, mideleg , medeleg)
14261f518b57SXuan Hu  val hdeleg = Mux(hasIntr, hideleg, hedeleg)
1427321934c7SKunlin You  // val delegS = ((deleg & (1 << (causeNO & 0xf))) != 0) && (privilegeMode < ModeM);
14285b0f0029SXuan Hu  val delegS = deleg(causeNO(7,0)) && (privilegeMode < ModeM)
1429d0de7e4aSpeixiaokun  val delegVS = virtMode && delegS && hdeleg(causeNO(7, 0)) && (privilegeMode < ModeM)
1430f7af4c74Schengguanghui  val clearTval = !updateTval || hasIntr
143113096f7eSYinan Xu
14321f518b57SXuan Hu  val clearTval_h = !updateTval_h || hasIntr
1433e25e4d90SXuan Hu  val isHyperInst = csrio.exception.bits.isHls
143413096f7eSYinan Xu  // ctrl block will use theses later for flush
143513096f7eSYinan Xu  val isXRetFlag = RegInit(false.B)
14363b739f49SXuan Hu  when (DelayN(io.flush.valid, 5)) {
143713096f7eSYinan Xu    isXRetFlag := false.B
143813096f7eSYinan Xu  }.elsewhen (isXRet) {
143913096f7eSYinan Xu    isXRetFlag := true.B
144013096f7eSYinan Xu  }
144113096f7eSYinan Xu  csrio.isXRet := isXRetFlag
1442f7af4c74Schengguanghui  private val retTargetReg = RegEnable(retTarget, isXRet && !illegalRetTarget)
1443d0de7e4aSpeixiaokun  private val illegalXret = RegEnable(illegalMret || illegalSret || illegalSModeSret || illegalVSModeSret, isXRet)
1444a4e57ea3SLi Qianruo
1445e25e4d90SXuan Hu  private val xtvec = Mux(delegS, Mux(delegVS, vstvec, stvec), mtvec)
1446f7af4c74Schengguanghui  private val xtvecBase = xtvec(VAddrBits - 1, 2)
1447a4e57ea3SLi Qianruo  // When MODE=Vectored, all synchronous exceptions into M/S mode
1448a4e57ea3SLi Qianruo  // cause the pc to be set to the address in the BASE field, whereas
1449a4e57ea3SLi Qianruo  // interrupts cause the pc to be set to the address in the BASE field
1450a4e57ea3SLi Qianruo  // plus four times the interrupt cause number.
1451f7af4c74Schengguanghui  private val pcFromXtvec = Cat(xtvecBase + Mux(xtvec(0) && hasIntr, causeNO(3, 0), 0.U), 0.U(2.W))
1452e9341afdSYinan Xu
1453f7af4c74Schengguanghui  // XRet sends redirect instead of Flush and isXRetFlag is true.B before redirect.valid.
1454f7af4c74Schengguanghui  // ROB sends exception at T0 while CSR receives at T2.
1455f7af4c74Schengguanghui  // We add a RegNext here and trapTarget is valid at T3.
1456f7af4c74Schengguanghui  csrio.trapTarget := RegEnable(
1457f7af4c74Schengguanghui    MuxCase(pcFromXtvec, Seq(
1458f7af4c74Schengguanghui      (isXRetFlag && !illegalXret) -> retTargetReg,
1459f7af4c74Schengguanghui      ((hasDebugTrap && !debugMode) || ebreakEnterParkLoop) -> debugTrapTarget
1460f7af4c74Schengguanghui    )),
1461f7af4c74Schengguanghui    isXRetFlag || csrio.exception.valid)
1462f7af4c74Schengguanghui
1463f7af4c74Schengguanghui  when(hasExceptionIntr) {
1464c84054caSLinJiawei    val mstatusOld = WireInit(mstatus.asTypeOf(new MstatusStruct))
1465c84054caSLinJiawei    val mstatusNew = WireInit(mstatus.asTypeOf(new MstatusStruct))
1466d0de7e4aSpeixiaokun    val hstatusOld = WireInit(hstatus.asTypeOf(new HstatusStruct))
1467d0de7e4aSpeixiaokun    val hstatusNew = WireInit(hstatus.asTypeOf(new HstatusStruct))
1468d0de7e4aSpeixiaokun    val vsstatusOld = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1469d0de7e4aSpeixiaokun    val vsstatusNew = WireInit(vsstatus.asTypeOf(new MstatusStruct))
1470d4aca96cSlqre    val dcsrNew = WireInit(dcsr.asTypeOf(new DcsrStruct))
1471d4aca96cSlqre    val debugModeNew = WireInit(debugMode)
1472f7af4c74Schengguanghui    when(hasDebugTrap && !debugMode) {
1473f7af4c74Schengguanghui      import DcsrStruct._
1474d4aca96cSlqre      debugModeNew := true.B
14750ffeff0dSXuan Hu      dcsrNew.prv := privilegeMode
14760ffeff0dSXuan Hu      privilegeMode := ModeM
1477f7af4c74Schengguanghui      when(hasDebugIntr) {
1478a4e57ea3SLi Qianruo        dpc := iexceptionPC
1479f7af4c74Schengguanghui        dcsrNew.cause := CAUSE_HALTREQ
1480f7af4c74Schengguanghui        XSDebug(hasDebugIntr, "Debug Mode: Trap to %x at pc %x\n", debugTrapTarget, dpc)
1481f7af4c74Schengguanghui      }.otherwise { // hasDebugException
1482f7af4c74Schengguanghui        dpc := iexceptionPC // TODO: check it when hasSingleStep
1483f7af4c74Schengguanghui        dcsrNew.cause := MuxCase(0.U, Seq(
1484f7af4c74Schengguanghui          hasTriggerFire -> CAUSE_TRIGGER,
14855f28e666Schengguanghui          raiseDebugException -> CAUSE_EBREAK,
1486f7af4c74Schengguanghui          hasBreakPoint -> CAUSE_HALTREQ,
1487f7af4c74Schengguanghui          hasSingleStep -> CAUSE_STEP
1488f7af4c74Schengguanghui        ))
1489d4aca96cSlqre      }
1490d4aca96cSlqre      dcsr := dcsrNew.asUInt
1491d4aca96cSlqre      debugIntrEnable := false.B
1492d7dd1af1SLi Qianruo    }.elsewhen (debugMode) {
1493d7dd1af1SLi Qianruo      //do nothing
1494d61cd5eeSpeixiaokun    }.elsewhen (delegVS) {
149596544367Speixiaokun      vscause := (hasIntr << (XLEN-1)).asUInt | Mux(hasIntr, intrNO - 1.U, exceptionNO)
1496d0de7e4aSpeixiaokun      vsepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1497d0de7e4aSpeixiaokun      vsstatusNew.spp := privilegeMode
1498d0de7e4aSpeixiaokun      vsstatusNew.pie.s := vsstatusOld.ie.s
1499d0de7e4aSpeixiaokun      vsstatusNew.ie.s := false.B
1500d0de7e4aSpeixiaokun      when (clearTval) {vstval := 0.U}
1501d0de7e4aSpeixiaokun      virtMode := true.B
1502d0de7e4aSpeixiaokun      privilegeMode := ModeS
1503d4aca96cSlqre    }.elsewhen (delegS) {
15040214776eSpeixiaokun      val virt = Mux(mstatusOld.mprv.asBool, mstatusOld.mpv, virtMode)
1505d0de7e4aSpeixiaokun      // to do hld st
1506d0de7e4aSpeixiaokun      hstatusNew.gva := (hasInstGuestPageFault || hasLoadGuestPageFault || hasStoreGuestPageFault ||
15071f518b57SXuan Hu                      ((virt.asBool || isHyperInst) && ((hasException && 0.U <= exceptionNO && exceptionNO <= 7.U && exceptionNO =/= 2.U)
1508d0de7e4aSpeixiaokun                      || hasInstrPageFault || hasLoadPageFault || hasStorePageFault)))
1509d0de7e4aSpeixiaokun      hstatusNew.spv := virtMode
1510d0de7e4aSpeixiaokun      when(virtMode){
1511d0de7e4aSpeixiaokun        hstatusNew.spvp := privilegeMode
1512d0de7e4aSpeixiaokun      }
1513d0de7e4aSpeixiaokun      virtMode := false.B
1514c84054caSLinJiawei      scause := causeNO
1515a4e57ea3SLi Qianruo      sepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1516321934c7SKunlin You      mstatusNew.spp := privilegeMode
1517c84054caSLinJiawei      mstatusNew.pie.s := mstatusOld.ie.s
1518c84054caSLinJiawei      mstatusNew.ie.s := false.B
1519321934c7SKunlin You      privilegeMode := ModeS
1520a4e57ea3SLi Qianruo      when (clearTval) { stval := 0.U }
1521d0de7e4aSpeixiaokun      when (clearTval_h) {htval := 0.U}
1522c84054caSLinJiawei    }.otherwise {
15230214776eSpeixiaokun      val virt = Mux(mstatusOld.mprv.asBool, mstatusOld.mpv, virtMode)
1524d0de7e4aSpeixiaokun      // to do hld st
1525d0de7e4aSpeixiaokun      mstatusNew.gva := (hasInstGuestPageFault || hasLoadGuestPageFault || hasStoreGuestPageFault ||
15261f518b57SXuan Hu      ((virt.asBool || isHyperInst) && ((hasException && 0.U <= exceptionNO && exceptionNO <= 7.U && exceptionNO =/= 2.U)
1527d0de7e4aSpeixiaokun        || hasInstrPageFault || hasLoadPageFault || hasStorePageFault)))
1528d0de7e4aSpeixiaokun      mstatusNew.mpv := virtMode
1529d0de7e4aSpeixiaokun      virtMode := false.B
1530c84054caSLinJiawei      mcause := causeNO
1531a4e57ea3SLi Qianruo      mepc := Mux(hasInstrPageFault || hasInstrAccessFault, iexceptionPC, dexceptionPC)
1532321934c7SKunlin You      mstatusNew.mpp := privilegeMode
1533c84054caSLinJiawei      mstatusNew.pie.m := mstatusOld.ie.m
1534c84054caSLinJiawei      mstatusNew.ie.m := false.B
1535321934c7SKunlin You      privilegeMode := ModeM
1536a4e57ea3SLi Qianruo      when (clearTval) { mtval := 0.U }
1537d0de7e4aSpeixiaokun      when (clearTval_h) {mtval2 := 0.U}
1538c84054caSLinJiawei    }
1539c84054caSLinJiawei    mstatus := mstatusNew.asUInt
1540d0de7e4aSpeixiaokun    vsstatus := vsstatusNew.asUInt
1541d0de7e4aSpeixiaokun    hstatus := hstatusNew.asUInt
1542d4aca96cSlqre    debugMode := debugModeNew
1543c84054caSLinJiawei  }
1544c84054caSLinJiawei
15459ef181f4SWilliam Wang  // Cache error debug support
15469ef181f4SWilliam Wang  if(HasCustomCSRCacheOp){
15479ef181f4SWilliam Wang    val cache_error_decoder = Module(new CSRCacheErrorDecoder)
15489ef181f4SWilliam Wang    cache_error_decoder.io.encoded_cache_error := cacheopRegs("CACHE_ERROR")
15499ef181f4SWilliam Wang  }
15509ef181f4SWilliam Wang
1551e30fd06aSYinan Xu  // Implicit add reset values for mepc[0] and sepc[0]
1552e30fd06aSYinan Xu  // TODO: rewrite mepc and sepc using a struct-like style with the LSB always being 0
155367ba96b4SYinan Xu  when (RegNext(RegNext(reset.asBool) && !reset.asBool)) {
1554e30fd06aSYinan Xu    mepc := Cat(mepc(XLEN - 1, 1), 0.U(1.W))
1555e30fd06aSYinan Xu    sepc := Cat(sepc(XLEN - 1, 1), 0.U(1.W))
155621ae6bc4Speixiaokun    vsepc := Cat(vsepc(XLEN - 1, 1), 0.U(1.W))
1557e30fd06aSYinan Xu  }
1558e30fd06aSYinan Xu
1559c84054caSLinJiawei  def readWithScala(addr: Int): UInt = mapping(addr)._1
1560c84054caSLinJiawei
1561f7af4c74Schengguanghui  val difftestIntrNO = Mux(hasIntr, causeNO, 0.U)
1562a165bd69Swangkaifan
1563cbe9a847SYinan Xu  // Always instantiate basic difftest modules.
1564cbe9a847SYinan Xu  if (env.AlwaysBasicDiff || env.EnableDifftest) {
15657d45a146SYinan Xu    val difftest = DifftestModule(new DiffArchEvent, delay = 3, dontCare = true)
15667d45a146SYinan Xu    difftest.coreid      := csrio.hartId
15677d45a146SYinan Xu    difftest.valid       := csrio.exception.valid
1568f7af4c74Schengguanghui    difftest.interrupt   := Mux(hasIntr, causeNO, 0.U)
1569f7af4c74Schengguanghui    difftest.exception   := Mux(hasException, causeNO, 0.U)
15707d45a146SYinan Xu    difftest.exceptionPC := dexceptionPC
1571a4e57ea3SLi Qianruo    if (env.EnableDifftest) {
15724b0d80d8SXuan Hu      difftest.exceptionInst := csrio.exception.bits.instr
1573a4e57ea3SLi Qianruo    }
15742225d46eSJiawei Lin  }
15752225d46eSJiawei Lin
1576cbe9a847SYinan Xu  // Always instantiate basic difftest modules.
1577cbe9a847SYinan Xu  if (env.AlwaysBasicDiff || env.EnableDifftest) {
15787d45a146SYinan Xu    val difftest = DifftestModule(new DiffCSRState)
15797d45a146SYinan Xu    difftest.coreid := csrio.hartId
1580321934c7SKunlin You    difftest.privilegeMode := privilegeMode
15817d45a146SYinan Xu    difftest.mstatus := mstatus
15827d45a146SYinan Xu    difftest.sstatus := mstatus & sstatusRmask
15837d45a146SYinan Xu    difftest.mepc := mepc
15847d45a146SYinan Xu    difftest.sepc := sepc
15857d45a146SYinan Xu    difftest.mtval:= mtval
15867d45a146SYinan Xu    difftest.stval:= stval
15877d45a146SYinan Xu    difftest.mtvec := mtvec
15887d45a146SYinan Xu    difftest.stvec := stvec
15897d45a146SYinan Xu    difftest.mcause := mcause
15907d45a146SYinan Xu    difftest.scause := scause
15917d45a146SYinan Xu    difftest.satp := satp
15927d45a146SYinan Xu    difftest.mip := mipReg
15937d45a146SYinan Xu    difftest.mie := mie
15947d45a146SYinan Xu    difftest.mscratch := mscratch
15957d45a146SYinan Xu    difftest.sscratch := sscratch
15967d45a146SYinan Xu    difftest.mideleg := mideleg
15977d45a146SYinan Xu    difftest.medeleg := medeleg
1598a165bd69Swangkaifan  }
1599a4e57ea3SLi Qianruo
1600a4e57ea3SLi Qianruo  if (env.AlwaysBasicDiff || env.EnableDifftest) {
160187d0ba30Speixiaokun    val difftest = DifftestModule(new DiffHCSRState)
160287d0ba30Speixiaokun    difftest.coreid := csrio.hartId
160387d0ba30Speixiaokun    difftest.virtMode := virtMode
160487d0ba30Speixiaokun    difftest.mtval2 := mtval2
160587d0ba30Speixiaokun    difftest.mtinst := mtinst
160687d0ba30Speixiaokun    difftest.hstatus := hstatus
160787d0ba30Speixiaokun    difftest.hideleg := hideleg
160887d0ba30Speixiaokun    difftest.hedeleg := hedeleg
160987d0ba30Speixiaokun    difftest.hcounteren := hcounteren
161087d0ba30Speixiaokun    difftest.htval := htval
161187d0ba30Speixiaokun    difftest.htinst := htinst
161287d0ba30Speixiaokun    difftest.hgatp := hgatp
161387d0ba30Speixiaokun    difftest.vsstatus := vsstatus
161487d0ba30Speixiaokun    difftest.vstvec := vstvec
161587d0ba30Speixiaokun    difftest.vsepc := vsepc
161687d0ba30Speixiaokun    difftest.vscause := vscause
161787d0ba30Speixiaokun    difftest.vstval := vstval
161887d0ba30Speixiaokun    difftest.vsatp := vsatp
161987d0ba30Speixiaokun    difftest.vsscratch := vsscratch
1620d0de7e4aSpeixiaokun  }
1621d0de7e4aSpeixiaokun
1622d0de7e4aSpeixiaokun  if(env.AlwaysBasicDiff || env.EnableDifftest) {
16237d45a146SYinan Xu    val difftest = DifftestModule(new DiffDebugMode)
16247d45a146SYinan Xu    difftest.coreid := csrio.hartId
16257d45a146SYinan Xu    difftest.debugMode := debugMode
16267d45a146SYinan Xu    difftest.dcsr := dcsr
16277d45a146SYinan Xu    difftest.dpc := dpc
1628f7af4c74Schengguanghui    difftest.dscratch0 := dscratch0
16297d45a146SYinan Xu    difftest.dscratch1 := dscratch1
1630a4e57ea3SLi Qianruo  }
163135d1557aSZiyue Zhang
163235d1557aSZiyue Zhang  if (env.AlwaysBasicDiff || env.EnableDifftest) {
163383ba63b3SXuan Hu    val difftest = DifftestModule(new DiffVecCSRState)
163483ba63b3SXuan Hu    difftest.coreid := csrio.hartId
163583ba63b3SXuan Hu    difftest.vstart := vstart
163683ba63b3SXuan Hu    difftest.vxsat := vcsr.asTypeOf(new VcsrStruct).vxsat
163783ba63b3SXuan Hu    difftest.vxrm := vcsr.asTypeOf(new VcsrStruct).vxrm
163883ba63b3SXuan Hu    difftest.vcsr := vcsr
163983ba63b3SXuan Hu    difftest.vl := vl
164083ba63b3SXuan Hu    difftest.vtype := vtype
164183ba63b3SXuan Hu    difftest.vlenb := vlenb
164235d1557aSZiyue Zhang  }
1643c84054caSLinJiawei}
1644075d4937Sjunxiong-jiclass PFEvent(implicit p: Parameters) extends XSModule {
1645cd365d4cSrvcoresjw  val io = IO(new Bundle {
1646cd365d4cSrvcoresjw    val distribute_csr = Flipped(new DistributedCSRIO())
1647cd365d4cSrvcoresjw    val hpmevent = Output(Vec(29, UInt(XLEN.W)))
1648cd365d4cSrvcoresjw  })
1649cd365d4cSrvcoresjw
1650cd365d4cSrvcoresjw  val w = io.distribute_csr.w
1651cd365d4cSrvcoresjw
16525fd90906Srvcoresjw  val perfEvents = List.fill(8)(RegInit("h0000000000".U(XLEN.W))) ++
16535fd90906Srvcoresjw                   List.fill(8)(RegInit("h4010040100".U(XLEN.W))) ++
16545fd90906Srvcoresjw                   List.fill(8)(RegInit("h8020080200".U(XLEN.W))) ++
16555fd90906Srvcoresjw                   List.fill(5)(RegInit("hc0300c0300".U(XLEN.W)))
1656cd365d4cSrvcoresjw
165712c44ce5Srvcoresjw  val perfEventMapping = (0 until 29).map(i => {Map(
1658075d4937Sjunxiong-ji    MaskedRegMap(addr = CSRs.mhpmevent3 + i,
165912c44ce5Srvcoresjw                 reg  = perfEvents(i),
166012c44ce5Srvcoresjw                 wmask = "hf87fff3fcff3fcff".U(XLEN.W))
166112c44ce5Srvcoresjw  )}).fold(Map())((a,b) => a ++ b)
1662cd365d4cSrvcoresjw
1663cd365d4cSrvcoresjw  val rdata = Wire(UInt(XLEN.W))
1664cd365d4cSrvcoresjw  MaskedRegMap.generate(perfEventMapping, w.bits.addr, rdata, w.valid, w.bits.data)
16655fd90906Srvcoresjw  for(i <- 0 until 29){
16665fd90906Srvcoresjw    io.hpmevent(i) := perfEvents(i)
16675fd90906Srvcoresjw  }
1668cd365d4cSrvcoresjw}
1669a67fd0f5SGuanghui Cheng*/
1670