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