xref: /XiangShan/src/main/scala/xiangshan/backend/rob/Rob.scala (revision 00c6a8aac7d4c20605fe93ba33304a90b4b5126a)
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}
3908373300SAnzoimport xiangshan.backend.decode.isa.bitfield.XSInstBitFields
404c7680e0SXuan Huimport xiangshan.backend.fu.{FuConfig, FuType}
416ab6918fSYinan Xuimport xiangshan.frontend.FtqPtr
42870f462dSXuan Huimport xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr}
43730cfbc0SXuan Huimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
44870f462dSXuan Huimport xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo}
454c7680e0SXuan Huimport xiangshan.backend.fu.vector.Bundles.VType
46870f462dSXuan Huimport xiangshan.backend.rename.SnapshotGenerator
47d280e426Slewislzhimport yunsuan.VfaluType
48780712aaSxiaofeibao-xjtuimport xiangshan.backend.rob.RobBundles._
4949162c9aSGuanghui Chengimport xiangshan.backend.trace._
506a8b2d5fSxiaofeibao-xjtuimport chisel3.experimental.BundleLiterals._
519aca92b9SYinan Xu
523b739f49SXuan Huclass Rob(params: BackendParams)(implicit p: Parameters) extends LazyModule with HasXSParameter {
5395e60e55STang Haojin  override def shouldBeInlined: Boolean = false
546ab6918fSYinan Xu
553b739f49SXuan Hu  lazy val module = new RobImp(this)(p, params)
566ab6918fSYinan Xu}
576ab6918fSYinan Xu
583b739f49SXuan Huclass RobImp(override val wrapper: Rob)(implicit p: Parameters, params: BackendParams) extends LazyModuleImp(wrapper)
5985a8d7caSZehao Liu  with HasXSParameter with HasCircularQueuePtrHelper with HasPerfEvents with HasCriticalErrors {
606ab6918fSYinan Xu
61870f462dSXuan Hu  private val LduCnt = params.LduCnt
62870f462dSXuan Hu  private val StaCnt = params.StaCnt
636810d1e8Ssfencevma  private val HyuCnt = params.HyuCnt
64870f462dSXuan Hu
659aca92b9SYinan Xu  val io = IO(new Bundle() {
66f57f7f2aSYangyu Chen    val hartId = Input(UInt(hartIdLen.W))
679aca92b9SYinan Xu    val redirect = Input(Valid(new Redirect))
689aca92b9SYinan Xu    val enq = new RobEnqIO
69f4b2089aSYinan Xu    val flushOut = ValidIO(new Redirect)
709aca92b9SYinan Xu    val exception = ValidIO(new ExceptionInfo)
719aca92b9SYinan Xu    // exu + brq
723b739f49SXuan Hu    val writeback: MixedVec[ValidIO[ExuOutput]] = Flipped(params.genWrite2CtrlBundles)
73bd5909d0Sxiaofeibao-xjtu    val exuWriteback: MixedVec[ValidIO[ExuOutput]] = Flipped(params.genWrite2CtrlBundles)
7485f51ecaSxiaofeibao-xjtu    val writebackNums = Flipped(Vec(writeback.size - params.StdCnt, ValidIO(UInt(writeback.size.U.getWidth.W))))
75571677c9Sxiaofeibao-xjtu    val writebackNeedFlush = Input(Vec(params.allExuParams.filter(_.needExceptionGen).length, Bool()))
76ccfddc82SHaojin Tang    val commits = Output(new RobCommitIO)
774907ec88Schengguanghui    val trace = new Bundle {
784907ec88Schengguanghui      val blockCommit = Input(Bool())
794907ec88Schengguanghui      val traceCommitInfo = new TraceBundle(hasIaddr = false, CommitWidth, IretireWidthInPipe)
804907ec88Schengguanghui    }
816b102a39SHaojin Tang    val rabCommits = Output(new RabCommitIO)
8263d67ef3STang Haojin    val diffCommits = if (backendParams.basicDebugEn) Some(Output(new DiffCommitIO)) else None
83a8db15d8Sfdy    val isVsetFlushPipe = Output(Bool())
849aca92b9SYinan Xu    val lsq = new RobLsqIO
859aca92b9SYinan Xu    val robDeqPtr = Output(new RobPtr)
869aca92b9SYinan Xu    val csr = new RobCSRIO
87fa7f2c26STang Haojin    val snpt = Input(new SnapshotPort)
889aca92b9SYinan Xu    val robFull = Output(Bool())
89d2b20d1aSTang Haojin    val headNotReady = Output(Bool())
90b6900d94SYinan Xu    val cpu_halt = Output(Bool())
9109309bdbSYinan Xu    val wfi_enable = Input(Bool())
924c7680e0SXuan Hu    val toDecode = new Bundle {
9386727929Ssinsanction      val isResumeVType = Output(Bool())
94d275ad0eSZiyue Zhang      val walkToArchVType = Output(Bool())
9581535d7bSsinsanction      val walkVType = ValidIO(VType())
967e4f0b19SZiyue-Zhang      val commitVType = new Bundle {
977e4f0b19SZiyue-Zhang        val vtype = ValidIO(VType())
987e4f0b19SZiyue-Zhang        val hasVsetvl = Output(Bool())
994c7680e0SXuan Hu      }
1009aca92b9SYinan Xu    }
101b9a37d2fSXuan Hu    val fromVecExcpMod = Input(new Bundle {
102b9a37d2fSXuan Hu      val busy = Bool()
103b9a37d2fSXuan Hu    })
1046f483f86SXuan Hu    val readGPAMemAddr = ValidIO(new Bundle {
1056f483f86SXuan Hu      val ftqPtr = new FtqPtr()
1066f483f86SXuan Hu      val ftqOffset = UInt(log2Up(PredictWidth).W)
1076f483f86SXuan Hu    })
108ad415ae0SXiaokun-Pei    val readGPAMemData = Input(new GPAMemEntry)
1095110577fSZiyue Zhang    val vstartIsZero = Input(Bool())
11060ebee38STang Haojin
111e43bb916SXuan Hu    val toVecExcpMod = Output(new Bundle {
112e43bb916SXuan Hu      val logicPhyRegMap = Vec(RabCommitWidth, ValidIO(new RegWriteFromRab))
113e43bb916SXuan Hu      val excpInfo = ValidIO(new VecExcpInfo)
114e43bb916SXuan Hu    })
1158744445eSMaxpicca-Li    val debug_ls = Flipped(new DebugLSIO)
116870f462dSXuan Hu    val debugRobHead = Output(new DynInst)
117d2b20d1aSTang Haojin    val debugEnqLsq = Input(new LsqEnqIO)
118d2b20d1aSTang Haojin    val debugHeadLsIssue = Input(Bool())
1196810d1e8Ssfencevma    val lsTopdownInfo = Vec(LduCnt + HyuCnt, Input(new LsTopdownInfo))
12060ebee38STang Haojin    val debugTopDown = new Bundle {
12160ebee38STang Haojin      val toCore = new RobCoreTopDownIO
12260ebee38STang Haojin      val toDispatch = new RobDispatchTopDownIO
12360ebee38STang Haojin      val robHeadLqIdx = Valid(new LqPtr)
12460ebee38STang Haojin    }
1257cf78eb2Shappy-lx    val debugRolling = new RobDebugRollingIO
1261bf9a598SAnzo
1271bf9a598SAnzo    // store event difftest information
1281bf9a598SAnzo    val storeDebugInfo = Vec(EnsbufferWidth, new Bundle {
1291bf9a598SAnzo      val robidx = Input(new RobPtr)
1301bf9a598SAnzo      val pc     = Output(UInt(VAddrBits.W))
1311bf9a598SAnzo    })
1329aca92b9SYinan Xu  })
1339aca92b9SYinan Xu
134bd5909d0Sxiaofeibao-xjtu  val exuWBs: Seq[ValidIO[ExuOutput]] = io.exuWriteback.filter(!_.bits.params.hasStdFu).toSeq
135bd5909d0Sxiaofeibao-xjtu  val stdWBs: Seq[ValidIO[ExuOutput]] = io.exuWriteback.filter(_.bits.params.hasStdFu).toSeq
13608373300SAnzo  val vldWBs: Seq[ValidIO[ExuOutput]] = io.exuWriteback.filter(_.bits.params.hasVLoadFu).toSeq
137bd5909d0Sxiaofeibao-xjtu  val fflagsWBs = io.exuWriteback.filter(x => x.bits.fflags.nonEmpty).toSeq
1381d2f6c6bSsinsanction  val exceptionWBs = io.writeback.filter(x => x.bits.exceptionVec.nonEmpty).toSeq
1391d2f6c6bSsinsanction  val redirectWBs = io.writeback.filter(x => x.bits.redirect.nonEmpty).toSeq
140bd5909d0Sxiaofeibao-xjtu  val vxsatWBs = io.exuWriteback.filter(x => x.bits.vxsat.nonEmpty).toSeq
14149162c9aSGuanghui Cheng  val branchWBs = io.exuWriteback.filter(_.bits.params.hasBrhFu).toSeq
142e836c770SZhaoyang You  val jmpWBs = io.exuWriteback.filter(_.bits.params.hasJmpFu).toSeq
14349162c9aSGuanghui Cheng  val csrWBs = io.exuWriteback.filter(x => x.bits.params.hasCSR).toSeq
1443b739f49SXuan Hu
1451592abd1SYan Xu  PerfCCT.tick(clock, reset)
1461592abd1SYan Xu
1471592abd1SYan Xu  io.exuWriteback.zipWithIndex.foreach{ case (wb, i) =>
1481592abd1SYan Xu    PerfCCT.updateInstPos(wb.bits.debug_seqNum, PerfCCT.InstPos.AtWriteVal.id.U, wb.valid, clock, reset)
1491592abd1SYan Xu  }
1501592abd1SYan Xu
1513b739f49SXuan Hu  val numExuWbPorts = exuWBs.length
1523b739f49SXuan Hu  val numStdWbPorts = stdWBs.length
153780712aaSxiaofeibao-xjtu  val bankAddrWidth = log2Up(CommitWidth)
1546ab6918fSYinan Xu
1553b739f49SXuan Hu  println(s"Rob: size $RobSize, numExuWbPorts: $numExuWbPorts, numStdWbPorts: $numStdWbPorts, commitwidth: $CommitWidth")
1563b739f49SXuan Hu
157780712aaSxiaofeibao-xjtu  val rab = Module(new RenameBuffer(RabSize))
158780712aaSxiaofeibao-xjtu  val vtypeBuffer = Module(new VTypeBuffer(VTypeBufferSize))
159780712aaSxiaofeibao-xjtu  val bankNum = 8
160780712aaSxiaofeibao-xjtu  assert(RobSize % bankNum == 0, "RobSize % bankNum must be 0")
1616a8b2d5fSxiaofeibao-xjtu  val robEntries = RegInit(VecInit.fill(RobSize)((new RobEntryBundle).Lit(_.valid -> false.B)))
162780712aaSxiaofeibao-xjtu  // pointers
163780712aaSxiaofeibao-xjtu  // For enqueue ptr, we don't duplicate it since only enqueue needs it.
164780712aaSxiaofeibao-xjtu  val enqPtrVec = Wire(Vec(RenameWidth, new RobPtr))
165780712aaSxiaofeibao-xjtu  val deqPtrVec = Wire(Vec(CommitWidth, new RobPtr))
166ea2894c8SXuan Hu  val deqPtrVec_next = Wire(Vec(CommitWidth, Output(new RobPtr)))
167780712aaSxiaofeibao-xjtu  val walkPtrVec = Reg(Vec(CommitWidth, new RobPtr))
168c0f8424bSzhanglyGit  val walkPtrTrue = Reg(new RobPtr)
169780712aaSxiaofeibao-xjtu  val lastWalkPtr = Reg(new RobPtr)
170780712aaSxiaofeibao-xjtu  val allowEnqueue = RegInit(true.B)
17135b3b30bSxiaofeibao  val allowEnqueueForDispatch = RegInit(true.B)
172e43bb916SXuan Hu  val vecExcpInfo = RegInit(ValidIO(new VecExcpInfo).Lit(
173e43bb916SXuan Hu    _.valid -> false.B,
174e43bb916SXuan Hu  ))
1759aca92b9SYinan Xu
176780712aaSxiaofeibao-xjtu  /**
177780712aaSxiaofeibao-xjtu   * Enqueue (from dispatch)
178780712aaSxiaofeibao-xjtu   */
179780712aaSxiaofeibao-xjtu  // special cases
180780712aaSxiaofeibao-xjtu  val hasBlockBackward = RegInit(false.B)
181780712aaSxiaofeibao-xjtu  val hasWaitForward = RegInit(false.B)
182780712aaSxiaofeibao-xjtu  val enqPtr = enqPtrVec(0)
183780712aaSxiaofeibao-xjtu  val deqPtr = deqPtrVec(0)
184780712aaSxiaofeibao-xjtu  val walkPtr = walkPtrVec(0)
185780712aaSxiaofeibao-xjtu  val allocatePtrVec = VecInit((0 until RenameWidth).map(i => enqPtrVec(PopCount(io.enq.req.take(i).map(req => req.valid && req.bits.firstUop)))))
186b9a37d2fSXuan Hu  io.enq.canAccept := allowEnqueue && !hasBlockBackward && rab.io.canEnq && vtypeBuffer.io.canEnq && !io.fromVecExcpMod.busy
1875540bdc7Sxiaofeibao  io.enq.canAcceptForDispatch := allowEnqueueForDispatch && !hasBlockBackward && rab.io.canEnqForDispatch && vtypeBuffer.io.canEnqForDispatch && !io.fromVecExcpMod.busy
188780712aaSxiaofeibao-xjtu  io.enq.resp := allocatePtrVec
189780712aaSxiaofeibao-xjtu  val canEnqueue = VecInit(io.enq.req.map(req => req.valid && req.bits.firstUop && io.enq.canAccept))
190780712aaSxiaofeibao-xjtu  val timer = GTimer()
191780712aaSxiaofeibao-xjtu  // robEntries enqueue
192780712aaSxiaofeibao-xjtu  for (i <- 0 until RobSize) {
193780712aaSxiaofeibao-xjtu    val enqOH = VecInit(canEnqueue.zip(allocatePtrVec.map(_.value === i.U)).map(x => x._1 && x._2))
194780712aaSxiaofeibao-xjtu    assert(PopCount(enqOH) < 2.U, s"robEntries$i enqOH is not one hot")
195780712aaSxiaofeibao-xjtu    when(enqOH.asUInt.orR && !io.redirect.valid){
196780712aaSxiaofeibao-xjtu      connectEnq(robEntries(i), Mux1H(enqOH, io.enq.req.map(_.bits)))
197a8db15d8Sfdy    }
198af4bdb08SXuan Hu  }
199780712aaSxiaofeibao-xjtu  // robBanks0 include robidx : 0 8 16 24 32 ...
200780712aaSxiaofeibao-xjtu  val robBanks = VecInit((0 until bankNum).map(i => VecInit(robEntries.zipWithIndex.filter(_._2 % bankNum == i).map(_._1))))
201780712aaSxiaofeibao-xjtu  // each Bank has 20 Entries, read addr is one hot
202780712aaSxiaofeibao-xjtu  // all banks use same raddr
203780712aaSxiaofeibao-xjtu  val eachBankEntrieNum = robBanks(0).length
204780712aaSxiaofeibao-xjtu  val robBanksRaddrThisLine = RegInit(1.U(eachBankEntrieNum.W))
205780712aaSxiaofeibao-xjtu  val robBanksRaddrNextLine = Wire(UInt(eachBankEntrieNum.W))
206780712aaSxiaofeibao-xjtu  robBanksRaddrThisLine := robBanksRaddrNextLine
207780712aaSxiaofeibao-xjtu  val bankNumWidth = log2Up(bankNum)
208780712aaSxiaofeibao-xjtu  val deqPtrWidth = deqPtr.value.getWidth
209780712aaSxiaofeibao-xjtu  val robIdxThisLine = VecInit((0 until bankNum).map(i => Cat(deqPtr.value(deqPtrWidth - 1, bankNumWidth), i.U(bankNumWidth.W))))
210780712aaSxiaofeibao-xjtu  val robIdxNextLine = VecInit((0 until bankNum).map(i => Cat(deqPtr.value(deqPtrWidth - 1, bankNumWidth) + 1.U, i.U(bankNumWidth.W))))
211780712aaSxiaofeibao-xjtu  // robBanks read
212780712aaSxiaofeibao-xjtu  val robBanksRdataThisLine = VecInit(robBanks.map{ case bank =>
213780712aaSxiaofeibao-xjtu    Mux1H(robBanksRaddrThisLine, bank)
214780712aaSxiaofeibao-xjtu  })
215780712aaSxiaofeibao-xjtu  val robBanksRdataNextLine = VecInit(robBanks.map{ case bank =>
216780712aaSxiaofeibao-xjtu    val shiftBank = bank.drop(1) :+ bank(0)
217780712aaSxiaofeibao-xjtu    Mux1H(robBanksRaddrThisLine, shiftBank)
218780712aaSxiaofeibao-xjtu  })
219780712aaSxiaofeibao-xjtu  val robBanksRdataThisLineUpdate = Wire(Vec(CommitWidth, new RobEntryBundle))
220780712aaSxiaofeibao-xjtu  val robBanksRdataNextLineUpdate = Wire(Vec(CommitWidth, new RobEntryBundle))
221780712aaSxiaofeibao-xjtu  val commitValidThisLine = Wire(Vec(CommitWidth, Bool()))
222780712aaSxiaofeibao-xjtu  val hasCommitted = RegInit(VecInit(Seq.fill(CommitWidth)(false.B)))
223780712aaSxiaofeibao-xjtu  val donotNeedWalk = RegInit(VecInit(Seq.fill(CommitWidth)(false.B)))
224780712aaSxiaofeibao-xjtu  val allCommitted = Wire(Bool())
225af4bdb08SXuan Hu
226780712aaSxiaofeibao-xjtu  when(allCommitted) {
227780712aaSxiaofeibao-xjtu    hasCommitted := 0.U.asTypeOf(hasCommitted)
228780712aaSxiaofeibao-xjtu  }.elsewhen(io.commits.isCommit){
229780712aaSxiaofeibao-xjtu    for (i <- 0 until CommitWidth){
230780712aaSxiaofeibao-xjtu      hasCommitted(i) := commitValidThisLine(i) || hasCommitted(i)
231780712aaSxiaofeibao-xjtu    }
232780712aaSxiaofeibao-xjtu  }
233780712aaSxiaofeibao-xjtu  allCommitted := io.commits.isCommit && commitValidThisLine.last
234780712aaSxiaofeibao-xjtu  val walkPtrHead = Wire(new RobPtr)
235780712aaSxiaofeibao-xjtu  val changeBankAddrToDeqPtr = (walkPtrVec.head + CommitWidth.U) > lastWalkPtr
236780712aaSxiaofeibao-xjtu  when(io.redirect.valid){
237780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := UIntToOH(walkPtrHead.value(walkPtrHead.value.getWidth-1, bankAddrWidth))
238780712aaSxiaofeibao-xjtu  }.elsewhen(allCommitted || io.commits.isWalk && !changeBankAddrToDeqPtr){
239780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := Mux(robBanksRaddrThisLine.head(1) === 1.U, 1.U, robBanksRaddrThisLine << 1)
240780712aaSxiaofeibao-xjtu  }.elsewhen(io.commits.isWalk && changeBankAddrToDeqPtr){
241780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := UIntToOH(deqPtr.value(deqPtr.value.getWidth-1, bankAddrWidth))
242780712aaSxiaofeibao-xjtu  }.otherwise(
243780712aaSxiaofeibao-xjtu    robBanksRaddrNextLine := robBanksRaddrThisLine
244780712aaSxiaofeibao-xjtu  )
245780712aaSxiaofeibao-xjtu  val robDeqGroup = Reg(Vec(bankNum, new RobCommitEntryBundle))
246d904dcfbSchengguanghui  val rawInfo = VecInit((0 until CommitWidth).map(i => robDeqGroup(deqPtrVec(i).value(bankAddrWidth-1, 0)))).toSeq
247780712aaSxiaofeibao-xjtu  val commitInfo = VecInit((0 until CommitWidth).map(i => robDeqGroup(deqPtrVec(i).value(bankAddrWidth-1,0)))).toSeq
2484c30949dSxiao feibao  val walkInfo = VecInit((0 until CommitWidth).map(i => robDeqGroup(walkPtrVec(i).value(bankAddrWidth-1, 0)))).toSeq
249780712aaSxiaofeibao-xjtu  for (i <- 0 until CommitWidth) {
250780712aaSxiaofeibao-xjtu    connectCommitEntry(robDeqGroup(i), robBanksRdataThisLineUpdate(i))
251780712aaSxiaofeibao-xjtu    when(allCommitted){
252780712aaSxiaofeibao-xjtu      connectCommitEntry(robDeqGroup(i), robBanksRdataNextLineUpdate(i))
253780712aaSxiaofeibao-xjtu    }
254780712aaSxiaofeibao-xjtu  }
25549162c9aSGuanghui Cheng
256d904dcfbSchengguanghui  // In each robentry, the ftqIdx and ftqOffset belong to the first instruction that was compressed,
257d904dcfbSchengguanghui  // That is Necessary when exceptions happen.
258d904dcfbSchengguanghui  // Update the ftqOffset to correctly notify the frontend which instructions have been committed.
259d904dcfbSchengguanghui  // Instructions in multiple Ftq entries compressed to one RobEntry do not occur.
260d904dcfbSchengguanghui  for (i <- 0 until CommitWidth) {
261d904dcfbSchengguanghui    val lastOffset = (rawInfo(i).traceBlockInPipe.iretire - (1.U << rawInfo(i).traceBlockInPipe.ilastsize.asUInt).asUInt) + rawInfo(i).ftqOffset
262b720b0cdSchengguanghui    commitInfo(i).ftqOffset := Mux(CommitType.isFused(rawInfo(i).commitType), rawInfo(i).ftqOffset, lastOffset)
263d904dcfbSchengguanghui  }
264d904dcfbSchengguanghui
2659aca92b9SYinan Xu  // data for debug
2669aca92b9SYinan Xu  // Warn: debug_* prefix should not exist in generated verilog.
267c7d010e5SXuan Hu  val debug_microOp = DebugMem(RobSize, new DynInst)
2689aca92b9SYinan Xu  val debug_exuData = Reg(Vec(RobSize, UInt(XLEN.W))) //for debug
2699aca92b9SYinan Xu  val debug_exuDebug = Reg(Vec(RobSize, new DebugBundle)) //for debug
2708744445eSMaxpicca-Li  val debug_lsInfo = RegInit(VecInit(Seq.fill(RobSize)(DebugLsInfo.init)))
271d2b20d1aSTang Haojin  val debug_lsTopdownInfo = RegInit(VecInit(Seq.fill(RobSize)(LsTopdownInfo.init)))
272d2b20d1aSTang Haojin  val debug_lqIdxValid = RegInit(VecInit.fill(RobSize)(false.B))
273d2b20d1aSTang Haojin  val debug_lsIssued = RegInit(VecInit.fill(RobSize)(false.B))
2749aca92b9SYinan Xu
2759aca92b9SYinan Xu  val isEmpty = enqPtr === deqPtr
276780712aaSxiaofeibao-xjtu  val snptEnq = io.enq.canAccept && io.enq.req.map(x => x.valid && x.bits.snapshot).reduce(_ || _)
277780712aaSxiaofeibao-xjtu  val snapshotPtrVec = Wire(Vec(CommitWidth, new RobPtr))
278780712aaSxiaofeibao-xjtu  snapshotPtrVec(0) := io.enq.req(0).bits.robIdx
279780712aaSxiaofeibao-xjtu  for (i <- 1 until CommitWidth) {
280780712aaSxiaofeibao-xjtu    snapshotPtrVec(i) := snapshotPtrVec(0) + i.U
281780712aaSxiaofeibao-xjtu  }
282780712aaSxiaofeibao-xjtu  val snapshots = SnapshotGenerator(snapshotPtrVec, snptEnq, io.snpt.snptDeq, io.redirect.valid, io.snpt.flushVec)
283d2b20d1aSTang Haojin  val debug_lsIssue = WireDefault(debug_lsIssued)
284d2b20d1aSTang Haojin  debug_lsIssue(deqPtr.value) := io.debugHeadLsIssue
285d2b20d1aSTang Haojin
2869aca92b9SYinan Xu  /**
2879aca92b9SYinan Xu   * states of Rob
2889aca92b9SYinan Xu   */
289ccfddc82SHaojin Tang  val s_idle :: s_walk :: Nil = Enum(2)
2909aca92b9SYinan Xu  val state = RegInit(s_idle)
291ea2894c8SXuan Hu  val state_next = Wire(chiselTypeOf(state))
2929aca92b9SYinan Xu
2938bf33c52Swakafa  val tip_computing :: tip_stalled :: tip_walk :: tip_drained :: Nil = Enum(4)
2948bf33c52Swakafa  val tip_state = WireInit(0.U(4.W))
2958bf33c52Swakafa  when(!isEmpty) {  // One or more inst in ROB
2968bf33c52Swakafa    when(state === s_walk || io.redirect.valid) {
2978bf33c52Swakafa      tip_state := tip_walk
2988bf33c52Swakafa    }.elsewhen(io.commits.isCommit && PopCount(io.commits.commitValid) =/= 0.U) {
2998bf33c52Swakafa      tip_state := tip_computing
3008bf33c52Swakafa    }.otherwise {
3018bf33c52Swakafa      tip_state := tip_stalled
3028bf33c52Swakafa    }
3038bf33c52Swakafa  }.otherwise {
3048bf33c52Swakafa    tip_state := tip_drained
3058bf33c52Swakafa  }
3068bf33c52Swakafa  class TipEntry()(implicit p: Parameters) extends XSBundle {
3078bf33c52Swakafa    val state = UInt(4.W)
3088bf33c52Swakafa    val commits = new RobCommitIO()      // info of commit
3098bf33c52Swakafa    val redirect = Valid(new Redirect)   // info of redirect
3108bf33c52Swakafa    val redirect_pc = UInt(VAddrBits.W)  // PC of the redirect uop
3118bf33c52Swakafa    val debugLsInfo = new DebugLsInfo()
3128bf33c52Swakafa  }
3138bf33c52Swakafa  val tip_table = ChiselDB.createTable("Tip_" + p(XSCoreParamsKey).HartId.toString, new TipEntry)
3148bf33c52Swakafa  val tip_data = Wire(new TipEntry())
3158bf33c52Swakafa  tip_data.state := tip_state
3168bf33c52Swakafa  tip_data.commits := io.commits
3178bf33c52Swakafa  tip_data.redirect := io.redirect
3188bf33c52Swakafa  tip_data.redirect_pc := debug_microOp(io.redirect.bits.robIdx.value).pc
3198bf33c52Swakafa  tip_data.debugLsInfo := debug_lsInfo(io.commits.robIdx(0).value)
3208bf33c52Swakafa  tip_table.log(tip_data, true.B, "", clock, reset)
3218bf33c52Swakafa
3223b739f49SXuan Hu  val exceptionGen = Module(new ExceptionGen(params))
3239aca92b9SYinan Xu  val exceptionDataRead = exceptionGen.io.state
3249aca92b9SYinan Xu  val fflagsDataRead = Wire(Vec(CommitWidth, UInt(5.W)))
325a8db15d8Sfdy  val vxsatDataRead = Wire(Vec(CommitWidth, Bool()))
3269aca92b9SYinan Xu  io.robDeqPtr := deqPtr
327d2b20d1aSTang Haojin  io.debugRobHead := debug_microOp(deqPtr.value)
3289aca92b9SYinan Xu
3294c7680e0SXuan Hu  /**
3304c7680e0SXuan Hu   * connection of [[rab]]
3314c7680e0SXuan Hu   */
33244369838SXuan Hu  rab.io.redirect.valid := io.redirect.valid
33344369838SXuan Hu
334a8db15d8Sfdy  rab.io.req.zip(io.enq.req).map { case (dest, src) =>
335a8db15d8Sfdy    dest.bits := src.bits
336a8db15d8Sfdy    dest.valid := src.valid && io.enq.canAccept
337a8db15d8Sfdy  }
338a8db15d8Sfdy
339cda1c534Sxiaofeibao-xjtu  val walkDestSizeDeqGroup = RegInit(VecInit(Seq.fill(CommitWidth)(0.U(log2Up(MaxUopSize + 1).W))))
340780712aaSxiaofeibao-xjtu  val realDestSizeSeq = VecInit(robDeqGroup.zip(hasCommitted).map{case (r, h) => Mux(h, 0.U, r.realDestSize)})
341780712aaSxiaofeibao-xjtu  val walkDestSizeSeq = VecInit(robDeqGroup.zip(donotNeedWalk).map{case (r, d) => Mux(d, 0.U, r.realDestSize)})
342780712aaSxiaofeibao-xjtu  val commitSizeSumSeq = VecInit((0 until CommitWidth).map(i => realDestSizeSeq.take(i + 1).reduce(_ +& _)))
343780712aaSxiaofeibao-xjtu  val walkSizeSumSeq   = VecInit((0 until CommitWidth).map(i => walkDestSizeSeq.take(i + 1).reduce(_ +& _)))
344780712aaSxiaofeibao-xjtu  val commitSizeSumCond = VecInit(commitValidThisLine.zip(hasCommitted).map{case (c,h) => (c || h) && io.commits.isCommit})
345780712aaSxiaofeibao-xjtu  val walkSizeSumCond   = VecInit(io.commits.walkValid.zip(donotNeedWalk).map{case (w,d) => (w || d) && io.commits.isWalk})
346cda1c534Sxiaofeibao-xjtu  val commitSizeSum = PriorityMuxDefault(commitSizeSumCond.reverse.zip(commitSizeSumSeq.reverse), 0.U)
347cda1c534Sxiaofeibao-xjtu  val walkSizeSum   = PriorityMuxDefault(walkSizeSumCond.reverse.zip(walkSizeSumSeq.reverse), 0.U)
34844369838SXuan Hu
349fd33b932Sxiaofeibao  val deqVlsExceptionNeedCommit = RegInit(false.B)
350fd33b932Sxiaofeibao  val deqVlsExceptionCommitSize = RegInit(0.U(log2Up(MaxUopSize + 1).W))
351fd33b932Sxiaofeibao  val deqVlsCanCommit= RegInit(false.B)
352fd33b932Sxiaofeibao  rab.io.fromRob.commitSize := Mux(deqVlsExceptionNeedCommit, deqVlsExceptionCommitSize, commitSizeSum)
35365f65924SXuan Hu  rab.io.fromRob.walkSize := walkSizeSum
354e43bb916SXuan Hu  rab.io.fromRob.vecLoadExcp.valid := RegNext(exceptionDataRead.valid && exceptionDataRead.bits.isVecLoad)
355e43bb916SXuan Hu  rab.io.fromRob.vecLoadExcp.bits.isStrided := RegEnable(exceptionDataRead.bits.isStrided, exceptionDataRead.valid)
356e43bb916SXuan Hu  rab.io.fromRob.vecLoadExcp.bits.isVlm := RegEnable(exceptionDataRead.bits.isVlm, exceptionDataRead.valid)
357c4b56310SHaojin Tang  rab.io.snpt := io.snpt
3589b9e991bSHaojin Tang  rab.io.snpt.snptEnq := snptEnq
359a8db15d8Sfdy
3603019c601Sxiaofeibao  // pipe rab commits for better timing and area
3613019c601Sxiaofeibao  io.rabCommits := RegNext(rab.io.commits)
362cda1c534Sxiaofeibao-xjtu  io.diffCommits.foreach(_ := rab.io.diffCommits.get)
363a8db15d8Sfdy
3649aca92b9SYinan Xu  /**
3654c7680e0SXuan Hu   * connection of [[vtypeBuffer]]
3664c7680e0SXuan Hu   */
3674c7680e0SXuan Hu
3684c7680e0SXuan Hu  vtypeBuffer.io.redirect.valid := io.redirect.valid
3694c7680e0SXuan Hu
3704c7680e0SXuan Hu  vtypeBuffer.io.req.zip(io.enq.req).map { case (sink, source) =>
3714c7680e0SXuan Hu    sink.valid := source.valid && io.enq.canAccept
3724c7680e0SXuan Hu    sink.bits := source.bits
3734c7680e0SXuan Hu  }
3744c7680e0SXuan Hu
3753e7f8698SXuan Hu  private val commitIsVTypeVec = VecInit(io.commits.commitValid.zip(io.commits.info).map { case (valid, info) => io.commits.isCommit && valid && info.isVset })
3764c30949dSxiao feibao  private val walkIsVTypeVec = VecInit(io.commits.walkValid.zip(walkInfo).map { case (valid, info) => io.commits.isWalk && valid && info.isVset })
3774c7680e0SXuan Hu  vtypeBuffer.io.fromRob.commitSize := PopCount(commitIsVTypeVec)
3784c7680e0SXuan Hu  vtypeBuffer.io.fromRob.walkSize := PopCount(walkIsVTypeVec)
3794c7680e0SXuan Hu  vtypeBuffer.io.snpt := io.snpt
3804c7680e0SXuan Hu  vtypeBuffer.io.snpt.snptEnq := snptEnq
381d275ad0eSZiyue Zhang  io.toDecode.walkToArchVType := vtypeBuffer.io.toDecode.walkToArchVType
38281535d7bSsinsanction  io.toDecode.commitVType := vtypeBuffer.io.toDecode.commitVType
38381535d7bSsinsanction  io.toDecode.walkVType := vtypeBuffer.io.toDecode.walkVType
384780712aaSxiaofeibao-xjtu
3859aca92b9SYinan Xu  // When blockBackward instruction leaves Rob (commit or walk), hasBlockBackward should be set to false.B
3869aca92b9SYinan Xu  // To reduce registers usage, for hasBlockBackward cases, we allow enqueue after ROB is empty.
387780712aaSxiaofeibao-xjtu  when(isEmpty) {
388780712aaSxiaofeibao-xjtu    hasBlockBackward := false.B
389780712aaSxiaofeibao-xjtu  }
3909aca92b9SYinan Xu  // When any instruction commits, hasNoSpecExec should be set to false.B
391780712aaSxiaofeibao-xjtu  when(io.commits.hasWalkInstr || io.commits.hasCommitInstr) {
392780712aaSxiaofeibao-xjtu    hasWaitForward := false.B
393780712aaSxiaofeibao-xjtu  }
3945c95ea2eSYinan Xu
3955c95ea2eSYinan Xu  // The wait-for-interrupt (WFI) instruction waits in the ROB until an interrupt might need servicing.
3965c95ea2eSYinan Xu  // io.csr.wfiEvent will be asserted if the WFI can resume execution, and we change the state to s_wfi_idle.
3975c95ea2eSYinan Xu  // It does not affect how interrupts are serviced. Note that WFI is noSpecExec and it does not trigger interrupts.
3985c95ea2eSYinan Xu  val hasWFI = RegInit(false.B)
3995c95ea2eSYinan Xu  io.cpu_halt := hasWFI
400342656a5SYinan Xu  // WFI Timeout: 2^20 = 1M cycles
401342656a5SYinan Xu  val wfi_cycles = RegInit(0.U(20.W))
402*00c6a8aaSGuanghui Cheng  if (wfiResume) {
403342656a5SYinan Xu    when(hasWFI) {
404342656a5SYinan Xu      wfi_cycles := wfi_cycles + 1.U
405342656a5SYinan Xu    }.elsewhen(!hasWFI && RegNext(hasWFI)) {
406342656a5SYinan Xu      wfi_cycles := 0.U
407342656a5SYinan Xu    }
408*00c6a8aaSGuanghui Cheng  }
409*00c6a8aaSGuanghui Cheng  val wfi_timeout = wfi_cycles.andR
410342656a5SYinan Xu  when(RegNext(RegNext(io.csr.wfiEvent)) || io.flushOut.valid || wfi_timeout) {
4115c95ea2eSYinan Xu    hasWFI := false.B
412b6900d94SYinan Xu  }
4139aca92b9SYinan Xu
4149aca92b9SYinan Xu  for (i <- 0 until RenameWidth) {
4159aca92b9SYinan Xu    // we don't check whether io.redirect is valid here since redirect has higher priority
4169aca92b9SYinan Xu    when(canEnqueue(i)) {
4176ab6918fSYinan Xu      val enqUop = io.enq.req(i).bits
4186474c47fSYinan Xu      val enqIndex = allocatePtrVec(i).value
4199aca92b9SYinan Xu      // store uop in data module and debug_microOp Vec
4206474c47fSYinan Xu      debug_microOp(enqIndex) := enqUop
4216474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.dispatchTime := timer
4226474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.enqRsTime := timer
4236474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.selectTime := timer
4246474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.issueTime := timer
4256474c47fSYinan Xu      debug_microOp(enqIndex).debugInfo.writebackTime := timer
4268744445eSMaxpicca-Li      debug_microOp(enqIndex).debugInfo.tlbFirstReqTime := timer
4278744445eSMaxpicca-Li      debug_microOp(enqIndex).debugInfo.tlbRespTime := timer
4288744445eSMaxpicca-Li      debug_lsInfo(enqIndex) := DebugLsInfo.init
429d2b20d1aSTang Haojin      debug_lsTopdownInfo(enqIndex) := LsTopdownInfo.init
430d2b20d1aSTang Haojin      debug_lqIdxValid(enqIndex) := false.B
431d2b20d1aSTang Haojin      debug_lsIssued(enqIndex) := false.B
4323b739f49SXuan Hu      when (enqUop.waitForward) {
4333b739f49SXuan Hu        hasWaitForward := true.B
4349aca92b9SYinan Xu      }
4357e0f64b0SGuanghui Cheng      val enqTriggerActionIsDebugMode = TriggerAction.isDmode(io.enq.req(i).bits.trigger)
4363b739f49SXuan Hu      val enqHasException = ExceptionNO.selectFrontend(enqUop.exceptionVec).asUInt.orR
4377e0f64b0SGuanghui Cheng      when(enqUop.isWFI && !enqHasException && !enqTriggerActionIsDebugMode) {
4385c95ea2eSYinan Xu        hasWFI := true.B
439b6900d94SYinan Xu      }
440e4f69d78Ssfencevma
441780712aaSxiaofeibao-xjtu      robEntries(enqIndex).mmio := false.B
442780712aaSxiaofeibao-xjtu      robEntries(enqIndex).vls := enqUop.vlsInstr
4439aca92b9SYinan Xu    }
4449aca92b9SYinan Xu  }
4453b601ae0SXuan Hu
4463b601ae0SXuan Hu  for (i <- 0 until RenameWidth) {
4473b601ae0SXuan Hu    val enqUop = io.enq.req(i)
4483b601ae0SXuan Hu    when(enqUop.valid && enqUop.bits.blockBackward && io.enq.canAccept) {
4493b601ae0SXuan Hu      hasBlockBackward := true.B
4503b601ae0SXuan Hu    }
4513b601ae0SXuan Hu  }
4523b601ae0SXuan Hu
453a8db15d8Sfdy  val dispatchNum = Mux(io.enq.canAccept, PopCount(io.enq.req.map(req => req.valid && req.bits.firstUop)), 0.U)
45475b25016SYinan Xu  io.enq.isEmpty := RegNext(isEmpty && !VecInit(io.enq.req.map(_.valid)).asUInt.orR)
4559aca92b9SYinan Xu
45609309bdbSYinan Xu  when(!io.wfi_enable) {
45709309bdbSYinan Xu    hasWFI := false.B
45809309bdbSYinan Xu  }
4594aa9ed34Sfdy  // sel vsetvl's flush position
4604aa9ed34Sfdy  val vs_idle :: vs_waitVinstr :: vs_waitFlush :: Nil = Enum(3)
4614aa9ed34Sfdy  val vsetvlState = RegInit(vs_idle)
4624aa9ed34Sfdy
4634aa9ed34Sfdy  val firstVInstrFtqPtr = RegInit(0.U.asTypeOf(new FtqPtr))
4644aa9ed34Sfdy  val firstVInstrFtqOffset = RegInit(0.U.asTypeOf(UInt(log2Up(PredictWidth).W)))
4654aa9ed34Sfdy  val firstVInstrRobIdx = RegInit(0.U.asTypeOf(new RobPtr))
4664aa9ed34Sfdy
4674aa9ed34Sfdy  val enq0 = io.enq.req(0)
468d91483a6Sfdy  val enq0IsVset = enq0.bits.isVset && enq0.bits.lastUop && canEnqueue(0)
4693b739f49SXuan Hu  val enq0IsVsetFlush = enq0IsVset && enq0.bits.flushPipe
470239413e5SXuan Hu  val enqIsVInstrVec = io.enq.req.zip(canEnqueue).map { case (req, fire) => FuType.isVArith(req.bits.fuType) && fire }
4714aa9ed34Sfdy  // for vs_idle
4724aa9ed34Sfdy  val firstVInstrIdle = PriorityMux(enqIsVInstrVec.zip(io.enq.req).drop(1) :+ (true.B, 0.U.asTypeOf(io.enq.req(0).cloneType)))
4734aa9ed34Sfdy  // for vs_waitVinstr
4744aa9ed34Sfdy  val enqIsVInstrOrVset = (enqIsVInstrVec(0) || enq0IsVset) +: enqIsVInstrVec.drop(1)
4754aa9ed34Sfdy  val firstVInstrWait = PriorityMux(enqIsVInstrOrVset, io.enq.req)
4764aa9ed34Sfdy  when(vsetvlState === vs_idle) {
4773b739f49SXuan Hu    firstVInstrFtqPtr := firstVInstrIdle.bits.ftqPtr
4783b739f49SXuan Hu    firstVInstrFtqOffset := firstVInstrIdle.bits.ftqOffset
4794aa9ed34Sfdy    firstVInstrRobIdx := firstVInstrIdle.bits.robIdx
4804aa9ed34Sfdy  }.elsewhen(vsetvlState === vs_waitVinstr) {
481a8db15d8Sfdy    when(Cat(enqIsVInstrOrVset).orR) {
4823b739f49SXuan Hu      firstVInstrFtqPtr := firstVInstrWait.bits.ftqPtr
4833b739f49SXuan Hu      firstVInstrFtqOffset := firstVInstrWait.bits.ftqOffset
4844aa9ed34Sfdy      firstVInstrRobIdx := firstVInstrWait.bits.robIdx
4854aa9ed34Sfdy    }
486a8db15d8Sfdy  }
4874aa9ed34Sfdy
4884aa9ed34Sfdy  val hasVInstrAfterI = Cat(enqIsVInstrVec(0)).orR
489a8db15d8Sfdy  when(vsetvlState === vs_idle && !io.redirect.valid) {
4904aa9ed34Sfdy    when(enq0IsVsetFlush) {
4914aa9ed34Sfdy      vsetvlState := Mux(hasVInstrAfterI, vs_waitFlush, vs_waitVinstr)
4924aa9ed34Sfdy    }
4934aa9ed34Sfdy  }.elsewhen(vsetvlState === vs_waitVinstr) {
4944aa9ed34Sfdy    when(io.redirect.valid) {
4954aa9ed34Sfdy      vsetvlState := vs_idle
4964aa9ed34Sfdy    }.elsewhen(Cat(enqIsVInstrOrVset).orR) {
4974aa9ed34Sfdy      vsetvlState := vs_waitFlush
4984aa9ed34Sfdy    }
4994aa9ed34Sfdy  }.elsewhen(vsetvlState === vs_waitFlush) {
5004aa9ed34Sfdy    when(io.redirect.valid) {
5014aa9ed34Sfdy      vsetvlState := vs_idle
5024aa9ed34Sfdy    }
5034aa9ed34Sfdy  }
50409309bdbSYinan Xu
505d2b20d1aSTang Haojin  // lqEnq
506d2b20d1aSTang Haojin  io.debugEnqLsq.needAlloc.map(_(0)).zip(io.debugEnqLsq.req).foreach { case (alloc, req) =>
507d2b20d1aSTang Haojin    when(io.debugEnqLsq.canAccept && alloc && req.valid) {
508d2b20d1aSTang Haojin      debug_microOp(req.bits.robIdx.value).lqIdx := req.bits.lqIdx
509d2b20d1aSTang Haojin      debug_lqIdxValid(req.bits.robIdx.value) := true.B
510d2b20d1aSTang Haojin    }
511d2b20d1aSTang Haojin  }
512d2b20d1aSTang Haojin
513d2b20d1aSTang Haojin  // lsIssue
514d2b20d1aSTang Haojin  when(io.debugHeadLsIssue) {
515d2b20d1aSTang Haojin    debug_lsIssued(deqPtr.value) := true.B
516d2b20d1aSTang Haojin  }
517d2b20d1aSTang Haojin
5189aca92b9SYinan Xu  /**
5199aca92b9SYinan Xu   * Writeback (from execution units)
5209aca92b9SYinan Xu   */
5213b739f49SXuan Hu  for (wb <- exuWBs) {
5223b739f49SXuan Hu    val wbIdx = wb.bits.robIdx.value
5238b33cd30Sklin02    val debug_Uop = debug_microOp(wbIdx)
5248b33cd30Sklin02    when(wb.valid) {
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))
5358b33cd30Sklin02    }
5368b33cd30Sklin02    XSInfo(wb.valid,
5373b739f49SXuan Hu      p"writebacked pc 0x${Hexadecimal(debug_Uop.pc)} wen ${debug_Uop.rfWen} " +
538618b89e6Slewislzh        p"data 0x${Hexadecimal(wb.bits.data(0))} ldst ${debug_Uop.ldest} pdst ${debug_Uop.pdest} " +
539bb76fc1bSYanqin Li        p"skip ${wb.bits.debug.isSkipDiff} robIdx: ${wb.bits.robIdx}\n"
5409aca92b9SYinan Xu    )
5419aca92b9SYinan Xu  }
5423b739f49SXuan Hu
5433b739f49SXuan Hu  val writebackNum = PopCount(exuWBs.map(_.valid))
5449aca92b9SYinan Xu  XSInfo(writebackNum =/= 0.U, "writebacked %d insts\n", writebackNum)
5459aca92b9SYinan Xu
546e4f69d78Ssfencevma  for (i <- 0 until LoadPipelineWidth) {
547e4f69d78Ssfencevma    when(RegNext(io.lsq.mmio(i))) {
548780712aaSxiaofeibao-xjtu      robEntries(RegEnable(io.lsq.uop(i).robIdx, io.lsq.mmio(i)).value).mmio := true.B
549e4f69d78Ssfencevma    }
550e4f69d78Ssfencevma  }
5519aca92b9SYinan Xu
552780712aaSxiaofeibao-xjtu
5539aca92b9SYinan Xu  /**
5549aca92b9SYinan Xu   * RedirectOut: Interrupt and Exceptions
5559aca92b9SYinan Xu   */
5569aca92b9SYinan Xu  val debug_deqUop = debug_microOp(deqPtr.value)
5579aca92b9SYinan Xu
55822b25a0eSGuanghui Cheng  val deqPtrEntry = rawInfo(0)
559571677c9Sxiaofeibao-xjtu  val deqPtrEntryValid = deqPtrEntry.commit_v
560c1ebb150STang Haojin  val deqHasFlushed = RegInit(false.B)
5619aca92b9SYinan Xu  val intrBitSetReg = RegNext(io.csr.intrBitSet)
562c1ebb150STang Haojin  val intrEnable = intrBitSetReg && !hasWaitForward && deqPtrEntry.interrupt_safe && !deqHasFlushed
563571677c9Sxiaofeibao-xjtu  val deqNeedFlush = deqPtrEntry.needFlush && deqPtrEntry.commit_v && deqPtrEntry.commit_w
564571677c9Sxiaofeibao-xjtu  val deqHitExceptionGenState = exceptionDataRead.valid && exceptionDataRead.bits.robIdx === deqPtr
565571677c9Sxiaofeibao-xjtu  val deqNeedFlushAndHitExceptionGenState = deqNeedFlush && deqHitExceptionGenState
5667e0f64b0SGuanghui Cheng  val exceptionGenStateIsException = exceptionDataRead.bits.exceptionVec.asUInt.orR || exceptionDataRead.bits.singleStep || TriggerAction.isDmode(exceptionDataRead.bits.trigger)
56702addab3Sxiaofeibao  val deqHasException = deqNeedFlushAndHitExceptionGenState && exceptionGenStateIsException && (!deqPtrEntry.isVls || RegNext(RegNext(deqPtrEntry.commit_w)))
568c0355297SAnzooooo  val deqHasFlushPipe = deqNeedFlushAndHitExceptionGenState && exceptionDataRead.bits.flushPipe && !deqHasException && (!deqPtrEntry.isVls || RegNext(RegNext(deqPtrEntry.commit_w)))
569571677c9Sxiaofeibao-xjtu  val deqHasReplayInst = deqNeedFlushAndHitExceptionGenState && exceptionDataRead.bits.replayInst
57011bd888fSXuan Hu  val deqIsVlsException = deqHasException && deqPtrEntry.isVls && !exceptionDataRead.bits.isEnqExcp
571fd33b932Sxiaofeibao  // delay 2 cycle wait exceptionGen out
572ddb49062SXuan Hu  // vls exception can be committed only when RAB commit all its reg pairs
573ddb49062SXuan Hu  deqVlsCanCommit := RegNext(RegNext(deqIsVlsException && deqPtrEntry.commit_w)) && rab.io.status.commitEnd
574ea2894c8SXuan Hu
575ea2894c8SXuan Hu  // lock at assertion of deqVlsExceptionNeedCommit until condition not assert
576ea2894c8SXuan Hu  val deqVlsExcpLock = RegInit(false.B)
57775dea01aSXuan Hu  val handleVlsExcp = deqIsVlsException && deqVlsCanCommit && !deqVlsExcpLock && state === s_idle
57875dea01aSXuan Hu  when(handleVlsExcp) {
579ea2894c8SXuan Hu    deqVlsExcpLock := true.B
580ea2894c8SXuan Hu  }.elsewhen(deqPtrVec.head =/= deqPtrVec_next.head) {
581ea2894c8SXuan Hu    deqVlsExcpLock := false.B
582ea2894c8SXuan Hu  }
583ea2894c8SXuan Hu
584ea2894c8SXuan Hu  // Only assert once when deqVlsExcp occurs until condition not assert to avoid multi message passed to RAB
585ea2894c8SXuan Hu  when (deqVlsExceptionNeedCommit) {
586ea2894c8SXuan Hu    deqVlsExceptionNeedCommit := false.B
58775dea01aSXuan Hu  }.elsewhen(handleVlsExcp){
588fd33b932Sxiaofeibao    deqVlsExceptionCommitSize := deqPtrEntry.realDestSize
589fd33b932Sxiaofeibao    deqVlsExceptionNeedCommit := true.B
590fd33b932Sxiaofeibao  }
59172951335SLi Qianruo
59284e47f35SLi Qianruo  XSDebug(deqHasException && exceptionDataRead.bits.singleStep, "Debug Mode: Deq has singlestep exception\n")
5937e0f64b0SGuanghui Cheng  XSDebug(deqHasException && TriggerAction.isDmode(exceptionDataRead.bits.trigger), "Debug Mode: Deq has trigger entry debug Mode\n")
59484e47f35SLi Qianruo
595571677c9Sxiaofeibao-xjtu  val isFlushPipe = deqPtrEntry.commit_w && (deqHasFlushPipe || deqHasReplayInst)
5969aca92b9SYinan Xu
597c9c4960fSZiyue Zhang  // vsetvl instruction need another one cycle to write to vtype gen
598c9c4960fSZiyue Zhang  val isVsetFlushPipe = deqPtrEntry.commit_w && deqHasFlushed && exceptionDataRead.bits.isVset
599c9c4960fSZiyue Zhang  val isVsetFlushPipeReg = RegNext(isVsetFlushPipe)
600a8db15d8Sfdy  //  val needModifyFtqIdxOffset = isVsetFlushPipe && (vsetvlState === vs_waitFlush)
601a8db15d8Sfdy  val needModifyFtqIdxOffset = false.B
602a8db15d8Sfdy  io.isVsetFlushPipe := isVsetFlushPipe
603c9c4960fSZiyue Zhang  io.toDecode.isResumeVType := vtypeBuffer.io.toDecode.isResumeVType || isVsetFlushPipeReg
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
61022b25a0eSGuanghui Cheng  io.flushOut.bits.isRVC := deqPtrEntry.isRVC
6114aa9ed34Sfdy  io.flushOut.bits.robIdx := Mux(needModifyFtqIdxOffset, firstVInstrRobIdx, deqPtr)
61222b25a0eSGuanghui Cheng  io.flushOut.bits.ftqIdx := Mux(needModifyFtqIdxOffset, firstVInstrFtqPtr, deqPtrEntry.ftqIdx)
61322b25a0eSGuanghui Cheng  io.flushOut.bits.ftqOffset := Mux(needModifyFtqIdxOffset, firstVInstrFtqOffset, deqPtrEntry.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
616e836c770SZhaoyang You  XSPerfAccumulate("flush_num", io.flushOut.valid)
6179aca92b9SYinan Xu  XSPerfAccumulate("interrupt_num", io.flushOut.valid && intrEnable)
618571677c9Sxiaofeibao-xjtu  XSPerfAccumulate("exception_num", io.flushOut.valid && deqHasException)
6199aca92b9SYinan Xu  XSPerfAccumulate("flush_pipe_num", io.flushOut.valid && isFlushPipe)
6209aca92b9SYinan Xu  XSPerfAccumulate("replay_inst_num", io.flushOut.valid && isFlushPipe && deqHasReplayInst)
6219aca92b9SYinan Xu
622c0355297SAnzooooo  val exceptionHappen = (state === s_idle) && deqPtrEntryValid && (intrEnable || deqHasException && (!deqIsVlsException || deqVlsCanCommit)) && !lastCycleFlush
6239aca92b9SYinan Xu  io.exception.valid := RegNext(exceptionHappen)
6243b739f49SXuan Hu  io.exception.bits.pc := RegEnable(debug_deqUop.pc, exceptionHappen)
625ad415ae0SXiaokun-Pei  io.exception.bits.gpaddr := io.readGPAMemData.gpaddr
626ad415ae0SXiaokun-Pei  io.exception.bits.isForVSnonLeafPTE := io.readGPAMemData.isForVSnonLeafPTE
6273b739f49SXuan Hu  io.exception.bits.instr := RegEnable(debug_deqUop.instr, exceptionHappen)
62822b25a0eSGuanghui Cheng  io.exception.bits.commitType := RegEnable(deqPtrEntry.commitType, exceptionHappen)
6293b739f49SXuan Hu  io.exception.bits.exceptionVec := RegEnable(exceptionDataRead.bits.exceptionVec, exceptionHappen)
63025742929SXuan Hu  // fetch trigger fire or execute ebreak
63125742929SXuan Hu  io.exception.bits.isPcBkpt := RegEnable(
63225742929SXuan Hu    exceptionDataRead.bits.exceptionVec(ExceptionNO.EX_BP) && (
63325742929SXuan Hu      exceptionDataRead.bits.isEnqExcp ||
63425742929SXuan Hu      exceptionDataRead.bits.trigger === TriggerAction.None
63525742929SXuan Hu    ),
636fe52823cSXuan Hu    exceptionHappen,
637fe52823cSXuan Hu  )
638a1d46413STang Haojin  io.exception.bits.isFetchMalAddr := RegEnable(exceptionDataRead.bits.isFetchMalAddr && deqHasException, exceptionHappen)
6393b739f49SXuan Hu  io.exception.bits.singleStep := RegEnable(exceptionDataRead.bits.singleStep, exceptionHappen)
6403b739f49SXuan Hu  io.exception.bits.crossPageIPFFix := RegEnable(exceptionDataRead.bits.crossPageIPFFix, exceptionHappen)
6419aca92b9SYinan Xu  io.exception.bits.isInterrupt := RegEnable(intrEnable, exceptionHappen)
64222b25a0eSGuanghui Cheng  io.exception.bits.isHls := RegEnable(deqPtrEntry.isHls, exceptionHappen)
64322b25a0eSGuanghui Cheng  io.exception.bits.vls := RegEnable(deqPtrEntry.vls, exceptionHappen)
644f7af4c74Schengguanghui  io.exception.bits.trigger := RegEnable(exceptionDataRead.bits.trigger, exceptionHappen)
6459aca92b9SYinan Xu
6466f483f86SXuan Hu  // data will be one cycle after valid
6476f483f86SXuan Hu  io.readGPAMemAddr.valid := exceptionHappen
6486f483f86SXuan Hu  io.readGPAMemAddr.bits.ftqPtr := exceptionDataRead.bits.ftqPtr
6496f483f86SXuan Hu  io.readGPAMemAddr.bits.ftqOffset := exceptionDataRead.bits.ftqOffset
6506f483f86SXuan Hu
6519aca92b9SYinan Xu  XSDebug(io.flushOut.valid,
6523b739f49SXuan Hu    p"generate redirect: pc 0x${Hexadecimal(io.exception.bits.pc)} intr $intrEnable " +
653571677c9Sxiaofeibao-xjtu      p"excp $deqHasException flushPipe $isFlushPipe " +
654c1b28b66STang Haojin      p"Trap_target 0x${Hexadecimal(io.csr.trapTarget.pc)} exceptionVec ${Binary(exceptionDataRead.bits.exceptionVec.asUInt)}\n")
6559aca92b9SYinan Xu
6569aca92b9SYinan Xu
6579aca92b9SYinan Xu  /**
6589aca92b9SYinan Xu   * Commits (and walk)
6599aca92b9SYinan Xu   * They share the same width.
6609aca92b9SYinan Xu   */
661780712aaSxiaofeibao-xjtu  // T redirect.valid, T+1 use walkPtrVec read robEntries, T+2 start walk, shouldWalkVec used in T+2
662780712aaSxiaofeibao-xjtu  val shouldWalkVec = Wire(Vec(CommitWidth,Bool()))
663780712aaSxiaofeibao-xjtu  val walkingPtrVec = RegNext(walkPtrVec)
664780712aaSxiaofeibao-xjtu  when(io.redirect.valid){
665780712aaSxiaofeibao-xjtu    shouldWalkVec := 0.U.asTypeOf(shouldWalkVec)
666780712aaSxiaofeibao-xjtu  }.elsewhen(RegNext(io.redirect.valid)){
667780712aaSxiaofeibao-xjtu    shouldWalkVec := 0.U.asTypeOf(shouldWalkVec)
668780712aaSxiaofeibao-xjtu  }.elsewhen(state === s_walk){
669780712aaSxiaofeibao-xjtu    shouldWalkVec := VecInit(walkingPtrVec.map(_ <= lastWalkPtr).zip(donotNeedWalk).map(x => x._1 && !x._2))
670780712aaSxiaofeibao-xjtu  }.otherwise(
671780712aaSxiaofeibao-xjtu    shouldWalkVec := 0.U.asTypeOf(shouldWalkVec)
672780712aaSxiaofeibao-xjtu  )
673c0f8424bSzhanglyGit  val walkFinished = walkPtrTrue > lastWalkPtr
67465f65924SXuan Hu  rab.io.fromRob.walkEnd := state === s_walk && walkFinished
6754c7680e0SXuan Hu  vtypeBuffer.io.fromRob.walkEnd := state === s_walk && walkFinished
6769aca92b9SYinan Xu
6779aca92b9SYinan Xu  require(RenameWidth <= CommitWidth)
6789aca92b9SYinan Xu
6799aca92b9SYinan Xu  // wiring to csr
680f1ba628bSHaojin Tang  val (wflags, dirtyFs) = (0 until CommitWidth).map(i => {
6816474c47fSYinan Xu    val v = io.commits.commitValid(i)
6829aca92b9SYinan Xu    val info = io.commits.info(i)
683780712aaSxiaofeibao-xjtu    (v & info.wflags, v & info.dirtyFs)
6849aca92b9SYinan Xu  }).unzip
6859aca92b9SYinan Xu  val fflags = Wire(Valid(UInt(5.W)))
6866474c47fSYinan Xu  fflags.valid := io.commits.isCommit && VecInit(wflags).asUInt.orR
6879aca92b9SYinan Xu  fflags.bits := wflags.zip(fflagsDataRead).map({
6889aca92b9SYinan Xu    case (w, f) => Mux(w, f, 0.U)
6899aca92b9SYinan Xu  }).reduce(_ | _)
6903af3539fSZiyue Zhang  val dirtyVs = (0 until CommitWidth).map(i => {
6913af3539fSZiyue Zhang    val v = io.commits.commitValid(i)
6923af3539fSZiyue Zhang    val info = io.commits.info(i)
6933af3539fSZiyue Zhang    v & info.dirtyVs
6943af3539fSZiyue Zhang  })
695f1ba628bSHaojin Tang  val dirty_fs = io.commits.isCommit && VecInit(dirtyFs).asUInt.orR
6963af3539fSZiyue Zhang  val dirty_vs = io.commits.isCommit && VecInit(dirtyVs).asUInt.orR
6979aca92b9SYinan Xu
6985110577fSZiyue Zhang  val resetVstart = dirty_vs && !io.vstartIsZero
6995110577fSZiyue Zhang
7007876e679STang Haojin  vecExcpInfo.valid := exceptionHappen && !intrEnable && exceptionDataRead.bits.vstartEn && exceptionDataRead.bits.isVecLoad && !exceptionDataRead.bits.isEnqExcp
701e43bb916SXuan Hu  when (exceptionHappen) {
702e43bb916SXuan Hu    vecExcpInfo.bits.nf := exceptionDataRead.bits.nf
703e43bb916SXuan Hu    vecExcpInfo.bits.vsew := exceptionDataRead.bits.vsew
704e43bb916SXuan Hu    vecExcpInfo.bits.veew := exceptionDataRead.bits.veew
705e43bb916SXuan Hu    vecExcpInfo.bits.vlmul := exceptionDataRead.bits.vlmul
706e43bb916SXuan Hu    vecExcpInfo.bits.isStride := exceptionDataRead.bits.isStrided
707e43bb916SXuan Hu    vecExcpInfo.bits.isIndexed := exceptionDataRead.bits.isIndexed
708e43bb916SXuan Hu    vecExcpInfo.bits.isWhole := exceptionDataRead.bits.isWhole
709e43bb916SXuan Hu    vecExcpInfo.bits.isVlm := exceptionDataRead.bits.isVlm
710e43bb916SXuan Hu    vecExcpInfo.bits.vstart := exceptionDataRead.bits.vstart
711e43bb916SXuan Hu  }
712e43bb916SXuan Hu
7130d134565SZiyue Zhang  io.csr.vstart.valid := RegNext(Mux(exceptionHappen && deqHasException, exceptionDataRead.bits.vstartEn, resetVstart))
7140d134565SZiyue Zhang  io.csr.vstart.bits := RegNext(Mux(exceptionHappen && deqHasException, exceptionDataRead.bits.vstart, 0.U))
7155110577fSZiyue Zhang
716a8db15d8Sfdy  val vxsat = Wire(Valid(Bool()))
717a8db15d8Sfdy  vxsat.valid := io.commits.isCommit && vxsat.bits
718a8db15d8Sfdy  vxsat.bits := io.commits.commitValid.zip(vxsatDataRead).map {
719a8db15d8Sfdy    case (valid, vxsat) => valid & vxsat
720a8db15d8Sfdy  }.reduce(_ | _)
721a8db15d8Sfdy
7229aca92b9SYinan Xu  // when mispredict branches writeback, stop commit in the next 2 cycles
7239aca92b9SYinan Xu  // TODO: don't check all exu write back
7243b739f49SXuan Hu  val misPredWb = Cat(VecInit(redirectWBs.map(wb =>
7252f2ee3b1SXuan Hu    wb.bits.redirect.get.bits.cfiUpdate.isMisPred && wb.bits.redirect.get.valid && wb.valid
72683ba63b3SXuan Hu  ).toSeq)).orR
7279aca92b9SYinan Xu  val misPredBlockCounter = Reg(UInt(3.W))
7289aca92b9SYinan Xu  misPredBlockCounter := Mux(misPredWb,
7299aca92b9SYinan Xu    "b111".U,
7309aca92b9SYinan Xu    misPredBlockCounter >> 1.U
7319aca92b9SYinan Xu  )
7329aca92b9SYinan Xu  val misPredBlock = misPredBlockCounter(0)
733571677c9Sxiaofeibao-xjtu  val deqFlushBlockCounter = Reg(UInt(3.W))
734571677c9Sxiaofeibao-xjtu  val deqFlushBlock = deqFlushBlockCounter(0)
7357c24a7e1Sxiaofeibao  val deqHasCommitted = io.commits.isCommit && io.commits.commitValid(0)
73635477a7aSAnzo  // TODO *** WARNING ***
73735477a7aSAnzo  // Blocking commit. Don't change this before we fully understand the logic.
73835477a7aSAnzo  val deqHitRedirectReg = RegNext(io.redirect.valid && io.redirect.bits.robIdx === deqPtr) || RegNext(RegNext(io.redirect.valid && io.redirect.bits.robIdx === deqPtr))
739a751b11aSchengguanghui  val criticalErrorState = io.csr.criticalErrorState
740571677c9Sxiaofeibao-xjtu  when(deqNeedFlush && deqHitRedirectReg){
741571677c9Sxiaofeibao-xjtu    deqFlushBlockCounter := "b111".U
742571677c9Sxiaofeibao-xjtu  }.otherwise{
743571677c9Sxiaofeibao-xjtu    deqFlushBlockCounter := deqFlushBlockCounter >> 1.U
744571677c9Sxiaofeibao-xjtu  }
7457c24a7e1Sxiaofeibao  when(deqHasCommitted){
746571677c9Sxiaofeibao-xjtu    deqHasFlushed := false.B
7478b9535b8STang Haojin  }.elsewhen(deqNeedFlush && io.flushOut.valid && !io.flushOut.bits.flushItself()){
7487c24a7e1Sxiaofeibao    deqHasFlushed := true.B
749571677c9Sxiaofeibao-xjtu  }
7504907ec88Schengguanghui  val traceBlock = io.trace.blockCommit
75185a8d7caSZehao Liu  val blockCommit = misPredBlock || lastCycleFlush || hasWFI || io.redirect.valid ||
7524907ec88Schengguanghui    (deqNeedFlush && !deqHasFlushed) || deqFlushBlock || criticalErrorState || traceBlock
7539aca92b9SYinan Xu
754ccfddc82SHaojin Tang  io.commits.isWalk := state === s_walk
7556474c47fSYinan Xu  io.commits.isCommit := state === s_idle && !blockCommit
756780712aaSxiaofeibao-xjtu
757780712aaSxiaofeibao-xjtu  val walk_v = VecInit(walkingPtrVec.map(ptr => robEntries(ptr.value).valid))
758780712aaSxiaofeibao-xjtu  val commit_vDeqGroup = VecInit(robDeqGroup.map(_.commit_v))
759780712aaSxiaofeibao-xjtu  val commit_wDeqGroup = VecInit(robDeqGroup.map(_.commit_w))
760780712aaSxiaofeibao-xjtu  val realCommitLast = deqPtrVec(0).lineHeadPtr + Fill(bankAddrWidth, 1.U)
761780712aaSxiaofeibao-xjtu  val commit_block = VecInit((0 until CommitWidth).map(i => !commit_wDeqGroup(i) && !hasCommitted(i)))
762571677c9Sxiaofeibao-xjtu  val allowOnlyOneCommit = VecInit(robDeqGroup.map(x => x.commit_v && x.needFlush)).asUInt.orR || intrBitSetReg
7639aca92b9SYinan Xu  // for instructions that may block others, we don't allow them to commit
764780712aaSxiaofeibao-xjtu  io.commits.commitValid := PriorityMux(commitValidThisLine, (0 until CommitWidth).map(i => (commitValidThisLine.asUInt >> i).asUInt.asTypeOf(io.commits.commitValid)))
765571677c9Sxiaofeibao-xjtu
7669aca92b9SYinan Xu  for (i <- 0 until CommitWidth) {
7679aca92b9SYinan Xu    // defaults: state === s_idle and instructions commit
7689aca92b9SYinan Xu    // when intrBitSetReg, allow only one instruction to commit at each clock cycle
76939112cdaSxiaofeibao    val isBlocked = intrEnable || (deqNeedFlush && !deqHasFlushed)
770780712aaSxiaofeibao-xjtu    val isBlockedByOlder = if (i != 0) commit_block.asUInt(i, 0).orR || allowOnlyOneCommit && !hasCommitted.asUInt(i - 1, 0).andR else false.B
771780712aaSxiaofeibao-xjtu    commitValidThisLine(i) := commit_vDeqGroup(i) && commit_wDeqGroup(i) && !isBlocked && !isBlockedByOlder && !hasCommitted(i)
772780712aaSxiaofeibao-xjtu    io.commits.info(i) := commitInfo(i)
773fa7f2c26STang Haojin    io.commits.robIdx(i) := deqPtrVec(i)
7741592abd1SYan Xu    val deqDebugInst = debug_microOp(deqPtrVec(i).value)
7751592abd1SYan Xu    PerfCCT.commitInstMeta(i.U, deqDebugInst.debug_seqNum, deqDebugInst.instrSize, io.commits.isCommit && io.commits.commitValid(i), clock, reset)
7769aca92b9SYinan Xu
7776474c47fSYinan Xu    io.commits.walkValid(i) := shouldWalkVec(i)
7788b33cd30Sklin02    XSError(
7798b33cd30Sklin02      state === s_walk &&
7808b33cd30Sklin02      io.commits.isWalk && state === s_walk && shouldWalkVec(i) &&
7818b33cd30Sklin02      !walk_v(i),
7828b33cd30Sklin02      s"The walking entry($i) should be valid\n")
7839aca92b9SYinan Xu
7846474c47fSYinan Xu    XSInfo(io.commits.isCommit && io.commits.commitValid(i),
785c61abc0cSXuan Hu      "retired pc %x wen %d ldest %d pdest %x data %x fflags: %b vxsat: %b\n",
7863b739f49SXuan Hu      debug_microOp(deqPtrVec(i).value).pc,
7879aca92b9SYinan Xu      io.commits.info(i).rfWen,
788780712aaSxiaofeibao-xjtu      io.commits.info(i).debug_ldest.getOrElse(0.U),
789780712aaSxiaofeibao-xjtu      io.commits.info(i).debug_pdest.getOrElse(0.U),
7909aca92b9SYinan Xu      debug_exuData(deqPtrVec(i).value),
791a8db15d8Sfdy      fflagsDataRead(i),
792a8db15d8Sfdy      vxsatDataRead(i)
7939aca92b9SYinan Xu    )
7946474c47fSYinan Xu    XSInfo(state === s_walk && io.commits.walkValid(i), "walked pc %x wen %d ldst %d data %x\n",
7953b739f49SXuan Hu      debug_microOp(walkPtrVec(i).value).pc,
7969aca92b9SYinan Xu      io.commits.info(i).rfWen,
797780712aaSxiaofeibao-xjtu      io.commits.info(i).debug_ldest.getOrElse(0.U),
7989aca92b9SYinan Xu      debug_exuData(walkPtrVec(i).value)
7999aca92b9SYinan Xu    )
8009aca92b9SYinan Xu  }
8019aca92b9SYinan Xu
802a8db15d8Sfdy  // sync fflags/dirty_fs/vxsat to csr
803056ddc44SXuan Hu  io.csr.fflags   := RegNextWithEnable(fflags)
804056ddc44SXuan Hu  io.csr.dirty_fs := GatedValidRegNext(dirty_fs)
805056ddc44SXuan Hu  io.csr.dirty_vs := GatedValidRegNext(dirty_vs)
806056ddc44SXuan Hu  io.csr.vxsat    := RegNextWithEnable(vxsat)
8079aca92b9SYinan Xu
8089aca92b9SYinan Xu  // commit load/store to lsq
8096474c47fSYinan Xu  val ldCommitVec = VecInit((0 until CommitWidth).map(i => io.commits.commitValid(i) && io.commits.info(i).commitType === CommitType.LOAD))
81086c54d62SXuan Hu  // TODO: Check if meet the require that only set scommit when commit scala store uop
81125df626eSgood-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 ))
8126474c47fSYinan Xu  io.lsq.lcommit := RegNext(Mux(io.commits.isCommit, PopCount(ldCommitVec), 0.U))
8136474c47fSYinan Xu  io.lsq.scommit := RegNext(Mux(io.commits.isCommit, PopCount(stCommitVec), 0.U))
8146474c47fSYinan Xu  // indicate a pending load or store
81522b25a0eSGuanghui Cheng  io.lsq.pendingMMIOld := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.LOAD && deqPtrEntryValid && deqPtrEntry.mmio)
81622b25a0eSGuanghui Cheng  io.lsq.pendingld := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.LOAD && deqPtrEntryValid)
817552da88aSXuan Hu  // TODO: Check if need deassert pendingst when it is vst
81822b25a0eSGuanghui Cheng  io.lsq.pendingst := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.STORE && deqPtrEntryValid)
819552da88aSXuan Hu  // TODO: Check if set correctly when vector store is at the head of ROB
82022b25a0eSGuanghui Cheng  io.lsq.pendingVst := RegNext(io.commits.isCommit && io.commits.info(0).commitType === CommitType.STORE && deqPtrEntryValid && deqPtrEntry.vls)
8216474c47fSYinan Xu  io.lsq.commit := RegNext(io.commits.isCommit && io.commits.commitValid(0))
822e4f69d78Ssfencevma  io.lsq.pendingPtr := RegNext(deqPtr)
82320a5248fSzhanglinjuan  io.lsq.pendingPtrNext := RegNext(deqPtrVec_next.head)
8249aca92b9SYinan Xu
8259aca92b9SYinan Xu  /**
8269aca92b9SYinan Xu   * state changes
827ccfddc82SHaojin Tang   * (1) redirect: switch to s_walk
828ccfddc82SHaojin Tang   * (2) walk: when walking comes to the end, switch to s_idle
8299aca92b9SYinan Xu   */
830ea2894c8SXuan Hu  state_next := Mux(
831780712aaSxiaofeibao-xjtu    io.redirect.valid || RegNext(io.redirect.valid), s_walk,
8324c7680e0SXuan Hu    Mux(
8334c7680e0SXuan Hu      state === s_walk && walkFinished && rab.io.status.walkEnd && vtypeBuffer.io.status.walkEnd, s_idle,
8344c7680e0SXuan Hu      state
8354c7680e0SXuan Hu    )
8364c7680e0SXuan Hu  )
8377e8294acSYinan Xu  XSPerfAccumulate("s_idle_to_idle", state === s_idle && state_next === s_idle)
8387e8294acSYinan Xu  XSPerfAccumulate("s_idle_to_walk", state === s_idle && state_next === s_walk)
8397e8294acSYinan Xu  XSPerfAccumulate("s_walk_to_idle", state === s_walk && state_next === s_idle)
8407e8294acSYinan Xu  XSPerfAccumulate("s_walk_to_walk", state === s_walk && state_next === s_walk)
8419aca92b9SYinan Xu  state := state_next
8429aca92b9SYinan Xu
8439aca92b9SYinan Xu  /**
8449aca92b9SYinan Xu   * pointers and counters
8459aca92b9SYinan Xu   */
846780712aaSxiaofeibao-xjtu  val deqPtrGenModule = Module(new NewRobDeqPtrWrapper)
8479aca92b9SYinan Xu  deqPtrGenModule.io.state := state
848cda1c534Sxiaofeibao-xjtu  deqPtrGenModule.io.deq_v := commit_vDeqGroup
849cda1c534Sxiaofeibao-xjtu  deqPtrGenModule.io.deq_w := commit_wDeqGroup
8509aca92b9SYinan Xu  deqPtrGenModule.io.exception_state := exceptionDataRead
8519aca92b9SYinan Xu  deqPtrGenModule.io.intrBitSetReg := intrBitSetReg
8523b739f49SXuan Hu  deqPtrGenModule.io.hasNoSpecExec := hasWaitForward
853571677c9Sxiaofeibao-xjtu  deqPtrGenModule.io.allowOnlyOneCommit := allowOnlyOneCommit
8541bd36f96Sxiao feibao  deqPtrGenModule.io.interrupt_safe := robDeqGroup(deqPtr.value(bankAddrWidth-1,0)).interrupt_safe
8556474c47fSYinan Xu  deqPtrGenModule.io.blockCommit := blockCommit
856780712aaSxiaofeibao-xjtu  deqPtrGenModule.io.hasCommitted := hasCommitted
857780712aaSxiaofeibao-xjtu  deqPtrGenModule.io.allCommitted := allCommitted
8589aca92b9SYinan Xu  deqPtrVec := deqPtrGenModule.io.out
85920a5248fSzhanglinjuan  deqPtrVec_next := deqPtrGenModule.io.next_out
8609aca92b9SYinan Xu
8619aca92b9SYinan Xu  val enqPtrGenModule = Module(new RobEnqPtrWrapper)
8629aca92b9SYinan Xu  enqPtrGenModule.io.redirect := io.redirect
863b9a37d2fSXuan Hu  enqPtrGenModule.io.allowEnqueue := allowEnqueue && rab.io.canEnq && !io.fromVecExcpMod.busy
8649aca92b9SYinan Xu  enqPtrGenModule.io.hasBlockBackward := hasBlockBackward
865a8db15d8Sfdy  enqPtrGenModule.io.enq := VecInit(io.enq.req.map(req => req.valid && req.bits.firstUop))
8666474c47fSYinan Xu  enqPtrVec := enqPtrGenModule.io.out
8679aca92b9SYinan Xu
8689aca92b9SYinan Xu  // next walkPtrVec:
8699aca92b9SYinan Xu  // (1) redirect occurs: update according to state
870ccfddc82SHaojin Tang  // (2) walk: move forwards
871780712aaSxiaofeibao-xjtu  val deqPtrReadBank = deqPtrVec_next(0).lineHeadPtr
872780712aaSxiaofeibao-xjtu  val deqPtrVecForWalk = VecInit((0 until CommitWidth).map(i => deqPtrReadBank + i.U))
873780712aaSxiaofeibao-xjtu  val snapPtrReadBank = snapshots(io.snpt.snptSelect)(0).lineHeadPtr
874780712aaSxiaofeibao-xjtu  val snapPtrVecForWalk = VecInit((0 until CommitWidth).map(i => snapPtrReadBank + i.U))
875c0f8424bSzhanglyGit  val walkPtrVec_next: Vec[RobPtr] = Mux(io.redirect.valid,
876780712aaSxiaofeibao-xjtu    Mux(io.snpt.useSnpt, snapPtrVecForWalk, deqPtrVecForWalk),
877780712aaSxiaofeibao-xjtu    Mux((state === s_walk) && !walkFinished, VecInit(walkPtrVec.map(_ + CommitWidth.U)), walkPtrVec)
8789aca92b9SYinan Xu  )
879c0f8424bSzhanglyGit  val walkPtrTrue_next: RobPtr = Mux(io.redirect.valid,
880c0f8424bSzhanglyGit    Mux(io.snpt.useSnpt, snapshots(io.snpt.snptSelect)(0), deqPtrVec_next(0)),
881c0f8424bSzhanglyGit    Mux((state === s_walk) && !walkFinished, walkPtrVec_next.head, walkPtrTrue)
882c0f8424bSzhanglyGit  )
883780712aaSxiaofeibao-xjtu  walkPtrHead := walkPtrVec_next.head
8849aca92b9SYinan Xu  walkPtrVec := walkPtrVec_next
885c0f8424bSzhanglyGit  walkPtrTrue := walkPtrTrue_next
886780712aaSxiaofeibao-xjtu  // T io.redirect.valid, T+1 walkPtrLowBits update, T+2 donotNeedWalk update
887780712aaSxiaofeibao-xjtu  val walkPtrLowBits = Reg(UInt(bankAddrWidth.W))
888780712aaSxiaofeibao-xjtu  when(io.redirect.valid){
889780712aaSxiaofeibao-xjtu    walkPtrLowBits := Mux(io.snpt.useSnpt, snapshots(io.snpt.snptSelect)(0).value(bankAddrWidth-1, 0), deqPtrVec_next(0).value(bankAddrWidth-1, 0))
890780712aaSxiaofeibao-xjtu  }
891780712aaSxiaofeibao-xjtu  when(io.redirect.valid) {
892780712aaSxiaofeibao-xjtu    donotNeedWalk := Fill(donotNeedWalk.length, true.B).asTypeOf(donotNeedWalk)
893780712aaSxiaofeibao-xjtu  }.elsewhen(RegNext(io.redirect.valid)){
894780712aaSxiaofeibao-xjtu    donotNeedWalk := (0 until CommitWidth).map(i => (i.U < walkPtrLowBits))
895c0f8424bSzhanglyGit  }.otherwise{
896780712aaSxiaofeibao-xjtu    donotNeedWalk := 0.U.asTypeOf(donotNeedWalk)
897c0f8424bSzhanglyGit  }
898cda1c534Sxiaofeibao-xjtu  walkDestSizeDeqGroup.zip(walkPtrVec_next).map {
89922b25a0eSGuanghui Cheng    case (reg, ptrNext) => reg := deqPtrEntry.realDestSize
900cda1c534Sxiaofeibao-xjtu  }
90175b25016SYinan Xu  val numValidEntries = distanceBetween(enqPtr, deqPtr)
902a8db15d8Sfdy  val commitCnt = PopCount(io.commits.commitValid)
9039aca92b9SYinan Xu
90435b3b30bSxiaofeibao  allowEnqueue := numValidEntries + dispatchNum <= (RobSize - RenameWidth).U
90535b3b30bSxiaofeibao  allowEnqueueForDispatch := numValidEntries + dispatchNum <= (RobSize - 2 * RenameWidth).U
9069aca92b9SYinan Xu
907ccfddc82SHaojin Tang  val redirectWalkDistance = distanceBetween(io.redirect.bits.robIdx, deqPtrVec_next(0))
9089aca92b9SYinan Xu  when(io.redirect.valid) {
909dcf3a679STang Haojin    lastWalkPtr := Mux(io.redirect.bits.flushItself(), io.redirect.bits.robIdx - 1.U, io.redirect.bits.robIdx)
9109aca92b9SYinan Xu  }
9119aca92b9SYinan Xu
9129aca92b9SYinan Xu
9139aca92b9SYinan Xu  /**
9149aca92b9SYinan Xu   * States
9159aca92b9SYinan Xu   * We put all the stage bits changes here.
916780712aaSxiaofeibao-xjtu   *
9179aca92b9SYinan Xu   * All events: (1) enqueue (dispatch); (2) writeback; (3) cancel; (4) dequeue (commit);
9189aca92b9SYinan Xu   * All states: (1) valid; (2) writebacked; (3) flagBkup
9199aca92b9SYinan Xu   */
920cda1c534Sxiaofeibao-xjtu
921780712aaSxiaofeibao-xjtu  val deqPtrGroup = Wire(Vec(2 * CommitWidth, new RobPtr))
922780712aaSxiaofeibao-xjtu  deqPtrGroup.zipWithIndex.map { case (deq, i) => deq := deqPtrVec(0) + i.U }
9239aca92b9SYinan Xu  val commitReadAddr = Mux(state === s_idle, VecInit(deqPtrVec.map(_.value)), VecInit(walkPtrVec.map(_.value)))
9249aca92b9SYinan Xu
925780712aaSxiaofeibao-xjtu  val redirectValidReg = RegNext(io.redirect.valid)
926780712aaSxiaofeibao-xjtu  val redirectBegin = Reg(UInt(log2Up(RobSize).W))
927780712aaSxiaofeibao-xjtu  val redirectEnd = Reg(UInt(log2Up(RobSize).W))
9282e4f14ffSxiaofeibao  val redirectAll = RegInit(false.B)
929ccfddc82SHaojin Tang  when(io.redirect.valid){
930780712aaSxiaofeibao-xjtu    redirectBegin := Mux(io.redirect.bits.flushItself(), io.redirect.bits.robIdx.value - 1.U, io.redirect.bits.robIdx.value)
931780712aaSxiaofeibao-xjtu    redirectEnd := enqPtr.value
9322e4f14ffSxiaofeibao    redirectAll := io.redirect.bits.flushItself() && (io.redirect.bits.robIdx.value === enqPtr.value) && (io.redirect.bits.robIdx.flag ^ enqPtr.flag)
933ccfddc82SHaojin Tang  }
934780712aaSxiaofeibao-xjtu
935780712aaSxiaofeibao-xjtu  // update robEntries valid
936780712aaSxiaofeibao-xjtu  for (i <- 0 until RobSize) {
937780712aaSxiaofeibao-xjtu    val enqOH = VecInit(canEnqueue.zip(allocatePtrVec.map(_.value === i.U)).map(x => x._1 && x._2))
938780712aaSxiaofeibao-xjtu    val commitCond = io.commits.isCommit && io.commits.commitValid.zip(deqPtrVec.map(_.value === i.U)).map(x => x._1 && x._2).reduce(_ || _)
939780712aaSxiaofeibao-xjtu    assert(PopCount(enqOH) < 2.U, s"robEntries$i enqOH is not one hot")
94015fbca49SZhaoyang You    val needFlush = redirectValidReg && (Mux(
94115fbca49SZhaoyang You      redirectEnd > redirectBegin,
942780712aaSxiaofeibao-xjtu      (i.U > redirectBegin) && (i.U < redirectEnd),
943780712aaSxiaofeibao-xjtu      (i.U > redirectBegin) || (i.U < redirectEnd)
94415fbca49SZhaoyang You    ) || redirectAll)
9456a8b2d5fSxiaofeibao-xjtu    when(commitCond) {
946780712aaSxiaofeibao-xjtu      robEntries(i).valid := false.B
947780712aaSxiaofeibao-xjtu    }.elsewhen(enqOH.asUInt.orR && !io.redirect.valid) {
948780712aaSxiaofeibao-xjtu      robEntries(i).valid := true.B
949780712aaSxiaofeibao-xjtu    }.elsewhen(needFlush){
950780712aaSxiaofeibao-xjtu      robEntries(i).valid := false.B
9519aca92b9SYinan Xu    }
9529aca92b9SYinan Xu  }
9539aca92b9SYinan Xu
9548744445eSMaxpicca-Li  // debug_inst update
955870f462dSXuan Hu  for (i <- 0 until (LduCnt + StaCnt)) {
9568744445eSMaxpicca-Li    debug_lsInfo(io.debug_ls.debugLsInfo(i).s1_robIdx).s1SignalEnable(io.debug_ls.debugLsInfo(i))
9578744445eSMaxpicca-Li    debug_lsInfo(io.debug_ls.debugLsInfo(i).s2_robIdx).s2SignalEnable(io.debug_ls.debugLsInfo(i))
9584d931b73SYanqin Li    debug_lsInfo(io.debug_ls.debugLsInfo(i).s3_robIdx).s3SignalEnable(io.debug_ls.debugLsInfo(i))
9598744445eSMaxpicca-Li  }
960870f462dSXuan Hu  for (i <- 0 until LduCnt) {
961d2b20d1aSTang Haojin    debug_lsTopdownInfo(io.lsTopdownInfo(i).s1.robIdx).s1SignalEnable(io.lsTopdownInfo(i))
962d2b20d1aSTang Haojin    debug_lsTopdownInfo(io.lsTopdownInfo(i).s2.robIdx).s2SignalEnable(io.lsTopdownInfo(i))
963d2b20d1aSTang Haojin  }
9648744445eSMaxpicca-Li
965f7af4c74Schengguanghui  // status field: writebacked
966f7af4c74Schengguanghui  // enqueue logic set 6 writebacked to false
967f7af4c74Schengguanghui
9689aca92b9SYinan Xu  // writeback logic set numWbPorts writebacked to true
969a8db15d8Sfdy
970a8db15d8Sfdy  // if the first uop of an instruction is valid , write writebackedCounter
971a8db15d8Sfdy  val uopEnqValidSeq = io.enq.req.map(req => io.enq.canAccept && req.valid)
972a8db15d8Sfdy  val instEnqValidSeq = io.enq.req.map(req => io.enq.canAccept && req.valid && req.bits.firstUop)
973a8db15d8Sfdy  val enqNeedWriteRFSeq = io.enq.req.map(_.bits.needWriteRf)
974124f6e6aSXuan Hu  val enqHasExcpSeq = io.enq.req.map(_.bits.hasException)
975a8db15d8Sfdy  val enqRobIdxSeq = io.enq.req.map(req => req.bits.robIdx.value)
976f1e8fcb2SXuan Hu  val enqUopNumVec = VecInit(io.enq.req.map(req => req.bits.numUops))
9773235a9d8SZiyue-Zhang  val enqWBNumVec = VecInit(io.enq.req.map(req => req.bits.numWB))
978a8db15d8Sfdy
979f1e8fcb2SXuan Hu  private val enqWriteStdVec: Vec[Bool] = VecInit(io.enq.req.map {
98012861ac7Slinzhida    req => FuType.isStore(req.bits.fuType)
981f1e8fcb2SXuan Hu  })
982cda1c534Sxiaofeibao-xjtu  val fflags_wb = fflagsWBs
983cda1c534Sxiaofeibao-xjtu  val vxsat_wb = vxsatWBs
984a8db15d8Sfdy  for (i <- 0 until RobSize) {
985a8db15d8Sfdy
986a8db15d8Sfdy    val robIdxMatchSeq = io.enq.req.map(_.bits.robIdx.value === i.U)
987a8db15d8Sfdy    val uopCanEnqSeq = uopEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
988a8db15d8Sfdy    val instCanEnqSeq = instEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
989a8db15d8Sfdy    val instCanEnqFlag = Cat(instCanEnqSeq).orR
990124f6e6aSXuan Hu    val hasExcpSeq = enqHasExcpSeq.lazyZip(robIdxMatchSeq).lazyZip(uopEnqValidSeq).map { case (excp, isMatch, valid) => excp && isMatch && valid }
991124f6e6aSXuan Hu    val hasExcpFlag = Cat(hasExcpSeq).orR
9928338e674Sxiaofeibao-xjtu    val isFirstEnq = !robEntries(i).valid && instCanEnqFlag
993780712aaSxiaofeibao-xjtu    val realDestEnqNum = PopCount(enqNeedWriteRFSeq.zip(uopCanEnqSeq).map { case (writeFlag, valid) => writeFlag && valid })
9948338e674Sxiaofeibao-xjtu    when(isFirstEnq){
9950a7d1d5cSxiaofeibao      robEntries(i).realDestSize := realDestEnqNum //Mux(hasExcpFlag, 0.U, realDestEnqNum)
99611a54ccaSsinsanction    }.elsewhen(robEntries(i).valid && Cat(uopCanEnqSeq).orR){
997780712aaSxiaofeibao-xjtu      robEntries(i).realDestSize := robEntries(i).realDestSize + realDestEnqNum
998780712aaSxiaofeibao-xjtu    }
999f1e8fcb2SXuan Hu    val enqUopNum = PriorityMux(instCanEnqSeq, enqUopNumVec)
10003235a9d8SZiyue-Zhang    val enqWBNum = PriorityMux(instCanEnqSeq, enqWBNumVec)
1001f1e8fcb2SXuan Hu    val enqWriteStd = PriorityMux(instCanEnqSeq, enqWriteStdVec)
1002a8db15d8Sfdy
1003a8db15d8Sfdy    val canWbSeq = exuWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U)
1004f1e8fcb2SXuan Hu    val canStdWbSeq = VecInit(stdWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U))
1005571677c9Sxiaofeibao-xjtu    val wbCnt = Mux1H(canWbSeq, io.writebackNums.map(_.bits))
100689cc69c1STang Haojin
1007571677c9Sxiaofeibao-xjtu    val canWbExceptionSeq = exceptionWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U)
1008571677c9Sxiaofeibao-xjtu    val needFlush = robEntries(i).needFlush
1009571677c9Sxiaofeibao-xjtu    val needFlushWriteBack = Wire(Bool())
1010571677c9Sxiaofeibao-xjtu    needFlushWriteBack := Mux1H(canWbExceptionSeq, io.writebackNeedFlush)
1011571677c9Sxiaofeibao-xjtu    when(robEntries(i).valid){
1012571677c9Sxiaofeibao-xjtu      needFlush := needFlush || needFlushWriteBack
1013571677c9Sxiaofeibao-xjtu    }
101489cc69c1STang Haojin
1015571677c9Sxiaofeibao-xjtu    when(robEntries(i).valid && (needFlush || needFlushWriteBack)) {
1016f1e8fcb2SXuan Hu      // exception flush
1017571677c9Sxiaofeibao-xjtu      robEntries(i).uopNum := robEntries(i).uopNum - wbCnt
1018780712aaSxiaofeibao-xjtu      robEntries(i).stdWritebacked := true.B
1019780712aaSxiaofeibao-xjtu    }.elsewhen(!robEntries(i).valid && instCanEnqFlag) {
1020f1e8fcb2SXuan Hu      // enq set num of uops
1021780712aaSxiaofeibao-xjtu      robEntries(i).uopNum := enqWBNum
1022780712aaSxiaofeibao-xjtu      robEntries(i).stdWritebacked := Mux(enqWriteStd, false.B, true.B)
1023780712aaSxiaofeibao-xjtu    }.elsewhen(robEntries(i).valid) {
1024f1e8fcb2SXuan Hu      // update by writing back
1025780712aaSxiaofeibao-xjtu      robEntries(i).uopNum := robEntries(i).uopNum - wbCnt
1026780712aaSxiaofeibao-xjtu      assert(!(robEntries(i).uopNum - wbCnt > robEntries(i).uopNum), s"robEntries $i uopNum is overflow!")
1027f1e8fcb2SXuan Hu      when(canStdWbSeq.asUInt.orR) {
1028780712aaSxiaofeibao-xjtu        robEntries(i).stdWritebacked := true.B
1029cda1c534Sxiaofeibao-xjtu      }
1030f1e8fcb2SXuan Hu    }
1031a8db15d8Sfdy
10323bc74e23SzhanglyGit    val fflagsCanWbSeq = fflags_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U && writeback.bits.wflags.getOrElse(false.B))
103327c566d7SXuan Hu    val fflagsRes = fflagsCanWbSeq.zip(fflags_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.fflags.get, 0.U) }.fold(false.B)(_ | _)
10348338e674Sxiaofeibao-xjtu    when(isFirstEnq) {
10358338e674Sxiaofeibao-xjtu      robEntries(i).fflags := 0.U
10368338e674Sxiaofeibao-xjtu    }.elsewhen(fflagsRes.orR) {
10378338e674Sxiaofeibao-xjtu      robEntries(i).fflags := robEntries(i).fflags | fflagsRes
10388338e674Sxiaofeibao-xjtu    }
1039a8db15d8Sfdy
1040a8db15d8Sfdy    val vxsatCanWbSeq = vxsat_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U)
104127c566d7SXuan Hu    val vxsatRes = vxsatCanWbSeq.zip(vxsat_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.vxsat.get, 0.U) }.fold(false.B)(_ | _)
10428338e674Sxiaofeibao-xjtu    when(isFirstEnq) {
10438338e674Sxiaofeibao-xjtu      robEntries(i).vxsat := 0.U
10448338e674Sxiaofeibao-xjtu    }.elsewhen(vxsatRes.orR) {
10458338e674Sxiaofeibao-xjtu      robEntries(i).vxsat := robEntries(i).vxsat | vxsatRes
10468338e674Sxiaofeibao-xjtu    }
104749162c9aSGuanghui Cheng
104849162c9aSGuanghui Cheng    // trace
104949162c9aSGuanghui Cheng    val taken = branchWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === i.U && writeback.bits.redirect.get.bits.cfiUpdate.taken).reduce(_ || _)
10508cbf000bSchengguanghui    when(robEntries(i).valid && Itype.isBranchType(robEntries(i).traceBlockInPipe.itype) && taken){
1051725e8ddcSchengguanghui      // BranchType code(notaken itype = 4) must be correctly replaced!
1052725e8ddcSchengguanghui      robEntries(i).traceBlockInPipe.itype := Itype.Taken
105349162c9aSGuanghui Cheng    }
10549aca92b9SYinan Xu  }
1055780712aaSxiaofeibao-xjtu
1056780712aaSxiaofeibao-xjtu  // begin update robBanksRdata
1057780712aaSxiaofeibao-xjtu  val robBanksRdata = VecInit(robBanksRdataThisLine ++ robBanksRdataNextLine)
1058780712aaSxiaofeibao-xjtu  val needUpdate = Wire(Vec(2 * CommitWidth, new RobEntryBundle))
1059780712aaSxiaofeibao-xjtu  needUpdate := VecInit(robBanksRdataThisLine ++ robBanksRdataNextLine)
1060780712aaSxiaofeibao-xjtu  val needUpdateRobIdx = robIdxThisLine ++ robIdxNextLine
1061cda1c534Sxiaofeibao-xjtu  for (i <- 0 until 2 * CommitWidth) {
1062780712aaSxiaofeibao-xjtu    val robIdxMatchSeq = io.enq.req.map(_.bits.robIdx.value === needUpdateRobIdx(i))
1063cda1c534Sxiaofeibao-xjtu    val uopCanEnqSeq = uopEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
1064cda1c534Sxiaofeibao-xjtu    val instCanEnqSeq = instEnqValidSeq.zip(robIdxMatchSeq).map { case (valid, isMatch) => valid && isMatch }
1065cda1c534Sxiaofeibao-xjtu    val instCanEnqFlag = Cat(instCanEnqSeq).orR
1066780712aaSxiaofeibao-xjtu    val realDestEnqNum = PopCount(enqNeedWriteRFSeq.zip(uopCanEnqSeq).map { case (writeFlag, valid) => writeFlag && valid })
1067780712aaSxiaofeibao-xjtu    when(!needUpdate(i).valid && instCanEnqFlag) {
1068780712aaSxiaofeibao-xjtu      needUpdate(i).realDestSize := realDestEnqNum
1069780712aaSxiaofeibao-xjtu    }.elsewhen(needUpdate(i).valid && instCanEnqFlag) {
1070780712aaSxiaofeibao-xjtu      needUpdate(i).realDestSize := robBanksRdata(i).realDestSize + realDestEnqNum
1071cda1c534Sxiaofeibao-xjtu    }
1072780712aaSxiaofeibao-xjtu    val enqUopNum = PriorityMux(instCanEnqSeq, enqUopNumVec)
1073780712aaSxiaofeibao-xjtu    val enqWBNum = PriorityMux(instCanEnqSeq, enqWBNumVec)
1074780712aaSxiaofeibao-xjtu    val enqWriteStd = PriorityMux(instCanEnqSeq, enqWriteStdVec)
1075780712aaSxiaofeibao-xjtu
1076780712aaSxiaofeibao-xjtu    val canWbSeq = exuWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i))
1077780712aaSxiaofeibao-xjtu    val canStdWbSeq = VecInit(stdWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i)))
1078571677c9Sxiaofeibao-xjtu    val wbCnt = Mux1H(canWbSeq, io.writebackNums.map(_.bits))
1079780712aaSxiaofeibao-xjtu
1080571677c9Sxiaofeibao-xjtu    val canWbExceptionSeq = exceptionWBs.map(writeback => writeback.valid && (writeback.bits.robIdx.value === needUpdateRobIdx(i)))
1081571677c9Sxiaofeibao-xjtu    val needFlush = robBanksRdata(i).needFlush
1082571677c9Sxiaofeibao-xjtu    val needFlushWriteBack = Wire(Bool())
1083571677c9Sxiaofeibao-xjtu    needFlushWriteBack := Mux1H(canWbExceptionSeq, io.writebackNeedFlush)
1084571677c9Sxiaofeibao-xjtu    when(needUpdate(i).valid) {
1085571677c9Sxiaofeibao-xjtu      needUpdate(i).needFlush := needFlush || needFlushWriteBack
1086571677c9Sxiaofeibao-xjtu    }
1087780712aaSxiaofeibao-xjtu
1088571677c9Sxiaofeibao-xjtu    when(needUpdate(i).valid && (needFlush || needFlushWriteBack)) {
1089780712aaSxiaofeibao-xjtu      // exception flush
1090571677c9Sxiaofeibao-xjtu      needUpdate(i).uopNum := robBanksRdata(i).uopNum - wbCnt
1091780712aaSxiaofeibao-xjtu      needUpdate(i).stdWritebacked := true.B
1092780712aaSxiaofeibao-xjtu    }.elsewhen(!needUpdate(i).valid && instCanEnqFlag) {
1093780712aaSxiaofeibao-xjtu      // enq set num of uops
1094780712aaSxiaofeibao-xjtu      needUpdate(i).uopNum := enqWBNum
1095780712aaSxiaofeibao-xjtu      needUpdate(i).stdWritebacked := Mux(enqWriteStd, false.B, true.B)
1096780712aaSxiaofeibao-xjtu    }.elsewhen(needUpdate(i).valid) {
1097780712aaSxiaofeibao-xjtu      // update by writing back
1098780712aaSxiaofeibao-xjtu      needUpdate(i).uopNum := robBanksRdata(i).uopNum - wbCnt
1099780712aaSxiaofeibao-xjtu      when(canStdWbSeq.asUInt.orR) {
1100780712aaSxiaofeibao-xjtu        needUpdate(i).stdWritebacked := true.B
11019aca92b9SYinan Xu      }
11029aca92b9SYinan Xu    }
11039aca92b9SYinan Xu
1104780712aaSxiaofeibao-xjtu    val fflagsCanWbSeq = fflags_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i) && writeback.bits.wflags.getOrElse(false.B))
1105780712aaSxiaofeibao-xjtu    val fflagsRes = fflagsCanWbSeq.zip(fflags_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.fflags.get, 0.U) }.fold(false.B)(_ | _)
1106780712aaSxiaofeibao-xjtu    needUpdate(i).fflags := Mux(!robBanksRdata(i).valid && instCanEnqFlag, 0.U, robBanksRdata(i).fflags | fflagsRes)
1107780712aaSxiaofeibao-xjtu
1108780712aaSxiaofeibao-xjtu    val vxsatCanWbSeq = vxsat_wb.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i))
1109780712aaSxiaofeibao-xjtu    val vxsatRes = vxsatCanWbSeq.zip(vxsat_wb).map { case (canWb, wb) => Mux(canWb, wb.bits.vxsat.get, 0.U) }.fold(false.B)(_ | _)
1110780712aaSxiaofeibao-xjtu    needUpdate(i).vxsat := Mux(!robBanksRdata(i).valid && instCanEnqFlag, 0.U, robBanksRdata(i).vxsat | vxsatRes)
1111b720b0cdSchengguanghui
1112b720b0cdSchengguanghui    // trace
1113b720b0cdSchengguanghui    val taken = branchWBs.map(writeback => writeback.valid && writeback.bits.robIdx.value === needUpdateRobIdx(i) && writeback.bits.redirect.get.bits.cfiUpdate.taken).reduce(_ || _)
11148cbf000bSchengguanghui    when(robBanksRdata(i).valid && Itype.isBranchType(robBanksRdata(i).traceBlockInPipe.itype) && taken){
1115b720b0cdSchengguanghui      // BranchType code(notaken itype = 4) must be correctly replaced!
1116b720b0cdSchengguanghui      needUpdate(i).traceBlockInPipe.itype := Itype.Taken
1117b720b0cdSchengguanghui    }
1118780712aaSxiaofeibao-xjtu  }
1119780712aaSxiaofeibao-xjtu  robBanksRdataThisLineUpdate := VecInit(needUpdate.take(8))
1120780712aaSxiaofeibao-xjtu  robBanksRdataNextLineUpdate := VecInit(needUpdate.drop(8))
1121780712aaSxiaofeibao-xjtu  // end update robBanksRdata
1122780712aaSxiaofeibao-xjtu
1123e8009193SYinan Xu  // interrupt_safe
1124e8009193SYinan Xu  for (i <- 0 until RenameWidth) {
11259d3877d6SGuanghui Cheng    when(canEnqueue(i)) {
1126e8009193SYinan Xu      // For now, we allow non-load-store instructions to trigger interrupts
1127e8009193SYinan Xu      // For MMIO instructions, they should not trigger interrupts since they may
1128e8009193SYinan Xu      // be sent to lower level before it writes back.
1129e8009193SYinan Xu      // However, we cannot determine whether a load/store instruction is MMIO.
1130e8009193SYinan Xu      // Thus, we don't allow load/store instructions to trigger an interrupt.
1131e8009193SYinan Xu      // TODO: support non-MMIO load-store instructions to trigger interrupts
1132493f6e1aSAnzo      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)
11339d3877d6SGuanghui Cheng      robEntries(allocatePtrVec(i).value).interrupt_safe := allow_interrupts
1134e8009193SYinan Xu    }
1135e8009193SYinan Xu  }
11369aca92b9SYinan Xu
11379aca92b9SYinan Xu  /**
11389aca92b9SYinan Xu   * read and write of data modules
11399aca92b9SYinan Xu   */
11409aca92b9SYinan Xu  val commitReadAddr_next = Mux(state_next === s_idle,
11419aca92b9SYinan Xu    VecInit(deqPtrVec_next.map(_.value)),
11429aca92b9SYinan Xu    VecInit(walkPtrVec_next.map(_.value))
11439aca92b9SYinan Xu  )
11449aca92b9SYinan Xu
11459aca92b9SYinan Xu  exceptionGen.io.redirect <> io.redirect
11469aca92b9SYinan Xu  exceptionGen.io.flush := io.flushOut.valid
1147a8db15d8Sfdy
1148a8db15d8Sfdy  val canEnqueueEG = VecInit(io.enq.req.map(req => req.valid && io.enq.canAccept))
11499aca92b9SYinan Xu  for (i <- 0 until RenameWidth) {
1150a8db15d8Sfdy    exceptionGen.io.enq(i).valid := canEnqueueEG(i)
11519aca92b9SYinan Xu    exceptionGen.io.enq(i).bits.robIdx := io.enq.req(i).bits.robIdx
11526f483f86SXuan Hu    exceptionGen.io.enq(i).bits.ftqPtr := io.enq.req(i).bits.ftqPtr
11536f483f86SXuan Hu    exceptionGen.io.enq(i).bits.ftqOffset := io.enq.req(i).bits.ftqOffset
11543b739f49SXuan Hu    exceptionGen.io.enq(i).bits.exceptionVec := ExceptionNO.selectFrontend(io.enq.req(i).bits.exceptionVec)
11553e8a0170SXuan Hu    exceptionGen.io.enq(i).bits.hasException := io.enq.req(i).bits.hasException
115611bd888fSXuan Hu    exceptionGen.io.enq(i).bits.isEnqExcp := io.enq.req(i).bits.hasException
1157c1b28b66STang Haojin    exceptionGen.io.enq(i).bits.isFetchMalAddr := io.enq.req(i).bits.isFetchMalAddr
11583b739f49SXuan Hu    exceptionGen.io.enq(i).bits.flushPipe := io.enq.req(i).bits.flushPipe
1159d91483a6Sfdy    exceptionGen.io.enq(i).bits.isVset := io.enq.req(i).bits.isVset
1160d7dd1af1SLi Qianruo    exceptionGen.io.enq(i).bits.replayInst := false.B
11613b739f49SXuan Hu    XSError(canEnqueue(i) && io.enq.req(i).bits.replayInst, "enq should not set replayInst")
11623b739f49SXuan Hu    exceptionGen.io.enq(i).bits.singleStep := io.enq.req(i).bits.singleStep
11633b739f49SXuan Hu    exceptionGen.io.enq(i).bits.crossPageIPFFix := io.enq.req(i).bits.crossPageIPFFix
11647e0f64b0SGuanghui Cheng    exceptionGen.io.enq(i).bits.trigger := io.enq.req(i).bits.trigger
1165e703da02SzhanglyGit    exceptionGen.io.enq(i).bits.vstartEn := false.B //DontCare
1166e703da02SzhanglyGit    exceptionGen.io.enq(i).bits.vstart := 0.U //DontCare
1167c0355297SAnzooooo    exceptionGen.io.enq(i).bits.vuopIdx := 0.U
1168e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isVecLoad := false.B
1169e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isVlm := false.B
1170e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isStrided := false.B
1171e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isIndexed := false.B
1172e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.isWhole := false.B
1173e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.nf := 0.U
1174e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.vsew := 0.U
1175e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.veew := 0.U
1176e43bb916SXuan Hu    exceptionGen.io.enq(i).bits.vlmul := 0.U
11779aca92b9SYinan Xu  }
11789aca92b9SYinan Xu
11796ab6918fSYinan Xu  println(s"ExceptionGen:")
11803b739f49SXuan Hu  println(s"num of exceptions: ${params.numException}")
11813b739f49SXuan Hu  require(exceptionWBs.length == exceptionGen.io.wb.length,
11823b739f49SXuan Hu    f"exceptionWBs.length: ${exceptionWBs.length}, " +
11833b739f49SXuan Hu      f"exceptionGen.io.wb.length: ${exceptionGen.io.wb.length}")
11843b739f49SXuan Hu  for (((wb, exc_wb), i) <- exceptionWBs.zip(exceptionGen.io.wb).zipWithIndex) {
11856ab6918fSYinan Xu    exc_wb.valid       := wb.valid
11863b739f49SXuan Hu    exc_wb.bits.robIdx := wb.bits.robIdx
11876f483f86SXuan Hu    // only enq inst use ftqPtr to read gpa
11886f483f86SXuan Hu    exc_wb.bits.ftqPtr          := 0.U.asTypeOf(exc_wb.bits.ftqPtr)
11896f483f86SXuan Hu    exc_wb.bits.ftqOffset       := 0.U.asTypeOf(exc_wb.bits.ftqOffset)
11903b739f49SXuan Hu    exc_wb.bits.exceptionVec    := wb.bits.exceptionVec.get
11913e8a0170SXuan Hu    exc_wb.bits.hasException    := wb.bits.exceptionVec.get.asUInt.orR // Todo: use io.writebackNeedFlush(i) instead
119211bd888fSXuan Hu    exc_wb.bits.isEnqExcp       := false.B
1193c1b28b66STang Haojin    exc_wb.bits.isFetchMalAddr  := false.B
11943b739f49SXuan Hu    exc_wb.bits.flushPipe       := wb.bits.flushPipe.getOrElse(false.B)
11954aa9ed34Sfdy    exc_wb.bits.isVset          := false.B
11963b739f49SXuan Hu    exc_wb.bits.replayInst      := wb.bits.replay.getOrElse(false.B)
11976ab6918fSYinan Xu    exc_wb.bits.singleStep      := false.B
11986ab6918fSYinan Xu    exc_wb.bits.crossPageIPFFix := false.B
1199b7dc2d1fSGuanghui Cheng    val trigger = wb.bits.trigger.getOrElse(TriggerAction.None).asTypeOf(exc_wb.bits.trigger)
12007e0f64b0SGuanghui Cheng    exc_wb.bits.trigger := trigger
1201f634b231SGuanghui Cheng    exc_wb.bits.vstartEn := (if (wb.bits.vls.nonEmpty) wb.bits.exceptionVec.get.asUInt.orR || TriggerAction.isDmode(trigger) else 0.U)
1202fd33b932Sxiaofeibao    exc_wb.bits.vstart := (if (wb.bits.vls.nonEmpty) wb.bits.vls.get.vpu.vstart else 0.U)
1203c0355297SAnzooooo    exc_wb.bits.vuopIdx := (if (wb.bits.vls.nonEmpty) wb.bits.vls.get.vpu.vuopIdx else 0.U)
1204e43bb916SXuan Hu    exc_wb.bits.isVecLoad := wb.bits.vls.map(_.isVecLoad).getOrElse(false.B)
1205e43bb916SXuan Hu    exc_wb.bits.isVlm := wb.bits.vls.map(_.isVlm).getOrElse(false.B)
1206e43bb916SXuan Hu    exc_wb.bits.isStrided := wb.bits.vls.map(_.isStrided).getOrElse(false.B) // strided need two mode tmp vreg
1207e43bb916SXuan Hu    exc_wb.bits.isIndexed := wb.bits.vls.map(_.isIndexed).getOrElse(false.B) // indexed and nf=0 need non-sequential uopidx -> vdidx
1208e43bb916SXuan Hu    exc_wb.bits.isWhole := wb.bits.vls.map(_.isWhole).getOrElse(false.B) // indexed and nf=0 need non-sequential uopidx -> vdidx
1209e43bb916SXuan Hu    exc_wb.bits.nf := wb.bits.vls.map(_.vpu.nf).getOrElse(0.U)
1210e43bb916SXuan Hu    exc_wb.bits.vsew := wb.bits.vls.map(_.vpu.vsew).getOrElse(0.U)
1211e43bb916SXuan Hu    exc_wb.bits.veew := wb.bits.vls.map(_.vpu.veew).getOrElse(0.U)
1212e43bb916SXuan Hu    exc_wb.bits.vlmul := wb.bits.vls.map(_.vpu.vlmul).getOrElse(0.U)
12139aca92b9SYinan Xu  }
12149aca92b9SYinan Xu
1215780712aaSxiaofeibao-xjtu  fflagsDataRead := (0 until CommitWidth).map(i => robEntries(deqPtrVec(i).value).fflags)
1216780712aaSxiaofeibao-xjtu  vxsatDataRead := (0 until CommitWidth).map(i => robEntries(deqPtrVec(i).value).vxsat)
1217d91483a6Sfdy
12188338e674Sxiaofeibao-xjtu  val isCommit = io.commits.isCommit
12198338e674Sxiaofeibao-xjtu  val isCommitReg = GatedValidRegNext(io.commits.isCommit)
12206474c47fSYinan Xu  val instrCntReg = RegInit(0.U(64.W))
12218338e674Sxiaofeibao-xjtu  val fuseCommitCnt = PopCount(io.commits.commitValid.zip(io.commits.info).map { case (v, i) => RegEnable(v && CommitType.isFused(i.commitType), isCommit) })
12228338e674Sxiaofeibao-xjtu  val trueCommitCnt = RegEnable(io.commits.commitValid.zip(io.commits.info).map { case (v, i) => Mux(v, i.instrSize, 0.U) }.reduce(_ +& _), isCommit) +& fuseCommitCnt
12238338e674Sxiaofeibao-xjtu  val retireCounter = Mux(isCommitReg, trueCommitCnt, 0.U)
12246474c47fSYinan Xu  val instrCnt = instrCntReg + retireCounter
12258338e674Sxiaofeibao-xjtu  when(isCommitReg){
12266474c47fSYinan Xu    instrCntReg := instrCnt
12278338e674Sxiaofeibao-xjtu  }
12286474c47fSYinan Xu  io.csr.perfinfo.retiredInstr := retireCounter
12299aca92b9SYinan Xu  io.robFull := !allowEnqueue
1230f094911bSshinezyy  io.headNotReady := commit_vDeqGroup(deqPtr.value(bankNumWidth-1, 0)) && !commit_wDeqGroup(deqPtr.value(bankNumWidth-1, 0))
12319aca92b9SYinan Xu
1232e43bb916SXuan Hu  io.toVecExcpMod.logicPhyRegMap := rab.io.toVecExcpMod.logicPhyRegMap
1233e43bb916SXuan Hu  io.toVecExcpMod.excpInfo := vecExcpInfo
1234e43bb916SXuan Hu
12359aca92b9SYinan Xu  /**
12364907ec88Schengguanghui   * trace
12374907ec88Schengguanghui   */
12384907ec88Schengguanghui
12394907ec88Schengguanghui  // trace output
12404907ec88Schengguanghui  val traceValids = io.trace.traceCommitInfo.blocks.map(_.valid)
12414907ec88Schengguanghui  val traceBlocks = io.trace.traceCommitInfo.blocks
12424907ec88Schengguanghui  val traceBlockInPipe = io.trace.traceCommitInfo.blocks.map(_.bits.tracePipe)
12434907ec88Schengguanghui
12448cbf000bSchengguanghui  // The reg 'isTraceXret' only for trace xret instructions. xret only occur in block(0).
12458cbf000bSchengguanghui  val isTraceXret = RegInit(false.B)
12468cbf000bSchengguanghui  when(io.csr.isXRet){
12478cbf000bSchengguanghui    isTraceXret := true.B
12488cbf000bSchengguanghui  }.elsewhen(isTraceXret && io.commits.isCommit && io.commits.commitValid(0)){
12498cbf000bSchengguanghui    isTraceXret := false.B
12508cbf000bSchengguanghui  }
12518cbf000bSchengguanghui
12524907ec88Schengguanghui  for (i <- 0 until CommitWidth) {
12534907ec88Schengguanghui    traceBlocks(i).bits.ftqIdx.foreach(_ := rawInfo(i).ftqIdx)
12544907ec88Schengguanghui    traceBlocks(i).bits.ftqOffset.foreach(_ := rawInfo(i).ftqOffset)
12554907ec88Schengguanghui    traceBlockInPipe(i).itype := rawInfo(i).traceBlockInPipe.itype
1256c308d936Schengguanghui    traceBlockInPipe(i).iretire := rawInfo(i).traceBlockInPipe.iretire
12574907ec88Schengguanghui    traceBlockInPipe(i).ilastsize := rawInfo(i).traceBlockInPipe.ilastsize
1258c308d936Schengguanghui    traceValids(i) := io.commits.isCommit && io.commits.commitValid(i)
12598cbf000bSchengguanghui    // exception/xret only occur in block(0).
1260c308d936Schengguanghui    if(i == 0) {
12618cbf000bSchengguanghui      when(isTraceXret && io.commits.isCommit && io.commits.commitValid(0)){ // trace xret
12628cbf000bSchengguanghui        traceBlocks(i).bits.tracePipe.itype := Itype.ExpIntReturn
12638cbf000bSchengguanghui      }.elsewhen(io.exception.valid){ // trace exception
1264c308d936Schengguanghui        traceBlocks(i).bits.tracePipe.itype := Mux(io.exception.bits.isInterrupt,
12654907ec88Schengguanghui          Itype.Interrupt,
12664907ec88Schengguanghui          Itype.Exception
12674907ec88Schengguanghui        )
1268c308d936Schengguanghui        traceValids(i) := true.B
1269c308d936Schengguanghui        traceBlockInPipe(i).iretire := 0.U
1270c308d936Schengguanghui      }
12714907ec88Schengguanghui    }
12724907ec88Schengguanghui  }
12734907ec88Schengguanghui
12744907ec88Schengguanghui  /**
12759aca92b9SYinan Xu   * debug info
12769aca92b9SYinan Xu   */
12779aca92b9SYinan Xu  XSDebug(p"enqPtr ${enqPtr} deqPtr ${deqPtr}\n")
12789aca92b9SYinan Xu  XSDebug("")
12792f2ee3b1SXuan Hu  XSError(isBefore(enqPtr, deqPtr) && !isFull(enqPtr, deqPtr), "\ndeqPtr is older than enqPtr!\n")
12809aca92b9SYinan Xu  for (i <- 0 until RobSize) {
1281780712aaSxiaofeibao-xjtu    XSDebug(false, !robEntries(i).valid, "-")
1282780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && robEntries(i).isWritebacked, "w")
1283780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && !robEntries(i).isWritebacked, "v")
12849aca92b9SYinan Xu  }
12859aca92b9SYinan Xu  XSDebug(false, true.B, "\n")
12869aca92b9SYinan Xu
12879aca92b9SYinan Xu  for (i <- 0 until RobSize) {
12889aca92b9SYinan Xu    if (i % 4 == 0) XSDebug("")
12893b739f49SXuan Hu    XSDebug(false, true.B, "%x ", debug_microOp(i).pc)
1290780712aaSxiaofeibao-xjtu    XSDebug(false, !robEntries(i).valid, "- ")
1291780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && robEntries(i).isWritebacked, "w ")
1292780712aaSxiaofeibao-xjtu    XSDebug(false, robEntries(i).valid && !robEntries(i).isWritebacked, "v ")
12939aca92b9SYinan Xu    if (i % 4 == 3) XSDebug(false, true.B, "\n")
12949aca92b9SYinan Xu  }
12959aca92b9SYinan Xu
12968338e674Sxiaofeibao-xjtu  def ifCommit(counter: UInt): UInt = Mux(isCommit, counter, 0.U)
1297780712aaSxiaofeibao-xjtu
12988338e674Sxiaofeibao-xjtu  def ifCommitReg(counter: UInt): UInt = Mux(isCommitReg, counter, 0.U)
12999aca92b9SYinan Xu
13009aca92b9SYinan Xu  val commitDebugUop = deqPtrVec.map(_.value).map(debug_microOp(_))
1301ef7a7f80STang Haojin  XSPerfAccumulate("clock_cycle", 1.U, XSPerfLevel.CRITICAL)
1302e986c5deSXuan Hu  QueuePerf(RobSize, numValidEntries, numValidEntries === RobSize.U)
13039aca92b9SYinan Xu  XSPerfAccumulate("commitUop", ifCommit(commitCnt))
1304ef7a7f80STang Haojin  XSPerfAccumulate("commitInstr", ifCommitReg(trueCommitCnt), XSPerfLevel.CRITICAL)
1305ec9e6512Swakafa  XSPerfRolling("ipc", ifCommitReg(trueCommitCnt), 1000, clock, reset)
1306839e5512SZifei Zhang  XSPerfRolling("cpi", perfCnt = 1.U /*Cycle*/ , eventTrigger = ifCommitReg(trueCommitCnt), granularity = 1000, clock, reset)
13077e8294acSYinan Xu  XSPerfAccumulate("commitInstrFused", ifCommitReg(fuseCommitCnt))
13089aca92b9SYinan Xu  val commitIsLoad = io.commits.info.map(_.commitType).map(_ === CommitType.LOAD)
13096474c47fSYinan Xu  val commitLoadValid = io.commits.commitValid.zip(commitIsLoad).map { case (v, t) => v && t }
13109aca92b9SYinan Xu  XSPerfAccumulate("commitInstrLoad", ifCommit(PopCount(commitLoadValid)))
131120edb3f7SWilliam Wang  val commitIsBranch = io.commits.info.map(_.commitType).map(_ === CommitType.BRANCH)
13126474c47fSYinan Xu  val commitBranchValid = io.commits.commitValid.zip(commitIsBranch).map { case (v, t) => v && t }
131320edb3f7SWilliam Wang  XSPerfAccumulate("commitInstrBranch", ifCommit(PopCount(commitBranchValid)))
13149aca92b9SYinan Xu  val commitIsStore = io.commits.info.map(_.commitType).map(_ === CommitType.STORE)
13156474c47fSYinan Xu  XSPerfAccumulate("commitInstrStore", ifCommit(PopCount(io.commits.commitValid.zip(commitIsStore).map { case (v, t) => v && t })))
1316780712aaSxiaofeibao-xjtu  XSPerfAccumulate("writeback", PopCount((0 until RobSize).map(i => robEntries(i).valid && robEntries(i).isWritebacked)))
1317c51eab43SYinan Xu  // XSPerfAccumulate("enqInstr", PopCount(io.dp1Req.map(_.fire)))
13189aca92b9SYinan Xu  // XSPerfAccumulate("d2rVnR", PopCount(io.dp1Req.map(p => p.valid && !p.ready)))
13196474c47fSYinan Xu  XSPerfAccumulate("walkInstr", Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U))
1320e986c5deSXuan Hu  XSPerfAccumulate("walkCycleTotal", state === s_walk)
1321e986c5deSXuan Hu  XSPerfAccumulate("waitRabWalkEnd", state === s_walk && walkFinished && !rab.io.status.walkEnd)
1322e986c5deSXuan Hu  private val walkCycle = RegInit(0.U(8.W))
1323e986c5deSXuan Hu  private val waitRabWalkCycle = RegInit(0.U(8.W))
1324e986c5deSXuan Hu  walkCycle := Mux(io.redirect.valid, 0.U, Mux(state === s_walk, walkCycle + 1.U, 0.U))
1325e986c5deSXuan Hu  waitRabWalkCycle := Mux(state === s_walk && walkFinished, 0.U, Mux(state === s_walk, walkCycle + 1.U, 0.U))
1326e986c5deSXuan Hu
1327e986c5deSXuan Hu  XSPerfHistogram("walkRobCycleHist", walkCycle, state === s_walk && walkFinished, 0, 32)
1328e986c5deSXuan Hu  XSPerfHistogram("walkRabExtraCycleHist", waitRabWalkCycle, state === s_walk && walkFinished && rab.io.status.walkEnd, 0, 32)
1329e986c5deSXuan Hu  XSPerfHistogram("walkTotalCycleHist", walkCycle, state === s_walk && state_next === s_idle, 0, 32)
1330e986c5deSXuan Hu
1331780712aaSxiaofeibao-xjtu  private val deqNotWritebacked = robEntries(deqPtr.value).valid && !robEntries(deqPtr.value).isWritebacked
1332780712aaSxiaofeibao-xjtu  private val deqStdNotWritebacked = robEntries(deqPtr.value).valid && !robEntries(deqPtr.value).stdWritebacked
1333780712aaSxiaofeibao-xjtu  private val deqUopNotWritebacked = robEntries(deqPtr.value).valid && !robEntries(deqPtr.value).isUopWritebacked
1334af4bdb08SXuan Hu  private val deqHeadInfo = debug_microOp(deqPtr.value)
13354b69927cSxiao feibao  val deqUopCommitType = debug_microOp(deqPtr.value).commitType
1336239413e5SXuan Hu
1337af4bdb08SXuan Hu  XSPerfAccumulate("waitAluCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.alu.U)
1338af4bdb08SXuan Hu  XSPerfAccumulate("waitMulCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.mul.U)
1339af4bdb08SXuan Hu  XSPerfAccumulate("waitDivCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.div.U)
1340af4bdb08SXuan Hu  XSPerfAccumulate("waitBrhCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.brh.U)
1341af4bdb08SXuan Hu  XSPerfAccumulate("waitJmpCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.jmp.U)
1342af4bdb08SXuan Hu  XSPerfAccumulate("waitCsrCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.csr.U)
1343af4bdb08SXuan Hu  XSPerfAccumulate("waitFenCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.fence.U)
1344af4bdb08SXuan Hu  XSPerfAccumulate("waitBkuCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.bku.U)
1345af4bdb08SXuan Hu  XSPerfAccumulate("waitLduCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.ldu.U)
1346af4bdb08SXuan Hu  XSPerfAccumulate("waitStuCycle", deqNotWritebacked && deqHeadInfo.fuType === FuType.stu.U)
1347af4bdb08SXuan Hu  XSPerfAccumulate("waitStaCycle", deqUopNotWritebacked && deqHeadInfo.fuType === FuType.stu.U)
1348af4bdb08SXuan Hu  XSPerfAccumulate("waitStdCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.stu.U)
1349af4bdb08SXuan Hu  XSPerfAccumulate("waitAtmCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.mou.U)
1350af4bdb08SXuan Hu
1351d280e426Slewislzh  XSPerfAccumulate("waitVfaluCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.vfalu.U)
1352d280e426Slewislzh  XSPerfAccumulate("waitVfmaCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.vfma.U)
1353d280e426Slewislzh  XSPerfAccumulate("waitVfdivCycle", deqStdNotWritebacked && deqHeadInfo.fuType === FuType.vfdiv.U)
1354d280e426Slewislzh
1355d280e426Slewislzh  val vfalufuop = Seq(VfaluType.vfadd, VfaluType.vfwadd, VfaluType.vfwadd_w, VfaluType.vfsub, VfaluType.vfwsub, VfaluType.vfwsub_w, VfaluType.vfmin, VfaluType.vfmax,
1356d280e426Slewislzh    VfaluType.vfmerge, VfaluType.vfmv, VfaluType.vfsgnj, VfaluType.vfsgnjn, VfaluType.vfsgnjx, VfaluType.vfeq, VfaluType.vfne, VfaluType.vflt, VfaluType.vfle, VfaluType.vfgt,
1357d280e426Slewislzh    VfaluType.vfge, VfaluType.vfclass, VfaluType.vfmv_f_s, VfaluType.vfmv_s_f, VfaluType.vfredusum, VfaluType.vfredmax, VfaluType.vfredmin, VfaluType.vfredosum, VfaluType.vfwredosum)
1358d280e426Slewislzh
1359d280e426Slewislzh  vfalufuop.zipWithIndex.map{
1360d280e426Slewislzh    case(fuoptype,i) =>  XSPerfAccumulate(s"waitVfalu_${i}Cycle", deqStdNotWritebacked && deqHeadInfo.fuOpType === fuoptype && deqHeadInfo.fuType === FuType.vfalu.U)
1361d280e426Slewislzh  }
1362d280e426Slewislzh
1363d280e426Slewislzh
1364d280e426Slewislzh
13659aca92b9SYinan Xu  XSPerfAccumulate("waitNormalCycle", deqNotWritebacked && deqUopCommitType === CommitType.NORMAL)
13669aca92b9SYinan Xu  XSPerfAccumulate("waitBranchCycle", deqNotWritebacked && deqUopCommitType === CommitType.BRANCH)
13679aca92b9SYinan Xu  XSPerfAccumulate("waitLoadCycle", deqNotWritebacked && deqUopCommitType === CommitType.LOAD)
13689aca92b9SYinan Xu  XSPerfAccumulate("waitStoreCycle", deqNotWritebacked && deqUopCommitType === CommitType.STORE)
1369780712aaSxiaofeibao-xjtu  XSPerfAccumulate("robHeadPC", io.commits.info(0).debug_pc.getOrElse(0.U))
137089cc69c1STang Haojin  XSPerfAccumulate("commitCompressCntAll", PopCount(io.commits.commitValid.zip(io.commits.info).map { case (valid, info) => io.commits.isCommit && valid && info.instrSize > 1.U }))
137189cc69c1STang Haojin  (2 to RenameWidth).foreach(i =>
137289cc69c1STang 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 }))
137389cc69c1STang Haojin  )
137489cc69c1STang 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(_ +& _))
13759aca92b9SYinan Xu  val dispatchLatency = commitDebugUop.map(uop => uop.debugInfo.dispatchTime - uop.debugInfo.renameTime)
13769aca92b9SYinan Xu  val enqRsLatency = commitDebugUop.map(uop => uop.debugInfo.enqRsTime - uop.debugInfo.dispatchTime)
13779aca92b9SYinan Xu  val selectLatency = commitDebugUop.map(uop => uop.debugInfo.selectTime - uop.debugInfo.enqRsTime)
13789aca92b9SYinan Xu  val issueLatency = commitDebugUop.map(uop => uop.debugInfo.issueTime - uop.debugInfo.selectTime)
13799aca92b9SYinan Xu  val executeLatency = commitDebugUop.map(uop => uop.debugInfo.writebackTime - uop.debugInfo.issueTime)
13809aca92b9SYinan Xu  val rsFuLatency = commitDebugUop.map(uop => uop.debugInfo.writebackTime - uop.debugInfo.enqRsTime)
13819aca92b9SYinan Xu  val commitLatency = commitDebugUop.map(uop => timer - uop.debugInfo.writebackTime)
1382780712aaSxiaofeibao-xjtu
13839aca92b9SYinan Xu  def latencySum(cond: Seq[Bool], latency: Seq[UInt]): UInt = {
13849aca92b9SYinan Xu    cond.zip(latency).map(x => Mux(x._1, x._2, 0.U)).reduce(_ +& _)
13859aca92b9SYinan Xu  }
1386780712aaSxiaofeibao-xjtu
13879aca92b9SYinan Xu  for (fuType <- FuType.functionNameMap.keys) {
13889aca92b9SYinan Xu    val fuName = FuType.functionNameMap(fuType)
13893b739f49SXuan Hu    val commitIsFuType = io.commits.commitValid.zip(commitDebugUop).map(x => x._1 && x._2.fuType === fuType.U)
1390839e5512SZifei Zhang    XSPerfRolling(s"ipc_futype_${fuName}", ifCommit(PopCount(commitIsFuType)), 1000, clock, reset)
13919aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_instr_cnt", ifCommit(PopCount(commitIsFuType)))
13929aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_dispatch", ifCommit(latencySum(commitIsFuType, dispatchLatency)))
13939aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_enq_rs", ifCommit(latencySum(commitIsFuType, enqRsLatency)))
13949aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_select", ifCommit(latencySum(commitIsFuType, selectLatency)))
13959aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_issue", ifCommit(latencySum(commitIsFuType, issueLatency)))
13969aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_execute", ifCommit(latencySum(commitIsFuType, executeLatency)))
13979aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_enq_rs_execute", ifCommit(latencySum(commitIsFuType, rsFuLatency)))
13989aca92b9SYinan Xu    XSPerfAccumulate(s"${fuName}_latency_commit", ifCommit(latencySum(commitIsFuType, commitLatency)))
13999aca92b9SYinan Xu  }
14006087ee12SXuan Hu  XSPerfAccumulate(s"redirect_use_snapshot", io.redirect.valid && io.snpt.useSnpt)
14019aca92b9SYinan Xu
140260ebee38STang Haojin  // top-down info
140360ebee38STang Haojin  io.debugTopDown.toCore.robHeadVaddr.valid := debug_lsTopdownInfo(deqPtr.value).s1.vaddr_valid
140460ebee38STang Haojin  io.debugTopDown.toCore.robHeadVaddr.bits := debug_lsTopdownInfo(deqPtr.value).s1.vaddr_bits
140560ebee38STang Haojin  io.debugTopDown.toCore.robHeadPaddr.valid := debug_lsTopdownInfo(deqPtr.value).s2.paddr_valid
140660ebee38STang Haojin  io.debugTopDown.toCore.robHeadPaddr.bits := debug_lsTopdownInfo(deqPtr.value).s2.paddr_bits
140760ebee38STang Haojin  io.debugTopDown.toDispatch.robTrueCommit := ifCommitReg(trueCommitCnt)
140860ebee38STang Haojin  io.debugTopDown.toDispatch.robHeadLsIssue := debug_lsIssue(deqPtr.value)
140960ebee38STang Haojin  io.debugTopDown.robHeadLqIdx.valid := debug_lqIdxValid(deqPtr.value)
141060ebee38STang Haojin  io.debugTopDown.robHeadLqIdx.bits := debug_microOp(deqPtr.value).lqIdx
14116ed1154eSTang Haojin
14127cf78eb2Shappy-lx  // rolling
14137cf78eb2Shappy-lx  io.debugRolling.robTrueCommit := ifCommitReg(trueCommitCnt)
14148744445eSMaxpicca-Li
14158744445eSMaxpicca-Li  /**
14168744445eSMaxpicca-Li   * DataBase info:
14178744445eSMaxpicca-Li   * log trigger is at writeback valid
14188744445eSMaxpicca-Li   * */
1419248b9a04SYanqin Li  if (!env.FPGAPlatform) {
1420248b9a04SYanqin Li    val instTableName = "InstTable" + p(XSCoreParamsKey).HartId.toString
1421248b9a04SYanqin Li    val instSiteName = "Rob" + p(XSCoreParamsKey).HartId.toString
142290d824ceSYanqin Li    val debug_instTable = ChiselDB.createTable(instTableName, new InstInfoEntry)
1423248b9a04SYanqin Li    for (wb <- exuWBs) {
1424248b9a04SYanqin Li      when(wb.valid) {
1425248b9a04SYanqin Li        val debug_instData = Wire(new InstInfoEntry)
1426248b9a04SYanqin Li        val idx = wb.bits.robIdx.value
1427248b9a04SYanqin Li        debug_instData.robIdx := idx
1428248b9a04SYanqin Li        debug_instData.dvaddr := wb.bits.debug.vaddr
1429248b9a04SYanqin Li        debug_instData.dpaddr := wb.bits.debug.paddr
1430248b9a04SYanqin Li        debug_instData.issueTime := wb.bits.debugInfo.issueTime
1431248b9a04SYanqin Li        debug_instData.writebackTime := wb.bits.debugInfo.writebackTime
1432248b9a04SYanqin Li        debug_instData.dispatchLatency := wb.bits.debugInfo.dispatchTime - wb.bits.debugInfo.renameTime
1433248b9a04SYanqin Li        debug_instData.enqRsLatency := wb.bits.debugInfo.enqRsTime - wb.bits.debugInfo.dispatchTime
1434248b9a04SYanqin Li        debug_instData.selectLatency := wb.bits.debugInfo.selectTime - wb.bits.debugInfo.enqRsTime
1435248b9a04SYanqin Li        debug_instData.issueLatency := wb.bits.debugInfo.issueTime - wb.bits.debugInfo.selectTime
1436248b9a04SYanqin Li        debug_instData.executeLatency := wb.bits.debugInfo.writebackTime - wb.bits.debugInfo.issueTime
1437248b9a04SYanqin Li        debug_instData.rsFuLatency := wb.bits.debugInfo.writebackTime - wb.bits.debugInfo.enqRsTime
1438248b9a04SYanqin Li        debug_instData.tlbLatency := wb.bits.debugInfo.tlbRespTime - wb.bits.debugInfo.tlbFirstReqTime
1439248b9a04SYanqin Li        debug_instData.exceptType := Cat(wb.bits.exceptionVec.getOrElse(ExceptionVec(false.B)))
1440248b9a04SYanqin Li        debug_instData.lsInfo := debug_lsInfo(idx)
1441248b9a04SYanqin Li        // debug_instData.globalID := wb.bits.uop.ctrl.debug_globalID
1442248b9a04SYanqin Li        // debug_instData.instType := wb.bits.uop.ctrl.fuType
1443248b9a04SYanqin Li        // debug_instData.ivaddr := wb.bits.uop.cf.pc
1444248b9a04SYanqin Li        // debug_instData.mdpInfo.ssid := wb.bits.uop.cf.ssid
1445248b9a04SYanqin Li        // debug_instData.mdpInfo.waitAllStore := wb.bits.uop.cf.loadWaitStrict && wb.bits.uop.cf.loadWaitBit
1446248b9a04SYanqin Li        debug_instTable.log(
1447248b9a04SYanqin Li          data = debug_instData,
1448248b9a04SYanqin Li          en = wb.valid,
1449248b9a04SYanqin Li          site = instSiteName,
1450248b9a04SYanqin Li          clock = clock,
1451248b9a04SYanqin Li          reset = reset
1452248b9a04SYanqin Li        )
1453248b9a04SYanqin Li      }
1454248b9a04SYanqin Li    }
1455248b9a04SYanqin Li  }
14568744445eSMaxpicca-Li
145708373300SAnzo  val debug_VecOtherPdest = RegInit(VecInit.fill(RobSize)(VecInit.fill(8)(0.U(PhyRegIdxWidth.W))))
145808373300SAnzo
145908373300SAnzo  vldWBs.map{ vldWb =>
146008373300SAnzo    val vldWbPdest  = vldWb.bits.pdest
146108373300SAnzo    val vldWbRobIdx = vldWb.bits.robIdx.value
146208373300SAnzo    val vldWbvdIdx  = vldWb.bits.vls.get.vdIdx
146308373300SAnzo    when (vldWb.fire && robEntries(vldWbRobIdx).valid && (vldWb.bits.vecWen.get || vldWb.bits.v0Wen.get)) {
146408373300SAnzo      debug_VecOtherPdest(vldWbRobIdx)(vldWbvdIdx) := vldWbPdest
146508373300SAnzo    }
146608373300SAnzo  }
14678744445eSMaxpicca-Li
14689aca92b9SYinan Xu  //difftest signals
1469f3034303SHaoyuan Feng  val firstValidCommit = (deqPtr + PriorityMux(io.commits.commitValid, VecInit(List.tabulate(CommitWidth)(_.U(log2Up(CommitWidth).W))))).value
14709aca92b9SYinan Xu
14719aca92b9SYinan Xu  val wdata = Wire(Vec(CommitWidth, UInt(XLEN.W)))
14729aca92b9SYinan Xu  val wpc = Wire(Vec(CommitWidth, UInt(XLEN.W)))
1473cbe9a847SYinan Xu
14749aca92b9SYinan Xu  for (i <- 0 until CommitWidth) {
14759aca92b9SYinan Xu    val idx = deqPtrVec(i).value
14769aca92b9SYinan Xu    wdata(i) := debug_exuData(idx)
14773b739f49SXuan Hu    wpc(i) := SignExt(commitDebugUop(i).pc, XLEN)
14789aca92b9SYinan Xu  }
14799aca92b9SYinan Xu
14807d45a146SYinan Xu  if (env.EnableDifftest || env.AlwaysBasicDiff) {
1481cbe9a847SYinan Xu    // These are the structures used by difftest only and should be optimized after synthesis.
1482cbe9a847SYinan Xu    val dt_eliminatedMove = Mem(RobSize, Bool())
1483cbe9a847SYinan Xu    val dt_isRVC = Mem(RobSize, Bool())
1484cbe9a847SYinan Xu    val dt_exuDebug = Reg(Vec(RobSize, new DebugBundle))
1485cbe9a847SYinan Xu    for (i <- 0 until RenameWidth) {
1486cbe9a847SYinan Xu      when(canEnqueue(i)) {
14876474c47fSYinan Xu        dt_eliminatedMove(allocatePtrVec(i).value) := io.enq.req(i).bits.eliminatedMove
14883b739f49SXuan Hu        dt_isRVC(allocatePtrVec(i).value) := io.enq.req(i).bits.preDecodeInfo.isRVC
1489cbe9a847SYinan Xu      }
1490cbe9a847SYinan Xu    }
14913b739f49SXuan Hu    for (wb <- exuWBs) {
14926ab6918fSYinan Xu      when(wb.valid) {
14933b739f49SXuan Hu        val wbIdx = wb.bits.robIdx.value
14946ab6918fSYinan Xu        dt_exuDebug(wbIdx) := wb.bits.debug
1495cbe9a847SYinan Xu      }
1496cbe9a847SYinan Xu    }
1497cbe9a847SYinan Xu    // Always instantiate basic difftest modules.
1498cbe9a847SYinan Xu    for (i <- 0 until CommitWidth) {
1499f1ba628bSHaojin Tang      val uop = commitDebugUop(i)
1500cbe9a847SYinan Xu      val commitInfo = io.commits.info(i)
1501cbe9a847SYinan Xu      val ptr = deqPtrVec(i).value
1502cbe9a847SYinan Xu      val exuOut = dt_exuDebug(ptr)
1503cbe9a847SYinan Xu      val eliminatedMove = dt_eliminatedMove(ptr)
1504cbe9a847SYinan Xu      val isRVC = dt_isRVC(ptr)
150508373300SAnzo      val instr = uop.instr.asTypeOf(new XSInstBitFields)
150608373300SAnzo      val isVLoad = instr.isVecLoad
1507cbe9a847SYinan Xu
1508e43bb916SXuan Hu      val difftest = DifftestModule(new DiffInstrCommit(MaxPhyRegs), delay = 3, dontCare = true)
1509bb76fc1bSYanqin Li      val dt_skip = Mux(eliminatedMove, false.B, exuOut.isSkipDiff)
15107d45a146SYinan Xu      difftest.coreid := io.hartId
15117d45a146SYinan Xu      difftest.index := i.U
15127d45a146SYinan Xu      difftest.valid := io.commits.commitValid(i) && io.commits.isCommit
1513202ef6b0SKunlin You      difftest.skip := dt_skip
15147d45a146SYinan Xu      difftest.isRVC := isRVC
1515780712aaSxiaofeibao-xjtu      difftest.rfwen := io.commits.commitValid(i) && commitInfo.rfWen && commitInfo.debug_ldest.get =/= 0.U
15164b0d80d8SXuan Hu      difftest.fpwen := io.commits.commitValid(i) && uop.fpWen
151708373300SAnzo      difftest.vecwen := io.commits.commitValid(i) && uop.vecWen
151808373300SAnzo      difftest.v0wen := io.commits.commitValid(i) && (uop.v0Wen || isVLoad && instr.VD === 0.U)
1519780712aaSxiaofeibao-xjtu      difftest.wpdest := commitInfo.debug_pdest.get
152008373300SAnzo      difftest.wdest := Mux(isVLoad, instr.VD, commitInfo.debug_ldest.get)
152108373300SAnzo      difftest.otherwpdest := debug_VecOtherPdest(ptr)
15226ce10964SXuan Hu      difftest.nFused := CommitType.isFused(commitInfo.commitType).asUInt + commitInfo.instrSize - 1.U
15236ce10964SXuan Hu      when(difftest.valid) {
15246ce10964SXuan Hu        assert(CommitType.isFused(commitInfo.commitType).asUInt + commitInfo.instrSize >= 1.U)
15256ce10964SXuan Hu      }
15267d45a146SYinan Xu      if (env.EnableDifftest) {
15277d45a146SYinan Xu        val uop = commitDebugUop(i)
152883ba63b3SXuan Hu        difftest.pc := SignExt(uop.pc, XLEN)
152983ba63b3SXuan Hu        difftest.instr := uop.instr
15307d45a146SYinan Xu        difftest.robIdx := ZeroExt(ptr, 10)
15317d45a146SYinan Xu        difftest.lqIdx := ZeroExt(uop.lqIdx.value, 7)
15327d45a146SYinan Xu        difftest.sqIdx := ZeroExt(uop.sqIdx.value, 7)
15337d45a146SYinan Xu        difftest.isLoad := io.commits.info(i).commitType === CommitType.LOAD
15347d45a146SYinan Xu        difftest.isStore := io.commits.info(i).commitType === CommitType.STORE
1535202ef6b0SKunlin You        // Check LoadEvent only when isAmo or isLoad and skip MMIO
1536202ef6b0SKunlin You        val difftestLoadEvent = DifftestModule(new DiffLoadEvent, delay = 3)
1537202ef6b0SKunlin You        difftestLoadEvent.coreid := io.hartId
1538202ef6b0SKunlin You        difftestLoadEvent.index := i.U
153908373300SAnzo        val loadCheck = (FuType.isAMO(uop.fuType) || FuType.isLoad(uop.fuType) || isVLoad) && !dt_skip
1540202ef6b0SKunlin You        difftestLoadEvent.valid    := io.commits.commitValid(i) && io.commits.isCommit && loadCheck
1541202ef6b0SKunlin You        difftestLoadEvent.paddr    := exuOut.paddr
1542202ef6b0SKunlin You        difftestLoadEvent.opType   := uop.fuOpType
1543202ef6b0SKunlin You        difftestLoadEvent.isAtomic := FuType.isAMO(uop.fuType)
1544202ef6b0SKunlin You        difftestLoadEvent.isLoad   := FuType.isLoad(uop.fuType)
154508373300SAnzo        difftestLoadEvent.isVLoad  := isVLoad
15467d45a146SYinan Xu      }
1547cbe9a847SYinan Xu    }
1548cbe9a847SYinan Xu  }
15499aca92b9SYinan Xu
15507d45a146SYinan Xu  if (env.EnableDifftest || env.AlwaysBasicDiff) {
1551cbe9a847SYinan Xu    val dt_isXSTrap = Mem(RobSize, Bool())
1552cbe9a847SYinan Xu    for (i <- 0 until RenameWidth) {
1553cbe9a847SYinan Xu      when(canEnqueue(i)) {
15543b739f49SXuan Hu        dt_isXSTrap(allocatePtrVec(i).value) := io.enq.req(i).bits.isXSTrap
1555cbe9a847SYinan Xu      }
1556cbe9a847SYinan Xu    }
15577d45a146SYinan Xu    val trapVec = io.commits.commitValid.zip(deqPtrVec).map { case (v, d) =>
15587d45a146SYinan Xu      io.commits.isCommit && v && dt_isXSTrap(d.value)
15597d45a146SYinan Xu    }
1560cbe9a847SYinan Xu    val hitTrap = trapVec.reduce(_ || _)
15617d45a146SYinan Xu    val difftest = DifftestModule(new DiffTrapEvent, dontCare = true)
15627d45a146SYinan Xu    difftest.coreid := io.hartId
15637d45a146SYinan Xu    difftest.hasTrap := hitTrap
15647d45a146SYinan Xu    difftest.cycleCnt := timer
15657d45a146SYinan Xu    difftest.instrCnt := instrCnt
15667d45a146SYinan Xu    difftest.hasWFI := hasWFI
15677d45a146SYinan Xu
15687d45a146SYinan Xu    if (env.EnableDifftest) {
1569cbe9a847SYinan Xu      val trapCode = PriorityMux(wdata.zip(trapVec).map(x => x._2 -> x._1))
1570cbe9a847SYinan Xu      val trapPC = SignExt(PriorityMux(wpc.zip(trapVec).map(x => x._2 -> x._1)), XLEN)
15717d45a146SYinan Xu      difftest.code := trapCode
15727d45a146SYinan Xu      difftest.pc := trapPC
15739aca92b9SYinan Xu    }
1574cbe9a847SYinan Xu  }
15751545277aSYinan Xu
15761bf9a598SAnzo  //store evetn difftest information
15771bf9a598SAnzo  io.storeDebugInfo := DontCare
15781bf9a598SAnzo  if (env.EnableDifftest) {
15791bf9a598SAnzo    io.storeDebugInfo.map{port =>
15801bf9a598SAnzo      port.pc := debug_microOp(port.robidx.value).pc
15811bf9a598SAnzo    }
15821bf9a598SAnzo  }
15831bf9a598SAnzo
1584e836c770SZhaoyang You  val brhMispred = PopCount(branchWBs.map(wb => wb.valid & wb.bits.redirect.get.valid))
1585e836c770SZhaoyang You  val jmpMispred = PopCount(jmpWBs.map(wb => wb.valid && wb.bits.redirect.get.valid))
1586e836c770SZhaoyang You  val misPred = brhMispred +& jmpMispred
1587e836c770SZhaoyang You
1588e836c770SZhaoyang You  XSPerfAccumulate("br_mis_pred", misPred)
1589e836c770SZhaoyang You
159043bdc4d9SYinan Xu  val commitLoadVec = VecInit(commitLoadValid)
159143bdc4d9SYinan Xu  val commitBranchVec = VecInit(commitBranchValid)
159243bdc4d9SYinan Xu  val commitStoreVec = VecInit(io.commits.commitValid.zip(commitIsStore).map { case (v, t) => v && t })
1593cd365d4cSrvcoresjw  val perfEvents = Seq(
1594cd365d4cSrvcoresjw    ("rob_interrupt_num      ", io.flushOut.valid && intrEnable),
1595571677c9Sxiaofeibao-xjtu    ("rob_exception_num      ", io.flushOut.valid && deqHasException),
1596cd365d4cSrvcoresjw    ("rob_flush_pipe_num     ", io.flushOut.valid && isFlushPipe),
1597cd365d4cSrvcoresjw    ("rob_replay_inst_num    ", io.flushOut.valid && isFlushPipe && deqHasReplayInst),
1598cd365d4cSrvcoresjw    ("rob_commitUop          ", ifCommit(commitCnt)),
15997e8294acSYinan Xu    ("rob_commitInstr        ", ifCommitReg(trueCommitCnt)),
16007e8294acSYinan Xu    ("rob_commitInstrFused   ", ifCommitReg(fuseCommitCnt)),
16018338e674Sxiaofeibao-xjtu    ("rob_commitInstrLoad    ", ifCommitReg(PopCount(RegEnable(commitLoadVec, isCommit)))),
16028338e674Sxiaofeibao-xjtu    ("rob_commitInstrBranch  ", ifCommitReg(PopCount(RegEnable(commitBranchVec, isCommit)))),
16038338e674Sxiaofeibao-xjtu    ("rob_commitInstrStore   ", ifCommitReg(PopCount(RegEnable(commitStoreVec, isCommit)))),
16046474c47fSYinan Xu    ("rob_walkInstr          ", Mux(io.commits.isWalk, PopCount(io.commits.walkValid), 0.U)),
1605ccfddc82SHaojin Tang    ("rob_walkCycle          ", (state === s_walk)),
16068338e674Sxiaofeibao-xjtu    ("rob_1_4_valid          ", numValidEntries <= (RobSize / 4).U),
16078338e674Sxiaofeibao-xjtu    ("rob_2_4_valid          ", numValidEntries > (RobSize / 4).U && numValidEntries <= (RobSize / 2).U),
16088338e674Sxiaofeibao-xjtu    ("rob_3_4_valid          ", numValidEntries > (RobSize / 2).U && numValidEntries <= (RobSize * 3 / 4).U),
16098338e674Sxiaofeibao-xjtu    ("rob_4_4_valid          ", numValidEntries > (RobSize * 3 / 4).U),
1610e836c770SZhaoyang You    ("BR_MIS_PRED            ", misPred),
1611e836c770SZhaoyang You    ("TOTAL_FLUSH            ", io.flushOut.valid)
1612cd365d4cSrvcoresjw  )
16131ca0e4f3SYinan Xu  generatePerfEvent()
1614780712aaSxiaofeibao-xjtu
161585a8d7caSZehao Liu  // max commit-stuck cycle
161685a8d7caSZehao Liu  val deqismmio = Mux(robEntries(deqPtr.value).valid, robEntries(deqPtr.value).mmio, false.B)
161785a8d7caSZehao Liu  val commitStuck = (!io.commits.commitValid.reduce(_ || _) || !io.commits.isCommit) && !deqismmio
161885a8d7caSZehao Liu  val commitStuckCycle = RegInit(0.U(log2Up(maxCommitStuck).W))
161985a8d7caSZehao Liu  when(commitStuck) {
162085a8d7caSZehao Liu    commitStuckCycle := commitStuckCycle + 1.U
162185a8d7caSZehao Liu  }.elsewhen(!commitStuck && RegNext(commitStuck)) {
162285a8d7caSZehao Liu    commitStuckCycle := 0.U
162385a8d7caSZehao Liu  }
162485a8d7caSZehao Liu  // check if stuck > 2^maxCommitStuckCycle
1625*00c6a8aaSGuanghui Cheng  val commitStuck_overflow = commitStuckCycle.andR && (if (wfiResume) true.B else (!hasWFI))
162685a8d7caSZehao Liu  val criticalErrors = Seq(
162785a8d7caSZehao Liu    ("rob_commit_stuck  ", commitStuck_overflow),
162885a8d7caSZehao Liu  )
162985a8d7caSZehao Liu  generateCriticalErrors()
163085a8d7caSZehao Liu
163185a8d7caSZehao Liu
1632780712aaSxiaofeibao-xjtu  // dontTouch for debug
1633780712aaSxiaofeibao-xjtu  if (backendParams.debugEn) {
1634780712aaSxiaofeibao-xjtu    dontTouch(enqPtrVec)
1635780712aaSxiaofeibao-xjtu    dontTouch(deqPtrVec)
1636780712aaSxiaofeibao-xjtu    dontTouch(robEntries)
1637780712aaSxiaofeibao-xjtu    dontTouch(robDeqGroup)
1638780712aaSxiaofeibao-xjtu    dontTouch(robBanks)
1639780712aaSxiaofeibao-xjtu    dontTouch(robBanksRaddrThisLine)
1640780712aaSxiaofeibao-xjtu    dontTouch(robBanksRaddrNextLine)
1641780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataThisLine)
1642780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataNextLine)
1643780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataThisLineUpdate)
1644780712aaSxiaofeibao-xjtu    dontTouch(robBanksRdataNextLineUpdate)
1645571677c9Sxiaofeibao-xjtu    dontTouch(needUpdate)
1646571677c9Sxiaofeibao-xjtu    val exceptionWBsVec = MixedVecInit(exceptionWBs)
1647571677c9Sxiaofeibao-xjtu    dontTouch(exceptionWBsVec)
1648780712aaSxiaofeibao-xjtu    dontTouch(commit_wDeqGroup)
1649780712aaSxiaofeibao-xjtu    dontTouch(commit_vDeqGroup)
1650780712aaSxiaofeibao-xjtu    dontTouch(commitSizeSumSeq)
1651780712aaSxiaofeibao-xjtu    dontTouch(walkSizeSumSeq)
1652780712aaSxiaofeibao-xjtu    dontTouch(commitSizeSumCond)
1653780712aaSxiaofeibao-xjtu    dontTouch(walkSizeSumCond)
1654780712aaSxiaofeibao-xjtu    dontTouch(commitSizeSum)
1655780712aaSxiaofeibao-xjtu    dontTouch(walkSizeSum)
1656780712aaSxiaofeibao-xjtu    dontTouch(realDestSizeSeq)
1657780712aaSxiaofeibao-xjtu    dontTouch(walkDestSizeSeq)
1658780712aaSxiaofeibao-xjtu    dontTouch(io.commits)
1659780712aaSxiaofeibao-xjtu    dontTouch(commitIsVTypeVec)
1660780712aaSxiaofeibao-xjtu    dontTouch(walkIsVTypeVec)
1661780712aaSxiaofeibao-xjtu    dontTouch(commitValidThisLine)
1662780712aaSxiaofeibao-xjtu    dontTouch(commitReadAddr_next)
1663780712aaSxiaofeibao-xjtu    dontTouch(donotNeedWalk)
1664780712aaSxiaofeibao-xjtu    dontTouch(walkPtrVec_next)
1665780712aaSxiaofeibao-xjtu    dontTouch(walkPtrVec)
1666780712aaSxiaofeibao-xjtu    dontTouch(deqPtrVec_next)
1667780712aaSxiaofeibao-xjtu    dontTouch(deqPtrVecForWalk)
1668780712aaSxiaofeibao-xjtu    dontTouch(snapPtrReadBank)
1669780712aaSxiaofeibao-xjtu    dontTouch(snapPtrVecForWalk)
1670780712aaSxiaofeibao-xjtu    dontTouch(shouldWalkVec)
1671780712aaSxiaofeibao-xjtu    dontTouch(walkFinished)
1672780712aaSxiaofeibao-xjtu    dontTouch(changeBankAddrToDeqPtr)
1673780712aaSxiaofeibao-xjtu  }
1674780712aaSxiaofeibao-xjtu  if (env.EnableDifftest) {
1675780712aaSxiaofeibao-xjtu    io.commits.info.map(info => dontTouch(info.debug_pc.get))
1676780712aaSxiaofeibao-xjtu  }
16779aca92b9SYinan Xu}
1678