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