xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Scheduler.scala (revision 68d130856f32eb5a07b1be2c23b3724a5a590e46)
1730cfbc0SXuan Hupackage xiangshan.backend.issue
2730cfbc0SXuan Hu
3730cfbc0SXuan Huimport chipsalliance.rocketchip.config.Parameters
4730cfbc0SXuan Huimport chisel3._
5730cfbc0SXuan Huimport chisel3.util._
6730cfbc0SXuan Huimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
7730cfbc0SXuan Huimport xiangshan._
8730cfbc0SXuan Huimport xiangshan.backend.Bundles
9730cfbc0SXuan Huimport xiangshan.backend.datapath.DataConfig.VAddrData
10730cfbc0SXuan Huimport xiangshan.backend.regfile.RfWritePortWithConfig
11730cfbc0SXuan Huimport xiangshan.backend.rename.BusyTable
12730cfbc0SXuan Huimport xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr}
13730cfbc0SXuan Huimport xiangshan.backend.Bundles.{DynInst, IssueQueueWakeUpBundle}
14730cfbc0SXuan Hu
15730cfbc0SXuan Husealed trait SchedulerType
16730cfbc0SXuan Hu
17730cfbc0SXuan Hucase class IntScheduler() extends SchedulerType
18730cfbc0SXuan Hucase class MemScheduler() extends SchedulerType
19730cfbc0SXuan Hucase class VfScheduler() extends SchedulerType
20730cfbc0SXuan Hucase class NoScheduler() extends SchedulerType
21730cfbc0SXuan Hu
22730cfbc0SXuan Huclass Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter {
23730cfbc0SXuan Hu  val numIntStateWrite = backendParams.numIntWb
24730cfbc0SXuan Hu  val numVfStateWrite = backendParams.numVfWb
25730cfbc0SXuan Hu
26730cfbc0SXuan Hu  val dispatch2Iq = LazyModule(new Dispatch2Iq(params))
27730cfbc0SXuan Hu  val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName)))
28730cfbc0SXuan Hu
29730cfbc0SXuan Hu  lazy val module = params.schdType match {
30730cfbc0SXuan Hu    case IntScheduler() => new SchedulerArithImp(this)(params, p)
31730cfbc0SXuan Hu    case MemScheduler() => new SchedulerMemImp(this)(params, p)
32730cfbc0SXuan Hu    case VfScheduler() => new SchedulerArithImp(this)(params, p)
33730cfbc0SXuan Hu    case _ => null
34730cfbc0SXuan Hu  }
35730cfbc0SXuan Hu}
36730cfbc0SXuan Hu
37730cfbc0SXuan Huclass SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle {
38*68d13085SXuan Hu  // params alias
39*68d13085SXuan Hu  private val LoadQueueSize = VirtualLoadQueueSize
40*68d13085SXuan Hu
41730cfbc0SXuan Hu  val fromTop = new Bundle {
42730cfbc0SXuan Hu    val hartId = Input(UInt(8.W))
43730cfbc0SXuan Hu  }
44730cfbc0SXuan Hu  val fromCtrlBlock = new Bundle {
45730cfbc0SXuan Hu    val pcVec = Input(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W)))
46730cfbc0SXuan Hu    val targetVec = Input(Vec(params.numPcReadPort, UInt(VAddrData().dataWidth.W)))
47730cfbc0SXuan Hu    val flush = Flipped(ValidIO(new Redirect))
48730cfbc0SXuan Hu  }
49730cfbc0SXuan Hu  val fromDispatch = new Bundle {
50730cfbc0SXuan Hu    val allocPregs = Vec(RenameWidth, Input(new ResetPregStateReq))
51730cfbc0SXuan Hu    val uops =  Vec(params.numUopIn, Flipped(DecoupledIO(new DynInst)))
52730cfbc0SXuan Hu  }
53730cfbc0SXuan Hu  val intWriteBack = MixedVec(Vec(backendParams.intPregParams.numWrite,
54730cfbc0SXuan Hu    new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth)))
55730cfbc0SXuan Hu  val vfWriteBack = MixedVec(Vec(backendParams.vfPregParams.numWrite,
56730cfbc0SXuan Hu    new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth)))
57730cfbc0SXuan Hu  val toDataPath: MixedVec[MixedVec[DecoupledIO[Bundles.IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle))
58730cfbc0SXuan Hu  val fromDataPath: MixedVec[MixedVec[Bundles.OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle)))
59730cfbc0SXuan Hu
60730cfbc0SXuan Hu  val memIO = if (params.isMemSchd) Some(new Bundle {
61730cfbc0SXuan Hu    val feedbackIO = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO))
62730cfbc0SXuan Hu    val lsqEnqIO = Flipped(new LsqEnqIO)
63730cfbc0SXuan Hu  }) else None
64730cfbc0SXuan Hu  val fromMem = if (params.isMemSchd) Some(new Bundle {
65730cfbc0SXuan Hu    val stIssuePtr = Input(new SqPtr())
66730cfbc0SXuan Hu    val lcommit = Input(UInt(log2Up(CommitWidth + 1).W))
67730cfbc0SXuan Hu    val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB
68730cfbc0SXuan Hu    // from lsq
69730cfbc0SXuan Hu    val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W))
70730cfbc0SXuan Hu    val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
71730cfbc0SXuan Hu    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
72730cfbc0SXuan Hu  }) else None
73730cfbc0SXuan Hu  val toMem = if (params.isMemSchd) Some(new Bundle {
74730cfbc0SXuan Hu    val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle))
75730cfbc0SXuan Hu  }) else None
76730cfbc0SXuan Hu}
77730cfbc0SXuan Hu
78730cfbc0SXuan Huabstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
79730cfbc0SXuan Hu  extends LazyModuleImp(wrapper)
80730cfbc0SXuan Hu    with HasXSParameter
81730cfbc0SXuan Hu{
82730cfbc0SXuan Hu  val io = IO(new SchedulerIO())
83730cfbc0SXuan Hu
84730cfbc0SXuan Hu  // alias
85730cfbc0SXuan Hu  private val schdType = params.schdType
86730cfbc0SXuan Hu  private val (numRfRead, numRfWrite) = params.numRfReadWrite.getOrElse((0, 0))
87730cfbc0SXuan Hu  private val numPregs = params.numPregs
88730cfbc0SXuan Hu
89730cfbc0SXuan Hu  // Modules
90730cfbc0SXuan Hu  val dispatch2Iq: Dispatch2IqImp = wrapper.dispatch2Iq.module
91730cfbc0SXuan Hu  val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module)
92730cfbc0SXuan Hu
93730cfbc0SXuan Hu  // BusyTable Modules
94730cfbc0SXuan Hu  val intBusyTable = schdType match {
95730cfbc0SXuan Hu    case IntScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numIntStateRead, wrapper.numIntStateWrite)))
96730cfbc0SXuan Hu    case _ => None
97730cfbc0SXuan Hu  }
98730cfbc0SXuan Hu
99730cfbc0SXuan Hu  val vfBusyTable = schdType match {
100730cfbc0SXuan Hu    case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numVfStateRead, wrapper.numVfStateWrite)))
101730cfbc0SXuan Hu    case _ => None
102730cfbc0SXuan Hu  }
103730cfbc0SXuan Hu
104730cfbc0SXuan Hu  dispatch2Iq.io match { case dp2iq =>
105730cfbc0SXuan Hu    dp2iq.redirect <> io.fromCtrlBlock.flush
106730cfbc0SXuan Hu    dp2iq.in <> io.fromDispatch.uops
107730cfbc0SXuan Hu    dp2iq.readIntState.foreach(_ <> intBusyTable.get.io.read)
108730cfbc0SXuan Hu    dp2iq.readVfState.foreach(_ <> vfBusyTable.get.io.read)
109730cfbc0SXuan Hu  }
110730cfbc0SXuan Hu
111730cfbc0SXuan Hu  intBusyTable match {
112730cfbc0SXuan Hu    case Some(bt) =>
113730cfbc0SXuan Hu      bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) =>
114730cfbc0SXuan Hu        btAllocPregs.valid := dpAllocPregs.isInt
115730cfbc0SXuan Hu        btAllocPregs.bits := dpAllocPregs.preg
116730cfbc0SXuan Hu      }
117730cfbc0SXuan Hu      bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) =>
118730cfbc0SXuan Hu        wb.valid := io.intWriteBack(i).wen && io.intWriteBack(i).intWen
119730cfbc0SXuan Hu        wb.bits := io.intWriteBack(i).addr
120730cfbc0SXuan Hu      }
121730cfbc0SXuan Hu    case None =>
122730cfbc0SXuan Hu  }
123730cfbc0SXuan Hu
124730cfbc0SXuan Hu  vfBusyTable match {
125730cfbc0SXuan Hu    case Some(bt) =>
126730cfbc0SXuan Hu      bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) =>
127730cfbc0SXuan Hu        btAllocPregs.valid := dpAllocPregs.isFp
128730cfbc0SXuan Hu        btAllocPregs.bits := dpAllocPregs.preg
129730cfbc0SXuan Hu      }
130730cfbc0SXuan Hu      bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) =>
131730cfbc0SXuan Hu        wb.valid := io.vfWriteBack(i).wen && (io.vfWriteBack(i).fpWen || io.vfWriteBack(i).vecWen)
132730cfbc0SXuan Hu        wb.bits := io.vfWriteBack(i).addr
133730cfbc0SXuan Hu      }
134730cfbc0SXuan Hu    case None =>
135730cfbc0SXuan Hu  }
136730cfbc0SXuan Hu
137730cfbc0SXuan Hu  val wakeupFromWBVec = Wire(Vec(params.numWakeupFromWB, ValidIO(new IssueQueueWakeUpBundle(params.pregIdxWidth))))
138730cfbc0SXuan Hu  val writeback = params.schdType match {
139730cfbc0SXuan Hu    case IntScheduler() => io.intWriteBack
140730cfbc0SXuan Hu    case MemScheduler() => io.intWriteBack ++ io.vfWriteBack
141730cfbc0SXuan Hu    case VfScheduler() => io.vfWriteBack
142730cfbc0SXuan Hu    case _ => Seq()
143730cfbc0SXuan Hu  }
144730cfbc0SXuan Hu  wakeupFromWBVec.zip(writeback).foreach { case (sink, source) =>
145730cfbc0SXuan Hu    sink.valid := source.wen
146730cfbc0SXuan Hu    sink.bits.rfWen := source.intWen
147730cfbc0SXuan Hu    sink.bits.fpWen := source.fpWen
148730cfbc0SXuan Hu    sink.bits.vecWen := source.vecWen
149730cfbc0SXuan Hu    sink.bits.pdest := source.addr
150730cfbc0SXuan Hu  }
151730cfbc0SXuan Hu
152730cfbc0SXuan Hu  io.toDataPath.zipWithIndex.foreach { case (toDp, i) =>
153730cfbc0SXuan Hu    toDp <> issueQueues(i).io.deq
154730cfbc0SXuan Hu  }
155730cfbc0SXuan Hu}
156730cfbc0SXuan Hu
157730cfbc0SXuan Huclass SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
158730cfbc0SXuan Hu  extends SchedulerImpBase(wrapper)
159730cfbc0SXuan Hu    with HasXSParameter
160730cfbc0SXuan Hu{
161730cfbc0SXuan Hu  println(s"[SchedulerArithImp] " +
162730cfbc0SXuan Hu    s"has intBusyTable: ${intBusyTable.nonEmpty}, " +
163730cfbc0SXuan Hu    s"has vfBusyTable: ${vfBusyTable.nonEmpty}")
164730cfbc0SXuan Hu
165730cfbc0SXuan Hu  issueQueues.zipWithIndex.foreach { case (iq, i) =>
166730cfbc0SXuan Hu    iq.io.flush <> io.fromCtrlBlock.flush
167730cfbc0SXuan Hu    iq.io.enq <> dispatch2Iq.io.out(i)
168730cfbc0SXuan Hu    iq.io.wakeup := wakeupFromWBVec
169730cfbc0SXuan Hu    iq.io.deqResp.zipWithIndex.foreach { case (deqResp, j) =>
170ea0f92d8Sczw      deqResp.valid := iq.io.deq(j).valid && io.toDataPath(i)(j).ready
171730cfbc0SXuan Hu      deqResp.bits.success := false.B
172ea0f92d8Sczw      deqResp.bits.respType := RSFeedbackType.issueSuccess
173730cfbc0SXuan Hu      deqResp.bits.addrOH := iq.io.deq(j).bits.addrOH
174730cfbc0SXuan Hu    }
175730cfbc0SXuan Hu    iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) =>
176730cfbc0SXuan Hu      og0Resp.valid := io.fromDataPath(i)(j).og0resp.valid
177730cfbc0SXuan Hu      og0Resp.bits.success := false.B // Todo: remove it
178730cfbc0SXuan Hu      og0Resp.bits.respType := io.fromDataPath(i)(j).og0resp.bits.respType
179730cfbc0SXuan Hu      og0Resp.bits.addrOH := io.fromDataPath(i)(j).og0resp.bits.addrOH
180730cfbc0SXuan Hu    }
181730cfbc0SXuan Hu    iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) =>
182730cfbc0SXuan Hu      og1Resp.valid := io.fromDataPath(i)(j).og1resp.valid
183730cfbc0SXuan Hu      og1Resp.bits.success := false.B
184730cfbc0SXuan Hu      og1Resp.bits.respType := io.fromDataPath(i)(j).og1resp.bits.respType
185730cfbc0SXuan Hu      og1Resp.bits.addrOH := io.fromDataPath(i)(j).og1resp.bits.addrOH
186730cfbc0SXuan Hu    }
187730cfbc0SXuan Hu  }
188730cfbc0SXuan Hu
189730cfbc0SXuan Hu  val iqJumpBundleVec: Seq[IssueQueueJumpBundle] = issueQueues.map {
190730cfbc0SXuan Hu    case imp: IssueQueueIntImp => imp.io.enqJmp
191730cfbc0SXuan Hu    case _ => None
192730cfbc0SXuan Hu  }.filter(_.nonEmpty).flatMap(_.get)
193730cfbc0SXuan Hu  println(s"[Scheduler] iqJumpBundleVec: ${iqJumpBundleVec}")
194730cfbc0SXuan Hu
195730cfbc0SXuan Hu  iqJumpBundleVec.zip(io.fromCtrlBlock.pcVec zip io.fromCtrlBlock.targetVec).foreach { case (iqJmp, (pc, target)) =>
196730cfbc0SXuan Hu    iqJmp.pc := pc
197730cfbc0SXuan Hu    iqJmp.target := target
198730cfbc0SXuan Hu  }
199730cfbc0SXuan Hu}
200730cfbc0SXuan Hu
201730cfbc0SXuan Huclass SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
202730cfbc0SXuan Hu  extends SchedulerImpBase(wrapper)
203730cfbc0SXuan Hu    with HasXSParameter
204730cfbc0SXuan Hu{
205730cfbc0SXuan Hu  println(s"[SchedulerMemImp] " +
206730cfbc0SXuan Hu    s"has intBusyTable: ${intBusyTable.nonEmpty}, " +
207730cfbc0SXuan Hu    s"has vfBusyTable: ${vfBusyTable.nonEmpty}")
208730cfbc0SXuan Hu
209730cfbc0SXuan Hu  val memAddrIQs = issueQueues.filter(iq => iq.params.StdCnt == 0)
210730cfbc0SXuan Hu  val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs
211730cfbc0SXuan Hu  val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0)
212730cfbc0SXuan Hu  require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty)
213730cfbc0SXuan Hu
214730cfbc0SXuan Hu  issueQueues.zipWithIndex.foreach { case (iq, i) =>
215730cfbc0SXuan Hu    iq.io.deqResp.zipWithIndex.foreach { case (deqResp, j) =>
216ea0f92d8Sczw      deqResp.valid := iq.io.deq(j).valid && io.toDataPath(i)(j).ready
217730cfbc0SXuan Hu      deqResp.bits.success := false.B
218ea0f92d8Sczw      deqResp.bits.respType := RSFeedbackType.issueSuccess
219730cfbc0SXuan Hu      deqResp.bits.addrOH := iq.io.deq(j).bits.addrOH
220730cfbc0SXuan Hu    }
221730cfbc0SXuan Hu    iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) =>
222730cfbc0SXuan Hu      og0Resp.valid := io.fromDataPath(i)(j).og0resp.valid
223730cfbc0SXuan Hu      og0Resp.bits.success := false.B // Todo: remove it
224730cfbc0SXuan Hu      og0Resp.bits.respType := io.fromDataPath(i)(j).og0resp.bits.respType
225730cfbc0SXuan Hu      og0Resp.bits.addrOH := io.fromDataPath(i)(j).og0resp.bits.addrOH
226730cfbc0SXuan Hu    }
227730cfbc0SXuan Hu    iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) =>
228730cfbc0SXuan Hu      og1Resp.valid := io.fromDataPath(i)(j).og1resp.valid
229730cfbc0SXuan Hu      og1Resp.bits.success := false.B
230730cfbc0SXuan Hu      og1Resp.bits.respType := io.fromDataPath(i)(j).og1resp.bits.respType
231730cfbc0SXuan Hu      og1Resp.bits.addrOH := io.fromDataPath(i)(j).og1resp.bits.addrOH
232730cfbc0SXuan Hu    }
233730cfbc0SXuan Hu  }
234730cfbc0SXuan Hu
235730cfbc0SXuan Hu  memAddrIQs.zipWithIndex.foreach { case (iq, i) =>
236730cfbc0SXuan Hu    iq.io.flush <> io.fromCtrlBlock.flush
237730cfbc0SXuan Hu    iq.io.enq <> dispatch2Iq.io.out(i)
238730cfbc0SXuan Hu    iq.io.wakeup := wakeupFromWBVec
239730cfbc0SXuan Hu  }
240730cfbc0SXuan Hu
241730cfbc0SXuan Hu
242730cfbc0SXuan Hu  dispatch2Iq.io.out(1).zip(stAddrIQs(0).io.enq).zip(stDataIQs(0).io.enq).foreach{ case((di, staIQ), stdIQ) =>
243730cfbc0SXuan Hu    val isAllReady = staIQ.ready && stdIQ.ready
244730cfbc0SXuan Hu    di.ready := isAllReady
245730cfbc0SXuan Hu    staIQ.valid := di.valid && isAllReady
246730cfbc0SXuan Hu    stdIQ.valid := di.valid && isAllReady
247730cfbc0SXuan Hu  }
248730cfbc0SXuan Hu
249730cfbc0SXuan Hu  require(stAddrIQs.size == stDataIQs.size, s"number of store address IQs(${stAddrIQs.size}) " +
250730cfbc0SXuan Hu    s"should be equal to number of data IQs(${stDataIQs})")
251730cfbc0SXuan Hu  stDataIQs.zip(stAddrIQs).zipWithIndex.foreach { case ((stdIQ, staIQ), i) =>
252730cfbc0SXuan Hu    stdIQ.io.flush <> io.fromCtrlBlock.flush
253730cfbc0SXuan Hu
254730cfbc0SXuan Hu    stdIQ.io.enq.zip(staIQ.io.enq).foreach { case (stdIQEnq, staIQEnq) =>
255730cfbc0SXuan Hu      stdIQEnq.bits  := staIQEnq.bits
256730cfbc0SXuan Hu      // Store data reuses store addr src(1) in dispatch2iq
257730cfbc0SXuan Hu      // [dispatch2iq] --src*------src*(0)--> [staIQ]
258730cfbc0SXuan Hu      //                       \
259730cfbc0SXuan Hu      //                        ---src*(1)--> [stdIQ]
260730cfbc0SXuan Hu      // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1)
261730cfbc0SXuan Hu      // instead of dispatch2Iq.io.out(x).bits.src*(1)
262730cfbc0SXuan Hu      stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(1)
263730cfbc0SXuan Hu      stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(1)
264730cfbc0SXuan Hu      stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(1)
265730cfbc0SXuan Hu      stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx
266730cfbc0SXuan Hu    }
267730cfbc0SXuan Hu    stdIQ.io.wakeup := wakeupFromWBVec
268730cfbc0SXuan Hu  }
269730cfbc0SXuan Hu
270730cfbc0SXuan Hu  val iqMemBundleVec = stAddrIQs.map {
271730cfbc0SXuan Hu    case imp: IssueQueueMemAddrImp => imp.io.memIO
272730cfbc0SXuan Hu    case _ => None
273730cfbc0SXuan Hu  }.filter(_.nonEmpty).map(_.get)
274730cfbc0SXuan Hu  println(s"[Scheduler] iqMemBundleVec: ${iqMemBundleVec}")
275730cfbc0SXuan Hu
276730cfbc0SXuan Hu  val lsqEnqCtrl = Module(new LsqEnqCtrl)
277730cfbc0SXuan Hu
278730cfbc0SXuan Hu  lsqEnqCtrl.io.redirect <> io.fromCtrlBlock.flush
279730cfbc0SXuan Hu  lsqEnqCtrl.io.enq <> dispatch2Iq.io.enqLsqIO.get
280730cfbc0SXuan Hu  lsqEnqCtrl.io.lcommit := io.fromMem.get.lcommit
281730cfbc0SXuan Hu  lsqEnqCtrl.io.scommit := io.fromMem.get.scommit
282730cfbc0SXuan Hu  lsqEnqCtrl.io.lqCancelCnt := io.fromMem.get.lqCancelCnt
283730cfbc0SXuan Hu  lsqEnqCtrl.io.sqCancelCnt := io.fromMem.get.sqCancelCnt
284730cfbc0SXuan Hu  io.memIO.get.lsqEnqIO <> lsqEnqCtrl.io.enqLsq
285730cfbc0SXuan Hu  require(io.memIO.get.feedbackIO.size == iqMemBundleVec.map(_.feedbackIO.size).sum,
286730cfbc0SXuan Hu    s"[SchedulerMemImp] io.memIO.feedbackIO.size(${io.memIO.get.feedbackIO.size}) " +
287730cfbc0SXuan Hu      s"should be equal to sum of memIQ.io.feedbackIO.size(${iqMemBundleVec.map(_.feedbackIO.size).sum})")
288730cfbc0SXuan Hu
289730cfbc0SXuan Hu  val memIQFeedbackIO: Seq[MemRSFeedbackIO] = iqMemBundleVec.flatMap(_.feedbackIO)
290730cfbc0SXuan Hu  io.memIO.get.feedbackIO <> memIQFeedbackIO
291730cfbc0SXuan Hu}
292