xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Scheduler.scala (revision 4daa5bf3c3f27e7fd090866d52405b21e107eb8d)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
7import utils.OptionWrapper
8import xiangshan._
9import xiangshan.backend.Bundles._
10import xiangshan.backend.datapath.DataConfig.{IntData, VAddrData, VecData, FpData}
11import xiangshan.backend.datapath.WbConfig.{IntWB, FpWB, VfWB}
12import xiangshan.backend.fu.FuType
13import xiangshan.backend.regfile.RfWritePortWithConfig
14import xiangshan.backend.rename.BusyTable
15import xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr, LqPtr}
16
17sealed trait SchedulerType
18
19case class IntScheduler() extends SchedulerType
20case class FpScheduler() extends SchedulerType
21case class MemScheduler() extends SchedulerType
22case class VfScheduler() extends SchedulerType
23case class NoScheduler() extends SchedulerType
24
25class Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter {
26  override def shouldBeInlined: Boolean = false
27
28  val numIntStateWrite = backendParams.numPregWb(IntData())
29  val numFpStateWrite = backendParams.numPregWb(FpData())
30  val numVfStateWrite = backendParams.numPregWb(VecData())
31
32  val dispatch2Iq = LazyModule(new Dispatch2Iq(params))
33  val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName)))
34
35  lazy val module: SchedulerImpBase = params.schdType match {
36    case IntScheduler() => new SchedulerArithImp(this)(params, p)
37    case FpScheduler()  => new SchedulerArithImp(this)(params, p)
38    case MemScheduler() => new SchedulerMemImp(this)(params, p)
39    case VfScheduler() => new SchedulerArithImp(this)(params, p)
40    case _ => null
41  }
42}
43
44class SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle {
45  // params alias
46  private val LoadQueueSize = VirtualLoadQueueSize
47
48  val fromTop = new Bundle {
49    val hartId = Input(UInt(8.W))
50  }
51  val fromWbFuBusyTable = new Bundle{
52    val fuBusyTableRead = MixedVec(params.issueBlockParams.map(x => Input(x.genWbFuBusyTableReadBundle)))
53  }
54  val wbFuBusyTable = MixedVec(params.issueBlockParams.map(x => Output(x.genWbFuBusyTableWriteBundle)))
55  val IQValidNumVec = Output(MixedVec(backendParams.genIQValidNumBundle))
56
57  val fromCtrlBlock = new Bundle {
58    val flush = Flipped(ValidIO(new Redirect))
59  }
60  val fromDispatch = new Bundle {
61    val allocPregs = Vec(RenameWidth, Input(new ResetPregStateReq))
62    val uops =  Vec(params.numUopIn, Flipped(DecoupledIO(new DynInst)))
63  }
64  val intWriteBack = MixedVec(Vec(backendParams.numPregWb(IntData()),
65    new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth)))
66  val fpWriteBack = MixedVec(Vec(backendParams.numPregWb(FpData()),
67    new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth)))
68  val vfWriteBack = MixedVec(Vec(backendParams.numPregWb(VecData()),
69    new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth)))
70  val toDataPathAfterDelay: MixedVec[MixedVec[DecoupledIO[IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle))
71
72  val fromSchedulers = new Bundle {
73    val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle)
74  }
75
76  val toSchedulers = new Bundle {
77    val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = params.genIQWakeUpOutValidBundle
78  }
79
80  val fromDataPath = new Bundle {
81    val resp: MixedVec[MixedVec[OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle)))
82    val og0Cancel = Input(ExuOH(backendParams.numExu))
83    // Todo: remove this after no cancel signal from og1
84    val og1Cancel = Input(ExuOH(backendParams.numExu))
85    val cancelToBusyTable = Vec(backendParams.numExu, Flipped(ValidIO(new CancelSignal)))
86    // just be compatible to old code
87    def apply(i: Int)(j: Int) = resp(i)(j)
88  }
89
90  val loadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x)))))))
91  val memAddrIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x)))))))
92
93  val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO))
94
95  val memIO = if (params.isMemSchd) Some(new Bundle {
96    val lsqEnqIO = Flipped(new LsqEnqIO)
97  }) else None
98  val fromMem = if (params.isMemSchd) Some(new Bundle {
99    val ldaFeedback = Flipped(Vec(params.LduCnt, new MemRSFeedbackIO))
100    val staFeedback = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO))
101    val hyuFeedback = Flipped(Vec(params.HyuCnt, new MemRSFeedbackIO))
102    val stIssuePtr = Input(new SqPtr())
103    val lcommit = Input(UInt(log2Up(CommitWidth + 1).W))
104    val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB
105    val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst)))
106    val lqDeqPtr = Input(new LqPtr)
107    val sqDeqPtr = Input(new SqPtr)
108    // from lsq
109    val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W))
110    val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
111    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
112  }) else None
113  val toMem = if (params.isMemSchd) Some(new Bundle {
114    val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle))
115  }) else None
116  val fromOg2 = if(params.isVfSchd) Some(MixedVec(params.issueBlockParams.map(x => Flipped(x.genOG2RespBundle)))) else None
117}
118
119abstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
120  extends LazyModuleImp(wrapper)
121    with HasXSParameter
122{
123  val io = IO(new SchedulerIO())
124
125  // alias
126  private val iqWakeUpInMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] =
127    io.fromSchedulers.wakeupVec.map(x => (x.bits.exuIdx, x)).toMap
128  private val schdType = params.schdType
129
130  // Modules
131  val dispatch2Iq: Dispatch2IqImp = wrapper.dispatch2Iq.module
132  val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module)
133  if (params.isIntSchd) {
134    dispatch2Iq.io.IQValidNumVec.get := io.IQValidNumVec
135    io.IQValidNumVec := MixedVecInit(issueQueues.map(_.io.validCntDeqVec))
136  }
137  else io.IQValidNumVec := 0.U.asTypeOf(io.IQValidNumVec)
138
139  // valid count
140  dispatch2Iq.io.iqValidCnt := issueQueues.filter(_.params.StdCnt == 0).map(_.io.status.validCnt)
141
142  // BusyTable Modules
143  val intBusyTable = schdType match {
144    case IntScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numIntStateRead, wrapper.numIntStateWrite, IntPhyRegs, IntWB())))
145    case _ => None
146  }
147  val fpBusyTable = schdType match {
148    case FpScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numFpStateRead, wrapper.numFpStateWrite, FpPhyRegs, FpWB())))
149    case _ => None
150  }
151  val vfBusyTable = schdType match {
152    case VfScheduler() | MemScheduler() => Some(Module(new BusyTable(dispatch2Iq.numVfStateRead, wrapper.numVfStateWrite, VfPhyRegs, VfWB())))
153    case _ => None
154  }
155
156  dispatch2Iq.io match { case dp2iq =>
157    dp2iq.redirect <> io.fromCtrlBlock.flush
158    dp2iq.in <> io.fromDispatch.uops
159    dp2iq.readIntState.foreach(_ <> intBusyTable.get.io.read)
160    dp2iq.readFpState.foreach(_ <> fpBusyTable.get.io.read)
161    dp2iq.readVfState.foreach(_ <> vfBusyTable.get.io.read)
162  }
163
164  intBusyTable match {
165    case Some(bt) =>
166      bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) =>
167        btAllocPregs.valid := dpAllocPregs.isInt
168        btAllocPregs.bits := dpAllocPregs.preg
169      }
170      bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) =>
171        wb.valid := io.intWriteBack(i).wen && io.intWriteBack(i).intWen
172        wb.bits := io.intWriteBack(i).addr
173      }
174      bt.io.wakeUp := io.fromSchedulers.wakeupVec
175      bt.io.cancel := io.fromDataPath.cancelToBusyTable
176      bt.io.ldCancel := io.ldCancel
177    case None =>
178  }
179
180  fpBusyTable match {
181    case Some(bt) =>
182      bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) =>
183        btAllocPregs.valid := dpAllocPregs.isFp
184        btAllocPregs.bits := dpAllocPregs.preg
185      }
186      bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) =>
187        wb.valid := io.fpWriteBack(i).wen && io.fpWriteBack(i).fpWen
188        wb.bits := io.fpWriteBack(i).addr
189      }
190      bt.io.wakeUp := io.fromSchedulers.wakeupVec
191      bt.io.cancel := io.fromDataPath.cancelToBusyTable
192      bt.io.ldCancel := io.ldCancel
193    case None =>
194  }
195
196  vfBusyTable match {
197    case Some(bt) =>
198      bt.io.allocPregs.zip(io.fromDispatch.allocPregs).foreach { case (btAllocPregs, dpAllocPregs) =>
199        btAllocPregs.valid := dpAllocPregs.isVec
200        btAllocPregs.bits := dpAllocPregs.preg
201      }
202      bt.io.wbPregs.zipWithIndex.foreach { case (wb, i) =>
203        wb.valid := io.vfWriteBack(i).wen && io.vfWriteBack(i).vecWen
204        wb.bits := io.vfWriteBack(i).addr
205      }
206      bt.io.wakeUp := io.fromSchedulers.wakeupVec
207      bt.io.cancel := io.fromDataPath.cancelToBusyTable
208      bt.io.ldCancel := io.ldCancel
209    case None =>
210  }
211
212  val wakeupFromIntWBVec = Wire(params.genIntWBWakeUpSinkValidBundle)
213  val wakeupFromFpWBVec = Wire(params.genFpWBWakeUpSinkValidBundle)
214  val wakeupFromVfWBVec = Wire(params.genVfWBWakeUpSinkValidBundle)
215
216  wakeupFromIntWBVec.zip(io.intWriteBack).foreach { case (sink, source) =>
217    sink.valid := source.wen
218    sink.bits.rfWen := source.intWen
219    sink.bits.fpWen := source.fpWen
220    sink.bits.vecWen := source.vecWen
221    sink.bits.pdest := source.addr
222  }
223
224  wakeupFromFpWBVec.zip(io.fpWriteBack).foreach { case (sink, source) =>
225    sink.valid := source.wen
226    sink.bits.rfWen := source.intWen
227    sink.bits.fpWen := source.fpWen
228    sink.bits.vecWen := source.vecWen
229    sink.bits.pdest := source.addr
230  }
231
232  wakeupFromVfWBVec.zip(io.vfWriteBack).foreach { case (sink, source) =>
233    sink.valid := source.wen
234    sink.bits.rfWen := source.intWen
235    sink.bits.fpWen := source.fpWen
236    sink.bits.vecWen := source.vecWen
237    sink.bits.pdest := source.addr
238  }
239
240  // Connect bundles having the same wakeup source
241  issueQueues.zipWithIndex.foreach { case(iq, i) =>
242    iq.io.wakeupFromIQ.foreach { wakeUp =>
243      val wakeUpIn = iqWakeUpInMap(wakeUp.bits.exuIdx)
244      val exuIdx = wakeUp.bits.exuIdx
245      println(s"[Backend] Connect wakeup exuIdx ${exuIdx}")
246      connectSamePort(wakeUp,wakeUpIn)
247      backendParams.connectWakeup(exuIdx)
248      if (backendParams.isCopyPdest(exuIdx)) {
249        println(s"[Backend] exuIdx ${exuIdx} use pdestCopy ${backendParams.getCopyPdestIndex(exuIdx)}")
250        wakeUp.bits.pdest := wakeUpIn.bits.pdestCopy.get(backendParams.getCopyPdestIndex(exuIdx))
251        if (wakeUpIn.bits.rfWenCopy.nonEmpty) wakeUp.bits.rfWen := wakeUpIn.bits.rfWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
252        if (wakeUpIn.bits.fpWenCopy.nonEmpty) wakeUp.bits.fpWen := wakeUpIn.bits.fpWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
253        if (wakeUpIn.bits.vecWenCopy.nonEmpty) wakeUp.bits.vecWen := wakeUpIn.bits.vecWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
254        if (wakeUpIn.bits.loadDependencyCopy.nonEmpty) wakeUp.bits.loadDependency := wakeUpIn.bits.loadDependencyCopy.get(backendParams.getCopyPdestIndex(exuIdx))
255      }
256      if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B
257      if (iq.params.numFpSrc == 0)  wakeUp.bits.fpWen := false.B
258      if (iq.params.numVfSrc == 0)  wakeUp.bits.vecWen := false.B
259    }
260    iq.io.og0Cancel := io.fromDataPath.og0Cancel
261    iq.io.og1Cancel := io.fromDataPath.og1Cancel
262    iq.io.ldCancel := io.ldCancel
263  }
264
265  private val iqWakeUpOutMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] =
266    issueQueues.flatMap(_.io.wakeupToIQ)
267      .map(x => (x.bits.exuIdx, x))
268      .toMap
269
270  // Connect bundles having the same wakeup source
271  io.toSchedulers.wakeupVec.foreach { wakeUp =>
272    wakeUp := iqWakeUpOutMap(wakeUp.bits.exuIdx)
273  }
274
275  io.toDataPathAfterDelay.zipWithIndex.foreach { case (toDpDy, i) =>
276    toDpDy <> issueQueues(i).io.deqDelay
277  }
278
279  // Response
280  issueQueues.zipWithIndex.foreach { case (iq, i) =>
281    iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) =>
282      og0Resp := io.fromDataPath(i)(j).og0resp
283    }
284    iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) =>
285      og1Resp := io.fromDataPath(i)(j).og1resp
286    }
287    iq.io.finalIssueResp.foreach(_.zipWithIndex.foreach { case (finalIssueResp, j) =>
288      if (io.loadFinalIssueResp(i).isDefinedAt(j)) {
289        finalIssueResp := io.loadFinalIssueResp(i)(j)
290      } else {
291        finalIssueResp := 0.U.asTypeOf(finalIssueResp)
292      }
293    })
294    iq.io.memAddrIssueResp.foreach(_.zipWithIndex.foreach { case (memAddrIssueResp, j) =>
295      if (io.memAddrIssueResp(i).isDefinedAt(j)) {
296        memAddrIssueResp := io.memAddrIssueResp(i)(j)
297      } else {
298        memAddrIssueResp := 0.U.asTypeOf(memAddrIssueResp)
299      }
300    })
301    if(params.isVfSchd) {
302      iq.io.og2Resp.get.zipWithIndex.foreach { case (og2Resp, exuIdx) =>
303        og2Resp := io.fromOg2.get(i)(exuIdx)
304      }
305    }
306    iq.io.wbBusyTableRead := io.fromWbFuBusyTable.fuBusyTableRead(i)
307    io.wbFuBusyTable(i) := iq.io.wbBusyTableWrite
308  }
309
310  println(s"[Scheduler] io.fromSchedulers.wakeupVec: ${io.fromSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}")
311  println(s"[Scheduler] iqWakeUpInKeys: ${iqWakeUpInMap.keys}")
312
313  println(s"[Scheduler] iqWakeUpOutKeys: ${iqWakeUpOutMap.keys}")
314  println(s"[Scheduler] io.toSchedulers.wakeupVec: ${io.toSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}")
315}
316
317class SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
318  extends SchedulerImpBase(wrapper)
319    with HasXSParameter
320{
321//  dontTouch(io.vfWbFuBusyTable)
322  println(s"[SchedulerArithImp] " +
323    s"has intBusyTable: ${intBusyTable.nonEmpty}, " +
324    s"has vfBusyTable: ${vfBusyTable.nonEmpty}")
325
326  issueQueues.zipWithIndex.foreach { case (iq, i) =>
327    iq.io.flush <> io.fromCtrlBlock.flush
328    iq.io.enq <> dispatch2Iq.io.out(i)
329    val intWBIQ = params.schdType match {
330      case IntScheduler() => wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1)
331      case FpScheduler() => wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1)
332      case VfScheduler() => wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1)
333      case _ => null
334    }
335    iq.io.wakeupFromWB.zip(intWBIQ).foreach{ case (sink, source) => sink := source}
336  }
337}
338
339// FIXME: Vector mem instructions may not be handled properly!
340class SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
341  extends SchedulerImpBase(wrapper)
342    with HasXSParameter
343{
344  println(s"[SchedulerMemImp] " +
345    s"has intBusyTable: ${intBusyTable.nonEmpty}, " +
346    s"has vfBusyTable: ${vfBusyTable.nonEmpty}")
347
348  val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ)
349  val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs
350  val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0)
351  val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0)
352  val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ)
353  val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip
354
355  println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}")
356  println(s"[SchedulerMemImp] stAddrIQs.size:  ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}")
357  println(s"[SchedulerMemImp] ldAddrIQs.size:  ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}")
358  println(s"[SchedulerMemImp] stDataIQs.size:  ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}")
359  println(s"[SchedulerMemImp] hyuIQs.size:     ${hyuIQs.size    }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}")
360  require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty)
361
362  io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed?
363
364  private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten
365  require(loadWakeUp.length == io.fromMem.get.wakeup.length)
366  loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2)
367
368  memAddrIQs.zipWithIndex.foreach { case (iq, i) =>
369    iq.io.flush <> io.fromCtrlBlock.flush
370    iq.io.enq <> dispatch2Iq.io.out(i)
371    iq.io.wakeupFromWB.zip(
372      wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
373      wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
374      wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1)
375    ).foreach{ case (sink, source) => sink := source}
376  }
377
378  ldAddrIQs.zipWithIndex.foreach {
379    case (imp: IssueQueueMemAddrImp, i) =>
380      imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head)
381      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
382      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
383    case _ =>
384  }
385
386  stAddrIQs.zipWithIndex.foreach {
387    case (imp: IssueQueueMemAddrImp, i) =>
388      imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i)
389      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
390      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
391    case _ =>
392  }
393
394  hyuIQs.zip(hyuIQIdxs).foreach {
395    case (imp: IssueQueueMemAddrImp, idx) =>
396      imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head
397      imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1))
398      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
399      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
400      // TODO: refactor ditry code
401      imp.io.deqDelay(1).ready := false.B
402      io.toDataPathAfterDelay(idx)(1).valid := false.B
403      io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits)
404    case _ =>
405  }
406
407  private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk)
408  private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk)
409
410  println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq")
411  println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq")
412
413  private val staEnqs = stAddrIQs.map(_.io.enq).flatten
414  private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size)
415  private val hyaEnqs = hyuIQs.map(_.io.enq).flatten
416  private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size)
417
418  require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " +
419  s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})")
420
421  require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " +
422  s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})")
423
424  val d2IqStaOut = dispatch2Iq.io.out.zipWithIndex.filter(staIdxSeq contains _._2).unzip._1.flatten
425  d2IqStaOut.zip(staEnqs).zip(stdEnqs).foreach{ case((dp, staIQ), stdIQ) =>
426    val isAllReady = staIQ.ready && stdIQ.ready
427    dp.ready := isAllReady
428    staIQ.valid := dp.valid && isAllReady
429    stdIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou)
430  }
431
432  val d2IqHyaOut = dispatch2Iq.io.out.zipWithIndex.filter(hyaIdxSeq contains _._2).unzip._1.flatten
433  d2IqHyaOut.zip(hyaEnqs).zip(hydEnqs).foreach{ case((dp, hyaIQ), hydIQ) =>
434    val isAllReady = hyaIQ.ready && hydIQ.ready
435    dp.ready := isAllReady
436    hyaIQ.valid := dp.valid && isAllReady
437    hydIQ.valid := dp.valid && isAllReady && FuType.FuTypeOrR(dp.bits.fuType, FuType.stu, FuType.mou)
438  }
439
440  stDataIQs.zipWithIndex.foreach { case (iq, i) =>
441    iq.io.flush <> io.fromCtrlBlock.flush
442    iq.io.wakeupFromWB.zip(
443      wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
444      wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
445      wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq
446    ).foreach{ case (sink, source) => sink := source}
447  }
448
449  (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) =>
450    stdIQEnq.bits  := staIQEnq.bits
451    // Store data reuses store addr src(1) in dispatch2iq
452    // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ]
453    //                       \
454    //                        ---src*(1)--> [stdIQ]
455    // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1)
456    // instead of dispatch2Iq.io.out(x).bits.src*(1)
457    val stdIdx = 1
458    stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx)
459    stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(1)
460      stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx)
461    stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx)
462    stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx
463  }
464
465  vecMemIQs.foreach {
466    case imp: IssueQueueVecMemImp =>
467      imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr)
468      imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr)
469      // not used
470      imp.io.memIO.get.feedbackIO := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO)
471      // maybe not used
472      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
473      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
474      imp.io.wakeupFromWB.zip(
475        wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
476        wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
477        wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq
478      ).foreach{ case (sink, source) => sink := source}
479
480    case _ =>
481  }
482
483  val lsqEnqCtrl = Module(new LsqEnqCtrl)
484
485  lsqEnqCtrl.io.redirect <> io.fromCtrlBlock.flush
486  lsqEnqCtrl.io.enq <> dispatch2Iq.io.enqLsqIO.get
487  lsqEnqCtrl.io.lcommit := io.fromMem.get.lcommit
488  lsqEnqCtrl.io.scommit := io.fromMem.get.scommit
489  lsqEnqCtrl.io.lqCancelCnt := io.fromMem.get.lqCancelCnt
490  lsqEnqCtrl.io.sqCancelCnt := io.fromMem.get.sqCancelCnt
491  io.memIO.get.lsqEnqIO <> lsqEnqCtrl.io.enqLsq
492}
493