xref: /XiangShan/src/main/scala/xiangshan/backend/dispatch/NewDispatch.scala (revision 41eedc8d7d71e266629bc1e10aea01a9df3f481c)
10a7d1d5cSxiaofeibao/***************************************************************************************
20a7d1d5cSxiaofeibao* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
30a7d1d5cSxiaofeibao* Copyright (c) 2020-2021 Peng Cheng Laboratory
40a7d1d5cSxiaofeibao*
50a7d1d5cSxiaofeibao* XiangShan is licensed under Mulan PSL v2.
60a7d1d5cSxiaofeibao* You can use this software according to the terms and conditions of the Mulan PSL v2.
70a7d1d5cSxiaofeibao* You may obtain a copy of Mulan PSL v2 at:
80a7d1d5cSxiaofeibao*          http://license.coscl.org.cn/MulanPSL2
90a7d1d5cSxiaofeibao*
100a7d1d5cSxiaofeibao* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
110a7d1d5cSxiaofeibao* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
120a7d1d5cSxiaofeibao* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
130a7d1d5cSxiaofeibao*
140a7d1d5cSxiaofeibao* See the Mulan PSL v2 for more details.
150a7d1d5cSxiaofeibao***************************************************************************************/
160a7d1d5cSxiaofeibao
170a7d1d5cSxiaofeibaopackage xiangshan.backend.dispatch
180a7d1d5cSxiaofeibao
190a7d1d5cSxiaofeibaoimport org.chipsalliance.cde.config.Parameters
200a7d1d5cSxiaofeibaoimport chisel3._
210a7d1d5cSxiaofeibaoimport chisel3.util._
220a7d1d5cSxiaofeibaoimport utility._
230a7d1d5cSxiaofeibaoimport xiangshan.ExceptionNO._
240a7d1d5cSxiaofeibaoimport xiangshan._
250a7d1d5cSxiaofeibaoimport xiangshan.backend.MemCoreTopDownIO
260a7d1d5cSxiaofeibaoimport xiangshan.backend.rob.{RobDispatchTopDownIO, RobEnqIO}
270a7d1d5cSxiaofeibaoimport xiangshan.mem.mdp._
280a7d1d5cSxiaofeibaoimport xiangshan.mem.{HasVLSUParameters, _}
290a7d1d5cSxiaofeibaoimport xiangshan.backend.Bundles.{DecodedInst, DynInst, ExuOH, ExuVec, IssueQueueIQWakeUpBundle}
300a7d1d5cSxiaofeibaoimport xiangshan.backend.fu.{FuConfig, FuType}
310a7d1d5cSxiaofeibaoimport xiangshan.backend.rename.BusyTable
320a7d1d5cSxiaofeibaoimport chisel3.util.experimental.decode._
330a7d1d5cSxiaofeibaoimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
340a7d1d5cSxiaofeibaoimport xiangshan.backend.fu.{FuConfig, FuType}
350a7d1d5cSxiaofeibaoimport xiangshan.backend.rename.BusyTableReadIO
360a7d1d5cSxiaofeibaoimport xiangshan.backend.datapath.DataConfig._
370a7d1d5cSxiaofeibaoimport xiangshan.backend.datapath.WbConfig._
380a7d1d5cSxiaofeibaoimport xiangshan.backend.datapath.DataSource
390a7d1d5cSxiaofeibaoimport xiangshan.backend.datapath.WbConfig.VfWB
400a7d1d5cSxiaofeibaoimport xiangshan.backend.fu.FuType.FuTypeOrR
410a7d1d5cSxiaofeibaoimport xiangshan.backend.dispatch.Dispatch2IqFpImp
420a7d1d5cSxiaofeibaoimport xiangshan.backend.regcache.{RCTagTableReadPort, RegCacheTagTable}
430a7d1d5cSxiaofeibao
440a7d1d5cSxiaofeibao
450a7d1d5cSxiaofeibao// TODO delete trigger message from frontend to iq
460a7d1d5cSxiaofeibaoclass NewDispatch(implicit p: Parameters) extends XSModule with HasPerfEvents with HasVLSUParameters {
470a7d1d5cSxiaofeibao  // std IQ donot need dispatch, only copy sta IQ, but need sta IQ's ready && std IQ's ready
480a7d1d5cSxiaofeibao  val allIssueParams = backendParams.allIssueParams.filter(_.StdCnt == 0)
490a7d1d5cSxiaofeibao  val allExuParams = allIssueParams.map(_.exuBlockParams).flatten
500a7d1d5cSxiaofeibao  val allFuConfigs = allExuParams.map(_.fuConfigs).flatten.toSet.toSeq
510a7d1d5cSxiaofeibao  val sortedFuConfigs = allFuConfigs.sortBy(_.fuType.id)
520a7d1d5cSxiaofeibao  println(s"[NewDispatch] ${allExuParams.map(_.name)}")
530a7d1d5cSxiaofeibao  println(s"[NewDispatch] ${allFuConfigs.map(_.name)}")
540a7d1d5cSxiaofeibao  println(s"[NewDispatch] ${allFuConfigs.map(_.fuType.id)}")
550a7d1d5cSxiaofeibao  println(s"[NewDispatch] ${sortedFuConfigs.map(_.name)}")
560a7d1d5cSxiaofeibao  println(s"[NewDispatch] ${sortedFuConfigs.map(_.fuType.id)}")
570a7d1d5cSxiaofeibao  val fuConfigsInIssueParams = allIssueParams.map(_.allExuParams.map(_.fuConfigs).flatten.toSet.toSeq)
580a7d1d5cSxiaofeibao  val fuMapIQIdx = sortedFuConfigs.map( fu => {
590a7d1d5cSxiaofeibao    val fuInIQIdx = fuConfigsInIssueParams.zipWithIndex.filter { case (f, i) => f.contains(fu) }.map(_._2)
600a7d1d5cSxiaofeibao    (fu -> fuInIQIdx)
610a7d1d5cSxiaofeibao   }
620a7d1d5cSxiaofeibao  )
630a7d1d5cSxiaofeibao  fuMapIQIdx.map { case (fu, iqidx) =>
640a7d1d5cSxiaofeibao    println(s"[NewDispatch] ${fu.name} $iqidx")
650a7d1d5cSxiaofeibao  }
660a7d1d5cSxiaofeibao  val sameIQIdxFus = fuMapIQIdx.map{ case (fu, iqidx) =>
670a7d1d5cSxiaofeibao    fuMapIQIdx.filter(_._2 == iqidx).map(_._1) -> iqidx
680a7d1d5cSxiaofeibao  }.toSet.toSeq
690a7d1d5cSxiaofeibao  val needMultiIQ = sameIQIdxFus.sortBy(_._1.head.fuType.id).filter(_._2.size > 1)
700a7d1d5cSxiaofeibao  val needSingleIQ = sameIQIdxFus.sortBy(_._1.head.fuType.id).filter(_._2.size == 1)
710a7d1d5cSxiaofeibao  needMultiIQ.map { case (fus, iqidx) =>
720a7d1d5cSxiaofeibao    println(s"[NewDispatch] needMultiIQ: ${fus.map(_.name)} $iqidx")
730a7d1d5cSxiaofeibao  }
740a7d1d5cSxiaofeibao  needSingleIQ.map { case (fus, iqidx) =>
750a7d1d5cSxiaofeibao    println(s"[NewDispatch] needSingleIQ: ${fus.map(_.name)} $iqidx")
760a7d1d5cSxiaofeibao  }
770a7d1d5cSxiaofeibao  val fuConfigsInExuParams = allExuParams.map(_.fuConfigs)
780a7d1d5cSxiaofeibao  val fuMapExuIdx = sortedFuConfigs.map { case fu => {
790a7d1d5cSxiaofeibao    val fuInExuIdx = fuConfigsInExuParams.zipWithIndex.filter { case (f, i) => f.contains(fu) }.map(_._2)
800a7d1d5cSxiaofeibao    (fu -> fuInExuIdx)
810a7d1d5cSxiaofeibao    }
820a7d1d5cSxiaofeibao  }
830a7d1d5cSxiaofeibao  val sameExuIdxFus = fuMapExuIdx.map { case (fu, exuidx) =>
840a7d1d5cSxiaofeibao    fuMapExuIdx.filter(_._2 == exuidx).map(_._1) -> exuidx
850a7d1d5cSxiaofeibao  }.toSet.toSeq
860a7d1d5cSxiaofeibao  val needMultiExu = sameExuIdxFus.sortBy(_._1.head.fuType.id).filter(_._2.size > 1).filter{ x =>
870a7d1d5cSxiaofeibao    x._1.map(y => fuMapIQIdx.filter(_._1 == y).head._2.size > 1).reduce(_ && _)
880a7d1d5cSxiaofeibao  }
890a7d1d5cSxiaofeibao
900a7d1d5cSxiaofeibao  val exuNum = allExuParams.size
910a7d1d5cSxiaofeibao  val maxIQSize = allIssueParams.map(_.numEntries).max
920a7d1d5cSxiaofeibao  val IQEnqSum = allIssueParams.map(_.numEnq).sum
930a7d1d5cSxiaofeibao
940a7d1d5cSxiaofeibao  val io = IO(new Bundle {
950a7d1d5cSxiaofeibao    // from rename
960a7d1d5cSxiaofeibao    val renameIn = Vec(RenameWidth, Flipped(ValidIO(new DecodedInst)))
970a7d1d5cSxiaofeibao    val fromRename = Vec(RenameWidth, Flipped(DecoupledIO(new DynInst)))
980a7d1d5cSxiaofeibao    val toRenameAllFire = Output(Bool())
990a7d1d5cSxiaofeibao    // enq Rob
1000a7d1d5cSxiaofeibao    val enqRob = Flipped(new RobEnqIO)
1010a7d1d5cSxiaofeibao    // IssueQueues
1020a7d1d5cSxiaofeibao    val IQValidNumVec = Vec(exuNum, Input(UInt(maxIQSize.U.getWidth.W)))
1030a7d1d5cSxiaofeibao    val toIssueQueues = Vec(IQEnqSum, DecoupledIO(new DynInst))
1040a7d1d5cSxiaofeibao    // to busyTable
1050a7d1d5cSxiaofeibao    // set preg state to ready (write back regfile)
1060a7d1d5cSxiaofeibao    val wbPregsInt = Vec(backendParams.numPregWb(IntData()), Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
1070a7d1d5cSxiaofeibao    val wbPregsFp = Vec(backendParams.numPregWb(FpData()), Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
1080a7d1d5cSxiaofeibao    val wbPregsVec = Vec(backendParams.numPregWb(VecData()), Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
1090a7d1d5cSxiaofeibao    val wbPregsV0 = Vec(backendParams.numPregWb(V0Data()), Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
1100a7d1d5cSxiaofeibao    val wbPregsVl = Vec(backendParams.numPregWb(VlData()), Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
1110a7d1d5cSxiaofeibao    val wakeUpAll = new Bundle {
1120a7d1d5cSxiaofeibao      val wakeUpInt: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(backendParams.intSchdParams.get.genIQWakeUpOutValidBundle)
1130a7d1d5cSxiaofeibao      val wakeUpFp: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(backendParams.fpSchdParams.get.genIQWakeUpOutValidBundle)
1140a7d1d5cSxiaofeibao      val wakeUpVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(backendParams.vfSchdParams.get.genIQWakeUpOutValidBundle)
1150a7d1d5cSxiaofeibao      val wakeUpMem: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(backendParams.memSchdParams.get.genIQWakeUpOutValidBundle)
1160a7d1d5cSxiaofeibao    }
1170a7d1d5cSxiaofeibao    val og0Cancel = Input(ExuVec())
1180a7d1d5cSxiaofeibao    val ldCancel = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
1190a7d1d5cSxiaofeibao    // from MemBlock
1200a7d1d5cSxiaofeibao    val fromMem = new Bundle {
1210a7d1d5cSxiaofeibao      val lcommit = Input(UInt(log2Up(CommitWidth + 1).W))
1220a7d1d5cSxiaofeibao      val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB
1230a7d1d5cSxiaofeibao      val lqDeqPtr = Input(new LqPtr)
1240a7d1d5cSxiaofeibao      val sqDeqPtr = Input(new SqPtr)
1250a7d1d5cSxiaofeibao      // from lsq
1260a7d1d5cSxiaofeibao      val lqCancelCnt = Input(UInt(log2Up(VirtualLoadQueueSize + 1).W))
1270a7d1d5cSxiaofeibao      val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
1280a7d1d5cSxiaofeibao    }
1290a7d1d5cSxiaofeibao    //toMem
1300a7d1d5cSxiaofeibao    val toMem = new Bundle {
1310a7d1d5cSxiaofeibao      val lsqEnqIO = Flipped(new LsqEnqIO)
1320a7d1d5cSxiaofeibao    }
1330a7d1d5cSxiaofeibao    // redirect
1340a7d1d5cSxiaofeibao    val redirect = Flipped(ValidIO(new Redirect))
1350a7d1d5cSxiaofeibao    // singleStep
1360a7d1d5cSxiaofeibao    val singleStep = Input(Bool())
1370a7d1d5cSxiaofeibao    // lfst
1380a7d1d5cSxiaofeibao    val lfst = new DispatchLFSTIO
1390a7d1d5cSxiaofeibao
1400a7d1d5cSxiaofeibao    // perf only
1410a7d1d5cSxiaofeibao    val robHead = Input(new DynInst)
1420a7d1d5cSxiaofeibao    val stallReason = Flipped(new StallReasonIO(RenameWidth))
1430a7d1d5cSxiaofeibao    val lqCanAccept = Input(Bool())
1440a7d1d5cSxiaofeibao    val sqCanAccept = Input(Bool())
1450a7d1d5cSxiaofeibao    val robHeadNotReady = Input(Bool())
1460a7d1d5cSxiaofeibao    val robFull = Input(Bool())
1470a7d1d5cSxiaofeibao    val debugTopDown = new Bundle {
1480a7d1d5cSxiaofeibao      val fromRob = Flipped(new RobDispatchTopDownIO)
1490a7d1d5cSxiaofeibao      val fromCore = new CoreDispatchTopDownIO
1500a7d1d5cSxiaofeibao    }
1510a7d1d5cSxiaofeibao  })
1520a7d1d5cSxiaofeibao  // Deq for std's IQ is not assigned in Dispatch2Iq, so add one more src for it.
1530a7d1d5cSxiaofeibao  val issueBlockParams = backendParams.allIssueParams
1540a7d1d5cSxiaofeibao  val renameIn = io.renameIn
1550a7d1d5cSxiaofeibao  val fromRename = io.fromRename
1560a7d1d5cSxiaofeibao  io.toRenameAllFire := io.fromRename.map(x => !x.valid || x.fire).reduce(_ && _)
1570a7d1d5cSxiaofeibao  val fromRenameUpdate = Wire(Vec(RenameWidth, Flipped(ValidIO(new DynInst))))
1580a7d1d5cSxiaofeibao  fromRenameUpdate := fromRename
1590a7d1d5cSxiaofeibao  val renameWidth = io.fromRename.size
1600a7d1d5cSxiaofeibao  val issueQueueCount = io.IQValidNumVec
1610a7d1d5cSxiaofeibao  val issueQueueNum = allIssueParams.size
1620a7d1d5cSxiaofeibao  // int fp vec v0 vl
1630a7d1d5cSxiaofeibao  val numRegType = 5
1640a7d1d5cSxiaofeibao  val idxRegTypeInt = allFuConfigs.map(x => {
1650a7d1d5cSxiaofeibao    x.srcData.map(xx => {
1660a7d1d5cSxiaofeibao      xx.zipWithIndex.filter(y => IntRegSrcDataSet.contains(y._1)).map(_._2)
1670a7d1d5cSxiaofeibao    }).flatten
1680a7d1d5cSxiaofeibao  }).flatten.toSet.toSeq.sorted
1690a7d1d5cSxiaofeibao  val idxRegTypeFp = allFuConfigs.map(x => {
1700a7d1d5cSxiaofeibao    x.srcData.map(xx => {
1710a7d1d5cSxiaofeibao      xx.zipWithIndex.filter(y => FpRegSrcDataSet.contains(y._1)).map(_._2)
1720a7d1d5cSxiaofeibao    }).flatten
1730a7d1d5cSxiaofeibao  }).flatten.toSet.toSeq.sorted
1740a7d1d5cSxiaofeibao  val idxRegTypeVec = allFuConfigs.map(x => {
1750a7d1d5cSxiaofeibao    x.srcData.map(xx => {
1760a7d1d5cSxiaofeibao      xx.zipWithIndex.filter(y => VecRegSrcDataSet.contains(y._1)).map(_._2)
1770a7d1d5cSxiaofeibao    }).flatten
1780a7d1d5cSxiaofeibao  }).flatten.toSet.toSeq.sorted
1790a7d1d5cSxiaofeibao  val idxRegTypeV0 = allFuConfigs.map(x => {
1800a7d1d5cSxiaofeibao    x.srcData.map(xx => {
1810a7d1d5cSxiaofeibao      xx.zipWithIndex.filter(y => V0RegSrcDataSet.contains(y._1)).map(_._2)
1820a7d1d5cSxiaofeibao    }).flatten
1830a7d1d5cSxiaofeibao  }).flatten.toSet.toSeq.sorted
1840a7d1d5cSxiaofeibao  val idxRegTypeVl = allFuConfigs.map(x => {
1850a7d1d5cSxiaofeibao    x.srcData.map(xx => {
1860a7d1d5cSxiaofeibao      xx.zipWithIndex.filter(y => VlRegSrcDataSet.contains(y._1)).map(_._2)
1870a7d1d5cSxiaofeibao    }).flatten
1880a7d1d5cSxiaofeibao  }).flatten.toSet.toSeq.sorted
1890a7d1d5cSxiaofeibao  println(s"[NewDispatch] idxRegTypeInt: $idxRegTypeInt")
1900a7d1d5cSxiaofeibao  println(s"[NewDispatch] idxRegTypeFp: $idxRegTypeFp")
1910a7d1d5cSxiaofeibao  println(s"[NewDispatch] idxRegTypeVec: $idxRegTypeVec")
1920a7d1d5cSxiaofeibao  println(s"[NewDispatch] idxRegTypeV0: $idxRegTypeV0")
1930a7d1d5cSxiaofeibao  println(s"[NewDispatch] idxRegTypeVl: $idxRegTypeVl")
1940a7d1d5cSxiaofeibao  val numRegSrc: Int = issueBlockParams.map(_.exuBlockParams.map(
1950a7d1d5cSxiaofeibao    x => if (x.hasStdFu) x.numRegSrc + 1 else x.numRegSrc
1960a7d1d5cSxiaofeibao  ).max).max
1970a7d1d5cSxiaofeibao
1980a7d1d5cSxiaofeibao  val numRegSrcInt: Int = issueBlockParams.map(_.exuBlockParams.map(
1990a7d1d5cSxiaofeibao    x => if (x.hasStdFu) x.numIntSrc + 1 else x.numIntSrc
2000a7d1d5cSxiaofeibao  ).max).max
2010a7d1d5cSxiaofeibao  val numRegSrcFp: Int = issueBlockParams.map(_.exuBlockParams.map(
2020a7d1d5cSxiaofeibao    x => if (x.hasStdFu) x.numFpSrc + 1 else x.numFpSrc
2030a7d1d5cSxiaofeibao  ).max).max
2040a7d1d5cSxiaofeibao  val numRegSrcVf: Int = issueBlockParams.map(_.exuBlockParams.map(
2050a7d1d5cSxiaofeibao    x => x.numVecSrc
2060a7d1d5cSxiaofeibao  ).max).max
2070a7d1d5cSxiaofeibao  val numRegSrcV0: Int = issueBlockParams.map(_.exuBlockParams.map(
2080a7d1d5cSxiaofeibao    x => x.numV0Src
2090a7d1d5cSxiaofeibao  ).max).max
2100a7d1d5cSxiaofeibao  val numRegSrcVl: Int = issueBlockParams.map(_.exuBlockParams.map(
2110a7d1d5cSxiaofeibao    x => x.numVlSrc
2120a7d1d5cSxiaofeibao  ).max).max
2130a7d1d5cSxiaofeibao
2140a7d1d5cSxiaofeibao  println(s"[Dispatch2Iq] numRegSrc: ${numRegSrc}, numRegSrcInt: ${numRegSrcInt}, numRegSrcFp: ${numRegSrcFp}, " +
2150a7d1d5cSxiaofeibao    s"numRegSrcVf: ${numRegSrcVf}, numRegSrcV0: ${numRegSrcV0}, numRegSrcVl: ${numRegSrcVl}")
2160a7d1d5cSxiaofeibao
2170a7d1d5cSxiaofeibao  // RegCacheTagTable Module
2180a7d1d5cSxiaofeibao  val rcTagTable = Module(new RegCacheTagTable(numRegSrcInt * renameWidth))
2190a7d1d5cSxiaofeibao  // BusyTable Modules
2200a7d1d5cSxiaofeibao  val intBusyTable = Module(new BusyTable(numRegSrcInt * renameWidth, backendParams.numPregWb(IntData()), IntPhyRegs, IntWB()))
2210a7d1d5cSxiaofeibao  val fpBusyTable = Module(new BusyTable(numRegSrcFp * renameWidth, backendParams.numPregWb(FpData()), FpPhyRegs, FpWB()))
2220a7d1d5cSxiaofeibao  val vecBusyTable = Module(new BusyTable(numRegSrcVf * renameWidth, backendParams.numPregWb(VecData()), VfPhyRegs, VfWB()))
2230a7d1d5cSxiaofeibao  val v0BusyTable = Module(new BusyTable(numRegSrcV0 * renameWidth, backendParams.numPregWb(V0Data()), V0PhyRegs, V0WB()))
2240a7d1d5cSxiaofeibao  val vlBusyTable = Module(new BusyTable(numRegSrcVl * renameWidth, backendParams.numPregWb(VlData()), VlPhyRegs, VlWB()))
2250a7d1d5cSxiaofeibao  val busyTables = Seq(intBusyTable, fpBusyTable, vecBusyTable, v0BusyTable, vlBusyTable)
2260a7d1d5cSxiaofeibao  val wbPregs = Seq(io.wbPregsInt, io.wbPregsFp, io.wbPregsVec, io.wbPregsV0, io.wbPregsVl)
2270a7d1d5cSxiaofeibao  val idxRegType = Seq(idxRegTypeInt, idxRegTypeFp, idxRegTypeVec, idxRegTypeV0, idxRegTypeVl)
2280a7d1d5cSxiaofeibao  val allocPregsValid = Wire(Vec(busyTables.size, Vec(RenameWidth, Bool())))
2290a7d1d5cSxiaofeibao  allocPregsValid(0) := VecInit(fromRename.map(x => x.valid && x.bits.rfWen && !x.bits.eliminatedMove))
2300a7d1d5cSxiaofeibao  allocPregsValid(1) := VecInit(fromRename.map(x => x.valid && x.bits.fpWen))
2310a7d1d5cSxiaofeibao  allocPregsValid(2) := VecInit(fromRename.map(x => x.valid && x.bits.vecWen))
2320a7d1d5cSxiaofeibao  allocPregsValid(3) := VecInit(fromRename.map(x => x.valid && x.bits.v0Wen))
2330a7d1d5cSxiaofeibao  allocPregsValid(4) := VecInit(fromRename.map(x => x.valid && x.bits.vlWen))
2340a7d1d5cSxiaofeibao  val allocPregs = Wire(Vec(busyTables.size, Vec(RenameWidth, ValidIO(UInt(PhyRegIdxWidth.W)))))
2350a7d1d5cSxiaofeibao  allocPregs.zip(allocPregsValid).map(x =>{
2360a7d1d5cSxiaofeibao    x._1.zip(x._2).zipWithIndex.map{case ((sink, source), i) => {
2370a7d1d5cSxiaofeibao      sink.valid := source
2380a7d1d5cSxiaofeibao      sink.bits := fromRename(i).bits.pdest
2390a7d1d5cSxiaofeibao    }}
2400a7d1d5cSxiaofeibao  })
2410a7d1d5cSxiaofeibao  val wakeUp = io.wakeUpAll.wakeUpInt ++ io.wakeUpAll.wakeUpFp ++ io.wakeUpAll.wakeUpVec ++ io.wakeUpAll.wakeUpMem
2420a7d1d5cSxiaofeibao  busyTables.zip(wbPregs).zip(allocPregs).map{ case ((b, w), a) => {
2430a7d1d5cSxiaofeibao    b.io.wakeUpInt := io.wakeUpAll.wakeUpInt
2440a7d1d5cSxiaofeibao    b.io.wakeUpFp  := io.wakeUpAll.wakeUpFp
2450a7d1d5cSxiaofeibao    b.io.wakeUpVec := io.wakeUpAll.wakeUpVec
2460a7d1d5cSxiaofeibao    b.io.wakeUpMem := io.wakeUpAll.wakeUpMem
2470a7d1d5cSxiaofeibao    b.io.og0Cancel := io.og0Cancel
2480a7d1d5cSxiaofeibao    b.io.ldCancel := io.ldCancel
2490a7d1d5cSxiaofeibao    b.io.wbPregs := w
2500a7d1d5cSxiaofeibao    b.io.allocPregs := a
2510a7d1d5cSxiaofeibao  }}
2520a7d1d5cSxiaofeibao  rcTagTable.io.allocPregs.zip(allocPregs(0)).map(x => x._1 := x._2)
2530a7d1d5cSxiaofeibao  rcTagTable.io.wakeupFromIQ := io.wakeUpAll.wakeUpInt ++ io.wakeUpAll.wakeUpMem
2540a7d1d5cSxiaofeibao  rcTagTable.io.og0Cancel := io.og0Cancel
2550a7d1d5cSxiaofeibao  rcTagTable.io.ldCancel := io.ldCancel
2560a7d1d5cSxiaofeibao  busyTables.zip(idxRegType).zipWithIndex.map { case ((b, idxseq), i) => {
2570a7d1d5cSxiaofeibao    val readAddr = VecInit(fromRename.map(x => x.bits.psrc.zipWithIndex.filter(xx => idxseq.contains(xx._2)).map(_._1)).flatten)
2580a7d1d5cSxiaofeibao    val readValid = VecInit(fromRename.map(x => x.bits.psrc.zipWithIndex.filter(xx => idxseq.contains(xx._2)).map(y => x.valid && SrcType.isXp(x.bits.srcType(y._2)))).flatten)
2590a7d1d5cSxiaofeibao    b.io.read.map(_.req).zip(readAddr).map(x => x._1 := x._2)
2600a7d1d5cSxiaofeibao    // only int src need srcLoadDependency, src0 src1
2610a7d1d5cSxiaofeibao    if (i == 0) {
2620a7d1d5cSxiaofeibao      val srcLoadDependencyUpdate = fromRenameUpdate.map(x => x.bits.srcLoadDependency.zipWithIndex.filter(x => idxseq.contains(x._2)).map(_._1)).flatten
2630a7d1d5cSxiaofeibao      val srcType = fromRenameUpdate.map(x => x.bits.srcType.zipWithIndex.filter(x => idxseq.contains(x._2)).map(_._1)).flatten
2640a7d1d5cSxiaofeibao      // for std, int src need srcLoadDependency, fp src donot need srcLoadDependency
2650a7d1d5cSxiaofeibao      srcLoadDependencyUpdate.lazyZip(b.io.read.map(_.loadDependency)).lazyZip(srcType).map{ case (sink, source, srctype) =>
2660a7d1d5cSxiaofeibao        sink := Mux(SrcType.isXp(srctype), source, 0.U.asTypeOf(sink))
2670a7d1d5cSxiaofeibao      }
2680a7d1d5cSxiaofeibao      // only int src need rcTag
2690a7d1d5cSxiaofeibao      val rcTagUpdate = fromRenameUpdate.map(x => x.bits.regCacheIdx.zipWithIndex.filter(x => idxseq.contains(x._2)).map(_._1)).flatten
2700a7d1d5cSxiaofeibao      rcTagUpdate.zip(rcTagTable.io.readPorts.map(_.addr)).map(x => x._1 := x._2)
2710a7d1d5cSxiaofeibao      val useRegCacheUpdate = fromRenameUpdate.map(x => x.bits.useRegCache.zipWithIndex.filter(x => idxseq.contains(x._2)).map(_._1)).flatten
2720a7d1d5cSxiaofeibao      useRegCacheUpdate.zip(rcTagTable.io.readPorts.map(_.valid)).map(x => x._1 := x._2)
2730a7d1d5cSxiaofeibao      rcTagTable.io.readPorts.map(_.ren).zip(readValid).map(x => x._1 := x._2)
2740a7d1d5cSxiaofeibao      rcTagTable.io.readPorts.map(_.tag).zip(readAddr).map(x => x._1 := x._2)
2750a7d1d5cSxiaofeibao    }
2760a7d1d5cSxiaofeibao  }}
2770a7d1d5cSxiaofeibao  val allSrcState = Wire(Vec(renameWidth, Vec(numRegSrc, Vec(numRegType, Bool()))))
2780a7d1d5cSxiaofeibao  for (i <- 0 until renameWidth){
2790a7d1d5cSxiaofeibao    for (j <- 0 until numRegSrc){
2800a7d1d5cSxiaofeibao      for (k <- 0 until numRegType){
2810a7d1d5cSxiaofeibao        if (!idxRegType(k).contains(j)) {
2820a7d1d5cSxiaofeibao          allSrcState(i)(j)(k) := false.B
2830a7d1d5cSxiaofeibao        }
2840a7d1d5cSxiaofeibao        else {
2850a7d1d5cSxiaofeibao          val readidx = i * idxRegType(k).size + idxRegType(k).indexOf(j)
2860a7d1d5cSxiaofeibao          val readEn = k match {
2870a7d1d5cSxiaofeibao            case 0 => SrcType.isXp(fromRename(i).bits.srcType(j))
2880a7d1d5cSxiaofeibao            case 1 => SrcType.isFp(fromRename(i).bits.srcType(j))
2890a7d1d5cSxiaofeibao            case 2 => SrcType.isVp(fromRename(i).bits.srcType(j))
2900a7d1d5cSxiaofeibao            case 3 => SrcType.isV0(fromRename(i).bits.srcType(j))
2910a7d1d5cSxiaofeibao            case 4 => true.B
2920a7d1d5cSxiaofeibao          }
2930a7d1d5cSxiaofeibao          allSrcState(i)(j)(k) := readEn && busyTables(k).io.read(readidx).resp || SrcType.isImm(fromRename(i).bits.srcType(j))
2940a7d1d5cSxiaofeibao        }
2950a7d1d5cSxiaofeibao      }
2960a7d1d5cSxiaofeibao    }
2970a7d1d5cSxiaofeibao  }
2980a7d1d5cSxiaofeibao
2990a7d1d5cSxiaofeibao
3000a7d1d5cSxiaofeibao
3010a7d1d5cSxiaofeibao  val minIQSelAll = Wire(Vec(needMultiExu.size, Vec(renameWidth, Vec(issueQueueNum, Bool()))))
3020a7d1d5cSxiaofeibao  needMultiExu.zipWithIndex.map{ case ((fus, exuidx), needMultiExuidx) => {
3030a7d1d5cSxiaofeibao    val suffix = fus.map(_.name).mkString("_")
3040a7d1d5cSxiaofeibao    val iqNum = exuidx.size
3050a7d1d5cSxiaofeibao    val iqidx = allIssueParams.map(_.exuBlockParams.map(_.fuConfigs).flatten.toSet.toSeq).zipWithIndex.filter{x => fus.toSet.subsetOf(x._1.toSet)}.map(_._2)
3060a7d1d5cSxiaofeibao    println(s"[NewDispatch] ${fus.map(_.name)};iqidx:$iqidx;exuIdx:$exuidx")
3070a7d1d5cSxiaofeibao    val compareMatrix = Wire(Vec(iqNum, Vec(iqNum, Bool()))).suggestName(s"compareMatrix_$suffix")
3080a7d1d5cSxiaofeibao    for (i <- 0 until iqNum) {
3090a7d1d5cSxiaofeibao      for (j <- 0 until iqNum) {
3100a7d1d5cSxiaofeibao        if (i == j) compareMatrix(i)(j) := false.B
3110a7d1d5cSxiaofeibao        else if (i < j) compareMatrix(i)(j) := issueQueueCount(exuidx(i)) < issueQueueCount(exuidx(j))
3120a7d1d5cSxiaofeibao        else compareMatrix(i)(j) := !compareMatrix(j)(i)
3130a7d1d5cSxiaofeibao      }
3140a7d1d5cSxiaofeibao    }
3150a7d1d5cSxiaofeibao    val IQSort = Reg(Vec(iqNum, Vec(iqNum, Bool()))).suggestName(s"IQSort_$suffix}")
3160a7d1d5cSxiaofeibao    for (i <- 0 until iqNum){
3170a7d1d5cSxiaofeibao      // i = 0 minimum iq, i = iqNum - 1 -> maximum iq
3180a7d1d5cSxiaofeibao      IQSort(i) := compareMatrix.map(x => PopCount(x) === (iqNum - 1 - i).U)
3190a7d1d5cSxiaofeibao    }
3200a7d1d5cSxiaofeibao    val minIQSel = Wire(Vec(renameWidth, Vec(issueQueueNum, Bool()))).suggestName(s"minIQSel_$suffix")
3210a7d1d5cSxiaofeibao    for (i <- 0 until renameWidth){
3220a7d1d5cSxiaofeibao      val minIQSel_ith = IQSort(i % iqNum)
3230a7d1d5cSxiaofeibao      println(s"minIQSel_${i}th_$suffix = IQSort(${i % iqNum})")
3240a7d1d5cSxiaofeibao      for (j <- 0 until issueQueueNum){
3250a7d1d5cSxiaofeibao        minIQSel(i)(j) := false.B
3260a7d1d5cSxiaofeibao        if (iqidx.contains(j)){
3270a7d1d5cSxiaofeibao          minIQSel(i)(j) := minIQSel_ith(iqidx.indexOf(j))
3280a7d1d5cSxiaofeibao          println(s"minIQSel_${suffix}_${i}_${j} = minIQSel_ith(iqidx.indexOf(${j}))")
3290a7d1d5cSxiaofeibao        }
3300a7d1d5cSxiaofeibao      }
3310a7d1d5cSxiaofeibao    }
3320a7d1d5cSxiaofeibao    minIQSelAll(needMultiExuidx) := minIQSel
3330a7d1d5cSxiaofeibao    if (backendParams.debugEn){
3340a7d1d5cSxiaofeibao      dontTouch(compareMatrix)
3350a7d1d5cSxiaofeibao      dontTouch(IQSort)
3360a7d1d5cSxiaofeibao      dontTouch(minIQSel)
3370a7d1d5cSxiaofeibao    }
3380a7d1d5cSxiaofeibao  }
3390a7d1d5cSxiaofeibao  }
3400a7d1d5cSxiaofeibao  val fuConfigSeq = needMultiExu.map(_._1)
3410a7d1d5cSxiaofeibao  val fuTypeOH = Wire(Vec(renameWidth, Vec(needMultiExu.size, Bool())))
3420a7d1d5cSxiaofeibao  fuTypeOH.zip(renameIn).map{ case(oh, in) => {
3430a7d1d5cSxiaofeibao    oh := fuConfigSeq.map(x => x.map(xx => in.bits.fuType(xx.fuType.id)).reduce(_ || _) && in.valid)
3440a7d1d5cSxiaofeibao  }
3450a7d1d5cSxiaofeibao  }
3460a7d1d5cSxiaofeibao  // not count itself
3470a7d1d5cSxiaofeibao  val popFuTypeOH = Wire(Vec(renameWidth, Vec(needMultiExu.size, UInt((renameWidth-1).U.getWidth.W))))
3480a7d1d5cSxiaofeibao  popFuTypeOH.zipWithIndex.map{ case (pop, idx) => {
3490a7d1d5cSxiaofeibao    if (idx == 0){
3500a7d1d5cSxiaofeibao      pop := 0.U.asTypeOf(pop)
3510a7d1d5cSxiaofeibao    }
3520a7d1d5cSxiaofeibao    else {
3530a7d1d5cSxiaofeibao      pop.zipWithIndex.map{ case (p, i) => {
3540a7d1d5cSxiaofeibao        p := PopCount(fuTypeOH.take(idx).map(x => x(i)))
3550a7d1d5cSxiaofeibao        }
3560a7d1d5cSxiaofeibao      }
3570a7d1d5cSxiaofeibao    }
3580a7d1d5cSxiaofeibao  }}
3590a7d1d5cSxiaofeibao  val uopSelIQ = Reg(Vec(renameWidth, Vec(issueQueueNum, Bool())))
3600a7d1d5cSxiaofeibao  val fuTypeOHSingle = Wire(Vec(renameWidth, Vec(needSingleIQ.size, Bool())))
3610a7d1d5cSxiaofeibao  fuTypeOHSingle.zip(renameIn).map{ case (oh, in) => {
3620a7d1d5cSxiaofeibao    oh := needSingleIQ.map(_._1).map(x => x.map(xx => in.valid && in.bits.fuType(xx.fuType.id)).reduce(_ || _))
3630a7d1d5cSxiaofeibao  }}
3640a7d1d5cSxiaofeibao  val uopSelIQSingle = Wire(Vec(needSingleIQ.size, Vec(issueQueueNum, Bool())))
3650a7d1d5cSxiaofeibao  uopSelIQSingle := VecInit(needSingleIQ.map(_._2).flatten.map(x => VecInit((1.U(issueQueueNum.W) << x)(issueQueueNum-1, 0).asBools)))
3660a7d1d5cSxiaofeibao  uopSelIQ.zipWithIndex.map{ case (u, i) => {
3670a7d1d5cSxiaofeibao    when(io.toRenameAllFire){
3680a7d1d5cSxiaofeibao      u := Mux(renameIn(i).valid,
3690a7d1d5cSxiaofeibao                Mux(fuTypeOH(i).asUInt.orR,
3700a7d1d5cSxiaofeibao                  Mux1H(fuTypeOH(i), minIQSelAll)(Mux1H(fuTypeOH(i), popFuTypeOH(i))),
3710a7d1d5cSxiaofeibao                  Mux1H(fuTypeOHSingle(i), uopSelIQSingle)),
3720a7d1d5cSxiaofeibao                0.U.asTypeOf(u)
3730a7d1d5cSxiaofeibao              )
3740a7d1d5cSxiaofeibao    }.elsewhen(io.fromRename(i).fire){
3750a7d1d5cSxiaofeibao      u := 0.U.asTypeOf(u)
3760a7d1d5cSxiaofeibao    }
3770a7d1d5cSxiaofeibao  }}
3780a7d1d5cSxiaofeibao  val uopSelIQMatrix = Wire(Vec(renameWidth, Vec(issueQueueNum, UInt(renameWidth.U.getWidth.W))))
3790a7d1d5cSxiaofeibao  uopSelIQMatrix.zipWithIndex.map{ case (u, i) => {
3800a7d1d5cSxiaofeibao    u.zipWithIndex.map{ case (uu, j) => {
3810a7d1d5cSxiaofeibao     uu := PopCount(uopSelIQ.take(i+1).map(x => x.zipWithIndex.filter(_._2 == j).map(_._1)).flatten)
3820a7d1d5cSxiaofeibao    }}
3830a7d1d5cSxiaofeibao  }}
3840a7d1d5cSxiaofeibao  val IQSelUop = Wire(Vec(IQEnqSum, ValidIO(new DynInst)))
3850a7d1d5cSxiaofeibao  val uopBlockByIQ = Wire(Vec(renameWidth, Bool()))
3860a7d1d5cSxiaofeibao  val allowDispatch = Wire(Vec(renameWidth, Bool()))
3870a7d1d5cSxiaofeibao  val thisCanActualOut = Wire(Vec(renameWidth, Bool()))
3880a7d1d5cSxiaofeibao  val lsqCanAccept = Wire(Bool())
3890a7d1d5cSxiaofeibao  for (i <- 0 until RenameWidth){
3900a7d1d5cSxiaofeibao    // update valid logic
3910a7d1d5cSxiaofeibao    fromRenameUpdate(i).valid := fromRename(i).valid && allowDispatch(i) && !uopBlockByIQ(i) && thisCanActualOut(i) && lsqCanAccept && !fromRename(i).bits.eliminatedMove
3920a7d1d5cSxiaofeibao    fromRename(i).ready := allowDispatch(i) && !uopBlockByIQ(i) && thisCanActualOut(i) && lsqCanAccept
3930a7d1d5cSxiaofeibao  }
394*41eedc8dSlinzhida  for (i <- 0 until RenameWidth){
395*41eedc8dSlinzhida    // check is drop amocas sta
396*41eedc8dSlinzhida    fromRenameUpdate(i).bits.isDropAmocasSta := fromRename(i).bits.isAMOCAS && fromRename(i).bits.uopIdx(0) === 1.U
397*41eedc8dSlinzhida  }
3980a7d1d5cSxiaofeibao  var temp = 0
3990a7d1d5cSxiaofeibao  allIssueParams.zipWithIndex.map{ case(issue, iqidx) => {
4000a7d1d5cSxiaofeibao    for (i <- 0 until issue.numEnq){
4010a7d1d5cSxiaofeibao      val oh = Wire(Vec(renameWidth, Bool())).suggestName(s"oh_IQSelUop_$temp")
4020a7d1d5cSxiaofeibao      oh := uopSelIQMatrix.map(_(iqidx)).map(_ === (i+1).U)
4030a7d1d5cSxiaofeibao      IQSelUop(temp) := PriorityMux(oh, fromRenameUpdate)
4040a7d1d5cSxiaofeibao      // there only assign valid not use PriorityMuxDefalut for better timing
4050a7d1d5cSxiaofeibao      IQSelUop(temp).valid := PriorityMuxDefault(oh.zip(fromRenameUpdate.map(_.valid)), false.B)
4060a7d1d5cSxiaofeibao      val allFuThisIQ = issue.exuBlockParams.map(_.fuConfigs).flatten.toSet.toSeq
4070a7d1d5cSxiaofeibao      val hasStaFu = !allFuThisIQ.filter(_.name == "sta").isEmpty
4080a7d1d5cSxiaofeibao      for (j <- 0 until numRegSrc){
4090a7d1d5cSxiaofeibao        val maskForStd = hasStaFu && (j == 1)
4100a7d1d5cSxiaofeibao        val thisSrcHasInt = allFuThisIQ.map(x => {x.srcData.map(xx => {if (j < xx.size) IntRegSrcDataSet.contains(xx(j)) else false}).reduce(_ || _)}).reduce(_ || _)
4110a7d1d5cSxiaofeibao        val thisSrcHasFp  = allFuThisIQ.map(x => {x.srcData.map(xx => {if (j < xx.size) FpRegSrcDataSet.contains(xx(j))  else false}).reduce(_ || _)}).reduce(_ || _)
4120a7d1d5cSxiaofeibao        val thisSrcHasVec = allFuThisIQ.map(x => {x.srcData.map(xx => {if (j < xx.size) VecRegSrcDataSet.contains(xx(j)) else false}).reduce(_ || _)}).reduce(_ || _)
4130a7d1d5cSxiaofeibao        val thisSrcHasV0  = allFuThisIQ.map(x => {x.srcData.map(xx => {if (j < xx.size) V0RegSrcDataSet.contains(xx(j))  else false}).reduce(_ || _)}).reduce(_ || _)
4140a7d1d5cSxiaofeibao        val thisSrcHasVl  = allFuThisIQ.map(x => {x.srcData.map(xx => {if (j < xx.size) VlRegSrcDataSet.contains(xx(j))  else false}).reduce(_ || _)}).reduce(_ || _)
4150a7d1d5cSxiaofeibao        val selSrcState = Seq(thisSrcHasInt || maskForStd, thisSrcHasFp || maskForStd, thisSrcHasVec, thisSrcHasV0, thisSrcHasVl)
4160a7d1d5cSxiaofeibao        IQSelUop(temp).bits.srcState(j) := PriorityMux(oh, allSrcState)(j).zip(selSrcState).filter(_._2 == true).map(_._1).foldLeft(false.B)(_ || _).asUInt
4170a7d1d5cSxiaofeibao      }
4180a7d1d5cSxiaofeibao      temp = temp + 1
4190a7d1d5cSxiaofeibao      if (backendParams.debugEn){
4200a7d1d5cSxiaofeibao        dontTouch(oh)
4210a7d1d5cSxiaofeibao      }
4220a7d1d5cSxiaofeibao    }
4230a7d1d5cSxiaofeibao  }}
4240a7d1d5cSxiaofeibao  temp = 0
4250a7d1d5cSxiaofeibao  val uopBlockMatrix = Wire(Vec(renameWidth, Vec(issueQueueNum, Bool())))
4260a7d1d5cSxiaofeibao  val uopBlockMatrixForAssign = allIssueParams.zipWithIndex.map { case (issue, iqidx) => {
4270a7d1d5cSxiaofeibao    val result = uopSelIQMatrix.map(_(iqidx)).map(x => Mux(io.toIssueQueues(temp).ready, x > issue.numEnq.U, x.orR))
4280a7d1d5cSxiaofeibao    temp = temp + issue.numEnq
4290a7d1d5cSxiaofeibao    result
4300a7d1d5cSxiaofeibao  }}.transpose
4310a7d1d5cSxiaofeibao  uopBlockMatrix.zip(uopBlockMatrixForAssign).map(x => x._1 := VecInit(x._2))
4320a7d1d5cSxiaofeibao  uopBlockByIQ := uopBlockMatrix.map(_.reduce(_ || _))
4330a7d1d5cSxiaofeibao  io.toIssueQueues.zip(IQSelUop).map(x => {
4340a7d1d5cSxiaofeibao    x._1.valid := x._2.valid
4350a7d1d5cSxiaofeibao    x._1.bits := x._2.bits
4360a7d1d5cSxiaofeibao  })
4370a7d1d5cSxiaofeibao  if (backendParams.debugEn){
4380a7d1d5cSxiaofeibao    dontTouch(uopSelIQMatrix)
4390a7d1d5cSxiaofeibao    dontTouch(IQSelUop)
4400a7d1d5cSxiaofeibao    dontTouch(fromRenameUpdate)
4410a7d1d5cSxiaofeibao    dontTouch(uopBlockByIQ)
4420a7d1d5cSxiaofeibao    dontTouch(allowDispatch)
4430a7d1d5cSxiaofeibao    dontTouch(thisCanActualOut)
4440a7d1d5cSxiaofeibao    dontTouch(popFuTypeOH)
4450a7d1d5cSxiaofeibao    dontTouch(fuTypeOH)
4460a7d1d5cSxiaofeibao    dontTouch(fuTypeOHSingle)
4470a7d1d5cSxiaofeibao    dontTouch(minIQSelAll)
4480a7d1d5cSxiaofeibao  }
4490a7d1d5cSxiaofeibao  ///////////////////////////////////////////////////////////
4500a7d1d5cSxiaofeibao
4510a7d1d5cSxiaofeibao  val lsqEnqCtrl = Module(new LsqEnqCtrl)
4520a7d1d5cSxiaofeibao
4530a7d1d5cSxiaofeibao  // TODO: check lsqEnqCtrl redirect logic
4540a7d1d5cSxiaofeibao  // here is RegNext because dispatch2iq use s2_s4_redirect, newDispatch use s1_s3_redirect
4550a7d1d5cSxiaofeibao  lsqEnqCtrl.io.redirect := RegNext(io.redirect)
4560a7d1d5cSxiaofeibao  lsqEnqCtrl.io.lcommit := io.fromMem.lcommit
4570a7d1d5cSxiaofeibao  lsqEnqCtrl.io.scommit := io.fromMem.scommit
4580a7d1d5cSxiaofeibao  lsqEnqCtrl.io.lqCancelCnt := io.fromMem.lqCancelCnt
4590a7d1d5cSxiaofeibao  lsqEnqCtrl.io.sqCancelCnt := io.fromMem.sqCancelCnt
4600a7d1d5cSxiaofeibao  lsqEnqCtrl.io.enq.iqAccept := io.fromRename.map(x => !x.valid || x.fire)
4610a7d1d5cSxiaofeibao  io.toMem.lsqEnqIO <> lsqEnqCtrl.io.enqLsq
4620a7d1d5cSxiaofeibao
4630a7d1d5cSxiaofeibao  private val enqLsqIO = lsqEnqCtrl.io.enq
4640a7d1d5cSxiaofeibao  private val lqFreeCount = lsqEnqCtrl.io.lqFreeCount
4650a7d1d5cSxiaofeibao  private val sqFreeCount = lsqEnqCtrl.io.sqFreeCount
4660a7d1d5cSxiaofeibao
4670a7d1d5cSxiaofeibao  private val numLoadDeq = LSQLdEnqWidth
4680a7d1d5cSxiaofeibao  private val numStoreAMODeq = LSQStEnqWidth
4690a7d1d5cSxiaofeibao  private val numVLoadDeq = LoadPipelineWidth
4700a7d1d5cSxiaofeibao  private val numDeq = enqLsqIO.req.size
4710a7d1d5cSxiaofeibao  lsqCanAccept := enqLsqIO.canAccept
4720a7d1d5cSxiaofeibao
4730a7d1d5cSxiaofeibao  private val isLoadVec = VecInit(fromRename.map(x => x.valid && FuType.isLoad(x.bits.fuType)))
4740a7d1d5cSxiaofeibao  private val isStoreVec = VecInit(fromRename.map(x => x.valid && FuType.isStore(x.bits.fuType)))
4750a7d1d5cSxiaofeibao  private val isAMOVec = fromRename.map(x => x.valid && FuType.isAMO(x.bits.fuType))
4760a7d1d5cSxiaofeibao  private val isStoreAMOVec = fromRename.map(x => x.valid && (FuType.isStore(x.bits.fuType) || FuType.isAMO(x.bits.fuType)))
4770a7d1d5cSxiaofeibao  private val isVLoadVec = VecInit(fromRename.map(x => x.valid && FuType.isVLoad(x.bits.fuType)))
4780a7d1d5cSxiaofeibao  private val isVStoreVec = VecInit(fromRename.map(x => x.valid && FuType.isVStore(x.bits.fuType)))
4790a7d1d5cSxiaofeibao
4800a7d1d5cSxiaofeibao  private val loadCntVec = VecInit(isLoadVec.indices.map(x => PopCount(isLoadVec.slice(0, x + 1))))
4810a7d1d5cSxiaofeibao  private val storeAMOCntVec = VecInit(isStoreAMOVec.indices.map(x => PopCount(isStoreAMOVec.slice(0, x + 1))))
4820a7d1d5cSxiaofeibao  private val vloadCntVec = VecInit(isVLoadVec.indices.map(x => PopCount(isVLoadVec.slice(0, x + 1))))
4830a7d1d5cSxiaofeibao
4840a7d1d5cSxiaofeibao  private val s0_enqLsq_resp = Wire(enqLsqIO.resp.cloneType)
4850a7d1d5cSxiaofeibao  for (i <- 0 until RenameWidth) {
4860a7d1d5cSxiaofeibao    // update lqIdx sqIdx
4870a7d1d5cSxiaofeibao    fromRenameUpdate(i).bits.lqIdx := s0_enqLsq_resp(i).lqIdx
4880a7d1d5cSxiaofeibao    fromRenameUpdate(i).bits.sqIdx := s0_enqLsq_resp(i).sqIdx
4890a7d1d5cSxiaofeibao  }
4900a7d1d5cSxiaofeibao
4910a7d1d5cSxiaofeibao  val loadBlockVec = VecInit(loadCntVec.map(_ > numLoadDeq.U))
4920a7d1d5cSxiaofeibao  val storeAMOBlockVec = VecInit(storeAMOCntVec.map(_ > numStoreAMODeq.U))
4930a7d1d5cSxiaofeibao  val vloadBlockVec = VecInit(vloadCntVec.map(_ > numVLoadDeq.U))
4940a7d1d5cSxiaofeibao  val lsStructBlockVec = VecInit((loadBlockVec.zip(storeAMOBlockVec)).zip(vloadBlockVec).map(x => x._1._1 || x._1._2 || x._2))
4950a7d1d5cSxiaofeibao  if (backendParams.debugEn) {
4960a7d1d5cSxiaofeibao    dontTouch(loadBlockVec)
4970a7d1d5cSxiaofeibao    dontTouch(storeAMOBlockVec)
4980a7d1d5cSxiaofeibao    dontTouch(lsStructBlockVec)
4990a7d1d5cSxiaofeibao    dontTouch(vloadBlockVec)
5000a7d1d5cSxiaofeibao    dontTouch(isLoadVec)
5010a7d1d5cSxiaofeibao    dontTouch(isVLoadVec)
5020a7d1d5cSxiaofeibao    dontTouch(loadCntVec)
5030a7d1d5cSxiaofeibao  }
5040a7d1d5cSxiaofeibao
5050a7d1d5cSxiaofeibao  private val uop = fromRename.map(_.bits)
5060a7d1d5cSxiaofeibao  private val fuType = uop.map(_.fuType)
5070a7d1d5cSxiaofeibao  private val fuOpType = uop.map(_.fuOpType)
5080a7d1d5cSxiaofeibao  private val vtype = uop.map(_.vpu.vtype)
5090a7d1d5cSxiaofeibao  private val sew = vtype.map(_.vsew)
5100a7d1d5cSxiaofeibao  private val lmul = vtype.map(_.vlmul)
5110a7d1d5cSxiaofeibao  private val eew = uop.map(_.vpu.veew)
5120a7d1d5cSxiaofeibao  private val mop = fuOpType.map(fuOpTypeItem => LSUOpType.getVecLSMop(fuOpTypeItem))
5130a7d1d5cSxiaofeibao  private val nf = fuOpType.zip(uop.map(_.vpu.nf)).map { case (fuOpTypeItem, nfItem) => Mux(LSUOpType.isWhole(fuOpTypeItem), 0.U, nfItem) }
5140a7d1d5cSxiaofeibao  private val emul = fuOpType.zipWithIndex.map { case (fuOpTypeItem, index) =>
5150a7d1d5cSxiaofeibao    Mux(
5160a7d1d5cSxiaofeibao      LSUOpType.isWhole(fuOpTypeItem),
5170a7d1d5cSxiaofeibao      GenUSWholeEmul(nf(index)),
5180a7d1d5cSxiaofeibao      Mux(
5190a7d1d5cSxiaofeibao        LSUOpType.isMasked(fuOpTypeItem),
5200a7d1d5cSxiaofeibao        0.U(mulBits.W),
5210a7d1d5cSxiaofeibao        EewLog2(eew(index)) - sew(index) + lmul(index)
5220a7d1d5cSxiaofeibao      )
5230a7d1d5cSxiaofeibao    )
5240a7d1d5cSxiaofeibao  }
5250a7d1d5cSxiaofeibao
5260a7d1d5cSxiaofeibao  private val isVlsType = fuType.map(fuTypeItem => FuType.isVls(fuTypeItem)).zip(fromRename.map(_.valid)).map(x => x._1 && x._2)
5270a7d1d5cSxiaofeibao  private val isSegment = fuType.map(fuTypeItem => FuType.isVsegls(fuTypeItem)).zip(fromRename.map(_.valid)).map(x => x._1 && x._2)
5280a7d1d5cSxiaofeibao  // TODO
5290a7d1d5cSxiaofeibao  private val isUnitStride = fuOpType.map(fuOpTypeItem => LSUOpType.isAllUS(fuOpTypeItem))
5300a7d1d5cSxiaofeibao  private val isVecUnitType = isVlsType.zip(isUnitStride).map { case (isVlsTypeItme, isUnitStrideItem) =>
5310a7d1d5cSxiaofeibao    isVlsTypeItme && isUnitStrideItem
5320a7d1d5cSxiaofeibao  }
5330a7d1d5cSxiaofeibao  private val isfofFixVlUop = uop.map { x => x.vpu.isVleff && x.lastUop }
5340a7d1d5cSxiaofeibao  private val instType = isSegment.zip(mop).map { case (isSegementItem, mopItem) => Cat(isSegementItem, mopItem) }
5350a7d1d5cSxiaofeibao  // There is no way to calculate the 'flow' for 'unit-stride' exactly:
5360a7d1d5cSxiaofeibao  //  Whether 'unit-stride' needs to be split can only be known after obtaining the address.
5370a7d1d5cSxiaofeibao  // For scalar instructions, this is not handled here, and different assignments are done later according to the situation.
5380a7d1d5cSxiaofeibao  private val numLsElem = VecInit(uop.map(_.numLsElem))
5390a7d1d5cSxiaofeibao
5400a7d1d5cSxiaofeibao  // The maximum 'numLsElem' number that can be emitted per port is:
5410a7d1d5cSxiaofeibao  //    16 2 2 2 2 2.
5420a7d1d5cSxiaofeibao  // The 'allowDispatch' calculations are done conservatively for timing purposes:
5430a7d1d5cSxiaofeibao  //   The Flow of scalar instructions is considered 1,
5440a7d1d5cSxiaofeibao  //   The flow of vector 'unit-stride' instructions is considered 2, and the flow of other vector instructions is considered 16.
5450a7d1d5cSxiaofeibao  private val conserveFlows = isVlsType.zipWithIndex.map { case (isVlsTyepItem, index) =>
5460a7d1d5cSxiaofeibao    Mux(
5470a7d1d5cSxiaofeibao      isVlsTyepItem,
5480a7d1d5cSxiaofeibao      if (index == 0) Mux(isUnitStride(index), VecMemUnitStrideMaxFlowNum.U, 16.U) else VecMemUnitStrideMaxFlowNum.U,
5490a7d1d5cSxiaofeibao      1.U
5500a7d1d5cSxiaofeibao    )
5510a7d1d5cSxiaofeibao  }
5520a7d1d5cSxiaofeibao
5530a7d1d5cSxiaofeibao  // A conservative allocation strategy is adopted here.
5540a7d1d5cSxiaofeibao  // Vector 'unit-stride' instructions and scalar instructions can be issued from all six ports,
5550a7d1d5cSxiaofeibao  // while other vector instructions can only be issued from the first port
5560a7d1d5cSxiaofeibao  // if is segment instruction, need disptch it to Vldst_RS0, so, except port 0, stall other.
5570a7d1d5cSxiaofeibao  // The allocation needs to meet a few conditions:
5580a7d1d5cSxiaofeibao  //  1) The lsq has enough entris.
5590a7d1d5cSxiaofeibao  //  2) The number of flows accumulated does not exceed VecMemDispatchMaxNumber.
5600a7d1d5cSxiaofeibao  //  3) Vector instructions other than 'unit-stride' can only be issued on the first port.
5610a7d1d5cSxiaofeibao
5620a7d1d5cSxiaofeibao
5630a7d1d5cSxiaofeibao  for (index <- allowDispatch.indices) {
5640a7d1d5cSxiaofeibao    val flowTotal = Wire(UInt(log2Up(VirtualLoadQueueMaxStoreQueueSize + 1).W))
5650a7d1d5cSxiaofeibao    flowTotal := conserveFlows.take(index + 1).reduce(_ +& _)
5660a7d1d5cSxiaofeibao    if (index == 0) {
5670a7d1d5cSxiaofeibao      when(isStoreVec(index) || isVStoreVec(index)) {
5680a7d1d5cSxiaofeibao        allowDispatch(index) := sqFreeCount > flowTotal
5690a7d1d5cSxiaofeibao      }.elsewhen(isLoadVec(index) || isVLoadVec(index)) {
5700a7d1d5cSxiaofeibao        allowDispatch(index) := lqFreeCount > flowTotal
5710a7d1d5cSxiaofeibao      }.elsewhen(isAMOVec(index)) {
5720a7d1d5cSxiaofeibao        allowDispatch(index) := true.B
5730a7d1d5cSxiaofeibao      }.otherwise {
5740a7d1d5cSxiaofeibao        allowDispatch(index) := true.B
5750a7d1d5cSxiaofeibao      }
5760a7d1d5cSxiaofeibao    }
5770a7d1d5cSxiaofeibao    else {
5780a7d1d5cSxiaofeibao      when(isStoreVec(index) || isVStoreVec(index)) {
5790a7d1d5cSxiaofeibao        allowDispatch(index) := (sqFreeCount > flowTotal) && (isVecUnitType(index) || !isVlsType(index)) && allowDispatch(index - 1)
5800a7d1d5cSxiaofeibao      }.elsewhen(isLoadVec(index) || isVLoadVec(index)) {
5810a7d1d5cSxiaofeibao        allowDispatch(index) := (lqFreeCount > flowTotal) && (isVecUnitType(index) || !isVlsType(index)) && allowDispatch(index - 1)
5820a7d1d5cSxiaofeibao      }.elsewhen(isAMOVec(index)) {
5830a7d1d5cSxiaofeibao        allowDispatch(index) := allowDispatch(index - 1)
5840a7d1d5cSxiaofeibao      }.otherwise {
5850a7d1d5cSxiaofeibao        allowDispatch(index) := allowDispatch(index - 1)
5860a7d1d5cSxiaofeibao      }
5870a7d1d5cSxiaofeibao    }
5880a7d1d5cSxiaofeibao  }
5890a7d1d5cSxiaofeibao
5900a7d1d5cSxiaofeibao
5910a7d1d5cSxiaofeibao  // enqLsq io
5920a7d1d5cSxiaofeibao  require(enqLsqIO.req.size == enqLsqIO.resp.size)
5930a7d1d5cSxiaofeibao  for (i <- enqLsqIO.req.indices) {
5940a7d1d5cSxiaofeibao    when(!io.fromRename(i).fire) {
5950a7d1d5cSxiaofeibao      enqLsqIO.needAlloc(i) := 0.U
5960a7d1d5cSxiaofeibao    }.elsewhen(isStoreVec(i) || isVStoreVec(i)) {
5970a7d1d5cSxiaofeibao      enqLsqIO.needAlloc(i) := 2.U // store | vstore
5980a7d1d5cSxiaofeibao    }.elsewhen(isLoadVec(i) || isVLoadVec(i)){
5990a7d1d5cSxiaofeibao      enqLsqIO.needAlloc(i) := 1.U // load | vload
6000a7d1d5cSxiaofeibao    }.otherwise {
6010a7d1d5cSxiaofeibao      enqLsqIO.needAlloc(i) := 0.U
6020a7d1d5cSxiaofeibao    }
6030a7d1d5cSxiaofeibao    enqLsqIO.req(i).valid := io.fromRename(i).fire && !isAMOVec(i) && !isSegment(i) && !isfofFixVlUop(i)
6040a7d1d5cSxiaofeibao    enqLsqIO.req(i).bits := io.fromRename(i).bits
6050a7d1d5cSxiaofeibao
6060a7d1d5cSxiaofeibao    // This is to make it easier to calculate in LSQ.
6070a7d1d5cSxiaofeibao    // Both scalar instructions and vector instructions with FLOW equal to 1 have a NUM value of 1.”
6080a7d1d5cSxiaofeibao    // But, the 'numLsElem' that is not a vector is set to 0 when passed to IQ
6090a7d1d5cSxiaofeibao    enqLsqIO.req(i).bits.numLsElem := Mux(isVlsType(i), numLsElem(i), 1.U)
6100a7d1d5cSxiaofeibao    s0_enqLsq_resp(i) := enqLsqIO.resp(i)
6110a7d1d5cSxiaofeibao  }
6120a7d1d5cSxiaofeibao
6130a7d1d5cSxiaofeibao
6140a7d1d5cSxiaofeibao
6150a7d1d5cSxiaofeibao
6160a7d1d5cSxiaofeibao
6170a7d1d5cSxiaofeibao
6180a7d1d5cSxiaofeibao
6190a7d1d5cSxiaofeibao
6200a7d1d5cSxiaofeibao
6210a7d1d5cSxiaofeibao
6220a7d1d5cSxiaofeibao
6230a7d1d5cSxiaofeibao
6240a7d1d5cSxiaofeibao  val isFp = VecInit(fromRename.map(req => FuType.isFArith(req.bits.fuType)))
6250a7d1d5cSxiaofeibao  val isVec     = VecInit(fromRename.map(req => FuType.isVArith (req.bits.fuType) ||
6260a7d1d5cSxiaofeibao                                                  FuType.isVsetRvfWvf(req.bits.fuType)))
6270a7d1d5cSxiaofeibao  val isMem    = VecInit(fromRename.map(req => FuType.isMem(req.bits.fuType) ||
6280a7d1d5cSxiaofeibao                                                  FuType.isVls (req.bits.fuType)))
6290a7d1d5cSxiaofeibao  val isLs     = VecInit(fromRename.map(req => FuType.isLoadStore(req.bits.fuType)))
6300a7d1d5cSxiaofeibao  val isVls    = VecInit(fromRename.map(req => FuType.isVls (req.bits.fuType)))
6310a7d1d5cSxiaofeibao  val isStore  = VecInit(fromRename.map(req => FuType.isStore(req.bits.fuType)))
6320a7d1d5cSxiaofeibao  val isVStore = VecInit(fromRename.map(req => FuType.isVStore(req.bits.fuType)))
6330a7d1d5cSxiaofeibao  val isAMO    = VecInit(fromRename.map(req => FuType.isAMO(req.bits.fuType)))
6340a7d1d5cSxiaofeibao  val isBlockBackward  = VecInit(fromRename.map(x => x.valid && x.bits.blockBackward))
6350a7d1d5cSxiaofeibao  val isWaitForward    = VecInit(fromRename.map(x => x.valid && x.bits.waitForward))
6360a7d1d5cSxiaofeibao
6370a7d1d5cSxiaofeibao  // Singlestep should only commit one machine instruction after dret, and then hart enter debugMode according to singlestep exception.
6380a7d1d5cSxiaofeibao  val s_holdRobidx :: s_updateRobidx :: Nil = Enum(2)
6390a7d1d5cSxiaofeibao  val singleStepState = RegInit(s_updateRobidx)
6400a7d1d5cSxiaofeibao
6410a7d1d5cSxiaofeibao  val robidxStepNext  = WireInit(0.U.asTypeOf(fromRename(0).bits.robIdx))
6420a7d1d5cSxiaofeibao  val robidxStepReg   = RegInit(0.U.asTypeOf(fromRename(0).bits.robIdx))
6430a7d1d5cSxiaofeibao  val robidxCanCommitStepping = WireInit(0.U.asTypeOf(fromRename(0).bits.robIdx))
6440a7d1d5cSxiaofeibao
6450a7d1d5cSxiaofeibao  when(!io.singleStep) {
6460a7d1d5cSxiaofeibao    singleStepState := s_updateRobidx
6470a7d1d5cSxiaofeibao  }.elsewhen(io.singleStep && fromRename(0).fire && io.enqRob.req(0).valid) {
6480a7d1d5cSxiaofeibao    singleStepState := s_holdRobidx
6490a7d1d5cSxiaofeibao    robidxStepNext := fromRename(0).bits.robIdx
6500a7d1d5cSxiaofeibao  }
6510a7d1d5cSxiaofeibao
6520a7d1d5cSxiaofeibao  when(singleStepState === s_updateRobidx) {
6530a7d1d5cSxiaofeibao    robidxStepReg := robidxStepNext
6540a7d1d5cSxiaofeibao    robidxCanCommitStepping := robidxStepNext
6550a7d1d5cSxiaofeibao  }.elsewhen(singleStepState === s_holdRobidx) {
6560a7d1d5cSxiaofeibao    robidxStepReg := robidxStepReg
6570a7d1d5cSxiaofeibao    robidxCanCommitStepping := robidxStepReg
6580a7d1d5cSxiaofeibao  }
6590a7d1d5cSxiaofeibao
6600a7d1d5cSxiaofeibao  val updatedUop = Wire(Vec(RenameWidth, new DynInst))
6610a7d1d5cSxiaofeibao  val checkpoint_id = RegInit(0.U(64.W))
6620a7d1d5cSxiaofeibao  checkpoint_id := checkpoint_id + PopCount((0 until RenameWidth).map(i =>
6630a7d1d5cSxiaofeibao    fromRename(i).fire
6640a7d1d5cSxiaofeibao  ))
6650a7d1d5cSxiaofeibao
6660a7d1d5cSxiaofeibao
6670a7d1d5cSxiaofeibao  for (i <- 0 until RenameWidth) {
6680a7d1d5cSxiaofeibao
6690a7d1d5cSxiaofeibao    updatedUop(i) := fromRename(i).bits
6700a7d1d5cSxiaofeibao    updatedUop(i).debugInfo.eliminatedMove := fromRename(i).bits.eliminatedMove
6710a7d1d5cSxiaofeibao    // For the LUI instruction: psrc(0) is from register file and should always be zero.
6720a7d1d5cSxiaofeibao    when (fromRename(i).bits.isLUI) {
6730a7d1d5cSxiaofeibao      updatedUop(i).psrc(0) := 0.U
6740a7d1d5cSxiaofeibao    }
6750a7d1d5cSxiaofeibao    //TODO: vec ls mdp
6760a7d1d5cSxiaofeibao    io.lfst.req(i).valid := fromRename(i).fire && updatedUop(i).storeSetHit
6770a7d1d5cSxiaofeibao    io.lfst.req(i).bits.isstore := isStore(i)
6780a7d1d5cSxiaofeibao    io.lfst.req(i).bits.ssid := updatedUop(i).ssid
6790a7d1d5cSxiaofeibao    io.lfst.req(i).bits.robIdx := updatedUop(i).robIdx // speculatively assigned in rename
6800a7d1d5cSxiaofeibao
6810a7d1d5cSxiaofeibao    // override load delay ctrl signal with store set result
6820a7d1d5cSxiaofeibao    if(StoreSetEnable) {
6830a7d1d5cSxiaofeibao      updatedUop(i).loadWaitBit := io.lfst.resp(i).bits.shouldWait
6840a7d1d5cSxiaofeibao      updatedUop(i).waitForRobIdx := io.lfst.resp(i).bits.robIdx
6850a7d1d5cSxiaofeibao    } else {
6860a7d1d5cSxiaofeibao      updatedUop(i).loadWaitBit := isLs(i) && !isStore(i) && fromRename(i).bits.loadWaitBit
6870a7d1d5cSxiaofeibao    }
6880a7d1d5cSxiaofeibao    // // update singleStep, singleStep exception only enable in next machine instruction.
6890a7d1d5cSxiaofeibao    updatedUop(i).singleStep := io.singleStep && (fromRename(i).bits.robIdx =/= robidxCanCommitStepping)
6900a7d1d5cSxiaofeibao    when (fromRename(i).fire) {
6910a7d1d5cSxiaofeibao      XSDebug(TriggerAction.isDmode(updatedUop(i).trigger) || updatedUop(i).exceptionVec(breakPoint), s"Debug Mode: inst ${i} has frontend trigger exception\n")
6920a7d1d5cSxiaofeibao      XSDebug(updatedUop(i).singleStep, s"Debug Mode: inst ${i} has single step exception\n")
6930a7d1d5cSxiaofeibao    }
6940a7d1d5cSxiaofeibao    if (env.EnableDifftest) {
6950a7d1d5cSxiaofeibao      // debug runahead hint
6960a7d1d5cSxiaofeibao      val debug_runahead_checkpoint_id = Wire(checkpoint_id.cloneType)
6970a7d1d5cSxiaofeibao      if(i == 0){
6980a7d1d5cSxiaofeibao        debug_runahead_checkpoint_id := checkpoint_id
6990a7d1d5cSxiaofeibao      } else {
7000a7d1d5cSxiaofeibao        debug_runahead_checkpoint_id := checkpoint_id + PopCount((0 until i).map(i =>
7010a7d1d5cSxiaofeibao          fromRename(i).fire
7020a7d1d5cSxiaofeibao        ))
7030a7d1d5cSxiaofeibao      }
7040a7d1d5cSxiaofeibao    }
7050a7d1d5cSxiaofeibao  }
7060a7d1d5cSxiaofeibao
7070a7d1d5cSxiaofeibao  // store set perf count
7080a7d1d5cSxiaofeibao  XSPerfAccumulate("waittable_load_wait", PopCount((0 until RenameWidth).map(i =>
7090a7d1d5cSxiaofeibao    fromRename(i).fire && fromRename(i).bits.loadWaitBit && !isStore(i) && isLs(i)
7100a7d1d5cSxiaofeibao  )))
7110a7d1d5cSxiaofeibao  XSPerfAccumulate("storeset_load_wait", PopCount((0 until RenameWidth).map(i =>
7120a7d1d5cSxiaofeibao    fromRename(i).fire && updatedUop(i).loadWaitBit && !isStore(i) && isLs(i)
7130a7d1d5cSxiaofeibao  )))
7140a7d1d5cSxiaofeibao  XSPerfAccumulate("storeset_load_strict_wait", PopCount((0 until RenameWidth).map(i =>
7150a7d1d5cSxiaofeibao    fromRename(i).fire && updatedUop(i).loadWaitBit && updatedUop(i).loadWaitStrict && !isStore(i) && isLs(i)
7160a7d1d5cSxiaofeibao  )))
7170a7d1d5cSxiaofeibao  XSPerfAccumulate("storeset_store_wait", PopCount((0 until RenameWidth).map(i =>
7180a7d1d5cSxiaofeibao    fromRename(i).fire && updatedUop(i).loadWaitBit && isStore(i)
7190a7d1d5cSxiaofeibao  )))
7200a7d1d5cSxiaofeibao
7210a7d1d5cSxiaofeibao  val allResourceReady = io.enqRob.canAccept
7220a7d1d5cSxiaofeibao
7230a7d1d5cSxiaofeibao  // Instructions should enter dispatch queues in order.
7240a7d1d5cSxiaofeibao  // blockedByWaitForward: this instruction is blocked by itself (based on waitForward)
7250a7d1d5cSxiaofeibao  // nextCanOut: next instructions can out (based on blockBackward)
7260a7d1d5cSxiaofeibao  // notBlockedByPrevious: previous instructions can enqueue
7270a7d1d5cSxiaofeibao  val hasException = VecInit(fromRename.zip(updatedUop).map {
7280a7d1d5cSxiaofeibao    case (fromRename: DecoupledIO[DynInst], uop: DynInst) =>
7290a7d1d5cSxiaofeibao      fromRename.bits.hasException || uop.singleStep
7300a7d1d5cSxiaofeibao  })
7310a7d1d5cSxiaofeibao
7320a7d1d5cSxiaofeibao  private val blockedByWaitForward = Wire(Vec(RenameWidth, Bool()))
7330a7d1d5cSxiaofeibao  blockedByWaitForward(0) := !io.enqRob.isEmpty && isWaitForward(0)
7340a7d1d5cSxiaofeibao  for (i <- 1 until RenameWidth) {
7350a7d1d5cSxiaofeibao    blockedByWaitForward(i) := blockedByWaitForward(i - 1) || (!io.enqRob.isEmpty || Cat(fromRename.take(i).map(_.valid)).orR) && isWaitForward(i)
7360a7d1d5cSxiaofeibao  }
7370a7d1d5cSxiaofeibao  if(backendParams.debugEn){
7380a7d1d5cSxiaofeibao    dontTouch(blockedByWaitForward)
7390a7d1d5cSxiaofeibao  }
7400a7d1d5cSxiaofeibao
7410a7d1d5cSxiaofeibao  // Only the uop with block backward flag will block the next uop
7420a7d1d5cSxiaofeibao  val nextCanOut = VecInit((0 until RenameWidth).map(i =>
7430a7d1d5cSxiaofeibao    !isBlockBackward(i)
7440a7d1d5cSxiaofeibao  ))
7450a7d1d5cSxiaofeibao  val notBlockedByPrevious = VecInit((0 until RenameWidth).map(i =>
7460a7d1d5cSxiaofeibao    if (i == 0) true.B
7470a7d1d5cSxiaofeibao    else Cat((0 until i).map(j => nextCanOut(j))).andR
7480a7d1d5cSxiaofeibao  ))
7490a7d1d5cSxiaofeibao
7500a7d1d5cSxiaofeibao  // for noSpecExec: (robEmpty || !this.noSpecExec) && !previous.noSpecExec
7510a7d1d5cSxiaofeibao  // For blockBackward:
7520a7d1d5cSxiaofeibao  // this instruction can actually dequeue: 3 conditions
7530a7d1d5cSxiaofeibao  // (1) resources are ready
7540a7d1d5cSxiaofeibao  // (2) previous instructions are ready
7550a7d1d5cSxiaofeibao  thisCanActualOut := VecInit((0 until RenameWidth).map(i => !blockedByWaitForward(i) && notBlockedByPrevious(i) && io.enqRob.canAccept))
7560a7d1d5cSxiaofeibao  val thisActualOut = (0 until RenameWidth).map(i => io.enqRob.req(i).valid && io.enqRob.canAccept)
7570a7d1d5cSxiaofeibao  val hasValidException = fromRename.zip(hasException).map(x => x._1.valid && x._2)
7580a7d1d5cSxiaofeibao
7590a7d1d5cSxiaofeibao  // input for ROB, LSQ
7600a7d1d5cSxiaofeibao  for (i <- 0 until RenameWidth) {
7610a7d1d5cSxiaofeibao    // needAlloc no use, need deleted
7620a7d1d5cSxiaofeibao    io.enqRob.needAlloc(i) := fromRename(i).valid
7630a7d1d5cSxiaofeibao    io.enqRob.req(i).valid := fromRename(i).fire
7640a7d1d5cSxiaofeibao    io.enqRob.req(i).bits := updatedUop(i)
7650a7d1d5cSxiaofeibao    io.enqRob.req(i).bits.hasException := updatedUop(i).hasException || updatedUop(i).singleStep
7660a7d1d5cSxiaofeibao    io.enqRob.req(i).bits.numWB := Mux(updatedUop(i).singleStep, 0.U, updatedUop(i).numWB)
7670a7d1d5cSxiaofeibao  }
7680a7d1d5cSxiaofeibao
7690a7d1d5cSxiaofeibao  val hasValidInstr = VecInit(fromRename.map(_.valid)).asUInt.orR
7700a7d1d5cSxiaofeibao  val hasSpecialInstr = Cat((0 until RenameWidth).map(i => isBlockBackward(i))).orR
7710a7d1d5cSxiaofeibao
7720a7d1d5cSxiaofeibao  private val canAccept = !hasValidInstr || !hasSpecialInstr && io.enqRob.canAccept
7730a7d1d5cSxiaofeibao
7740a7d1d5cSxiaofeibao  val isWaitForwardOrBlockBackward = isWaitForward.asUInt.orR || isBlockBackward.asUInt.orR
7750a7d1d5cSxiaofeibao  val renameFireCnt = PopCount(fromRename.map(_.fire))
7760a7d1d5cSxiaofeibao
7770a7d1d5cSxiaofeibao  val stall_rob = hasValidInstr && !io.enqRob.canAccept
7780a7d1d5cSxiaofeibao  val stall_int_dq = hasValidInstr && io.enqRob.canAccept
7790a7d1d5cSxiaofeibao  val stall_int_dq0 = hasValidInstr && io.enqRob.canAccept
7800a7d1d5cSxiaofeibao  val stall_int_dq1 = hasValidInstr && io.enqRob.canAccept
7810a7d1d5cSxiaofeibao  val stall_fp_dq = hasValidInstr && io.enqRob.canAccept
7820a7d1d5cSxiaofeibao  val stall_ls_dq = hasValidInstr && io.enqRob.canAccept
7830a7d1d5cSxiaofeibao
7840a7d1d5cSxiaofeibao  XSPerfAccumulate("in_valid_count", PopCount(fromRename.map(_.valid)))
7850a7d1d5cSxiaofeibao  XSPerfAccumulate("in_fire_count", PopCount(fromRename.map(_.fire)))
7860a7d1d5cSxiaofeibao  XSPerfAccumulate("in_valid_not_ready_count", PopCount(fromRename.map(x => x.valid && !x.ready)))
7870a7d1d5cSxiaofeibao  XSPerfAccumulate("wait_cycle", !fromRename.head.valid && allResourceReady)
7880a7d1d5cSxiaofeibao
7890a7d1d5cSxiaofeibao  XSPerfAccumulate("stall_cycle_rob", stall_rob)
7900a7d1d5cSxiaofeibao  XSPerfAccumulate("stall_cycle_int_dq0", stall_int_dq0)
7910a7d1d5cSxiaofeibao  XSPerfAccumulate("stall_cycle_int_dq1", stall_int_dq1)
7920a7d1d5cSxiaofeibao  XSPerfAccumulate("stall_cycle_fp_dq", stall_fp_dq)
7930a7d1d5cSxiaofeibao  XSPerfAccumulate("stall_cycle_ls_dq", stall_ls_dq)
7940a7d1d5cSxiaofeibao
7950a7d1d5cSxiaofeibao  val notIssue = !io.debugTopDown.fromRob.robHeadLsIssue
7960a7d1d5cSxiaofeibao  val tlbReplay = io.debugTopDown.fromCore.fromMem.robHeadTlbReplay
7970a7d1d5cSxiaofeibao  val tlbMiss = io.debugTopDown.fromCore.fromMem.robHeadTlbMiss
7980a7d1d5cSxiaofeibao  val vioReplay = io.debugTopDown.fromCore.fromMem.robHeadLoadVio
7990a7d1d5cSxiaofeibao  val mshrReplay = io.debugTopDown.fromCore.fromMem.robHeadLoadMSHR
8000a7d1d5cSxiaofeibao  val l1Miss = io.debugTopDown.fromCore.fromMem.robHeadMissInDCache
8010a7d1d5cSxiaofeibao  val l2Miss = io.debugTopDown.fromCore.l2MissMatch
8020a7d1d5cSxiaofeibao  val l3Miss = io.debugTopDown.fromCore.l3MissMatch
8030a7d1d5cSxiaofeibao
8040a7d1d5cSxiaofeibao  val ldReason = Mux(l3Miss, TopDownCounters.LoadMemStall.id.U,
8050a7d1d5cSxiaofeibao  Mux(l2Miss, TopDownCounters.LoadL3Stall.id.U,
8060a7d1d5cSxiaofeibao  Mux(l1Miss, TopDownCounters.LoadL2Stall.id.U,
8070a7d1d5cSxiaofeibao  Mux(notIssue, TopDownCounters.MemNotReadyStall.id.U,
8080a7d1d5cSxiaofeibao  Mux(tlbMiss, TopDownCounters.LoadTLBStall.id.U,
8090a7d1d5cSxiaofeibao  Mux(tlbReplay, TopDownCounters.LoadTLBStall.id.U,
8100a7d1d5cSxiaofeibao  Mux(mshrReplay, TopDownCounters.LoadMSHRReplayStall.id.U,
8110a7d1d5cSxiaofeibao  Mux(vioReplay, TopDownCounters.LoadVioReplayStall.id.U,
8120a7d1d5cSxiaofeibao  TopDownCounters.LoadL1Stall.id.U))))))))
8130a7d1d5cSxiaofeibao
8140a7d1d5cSxiaofeibao  val decodeReason = RegNextN(io.stallReason.reason, 2)
8150a7d1d5cSxiaofeibao  val renameReason = RegNext(io.stallReason.reason)
8160a7d1d5cSxiaofeibao
8170a7d1d5cSxiaofeibao  val stallReason = Wire(chiselTypeOf(io.stallReason.reason))
8180a7d1d5cSxiaofeibao  val firedVec = fromRename.map(_.fire)
8190a7d1d5cSxiaofeibao  io.stallReason.backReason.valid := !canAccept
8200a7d1d5cSxiaofeibao  io.stallReason.backReason.bits := TopDownCounters.OtherCoreStall.id.U
8210a7d1d5cSxiaofeibao  stallReason.zip(io.stallReason.reason).zip(firedVec).zipWithIndex.map { case (((update, in), fire), idx) =>
8220a7d1d5cSxiaofeibao    val headIsInt = FuType.isInt(io.robHead.getDebugFuType)  && io.robHeadNotReady
8230a7d1d5cSxiaofeibao    val headIsFp  = FuType.isFArith(io.robHead.getDebugFuType)   && io.robHeadNotReady
8240a7d1d5cSxiaofeibao    val headIsDiv = FuType.isDivSqrt(io.robHead.getDebugFuType) && io.robHeadNotReady
8250a7d1d5cSxiaofeibao    val headIsLd  = io.robHead.getDebugFuType === FuType.ldu.U && io.robHeadNotReady || !io.lqCanAccept
8260a7d1d5cSxiaofeibao    val headIsSt  = io.robHead.getDebugFuType === FuType.stu.U && io.robHeadNotReady || !io.sqCanAccept
8270a7d1d5cSxiaofeibao    val headIsAmo = io.robHead.getDebugFuType === FuType.mou.U && io.robHeadNotReady
8280a7d1d5cSxiaofeibao    val headIsLs  = headIsLd || headIsSt
8290a7d1d5cSxiaofeibao    val robLsFull = io.robFull || !io.lqCanAccept || !io.sqCanAccept
8300a7d1d5cSxiaofeibao
8310a7d1d5cSxiaofeibao    import TopDownCounters._
8320a7d1d5cSxiaofeibao    update := MuxCase(OtherCoreStall.id.U, Seq(
8330a7d1d5cSxiaofeibao      // fire
8340a7d1d5cSxiaofeibao      (fire                                              ) -> NoStall.id.U          ,
8350a7d1d5cSxiaofeibao      // dispatch not stall / core stall from decode or rename
8360a7d1d5cSxiaofeibao      (in =/= OtherCoreStall.id.U && in =/= NoStall.id.U ) -> in                    ,
8370a7d1d5cSxiaofeibao      // rob stall
8380a7d1d5cSxiaofeibao      (headIsAmo                                         ) -> AtomicStall.id.U      ,
8390a7d1d5cSxiaofeibao      (headIsSt                                          ) -> StoreStall.id.U       ,
8400a7d1d5cSxiaofeibao      (headIsLd                                          ) -> ldReason              ,
8410a7d1d5cSxiaofeibao      (headIsDiv                                         ) -> DivStall.id.U         ,
8420a7d1d5cSxiaofeibao      (headIsInt                                         ) -> IntNotReadyStall.id.U ,
8430a7d1d5cSxiaofeibao      (headIsFp                                          ) -> FPNotReadyStall.id.U  ,
8440a7d1d5cSxiaofeibao      (renameReason(idx) =/= NoStall.id.U                ) -> renameReason(idx)     ,
8450a7d1d5cSxiaofeibao      (decodeReason(idx) =/= NoStall.id.U                ) -> decodeReason(idx)     ,
8460a7d1d5cSxiaofeibao    ))
8470a7d1d5cSxiaofeibao  }
8480a7d1d5cSxiaofeibao
8490a7d1d5cSxiaofeibao  TopDownCounters.values.foreach(ctr => XSPerfAccumulate(ctr.toString(), PopCount(stallReason.map(_ === ctr.id.U))))
8500a7d1d5cSxiaofeibao
8510a7d1d5cSxiaofeibao  val robTrueCommit = io.debugTopDown.fromRob.robTrueCommit
8520a7d1d5cSxiaofeibao  TopDownCounters.values.foreach(ctr => XSPerfRolling("td_"+ctr.toString(), PopCount(stallReason.map(_ === ctr.id.U)),
8530a7d1d5cSxiaofeibao                                                      robTrueCommit, 1000, clock, reset))
8540a7d1d5cSxiaofeibao
8550a7d1d5cSxiaofeibao  XSPerfHistogram("slots_fire", PopCount(thisActualOut), true.B, 0, RenameWidth+1, 1)
8560a7d1d5cSxiaofeibao  // Explaination: when out(0) not fire, PopCount(valid) is not meaningfull
8570a7d1d5cSxiaofeibao  XSPerfHistogram("slots_valid_pure", PopCount(io.enqRob.req.map(_.valid)), thisActualOut(0), 0, RenameWidth+1, 1)
8580a7d1d5cSxiaofeibao  XSPerfHistogram("slots_valid_rough", PopCount(io.enqRob.req.map(_.valid)), true.B, 0, RenameWidth+1, 1)
8590a7d1d5cSxiaofeibao
8600a7d1d5cSxiaofeibao  val perfEvents = Seq(
8610a7d1d5cSxiaofeibao    ("dispatch_in",                 PopCount(fromRename.map(_.valid && fromRename(0).ready))                       ),
8620a7d1d5cSxiaofeibao    ("dispatch_empty",              !hasValidInstr                                                                 ),
8630a7d1d5cSxiaofeibao    ("dispatch_utili",              PopCount(fromRename.map(_.valid))                                              ),
8640a7d1d5cSxiaofeibao    ("dispatch_waitinstr",          PopCount(fromRename.map(!_.valid && canAccept))                                ),
8650a7d1d5cSxiaofeibao    ("dispatch_stall_cycle_lsq",    false.B                                                                        ),
8660a7d1d5cSxiaofeibao    ("dispatch_stall_cycle_rob",    stall_rob                                                                      ),
8670a7d1d5cSxiaofeibao    ("dispatch_stall_cycle_int_dq", stall_int_dq                                                                   ),
8680a7d1d5cSxiaofeibao    ("dispatch_stall_cycle_fp_dq",  stall_fp_dq                                                                    ),
8690a7d1d5cSxiaofeibao    ("dispatch_stall_cycle_ls_dq",  stall_ls_dq                                                                    )
8700a7d1d5cSxiaofeibao  )
8710a7d1d5cSxiaofeibao  generatePerfEvent()
8720a7d1d5cSxiaofeibao}
873