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