xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Scheduler.scala (revision 7da4513bca2c8a5b0aa433f4c859c25e12b2eb26)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
7import utility.HasPerfEvents
8import utils.OptionWrapper
9import xiangshan._
10import xiangshan.backend.Bundles._
11import xiangshan.backend.datapath.DataConfig._
12import xiangshan.backend.datapath.WbConfig._
13import xiangshan.backend.fu.FuType
14import xiangshan.backend.regfile.RfWritePortWithConfig
15import xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr, LqPtr}
16import xiangshan.backend.datapath.WbConfig.V0WB
17import xiangshan.backend.regfile.VlPregParams
18import xiangshan.backend.regcache.RegCacheTagTable
19
20sealed trait SchedulerType
21
22case class IntScheduler() extends SchedulerType
23case class FpScheduler() extends SchedulerType
24case class MemScheduler() extends SchedulerType
25case class VfScheduler() extends SchedulerType
26case class NoScheduler() extends SchedulerType
27
28class Scheduler(val params: SchdBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter {
29  override def shouldBeInlined: Boolean = false
30
31  val numIntStateWrite = backendParams.numPregWb(IntData())
32  val numFpStateWrite = backendParams.numPregWb(FpData())
33  val numVfStateWrite = backendParams.numPregWb(VecData())
34  val numV0StateWrite = backendParams.numPregWb(V0Data())
35  val numVlStateWrite = backendParams.numPregWb(VlData())
36
37  val issueQueue = params.issueBlockParams.map(x => LazyModule(new IssueQueue(x).suggestName(x.getIQName)))
38
39  lazy val module: SchedulerImpBase = params.schdType match {
40    case IntScheduler() => new SchedulerArithImp(this)(params, p)
41    case FpScheduler()  => new SchedulerArithImp(this)(params, p)
42    case MemScheduler() => new SchedulerMemImp(this)(params, p)
43    case VfScheduler() => new SchedulerArithImp(this)(params, p)
44    case _ => null
45  }
46}
47
48class SchedulerIO()(implicit params: SchdBlockParams, p: Parameters) extends XSBundle {
49  // params alias
50  private val LoadQueueSize = VirtualLoadQueueSize
51  val fromDispatchUopNum = params.issueBlockParams.filter(x => x.StdCnt == 0).map(_.numEnq).sum
52  val allIssueParams = params.issueBlockParams.filter(_.StdCnt == 0)
53  val IssueQueueDeqSum = allIssueParams.map(_.numDeq).sum
54  val maxIQSize = allIssueParams.map(_.numEntries).max
55  val fromTop = new Bundle {
56    val hartId = Input(UInt(8.W))
57  }
58  val fromWbFuBusyTable = new Bundle{
59    val fuBusyTableRead = MixedVec(params.issueBlockParams.map(x => Input(x.genWbFuBusyTableReadBundle)))
60  }
61  val wbFuBusyTable = MixedVec(params.issueBlockParams.map(x => Output(x.genWbFuBusyTableWriteBundle)))
62  val IQValidNumVec = Output(Vec(IssueQueueDeqSum, UInt((maxIQSize).U.getWidth.W)))
63
64  val fromCtrlBlock = new Bundle {
65    val flush = Flipped(ValidIO(new Redirect))
66  }
67  val fromDispatch = new Bundle {
68    val uops =  Vec(fromDispatchUopNum, Flipped(DecoupledIO(new DynInst)))
69  }
70  val intWriteBack = MixedVec(Vec(backendParams.numPregWb(IntData()),
71    new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth)))
72  val fpWriteBack = MixedVec(Vec(backendParams.numPregWb(FpData()),
73    new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth)))
74  val vfWriteBack = MixedVec(Vec(backendParams.numPregWb(VecData()),
75    new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth)))
76  val v0WriteBack = MixedVec(Vec(backendParams.numPregWb(V0Data()),
77    new RfWritePortWithConfig(backendParams.v0PregParams.dataCfg, backendParams.v0PregParams.addrWidth)))
78  val vlWriteBack = MixedVec(Vec(backendParams.numPregWb(VlData()),
79    new RfWritePortWithConfig(backendParams.vlPregParams.dataCfg, backendParams.vlPregParams.addrWidth)))
80  val intWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(IntData()),
81    new RfWritePortWithConfig(backendParams.intPregParams.dataCfg, backendParams.intPregParams.addrWidth)))
82  val fpWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(FpData()),
83    new RfWritePortWithConfig(backendParams.fpPregParams.dataCfg, backendParams.fpPregParams.addrWidth)))
84  val vfWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(VecData()),
85    new RfWritePortWithConfig(backendParams.vfPregParams.dataCfg, backendParams.vfPregParams.addrWidth)))
86  val v0WriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(V0Data()),
87    new RfWritePortWithConfig(backendParams.v0PregParams.dataCfg, backendParams.v0PregParams.addrWidth)))
88  val vlWriteBackDelayed = MixedVec(Vec(backendParams.numPregWb(VlData()),
89    new RfWritePortWithConfig(backendParams.vlPregParams.dataCfg, backendParams.vlPregParams.addrWidth)))
90  val toDataPathAfterDelay: MixedVec[MixedVec[DecoupledIO[IssueQueueIssueBundle]]] = MixedVec(params.issueBlockParams.map(_.genIssueDecoupledBundle))
91
92  val vlWriteBackInfo = new Bundle {
93    val vlFromIntIsZero  = Input(Bool())
94    val vlFromIntIsVlmax = Input(Bool())
95    val vlFromVfIsZero   = Input(Bool())
96    val vlFromVfIsVlmax  = Input(Bool())
97  }
98
99  val fromSchedulers = new Bundle {
100    val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle)
101    val wakeupVecDelayed: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpInValidBundle)
102  }
103
104  val toSchedulers = new Bundle {
105    val wakeupVec: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = params.genIQWakeUpOutValidBundle
106  }
107
108  val fromDataPath = new Bundle {
109    val resp: MixedVec[MixedVec[OGRespBundle]] = MixedVec(params.issueBlockParams.map(x => Flipped(x.genOGRespBundle)))
110    val og0Cancel = Input(ExuVec())
111    // Todo: remove this after no cancel signal from og1
112    val og1Cancel = Input(ExuVec())
113    // replace RCIdx to Wakeup Queue
114    val replaceRCIdx = OptionWrapper(params.needWriteRegCache, Vec(params.numWriteRegCache, Input(UInt(RegCacheIdxWidth.W))))
115    // just be compatible to old code
116    def apply(i: Int)(j: Int) = resp(i)(j)
117  }
118
119  val loadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x)))))))
120  val vecLoadFinalIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.VlduCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x)))))))
121  val memAddrIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.LdExuCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x)))))))
122  val vecLoadIssueResp = MixedVec(params.issueBlockParams.map(x => MixedVec(Vec(x.VlduCnt, Flipped(ValidIO(new IssueQueueDeqRespBundle()(p, x)))))))
123
124  val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO))
125
126  val fromMem = if (params.isMemSchd) Some(new Bundle {
127    val ldaFeedback = Flipped(Vec(params.LduCnt, new MemRSFeedbackIO))
128    val staFeedback = Flipped(Vec(params.StaCnt, new MemRSFeedbackIO))
129    val hyuFeedback = Flipped(Vec(params.HyuCnt, new MemRSFeedbackIO))
130    val vstuFeedback = Flipped(Vec(params.VstuCnt, new MemRSFeedbackIO(isVector = true)))
131    val vlduFeedback = Flipped(Vec(params.VlduCnt, new MemRSFeedbackIO(isVector = true)))
132    val stIssuePtr = Input(new SqPtr())
133    val lcommit = Input(UInt(log2Up(CommitWidth + 1).W))
134    val scommit = Input(UInt(log2Ceil(EnsbufferWidth + 1).W)) // connected to `memBlock.io.sqDeq` instead of ROB
135    val wakeup = Vec(params.LdExuCnt, Flipped(Valid(new DynInst)))
136    val lqDeqPtr = Input(new LqPtr)
137    val sqDeqPtr = Input(new SqPtr)
138    // from lsq
139    val lqCancelCnt = Input(UInt(log2Up(LoadQueueSize + 1).W))
140    val sqCancelCnt = Input(UInt(log2Up(StoreQueueSize + 1).W))
141    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
142  }) else None
143  val toMem = if (params.isMemSchd) Some(new Bundle {
144    val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle))
145  }) else None
146  val fromOg2Resp = if(params.needOg2Resp) Some(MixedVec(params.issueBlockParams.filter(_.needOg2Resp).map(x => Flipped(x.genOG2RespBundle)))) else None
147}
148
149abstract class SchedulerImpBase(wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
150  extends LazyModuleImp(wrapper)
151    with HasXSParameter
152{
153  val io = IO(new SchedulerIO())
154
155  // alias
156  private val iqWakeUpInMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] =
157    io.fromSchedulers.wakeupVec.map(x => (x.bits.exuIdx, x)).toMap
158  private val iqWakeUpInMapDelayed: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] =
159    io.fromSchedulers.wakeupVecDelayed.map(x => (x.bits.exuIdx, x)).toMap
160  private val schdType = params.schdType
161
162  // Modules
163  val issueQueues: Seq[IssueQueueImp] = wrapper.issueQueue.map(_.module)
164
165  io.IQValidNumVec := issueQueues.filter(_.params.StdCnt == 0).map(_.io.validCntDeqVec).flatten
166  val wakeupFromIntWBVec = Wire(params.genIntWBWakeUpSinkValidBundle)
167  val wakeupFromFpWBVec = Wire(params.genFpWBWakeUpSinkValidBundle)
168  val wakeupFromVfWBVec = Wire(params.genVfWBWakeUpSinkValidBundle)
169  val wakeupFromV0WBVec = Wire(params.genV0WBWakeUpSinkValidBundle)
170  val wakeupFromVlWBVec = Wire(params.genVlWBWakeUpSinkValidBundle)
171  val wakeupFromIntWBVecDelayed = Wire(params.genIntWBWakeUpSinkValidBundle)
172  val wakeupFromFpWBVecDelayed = Wire(params.genFpWBWakeUpSinkValidBundle)
173  val wakeupFromVfWBVecDelayed = Wire(params.genVfWBWakeUpSinkValidBundle)
174  val wakeupFromV0WBVecDelayed = Wire(params.genV0WBWakeUpSinkValidBundle)
175  val wakeupFromVlWBVecDelayed = Wire(params.genVlWBWakeUpSinkValidBundle)
176
177  val wakeupFromWBVec = Seq(wakeupFromIntWBVec, wakeupFromFpWBVec, wakeupFromVfWBVec, wakeupFromV0WBVec, wakeupFromVlWBVec)
178  val allWriteBack = Seq(io.intWriteBack, io.fpWriteBack, io.vfWriteBack, io.v0WriteBack, io.vlWriteBack)
179  wakeupFromWBVec.zip(allWriteBack).map{ case (sinks, sources) =>
180    sinks.zip(sources).map{ case (sink, source) =>
181      sink.valid := source.wen
182      sink.bits.rfWen := source.intWen
183      sink.bits.fpWen := source.fpWen
184      sink.bits.vecWen := source.vecWen
185      sink.bits.v0Wen := source.v0Wen
186      sink.bits.vlWen := source.vlWen
187      sink.bits.pdest := source.addr
188    }
189  }
190
191  val wakeupFromWBVecDelayed = Seq(wakeupFromIntWBVecDelayed, wakeupFromFpWBVecDelayed, wakeupFromVfWBVecDelayed, wakeupFromV0WBVecDelayed, wakeupFromVlWBVecDelayed)
192  val allWriteBackDelayed = Seq(io.intWriteBackDelayed, io.fpWriteBackDelayed, io.vfWriteBackDelayed, io.v0WriteBackDelayed, io.vlWriteBackDelayed)
193  wakeupFromWBVecDelayed.zip(allWriteBackDelayed).map { case (sinks, sources) =>
194    sinks.zip(sources).map { case (sink, source) =>
195      sink.valid := source.wen
196      sink.bits.rfWen := source.intWen
197      sink.bits.fpWen := source.fpWen
198      sink.bits.vecWen := source.vecWen
199      sink.bits.v0Wen := source.v0Wen
200      sink.bits.vlWen := source.vlWen
201      sink.bits.pdest := source.addr
202    }
203  }
204  // Connect bundles having the same wakeup source
205  issueQueues.zipWithIndex.foreach { case(iq, i) =>
206    iq.io.wakeupFromIQ.foreach { wakeUp =>
207      val wakeUpIn = iqWakeUpInMap(wakeUp.bits.exuIdx)
208      val exuIdx = wakeUp.bits.exuIdx
209      println(s"[Backend] Connect wakeup exuIdx ${exuIdx}")
210      connectSamePort(wakeUp,wakeUpIn)
211      backendParams.connectWakeup(exuIdx)
212      if (backendParams.isCopyPdest(exuIdx)) {
213        println(s"[Backend] exuIdx ${exuIdx} use pdestCopy ${backendParams.getCopyPdestIndex(exuIdx)}")
214        wakeUp.bits.pdest := wakeUpIn.bits.pdestCopy.get(backendParams.getCopyPdestIndex(exuIdx))
215        if (wakeUpIn.bits.rfWenCopy.nonEmpty) wakeUp.bits.rfWen := wakeUpIn.bits.rfWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
216        if (wakeUpIn.bits.fpWenCopy.nonEmpty) wakeUp.bits.fpWen := wakeUpIn.bits.fpWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
217        if (wakeUpIn.bits.vecWenCopy.nonEmpty) wakeUp.bits.vecWen := wakeUpIn.bits.vecWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
218        if (wakeUpIn.bits.v0WenCopy.nonEmpty) wakeUp.bits.v0Wen := wakeUpIn.bits.v0WenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
219        if (wakeUpIn.bits.vlWenCopy.nonEmpty) wakeUp.bits.vlWen := wakeUpIn.bits.vlWenCopy.get(backendParams.getCopyPdestIndex(exuIdx))
220        if (wakeUpIn.bits.loadDependencyCopy.nonEmpty) wakeUp.bits.loadDependency := wakeUpIn.bits.loadDependencyCopy.get(backendParams.getCopyPdestIndex(exuIdx))
221      }
222      if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B
223      if (iq.params.numFpSrc == 0)  wakeUp.bits.fpWen := false.B
224      if (iq.params.numVfSrc == 0)  wakeUp.bits.vecWen := false.B
225      if (iq.params.numV0Src == 0)  wakeUp.bits.v0Wen := false.B
226      if (iq.params.numVlSrc == 0)  wakeUp.bits.vlWen := false.B
227    }
228    iq.io.wakeupFromIQDelayed.foreach { wakeUp =>
229      val wakeUpIn = iqWakeUpInMapDelayed(wakeUp.bits.exuIdx)
230      connectSamePort(wakeUp, wakeUpIn)
231      if (iq.params.numIntSrc == 0) wakeUp.bits.rfWen := false.B
232      if (iq.params.numFpSrc == 0) wakeUp.bits.fpWen := false.B
233      if (iq.params.numVfSrc == 0) wakeUp.bits.vecWen := false.B
234      if (iq.params.numV0Src == 0) wakeUp.bits.v0Wen := false.B
235      if (iq.params.numVlSrc == 0) wakeUp.bits.vlWen := false.B
236    }
237    iq.io.og0Cancel := io.fromDataPath.og0Cancel
238    iq.io.og1Cancel := io.fromDataPath.og1Cancel
239    if (iq.params.needLoadDependency)
240      iq.io.ldCancel := io.ldCancel
241    else
242      iq.io.ldCancel := 0.U.asTypeOf(io.ldCancel)
243  }
244
245  // connect the vl writeback informatino to the issue queues
246  issueQueues.zipWithIndex.foreach { case(iq, i) =>
247    iq.io.vlFromIntIsVlmax := io.vlWriteBackInfo.vlFromIntIsVlmax
248    iq.io.vlFromIntIsZero := io.vlWriteBackInfo.vlFromIntIsZero
249    iq.io.vlFromVfIsVlmax := io.vlWriteBackInfo.vlFromVfIsVlmax
250    iq.io.vlFromVfIsZero := io.vlWriteBackInfo.vlFromVfIsZero
251  }
252
253  private val iqWakeUpOutMap: Map[Int, ValidIO[IssueQueueIQWakeUpBundle]] =
254    issueQueues.flatMap(_.io.wakeupToIQ)
255      .map(x => (x.bits.exuIdx, x))
256      .toMap
257
258  // Connect bundles having the same wakeup source
259  io.toSchedulers.wakeupVec.foreach { wakeUp =>
260    wakeUp := iqWakeUpOutMap(wakeUp.bits.exuIdx)
261  }
262
263  io.toDataPathAfterDelay.zipWithIndex.foreach { case (toDpDy, i) =>
264    toDpDy <> issueQueues(i).io.deqDelay
265  }
266
267  // Response
268  issueQueues.zipWithIndex.foreach { case (iq, i) =>
269    iq.io.og0Resp.zipWithIndex.foreach { case (og0Resp, j) =>
270      og0Resp := io.fromDataPath(i)(j).og0resp
271    }
272    iq.io.og1Resp.zipWithIndex.foreach { case (og1Resp, j) =>
273      og1Resp := io.fromDataPath(i)(j).og1resp
274    }
275    iq.io.finalIssueResp.foreach(_.zipWithIndex.foreach { case (finalIssueResp, j) =>
276      if (io.loadFinalIssueResp(i).isDefinedAt(j) && iq.params.isLdAddrIQ) {
277        finalIssueResp := io.loadFinalIssueResp(i)(j)
278      } else if (io.vecLoadFinalIssueResp(i).isDefinedAt(j) && iq.params.isVecLduIQ) {
279        finalIssueResp := io.vecLoadFinalIssueResp(i)(j)
280      }
281      else {
282        finalIssueResp := 0.U.asTypeOf(finalIssueResp)
283      }
284    })
285    iq.io.memAddrIssueResp.foreach(_.zipWithIndex.foreach { case (memAddrIssueResp, j) =>
286      if (io.memAddrIssueResp(i).isDefinedAt(j)) {
287        memAddrIssueResp := io.memAddrIssueResp(i)(j)
288      } else {
289        memAddrIssueResp := 0.U.asTypeOf(memAddrIssueResp)
290      }
291    })
292    iq.io.vecLoadIssueResp.foreach(_.zipWithIndex.foreach { case (resp, deqIdx) =>
293      resp := io.vecLoadIssueResp(i)(deqIdx)
294    })
295    iq.io.wbBusyTableRead := io.fromWbFuBusyTable.fuBusyTableRead(i)
296    io.wbFuBusyTable(i) := iq.io.wbBusyTableWrite
297    iq.io.replaceRCIdx.foreach(x => x := 0.U.asTypeOf(x))
298  }
299  if (params.needOg2Resp) {
300    issueQueues.filter(_.params.needOg2Resp).zip(io.fromOg2Resp.get).foreach{ case (iq, og2RespVec) =>
301      iq.io.og2Resp.get.zip(og2RespVec).foreach{ case (iqOg2Resp, og2Resp) =>
302        iqOg2Resp := og2Resp
303      }
304    }
305  }
306
307  // Connect each replace RCIdx to IQ
308  if (params.needWriteRegCache) {
309    val iqReplaceRCIdxVec = issueQueues.filter(_.params.needWriteRegCache).flatMap{ iq =>
310      iq.params.allExuParams.zip(iq.io.replaceRCIdx.get).filter(_._1.needWriteRegCache).map(_._2)
311    }
312    iqReplaceRCIdxVec.zip(io.fromDataPath.replaceRCIdx.get).foreach{ case (iq, in) =>
313      iq := in
314    }
315
316    println(s"[Scheduler] numWriteRegCache: ${params.numWriteRegCache}")
317    println(s"[Scheduler] iqReplaceRCIdxVec: ${iqReplaceRCIdxVec.size}")
318  }
319
320  // perfEvent
321  val lastCycleIqEnqFireVec    = RegNext(VecInit(issueQueues.map(_.io.enq.map(_.fire)).flatten))
322  val lastCycleIqFullVec       = RegNext(VecInit(issueQueues.map(_.io.enq.head.ready)))
323
324  val issueQueueFullVecPerf = issueQueues.zip(lastCycleIqFullVec)map{ case (iq, full) => (iq.params.getIQName + s"_full", full) }
325  val basePerfEvents = Seq(
326    ("issueQueue_enq_fire_cnt",  PopCount(lastCycleIqEnqFireVec)                    )
327  )  ++ issueQueueFullVecPerf
328
329  println(s"[Scheduler] io.fromSchedulers.wakeupVec: ${io.fromSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}")
330  println(s"[Scheduler] iqWakeUpInKeys: ${iqWakeUpInMap.keys}")
331
332  println(s"[Scheduler] iqWakeUpOutKeys: ${iqWakeUpOutMap.keys}")
333  println(s"[Scheduler] io.toSchedulers.wakeupVec: ${io.toSchedulers.wakeupVec.map(x => backendParams.getExuName(x.bits.exuIdx))}")
334}
335
336class SchedulerArithImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
337  extends SchedulerImpBase(wrapper)
338    with HasXSParameter
339    with HasPerfEvents
340{
341  val issueQueuesUopIn = issueQueues.map(_.io.enq).flatten
342  issueQueuesUopIn.zip(io.fromDispatch.uops).map(x => x._1 <> x._2)
343  issueQueues.zipWithIndex.foreach { case (iq, i) =>
344    iq.io.flush <> io.fromCtrlBlock.flush
345    if (!iq.params.needLoadDependency) {
346      iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency))
347    }
348    val intWBIQ = params.schdType match {
349      case IntScheduler() => wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1)
350      case FpScheduler() => wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1)
351      case VfScheduler() => (wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
352                             wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++
353                             wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1))
354      case _ => null
355    }
356    val intWBIQDelayed = params.schdType match {
357      case IntScheduler() => wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1)
358      case FpScheduler() => wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1)
359      case VfScheduler() => (wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
360                             wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++
361                             wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1))
362      case _ => null
363    }
364    iq.io.wakeupFromWB.zip(intWBIQ).foreach{ case (sink, source) => sink := source}
365    iq.io.wakeupFromWBDelayed.zip(intWBIQDelayed).foreach{ case (sink, source) => sink := source}
366  }
367
368  val perfEvents = basePerfEvents
369  generatePerfEvent()
370}
371
372// FIXME: Vector mem instructions may not be handled properly!
373class SchedulerMemImp(override val wrapper: Scheduler)(implicit params: SchdBlockParams, p: Parameters)
374  extends SchedulerImpBase(wrapper)
375    with HasXSParameter
376    with HasPerfEvents
377{
378
379  val issueQueuesUopIn = issueQueues.filter(_.params.StdCnt == 0).map(_.io.enq).flatten
380  issueQueuesUopIn.zip(io.fromDispatch.uops).map(x => x._1 <> x._2)
381  val noStdExuParams = params.issueBlockParams.map(x => Seq.fill(x.numEnq)(x.exuBlockParams)).flatten.filter{x => x.map(!_.hasStdFu).reduce(_ && _)}
382  val staIdx = noStdExuParams.zipWithIndex.filter{x => x._1.map(_.hasStoreAddrFu).reduce(_ || _)}.map(_._2)
383  val staReady = issueQueues.filter(iq => iq.params.StaCnt > 0).map(_.io.enq.map(_.ready)).flatten
384  val stdReady = issueQueues.filter(iq => iq.params.StdCnt > 0).map(_.io.enq.map(_.ready)).flatten
385  staIdx.zipWithIndex.map{ case (sta, i) => {
386    io.fromDispatch.uops(sta).ready := staReady(i) && stdReady(i)
387  }}
388  val memAddrIQs = issueQueues.filter(_.params.isMemAddrIQ)
389  val stAddrIQs = issueQueues.filter(iq => iq.params.StaCnt > 0) // included in memAddrIQs
390  val ldAddrIQs = issueQueues.filter(iq => iq.params.LduCnt > 0)
391  val stDataIQs = issueQueues.filter(iq => iq.params.StdCnt > 0)
392  val vecMemIQs = issueQueues.filter(_.params.isVecMemIQ)
393  val (hyuIQs, hyuIQIdxs) = issueQueues.zipWithIndex.filter(_._1.params.HyuCnt > 0).unzip
394
395  println(s"[SchedulerMemImp] memAddrIQs.size: ${memAddrIQs.size}, enq.size: ${memAddrIQs.map(_.io.enq.size).sum}")
396  println(s"[SchedulerMemImp] stAddrIQs.size:  ${stAddrIQs.size }, enq.size: ${stAddrIQs.map(_.io.enq.size).sum}")
397  println(s"[SchedulerMemImp] ldAddrIQs.size:  ${ldAddrIQs.size }, enq.size: ${ldAddrIQs.map(_.io.enq.size).sum}")
398  println(s"[SchedulerMemImp] stDataIQs.size:  ${stDataIQs.size }, enq.size: ${stDataIQs.map(_.io.enq.size).sum}")
399  println(s"[SchedulerMemImp] hyuIQs.size:     ${hyuIQs.size    }, enq.size: ${hyuIQs.map(_.io.enq.size).sum}")
400  require(memAddrIQs.nonEmpty && stDataIQs.nonEmpty)
401
402  io.toMem.get.loadFastMatch := 0.U.asTypeOf(io.toMem.get.loadFastMatch) // TODO: is still needed?
403
404  private val loadWakeUp = issueQueues.filter(_.params.LdExuCnt > 0).map(_.asInstanceOf[IssueQueueMemAddrImp].io.memIO.get.loadWakeUp).flatten
405  require(loadWakeUp.length == io.fromMem.get.wakeup.length)
406  loadWakeUp.zip(io.fromMem.get.wakeup).foreach(x => x._1 := x._2)
407
408  memAddrIQs.zipWithIndex.foreach { case (iq, i) =>
409    iq.io.flush <> io.fromCtrlBlock.flush
410    if (!iq.params.needLoadDependency) {
411      iq.io.enq.map(x => x.bits.srcLoadDependency := 0.U.asTypeOf(x.bits.srcLoadDependency))
412    }
413    iq.io.wakeupFromWB.zip(
414      wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
415      wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
416      wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
417      wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++
418      wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1)
419    ).foreach{ case (sink, source) => sink := source}
420    iq.io.wakeupFromWBDelayed.zip(
421      wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
422      wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
423      wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1) ++
424      wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1) ++
425      wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1)
426    ).foreach { case (sink, source) => sink := source }
427  }
428
429  ldAddrIQs.zipWithIndex.foreach {
430    case (imp: IssueQueueMemAddrImp, i) =>
431      imp.io.memIO.get.feedbackIO.head := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO.head)
432      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
433      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
434    case _ =>
435  }
436
437  stAddrIQs.zipWithIndex.foreach {
438    case (imp: IssueQueueMemAddrImp, i) =>
439      imp.io.memIO.get.feedbackIO.head := io.fromMem.get.staFeedback(i)
440      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
441      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
442    case _ =>
443  }
444
445  hyuIQs.zip(hyuIQIdxs).foreach {
446    case (imp: IssueQueueMemAddrImp, idx) =>
447      imp.io.memIO.get.feedbackIO.head := io.fromMem.get.hyuFeedback.head
448      imp.io.memIO.get.feedbackIO(1) := 0.U.asTypeOf(imp.io.memIO.get.feedbackIO(1))
449      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
450      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
451      // TODO: refactor ditry code
452      imp.io.deqDelay(1).ready := false.B
453      io.toDataPathAfterDelay(idx)(1).valid := false.B
454      io.toDataPathAfterDelay(idx)(1).bits := 0.U.asTypeOf(io.toDataPathAfterDelay(idx)(1).bits)
455    case _ =>
456  }
457
458  private val staIdxSeq = (stAddrIQs).map(iq => iq.params.idxInSchBlk)
459  private val hyaIdxSeq = (hyuIQs).map(iq => iq.params.idxInSchBlk)
460
461  println(s"[SchedulerMemImp] sta iq idx in memSchdBlock: $staIdxSeq")
462  println(s"[SchedulerMemImp] hya iq idx in memSchdBlock: $hyaIdxSeq")
463
464  private val staEnqs = stAddrIQs.map(_.io.enq).flatten
465  private val stdEnqs = stDataIQs.map(_.io.enq).flatten.take(staEnqs.size)
466  private val hyaEnqs = hyuIQs.map(_.io.enq).flatten
467  private val hydEnqs = stDataIQs.map(_.io.enq).flatten.drop(staEnqs.size)
468
469  require(staEnqs.size == stdEnqs.size, s"number of enq ports of store address IQs(${staEnqs.size}) " +
470  s"should be equal to number of enq ports of store data IQs(${stdEnqs.size})")
471
472  require(hyaEnqs.size == hydEnqs.size, s"number of enq ports of hybrid address IQs(${hyaEnqs.size}) " +
473  s"should be equal to number of enq ports of hybrid data IQs(${hydEnqs.size})")
474
475  stDataIQs.zipWithIndex.foreach { case (iq, i) =>
476    iq.io.flush <> io.fromCtrlBlock.flush
477    iq.io.wakeupFromWB.zip(
478      wakeupFromIntWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
479      wakeupFromFpWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
480      wakeupFromVfWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
481      wakeupFromV0WBVec.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
482      wakeupFromVlWBVec.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq
483    ).foreach{ case (sink, source) => sink := source}
484    iq.io.wakeupFromWBDelayed.zip(
485      wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
486      wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
487      wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
488      wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
489      wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => iq.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq
490    ).foreach { case (sink, source) => sink := source }
491    // here disable fp load fast wakeup to std, and no FEX wakeup to std
492    iq.io.wakeupFromIQ.map(_.bits.fpWen := false.B)
493  }
494
495  (stdEnqs ++ hydEnqs).zip(staEnqs ++ hyaEnqs).zipWithIndex.foreach { case ((stdIQEnq, staIQEnq), i) =>
496    stdIQEnq.valid := staIQEnq.valid && FuType.FuTypeOrR(staIQEnq.bits.fuType, FuType.stu, FuType.mou)
497    stdIQEnq.bits  := staIQEnq.bits
498    // Store data reuses store addr src(1) in dispatch2iq
499    // [dispatch2iq] --src*------src*(0)--> [staIQ|hyaIQ]
500    //                       \
501    //                        ---src*(1)--> [stdIQ]
502    // Since the src(1) of sta is easier to get, stdIQEnq.bits.src*(0) is assigned to staIQEnq.bits.src*(1)
503    // instead of dispatch2Iq.io.out(x).bits.src*(1)
504    val stdIdx = 1
505    stdIQEnq.bits.srcState(0) := staIQEnq.bits.srcState(stdIdx)
506    stdIQEnq.bits.srcLoadDependency(0) := staIQEnq.bits.srcLoadDependency(stdIdx)
507    stdIQEnq.bits.srcType(0) := staIQEnq.bits.srcType(stdIdx)
508    stdIQEnq.bits.psrc(0) := staIQEnq.bits.psrc(stdIdx)
509    stdIQEnq.bits.sqIdx := staIQEnq.bits.sqIdx
510    stdIQEnq.bits.useRegCache(0) := staIQEnq.bits.useRegCache(stdIdx)
511    stdIQEnq.bits.regCacheIdx(0) := staIQEnq.bits.regCacheIdx(stdIdx)
512  }
513
514  vecMemIQs.foreach {
515    case imp: IssueQueueVecMemImp =>
516      imp.io.memIO.get.sqDeqPtr.foreach(_ := io.fromMem.get.sqDeqPtr)
517      imp.io.memIO.get.lqDeqPtr.foreach(_ := io.fromMem.get.lqDeqPtr)
518      // not used
519      //imp.io.memIO.get.feedbackIO.head := io.fromMem.get.vstuFeedback.head // only vector store replay
520      // maybe not used
521      imp.io.memIO.get.checkWait.stIssuePtr := io.fromMem.get.stIssuePtr
522      imp.io.memIO.get.checkWait.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
523      imp.io.wakeupFromWB.zip(
524        wakeupFromIntWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
525        wakeupFromFpWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
526        wakeupFromVfWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
527        wakeupFromV0WBVec.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
528        wakeupFromVlWBVec.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq
529      ).foreach{ case (sink, source) => sink := source}
530      imp.io.wakeupFromWBDelayed.zip(
531        wakeupFromIntWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromIntWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
532        wakeupFromFpWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromFpWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
533        wakeupFromVfWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromVfWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
534        wakeupFromV0WBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromV0WBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq ++
535        wakeupFromVlWBVecDelayed.zipWithIndex.filter(x => imp.params.needWakeupFromVlWBPort.keys.toSeq.contains(x._2)).map(_._1).toSeq
536      ).foreach { case (sink, source) => sink := source }
537
538    case _ =>
539  }
540  val vecMemFeedbackIO: Seq[MemRSFeedbackIO] = vecMemIQs.map {
541    case imp: IssueQueueVecMemImp =>
542      imp.io.memIO.get.feedbackIO
543  }.flatten
544  assert(vecMemFeedbackIO.size == io.fromMem.get.vstuFeedback.size, "vecMemFeedback size dont match!")
545  vecMemFeedbackIO.zip(io.fromMem.get.vstuFeedback).foreach{
546    case (sink, source) =>
547      sink := source
548  }
549
550  val perfEvents = basePerfEvents
551  generatePerfEvent()
552}
553