xref: /XiangShan/src/main/scala/xiangshan/backend/rob/Rob.scala (revision 2e4f14ff584706af76b9623737fb513b9b9e7abb)
19aca92b9SYinan Xu/***************************************************************************************
29aca92b9SYinan Xu* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
39aca92b9SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory
49aca92b9SYinan Xu*
59aca92b9SYinan Xu* XiangShan is licensed under Mulan PSL v2.
69aca92b9SYinan Xu* You can use this software according to the terms and conditions of the Mulan PSL v2.
79aca92b9SYinan Xu* You may obtain a copy of Mulan PSL v2 at:
89aca92b9SYinan Xu*          http://license.coscl.org.cn/MulanPSL2
99aca92b9SYinan Xu*
109aca92b9SYinan Xu* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
119aca92b9SYinan Xu* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
129aca92b9SYinan Xu* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
139aca92b9SYinan Xu*
149aca92b9SYinan Xu* See the Mulan PSL v2 for more details.
15c49ebec8SHaoyuan Feng*
16c49ebec8SHaoyuan Feng*
17c49ebec8SHaoyuan Feng* Acknowledgement
18c49ebec8SHaoyuan Feng*
19c49ebec8SHaoyuan Feng* This implementation is inspired by several key papers:
20c49ebec8SHaoyuan Feng* [1] James E. Smith, and Andrew R. Pleszkun. "[Implementation of precise interrupts in pipelined processors.]
21c49ebec8SHaoyuan Feng* (https://dl.acm.org/doi/10.5555/327010.327125)" 12th Annual International Symposium on Computer Architecture (ISCA).
22c49ebec8SHaoyuan Feng* 1985.
239aca92b9SYinan Xu***************************************************************************************/
249aca92b9SYinan Xu
259aca92b9SYinan Xupackage xiangshan.backend.rob
269aca92b9SYinan Xu
278891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
289aca92b9SYinan Xuimport chisel3._
299aca92b9SYinan Xuimport chisel3.util._
30e43bb916SXuan Huimport chisel3.experimental.BundleLiterals._
319aca92b9SYinan Xuimport difftest._
326ab6918fSYinan Xuimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
333c02ee8fSwakafaimport utility._
343b739f49SXuan Huimport utils._
356ab6918fSYinan Xuimport xiangshan._
36ad415ae0SXiaokun-Peiimport xiangshan.backend.GPAMemEntry
37e43bb916SXuan Huimport xiangshan.backend.{BackendParams, RatToVecExcpMod, RegWriteFromRab, VecExcpInfo}
38d91483a6Sfdyimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
394c7680e0SXuan Huimport xiangshan.backend.fu.{FuConfig, FuType}
406ab6918fSYinan Xuimport xiangshan.frontend.FtqPtr
41870f462dSXuan Huimport xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr}
42730cfbc0SXuan Huimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
43870f462dSXuan Huimport xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo}
444c7680e0SXuan Huimport xiangshan.backend.fu.vector.Bundles.VType
45870f462dSXuan Huimport xiangshan.backend.rename.SnapshotGenerator
46d280e426Slewislzhimport yunsuan.VfaluType
47780712aaSxiaofeibao-xjtuimport xiangshan.backend.rob.RobBundles._
4849162c9aSGuanghui Chengimport xiangshan.backend.trace._
496a8b2d5fSxiaofeibao-xjtuimport chisel3.experimental.BundleLiterals._
509aca92b9SYinan Xu
513b739f49SXuan Huclass Rob(params: BackendParams)(implicit p: Parameters) extends LazyModule with HasXSParameter {
5295e60e55STang Haojin  override def shouldBeInlined: Boolean = false
536ab6918fSYinan Xu
543b739f49SXuan Hu  lazy val module = new RobImp(this)(p, params)
556ab6918fSYinan Xu}
566ab6918fSYinan Xu
573b739f49SXuan Huclass RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendParams) extends LazyModuleImp(wrapper)
5885a8d7caSZehao Liu  with HasXSParameter with HasCircularQueuePtrHelper with HasPerfEvents with HasCriticalErrors {
596ab6918fSYinan Xu
60870f462dSXuan Hu  private val LduCnt = params.LduCnt
61870f462dSXuan Hu  private val StaCnt = params.StaCnt
626810d1e8Ssfencevma  private val HyuCnt = params.HyuCnt
63870f462dSXuan Hu
649aca92b9SYinan Xu  val io = IO(new Bundle() {
65f57f7f2aSYangyu Chen    val hartId = Input(UInt(hartIdLen.W))
669aca92b9SYinan Xu    val redirect = Input(Valid(new Redirect))
679aca92b9SYinan Xu    val enq = new RobEnqIO
68f4b2089aSYinan Xu    val flushOut = ValidIO(new Redirect)
699aca92b9SYinan Xu    val exception = ValidIO(new ExceptionInfo)
709aca92b9SYinan Xu    // exu + brq
713b739f49SXuan Hu    val writeback: MixedVec[ValidIO[ExuOutput]] = Flipped(params.genWrite2CtrlBundles)
72bd5909d0Sxiaofeibao-xjtu    val exuWriteback: MixedVec[ValidIO[ExuOutput]] = Flipped(params.genWrite2CtrlBundles)
7385f51ecaSxiaofeibao-xjtu    val writebackNums = Flipped(Vec(writeback.size - params.StdCnt, ValidIO(UInt(writeback.size.U.getWidth.W))))
74571677c9Sxiaofeibao-xjtu    val writebackNeedFlush = Input(Vec(params.allExuParams.filter(_.needExceptionGen).length, Bool()))
75ccfddc82SHaojin Tang    val commits = Output(new RobCommitIO)
764907ec88Schengguanghui    val trace = new Bundle {
774907ec88Schengguanghui      val blockCommit = Input(Bool())
784907ec88Schengguanghui      val traceCommitInfo = new TraceBundle(hasIaddr = false, CommitWidth, IretireWidthInPipe)
794907ec88Schengguanghui    }
806b102a39SHaojin Tang    val rabCommits = Output(new RabCommitIO)
8163d67ef3STang Haojin    val diffCommits = if (backendParams.basicDebugEn) Some(Output(new DiffCommitIO)) else None
82a8db15d8Sfdy    val isVsetFlushPipe = Output(Bool())
839aca92b9SYinan Xu    val lsq = new RobLsqIO
849aca92b9SYinan Xu    val robDeqPtr = Output(new RobPtr)
859aca92b9SYinan Xu    val csr = new RobCSRIO
86fa7f2c26STang Haojin    val snpt = Input(new SnapshotPort)
879aca92b9SYinan Xu    val robFull = Output(Bool())
88d2b20d1aSTang Haojin    val headNotReady = Output(Bool())
89b6900d94SYinan Xu    val cpu_halt = Output(Bool())
9009309bdbSYinan Xu    val wfi_enable = Input(Bool())
914c7680e0SXuan Hu    val toDecode = new Bundle {
9286727929Ssinsanction      val isResumeVType = Output(Bool())
93d275ad0eSZiyue Zhang      val walkToArchVType = Output(Bool())
9481535d7bSsinsanction      val walkVType = ValidIO(VType())
957e4f0b19SZiyue-Zhang      val commitVType = new Bundle {
967e4f0b19SZiyue-Zhang        val vtype = ValidIO(VType())
977e4f0b19SZiyue-Zhang        val hasVsetvl = Output(Bool())
984c7680e0SXuan Hu      }
999aca92b9SYinan Xu    }
100b9a37d2fSXuan Hu    val fromVecExcpMod = Input(new Bundle {
101b9a37d2fSXuan Hu      val busy = Bool()
102b9a37d2fSXuan Hu    })
1036f483f86SXuan Hu    val readGPAMemAddr = ValidIO(new Bundle {
1046f483f86SXuan Hu      val ftqPtr = new FtqPtr()
1056f483f86SXuan Hu      val ftqOffset = UInt(log2Up(PredictWidth).W)
1066f483f86SXuan Hu    })
107ad415ae0SXiaokun-Pei    val readGPAMemData = Input(new GPAMemEntry)
1085110577fSZiyue Zhang    val vstartIsZero = Input(Bool())
10960ebee38STang Haojin
110e43bb916SXuan Hu    val toVecExcpMod = Output(new Bundle {
111e43bb916SXuan Hu      val logicPhyRegMap = Vec(RabCommitWidth, ValidIO(new RegWriteFromRab))
112e43bb916SXuan Hu      val excpInfo = ValidIO(new VecExcpInfo)
113e43bb916SXuan Hu    })
1148744445eSMaxpicca-Li    val debug_ls = Flipped(new DebugLSIO)
115870f462dSXuan Hu    val debugRobHead = Output(new DynInst)
116d2b20d1aSTang Haojin    val debugEnqLsq = Input(new LsqEnqIO)
117d2b20d1aSTang Haojin    val debugHeadLsIssue = Input(Bool())
1186810d1e8Ssfencevma    val lsTopdownInfo = Vec(LduCnt + HyuCnt, Input(new LsTopdownInfo))
11960ebee38STang Haojin    val debugTopDown = new Bundle {
12060ebee38STang Haojin      val toCore = new RobCoreTopDownIO
12160ebee38STang Haojin      val toDispatch = new RobDispatchTopDownIO
12260ebee38STang Haojin      val robHeadLqIdx = Valid(new LqPtr)
12360ebee38STang Haojin    }
1247cf78eb2Shappy-lx    val debugRolling = new RobDebugRollingIO
1251bf9a598SAnzo
1261bf9a598SAnzo    // store event difftest information
1271bf9a598SAnzo    val storeDebugInfo = Vec(EnsbufferWidth, new Bundle {
1281bf9a598SAnzo      val robidx = Input(new RobPtr)
1291bf9a598SAnzo      val pc     = Output(UInt(VAddrBits.W))
1301bf9a598SAnzo    })
1319aca92b9SYinan Xu  })
1329aca92b9SYinan Xu
133bd5909d0Sxiaofeibao-xjtu  val exuWBs: Seq[ValidIO[ExuOutput]] = io.exuWriteback.filter(!_.bits.params.hasStdFu).toSeq
134bd5909d0Sxiaofeibao-xjtu  val stdWBs: Seq[ValidIO[ExuOutput]] = io.exuWriteback.filter(_.bits.params.hasStdFu).toSeq
135bd5909d0Sxiaofeibao-xjtu  val fflagsWBs = io.exuWriteback.filter(x => x.bits.fflags.nonEmpty).toSeq
1361d2f6c6bSsinsanction  val exceptionWBs = io.writeback.filter(x => x.bits.exceptionVec.nonEmpty).toSeq
1371d2f6c6bSsinsanction  val redirectWBs = io.writeback.filter(x => x.bits.redirect.nonEmpty).toSeq
138bd5909d0Sxiaofeibao-xjtu  val vxsatWBs = io.exuWriteback.filter(x => x.bits.vxsat.nonEmpty).toSeq
13949162c9aSGuanghui Cheng  val branchWBs = io.exuWriteback.filter(_.bits.params.hasBrhFu).toSeq
14049162c9aSGuanghui Cheng  val csrWBs = io.exuWriteback.filter(x => x.bits.params.hasCSR).toSeq
1413b739f49SXuan Hu
1423b739f49SXuan Hu  val numExuWbPorts = exuWBs.length
1433b739f49SXuan Hu  val numStdWbPorts = stdWBs.length
144780712aaSxiaofeibao-xjtu  val bankAddrWidth = log2Up(CommitWidth)
1456ab6918fSYinan Xu
1463b739f49SXuan Hu  println(s"Rob: size $RobSize, numExuWbPorts: $numExuWbPorts, numStdWbPorts: $numStdWbPorts, commitwidth: $CommitWidth")
1473b739f49SXuan Hu
148780712aaSxiaofeibao-xjtu  val rab = Module(new RenameBuffer(RabSize))
149780712aaSxiaofeibao-xjtu  val vtypeBuffer = Module(new VTypeBuffer(VTypeBufferSize))
150780712aaSxiaofeibao-xjtu  val bankNum = 8
151780712aaSxiaofeibao-xjtu  assert(RobSize % bankNum == 0, "RobSize % bankNum must be 0")
1526a8b2d5fSxiaofeibao-xjtu  val robEntries = RegInit(VecInit.fill(RobSize)((new RobEntryBundle).Lit(_.valid -> false.B)))
153780712aaSxiaofeibao-xjtu  // pointers
154780712aaSxiaofeibao-xjtu  // For enqueue ptr, we don't duplicate it since only enqueue needs it.
155780712aaSxiaofeibao-xjtu  val enqPtrVec = Wire(Vec(RenameWidth, new RobPtr))
156780712aaSxiaofeibao-xjtu  val deqPtrVec = Wire(Vec(CommitWidth, new RobPtr))
157ea2894c8SXuan Hu  val deqPtrVec_next = Wire(Vec(CommitWidth, Output(new RobPtr)))
158780712aaSxiaofeibao-xjtu  val walkPtrVec = Reg(Vec(CommitWidth, new RobPtr))
159c0f8424bSzhanglyGit  val walkPtrTrue = Reg(new RobPtr)
160780712aaSxiaofeibao-xjtu  val lastWalkPtr = Reg(new RobPtr)
161780712aaSxiaofeibao-xjtu  val allowEnqueue = RegInit(true.B)
16235b3b30bSxiaofeibao  val allowEnqueueForDispatch = RegInit(true.B)
163e43bb916SXuan Hu  val vecExcpInfo = RegInit(ValidIO(new VecExcpInfo).Lit(
164e43bb916SXuan Hu    _.valid -> false.B,
165e43bb916SXuan Hu  ))
1669aca92b9SYinan Xu
167780712aaSxiaofeibao-xjtu  /**
168780712aaSxiaofeibao-xjtu   * Enqueue (from dispatch)
169780712aaSxiaofeibao-xjtu   */
170780712aaSxiaofeibao-xjtu  // special cases
171780712aaSxiaofeibao-xjtu  val hasBlockBackward = RegInit(false.B)
172780712aaSxiaofeibao-xjtu  val hasWaitForward = RegInit(false.B)
173780712aaSxiaofeibao-xjtu  val doingSvinval = RegInit(false.B)
174780712aaSxiaofeibao-xjtu  val enqPtr = enqPtrVec(0)
175780712aaSxiaofeibao-xjtu  val deqPtr = deqPtrVec(0)
176780712aaSxiaofeibao-xjtu  val walkPtr = walkPtrVec(0)
177780712aaSxiaofeibao-xjtu  val allocatePtrVec = VecInit((0 until RenameWidth).map(i => enqPtrVec(PopCount(io.enq.req.take(i).map(req => req.valid && req.bits.firstUop)))))
178b9a37d2fSXuan Hu  io.enq.canAccept := allowEnqueue && !hasBlockBackward && rab.io.canEnq && vtypeBuffer.io.canEnq && !io.fromVecExcpMod.busy
1795540bdc7Sxiaofeibao  io.enq.canAcceptForDispatch := allowEnqueueForDispatch && !hasBlockBackward && rab.io.canEnqForDispatch && vtypeBuffer.io.canEnqForDispatch && !io.fromVecExcpMod.busy
180780712aaSxiaofeibao-xjtu  io.enq.resp := allocatePtrVec
181780712aaSxiaofeibao-xjtu  val canEnqueue = VecInit(io.enq.req.map(req => req.valid && req.bits.firstUop && io.enq.canAccept))
182780712aaSxiaofeibao-xjtu  val timer = GTimer()
183780712aaSxiaofeibao-xjtu  // robEntries enqueue
184780712aaSxiaofeibao-xjtu  for (i <- 0 until RobSize) {
185780712aaSxiaofeibao-xjtu    val enqOH = VecInit(canEnqueue.zip(allocatePtrVec.map(_.value === i.U)).map(x => x._1 && x._2))
186780712aaSxiaofeibao-xjtu    assert(PopCount(enqOH) < 2.U, s"robEntries$i enqOH is not one hot")
187780712aaSxiaofeibao-xjtu    when(enqOH.asUInt.orR && !io.redirect.valid){
188780712aaSxiaofeibao-xjtu      connectEnq(robEntries(i), Mux1H(enqOH, io.enq.req.map(_.bits)))
189a8db15d8Sfdy    }
190af4bdb08SXuan Hu  }
191780712aaSxiaofeibao-xjtu  // robBanks0 include robidx : 0 8 16 24 32 ...
192780712aaSxiaofeibao-xjtu  val robBanks = VecInit((0 until bankNum).map(i => VecInit(robEntries.zipWithIndex.filter(_._2 % bankNum == i).map(_._1))))
193780712aaSxiaofeibao-xjtu  // each Bank has 20 Entries, read addr is one hot
194780712aaSxiaofeibao-xjtu  // all banks use same raddr
195780712aaSxiaofeibao-xjtu  val eachBankEntrieNum = robBanks(0).length
196780712aaSxiaofeibao-xjtu  val robBanksRaddrThisLine = RegInit(1.U(eachBankEntrieNum.W))
197780712aaSxiaofeibao-xjtu  val robBanksRaddrNextLine = Wire(UInt(eachBankEntrieNum.W))
198780712aaSxiaofeibao-xjtu  robBanksRaddrThisLine := robBanksRaddrNextLine
199780712aaSxiaofeibao-xjtu  val bankNumWidth = log2Up(bankNum)
200780712aaSxiaofeibao-xjtu  val deqPtrWidth = deqPtr.value.getWidth
201780712aaSxiaofeibao-xjtu  val robIdxThisLine = VecInit((0 until bankNum).map(i => Cat(deqPtr.value(deqPtrWidth - 1, bankNumWidth), i.U(bankNumWidth.W))))
202780712aaSxiaofeibao-xjtu  val robIdxNextLine = VecInit((0 until bankNum).map(i => Cat(deqPtr.value(deqPtrWidth - 1, bankNumWidth) + 1.U, i.U(bankNumWidth.W))))
203780712aaSxiaofeibao-xjtu  // robBanks read
204780712aaSxiaofeibao-xjtu  val robBanksRdataThisLine = VecInit(robBanks.map{ case bank =>
205780712aaSxiaofeibao-xjtu    Mux1H(robBanksRaddrThisLine, bank)
206780712aaSxiaofeibao-xjtu  })
207780712aaSxiaofeibao-xjtu  val robBanksRdataNextLine = VecInit(robBanks.map{ case bank =>
208780712aaSxiaofeibao-xjtu    val shiftBank = bank.drop(1) :+ bank(0)
209780712aaSxiaofeibao-xjtu    Mux1H(robBanksRaddrThisLine, shiftBank)
210780712aaSxiaofeibao-xjtu  })
211780712aaSxiaofeibao-xjtu  val robBanksRdataThisLineUpdate = Wire(Vec(CommitWidth, new RobEntryBundle))
212780712aaSxiaofeibao-xjtu  val robBanksRdataNextLineUpdate = Wire(Vec(CommitWidth, new RobEntryBundle))
213780712aaSxiaofeibao-xjtu  val commitValidThisLine = Wire(Vec(CommitWidth, Bool()))
214780712aaSxiaofeibao-xjtu  val hasCommitted = RegInit(VecInit(Seq.fill(CommitWidth)(false.B)))
215780712aaSxiaofeibao-xjtu  val donotNeedWalk = RegInit(VecInit(Seq.fill(CommitWidth)(false.B)))
216780712aaSxiaofeibao-xjtu  val allCommitted = Wire(Bool())
217af4bdb08SXuan Hu
218780712aaSxiaofeibao-xjtu  when(allCommitted) {
219780712aaSxiaofeibao-xjtu    hasCommitted := 0.U.asTypeOf(hasCommitted)
220780712aaSxiaofeibao-xjtu  }.elsewhen(io.commits.isCommit){
221780712aaSxiaofeibao-xjtu    for (i <- 0 until CommitWidth){
222780712aaSxiaofeibao-xjtu      hasCommitted(i) := commitValidThisLine(i) || hasCommitted(i)
223780712aaSxiaofeibao-xjtu    }
224780712aaSxiaofeibao-xjtu  }
225780712aaSxiaofeibao-xjtu  allCommitted := io.commits.isCommit && commitValidThisLine.last
226780712aaSxiaofeibao-xjtu  val walkPtrHead = Wire(new RobPtr)
227780712aaSxiaofeibao-xjtu  val changeBankAddrToDeqPtr = (walkPtrVec.head + CommitWidth.U) > lastWalkPtr
228780712aaSxiaofeibao-xjtu  when(io.redirect.valid){
229780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := UIntToOH(walkPtrHead.value(walkPtrHead.value.getWidth-1, bankAddrWidth))
230780712aaSxiaofeibao-xjtu  }.elsewhen(allCommitted || io.commits.isWalk && !changeBankAddrToDeqPtr){
231780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := Mux(robBanksRaddrThisLine.head(1) === 1.U, 1.U, robBanksRaddrThisLine << 1)
232780712aaSxiaofeibao-xjtu  }.elsewhen(io.commits.isWalk && changeBankAddrToDeqPtr){
233780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := UIntToOH(deqPtr.value(deqPtr.value.getWidth-1, bankAddrWidth))
234780712aaSxiaofeibao-xjtu  }.otherwise(
235780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := robBanksRaddrThisLine
236780712aaSxiaofeibao-xjtu  )
237780712aaSxiaofeibao-xjtu  val robDeqGroup = Reg(Vec(bankNum, new RobCommitEntryBundle))
238d904dcfbSchengguanghui  val rawInfo = VecInit((0 until CommitWidth).map(i => robDeqGroup(deqPtrVec(i).value(bankAddrWidth-1, 0)))).toSeq
239780712aaSxiaofeibao-xjtu  val commitInfo = VecInit((0 until CommitWidth).map(i => robDeqGroup(deqPtrVec(i).value(bankAddrWidth-1,0)))).toSeq
2404c30949dSxiao feibao  val walkInfo = VecInit((0 until CommitWidth).map(i => robDeqGroup(walkPtrVec(i).value(bankAddrWidth-1, 0)))).toSeq
241780712aaSxiaofeibao-xjtu  for (i <- 0 until CommitWidth) {
242780712aaSxiaofeibao-xjtu    connectCommitEntry(robDeqGroup(i), robBanksRdataThisLineUpdate(i))
243780712aaSxiaofeibao-xjtu    when(allCommitted){
244780712aaSxiaofeibao-xjtu      connectCommitEntry(robDeqGroup(i), robBanksRdataNextLineUpdate(i))
245780712aaSxiaofeibao-xjtu    }
246780712aaSxiaofeibao-xjtu  }
24749162c9aSGuanghui Cheng
248d904dcfbSchengguanghui  // In each robentry, the ftqIdx and ftqOffset belong to the first instruction that was compressed,
249d904dcfbSchengguanghui  // That is Necessary when exceptions happen.
250d904dcfbSchengguanghui  // Update the ftqOffset to correctly notify the frontend which instructions have been committed.
251d904dcfbSchengguanghui  // Instructions in multiple Ftq entries compressed to one RobEntry do not occur.
252d904dcfbSchengguanghui  for (i <- 0 until CommitWidth) {
253d904dcfbSchengguanghui    val lastOffset = (rawInfo(i).traceBlockInPipe.iretire - (1.U << rawInfo(i).traceBlockInPipe.ilastsize.asUInt).asUInt) + rawInfo(i).ftqOffset
254b720b0cdSchengguanghui    commitInfo(i).ftqOffset := Mux(CommitType.isFused(rawInfo(i).commitType), rawInfo(i).ftqOffset, lastOffset)
255d904dcfbSchengguanghui  }
256d904dcfbSchengguanghui
2579aca92b9SYinan Xu  // data for debug
2589aca92b9SYinan Xu  // Warn: debug_* prefix should not exist in generated verilog.
259c7d010e5SXuan Hu  val debug_microOp = DebugMem(RobSize, new DynInst)
2609aca92b9SYinan Xu  val debug_exuData = Reg(Vec(RobSize, UInt(XLEN.W))) //for debug
2619aca92b9SYinan Xu  val debug_exuDebug = Reg(Vec(RobSize, new DebugBundle)) //for debug
2628744445eSMaxpicca-Li  val debug_lsInfo = RegInit(VecInit(Seq.fill(RobSize)(DebugLsInfo.init)))
263d2b20d1aSTang Haojin  val debug_lsTopdownInfo = RegInit(VecInit(Seq.fill(RobSize)(LsTopdownInfo.init)))
264d2b20d1aSTang Haojin  val debug_lqIdxValid = RegInit(VecInit.fill(RobSize)(false.B))
265d2b20d1aSTang Haojin  val debug_lsIssued = RegInit(VecInit.fill(RobSize)(false.B))
2669aca92b9SYinan Xu
2679aca92b9SYinan Xu  val isEmpty = enqPtr === deqPtr
268780712aaSxiaofeibao-xjtu  val snptEnq = io.enq.canAccept && io.enq.req.map(x => x.valid && x.bits.snapshot).reduce(_ || _)
269780712aaSxiaofeibao-xjtu  val snapshotPtrVec = Wire(Vec(CommitWidth, new RobPtr))
270780712aaSxiaofeibao-xjtu  snapshotPtrVec(0) := io.enq.req(0).bits.robIdx
271780712aaSxiaofeibao-xjtu  for (i <- 1 until CommitWidth) {
272780712aaSxiaofeibao-xjtu    snapshotPtrVec(i) := snapshotPtrVec(0) + i.U
273780712aaSxiaofeibao-xjtu  }
274780712aaSxiaofeibao-xjtu  val snapshots = SnapshotGenerator(snapshotPtrVec, snptEnq, io.snpt.snptDeq, io.redirect.valid, io.snpt.flushVec)
275d2b20d1aSTang Haojin  val debug_lsIssue = WireDefault(debug_lsIssued)
276d2b20d1aSTang Haojin  debug_lsIssue(deqPtr.value) := io.debugHeadLsIssue
277d2b20d1aSTang Haojin
2789aca92b9SYinan Xu  /**
2799aca92b9SYinan Xu   * states of Rob
2809aca92b9SYinan Xu   */
281ccfddc82SHaojin Tang  val s_idle :: s_walk :: Nil = Enum(2)
2829aca92b9SYinan Xu  val state = RegInit(s_idle)
283ea2894c8SXuan Hu  val state_next = Wire(chiselTypeOf(state))
2849aca92b9SYinan Xu
2858bf33c52Swakafa  val tip_computing :: tip_stalled :: tip_walk :: tip_drained :: Nil = Enum(4)
2868bf33c52Swakafa  val tip_state = WireInit(0.U(4.W))
2878bf33c52Swakafa  when(!isEmpty) {  // One or more inst in ROB
2888bf33c52Swakafa    when(state === s_walk || io.redirect.valid) {
2898bf33c52Swakafa      tip_state := tip_walk
2908bf33c52Swakafa    }.elsewhen(io.commits.isCommit && PopCount(io.commits.commitValid) =/= 0.U) {
2918bf33c52Swakafa      tip_state := tip_computing
2928bf33c52Swakafa    }.otherwise {
2938bf33c52Swakafa      tip_state := tip_stalled
2948bf33c52Swakafa    }
2958bf33c52Swakafa  }.otherwise {
2968bf33c52Swakafa    tip_state := tip_drained
2978bf33c52Swakafa  }
2988bf33c52Swakafa  class TipEntry()(implicit p: Parameters) extends XSBundle {
2998bf33c52Swakafa    val state = UInt(4.W)
3008bf33c52Swakafa    val commits = new RobCommitIO()      // info of commit
3018bf33c52Swakafa    val redirect = Valid(new Redirect)   // info of redirect
3028bf33c52Swakafa    val redirect_pc = UInt(VAddrBits.W)  // PC of the redirect uop
3038bf33c52Swakafa    val debugLsInfo = new DebugLsInfo()
3048bf33c52Swakafa  }
3058bf33c52Swakafa  val tip_table = ChiselDB.createTable("Tip_" + p(XSCoreParamsKey).HartId.toString, new TipEntry)
3068bf33c52Swakafa  val tip_data = Wire(new TipEntry())
3078bf33c52Swakafa  tip_data.state := tip_state
3088bf33c52Swakafa  tip_data.commits := io.commits
3098bf33c52Swakafa  tip_data.redirect := io.redirect
3108bf33c52Swakafa  tip_data.redirect_pc := debug_microOp(io.redirect.bits.robIdx.value).pc
3118bf33c52Swakafa  tip_data.debugLsInfo := debug_lsInfo(io.commits.robIdx(0).value)
3128bf33c52Swakafa  tip_table.log(tip_data, true.B, "", clock, reset)
3138bf33c52Swakafa
3143b739f49SXuan Hu  val exceptionGen = Module(new ExceptionGen(params))
3159aca92b9SYinan Xu  val exceptionDataRead = exceptionGen.io.state
3169aca92b9SYinan Xu  val fflagsDataRead = Wire(Vec(CommitWidth, UInt(5.W)))
317a8db15d8Sfdy  val vxsatDataRead = Wire(Vec(CommitWidth, Bool()))
3189aca92b9SYinan Xu  io.robDeqPtr := deqPtr
319d2b20d1aSTang Haojin  io.debugRobHead := debug_microOp(deqPtr.value)
3209aca92b9SYinan Xu
3214c7680e0SXuan Hu  /**
3224c7680e0SXuan Hu   * connection of [[rab]]
3234c7680e0SXuan Hu   */
32444369838SXuan Hu  rab.io.redirect.valid := io.redirect.valid
32544369838SXuan Hu
326a8db15d8Sfdy  rab.io.req.zip(io.enq.req).map { case (dest, src) =>
327a8db15d8Sfdy    dest.bits := src.bits
328a8db15d8Sfdy    dest.valid := src.valid && io.enq.canAccept
329a8db15d8Sfdy  }
330a8db15d8Sfdy
331cda1c534Sxiaofeibao-xjtu  val walkDestSizeDeqGroup = RegInit(VecInit(Seq.fill(CommitWidth)(0.U(log2Up(MaxUopSize + 1).W))))
332780712aaSxiaofeibao-xjtu  val realDestSizeSeq = VecInit(robDeqGroup.zip(hasCommitted).map{case (r, h) => Mux(h, 0.U, r.realDestSize)})
333780712aaSxiaofeibao-xjtu  val walkDestSizeSeq = VecInit(robDeqGroup.zip(donotNeedWalk).map{case (r, d) => Mux(d, 0.U, r.realDestSize)})
334780712aaSxiaofeibao-xjtu  val commitSizeSumSeq = VecInit((0 until CommitWidth).map(i => realDestSizeSeq.take(i + 1).reduce(_ +& _)))
335780712aaSxiaofeibao-xjtu  val walkSizeSumSeq   = VecInit((0 until CommitWidth).map(i => walkDestSizeSeq.take(i + 1).reduce(_ +& _)))
336780712aaSxiaofeibao-xjtu  val commitSizeSumCond = VecInit(commitValidThisLine.zip(hasCommitted).map{case (c,h) => (c || h) && io.commits.isCommit})
337780712aaSxiaofeibao-xjtu  val walkSizeSumCond   = VecInit(io.commits.walkValid.zip(donotNeedWalk).map{case (w,d) => (w || d) && io.commits.isWalk})
338cda1c534Sxiaofeibao-xjtu  val commitSizeSum = PriorityMuxDefault(commitSizeSumCond.reverse.zip(commitSizeSumSeq.reverse), 0.U)
339cda1c534Sxiaofeibao-xjtu  val walkSizeSum   = PriorityMuxDefault(walkSizeSumCond.reverse.zip(walkSizeSumSeq.reverse), 0.U)
34044369838SXuan Hu
341fd33b932Sxiaofeibao  val deqVlsExceptionNeedCommit = RegInit(false.B)
342fd33b932Sxiaofeibao  val deqVlsExceptionCommitSize = RegInit(0.U(log2Up(MaxUopSize + 1).W))
343fd33b932Sxiaofeibao  val deqVlsCanCommit= RegInit(false.B)
344fd33b932Sxiaofeibao  rab.io.fromRob.commitSize := Mux(deqVlsExceptionNeedCommit, deqVlsExceptionCommitSize, commitSizeSum)
34565f65924SXuan Hu  rab.io.fromRob.walkSize := walkSizeSum
346e43bb916SXuan Hu  rab.io.fromRob.vecLoadExcp.valid := RegNext(exceptionDataRead.valid && exceptionDataRead.bits.isVecLoad)
347e43bb916SXuan Hu  rab.io.fromRob.vecLoadExcp.bits.isStrided := RegEnable(exceptionDataRead.bits.isStrided, exceptionDataRead.valid)
348e43bb916SXuan Hu  rab.io.fromRob.vecLoadExcp.bits.isVlm := RegEnable(exceptionDataRead.bits.isVlm, exceptionDataRead.valid)
349c4b56310SHaojin Tang  rab.io.snpt := io.snpt
3509b9e991bSHaojin Tang  rab.io.snpt.snptEnq := snptEnq
351a8db15d8Sfdy
3523019c601Sxiaofeibao  // pipe rab commits for better timing and area
3533019c601Sxiaofeibao  io.rabCommits := RegNext(rab.io.commits)
354cda1c534Sxiaofeibao-xjtu  io.diffCommits.foreach(_ := rab.io.diffCommits.get)
355a8db15d8Sfdy
3569aca92b9SYinan Xu  /**
3574c7680e0SXuan Hu   * connection of [[vtypeBuffer]]
3584c7680e0SXuan Hu   */
3594c7680e0SXuan Hu
3604c7680e0SXuan Hu  vtypeBuffer.io.redirect.valid := io.redirect.valid
3614c7680e0SXuan Hu
3624c7680e0SXuan Hu  vtypeBuffer.io.req.zip(io.enq.req).map { case (sink, source) =>
3634c7680e0SXuan Hu    sink.valid := source.valid && io.enq.canAccept
3644c7680e0SXuan Hu    sink.bits := source.bits
3654c7680e0SXuan Hu  }
3664c7680e0SXuan Hu
3673e7f8698SXuan Hu  private val commitIsVTypeVec = VecInit(io.commits.commitValid.zip(io.commits.info).map { case (valid, info) => io.commits.isCommit && valid && info.isVset })
3684c30949dSxiao feibao  private val walkIsVTypeVec = VecInit(io.commits.walkValid.zip(walkInfo).map { case (valid, info) => io.commits.isWalk && valid && info.isVset })
3694c7680e0SXuan Hu  vtypeBuffer.io.fromRob.commitSize := PopCount(commitIsVTypeVec)
3704c7680e0SXuan Hu  vtypeBuffer.io.fromRob.walkSize := PopCount(walkIsVTypeVec)
3714c7680e0SXuan Hu  vtypeBuffer.io.snpt := io.snpt
3724c7680e0SXuan Hu  vtypeBuffer.io.snpt.snptEnq := snptEnq
37386727929Ssinsanction  io.toDecode.isResumeVType := vtypeBuffer.io.toDecode.isResumeVType
374d275ad0eSZiyue Zhang  io.toDecode.walkToArchVType := vtypeBuffer.io.toDecode.walkToArchVType
37581535d7bSsinsanction  io.toDecode.commitVType := vtypeBuffer.io.toDecode.commitVType
37681535d7bSsinsanction  io.toDecode.walkVType := vtypeBuffer.io.toDecode.walkVType
377780712aaSxiaofeibao-xjtu
3789aca92b9SYinan Xu  // When blockBackward instruction leaves Rob (commit or walk), hasBlockBackward should be set to false.B
3799aca92b9SYinan Xu  // To reduce registers usage, for hasBlockBackward cases, we allow enqueue after ROB is empty.
380780712aaSxiaofeibao-xjtu  when(isEmpty) {
381780712aaSxiaofeibao-xjtu    hasBlockBackward := false.B
382780712aaSxiaofeibao-xjtu  }
3839aca92b9SYinan Xu  // When any instruction commits, hasNoSpecExec should be set to false.B
384780712aaSxiaofeibao-xjtu  when(io.commits.hasWalkInstr || io.commits.hasCommitInstr) {
385780712aaSxiaofeibao-xjtu    hasWaitForward := false.B
386780712aaSxiaofeibao-xjtu  }
3875c95ea2eSYinan Xu
3885c95ea2eSYinan Xu  // The wait-for-interrupt (WFI) instruction waits in the ROB until an interrupt might need servicing.
3895c95ea2eSYinan Xu  // io.csr.wfiEvent will be asserted if the WFI can resume execution, and we change the state to s_wfi_idle.
3905c95ea2eSYinan Xu  // It does not affect how interrupts are serviced. Note that WFI is noSpecExec and it does not trigger interrupts.
3915c95ea2eSYinan Xu  val hasWFI = RegInit(false.B)
3925c95ea2eSYinan Xu  io.cpu_halt := hasWFI
393342656a5SYinan Xu  // WFI Timeout: 2^20 = 1M cycles
394342656a5SYinan Xu  val wfi_cycles = RegInit(0.U(20.W))
395342656a5SYinan Xu  when(hasWFI) {
396342656a5SYinan Xu    wfi_cycles := wfi_cycles + 1.U
397342656a5SYinan Xu  }.elsewhen(!hasWFI && RegNext(hasWFI)) {
398342656a5SYinan Xu    wfi_cycles := 0.U
399342656a5SYinan Xu  }
400342656a5SYinan Xu  val wfi_timeout = wfi_cycles.andR
401342656a5SYinan Xu  when(RegNext(RegNext(io.csr.wfiEvent)) || io.flushOut.valid || wfi_timeout) {
4025c95ea2eSYinan Xu    hasWFI := false.B
403b6900d94SYinan Xu  }
4049aca92b9SYinan Xu
4059aca92b9SYinan Xu  for (i <- 0 until RenameWidth) {
4069aca92b9SYinan Xu    // we don't check whether io.redirect is valid here since redirect has higher priority
4079aca92b9SYinan Xu    when(canEnqueue(i)) {
4086ab6918fSYinan Xu      val enqUop = io.enq.req(i).bits
4096474c47fSYinan Xu      val enqIndex = allocatePtrVec(i).value
4109aca92b9SYinan Xu      // store uop in data module and debug_microOp Vec
4116474c47fSYinan Xu      debug_microOp(enqIndex) := enqUop
4126474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.dispatchTime := timer
4136474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.enqRsTime := timer
4146474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.selectTime := timer
4156474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.issueTime := timer
4166474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.writebackTime := timer
4178744445eSMaxpicca-Li      debug_microOp(enqIndex).debugInfo.tlbFirstReqTime := timer
4188744445eSMaxpicca-Li      debug_microOp(enqIndex).debugInfo.tlbRespTime := timer
4198744445eSMaxpicca-Li      debug_lsInfo(enqIndex) := DebugLsInfo.init
420d2b20d1aSTang Haojin      debug_lsTopdownInfo(enqIndex) := LsTopdownInfo.init
421d2b20d1aSTang Haojin      debug_lqIdxValid(enqIndex) := false.B
422d2b20d1aSTang Haojin      debug_lsIssued(enqIndex) := false.B
4233b739f49SXuan Hu      when (enqUop.waitForward) {
4243b739f49SXuan Hu        hasWaitForward := true.B
4259aca92b9SYinan Xu      }
4267e0f64b0SGuanghui Cheng      val enqTriggerActionIsDebugMode = TriggerAction.isDmode(io.enq.req(i).bits.trigger)
4273b739f49SXuan Hu      val enqHasException = ExceptionNO.selectFrontend(enqUop.exceptionVec).asUInt.orR
428af2f7849Shappy-lx      // the begin instruction of Svinval enqs so mark doingSvinval as true to indicate this process
4297e0f64b0SGuanghui Cheng      when(!enqTriggerActionIsDebugMode && !enqHasException && enqUop.isSvinvalBegin(enqUop.flushPipe)) {
430af2f7849Shappy-lx        doingSvinval := true.B
431af2f7849Shappy-lx      }
432af2f7849Shappy-lx      // the end instruction of Svinval enqs so clear doingSvinval
4337e0f64b0SGuanghui Cheng      when(!enqTriggerActionIsDebugMode && !enqHasException && enqUop.isSvinvalEnd(enqUop.flushPipe)) {
434af2f7849Shappy-lx        doingSvinval := false.B
435af2f7849Shappy-lx      }
436af2f7849Shappy-lx      // when we are in the process of Svinval software code area , only Svinval.vma and end instruction of Svinval can appear
43749fd6a7cSXuan Hu      assert(!doingSvinval || (enqUop.isSvinval(enqUop.flushPipe) || enqUop.isSvinvalEnd(enqUop.flushPipe) || enqUop.isNotSvinval))
4387e0f64b0SGuanghui Cheng      when(enqUop.isWFI && !enqHasException && !enqTriggerActionIsDebugMode) {
4395c95ea2eSYinan Xu        hasWFI := true.B
440b6900d94SYinan Xu      }
441e4f69d78Ssfencevma
442780712aaSxiaofeibao-xjtu      robEntries(enqIndex).mmio := false.B
443780712aaSxiaofeibao-xjtu      robEntries(enqIndex).vls := enqUop.vlsInstr
4449aca92b9SYinan Xu    }
4459aca92b9SYinan Xu  }
4463b601ae0SXuan Hu
4473b601ae0SXuan Hu  for (i <- 0 until RenameWidth) {
4483b601ae0SXuan Hu    val enqUop = io.enq.req(i)
4493b601ae0SXuan Hu    when(enqUop.valid && enqUop.bits.blockBackward && io.enq.canAccept) {
4503b601ae0SXuan Hu      hasBlockBackward := true.B
4513b601ae0SXuan Hu    }
4523b601ae0SXuan Hu  }
4533b601ae0SXuan Hu
454a8db15d8Sfdy  val dispatchNum = Mux(io.enq.canAccept, PopCount(io.enq.req.map(req => req.valid && req.bits.firstUop)), 0.U)
45575b25016SYinan Xu  io.enq.isEmpty := RegNext(isEmpty && !VecInit(io.enq.req.map(_.valid)).asUInt.orR)
4569aca92b9SYinan Xu
45709309bdbSYinan Xu  when(!io.wfi_enable) {
45809309bdbSYinan Xu    hasWFI := false.B
45909309bdbSYinan Xu  }
4604aa9ed34Sfdy  // sel vsetvl's flush position
4614aa9ed34Sfdy  val vs_idle :: vs_waitVinstr :: vs_waitFlush :: Nil = Enum(3)
4624aa9ed34Sfdy  val vsetvlState = RegInit(vs_idle)
4634aa9ed34Sfdy
4644aa9ed34Sfdy  val firstVInstrFtqPtr = RegInit(0.U.asTypeOf(new FtqPtr))
4654aa9ed34Sfdy  val firstVInstrFtqOffset = RegInit(0.U.asTypeOf(UInt(log2Up(PredictWidth).W)))
4664aa9ed34Sfdy  val firstVInstrRobIdx = RegInit(0.U.asTypeOf(new RobPtr))
4674aa9ed34Sfdy
4684aa9ed34Sfdy  val enq0 = io.enq.req(0)
469d91483a6Sfdy  val enq0IsVset = enq0.bits.isVset && enq0.bits.lastUop && canEnqueue(0)
4703b739f49SXuan Hu  val enq0IsVsetFlush = enq0IsVset && enq0.bits.flushPipe
471239413e5SXuan Hu  val enqIsVInstrVec = io.enq.req.zip(canEnqueue).map { case (req, fire) => FuType.isVArith(req.bits.fuType) && fire }
4724aa9ed34Sfdy  // for vs_idle
4734aa9ed34Sfdy  val firstVInstrIdle = PriorityMux(enqIsVInstrVec.zip(io.enq.req).drop(1) :+ (true.B, 0.U.asTypeOf(io.enq.req(0).cloneType)))
4744aa9ed34Sfdy  // for vs_waitVinstr
4754aa9ed34Sfdy  val enqIsVInstrOrVset = (enqIsVInstrVec(0) || enq0IsVset) +: enqIsVInstrVec.drop(1)
4764aa9ed34Sfdy  val firstVInstrWait = PriorityMux(enqIsVInstrOrVset, io.enq.req)
4774aa9ed34Sfdy  when(vsetvlState === vs_idle) {
4783b739f49SXuan Hu    firstVInstrFtqPtr := firstVInstrIdle.bits.ftqPtr
4793b739f49SXuan Hu    firstVInstrFtqOffset := firstVInstrIdle.bits.ftqOffset
4804aa9ed34Sfdy    firstVInstrRobIdx := firstVInstrIdle.bits.robIdx
4814aa9ed34Sfdy  }.elsewhen(vsetvlState === vs_waitVinstr) {
482a8db15d8Sfdy    when(Cat(enqIsVInstrOrVset).orR) {
4833b739f49SXuan Hu      firstVInstrFtqPtr := firstVInstrWait.bits.ftqPtr
4843b739f49SXuan Hu      firstVInstrFtqOffset := firstVInstrWait.bits.ftqOffset
4854aa9ed34Sfdy      firstVInstrRobIdx := firstVInstrWait.bits.robIdx
4864aa9ed34Sfdy    }
487a8db15d8Sfdy  }
4884aa9ed34Sfdy
4894aa9ed34Sfdy  val hasVInstrAfterI = Cat(enqIsVInstrVec(0)).orR
490a8db15d8Sfdy  when(vsetvlState === vs_idle && !io.redirect.valid) {
4914aa9ed34Sfdy    when(enq0IsVsetFlush) {
4924aa9ed34Sfdy      vsetvlState := Mux(hasVInstrAfterI, vs_waitFlush, vs_waitVinstr)
4934aa9ed34Sfdy    }
4944aa9ed34Sfdy  }.elsewhen(vsetvlState === vs_waitVinstr) {
4954aa9ed34Sfdy    when(io.redirect.valid) {
4964aa9ed34Sfdy      vsetvlState := vs_idle
4974aa9ed34Sfdy    }.elsewhen(Cat(enqIsVInstrOrVset).orR) {
4984aa9ed34Sfdy      vsetvlState := vs_waitFlush
4994aa9ed34Sfdy    }
5004aa9ed34Sfdy  }.elsewhen(vsetvlState === vs_waitFlush) {
5014aa9ed34Sfdy    when(io.redirect.valid) {
5024aa9ed34Sfdy      vsetvlState := vs_idle
5034aa9ed34Sfdy    }
5044aa9ed34Sfdy  }
50509309bdbSYinan Xu
506d2b20d1aSTang Haojin  // lqEnq
507d2b20d1aSTang Haojin  io.debugEnqLsq.needAlloc.map(_(0)).zip(io.debugEnqLsq.req).foreach { case (alloc, req) =>
508d2b20d1aSTang Haojin    when(io.debugEnqLsq.canAccept && alloc && req.valid) {
509d2b20d1aSTang Haojin      debug_microOp(req.bits.robIdx.value).lqIdx := req.bits.lqIdx
510d2b20d1aSTang Haojin      debug_lqIdxValid(req.bits.robIdx.value) := true.B
511d2b20d1aSTang Haojin    }
512d2b20d1aSTang Haojin  }
513d2b20d1aSTang Haojin
514d2b20d1aSTang Haojin  // lsIssue
515d2b20d1aSTang Haojin  when(io.debugHeadLsIssue) {
516d2b20d1aSTang Haojin    debug_lsIssued(deqPtr.value) := true.B
517d2b20d1aSTang Haojin  }
518d2b20d1aSTang Haojin
5199aca92b9SYinan Xu  /**
5209aca92b9SYinan Xu   * Writeback (from execution units)
5219aca92b9SYinan Xu   */
5223b739f49SXuan Hu  for (wb <- exuWBs) {
5236ab6918fSYinan Xu    when(wb.valid) {
5243b739f49SXuan Hu      val wbIdx = wb.bits.robIdx.value
525618b89e6Slewislzh      debug_exuData(wbIdx) := wb.bits.data(0)
5266ab6918fSYinan Xu      debug_exuDebug(wbIdx) := wb.bits.debug
5273b739f49SXuan Hu      debug_microOp(wbIdx).debugInfo.enqRsTime := wb.bits.debugInfo.enqRsTime
5283b739f49SXuan Hu      debug_microOp(wbIdx).debugInfo.selectTime := wb.bits.debugInfo.selectTime
5293b739f49SXuan Hu      debug_microOp(wbIdx).debugInfo.issueTime := wb.bits.debugInfo.issueTime
5303b739f49SXuan Hu      debug_microOp(wbIdx).debugInfo.writebackTime := wb.bits.debugInfo.writebackTime
5319aca92b9SYinan Xu
532b211808bShappy-lx      // debug for lqidx and sqidx
533141a6449SXuan Hu      debug_microOp(wbIdx).lqIdx := wb.bits.lqIdx.getOrElse(0.U.asTypeOf(new LqPtr))
534141a6449SXuan Hu      debug_microOp(wbIdx).sqIdx := wb.bits.sqIdx.getOrElse(0.U.asTypeOf(new SqPtr))
535b211808bShappy-lx
5369aca92b9SYinan Xu      val debug_Uop = debug_microOp(wbIdx)
5379aca92b9SYinan Xu      XSInfo(true.B,
5383b739f49SXuan Hu        p"writebacked pc 0x${Hexadecimal(debug_Uop.pc)} wen ${debug_Uop.rfWen} " +
539618b89e6Slewislzh          p"data 0x${Hexadecimal(wb.bits.data(0))} ldst ${debug_Uop.ldest} pdst ${debug_Uop.pdest} " +
540bb76fc1bSYanqin Li          p"skip ${wb.bits.debug.isSkipDiff} robIdx: ${wb.bits.robIdx}\n"
5419aca92b9SYinan Xu      )
5429aca92b9SYinan Xu    }
5439aca92b9SYinan Xu  }
5443b739f49SXuan Hu
5453b739f49SXuan Hu  val writebackNum = PopCount(exuWBs.map(_.valid))
5469aca92b9SYinan Xu  XSInfo(writebackNum =/= 0.U, "writebacked %d insts\n", writebackNum)
5479aca92b9SYinan Xu
548e4f69d78Ssfencevma  for (i <- 0 until LoadPipelineWidth) {
549e4f69d78Ssfencevma    when(RegNext(io.lsq.mmio(i))) {
550780712aaSxiaofeibao-xjtu      robEntries(RegEnable(io.lsq.uop(i).robIdx, io.lsq.mmio(i)).value).mmio := true.B
551e4f69d78Ssfencevma    }
552e4f69d78Ssfencevma  }
5539aca92b9SYinan Xu
554780712aaSxiaofeibao-xjtu
5559aca92b9SYinan Xu  /**
5569aca92b9SYinan Xu   * RedirectOut: Interrupt and Exceptions
5579aca92b9SYinan Xu   */
558ffebba96Sxiao feibao  val deqDispatchData = robEntries(deqPtr.value)
5599aca92b9SYinan Xu  val debug_deqUop = debug_microOp(deqPtr.value)
5609aca92b9SYinan Xu
561571677c9Sxiaofeibao-xjtu  val deqPtrEntry = robDeqGroup(deqPtr.value(bankAddrWidth-1,0))
562571677c9Sxiaofeibao-xjtu  val deqPtrEntryValid = deqPtrEntry.commit_v
563c1ebb150STang Haojin  val deqHasFlushed = RegInit(false.B)
5649aca92b9SYinan Xu  val intrBitSetReg = RegNext(io.csr.intrBitSet)
565c1ebb150STang Haojin  val intrEnable = intrBitSetReg && !hasWaitForward && deqPtrEntry.interrupt_safe && !deqHasFlushed
566571677c9Sxiaofeibao-xjtu  val deqNeedFlush = deqPtrEntry.needFlush && deqPtrEntry.commit_v && deqPtrEntry.commit_w
567571677c9Sxiaofeibao-xjtu  val deqHitExceptionGenState = exceptionDataRead.valid && exceptionDataRead.bits.robIdx === deqPtr
568571677c9Sxiaofeibao-xjtu  val deqNeedFlushAndHitExceptionGenState = deqNeedFlush && deqHitExceptionGenState
5697e0f64b0SGuanghui Cheng  val exceptionGenStateIsException = exceptionDataRead.bits.exceptionVec.asUInt.orR || exceptionDataRead.bits.singleStep || TriggerAction.isDmode(exceptionDataRead.bits.trigger)
570571677c9Sxiaofeibao-xjtu  val deqHasException = deqNeedFlushAndHitExceptionGenState && exceptionGenStateIsException
571c0355297SAnzooooo  val deqHasFlushPipe = deqNeedFlushAndHitExceptionGenState && exceptionDataRead.bits.flushPipe && !deqHasException && (!deqPtrEntry.isVls || RegNext(RegNext(deqPtrEntry.commit_w)))
572571677c9Sxiaofeibao-xjtu  val deqHasReplayInst = deqNeedFlushAndHitExceptionGenState && exceptionDataRead.bits.replayInst
57311bd888fSXuan Hu  val deqIsVlsException = deqHasException && deqPtrEntry.isVls && !exceptionDataRead.bits.isEnqExcp
574fd33b932Sxiaofeibao  // delay 2 cycle wait exceptionGen out
575ddb49062SXuan Hu  // vls exception can be committed only when RAB commit all its reg pairs
576ddb49062SXuan Hu  deqVlsCanCommit := RegNext(RegNext(deqIsVlsException && deqPtrEntry.commit_w)) && rab.io.status.commitEnd
577ea2894c8SXuan Hu
578ea2894c8SXuan Hu  // lock at assertion of deqVlsExceptionNeedCommit until condition not assert
579ea2894c8SXuan Hu  val deqVlsExcpLock = RegInit(false.B)
58075dea01aSXuan Hu  val handleVlsExcp = deqIsVlsException && deqVlsCanCommit && !deqVlsExcpLock && state === s_idle
58175dea01aSXuan Hu  when(handleVlsExcp) {
582ea2894c8SXuan Hu    deqVlsExcpLock := true.B
583ea2894c8SXuan Hu  }.elsewhen(deqPtrVec.head =/= deqPtrVec_next.head) {
584ea2894c8SXuan Hu    deqVlsExcpLock := false.B
585ea2894c8SXuan Hu  }
586ea2894c8SXuan Hu
587ea2894c8SXuan Hu  // Only assert once when deqVlsExcp occurs until condition not assert to avoid multi message passed to RAB
588ea2894c8SXuan Hu  when (deqVlsExceptionNeedCommit) {
589ea2894c8SXuan Hu    deqVlsExceptionNeedCommit := false.B
59075dea01aSXuan Hu  }.elsewhen(handleVlsExcp){
591fd33b932Sxiaofeibao    deqVlsExceptionCommitSize := deqPtrEntry.realDestSize
592fd33b932Sxiaofeibao    deqVlsExceptionNeedCommit := true.B
593fd33b932Sxiaofeibao  }
59472951335SLi Qianruo
59584e47f35SLi Qianruo  XSDebug(deqHasException && exceptionDataRead.bits.singleStep, "Debug Mode: Deq has singlestep exception\n")
5967e0f64b0SGuanghui Cheng  XSDebug(deqHasException && TriggerAction.isDmode(exceptionDataRead.bits.trigger), "Debug Mode: Deq has trigger entry debug Mode\n")
59784e47f35SLi Qianruo
598571677c9Sxiaofeibao-xjtu  val isFlushPipe = deqPtrEntry.commit_w && (deqHasFlushPipe || deqHasReplayInst)
5999aca92b9SYinan Xu
600571677c9Sxiaofeibao-xjtu  val isVsetFlushPipe = deqPtrEntry.commit_w && deqHasFlushPipe && exceptionDataRead.bits.isVset
601a8db15d8Sfdy  //  val needModifyFtqIdxOffset = isVsetFlushPipe && (vsetvlState === vs_waitFlush)
602a8db15d8Sfdy  val needModifyFtqIdxOffset = false.B
603a8db15d8Sfdy  io.isVsetFlushPipe := isVsetFlushPipe
604f4b2089aSYinan Xu  // io.flushOut will trigger redirect at the next cycle.
605f4b2089aSYinan Xu  // Block any redirect or commit at the next cycle.
606f4b2089aSYinan Xu  val lastCycleFlush = RegNext(io.flushOut.valid)
607f4b2089aSYinan Xu
608fd33b932Sxiaofeibao  io.flushOut.valid := (state === s_idle) && deqPtrEntryValid && (intrEnable || deqHasException && (!deqIsVlsException || deqVlsCanCommit) || isFlushPipe) && !lastCycleFlush
609f4b2089aSYinan Xu  io.flushOut.bits := DontCare
61014a67055Ssfencevma  io.flushOut.bits.isRVC := deqDispatchData.isRVC
6114aa9ed34Sfdy  io.flushOut.bits.robIdx := Mux(needModifyFtqIdxOffset, firstVInstrRobIdx, deqPtr)
6124aa9ed34Sfdy  io.flushOut.bits.ftqIdx := Mux(needModifyFtqIdxOffset, firstVInstrFtqPtr, deqDispatchData.ftqIdx)
6134aa9ed34Sfdy  io.flushOut.bits.ftqOffset := Mux(needModifyFtqIdxOffset, firstVInstrFtqOffset, deqDispatchData.ftqOffset)
614571677c9Sxiaofeibao-xjtu  io.flushOut.bits.level := Mux(deqHasReplayInst || intrEnable || deqHasException || needModifyFtqIdxOffset, RedirectLevel.flush, RedirectLevel.flushAfter) // TODO use this to implement "exception next"
615f4b2089aSYinan Xu  io.flushOut.bits.interrupt := true.B
6169aca92b9SYinan Xu  XSPerfAccumulate("interrupt_num", io.flushOut.valid && intrEnable)
617571677c9Sxiaofeibao-xjtu  XSPerfAccumulate("exception_num", io.flushOut.valid && deqHasException)
6189aca92b9SYinan Xu  XSPerfAccumulate("flush_pipe_num", io.flushOut.valid && isFlushPipe)
6199aca92b9SYinan Xu  XSPerfAccumulate("replay_inst_num", io.flushOut.valid && isFlushPipe && deqHasReplayInst)
6209aca92b9SYinan Xu
621c0355297SAnzooooo  val exceptionHappen = (state === s_idle) && deqPtrEntryValid && (intrEnable || deqHasException && (!deqIsVlsException || deqVlsCanCommit)) && !lastCycleFlush
6229aca92b9SYinan Xu  io.exception.valid := RegNext(exceptionHappen)
6233b739f49SXuan Hu  io.exception.bits.pc := RegEnable(debug_deqUop.pc, exceptionHappen)
624ad415ae0SXiaokun-Pei  io.exception.bits.gpaddr := io.readGPAMemData.gpaddr
625ad415ae0SXiaokun-Pei  io.exception.bits.isForVSnonLeafPTE := io.readGPAMemData.isForVSnonLeafPTE
6263b739f49SXuan Hu  io.exception.bits.instr := RegEnable(debug_deqUop.instr, exceptionHappen)
6273b739f49SXuan Hu  io.exception.bits.commitType := RegEnable(deqDispatchData.commitType, exceptionHappen)
6283b739f49SXuan Hu  io.exception.bits.exceptionVec := RegEnable(exceptionDataRead.bits.exceptionVec, exceptionHappen)
62925742929SXuan Hu  // fetch trigger fire or execute ebreak
63025742929SXuan Hu  io.exception.bits.isPcBkpt := RegEnable(
63125742929SXuan Hu    exceptionDataRead.bits.exceptionVec(ExceptionNO.EX_BP) && (
63225742929SXuan Hu      exceptionDataRead.bits.isEnqExcp ||
63325742929SXuan Hu      exceptionDataRead.bits.trigger === TriggerAction.None
63425742929SXuan Hu    ),
635fe52823cSXuan Hu    exceptionHappen,
636fe52823cSXuan Hu  )
637a1d46413STang Haojin  io.exception.bits.isFetchMalAddr := RegEnable(exceptionDataRead.bits.isFetchMalAddr && deqHasException, exceptionHappen)
6383b739f49SXuan Hu  io.exception.bits.singleStep := RegEnable(exceptionDataRead.bits.singleStep, exceptionHappen)
6393b739f49SXuan Hu  io.exception.bits.crossPageIPFFix := RegEnable(exceptionDataRead.bits.crossPageIPFFix, exceptionHappen)
6409aca92b9SYinan Xu  io.exception.bits.isInterrupt := RegEnable(intrEnable, exceptionHappen)
641e25e4d90SXuan Hu  io.exception.bits.isHls := RegEnable(deqDispatchData.isHls, exceptionHappen)
642780712aaSxiaofeibao-xjtu  io.exception.bits.vls := RegEnable(robEntries(deqPtr.value).vls, exceptionHappen)
643f7af4c74Schengguanghui  io.exception.bits.trigger := RegEnable(exceptionDataRead.bits.trigger, exceptionHappen)
6449aca92b9SYinan Xu
6456f483f86SXuan Hu  // data will be one cycle after valid
6466f483f86SXuan Hu  io.readGPAMemAddr.valid := exceptionHappen
6476f483f86SXuan Hu  io.readGPAMemAddr.bits.ftqPtr := exceptionDataRead.bits.ftqPtr
6486f483f86SXuan Hu  io.readGPAMemAddr.bits.ftqOffset := exceptionDataRead.bits.ftqOffset
6496f483f86SXuan Hu
6509aca92b9SYinan Xu  XSDebug(io.flushOut.valid,
6513b739f49SXuan Hu    p"generate redirect: pc 0x${Hexadecimal(io.exception.bits.pc)} intr $intrEnable " +
652571677c9Sxiaofeibao-xjtu      p"excp $deqHasException flushPipe $isFlushPipe " +
653c1b28b66STang Haojin      p"Trap_target 0x${Hexadecimal(io.csr.trapTarget.pc)} exceptionVec ${Binary(exceptionDataRead.bits.exceptionVec.asUInt)}\n")
6549aca92b9SYinan Xu
6559aca92b9SYinan Xu
6569aca92b9SYinan Xu  /**
6579aca92b9SYinan Xu   * Commits (and walk)
6589aca92b9SYinan Xu   * They share the same width.
6599aca92b9SYinan Xu   */
660780712aaSxiaofeibao-xjtu  // T redirect.valid, T+1 use walkPtrVec read robEntries, T+2 start walk, shouldWalkVec used in T+2
661780712aaSxiaofeibao-xjtu  val shouldWalkVec = Wire(Vec(CommitWidth,Bool()))
662780712aaSxiaofeibao-xjtu  val walkingPtrVec = RegNext(walkPtrVec)
663780712aaSxiaofeibao-xjtu  when(io.redirect.valid){
664780712aaSxiaofeibao-xjtu    shouldWalkVec := 0.U.asTypeOf(shouldWalkVec)
665780712aaSxiaofeibao-xjtu  }.elsewhen(RegNext(io.redirect.valid)){
666780712aaSxiaofeibao-xjtu    shouldWalkVec := 0.U.asTypeOf(shouldWalkVec)
667780712aaSxiaofeibao-xjtu  }.elsewhen(state === s_walk){
668780712aaSxiaofeibao-xjtu    shouldWalkVec := VecInit(walkingPtrVec.map(_ <= lastWalkPtr).zip(donotNeedWalk).map(x => x._1 && !x._2))
669780712aaSxiaofeibao-xjtu  }.otherwise(
670780712aaSxiaofeibao-xjtu    shouldWalkVec := 0.U.asTypeOf(shouldWalkVec)
671780712aaSxiaofeibao-xjtu  )
672c0f8424bSzhanglyGit  val walkFinished = walkPtrTrue > lastWalkPtr
67365f65924SXuan Hu  rab.io.fromRob.walkEnd := state === s_walk && walkFinished
6744c7680e0SXuan Hu  vtypeBuffer.io.fromRob.walkEnd := state === s_walk && walkFinished
6759aca92b9SYinan Xu
6769aca92b9SYinan Xu  require(RenameWidth <= CommitWidth)
6779aca92b9SYinan Xu
6789aca92b9SYinan Xu  // wiring to csr
679f1ba628bSHaojin Tang  val (wflags, dirtyFs) = (0 until CommitWidth).map(i => {
6806474c47fSYinan Xu    val v = io.commits.commitValid(i)
6819aca92b9SYinan Xu    val info = io.commits.info(i)
682780712aaSxiaofeibao-xjtu    (v & info.wflags, v & info.dirtyFs)
6839aca92b9SYinan Xu  }).unzip
6849aca92b9SYinan Xu  val fflags = Wire(Valid(UInt(5.W)))
6856474c47fSYinan Xu  fflags.valid := io.commits.isCommit && VecInit(wflags).asUInt.orR
6869aca92b9SYinan Xu  fflags.bits := wflags.zip(fflagsDataRead).map({
6879aca92b9SYinan Xu    case (w, f) => Mux(w, f, 0.U)
6889aca92b9SYinan Xu  }).reduce(_ | _)
6893af3539fSZiyue Zhang  val dirtyVs = (0 until CommitWidth).map(i => {
6903af3539fSZiyue Zhang    val v = io.commits.commitValid(i)
6913af3539fSZiyue Zhang    val info = io.commits.info(i)
6923af3539fSZiyue Zhang    v & info.dirtyVs
6933af3539fSZiyue Zhang  })
694f1ba628bSHaojin Tang  val dirty_fs = io.commits.isCommit && VecInit(dirtyFs).asUInt.orR
6953af3539fSZiyue Zhang  val dirty_vs = io.commits.isCommit && VecInit(dirtyVs).asUInt.orR
6969aca92b9SYinan Xu
6975110577fSZiyue Zhang  val resetVstart = dirty_vs && !io.vstartIsZero
6985110577fSZiyue Zhang
6997876e679STang Haojin  vecExcpInfo.valid := exceptionHappen && !intrEnable && exceptionDataRead.bits.vstartEn && exceptionDataRead.bits.isVecLoad && !exceptionDataRead.bits.isEnqExcp
700e43bb916SXuan Hu  when (exceptionHappen) {
701e43bb916SXuan Hu    vecExcpInfo.bits.nf := exceptionDataRead.bits.nf
702e43bb916SXuan Hu    vecExcpInfo.bits.vsew := exceptionDataRead.bits.vsew
703e43bb916SXuan Hu    vecExcpInfo.bits.veew := exceptionDataRead.bits.veew
704e43bb916SXuan Hu    vecExcpInfo.bits.vlmul := exceptionDataRead.bits.vlmul
705e43bb916SXuan Hu    vecExcpInfo.bits.isStride := exceptionDataRead.bits.isStrided
706e43bb916SXuan Hu    vecExcpInfo.bits.isIndexed := exceptionDataRead.bits.isIndexed
707e43bb916SXuan Hu    vecExcpInfo.bits.isWhole := exceptionDataRead.bits.isWhole
708e43bb916SXuan Hu    vecExcpInfo.bits.isVlm := exceptionDataRead.bits.isVlm
709e43bb916SXuan Hu    vecExcpInfo.bits.vstart := exceptionDataRead.bits.vstart
710e43bb916SXuan Hu  }
711e43bb916SXuan Hu
7120d134565SZiyue Zhang  io.csr.vstart.valid := RegNext(Mux(exceptionHappen && deqHasException, exceptionDataRead.bits.vstartEn, resetVstart))
7130d134565SZiyue Zhang  io.csr.vstart.bits := RegNext(Mux(exceptionHappen && deqHasException, exceptionDataRead.bits.vstart, 0.U))
7145110577fSZiyue Zhang
715a8db15d8Sfdy  val vxsat = Wire(Valid(Bool()))
716a8db15d8Sfdy  vxsat.valid := io.commits.isCommit && vxsat.bits
717a8db15d8Sfdy  vxsat.bits := io.commits.commitValid.zip(vxsatDataRead).map {
718a8db15d8Sfdy    case (valid, vxsat) => valid & vxsat
719a8db15d8Sfdy  }.reduce(_ | _)
720a8db15d8Sfdy
7219aca92b9SYinan Xu  // when mispredict branches writeback, stop commit in the next 2 cycles
7229aca92b9SYinan Xu  // TODO: don't check all exu write back
7233b739f49SXuan Hu  val misPredWb = Cat(VecInit(redirectWBs.map(wb =>
7242f2ee3b1SXuan Hu    wb.bits.redirect.get.bits.cfiUpdate.isMisPred && wb.bits.redirect.get.valid && wb.valid
72583ba63b3SXuan Hu  ).toSeq)).orR
7269aca92b9SYinan Xu  val misPredBlockCounter = Reg(UInt(3.W))
7279aca92b9SYinan Xu  misPredBlockCounter := Mux(misPredWb,
7289aca92b9SYinan Xu    "b111".U,
7299aca92b9SYinan Xu    misPredBlockCounter >> 1.U
7309aca92b9SYinan Xu  )
7319aca92b9SYinan Xu  val misPredBlock = misPredBlockCounter(0)
732571677c9Sxiaofeibao-xjtu  val deqFlushBlockCounter = Reg(UInt(3.W))
733571677c9Sxiaofeibao-xjtu  val deqFlushBlock = deqFlushBlockCounter(0)
7347c24a7e1Sxiaofeibao  val deqHasCommitted = io.commits.isCommit && io.commits.commitValid(0)
73535477a7aSAnzo  // TODO *** WARNING ***
73635477a7aSAnzo  // Blocking commit. Don't change this before we fully understand the logic.
73735477a7aSAnzo  val deqHitRedirectReg = RegNext(io.redirect.valid && io.redirect.bits.robIdx === deqPtr) || RegNext(RegNext(io.redirect.valid && io.redirect.bits.robIdx === deqPtr))
738a751b11aSchengguanghui  val criticalErrorState = io.csr.criticalErrorState
739571677c9Sxiaofeibao-xjtu  when(deqNeedFlush && deqHitRedirectReg){
740571677c9Sxiaofeibao-xjtu    deqFlushBlockCounter := "b111".U
741571677c9Sxiaofeibao-xjtu  }.otherwise{
742571677c9Sxiaofeibao-xjtu    deqFlushBlockCounter := deqFlushBlockCounter >> 1.U
743571677c9Sxiaofeibao-xjtu  }
7447c24a7e1Sxiaofeibao  when(deqHasCommitted){
745571677c9Sxiaofeibao-xjtu    deqHasFlushed := false.B
7468b9535b8STang Haojin  }.elsewhen(deqNeedFlush && io.flushOut.valid && !io.flushOut.bits.flushItself()){
7477c24a7e1Sxiaofeibao    deqHasFlushed := true.B
748571677c9Sxiaofeibao-xjtu  }
7494907ec88Schengguanghui  val traceBlock = io.trace.blockCommit
75085a8d7caSZehao Liu  val blockCommit = misPredBlock || lastCycleFlush || hasWFI || io.redirect.valid ||
7514907ec88Schengguanghui    (deqNeedFlush && !deqHasFlushed) || deqFlushBlock || criticalErrorState || traceBlock
7529aca92b9SYinan Xu
753ccfddc82SHaojin Tang  io.commits.isWalk := state === s_walk
7546474c47fSYinan Xu  io.commits.isCommit := state === s_idle && !blockCommit
755780712aaSxiaofeibao-xjtu
756780712aaSxiaofeibao-xjtu  val walk_v = VecInit(walkingPtrVec.map(ptr => robEntries(ptr.value).valid))
757780712aaSxiaofeibao-xjtu  val commit_vDeqGroup = VecInit(robDeqGroup.map(_.commit_v))
758780712aaSxiaofeibao-xjtu  val commit_wDeqGroup = VecInit(robDeqGroup.map(_.commit_w))
759780712aaSxiaofeibao-xjtu  val realCommitLast = deqPtrVec(0).lineHeadPtr + Fill(bankAddrWidth, 1.U)
760780712aaSxiaofeibao-xjtu  val commit_block = VecInit((0 until CommitWidth).map(i => !commit_wDeqGroup(i) && !hasCommitted(i)))
761571677c9Sxiaofeibao-xjtu  val allowOnlyOneCommit = VecInit(robDeqGroup.map(x => x.commit_v && x.needFlush)).asUInt.orR || intrBitSetReg
7629aca92b9SYinan Xu  // for instructions that may block others, we don't allow them to commit
763780712aaSxiaofeibao-xjtu  io.commits.commitValid := PriorityMux(commitValidThisLine, (0 until CommitWidth).map(i => (commitValidThisLine.asUInt >> i).asUInt.asTypeOf(io.commits.commitValid)))
764571677c9Sxiaofeibao-xjtu
7659aca92b9SYinan Xu  for (i <- 0 until CommitWidth) {
7669aca92b9SYinan Xu    // defaults: state === s_idle and instructions commit
7679aca92b9SYinan Xu    // when intrBitSetReg, allow only one instruction to commit at each clock cycle
768571677c9Sxiaofeibao-xjtu    val isBlocked = intrEnable || (deqNeedFlush && !deqHasFlushed && !deqHasFlushPipe)
769780712aaSxiaofeibao-xjtu    val isBlockedByOlder = if (i != 0) commit_block.asUInt(i, 0).orR || allowOnlyOneCommit && !hasCommitted.asUInt(i - 1, 0).andR else false.B
770780712aaSxiaofeibao-xjtu    commitValidThisLine(i) := commit_vDeqGroup(i) && commit_wDeqGroup(i) && !isBlocked && !isBlockedByOlder && !hasCommitted(i)
771780712aaSxiaofeibao-xjtu    io.commits.info(i) := commitInfo(i)
772fa7f2c26STang Haojin    io.commits.robIdx(i) := deqPtrVec(i)
7739aca92b9SYinan Xu
7746474c47fSYinan Xu    io.commits.walkValid(i) := shouldWalkVec(i)
775935edac4STang Haojin    when(state === s_walk) {
7766474c47fSYinan Xu      when(io.commits.isWalk && state === s_walk && shouldWalkVec(i)) {
777ef8fa011SXuan Hu        XSError(!walk_v(i), s"The walking entry($i) should be valid\n")
7786474c47fSYinan Xu      }
7799aca92b9SYinan Xu    }
7809aca92b9SYinan Xu
7816474c47fSYinan Xu    XSInfo(io.commits.isCommit && io.commits.commitValid(i),
782c61abc0cSXuan Hu      "retired pc %x wen %d ldest %d pdest %x data %x fflags: %b vxsat: %b\n",
7833b739f49SXuan Hu      debug_microOp(deqPtrVec(i).value).pc,
7849aca92b9SYinan Xu      io.commits.info(i).rfWen,
785780712aaSxiaofeibao-xjtu      io.commits.info(i).debug_ldest.getOrElse(0.U),
786780712aaSxiaofeibao-xjtu      io.commits.info(i).debug_pdest.getOrElse(0.U),
7879aca92b9SYinan Xu      debug_exuData(deqPtrVec(i).value),
788a8db15d8Sfdy      fflagsDataRead(i),
789a8db15d8Sfdy      vxsatDataRead(i)
7909aca92b9SYinan Xu    )
7916474c47fSYinan Xu    XSInfo(state === s_walk && io.commits.walkValid(i), "walked pc %x wen %d ldst %d data %x\n",
7923b739f49SXuan Hu      debug_microOp(walkPtrVec(i).value).pc,
7939aca92b9SYinan Xu      io.commits.info(i).rfWen,
794780712aaSxiaofeibao-xjtu      io.commits.info(i).debug_ldest.getOrElse(0.U),
7959aca92b9SYinan Xu      debug_exuData(walkPtrVec(i).value)
7969aca92b9SYinan Xu    )
7979aca92b9SYinan Xu  }
7989aca92b9SYinan Xu
799a8db15d8Sfdy  // sync fflags/dirty_fs/vxsat to csr
800056ddc44SXuan Hu  io.csr.fflags   := RegNextWithEnable(fflags)
801056ddc44SXuan Hu  io.csr.dirty_fs := GatedValidRegNext(dirty_fs)
802056ddc44SXuan Hu  io.csr.dirty_vs := GatedValidRegNext(dirty_vs)
803056ddc44SXuan Hu  io.csr.vxsat    := RegNextWithEnable(vxsat)
8049aca92b9SYinan Xu
8059aca92b9SYinan Xu  // commit load/store to lsq
8066474c47fSYinan Xu  val ldCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.commitValid(i) && io.commits.info(i).commitType === CommitType.LOAD))
80786c54d62SXuan Hu  // TODO: Check if meet the require that only set scommit when commit scala store uop
80825df626eSgood-circle  val stCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.commitValid(i) && io.commits.info(i).commitType === CommitType.STORE && !robEntries(deqPtrVec(i).value).vls ))
8096474c47fSYinan Xu  io.lsq.lcommit := RegNext(Mux(io.commits.isCommit, PopCount(ldCommitVec), 0.U))
8106474c47fSYinan Xu  io.lsq.scommit := RegNext(Mux(io.commits.isCommit, PopCount(stCommitVec), 0.U))
8116474c47fSYinan Xu  // indicate a pending load or store
812c7353d05SYanqin Li  io.lsq.pendingMMIOld := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.LOAD && robEntries(deqPtr.value).valid && robEntries(deqPtr.value).mmio)
81341d8d239Shappy-lx  io.lsq.pendingld := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.LOAD && robEntries(deqPtr.value).valid)
814552da88aSXuan Hu  // TODO: Check if need deassert pendingst when it is vst
815780712aaSxiaofeibao-xjtu  io.lsq.pendingst := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.STORE && robEntries(deqPtr.value).valid)
816552da88aSXuan Hu  // TODO: Check if set correctly when vector store is at the head of ROB
81725df626eSgood-circle  io.lsq.pendingVst := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.STORE && robEntries(deqPtr.value).valid && robEntries(deqPtr.value).vls)
8186474c47fSYinan Xu  io.lsq.commit := RegNext(io.commits.isCommit && io.commits.commitValid(0))
819e4f69d78Ssfencevma  io.lsq.pendingPtr := RegNext(deqPtr)
82020a5248fSzhanglinjuan  io.lsq.pendingPtrNext := RegNext(deqPtrVec_next.head)
8219aca92b9SYinan Xu
8229aca92b9SYinan Xu  /**
8239aca92b9SYinan Xu   * state changes
824ccfddc82SHaojin Tang   * (1) redirect: switch to s_walk
825ccfddc82SHaojin Tang   * (2) walk: when walking comes to the end, switch to s_idle
8269aca92b9SYinan Xu   */
827ea2894c8SXuan Hu  state_next := Mux(
828780712aaSxiaofeibao-xjtu    io.redirect.valid || RegNext(io.redirect.valid), s_walk,
8294c7680e0SXuan Hu    Mux(
8304c7680e0SXuan Hu      state === s_walk && walkFinished && rab.io.status.walkEnd && vtypeBuffer.io.status.walkEnd, s_idle,
8314c7680e0SXuan Hu      state
8324c7680e0SXuan Hu    )
8334c7680e0SXuan Hu  )
8347e8294acSYinan Xu  XSPerfAccumulate("s_idle_to_idle", state === s_idle && state_next === s_idle)
8357e8294acSYinan Xu  XSPerfAccumulate("s_idle_to_walk", state === s_idle && state_next === s_walk)
8367e8294acSYinan Xu  XSPerfAccumulate("s_walk_to_idle", state === s_walk && state_next === s_idle)
8377e8294acSYinan Xu  XSPerfAccumulate("s_walk_to_walk", state === s_walk && state_next === s_walk)
8389aca92b9SYinan Xu  state := state_next
8399aca92b9SYinan Xu
8409aca92b9SYinan Xu  /**
8419aca92b9SYinan Xu   * pointers and counters
8429aca92b9SYinan Xu   */
843780712aaSxiaofeibao-xjtu  val deqPtrGenModule = Module(new NewRobDeqPtrWrapper)
8449aca92b9SYinan Xu  deqPtrGenModule.io.state := state
845cda1c534Sxiaofeibao-xjtu  deqPtrGenModule.io.deq_v := commit_vDeqGroup
846cda1c534Sxiaofeibao-xjtu  deqPtrGenModule.io.deq_w := commit_wDeqGroup
8479aca92b9SYinan Xu  deqPtrGenModule.io.exception_state := exceptionDataRead
8489aca92b9SYinan Xu  deqPtrGenModule.io.intrBitSetReg := intrBitSetReg
8493b739f49SXuan Hu  deqPtrGenModule.io.hasNoSpecExec := hasWaitForward
850571677c9Sxiaofeibao-xjtu  deqPtrGenModule.io.allowOnlyOneCommit := allowOnlyOneCommit
8511bd36f96Sxiao feibao  deqPtrGenModule.io.interrupt_safe := robDeqGroup(deqPtr.value(bankAddrWidth-1,0)).interrupt_safe
8526474c47fSYinan Xu  deqPtrGenModule.io.blockCommit := blockCommit
853780712aaSxiaofeibao-xjtu  deqPtrGenModule.io.hasCommitted := hasCommitted
854780712aaSxiaofeibao-xjtu  deqPtrGenModule.io.allCommitted := allCommitted
8559aca92b9SYinan Xu  deqPtrVec := deqPtrGenModule.io.out
85620a5248fSzhanglinjuan  deqPtrVec_next := deqPtrGenModule.io.next_out
8579aca92b9SYinan Xu
8589aca92b9SYinan Xu  val enqPtrGenModule = Module(new RobEnqPtrWrapper)
8599aca92b9SYinan Xu  enqPtrGenModule.io.redirect := io.redirect
860b9a37d2fSXuan Hu  enqPtrGenModule.io.allowEnqueue := allowEnqueue && rab.io.canEnq && !io.fromVecExcpMod.busy
8619aca92b9SYinan Xu  enqPtrGenModule.io.hasBlockBackward := hasBlockBackward
862a8db15d8Sfdy  enqPtrGenModule.io.enq := VecInit(io.enq.req.map(req => req.valid && req.bits.firstUop))
8636474c47fSYinan Xu  enqPtrVec := enqPtrGenModule.io.out
8649aca92b9SYinan Xu
8659aca92b9SYinan Xu  // next walkPtrVec:
8669aca92b9SYinan Xu  // (1) redirect occurs: update according to state
867ccfddc82SHaojin Tang  // (2) walk: move forwards
868780712aaSxiaofeibao-xjtu  val deqPtrReadBank = deqPtrVec_next(0).lineHeadPtr
869780712aaSxiaofeibao-xjtu  val deqPtrVecForWalk = VecInit((0 until CommitWidth).map(i => deqPtrReadBank + i.U))
870780712aaSxiaofeibao-xjtu  val snapPtrReadBank = snapshots(io.snpt.snptSelect)(0).lineHeadPtr
871780712aaSxiaofeibao-xjtu  val snapPtrVecForWalk = VecInit((0 until CommitWidth).map(i => snapPtrReadBank + i.U))
872c0f8424bSzhanglyGit  val walkPtrVec_next: Vec[RobPtr] = Mux(io.redirect.valid,
873780712aaSxiaofeibao-xjtu    Mux(io.snpt.useSnpt, snapPtrVecForWalk, deqPtrVecForWalk),
874780712aaSxiaofeibao-xjtu    Mux((state === s_walk) && !walkFinished, VecInit(walkPtrVec.map(_ + CommitWidth.U)), walkPtrVec)
8759aca92b9SYinan Xu  )
876c0f8424bSzhanglyGit  val walkPtrTrue_next: RobPtr = Mux(io.redirect.valid,
877c0f8424bSzhanglyGit    Mux(io.snpt.useSnpt, snapshots(io.snpt.snptSelect)(0), deqPtrVec_next(0)),
878c0f8424bSzhanglyGit    Mux((state === s_walk) && !walkFinished, walkPtrVec_next.head, walkPtrTrue)
879c0f8424bSzhanglyGit  )
880780712aaSxiaofeibao-xjtu  walkPtrHead := walkPtrVec_next.head
8819aca92b9SYinan Xu  walkPtrVec := walkPtrVec_next
882c0f8424bSzhanglyGit  walkPtrTrue := walkPtrTrue_next
883780712aaSxiaofeibao-xjtu  // T io.redirect.valid, T+1 walkPtrLowBits update, T+2 donotNeedWalk update
884780712aaSxiaofeibao-xjtu  val walkPtrLowBits = Reg(UInt(bankAddrWidth.W))
885780712aaSxiaofeibao-xjtu  when(io.redirect.valid){
886780712aaSxiaofeibao-xjtu    walkPtrLowBits := Mux(io.snpt.useSnpt, snapshots(io.snpt.snptSelect)(0).value(bankAddrWidth-1, 0), deqPtrVec_next(0).value(bankAddrWidth-1, 0))
887780712aaSxiaofeibao-xjtu  }
888780712aaSxiaofeibao-xjtu  when(io.redirect.valid) {
889780712aaSxiaofeibao-xjtu    donotNeedWalk := Fill(donotNeedWalk.length, true.B).asTypeOf(donotNeedWalk)
890780712aaSxiaofeibao-xjtu  }.elsewhen(RegNext(io.redirect.valid)){
891780712aaSxiaofeibao-xjtu    donotNeedWalk := (0 until CommitWidth).map(i => (i.U < walkPtrLowBits))
892c0f8424bSzhanglyGit  }.otherwise{
893780712aaSxiaofeibao-xjtu    donotNeedWalk := 0.U.asTypeOf(donotNeedWalk)
894c0f8424bSzhanglyGit  }
895cda1c534Sxiaofeibao-xjtu  walkDestSizeDeqGroup.zip(walkPtrVec_next).map {
896780712aaSxiaofeibao-xjtu    case (reg, ptrNext) => reg := robEntries(deqPtr.value).realDestSize
897cda1c534Sxiaofeibao-xjtu  }
89875b25016SYinan Xu  val numValidEntries = distanceBetween(enqPtr, deqPtr)
899a8db15d8Sfdy  val commitCnt = PopCount(io.commits.commitValid)
9009aca92b9SYinan Xu
90135b3b30bSxiaofeibao  allowEnqueue := numValidEntries + dispatchNum <= (RobSize - RenameWidth).U
90235b3b30bSxiaofeibao  allowEnqueueForDispatch := numValidEntries + dispatchNum <= (RobSize - 2 * RenameWidth).U
9039aca92b9SYinan Xu
904ccfddc82SHaojin Tang  val redirectWalkDistance = distanceBetween(io.redirect.bits.robIdx, deqPtrVec_next(0))
9059aca92b9SYinan Xu  when(io.redirect.valid) {
906dcf3a679STang Haojin    lastWalkPtr := Mux(io.redirect.bits.flushItself(), io.redirect.bits.robIdx - 1.U, io.redirect.bits.robIdx)
9079aca92b9SYinan Xu  }
9089aca92b9SYinan Xu
9099aca92b9SYinan Xu
9109aca92b9SYinan Xu  /**
9119aca92b9SYinan Xu   * States
9129aca92b9SYinan Xu   * We put all the stage bits changes here.
913780712aaSxiaofeibao-xjtu   *
9149aca92b9SYinan Xu   * All events: (1) enqueue (dispatch); (2) writeback; (3) cancel; (4) dequeue (commit);
9159aca92b9SYinan Xu   * All states: (1) valid; (2) writebacked; (3) flagBkup
9169aca92b9SYinan Xu   */
917cda1c534Sxiaofeibao-xjtu
918780712aaSxiaofeibao-xjtu  val deqPtrGroup = Wire(Vec(2 * CommitWidth, new RobPtr))
919780712aaSxiaofeibao-xjtu  deqPtrGroup.zipWithIndex.map { case (deq, i) => deq := deqPtrVec(0) + i.U }
9209aca92b9SYinan Xu  val commitReadAddr = Mux(state === s_idle, VecInit(deqPtrVec.map(_.value)), VecInit(walkPtrVec.map(_.value)))
9219aca92b9SYinan Xu
922780712aaSxiaofeibao-xjtu  val redirectValidReg = RegNext(io.redirect.valid)
923780712aaSxiaofeibao-xjtu  val redirectBegin = Reg(UInt(log2Up(RobSize).W))
924780712aaSxiaofeibao-xjtu  val redirectEnd = Reg(UInt(log2Up(RobSize).W))
925*2e4f14ffSxiaofeibao  val redirectAll = RegInit(false.B)
926ccfddc82SHaojin Tang  when(io.redirect.valid){
927780712aaSxiaofeibao-xjtu    redirectBegin := Mux(io.redirect.bits.flushItself(), io.redirect.bits.robIdx.value - 1.U, io.redirect.bits.robIdx.value)
928780712aaSxiaofeibao-xjtu    redirectEnd := enqPtr.value
929*2e4f14ffSxiaofeibao    redirectAll := io.redirect.bits.flushItself() && (io.redirect.bits.robIdx.value === enqPtr.value) && (io.redirect.bits.robIdx.flag ^ enqPtr.flag)
930ccfddc82SHaojin Tang  }
931780712aaSxiaofeibao-xjtu
932780712aaSxiaofeibao-xjtu  // update robEntries valid
933780712aaSxiaofeibao-xjtu  for (i <- 0 until RobSize) {
934780712aaSxiaofeibao-xjtu    val enqOH = VecInit(canEnqueue.zip(allocatePtrVec.map(_.value === i.U)).map(x => x._1 && x._2))
935780712aaSxiaofeibao-xjtu    val commitCond = io.commits.isCommit && io.commits.commitValid.zip(deqPtrVec.map(_.value === i.U)).map(x => x._1 && x._2).reduce(_ || _)
936780712aaSxiaofeibao-xjtu    assert(PopCount(enqOH) < 2.U, s"robEntries$i enqOH is not one hot")
937780712aaSxiaofeibao-xjtu    val needFlush = redirectValidReg && Mux(
938*2e4f14ffSxiaofeibao      (redirectEnd > redirectBegin) && !redirectAll,
939780712aaSxiaofeibao-xjtu      (i.U > redirectBegin) && (i.U < redirectEnd),
940780712aaSxiaofeibao-xjtu      (i.U > redirectBegin) || (i.U < redirectEnd)
941780712aaSxiaofeibao-xjtu    )
9426a8b2d5fSxiaofeibao-xjtu    when(commitCond) {
943780712aaSxiaofeibao-xjtu      robEntries(i).valid := false.B
944780712aaSxiaofeibao-xjtu    }.elsewhen(enqOH.asUInt.orR && !io.redirect.valid) {
945780712aaSxiaofeibao-xjtu      robEntries(i).valid := true.B
946780712aaSxiaofeibao-xjtu    }.elsewhen(needFlush){
947780712aaSxiaofeibao-xjtu      robEntries(i).valid := false.B
9489aca92b9SYinan Xu    }
9499aca92b9SYinan Xu  }
9509aca92b9SYinan Xu
9518744445eSMaxpicca-Li  // debug_inst update
952870f462dSXuan Hu  for (i <- 0 until (LduCnt + StaCnt)) {
9538744445eSMaxpicca-Li    debug_lsInfo(io.debug_ls.debugLsInfo(i).s1_robIdx).s1SignalEnable(io.debug_ls.debugLsInfo(i))
9548744445eSMaxpicca-Li    debug_lsInfo(io.debug_ls.debugLsInfo(i).s2_robIdx).s2SignalEnable(io.debug_ls.debugLsInfo(i))
9554d931b73SYanqin Li    debug_lsInfo(io.debug_ls.debugLsInfo(i).s3_robIdx).s3SignalEnable(io.debug_ls.debugLsInfo(i))
9568744445eSMaxpicca-Li  }
957870f462dSXuan Hu  for (i <- 0 until LduCnt) {
958d2b20d1aSTang Haojin    debug_lsTopdownInfo(io.lsTopdownInfo(i).s1.robIdx).s1SignalEnable(io.lsTopdownInfo(i))
959d2b20d1aSTang Haojin    debug_lsTopdownInfo(io.lsTopdownInfo(i).s2.robIdx).s2SignalEnable(io.lsTopdownInfo(i))
960d2b20d1aSTang Haojin  }
9618744445eSMaxpicca-Li
962f7af4c74Schengguanghui  // status field: writebacked
963f7af4c74Schengguanghui  // enqueue logic set 6 writebacked to false
964f7af4c74Schengguanghui
9659aca92b9SYinan Xu  // writeback logic set numWbPorts writebacked to true
966a8db15d8Sfdy
967a8db15d8Sfdy  // if the first uop of an instruction is valid , write writebackedCounter
968a8db15d8Sfdy  val uopEnqValidSeq = io.enq.req.map(req => io.enq.canAccept && req.valid)
969a8db15d8Sfdy  val instEnqValidSeq = io.enq.req.map(req => io.enq.canAccept && req.valid && req.bits.firstUop)
970a8db15d8Sfdy  val enqNeedWriteRFSeq = io.enq.req.map(_.bits.needWriteRf)
971124f6e6aSXuan Hu  val enqHasExcpSeq = io.enq.req.map(_.bits.hasException)
972a8db15d8Sfdy  val enqRobIdxSeq = io.enq.req.map(req => req.bits.robIdx.value)
973f1e8fcb2SXuan Hu  val enqUopNumVec = VecInit(io.enq.req.map(req => req.bits.numUops))
9743235a9d8SZiyue-Zhang  val enqWBNumVec = VecInit(io.enq.req.map(req => req.bits.numWB))
975a8db15d8Sfdy
976f1e8fcb2SXuan Hu  private val enqWriteStdVec: Vec[Bool] = VecInit(io.enq.req.map {
97712861ac7Slinzhida    req => FuType.isStore(req.bits.fuType)
978f1e8fcb2SXuan Hu  })
979cda1c534Sxiaofeibao-xjtu  val fflags_wb = fflagsWBs
980cda1c534Sxiaofeibao-xjtu  val vxsat_wb = vxsatWBs
981a8db15d8Sfdy  for (i <- 0 until RobSize) {
982a8db15d8Sfdy
983a8db15d8Sfdy    val robIdxMatchSeq = io.enq.req.map(_.bits.robIdx.value === i.U)
984a8db15d8Sfdy    val uopCanEnqSeq = uopEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
985a8db15d8Sfdy    val instCanEnqSeq = instEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
986a8db15d8Sfdy    val instCanEnqFlag = Cat(instCanEnqSeq).orR
987124f6e6aSXuan Hu    val hasExcpSeq = enqHasExcpSeq.lazyZip(robIdxMatchSeq).lazyZip(uopEnqValidSeq).map { case (excp, isMatch, valid) => excp && isMatch && valid }
988124f6e6aSXuan Hu    val hasExcpFlag = Cat(hasExcpSeq).orR
9898338e674Sxiaofeibao-xjtu    val isFirstEnq = !robEntries(i).valid && instCanEnqFlag
990780712aaSxiaofeibao-xjtu    val realDestEnqNum = PopCount(enqNeedWriteRFSeq.zip(uopCanEnqSeq).map { case (writeFlag, valid) => writeFlag && valid })
9918338e674Sxiaofeibao-xjtu    when(isFirstEnq){
9920a7d1d5cSxiaofeibao      robEntries(i).realDestSize := realDestEnqNum //Mux(hasExcpFlag, 0.U, realDestEnqNum)
99311a54ccaSsinsanction    }.elsewhen(robEntries(i).valid && Cat(uopCanEnqSeq).orR){
994780712aaSxiaofeibao-xjtu      robEntries(i).realDestSize := robEntries(i).realDestSize + realDestEnqNum
995780712aaSxiaofeibao-xjtu    }
996f1e8fcb2SXuan Hu    val enqUopNum = PriorityMux(instCanEnqSeq, enqUopNumVec)
9973235a9d8SZiyue-Zhang    val enqWBNum = PriorityMux(instCanEnqSeq, enqWBNumVec)
998f1e8fcb2SXuan Hu    val enqWriteStd = PriorityMux(instCanEnqSeq, enqWriteStdVec)
999a8db15d8Sfdy
1000a8db15d8Sfdy    val canWbSeq = exuWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U)
1001f1e8fcb2SXuan Hu    val canStdWbSeq = VecInit(stdWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U))
1002571677c9Sxiaofeibao-xjtu    val wbCnt = Mux1H(canWbSeq, io.writebackNums.map(_.bits))
100389cc69c1STang Haojin
1004571677c9Sxiaofeibao-xjtu    val canWbExceptionSeq = exceptionWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U)
1005571677c9Sxiaofeibao-xjtu    val needFlush = robEntries(i).needFlush
1006571677c9Sxiaofeibao-xjtu    val needFlushWriteBack = Wire(Bool())
1007571677c9Sxiaofeibao-xjtu    needFlushWriteBack := Mux1H(canWbExceptionSeq, io.writebackNeedFlush)
1008571677c9Sxiaofeibao-xjtu    when(robEntries(i).valid){
1009571677c9Sxiaofeibao-xjtu      needFlush := needFlush || needFlushWriteBack
1010571677c9Sxiaofeibao-xjtu    }
101189cc69c1STang Haojin
1012571677c9Sxiaofeibao-xjtu    when(robEntries(i).valid && (needFlush || needFlushWriteBack)) {
1013f1e8fcb2SXuan Hu      // exception flush
1014571677c9Sxiaofeibao-xjtu      robEntries(i).uopNum := robEntries(i).uopNum - wbCnt
1015780712aaSxiaofeibao-xjtu      robEntries(i).stdWritebacked := true.B
1016780712aaSxiaofeibao-xjtu    }.elsewhen(!robEntries(i).valid && instCanEnqFlag) {
1017f1e8fcb2SXuan Hu      // enq set num of uops
1018780712aaSxiaofeibao-xjtu      robEntries(i).uopNum := enqWBNum
1019780712aaSxiaofeibao-xjtu      robEntries(i).stdWritebacked := Mux(enqWriteStd, false.B, true.B)
1020780712aaSxiaofeibao-xjtu    }.elsewhen(robEntries(i).valid) {
1021f1e8fcb2SXuan Hu      // update by writing back
1022780712aaSxiaofeibao-xjtu      robEntries(i).uopNum := robEntries(i).uopNum - wbCnt
1023780712aaSxiaofeibao-xjtu      assert(!(robEntries(i).uopNum - wbCnt > robEntries(i).uopNum), s"robEntries $i uopNum is overflow!")
1024f1e8fcb2SXuan Hu      when(canStdWbSeq.asUInt.orR) {
1025780712aaSxiaofeibao-xjtu        robEntries(i).stdWritebacked := true.B
1026cda1c534Sxiaofeibao-xjtu      }
1027f1e8fcb2SXuan Hu    }
1028a8db15d8Sfdy
10293bc74e23SzhanglyGit    val fflagsCanWbSeq = fflags_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U && writeback.bits.wflags.getOrElse(false.B))
103027c566d7SXuan Hu    val fflagsRes = fflagsCanWbSeq.zip(fflags_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.fflags.get, 0.U) }.fold(false.B)(_ | _)
10318338e674Sxiaofeibao-xjtu    when(isFirstEnq) {
10328338e674Sxiaofeibao-xjtu      robEntries(i).fflags := 0.U
10338338e674Sxiaofeibao-xjtu    }.elsewhen(fflagsRes.orR) {
10348338e674Sxiaofeibao-xjtu      robEntries(i).fflags := robEntries(i).fflags | fflagsRes
10358338e674Sxiaofeibao-xjtu    }
1036a8db15d8Sfdy
1037a8db15d8Sfdy    val vxsatCanWbSeq = vxsat_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U)
103827c566d7SXuan Hu    val vxsatRes = vxsatCanWbSeq.zip(vxsat_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.vxsat.get, 0.U) }.fold(false.B)(_ | _)
10398338e674Sxiaofeibao-xjtu    when(isFirstEnq) {
10408338e674Sxiaofeibao-xjtu      robEntries(i).vxsat := 0.U
10418338e674Sxiaofeibao-xjtu    }.elsewhen(vxsatRes.orR) {
10428338e674Sxiaofeibao-xjtu      robEntries(i).vxsat := robEntries(i).vxsat | vxsatRes
10438338e674Sxiaofeibao-xjtu    }
104449162c9aSGuanghui Cheng
104549162c9aSGuanghui Cheng    // trace
104649162c9aSGuanghui Cheng    val taken = branchWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U && writeback.bits.redirect.get.bits.cfiUpdate.taken).reduce(_ || _)
10478cbf000bSchengguanghui    when(robEntries(i).valid && Itype.isBranchType(robEntries(i).traceBlockInPipe.itype) && taken){
1048725e8ddcSchengguanghui      // BranchType code(notaken itype = 4) must be correctly replaced!
1049725e8ddcSchengguanghui      robEntries(i).traceBlockInPipe.itype := Itype.Taken
105049162c9aSGuanghui Cheng    }
10519aca92b9SYinan Xu  }
1052780712aaSxiaofeibao-xjtu
1053780712aaSxiaofeibao-xjtu  // begin update robBanksRdata
1054780712aaSxiaofeibao-xjtu  val robBanksRdata = VecInit(robBanksRdataThisLine ++ robBanksRdataNextLine)
1055780712aaSxiaofeibao-xjtu  val needUpdate = Wire(Vec(2 * CommitWidth, new RobEntryBundle))
1056780712aaSxiaofeibao-xjtu  needUpdate := VecInit(robBanksRdataThisLine ++ robBanksRdataNextLine)
1057780712aaSxiaofeibao-xjtu  val needUpdateRobIdx = robIdxThisLine ++ robIdxNextLine
1058cda1c534Sxiaofeibao-xjtu  for (i <- 0 until 2 * CommitWidth) {
1059780712aaSxiaofeibao-xjtu    val robIdxMatchSeq = io.enq.req.map(_.bits.robIdx.value === needUpdateRobIdx(i))
1060cda1c534Sxiaofeibao-xjtu    val uopCanEnqSeq = uopEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
1061cda1c534Sxiaofeibao-xjtu    val instCanEnqSeq = instEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
1062cda1c534Sxiaofeibao-xjtu    val instCanEnqFlag = Cat(instCanEnqSeq).orR
1063780712aaSxiaofeibao-xjtu    val realDestEnqNum = PopCount(enqNeedWriteRFSeq.zip(uopCanEnqSeq).map { case (writeFlag, valid) => writeFlag && valid })
1064780712aaSxiaofeibao-xjtu    when(!needUpdate(i).valid && instCanEnqFlag) {
1065780712aaSxiaofeibao-xjtu      needUpdate(i).realDestSize := realDestEnqNum
1066780712aaSxiaofeibao-xjtu    }.elsewhen(needUpdate(i).valid && instCanEnqFlag) {
1067780712aaSxiaofeibao-xjtu      needUpdate(i).realDestSize := robBanksRdata(i).realDestSize + realDestEnqNum
1068cda1c534Sxiaofeibao-xjtu    }
1069780712aaSxiaofeibao-xjtu    val enqUopNum = PriorityMux(instCanEnqSeq, enqUopNumVec)
1070780712aaSxiaofeibao-xjtu    val enqWBNum = PriorityMux(instCanEnqSeq, enqWBNumVec)
1071780712aaSxiaofeibao-xjtu    val enqWriteStd = PriorityMux(instCanEnqSeq, enqWriteStdVec)
1072780712aaSxiaofeibao-xjtu
1073780712aaSxiaofeibao-xjtu    val canWbSeq = exuWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i))
1074780712aaSxiaofeibao-xjtu    val canStdWbSeq = VecInit(stdWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i)))
1075571677c9Sxiaofeibao-xjtu    val wbCnt = Mux1H(canWbSeq, io.writebackNums.map(_.bits))
1076780712aaSxiaofeibao-xjtu
1077571677c9Sxiaofeibao-xjtu    val canWbExceptionSeq = exceptionWBs.map(writeback => writeback.valid && (writeback.bits.robIdx.value === needUpdateRobIdx(i)))
1078571677c9Sxiaofeibao-xjtu    val needFlush = robBanksRdata(i).needFlush
1079571677c9Sxiaofeibao-xjtu    val needFlushWriteBack = Wire(Bool())
1080571677c9Sxiaofeibao-xjtu    needFlushWriteBack := Mux1H(canWbExceptionSeq, io.writebackNeedFlush)
1081571677c9Sxiaofeibao-xjtu    when(needUpdate(i).valid) {
1082571677c9Sxiaofeibao-xjtu      needUpdate(i).needFlush := needFlush || needFlushWriteBack
1083571677c9Sxiaofeibao-xjtu    }
1084780712aaSxiaofeibao-xjtu
1085571677c9Sxiaofeibao-xjtu    when(needUpdate(i).valid && (needFlush || needFlushWriteBack)) {
1086780712aaSxiaofeibao-xjtu      // exception flush
1087571677c9Sxiaofeibao-xjtu      needUpdate(i).uopNum := robBanksRdata(i).uopNum - wbCnt
1088780712aaSxiaofeibao-xjtu      needUpdate(i).stdWritebacked := true.B
1089780712aaSxiaofeibao-xjtu    }.elsewhen(!needUpdate(i).valid && instCanEnqFlag) {
1090780712aaSxiaofeibao-xjtu      // enq set num of uops
1091780712aaSxiaofeibao-xjtu      needUpdate(i).uopNum := enqWBNum
1092780712aaSxiaofeibao-xjtu      needUpdate(i).stdWritebacked := Mux(enqWriteStd, false.B, true.B)
1093780712aaSxiaofeibao-xjtu    }.elsewhen(needUpdate(i).valid) {
1094780712aaSxiaofeibao-xjtu      // update by writing back
1095780712aaSxiaofeibao-xjtu      needUpdate(i).uopNum := robBanksRdata(i).uopNum - wbCnt
1096780712aaSxiaofeibao-xjtu      when(canStdWbSeq.asUInt.orR) {
1097780712aaSxiaofeibao-xjtu        needUpdate(i).stdWritebacked := true.B
10989aca92b9SYinan Xu      }
10999aca92b9SYinan Xu    }
11009aca92b9SYinan Xu
1101780712aaSxiaofeibao-xjtu    val fflagsCanWbSeq = fflags_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i) && writeback.bits.wflags.getOrElse(false.B))
1102780712aaSxiaofeibao-xjtu    val fflagsRes = fflagsCanWbSeq.zip(fflags_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.fflags.get, 0.U) }.fold(false.B)(_ | _)
1103780712aaSxiaofeibao-xjtu    needUpdate(i).fflags := Mux(!robBanksRdata(i).valid && instCanEnqFlag, 0.U, robBanksRdata(i).fflags | fflagsRes)
1104780712aaSxiaofeibao-xjtu
1105780712aaSxiaofeibao-xjtu    val vxsatCanWbSeq = vxsat_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i))
1106780712aaSxiaofeibao-xjtu    val vxsatRes = vxsatCanWbSeq.zip(vxsat_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.vxsat.get, 0.U) }.fold(false.B)(_ | _)
1107780712aaSxiaofeibao-xjtu    needUpdate(i).vxsat := Mux(!robBanksRdata(i).valid && instCanEnqFlag, 0.U, robBanksRdata(i).vxsat | vxsatRes)
1108b720b0cdSchengguanghui
1109b720b0cdSchengguanghui    // trace
1110b720b0cdSchengguanghui    val taken = branchWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i) && writeback.bits.redirect.get.bits.cfiUpdate.taken).reduce(_ || _)
11118cbf000bSchengguanghui    when(robBanksRdata(i).valid && Itype.isBranchType(robBanksRdata(i).traceBlockInPipe.itype) && taken){
1112b720b0cdSchengguanghui      // BranchType code(notaken itype = 4) must be correctly replaced!
1113b720b0cdSchengguanghui      needUpdate(i).traceBlockInPipe.itype := Itype.Taken
1114b720b0cdSchengguanghui    }
1115780712aaSxiaofeibao-xjtu  }
1116780712aaSxiaofeibao-xjtu  robBanksRdataThisLineUpdate := VecInit(needUpdate.take(8))
1117780712aaSxiaofeibao-xjtu  robBanksRdataNextLineUpdate := VecInit(needUpdate.drop(8))
1118780712aaSxiaofeibao-xjtu  // end update robBanksRdata
1119780712aaSxiaofeibao-xjtu
1120e8009193SYinan Xu  // interrupt_safe
1121e8009193SYinan Xu  for (i <- 0 until RenameWidth) {
11229d3877d6SGuanghui Cheng    when(canEnqueue(i)) {
1123e8009193SYinan Xu      // For now, we allow non-load-store instructions to trigger interrupts
1124e8009193SYinan Xu      // For MMIO instructions, they should not trigger interrupts since they may
1125e8009193SYinan Xu      // be sent to lower level before it writes back.
1126e8009193SYinan Xu      // However, we cannot determine whether a load/store instruction is MMIO.
1127e8009193SYinan Xu      // Thus, we don't allow load/store instructions to trigger an interrupt.
1128e8009193SYinan Xu      // TODO: support non-MMIO load-store instructions to trigger interrupts
1129493f6e1aSAnzo      val allow_interrupts = !CommitType.isLoadStore(io.enq.req(i).bits.commitType) && !FuType.isFence(io.enq.req(i).bits.fuType) && !FuType.isCsr(io.enq.req(i).bits.fuType) && !FuType.isVset(io.enq.req(i).bits.fuType)
11309d3877d6SGuanghui Cheng      robEntries(allocatePtrVec(i).value).interrupt_safe := allow_interrupts
1131e8009193SYinan Xu    }
1132e8009193SYinan Xu  }
11339aca92b9SYinan Xu
11349aca92b9SYinan Xu  /**
11359aca92b9SYinan Xu   * read and write of data modules
11369aca92b9SYinan Xu   */
11379aca92b9SYinan Xu  val commitReadAddr_next = Mux(state_next === s_idle,
11389aca92b9SYinan Xu    VecInit(deqPtrVec_next.map(_.value)),
11399aca92b9SYinan Xu    VecInit(walkPtrVec_next.map(_.value))
11409aca92b9SYinan Xu  )
11419aca92b9SYinan Xu
11429aca92b9SYinan Xu  exceptionGen.io.redirect <> io.redirect
11439aca92b9SYinan Xu  exceptionGen.io.flush := io.flushOut.valid
1144a8db15d8Sfdy
1145a8db15d8Sfdy  val canEnqueueEG = VecInit(io.enq.req.map(req => req.valid && io.enq.canAccept))
11469aca92b9SYinan Xu  for (i <- 0 until RenameWidth) {
1147a8db15d8Sfdy    exceptionGen.io.enq(i).valid := canEnqueueEG(i)
11489aca92b9SYinan Xu    exceptionGen.io.enq(i).bits.robIdx := io.enq.req(i).bits.robIdx
11496f483f86SXuan Hu    exceptionGen.io.enq(i).bits.ftqPtr := io.enq.req(i).bits.ftqPtr
11506f483f86SXuan Hu    exceptionGen.io.enq(i).bits.ftqOffset := io.enq.req(i).bits.ftqOffset
11513b739f49SXuan Hu    exceptionGen.io.enq(i).bits.exceptionVec := ExceptionNO.selectFrontend(io.enq.req(i).bits.exceptionVec)
11523e8a0170SXuan Hu    exceptionGen.io.enq(i).bits.hasException := io.enq.req(i).bits.hasException
115311bd888fSXuan Hu    exceptionGen.io.enq(i).bits.isEnqExcp := io.enq.req(i).bits.hasException
1154c1b28b66STang Haojin    exceptionGen.io.enq(i).bits.isFetchMalAddr := io.enq.req(i).bits.isFetchMalAddr
11553b739f49SXuan Hu    exceptionGen.io.enq(i).bits.flushPipe := io.enq.req(i).bits.flushPipe
1156d91483a6Sfdy    exceptionGen.io.enq(i).bits.isVset := io.enq.req(i).bits.isVset
1157d7dd1af1SLi Qianruo    exceptionGen.io.enq(i).bits.replayInst := false.B
11583b739f49SXuan Hu    XSError(canEnqueue(i) && io.enq.req(i).bits.replayInst, "enq should not set replayInst")
11593b739f49SXuan Hu    exceptionGen.io.enq(i).bits.singleStep := io.enq.req(i).bits.singleStep
11603b739f49SXuan Hu    exceptionGen.io.enq(i).bits.crossPageIPFFix := io.enq.req(i).bits.crossPageIPFFix
11617e0f64b0SGuanghui Cheng    exceptionGen.io.enq(i).bits.trigger := io.enq.req(i).bits.trigger
1162e703da02SzhanglyGit    exceptionGen.io.enq(i).bits.vstartEn := false.B //DontCare
1163e703da02SzhanglyGit    exceptionGen.io.enq(i).bits.vstart := 0.U //DontCare
1164c0355297SAnzooooo    exceptionGen.io.enq(i).bits.vuopIdx := 0.U
1165e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isVecLoad := false.B
1166e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isVlm := false.B
1167e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isStrided := false.B
1168e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isIndexed := false.B
1169e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isWhole := false.B
1170e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.nf := 0.U
1171e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.vsew := 0.U
1172e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.veew := 0.U
1173e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.vlmul := 0.U
11749aca92b9SYinan Xu  }
11759aca92b9SYinan Xu
11766ab6918fSYinan Xu  println(s"ExceptionGen:")
11773b739f49SXuan Hu  println(s"num of exceptions: ${params.numException}")
11783b739f49SXuan Hu  require(exceptionWBs.length == exceptionGen.io.wb.length,
11793b739f49SXuan Hu    f"exceptionWBs.length: ${exceptionWBs.length}, " +
11803b739f49SXuan Hu      f"exceptionGen.io.wb.length: ${exceptionGen.io.wb.length}")
11813b739f49SXuan Hu  for (((wb, exc_wb), i) <- exceptionWBs.zip(exceptionGen.io.wb).zipWithIndex) {
11826ab6918fSYinan Xu    exc_wb.valid       := wb.valid
11833b739f49SXuan Hu    exc_wb.bits.robIdx := wb.bits.robIdx
11846f483f86SXuan Hu    // only enq inst use ftqPtr to read gpa
11856f483f86SXuan Hu    exc_wb.bits.ftqPtr          := 0.U.asTypeOf(exc_wb.bits.ftqPtr)
11866f483f86SXuan Hu    exc_wb.bits.ftqOffset       := 0.U.asTypeOf(exc_wb.bits.ftqOffset)
11873b739f49SXuan Hu    exc_wb.bits.exceptionVec    := wb.bits.exceptionVec.get
11883e8a0170SXuan Hu    exc_wb.bits.hasException    := wb.bits.exceptionVec.get.asUInt.orR // Todo: use io.writebackNeedFlush(i) instead
118911bd888fSXuan Hu    exc_wb.bits.isEnqExcp       := false.B
1190c1b28b66STang Haojin    exc_wb.bits.isFetchMalAddr  := false.B
11913b739f49SXuan Hu    exc_wb.bits.flushPipe       := wb.bits.flushPipe.getOrElse(false.B)
11924aa9ed34Sfdy    exc_wb.bits.isVset          := false.B
11933b739f49SXuan Hu    exc_wb.bits.replayInst      := wb.bits.replay.getOrElse(false.B)
11946ab6918fSYinan Xu    exc_wb.bits.singleStep      := false.B
11956ab6918fSYinan Xu    exc_wb.bits.crossPageIPFFix := false.B
1196b7dc2d1fSGuanghui Cheng    val trigger = wb.bits.trigger.getOrElse(TriggerAction.None).asTypeOf(exc_wb.bits.trigger)
11977e0f64b0SGuanghui Cheng    exc_wb.bits.trigger := trigger
1198f634b231SGuanghui Cheng    exc_wb.bits.vstartEn := (if (wb.bits.vls.nonEmpty) wb.bits.exceptionVec.get.asUInt.orR || TriggerAction.isDmode(trigger) else 0.U)
1199fd33b932Sxiaofeibao    exc_wb.bits.vstart := (if (wb.bits.vls.nonEmpty) wb.bits.vls.get.vpu.vstart else 0.U)
1200c0355297SAnzooooo    exc_wb.bits.vuopIdx := (if (wb.bits.vls.nonEmpty) wb.bits.vls.get.vpu.vuopIdx else 0.U)
1201e43bb916SXuan Hu    exc_wb.bits.isVecLoad := wb.bits.vls.map(_.isVecLoad).getOrElse(false.B)
1202e43bb916SXuan Hu    exc_wb.bits.isVlm := wb.bits.vls.map(_.isVlm).getOrElse(false.B)
1203e43bb916SXuan Hu    exc_wb.bits.isStrided := wb.bits.vls.map(_.isStrided).getOrElse(false.B) // strided need two mode tmp vreg
1204e43bb916SXuan Hu    exc_wb.bits.isIndexed := wb.bits.vls.map(_.isIndexed).getOrElse(false.B) // indexed and nf=0 need non-sequential uopidx -> vdidx
1205e43bb916SXuan Hu    exc_wb.bits.isWhole := wb.bits.vls.map(_.isWhole).getOrElse(false.B) // indexed and nf=0 need non-sequential uopidx -> vdidx
1206e43bb916SXuan Hu    exc_wb.bits.nf := wb.bits.vls.map(_.vpu.nf).getOrElse(0.U)
1207e43bb916SXuan Hu    exc_wb.bits.vsew := wb.bits.vls.map(_.vpu.vsew).getOrElse(0.U)
1208e43bb916SXuan Hu    exc_wb.bits.veew := wb.bits.vls.map(_.vpu.veew).getOrElse(0.U)
1209e43bb916SXuan Hu    exc_wb.bits.vlmul := wb.bits.vls.map(_.vpu.vlmul).getOrElse(0.U)
12109aca92b9SYinan Xu  }
12119aca92b9SYinan Xu
1212780712aaSxiaofeibao-xjtu  fflagsDataRead := (0 until CommitWidth).map(i => robEntries(deqPtrVec(i).value).fflags)
1213780712aaSxiaofeibao-xjtu  vxsatDataRead := (0 until CommitWidth).map(i => robEntries(deqPtrVec(i).value).vxsat)
1214d91483a6Sfdy
12158338e674Sxiaofeibao-xjtu  val isCommit = io.commits.isCommit
12168338e674Sxiaofeibao-xjtu  val isCommitReg = GatedValidRegNext(io.commits.isCommit)
12176474c47fSYinan Xu  val instrCntReg = RegInit(0.U(64.W))
12188338e674Sxiaofeibao-xjtu  val fuseCommitCnt = PopCount(io.commits.commitValid.zip(io.commits.info).map { case (v, i) => RegEnable(v && CommitType.isFused(i.commitType), isCommit) })
12198338e674Sxiaofeibao-xjtu  val trueCommitCnt = RegEnable(io.commits.commitValid.zip(io.commits.info).map { case (v, i) => Mux(v, i.instrSize, 0.U) }.reduce(_ +& _), isCommit) +& fuseCommitCnt
12208338e674Sxiaofeibao-xjtu  val retireCounter = Mux(isCommitReg, trueCommitCnt, 0.U)
12216474c47fSYinan Xu  val instrCnt = instrCntReg + retireCounter
12228338e674Sxiaofeibao-xjtu  when(isCommitReg){
12236474c47fSYinan Xu    instrCntReg := instrCnt
12248338e674Sxiaofeibao-xjtu  }
12256474c47fSYinan Xu  io.csr.perfinfo.retiredInstr := retireCounter
12269aca92b9SYinan Xu  io.robFull := !allowEnqueue
1227f094911bSshinezyy  io.headNotReady := commit_vDeqGroup(deqPtr.value(bankNumWidth-1, 0)) && !commit_wDeqGroup(deqPtr.value(bankNumWidth-1, 0))
12289aca92b9SYinan Xu
1229e43bb916SXuan Hu  io.toVecExcpMod.logicPhyRegMap := rab.io.toVecExcpMod.logicPhyRegMap
1230e43bb916SXuan Hu  io.toVecExcpMod.excpInfo := vecExcpInfo
1231e43bb916SXuan Hu
12329aca92b9SYinan Xu  /**
12334907ec88Schengguanghui   * trace
12344907ec88Schengguanghui   */
12354907ec88Schengguanghui
12364907ec88Schengguanghui  // trace output
12374907ec88Schengguanghui  val traceValids = io.trace.traceCommitInfo.blocks.map(_.valid)
12384907ec88Schengguanghui  val traceBlocks = io.trace.traceCommitInfo.blocks
12394907ec88Schengguanghui  val traceBlockInPipe = io.trace.traceCommitInfo.blocks.map(_.bits.tracePipe)
12404907ec88Schengguanghui
12418cbf000bSchengguanghui  // The reg 'isTraceXret' only for trace xret instructions. xret only occur in block(0).
12428cbf000bSchengguanghui  val isTraceXret = RegInit(false.B)
12438cbf000bSchengguanghui  when(io.csr.isXRet){
12448cbf000bSchengguanghui    isTraceXret := true.B
12458cbf000bSchengguanghui  }.elsewhen(isTraceXret && io.commits.isCommit && io.commits.commitValid(0)){
12468cbf000bSchengguanghui    isTraceXret := false.B
12478cbf000bSchengguanghui  }
12488cbf000bSchengguanghui
12494907ec88Schengguanghui  for (i <- 0 until CommitWidth) {
12504907ec88Schengguanghui    traceBlocks(i).bits.ftqIdx.foreach(_ := rawInfo(i).ftqIdx)
12514907ec88Schengguanghui    traceBlocks(i).bits.ftqOffset.foreach(_ := rawInfo(i).ftqOffset)
12524907ec88Schengguanghui    traceBlockInPipe(i).itype := rawInfo(i).traceBlockInPipe.itype
1253c308d936Schengguanghui    traceBlockInPipe(i).iretire := rawInfo(i).traceBlockInPipe.iretire
12544907ec88Schengguanghui    traceBlockInPipe(i).ilastsize := rawInfo(i).traceBlockInPipe.ilastsize
1255c308d936Schengguanghui    traceValids(i) := io.commits.isCommit && io.commits.commitValid(i)
12568cbf000bSchengguanghui    // exception/xret only occur in block(0).
1257c308d936Schengguanghui    if(i == 0) {
12588cbf000bSchengguanghui      when(isTraceXret && io.commits.isCommit && io.commits.commitValid(0)){ // trace xret
12598cbf000bSchengguanghui        traceBlocks(i).bits.tracePipe.itype := Itype.ExpIntReturn
12608cbf000bSchengguanghui      }.elsewhen(io.exception.valid){ // trace exception
1261c308d936Schengguanghui        traceBlocks(i).bits.tracePipe.itype := Mux(io.exception.bits.isInterrupt,
12624907ec88Schengguanghui          Itype.Interrupt,
12634907ec88Schengguanghui          Itype.Exception
12644907ec88Schengguanghui        )
1265c308d936Schengguanghui        traceValids(i) := true.B
1266c308d936Schengguanghui        traceBlockInPipe(i).iretire := 0.U
1267c308d936Schengguanghui      }
12684907ec88Schengguanghui    }
12694907ec88Schengguanghui  }
12704907ec88Schengguanghui
12714907ec88Schengguanghui  /**
12729aca92b9SYinan Xu   * debug info
12739aca92b9SYinan Xu   */
12749aca92b9SYinan Xu  XSDebug(p"enqPtr ${enqPtr} deqPtr ${deqPtr}\n")
12759aca92b9SYinan Xu  XSDebug("")
12762f2ee3b1SXuan Hu  XSError(isBefore(enqPtr, deqPtr) && !isFull(enqPtr, deqPtr), "\ndeqPtr is older than enqPtr!\n")
12779aca92b9SYinan Xu  for (i <- 0 until RobSize) {
1278780712aaSxiaofeibao-xjtu    XSDebug(false, !robEntries(i).valid, "-")
1279780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && robEntries(i).isWritebacked, "w")
1280780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && !robEntries(i).isWritebacked, "v")
12819aca92b9SYinan Xu  }
12829aca92b9SYinan Xu  XSDebug(false, true.B, "\n")
12839aca92b9SYinan Xu
12849aca92b9SYinan Xu  for (i <- 0 until RobSize) {
12859aca92b9SYinan Xu    if (i % 4 == 0) XSDebug("")
12863b739f49SXuan Hu    XSDebug(false, true.B, "%x ", debug_microOp(i).pc)
1287780712aaSxiaofeibao-xjtu    XSDebug(false, !robEntries(i).valid, "- ")
1288780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && robEntries(i).isWritebacked, "w ")
1289780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && !robEntries(i).isWritebacked, "v ")
12909aca92b9SYinan Xu    if (i % 4 == 3) XSDebug(false, true.B, "\n")
12919aca92b9SYinan Xu  }
12929aca92b9SYinan Xu
12938338e674Sxiaofeibao-xjtu  def ifCommit(counter: UInt): UInt = Mux(isCommit, counter, 0.U)
1294780712aaSxiaofeibao-xjtu
12958338e674Sxiaofeibao-xjtu  def ifCommitReg(counter: UInt): UInt = Mux(isCommitReg, counter, 0.U)
12969aca92b9SYinan Xu
12979aca92b9SYinan Xu  val commitDebugUop = deqPtrVec.map(_.value).map(debug_microOp(_))
12989aca92b9SYinan Xu  XSPerfAccumulate("clock_cycle", 1.U)
1299e986c5deSXuan Hu  QueuePerf(RobSize, numValidEntries, numValidEntries === RobSize.U)
13009aca92b9SYinan Xu  XSPerfAccumulate("commitUop", ifCommit(commitCnt))
13017e8294acSYinan Xu  XSPerfAccumulate("commitInstr", ifCommitReg(trueCommitCnt))
1302ec9e6512Swakafa  XSPerfRolling("ipc", ifCommitReg(trueCommitCnt), 1000, clock, reset)
1303839e5512SZifei Zhang  XSPerfRolling("cpi", perfCnt = 1.U /*Cycle*/ , eventTrigger = ifCommitReg(trueCommitCnt), granularity = 1000, clock, reset)
13047e8294acSYinan Xu  XSPerfAccumulate("commitInstrFused", ifCommitReg(fuseCommitCnt))
13059aca92b9SYinan Xu  val commitIsLoad = io.commits.info.map(_.commitType).map(_ === CommitType.LOAD)
13066474c47fSYinan Xu  val commitLoadValid = io.commits.commitValid.zip(commitIsLoad).map { case (v, t) => v && t }
13079aca92b9SYinan Xu  XSPerfAccumulate("commitInstrLoad", ifCommit(PopCount(commitLoadValid)))
130820edb3f7SWilliam Wang  val commitIsBranch = io.commits.info.map(_.commitType).map(_ === CommitType.BRANCH)
13096474c47fSYinan Xu  val commitBranchValid = io.commits.commitValid.zip(commitIsBranch).map { case (v, t) => v && t }
131020edb3f7SWilliam Wang  XSPerfAccumulate("commitInstrBranch", ifCommit(PopCount(commitBranchValid)))
13119aca92b9SYinan Xu  val commitIsStore = io.commits.info.map(_.commitType).map(_ === CommitType.STORE)
13126474c47fSYinan Xu  XSPerfAccumulate("commitInstrStore", ifCommit(PopCount(io.commits.commitValid.zip(commitIsStore).map { case (v, t) => v && t })))
1313780712aaSxiaofeibao-xjtu  XSPerfAccumulate("writeback", PopCount((0 until RobSize).map(i => robEntries(i).valid && robEntries(i).isWritebacked)))
1314c51eab43SYinan Xu  // XSPerfAccumulate("enqInstr", PopCount(io.dp1Req.map(_.fire)))
13159aca92b9SYinan Xu  // XSPerfAccumulate("d2rVnR", PopCount(io.dp1Req.map(p => p.valid && !p.ready)))
13166474c47fSYinan Xu  XSPerfAccumulate("walkInstr", Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U))
1317e986c5deSXuan Hu  XSPerfAccumulate("walkCycleTotal", state === s_walk)
1318e986c5deSXuan Hu  XSPerfAccumulate("waitRabWalkEnd", state === s_walk && walkFinished && !rab.io.status.walkEnd)
1319e986c5deSXuan Hu  private val walkCycle = RegInit(0.U(8.W))
1320e986c5deSXuan Hu  private val waitRabWalkCycle = RegInit(0.U(8.W))
1321e986c5deSXuan Hu  walkCycle := Mux(io.redirect.valid, 0.U, Mux(state === s_walk, walkCycle + 1.U, 0.U))
1322e986c5deSXuan Hu  waitRabWalkCycle := Mux(state === s_walk && walkFinished, 0.U, Mux(state === s_walk, walkCycle + 1.U, 0.U))
1323e986c5deSXuan Hu
1324e986c5deSXuan Hu  XSPerfHistogram("walkRobCycleHist", walkCycle, state === s_walk && walkFinished, 0, 32)
1325e986c5deSXuan Hu  XSPerfHistogram("walkRabExtraCycleHist", waitRabWalkCycle, state === s_walk && walkFinished && rab.io.status.walkEnd, 0, 32)
1326e986c5deSXuan Hu  XSPerfHistogram("walkTotalCycleHist", walkCycle, state === s_walk && state_next === s_idle, 0, 32)
1327e986c5deSXuan Hu
1328780712aaSxiaofeibao-xjtu  private val deqNotWritebacked = robEntries(deqPtr.value).valid && !robEntries(deqPtr.value).isWritebacked
1329780712aaSxiaofeibao-xjtu  private val deqStdNotWritebacked = robEntries(deqPtr.value).valid && !robEntries(deqPtr.value).stdWritebacked
1330780712aaSxiaofeibao-xjtu  private val deqUopNotWritebacked = robEntries(deqPtr.value).valid && !robEntries(deqPtr.value).isUopWritebacked
1331af4bdb08SXuan Hu  private val deqHeadInfo = debug_microOp(deqPtr.value)
13324b69927cSxiao feibao  val deqUopCommitType = debug_microOp(deqPtr.value).commitType
1333239413e5SXuan Hu
1334af4bdb08SXuan Hu  XSPerfAccumulate("waitAluCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.alu.U)
1335af4bdb08SXuan Hu  XSPerfAccumulate("waitMulCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.mul.U)
1336af4bdb08SXuan Hu  XSPerfAccumulate("waitDivCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.div.U)
1337af4bdb08SXuan Hu  XSPerfAccumulate("waitBrhCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.brh.U)
1338af4bdb08SXuan Hu  XSPerfAccumulate("waitJmpCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.jmp.U)
1339af4bdb08SXuan Hu  XSPerfAccumulate("waitCsrCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.csr.U)
1340af4bdb08SXuan Hu  XSPerfAccumulate("waitFenCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.fence.U)
1341af4bdb08SXuan Hu  XSPerfAccumulate("waitBkuCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.bku.U)
1342af4bdb08SXuan Hu  XSPerfAccumulate("waitLduCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.ldu.U)
1343af4bdb08SXuan Hu  XSPerfAccumulate("waitStuCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.stu.U)
1344af4bdb08SXuan Hu  XSPerfAccumulate("waitStaCycle", deqUopNotWritebacked && deqHeadInfo.fuType === FuType.stu.U)
1345af4bdb08SXuan Hu  XSPerfAccumulate("waitStdCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.stu.U)
1346af4bdb08SXuan Hu  XSPerfAccumulate("waitAtmCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.mou.U)
1347af4bdb08SXuan Hu
1348d280e426Slewislzh  XSPerfAccumulate("waitVfaluCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.vfalu.U)
1349d280e426Slewislzh  XSPerfAccumulate("waitVfmaCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.vfma.U)
1350d280e426Slewislzh  XSPerfAccumulate("waitVfdivCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.vfdiv.U)
1351d280e426Slewislzh
1352d280e426Slewislzh  val vfalufuop = Seq(VfaluType.vfadd, VfaluType.vfwadd, VfaluType.vfwadd_w, VfaluType.vfsub, VfaluType.vfwsub, VfaluType.vfwsub_w, VfaluType.vfmin, VfaluType.vfmax,
1353d280e426Slewislzh    VfaluType.vfmerge, VfaluType.vfmv, VfaluType.vfsgnj, VfaluType.vfsgnjn, VfaluType.vfsgnjx, VfaluType.vfeq, VfaluType.vfne, VfaluType.vflt, VfaluType.vfle, VfaluType.vfgt,
1354d280e426Slewislzh    VfaluType.vfge, VfaluType.vfclass, VfaluType.vfmv_f_s, VfaluType.vfmv_s_f, VfaluType.vfredusum, VfaluType.vfredmax, VfaluType.vfredmin, VfaluType.vfredosum, VfaluType.vfwredosum)
1355d280e426Slewislzh
1356d280e426Slewislzh  vfalufuop.zipWithIndex.map{
1357d280e426Slewislzh    case(fuoptype,i) =>  XSPerfAccumulate(s"waitVfalu_${i}Cycle", deqStdNotWritebacked && deqHeadInfo.fuOpType === fuoptype && deqHeadInfo.fuType === FuType.vfalu.U)
1358d280e426Slewislzh  }
1359d280e426Slewislzh
1360d280e426Slewislzh
1361d280e426Slewislzh
13629aca92b9SYinan Xu  XSPerfAccumulate("waitNormalCycle", deqNotWritebacked && deqUopCommitType === CommitType.NORMAL)
13639aca92b9SYinan Xu  XSPerfAccumulate("waitBranchCycle", deqNotWritebacked && deqUopCommitType === CommitType.BRANCH)
13649aca92b9SYinan Xu  XSPerfAccumulate("waitLoadCycle", deqNotWritebacked && deqUopCommitType === CommitType.LOAD)
13659aca92b9SYinan Xu  XSPerfAccumulate("waitStoreCycle", deqNotWritebacked && deqUopCommitType === CommitType.STORE)
1366780712aaSxiaofeibao-xjtu  XSPerfAccumulate("robHeadPC", io.commits.info(0).debug_pc.getOrElse(0.U))
136789cc69c1STang Haojin  XSPerfAccumulate("commitCompressCntAll", PopCount(io.commits.commitValid.zip(io.commits.info).map { case (valid, info) => io.commits.isCommit && valid && info.instrSize > 1.U }))
136889cc69c1STang Haojin  (2 to RenameWidth).foreach(i =>
136989cc69c1STang Haojin    XSPerfAccumulate(s"commitCompressCnt${i}", PopCount(io.commits.commitValid.zip(io.commits.info).map { case (valid, info) => io.commits.isCommit && valid && info.instrSize === i.U }))
137089cc69c1STang Haojin  )
137189cc69c1STang Haojin  XSPerfAccumulate("compressSize", io.commits.commitValid.zip(io.commits.info).map { case (valid, info) => Mux(io.commits.isCommit && valid && info.instrSize > 1.U, info.instrSize, 0.U) }.reduce(_ +& _))
13729aca92b9SYinan Xu  val dispatchLatency = commitDebugUop.map(uop => uop.debugInfo.dispatchTime - uop.debugInfo.renameTime)
13739aca92b9SYinan Xu  val enqRsLatency = commitDebugUop.map(uop => uop.debugInfo.enqRsTime - uop.debugInfo.dispatchTime)
13749aca92b9SYinan Xu  val selectLatency = commitDebugUop.map(uop => uop.debugInfo.selectTime - uop.debugInfo.enqRsTime)
13759aca92b9SYinan Xu  val issueLatency = commitDebugUop.map(uop => uop.debugInfo.issueTime - uop.debugInfo.selectTime)
13769aca92b9SYinan Xu  val executeLatency = commitDebugUop.map(uop => uop.debugInfo.writebackTime - uop.debugInfo.issueTime)
13779aca92b9SYinan Xu  val rsFuLatency = commitDebugUop.map(uop => uop.debugInfo.writebackTime - uop.debugInfo.enqRsTime)
13789aca92b9SYinan Xu  val commitLatency = commitDebugUop.map(uop => timer - uop.debugInfo.writebackTime)
1379780712aaSxiaofeibao-xjtu
13809aca92b9SYinan Xu  def latencySum(cond: Seq[Bool], latency: Seq[UInt]): UInt = {
13819aca92b9SYinan Xu    cond.zip(latency).map(x => Mux(x._1, x._2, 0.U)).reduce(_ +& _)
13829aca92b9SYinan Xu  }
1383780712aaSxiaofeibao-xjtu
13849aca92b9SYinan Xu  for (fuType <- FuType.functionNameMap.keys) {
13859aca92b9SYinan Xu    val fuName = FuType.functionNameMap(fuType)
13863b739f49SXuan Hu    val commitIsFuType = io.commits.commitValid.zip(commitDebugUop).map(x => x._1 && x._2.fuType === fuType.U)
1387839e5512SZifei Zhang    XSPerfRolling(s"ipc_futype_${fuName}", ifCommit(PopCount(commitIsFuType)), 1000, clock, reset)
13889aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_instr_cnt", ifCommit(PopCount(commitIsFuType)))
13899aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_dispatch", ifCommit(latencySum(commitIsFuType, dispatchLatency)))
13909aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_enq_rs", ifCommit(latencySum(commitIsFuType, enqRsLatency)))
13919aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_select", ifCommit(latencySum(commitIsFuType, selectLatency)))
13929aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_issue", ifCommit(latencySum(commitIsFuType, issueLatency)))
13939aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_execute", ifCommit(latencySum(commitIsFuType, executeLatency)))
13949aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_enq_rs_execute", ifCommit(latencySum(commitIsFuType, rsFuLatency)))
13959aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_commit", ifCommit(latencySum(commitIsFuType, commitLatency)))
13969aca92b9SYinan Xu  }
13976087ee12SXuan Hu  XSPerfAccumulate(s"redirect_use_snapshot", io.redirect.valid && io.snpt.useSnpt)
13989aca92b9SYinan Xu
139960ebee38STang Haojin  // top-down info
140060ebee38STang Haojin  io.debugTopDown.toCore.robHeadVaddr.valid := debug_lsTopdownInfo(deqPtr.value).s1.vaddr_valid
140160ebee38STang Haojin  io.debugTopDown.toCore.robHeadVaddr.bits := debug_lsTopdownInfo(deqPtr.value).s1.vaddr_bits
140260ebee38STang Haojin  io.debugTopDown.toCore.robHeadPaddr.valid := debug_lsTopdownInfo(deqPtr.value).s2.paddr_valid
140360ebee38STang Haojin  io.debugTopDown.toCore.robHeadPaddr.bits := debug_lsTopdownInfo(deqPtr.value).s2.paddr_bits
140460ebee38STang Haojin  io.debugTopDown.toDispatch.robTrueCommit := ifCommitReg(trueCommitCnt)
140560ebee38STang Haojin  io.debugTopDown.toDispatch.robHeadLsIssue := debug_lsIssue(deqPtr.value)
140660ebee38STang Haojin  io.debugTopDown.robHeadLqIdx.valid := debug_lqIdxValid(deqPtr.value)
140760ebee38STang Haojin  io.debugTopDown.robHeadLqIdx.bits := debug_microOp(deqPtr.value).lqIdx
14086ed1154eSTang Haojin
14097cf78eb2Shappy-lx  // rolling
14107cf78eb2Shappy-lx  io.debugRolling.robTrueCommit := ifCommitReg(trueCommitCnt)
14118744445eSMaxpicca-Li
14128744445eSMaxpicca-Li  /**
14138744445eSMaxpicca-Li   * DataBase info:
14148744445eSMaxpicca-Li   * log trigger is at writeback valid
14158744445eSMaxpicca-Li   * */
1416248b9a04SYanqin Li  if (!env.FPGAPlatform) {
1417248b9a04SYanqin Li    val instTableName = "InstTable" + p(XSCoreParamsKey).HartId.toString
1418248b9a04SYanqin Li    val instSiteName = "Rob" + p(XSCoreParamsKey).HartId.toString
141990d824ceSYanqin Li    val debug_instTable = ChiselDB.createTable(instTableName, new InstInfoEntry)
1420248b9a04SYanqin Li    for (wb <- exuWBs) {
1421248b9a04SYanqin Li      when(wb.valid) {
1422248b9a04SYanqin Li        val debug_instData = Wire(new InstInfoEntry)
1423248b9a04SYanqin Li        val idx = wb.bits.robIdx.value
1424248b9a04SYanqin Li        debug_instData.robIdx := idx
1425248b9a04SYanqin Li        debug_instData.dvaddr := wb.bits.debug.vaddr
1426248b9a04SYanqin Li        debug_instData.dpaddr := wb.bits.debug.paddr
1427248b9a04SYanqin Li        debug_instData.issueTime := wb.bits.debugInfo.issueTime
1428248b9a04SYanqin Li        debug_instData.writebackTime := wb.bits.debugInfo.writebackTime
1429248b9a04SYanqin Li        debug_instData.dispatchLatency := wb.bits.debugInfo.dispatchTime - wb.bits.debugInfo.renameTime
1430248b9a04SYanqin Li        debug_instData.enqRsLatency := wb.bits.debugInfo.enqRsTime - wb.bits.debugInfo.dispatchTime
1431248b9a04SYanqin Li        debug_instData.selectLatency := wb.bits.debugInfo.selectTime - wb.bits.debugInfo.enqRsTime
1432248b9a04SYanqin Li        debug_instData.issueLatency := wb.bits.debugInfo.issueTime - wb.bits.debugInfo.selectTime
1433248b9a04SYanqin Li        debug_instData.executeLatency := wb.bits.debugInfo.writebackTime - wb.bits.debugInfo.issueTime
1434248b9a04SYanqin Li        debug_instData.rsFuLatency := wb.bits.debugInfo.writebackTime - wb.bits.debugInfo.enqRsTime
1435248b9a04SYanqin Li        debug_instData.tlbLatency := wb.bits.debugInfo.tlbRespTime - wb.bits.debugInfo.tlbFirstReqTime
1436248b9a04SYanqin Li        debug_instData.exceptType := Cat(wb.bits.exceptionVec.getOrElse(ExceptionVec(false.B)))
1437248b9a04SYanqin Li        debug_instData.lsInfo := debug_lsInfo(idx)
1438248b9a04SYanqin Li        // debug_instData.globalID := wb.bits.uop.ctrl.debug_globalID
1439248b9a04SYanqin Li        // debug_instData.instType := wb.bits.uop.ctrl.fuType
1440248b9a04SYanqin Li        // debug_instData.ivaddr := wb.bits.uop.cf.pc
1441248b9a04SYanqin Li        // debug_instData.mdpInfo.ssid := wb.bits.uop.cf.ssid
1442248b9a04SYanqin Li        // debug_instData.mdpInfo.waitAllStore := wb.bits.uop.cf.loadWaitStrict && wb.bits.uop.cf.loadWaitBit
1443248b9a04SYanqin Li        debug_instTable.log(
1444248b9a04SYanqin Li          data = debug_instData,
1445248b9a04SYanqin Li          en = wb.valid,
1446248b9a04SYanqin Li          site = instSiteName,
1447248b9a04SYanqin Li          clock = clock,
1448248b9a04SYanqin Li          reset = reset
1449248b9a04SYanqin Li        )
1450248b9a04SYanqin Li      }
1451248b9a04SYanqin Li    }
1452248b9a04SYanqin Li  }
14538744445eSMaxpicca-Li
14548744445eSMaxpicca-Li
14559aca92b9SYinan Xu  //difftest signals
1456f3034303SHaoyuan Feng  val firstValidCommit = (deqPtr + PriorityMux(io.commits.commitValid, VecInit(List.tabulate(CommitWidth)(_.U(log2Up(CommitWidth).W))))).value
14579aca92b9SYinan Xu
14589aca92b9SYinan Xu  val wdata = Wire(Vec(CommitWidth, UInt(XLEN.W)))
14599aca92b9SYinan Xu  val wpc = Wire(Vec(CommitWidth, UInt(XLEN.W)))
1460cbe9a847SYinan Xu
14619aca92b9SYinan Xu  for (i <- 0 until CommitWidth) {
14629aca92b9SYinan Xu    val idx = deqPtrVec(i).value
14639aca92b9SYinan Xu    wdata(i) := debug_exuData(idx)
14643b739f49SXuan Hu    wpc(i) := SignExt(commitDebugUop(i).pc, XLEN)
14659aca92b9SYinan Xu  }
14669aca92b9SYinan Xu
14677d45a146SYinan Xu  if (env.EnableDifftest || env.AlwaysBasicDiff) {
1468cbe9a847SYinan Xu    // These are the structures used by difftest only and should be optimized after synthesis.
1469cbe9a847SYinan Xu    val dt_eliminatedMove = Mem(RobSize, Bool())
1470cbe9a847SYinan Xu    val dt_isRVC = Mem(RobSize, Bool())
1471cbe9a847SYinan Xu    val dt_exuDebug = Reg(Vec(RobSize, new DebugBundle))
1472cbe9a847SYinan Xu    for (i <- 0 until RenameWidth) {
1473cbe9a847SYinan Xu      when(canEnqueue(i)) {
14746474c47fSYinan Xu        dt_eliminatedMove(allocatePtrVec(i).value) := io.enq.req(i).bits.eliminatedMove
14753b739f49SXuan Hu        dt_isRVC(allocatePtrVec(i).value) := io.enq.req(i).bits.preDecodeInfo.isRVC
1476cbe9a847SYinan Xu      }
1477cbe9a847SYinan Xu    }
14783b739f49SXuan Hu    for (wb <- exuWBs) {
14796ab6918fSYinan Xu      when(wb.valid) {
14803b739f49SXuan Hu        val wbIdx = wb.bits.robIdx.value
14816ab6918fSYinan Xu        dt_exuDebug(wbIdx) := wb.bits.debug
1482cbe9a847SYinan Xu      }
1483cbe9a847SYinan Xu    }
1484cbe9a847SYinan Xu    // Always instantiate basic difftest modules.
1485cbe9a847SYinan Xu    for (i <- 0 until CommitWidth) {
1486f1ba628bSHaojin Tang      val uop = commitDebugUop(i)
1487cbe9a847SYinan Xu      val commitInfo = io.commits.info(i)
1488cbe9a847SYinan Xu      val ptr = deqPtrVec(i).value
1489cbe9a847SYinan Xu      val exuOut = dt_exuDebug(ptr)
1490cbe9a847SYinan Xu      val eliminatedMove = dt_eliminatedMove(ptr)
1491cbe9a847SYinan Xu      val isRVC = dt_isRVC(ptr)
1492cbe9a847SYinan Xu
1493e43bb916SXuan Hu      val difftest = DifftestModule(new DiffInstrCommit(MaxPhyRegs), delay = 3, dontCare = true)
1494bb76fc1bSYanqin Li      val dt_skip = Mux(eliminatedMove, false.B, exuOut.isSkipDiff)
14957d45a146SYinan Xu      difftest.coreid := io.hartId
14967d45a146SYinan Xu      difftest.index := i.U
14977d45a146SYinan Xu      difftest.valid := io.commits.commitValid(i) && io.commits.isCommit
1498202ef6b0SKunlin You      difftest.skip := dt_skip
14997d45a146SYinan Xu      difftest.isRVC := isRVC
1500780712aaSxiaofeibao-xjtu      difftest.rfwen := io.commits.commitValid(i) && commitInfo.rfWen && commitInfo.debug_ldest.get =/= 0.U
15014b0d80d8SXuan Hu      difftest.fpwen := io.commits.commitValid(i) && uop.fpWen
1502780712aaSxiaofeibao-xjtu      difftest.wpdest := commitInfo.debug_pdest.get
1503780712aaSxiaofeibao-xjtu      difftest.wdest := commitInfo.debug_ldest.get
15046ce10964SXuan Hu      difftest.nFused := CommitType.isFused(commitInfo.commitType).asUInt + commitInfo.instrSize - 1.U
15056ce10964SXuan Hu      when(difftest.valid) {
15066ce10964SXuan Hu        assert(CommitType.isFused(commitInfo.commitType).asUInt + commitInfo.instrSize >= 1.U)
15076ce10964SXuan Hu      }
15087d45a146SYinan Xu      if (env.EnableDifftest) {
15097d45a146SYinan Xu        val uop = commitDebugUop(i)
151083ba63b3SXuan Hu        difftest.pc := SignExt(uop.pc, XLEN)
151183ba63b3SXuan Hu        difftest.instr := uop.instr
15127d45a146SYinan Xu        difftest.robIdx := ZeroExt(ptr, 10)
15137d45a146SYinan Xu        difftest.lqIdx := ZeroExt(uop.lqIdx.value, 7)
15147d45a146SYinan Xu        difftest.sqIdx := ZeroExt(uop.sqIdx.value, 7)
15157d45a146SYinan Xu        difftest.isLoad := io.commits.info(i).commitType === CommitType.LOAD
15167d45a146SYinan Xu        difftest.isStore := io.commits.info(i).commitType === CommitType.STORE
1517202ef6b0SKunlin You        // Check LoadEvent only when isAmo or isLoad and skip MMIO
1518202ef6b0SKunlin You        val difftestLoadEvent = DifftestModule(new DiffLoadEvent, delay = 3)
1519202ef6b0SKunlin You        difftestLoadEvent.coreid := io.hartId
1520202ef6b0SKunlin You        difftestLoadEvent.index := i.U
1521202ef6b0SKunlin You        val loadCheck = (FuType.isAMO(uop.fuType) || FuType.isLoad(uop.fuType)) && !dt_skip
1522202ef6b0SKunlin You        difftestLoadEvent.valid    := io.commits.commitValid(i) && io.commits.isCommit && loadCheck
1523202ef6b0SKunlin You        difftestLoadEvent.paddr    := exuOut.paddr
1524202ef6b0SKunlin You        difftestLoadEvent.opType   := uop.fuOpType
1525202ef6b0SKunlin You        difftestLoadEvent.isAtomic := FuType.isAMO(uop.fuType)
1526202ef6b0SKunlin You        difftestLoadEvent.isLoad   := FuType.isLoad(uop.fuType)
15277d45a146SYinan Xu      }
1528cbe9a847SYinan Xu    }
1529cbe9a847SYinan Xu  }
15309aca92b9SYinan Xu
15317d45a146SYinan Xu  if (env.EnableDifftest || env.AlwaysBasicDiff) {
1532cbe9a847SYinan Xu    val dt_isXSTrap = Mem(RobSize, Bool())
1533cbe9a847SYinan Xu    for (i <- 0 until RenameWidth) {
1534cbe9a847SYinan Xu      when(canEnqueue(i)) {
15353b739f49SXuan Hu        dt_isXSTrap(allocatePtrVec(i).value) := io.enq.req(i).bits.isXSTrap
1536cbe9a847SYinan Xu      }
1537cbe9a847SYinan Xu    }
15387d45a146SYinan Xu    val trapVec = io.commits.commitValid.zip(deqPtrVec).map { case (v, d) =>
15397d45a146SYinan Xu      io.commits.isCommit && v && dt_isXSTrap(d.value)
15407d45a146SYinan Xu    }
1541cbe9a847SYinan Xu    val hitTrap = trapVec.reduce(_ || _)
15427d45a146SYinan Xu    val difftest = DifftestModule(new DiffTrapEvent, dontCare = true)
15437d45a146SYinan Xu    difftest.coreid := io.hartId
15447d45a146SYinan Xu    difftest.hasTrap := hitTrap
15457d45a146SYinan Xu    difftest.cycleCnt := timer
15467d45a146SYinan Xu    difftest.instrCnt := instrCnt
15477d45a146SYinan Xu    difftest.hasWFI := hasWFI
15487d45a146SYinan Xu
15497d45a146SYinan Xu    if (env.EnableDifftest) {
1550cbe9a847SYinan Xu      val trapCode = PriorityMux(wdata.zip(trapVec).map(x => x._2 -> x._1))
1551cbe9a847SYinan Xu      val trapPC = SignExt(PriorityMux(wpc.zip(trapVec).map(x => x._2 -> x._1)), XLEN)
15527d45a146SYinan Xu      difftest.code := trapCode
15537d45a146SYinan Xu      difftest.pc := trapPC
15549aca92b9SYinan Xu    }
1555cbe9a847SYinan Xu  }
15561545277aSYinan Xu
15571bf9a598SAnzo  //store evetn difftest information
15581bf9a598SAnzo  io.storeDebugInfo := DontCare
15591bf9a598SAnzo  if (env.EnableDifftest) {
15601bf9a598SAnzo    io.storeDebugInfo.map{port =>
15611bf9a598SAnzo      port.pc := debug_microOp(port.robidx.value).pc
15621bf9a598SAnzo    }
15631bf9a598SAnzo  }
15641bf9a598SAnzo
156543bdc4d9SYinan Xu  val commitLoadVec = VecInit(commitLoadValid)
156643bdc4d9SYinan Xu  val commitBranchVec = VecInit(commitBranchValid)
156743bdc4d9SYinan Xu  val commitStoreVec = VecInit(io.commits.commitValid.zip(commitIsStore).map { case (v, t) => v && t })
1568cd365d4cSrvcoresjw  val perfEvents = Seq(
1569cd365d4cSrvcoresjw    ("rob_interrupt_num      ", io.flushOut.valid && intrEnable),
1570571677c9Sxiaofeibao-xjtu    ("rob_exception_num      ", io.flushOut.valid && deqHasException),
1571cd365d4cSrvcoresjw    ("rob_flush_pipe_num     ", io.flushOut.valid && isFlushPipe),
1572cd365d4cSrvcoresjw    ("rob_replay_inst_num    ", io.flushOut.valid && isFlushPipe && deqHasReplayInst),
1573cd365d4cSrvcoresjw    ("rob_commitUop          ", ifCommit(commitCnt)),
15747e8294acSYinan Xu    ("rob_commitInstr        ", ifCommitReg(trueCommitCnt)),
15757e8294acSYinan Xu    ("rob_commitInstrFused   ", ifCommitReg(fuseCommitCnt)),
15768338e674Sxiaofeibao-xjtu    ("rob_commitInstrLoad    ", ifCommitReg(PopCount(RegEnable(commitLoadVec, isCommit)))),
15778338e674Sxiaofeibao-xjtu    ("rob_commitInstrBranch  ", ifCommitReg(PopCount(RegEnable(commitBranchVec, isCommit)))),
15788338e674Sxiaofeibao-xjtu    ("rob_commitInstrStore   ", ifCommitReg(PopCount(RegEnable(commitStoreVec, isCommit)))),
15796474c47fSYinan Xu    ("rob_walkInstr          ", Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U)),
1580ccfddc82SHaojin Tang    ("rob_walkCycle          ", (state === s_walk)),
15818338e674Sxiaofeibao-xjtu    ("rob_1_4_valid          ", numValidEntries <= (RobSize / 4).U),
15828338e674Sxiaofeibao-xjtu    ("rob_2_4_valid          ", numValidEntries > (RobSize / 4).U && numValidEntries <= (RobSize / 2).U),
15838338e674Sxiaofeibao-xjtu    ("rob_3_4_valid          ", numValidEntries > (RobSize / 2).U && numValidEntries <= (RobSize * 3 / 4).U),
15848338e674Sxiaofeibao-xjtu    ("rob_4_4_valid          ", numValidEntries > (RobSize * 3 / 4).U),
1585cd365d4cSrvcoresjw  )
15861ca0e4f3SYinan Xu  generatePerfEvent()
1587780712aaSxiaofeibao-xjtu
158885a8d7caSZehao Liu  // max commit-stuck cycle
158985a8d7caSZehao Liu  val deqismmio = Mux(robEntries(deqPtr.value).valid, robEntries(deqPtr.value).mmio, false.B)
159085a8d7caSZehao Liu  val commitStuck = (!io.commits.commitValid.reduce(_ || _) || !io.commits.isCommit) && !deqismmio
159185a8d7caSZehao Liu  val commitStuckCycle = RegInit(0.U(log2Up(maxCommitStuck).W))
159285a8d7caSZehao Liu  when(commitStuck) {
159385a8d7caSZehao Liu    commitStuckCycle := commitStuckCycle + 1.U
159485a8d7caSZehao Liu  }.elsewhen(!commitStuck && RegNext(commitStuck)) {
159585a8d7caSZehao Liu    commitStuckCycle := 0.U
159685a8d7caSZehao Liu  }
159785a8d7caSZehao Liu  // check if stuck > 2^maxCommitStuckCycle
159885a8d7caSZehao Liu  val commitStuck_overflow = commitStuckCycle.andR
159985a8d7caSZehao Liu  val criticalErrors = Seq(
160085a8d7caSZehao Liu    ("rob_commit_stuck  ", commitStuck_overflow),
160185a8d7caSZehao Liu  )
160285a8d7caSZehao Liu  generateCriticalErrors()
160385a8d7caSZehao Liu
160485a8d7caSZehao Liu
1605780712aaSxiaofeibao-xjtu  // dontTouch for debug
1606780712aaSxiaofeibao-xjtu  if (backendParams.debugEn) {
1607780712aaSxiaofeibao-xjtu    dontTouch(enqPtrVec)
1608780712aaSxiaofeibao-xjtu    dontTouch(deqPtrVec)
1609780712aaSxiaofeibao-xjtu    dontTouch(robEntries)
1610780712aaSxiaofeibao-xjtu    dontTouch(robDeqGroup)
1611780712aaSxiaofeibao-xjtu    dontTouch(robBanks)
1612780712aaSxiaofeibao-xjtu    dontTouch(robBanksRaddrThisLine)
1613780712aaSxiaofeibao-xjtu    dontTouch(robBanksRaddrNextLine)
1614780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataThisLine)
1615780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataNextLine)
1616780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataThisLineUpdate)
1617780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataNextLineUpdate)
1618571677c9Sxiaofeibao-xjtu    dontTouch(needUpdate)
1619571677c9Sxiaofeibao-xjtu    val exceptionWBsVec = MixedVecInit(exceptionWBs)
1620571677c9Sxiaofeibao-xjtu    dontTouch(exceptionWBsVec)
1621780712aaSxiaofeibao-xjtu    dontTouch(commit_wDeqGroup)
1622780712aaSxiaofeibao-xjtu    dontTouch(commit_vDeqGroup)
1623780712aaSxiaofeibao-xjtu    dontTouch(commitSizeSumSeq)
1624780712aaSxiaofeibao-xjtu    dontTouch(walkSizeSumSeq)
1625780712aaSxiaofeibao-xjtu    dontTouch(commitSizeSumCond)
1626780712aaSxiaofeibao-xjtu    dontTouch(walkSizeSumCond)
1627780712aaSxiaofeibao-xjtu    dontTouch(commitSizeSum)
1628780712aaSxiaofeibao-xjtu    dontTouch(walkSizeSum)
1629780712aaSxiaofeibao-xjtu    dontTouch(realDestSizeSeq)
1630780712aaSxiaofeibao-xjtu    dontTouch(walkDestSizeSeq)
1631780712aaSxiaofeibao-xjtu    dontTouch(io.commits)
1632780712aaSxiaofeibao-xjtu    dontTouch(commitIsVTypeVec)
1633780712aaSxiaofeibao-xjtu    dontTouch(walkIsVTypeVec)
1634780712aaSxiaofeibao-xjtu    dontTouch(commitValidThisLine)
1635780712aaSxiaofeibao-xjtu    dontTouch(commitReadAddr_next)
1636780712aaSxiaofeibao-xjtu    dontTouch(donotNeedWalk)
1637780712aaSxiaofeibao-xjtu    dontTouch(walkPtrVec_next)
1638780712aaSxiaofeibao-xjtu    dontTouch(walkPtrVec)
1639780712aaSxiaofeibao-xjtu    dontTouch(deqPtrVec_next)
1640780712aaSxiaofeibao-xjtu    dontTouch(deqPtrVecForWalk)
1641780712aaSxiaofeibao-xjtu    dontTouch(snapPtrReadBank)
1642780712aaSxiaofeibao-xjtu    dontTouch(snapPtrVecForWalk)
1643780712aaSxiaofeibao-xjtu    dontTouch(shouldWalkVec)
1644780712aaSxiaofeibao-xjtu    dontTouch(walkFinished)
1645780712aaSxiaofeibao-xjtu    dontTouch(changeBankAddrToDeqPtr)
1646780712aaSxiaofeibao-xjtu  }
1647780712aaSxiaofeibao-xjtu  if (env.EnableDifftest) {
1648780712aaSxiaofeibao-xjtu    io.commits.info.map(info => dontTouch(info.debug_pc.get))
1649780712aaSxiaofeibao-xjtu  }
16509aca92b9SYinan Xu}
1651