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