xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision 1526754bbe4ce56ccc1f68f09ea2756884e37b5a)
1package xiangshan.backend.issue
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import chisel3.util._
6import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
7import utility.{HasCircularQueuePtrHelper, ParallelLookUp}
8import utils.OptionWrapper
9import xiangshan._
10import xiangshan.backend.fu.{FuConfig, FuType}
11import xiangshan.mem.{MemWaitUpdateReq, SqPtr}
12import xiangshan.backend.Bundles._
13import xiangshan.backend.datapath.DataConfig._
14import xiangshan.backend.datapath.DataSource
15
16class IssueQueue(params: IssueBlockParams)(implicit p: Parameters) extends LazyModule with HasXSParameter {
17  implicit val iqParams = params
18  lazy val module = iqParams.schdType match {
19    case IntScheduler() => new IssueQueueIntImp(this)
20    case VfScheduler() => new IssueQueueVfImp(this)
21    case MemScheduler() => if (iqParams.StdCnt == 0) new IssueQueueMemAddrImp(this)
22      else new IssueQueueIntImp(this)
23    case _ => null
24  }
25}
26
27class IssueQueueStatusBundle(numEnq: Int) extends Bundle {
28  val empty = Output(Bool())
29  val full = Output(Bool())
30  val leftVec = Output(Vec(numEnq + 1, Bool()))
31}
32
33class IssueQueueDeqRespBundle(implicit p:Parameters, params: IssueBlockParams) extends StatusArrayDeqRespBundle
34
35class IssueQueueIO()(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
36  // Inputs
37  val flush = Flipped(ValidIO(new Redirect))
38  val enq = Vec(params.numEnq, Flipped(DecoupledIO(new DynInst)))
39
40  val deqResp = Vec(params.numDeq, Flipped(ValidIO(new IssueQueueDeqRespBundle)))
41  val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new IssueQueueDeqRespBundle)))
42  val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new IssueQueueDeqRespBundle)))
43  val wbBusyTableRead = Input(params.genWbFuBusyTableReadBundle())
44  val wbBusyTableWrite = Output(params.genWbFuBusyTableWriteBundle())
45  val wakeupFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
46  val wakeupFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
47  val cancelFromDataPath: MixedVec[IssueQueueCancelBundle] = Input(params.genCancelBundle(cancelStages))
48
49  // Outputs
50  val deq: MixedVec[DecoupledIO[IssueQueueIssueBundle]] = params.genIssueDecoupledBundle
51  val wakeupToIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = params.genIQWakeUpSourceValidBundle
52  val status = Output(new IssueQueueStatusBundle(params.numEnq))
53  val statusNext = Output(new IssueQueueStatusBundle(params.numEnq))
54
55  def allWakeUp = wakeupFromWB ++ wakeupFromIQ
56}
57
58class IssueQueueImp(override val wrapper: IssueQueue)(implicit p: Parameters, val params: IssueBlockParams)
59  extends LazyModuleImp(wrapper)
60  with HasXSParameter {
61
62  println(s"[IssueQueueImp] ${params.getIQName} wakeupFromWB(${io.wakeupFromWB.size}), " +
63    s"wakeup exu sources(${params.wakeUpInExuSources.size}): ${params.wakeUpInExuSources.map(_.name).mkString("{",",","}")}, " +
64    s"numEntries: ${params.numEntries}, numRegSrc: ${params.numRegSrc}")
65
66  require(params.numExu <= 2, "IssueQueue has not supported more than 2 deq ports")
67  val deqFuCfgs     : Seq[Seq[FuConfig]] = params.exuBlockParams.map(_.fuConfigs)
68  val allDeqFuCfgs  : Seq[FuConfig] = params.exuBlockParams.flatMap(_.fuConfigs)
69  val fuCfgsCnt     : Map[FuConfig, Int] = allDeqFuCfgs.groupBy(x => x).map { case (cfg, cfgSeq) => (cfg, cfgSeq.length) }
70  val commonFuCfgs  : Seq[FuConfig] = fuCfgsCnt.filter(_._2 > 1).keys.toSeq
71  val fuLatencyMaps : Seq[Map[Int, Int]] = params.exuBlockParams.map(x => x.fuLatencyMap)
72  println(s"[IssueQueueImp] ${params.getIQName} commonFuCfgs: ${commonFuCfgs.map(_.name)}")
73  lazy val io = IO(new IssueQueueIO())
74  dontTouch(io.deq)
75  dontTouch(io.deqResp)
76  // Modules
77  val statusArray   = Module(StatusArray(p, params))
78  val immArray      = Module(new DataArray(UInt(XLEN.W), params.numDeq, params.numEnq, params.numEntries))
79  val payloadArray  = Module(new DataArray(Output(new DynInst), params.numDeq, params.numEnq, params.numEntries))
80  val enqPolicy     = Module(new EnqPolicy)
81  val subDeqPolicies  = deqFuCfgs.map(x => if (x.nonEmpty) Some(Module(new DeqPolicy())) else None)
82  val fuBusyTableWrite = params.exuBlockParams.map { case x => OptionWrapper(x.latencyValMax > 0, Module(new FuBusyTableWrite(x.fuLatencyMap))) }
83  val fuBusyTableRead = params.exuBlockParams.map { case x => OptionWrapper(x.latencyValMax > 0, Module(new FuBusyTableRead(x.fuLatencyMap))) }
84  val intWbBusyTableWrite = params.exuBlockParams.map { case x => OptionWrapper(x.intLatencyCertain, Module(new FuBusyTableWrite(x.intFuLatencyMap))) }
85  val intWbBusyTableRead = params.exuBlockParams.map { case x => OptionWrapper(x.intLatencyCertain, Module(new FuBusyTableRead(x.intFuLatencyMap))) }
86  val vfWbBusyTableWrite = params.exuBlockParams.map { case x => OptionWrapper(x.vfLatencyCertain, Module(new FuBusyTableWrite(x.vfFuLatencyMap))) }
87  val vfWbBusyTableRead = params.exuBlockParams.map { case x => OptionWrapper(x.vfLatencyCertain, Module(new FuBusyTableRead(x.vfFuLatencyMap))) }
88
89  val wakeUpQueues: Seq[Option[MultiWakeupQueue[ExuInput, ValidIO[Redirect]]]] = params.exuBlockParams.map { x => OptionWrapper(x.isIQWakeUpSource, Module(
90    new MultiWakeupQueue(
91      new ExuInput(x),
92      ValidIO(new Redirect) ,
93      x.fuLatancySet,
94      (exuInput: ExuInput, flush: ValidIO[Redirect]) => exuInput.robIdx.needFlush(flush)
95    )
96  ))}
97
98  val intWbBusyTableIn = io.wbBusyTableRead.map(_.intWbBusyTable)
99  val vfWbBusyTableIn = io.wbBusyTableRead.map(_.vfWbBusyTable)
100  val intWbBusyTableOut = io.wbBusyTableWrite.map(_.intWbBusyTable)
101  val vfWbBusyTableOut = io.wbBusyTableWrite.map(_.vfWbBusyTable)
102  val intDeqRespSetOut = io.wbBusyTableWrite.map(_.intDeqRespSet)
103  val vfDeqRespSetOut = io.wbBusyTableWrite.map(_.vfDeqRespSet)
104  val fuBusyTableMask = Wire(Vec(params.numDeq, UInt(params.numEntries.W)))
105  val intWbBusyTableMask = Wire(Vec(params.numDeq, UInt(params.numEntries.W)))
106  val vfWbBusyTableMask = Wire(Vec(params.numDeq, UInt(params.numEntries.W)))
107  val s0_enqValidVec = io.enq.map(_.valid)
108  val s0_enqSelValidVec = Wire(Vec(params.numEnq, Bool()))
109  val s0_enqSelOHVec = Wire(Vec(params.numEnq, UInt(params.numEntries.W)))
110  val s0_enqNotFlush = !io.flush.valid
111  val s0_enqBits = WireInit(VecInit(io.enq.map(_.bits)))
112  val s0_doEnqSelValidVec = s0_enqSelValidVec.map(_ && s0_enqNotFlush)
113  val s0_doEnqOH: Vec[UInt] = VecInit((s0_doEnqSelValidVec zip s0_enqSelOHVec).map { case (valid, oh) =>
114    Mux(valid, oh, 0.U)
115  })
116
117  val s0_enqImmValidVec = io.enq.map(enq => enq.valid)
118  val s0_enqImmVec = VecInit(io.enq.map(_.bits.imm))
119
120  // One deq port only need one special deq policy
121  val subDeqSelValidVec: Seq[Option[Vec[Bool]]] = subDeqPolicies.map(_.map(_ => Wire(Vec(params.numDeq, Bool()))))
122  val subDeqSelOHVec: Seq[Option[Vec[UInt]]] = subDeqPolicies.map(_.map(_ => Wire(Vec(params.numDeq, UInt(params.numEntries.W)))))
123
124  val finalDeqSelValidVec = Wire(Vec(params.numDeq, Bool()))
125  val finalDeqSelOHVec    = Wire(Vec(params.numDeq, UInt(params.numEntries.W)))
126  val finalDeqOH: IndexedSeq[UInt] = (finalDeqSelValidVec zip finalDeqSelOHVec).map { case (valid, oh) =>
127    Mux(valid, oh, 0.U)
128  }
129  val finalDeqMask: UInt = finalDeqOH.reduce(_ | _)
130
131  val deqRespVec = io.deqResp
132
133  val validVec = VecInit(statusArray.io.valid.asBools)
134  val canIssueVec = VecInit(statusArray.io.canIssue.asBools)
135  val clearVec = VecInit(statusArray.io.clear.asBools)
136  val deqFirstIssueVec = VecInit(statusArray.io.deq.map(_.isFirstIssue))
137
138  val dataSources: Vec[Vec[DataSource]] = statusArray.io.dataSources
139  val finalDataSources: Vec[Vec[DataSource]] = VecInit(finalDeqOH.map(oh => Mux1H(oh, dataSources)))
140  // (entryIdx)(srcIdx)(exuIdx)
141  val wakeUpL1ExuOH: Option[Vec[Vec[Vec[Bool]]]] = statusArray.io.srcWakeUpL1ExuOH
142  val wakeUpL2ExuVec: Option[Vec[Vec[Vec[Bool]]]] = statusArray.io.srcWakeUpL2ExuVec
143
144  // (deqIdx)(srcIdx)(exuIdx)
145  val finalWakeUpL1ExuOH: Option[Vec[Vec[Vec[Bool]]]] = wakeUpL1ExuOH.map(x => VecInit(finalDeqOH.map(oh => Mux1H(oh, x))))
146  val finalWakeUpL2ExuVec: Option[Vec[Vec[Vec[Bool]]]] = wakeUpL2ExuVec.map(x => VecInit(finalDeqOH.map(oh => Mux1H(oh, x))))
147
148  val wakeupEnqSrcStateBypass = Wire(Vec(io.enq.size, Vec(io.enq.head.bits.srcType.size, SrcState())))
149  for (i <- io.enq.indices) {
150    for (j <- s0_enqBits(i).srcType.indices) {
151      wakeupEnqSrcStateBypass(i)(j) := Cat(
152        io.wakeupFromWB.map(x => x.bits.wakeUp(Seq((s0_enqBits(i).psrc(j), s0_enqBits(i).srcType(j))), x.valid).head)
153      ).orR
154    }
155  }
156
157  /**
158    * Connection of [[statusArray]]
159    */
160  statusArray.io match { case statusArrayIO: StatusArrayIO =>
161    statusArrayIO.flush  <> io.flush
162    statusArrayIO.wakeUpFromIQ := io.wakeupFromIQ
163    statusArrayIO.cancelFromDataPath := io.cancelFromDataPath
164    statusArrayIO.wakeUpFromWB := io.wakeupFromWB
165    statusArrayIO.enq.zipWithIndex.foreach { case (enq: ValidIO[StatusArrayEnqBundle], i) =>
166      enq.valid                 := s0_doEnqSelValidVec(i)
167      enq.bits.addrOH           := s0_enqSelOHVec(i)
168      val numLSrc = s0_enqBits(i).srcType.size.min(enq.bits.data.srcType.size)
169      for (j <- 0 until numLSrc) {
170        enq.bits.data.srcState(j) := s0_enqBits(i).srcState(j) | wakeupEnqSrcStateBypass(i)(j)
171        enq.bits.data.psrc(j)     := s0_enqBits(i).psrc(j)
172        enq.bits.data.srcType(j)  := s0_enqBits(i).srcType(j)
173      }
174      enq.bits.data.robIdx      := s0_enqBits(i).robIdx
175      enq.bits.data.issued      := false.B
176      enq.bits.data.firstIssue  := false.B
177      enq.bits.data.blocked     := false.B
178      enq.bits.data.dataSources.foreach(_.value := DataSource.reg)
179      enq.bits.data.srcWakeUpL1ExuOH match {
180        case Some(value) => value := 0.U.asTypeOf(value)
181        case None =>
182      }
183      enq.bits.data.srcWakeUpL2ExuVec match {
184        case Some(value) => value := 0.U.asTypeOf(value)
185        case None =>
186      }
187      enq.bits.data.srcTimer match {
188        case Some(value) => value := 0.U.asTypeOf(value)
189        case None =>
190      }
191    }
192    statusArrayIO.deq.zipWithIndex.foreach { case (deq, i) =>
193      deq.deqSelOH.valid  := finalDeqSelValidVec(i)
194      deq.deqSelOH.bits   := finalDeqSelOHVec(i)
195    }
196    statusArrayIO.deqResp.zipWithIndex.foreach { case (deqResp, i) =>
197      deqResp.valid      := io.deqResp(i).valid
198      deqResp.bits.addrOH := io.deqResp(i).bits.addrOH
199      deqResp.bits.dataInvalidSqIdx := io.deqResp(i).bits.dataInvalidSqIdx
200      deqResp.bits.respType := io.deqResp(i).bits.respType
201      deqResp.bits.rfWen := io.deqResp(i).bits.rfWen
202      deqResp.bits.fuType := io.deqResp(i).bits.fuType
203    }
204    statusArrayIO.og0Resp.zipWithIndex.foreach { case (og0Resp, i) =>
205      og0Resp.valid := io.og0Resp(i).valid
206      og0Resp.bits.addrOH := io.og0Resp(i).bits.addrOH
207      og0Resp.bits.dataInvalidSqIdx := io.og0Resp(i).bits.dataInvalidSqIdx
208      og0Resp.bits.respType := io.og0Resp(i).bits.respType
209      og0Resp.bits.rfWen := io.og0Resp(i).bits.rfWen
210      og0Resp.bits.fuType := io.og0Resp(i).bits.fuType
211    }
212    statusArrayIO.og1Resp.zipWithIndex.foreach { case (og1Resp, i) =>
213      og1Resp.valid := io.og1Resp(i).valid
214      og1Resp.bits.addrOH := io.og1Resp(i).bits.addrOH
215      og1Resp.bits.dataInvalidSqIdx := io.og1Resp(i).bits.dataInvalidSqIdx
216      og1Resp.bits.respType := io.og1Resp(i).bits.respType
217      og1Resp.bits.rfWen := io.og1Resp(i).bits.rfWen
218      og1Resp.bits.fuType := io.og1Resp(i).bits.fuType
219    }
220  }
221
222  /**
223    * Connection of [[immArray]]
224    */
225  val immArrayRdataVec = immArray.io.read.map(_.data)
226  immArray.io match { case immArrayIO: DataArrayIO[UInt] =>
227    immArrayIO.write.zipWithIndex.foreach { case (w, i) =>
228      w.en := s0_doEnqSelValidVec(i) && s0_enqImmValidVec(i)
229      w.addr := s0_enqSelOHVec(i)
230      w.data := s0_enqImmVec(i)
231    }
232    immArrayIO.read.zipWithIndex.foreach { case (r, i) =>
233      r.addr := finalDeqOH(i)
234    }
235  }
236
237  /**
238    * Connection of [[payloadArray]]
239    */
240  val payloadArrayRdata = Wire(Vec(params.numDeq, Output(new DynInst)))
241  payloadArray.io match { case payloadArrayIO: DataArrayIO[DynInst] =>
242    payloadArrayIO.write.zipWithIndex.foreach { case (w, i) =>
243      w.en := s0_doEnqSelValidVec(i)
244      w.addr := s0_enqSelOHVec(i)
245      w.data := s0_enqBits(i)
246    }
247    payloadArrayIO.read.zipWithIndex.foreach { case (r, i) =>
248      r.addr := finalDeqOH(i)
249      payloadArrayRdata(i) := r.data
250    }
251  }
252
253  val fuTypeRegVec = Reg(Vec(params.numEntries, FuType()))
254  val fuTypeNextVec = WireInit(fuTypeRegVec)
255  fuTypeRegVec := fuTypeNextVec
256
257  s0_doEnqSelValidVec.zip(s0_enqSelOHVec).zipWithIndex.foreach { case ((valid, oh), i) =>
258    when (valid) {
259      fuTypeNextVec(OHToUInt(oh)) := s0_enqBits(i).fuType
260    }
261  }
262
263  enqPolicy match { case ep =>
264    ep.io.valid     := validVec.asUInt
265    s0_enqSelValidVec  := ep.io.enqSelOHVec.map(oh => oh.valid).zip(s0_enqValidVec).zip(io.enq).map { case((sel, enqValid), enq) => enqValid && sel && enq.ready}
266    s0_enqSelOHVec     := ep.io.enqSelOHVec.map(oh => oh.bits)
267  }
268
269  protected val commonAccept: UInt = Cat(fuTypeRegVec.map(fuType =>
270    Cat(commonFuCfgs.map(_.fuType.U === fuType)).orR
271  ).reverse)
272
273  // if deq port can accept the uop
274  protected val canAcceptVec: Seq[UInt] = deqFuCfgs.map { fuCfgs: Seq[FuConfig] =>
275    Cat(fuTypeRegVec.map(fuType => Cat(fuCfgs.map(_.fuType.U === fuType)).orR).reverse).asUInt
276  }
277
278  protected val deqCanAcceptVec: Seq[IndexedSeq[Bool]] = deqFuCfgs.map { fuCfgs: Seq[FuConfig] =>
279    fuTypeRegVec.map(fuType =>
280      Cat(fuCfgs.map(_.fuType.U === fuType)).asUInt.orR) // C+E0    C+E1
281  }
282
283  subDeqPolicies.zipWithIndex.map { case (dpOption: Option[DeqPolicy], i) =>
284    if (dpOption.nonEmpty) {
285      val dp = dpOption.get
286      dp.io.request             := canIssueVec.asUInt & VecInit(deqCanAcceptVec(i)).asUInt & (~fuBusyTableMask(i)).asUInt & (~intWbBusyTableMask(i)).asUInt & (~vfWbBusyTableMask(i)).asUInt
287      subDeqSelValidVec(i).get  := dp.io.deqSelOHVec.map(oh => oh.valid)
288      subDeqSelOHVec(i).get     := dp.io.deqSelOHVec.map(oh => oh.bits)
289    }
290  }
291
292  protected val enqCanAcceptVec: Seq[IndexedSeq[Bool]] = deqFuCfgs.map { fuCfgs: Seq[FuConfig] =>
293    io.enq.map(_.bits.fuType).map(fuType =>
294      Cat(fuCfgs.map(_.fuType.U === fuType)).asUInt.orR) // C+E0    C+E1
295  }
296
297  val ageDetectorEnqVec: Vec[Vec[UInt]] = WireInit(VecInit(Seq.fill(params.numDeq)(VecInit(Seq.fill(params.numEnq)(0.U(params.numEntries.W))))))
298
299  ageDetectorEnqVec.zip(enqCanAcceptVec) foreach {
300    case (ageDetectorEnq, enqCanAccept) =>
301      ageDetectorEnq := enqCanAccept.zip(s0_doEnqOH).map {
302        case (enqCanAccept, s0_doEnqOH) => Mux(enqCanAccept, s0_doEnqOH, 0.U)
303      }
304  }
305
306  val oldestSelVec = (0 until params.numDeq).map {
307    case deqIdx =>
308      AgeDetector(numEntries = params.numEntries,
309        enq = ageDetectorEnqVec(deqIdx),
310        deq = clearVec.asUInt,
311        canIssue = canIssueVec.asUInt & (~fuBusyTableMask(deqIdx)).asUInt & (~intWbBusyTableMask(deqIdx)).asUInt & (~vfWbBusyTableMask(deqIdx)).asUInt)
312  }
313
314  finalDeqSelValidVec.head := oldestSelVec.head.valid || subDeqSelValidVec.head.getOrElse(Seq(false.B)).head
315  finalDeqSelOHVec.head := Mux(oldestSelVec.head.valid, oldestSelVec.head.bits, subDeqSelOHVec.head.getOrElse(Seq(0.U)).head)
316
317  if (params.numDeq == 2) {
318    val chooseOldest = oldestSelVec(1).valid && oldestSelVec(1).bits =/= finalDeqSelOHVec.head
319    val choose1stSub = subDeqSelOHVec(1).getOrElse(Seq(0.U)).head =/= finalDeqSelOHVec.head
320
321    finalDeqSelValidVec(1) := MuxCase(subDeqSelValidVec(1).getOrElse(Seq(false.B)).last, Seq(
322      (chooseOldest) -> oldestSelVec(1).valid,
323      (choose1stSub) -> subDeqSelValidVec(1).getOrElse(Seq(false.B)).head)
324    )
325    finalDeqSelOHVec(1) := MuxCase(subDeqSelOHVec(1).getOrElse(Seq(0.U)).last, Seq(
326      (chooseOldest) -> oldestSelVec(1).bits,
327      (choose1stSub) -> subDeqSelOHVec(1).getOrElse(Seq(0.U)).head)
328    )
329  }
330
331  //fuBusyTable
332  fuBusyTableWrite.zip(fuBusyTableRead).zipWithIndex.map { case ((busyTableWrite: Option[FuBusyTableWrite], busyTableRead: Option[FuBusyTableRead]), i) =>
333    if(busyTableWrite.nonEmpty) {
334      val btwr = busyTableWrite.get
335      val btrd = busyTableRead.get
336      btwr.io.in.deqResp := io.deqResp(i)
337      btwr.io.in.og0Resp := io.og0Resp(i)
338      btwr.io.in.og1Resp := io.og1Resp(i)
339      btrd.io.in.fuBusyTable := btwr.io.out.fuBusyTable
340      btrd.io.in.fuTypeRegVec := fuTypeRegVec
341      fuBusyTableMask(i) := btrd.io.out.fuBusyTableMask
342    }
343    else {
344      fuBusyTableMask(i) := 0.U(params.numEntries.W)
345    }
346  }
347
348  //wbfuBusyTable write
349  intWbBusyTableWrite.zip(intWbBusyTableOut).zip(intDeqRespSetOut).zipWithIndex.map { case (((busyTableWrite: Option[FuBusyTableWrite], busyTable: Option[UInt]), deqResp), i) =>
350    if(busyTableWrite.nonEmpty) {
351      val btwr = busyTableWrite.get
352      val bt = busyTable.get
353      val dq = deqResp.get
354      btwr.io.in.deqResp := io.deqResp(i)
355      btwr.io.in.og0Resp := io.og0Resp(i)
356      btwr.io.in.og1Resp := io.og1Resp(i)
357      bt := btwr.io.out.fuBusyTable
358      dq := btwr.io.out.deqRespSet
359    }
360  }
361
362  vfWbBusyTableWrite.zip(vfWbBusyTableOut).zip(vfDeqRespSetOut).zipWithIndex.map { case (((busyTableWrite: Option[FuBusyTableWrite], busyTable: Option[UInt]), deqResp), i) =>
363    if (busyTableWrite.nonEmpty) {
364      val btwr = busyTableWrite.get
365      val bt = busyTable.get
366      val dq = deqResp.get
367      btwr.io.in.deqResp := io.deqResp(i)
368      btwr.io.in.og0Resp := io.og0Resp(i)
369      btwr.io.in.og1Resp := io.og1Resp(i)
370      bt := btwr.io.out.fuBusyTable
371      dq := btwr.io.out.deqRespSet
372    }
373  }
374
375  //wbfuBusyTable read
376  intWbBusyTableRead.zip(intWbBusyTableIn).zipWithIndex.map { case ((busyTableRead: Option[FuBusyTableRead], busyTable: Option[UInt]), i) =>
377    if(busyTableRead.nonEmpty) {
378      val btrd = busyTableRead.get
379      val bt = busyTable.get
380      btrd.io.in.fuBusyTable := bt
381      btrd.io.in.fuTypeRegVec := fuTypeRegVec
382      intWbBusyTableMask(i) := btrd.io.out.fuBusyTableMask
383    }
384    else {
385      intWbBusyTableMask(i) := 0.U(params.numEntries.W)
386    }
387  }
388  vfWbBusyTableRead.zip(vfWbBusyTableIn).zipWithIndex.map { case ((busyTableRead: Option[FuBusyTableRead], busyTable: Option[UInt]), i) =>
389    if (busyTableRead.nonEmpty) {
390      val btrd = busyTableRead.get
391      val bt = busyTable.get
392      btrd.io.in.fuBusyTable := bt
393      btrd.io.in.fuTypeRegVec := fuTypeRegVec
394      vfWbBusyTableMask(i) := btrd.io.out.fuBusyTableMask
395    }
396    else {
397      vfWbBusyTableMask(i) := 0.U(params.numEntries.W)
398    }
399  }
400
401  wakeUpQueues.zipWithIndex.foreach { case (wakeUpQueueOption, i) =>
402    wakeUpQueueOption.foreach {
403      wakeUpQueue =>
404        wakeUpQueue.io.flush := io.flush
405        wakeUpQueue.io.enq.valid := io.deq(i).fire && {
406          if (io.deq(i).bits.common.rfWen.isDefined)
407            io.deq(i).bits.common.rfWen.get && io.deq(i).bits.common.pdest =/= 0.U
408          else
409            true.B
410        }
411        wakeUpQueue.io.enq.bits.uop := io.deq(i).bits.common
412        wakeUpQueue.io.enq.bits.lat := getDeqLat(i, io.deq(i).bits.common.fuType)
413    }
414  }
415
416  io.deq.zipWithIndex.foreach { case (deq, i) =>
417    deq.valid                := finalDeqSelValidVec(i)
418    deq.bits.addrOH          := finalDeqSelOHVec(i)
419    deq.bits.common.isFirstIssue := deqFirstIssueVec(i)
420    deq.bits.common.iqIdx    := OHToUInt(finalDeqSelOHVec(i))
421    deq.bits.common.fuType   := payloadArrayRdata(i).fuType
422    deq.bits.common.fuOpType := payloadArrayRdata(i).fuOpType
423    deq.bits.common.rfWen.foreach(_ := payloadArrayRdata(i).rfWen)
424    deq.bits.common.fpWen.foreach(_ := payloadArrayRdata(i).fpWen)
425    deq.bits.common.vecWen.foreach(_ := payloadArrayRdata(i).vecWen)
426    deq.bits.common.flushPipe.foreach(_ := payloadArrayRdata(i).flushPipe)
427    deq.bits.common.pdest := payloadArrayRdata(i).pdest
428    deq.bits.common.robIdx := payloadArrayRdata(i).robIdx
429    deq.bits.common.imm := immArrayRdataVec(i)
430    deq.bits.common.dataSources.zip(finalDataSources(i)).zipWithIndex.foreach {
431      case ((sink, source), srcIdx) =>
432        sink.value := Mux(
433          SrcType.isXp(payloadArrayRdata(i).srcType(srcIdx)) && payloadArrayRdata(i).psrc(srcIdx) === 0.U,
434          DataSource.none,
435          source.value
436        )
437    }
438    deq.bits.common.l1ExuVec.foreach(_ := finalWakeUpL1ExuOH.get(i))
439    deq.bits.common.l2ExuVec.foreach(_ := finalWakeUpL2ExuVec.get(i))
440
441    deq.bits.rf.zip(payloadArrayRdata(i).psrc).foreach { case (rf, psrc) =>
442      rf.foreach(_.addr := psrc) // psrc in payload array can be pregIdx of IntRegFile or VfRegFile
443    }
444    deq.bits.rf.zip(payloadArrayRdata(i).srcType).foreach { case (rf, srcType) =>
445      rf.foreach(_.srcType := srcType) // psrc in payload array can be pregIdx of IntRegFile or VfRegFile
446    }
447    deq.bits.srcType.zip(payloadArrayRdata(i).srcType).foreach { case (sink, source) =>
448      sink := source
449    }
450    deq.bits.immType := payloadArrayRdata(i).selImm
451  }
452
453  io.wakeupToIQ.zipWithIndex.foreach { case (wakeup, i) =>
454    if (wakeUpQueues(i).nonEmpty) {
455      wakeup.valid := wakeUpQueues(i).get.io.deq.valid
456      wakeup.bits.fromExuInput(wakeUpQueues(i).get.io.deq.bits, finalWakeUpL1ExuOH.get(i))
457    } else {
458      wakeup.valid := false.B
459      wakeup.bits := 0.U.asTypeOf(wakeup.bits.cloneType)
460    }
461  }
462
463  // Todo: better counter implementation
464  private val validCnt = PopCount(validVec)
465  private val enqSelCnt = PopCount(s0_doEnqSelValidVec)
466  private val validCntNext = validCnt + enqSelCnt
467  io.status.full := validVec.asUInt.andR
468  io.status.empty := !validVec.asUInt.orR
469  io.status.leftVec(0) := io.status.full
470  for (i <- 0 until params.numEnq) {
471    io.status.leftVec(i + 1) := validCnt === (params.numEntries - (i + 1)).U
472  }
473  io.statusNext.full := validCntNext === params.numEntries.U
474  io.statusNext.empty := validCntNext === 0.U // always false now
475  io.statusNext.leftVec(0) := io.statusNext.full
476  for (i <- 0 until params.numEnq) {
477    io.statusNext.leftVec(i + 1) := validCntNext === (params.numEntries - (i + 1)).U
478  }
479  io.enq.foreach(_.ready := !Cat(io.status.leftVec).orR) // Todo: more efficient implementation
480
481  protected def getDeqLat(deqPortIdx: Int, fuType: UInt) : UInt = {
482    ParallelLookUp(fuType, fuLatencyMaps(deqPortIdx).map { case (k, v) => (k.U, v.U) }.toSeq)
483  }
484}
485
486class IssueQueueJumpBundle extends Bundle {
487  val pc = UInt(VAddrData().dataWidth.W)
488  val target = UInt(VAddrData().dataWidth.W)
489}
490
491class IssueQueueLoadBundle(implicit p: Parameters) extends XSBundle {
492  val fastMatch = UInt(backendParams.LduCnt.W)
493  val fastImm = UInt(12.W)
494}
495
496class IssueQueueIntIO()(implicit p: Parameters, params: IssueBlockParams) extends IssueQueueIO {
497  val enqJmp = if(params.numPcReadPort > 0) Some(Input(Vec(params.numPcReadPort, new IssueQueueJumpBundle))) else None
498}
499
500class IssueQueueIntImp(override val wrapper: IssueQueue)(implicit p: Parameters, iqParams: IssueBlockParams)
501  extends IssueQueueImp(wrapper)
502{
503  io.suggestName("none")
504  override lazy val io = IO(new IssueQueueIntIO).suggestName("io")
505  val pcArray: Option[DataArray[UInt]] = if(params.needPc) Some(Module(
506    new DataArray(UInt(VAddrData().dataWidth.W), params.numDeq, params.numEnq, params.numEntries)
507  )) else None
508  val targetArray: Option[DataArray[UInt]] = if(params.needPc) Some(Module(
509    new DataArray(UInt(VAddrData().dataWidth.W), params.numDeq, params.numEnq, params.numEntries)
510  )) else None
511
512  if (pcArray.nonEmpty) {
513    val pcArrayIO = pcArray.get.io
514    pcArrayIO.read.zipWithIndex.foreach { case (r, i) =>
515      r.addr := finalDeqSelOHVec(i)
516    }
517    pcArrayIO.write.zipWithIndex.foreach { case (w, i) =>
518      w.en := s0_doEnqSelValidVec(i)
519      w.addr := s0_enqSelOHVec(i)
520      w.data := io.enq(i).bits.pc
521    }
522  }
523
524  if (targetArray.nonEmpty) {
525    val arrayIO = targetArray.get.io
526    arrayIO.read.zipWithIndex.foreach { case (r, i) =>
527      r.addr := finalDeqSelOHVec(i)
528    }
529    arrayIO.write.zipWithIndex.foreach { case (w, i) =>
530      w.en := s0_doEnqSelValidVec(i)
531      w.addr := s0_enqSelOHVec(i)
532      w.data := io.enqJmp.get(i).target
533    }
534  }
535
536  io.deq.zipWithIndex.foreach{ case (deq, i) => {
537    deq.bits.jmp.foreach((deqJmp: IssueQueueJumpBundle) => {
538      deqJmp.pc := pcArray.get.io.read(i).data
539      deqJmp.target := targetArray.get.io.read(i).data
540    })
541    deq.bits.common.preDecode.foreach(_ := payloadArrayRdata(i).preDecodeInfo)
542    deq.bits.common.ftqIdx.foreach(_ := payloadArrayRdata(i).ftqPtr)
543    deq.bits.common.ftqOffset.foreach(_ := payloadArrayRdata(i).ftqOffset)
544    deq.bits.common.predictInfo.foreach(x => {
545      x.target := targetArray.get.io.read(i).data
546      x.taken := payloadArrayRdata(i).pred_taken
547    })
548    // for std
549    deq.bits.common.sqIdx.foreach(_ := payloadArrayRdata(i).sqIdx)
550    // for i2f
551    deq.bits.common.fpu.foreach(_ := payloadArrayRdata(i).fpu)
552  }}
553}
554
555class IssueQueueVfImp(override val wrapper: IssueQueue)(implicit p: Parameters, iqParams: IssueBlockParams)
556  extends IssueQueueImp(wrapper)
557{
558  statusArray.io match { case statusArrayIO: StatusArrayIO =>
559    statusArrayIO.enq.zipWithIndex.foreach { case (enq: ValidIO[StatusArrayEnqBundle], i) =>
560      val numLSrc = s0_enqBits(i).srcType.size min enq.bits.data.srcType.size
561      val numPSrc = s0_enqBits(i).srcState.size min enq.bits.data.srcState.size
562
563      for (j <- 0 until numPSrc) {
564        enq.bits.data.srcState(j) := s0_enqBits(i).srcState(j) | wakeupEnqSrcStateBypass(i)(j)
565        enq.bits.data.psrc(j)     := s0_enqBits(i).psrc(j)
566      }
567
568      for (j <- 0 until numLSrc) {
569        enq.bits.data.srcType(j) := s0_enqBits(i).srcType(j)
570      }
571      if (enq.bits.data.srcType.isDefinedAt(3)) enq.bits.data.srcType(3) := SrcType.vp // v0: mask src
572      if (enq.bits.data.srcType.isDefinedAt(4)) enq.bits.data.srcType(4) := SrcType.vp // vl&vtype
573    }
574  }
575  io.deq.zipWithIndex.foreach{ case (deq, i) => {
576    deq.bits.common.fpu.foreach(_ := payloadArrayRdata(i).fpu)
577    deq.bits.common.vpu.foreach(_ := payloadArrayRdata(i).vpu)
578    deq.bits.common.vpu.foreach(_.vuopIdx := payloadArrayRdata(i).uopIdx)
579  }}
580}
581
582class IssueQueueMemBundle(implicit p: Parameters, params: IssueBlockParams) extends Bundle {
583  val feedbackIO = Flipped(Vec(params.numDeq, new MemRSFeedbackIO))
584  val checkWait = new Bundle {
585    val stIssuePtr = Input(new SqPtr)
586    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
587  }
588  val loadFastMatch = Output(Vec(params.LduCnt, new IssueQueueLoadBundle))
589}
590
591class IssueQueueMemIO(implicit p: Parameters, params: IssueBlockParams) extends IssueQueueIO {
592  val memIO = Some(new IssueQueueMemBundle)
593}
594
595class IssueQueueMemAddrImp(override val wrapper: IssueQueue)(implicit p: Parameters, params: IssueBlockParams)
596  extends IssueQueueImp(wrapper) with HasCircularQueuePtrHelper {
597
598  require(params.StdCnt == 0 && (params.LduCnt + params.StaCnt + params.VlduCnt) > 0, "IssueQueueMemAddrImp can only be instance of MemAddr IQ")
599
600  io.suggestName("none")
601  override lazy val io = IO(new IssueQueueMemIO).suggestName("io")
602  private val memIO = io.memIO.get
603
604  for (i <- io.enq.indices) {
605    val blockNotReleased = isAfter(io.enq(i).bits.sqIdx, memIO.checkWait.stIssuePtr)
606    val storeAddrWaitForIsIssuing = VecInit((0 until StorePipelineWidth).map(i => {
607      memIO.checkWait.memWaitUpdateReq.staIssue(i).valid &&
608        memIO.checkWait.memWaitUpdateReq.staIssue(i).bits.uop.robIdx.value === io.enq(i).bits.waitForRobIdx.value
609    })).asUInt.orR && !io.enq(i).bits.loadWaitStrict // is waiting for store addr ready
610    s0_enqBits(i).loadWaitBit := io.enq(i).bits.loadWaitBit && !storeAddrWaitForIsIssuing && blockNotReleased
611  }
612
613  for (i <- statusArray.io.enq.indices) {
614    statusArray.io.enq(i).bits.data match { case enqData =>
615      enqData.blocked := s0_enqBits(i).loadWaitBit
616      enqData.mem.get.strictWait := s0_enqBits(i).loadWaitStrict
617      enqData.mem.get.waitForStd := false.B
618      enqData.mem.get.waitForRobIdx := s0_enqBits(i).waitForRobIdx
619      enqData.mem.get.waitForSqIdx := 0.U.asTypeOf(enqData.mem.get.waitForSqIdx) // generated by sq, will be updated later
620      enqData.mem.get.sqIdx := s0_enqBits(i).sqIdx
621    }
622
623    statusArray.io.fromMem.get.slowResp.zipWithIndex.foreach { case (slowResp, i) =>
624      slowResp.valid                 := memIO.feedbackIO(i).feedbackSlow.valid
625      slowResp.bits.addrOH           := UIntToOH(memIO.feedbackIO(i).feedbackSlow.bits.rsIdx)
626      slowResp.bits.respType         := Mux(memIO.feedbackIO(i).feedbackSlow.bits.hit, RSFeedbackType.fuIdle, RSFeedbackType.feedbackInvalid)
627      slowResp.bits.dataInvalidSqIdx := memIO.feedbackIO(i).feedbackSlow.bits.dataInvalidSqIdx
628      slowResp.bits.rfWen := DontCare
629      slowResp.bits.fuType := DontCare
630    }
631
632    statusArray.io.fromMem.get.fastResp.zipWithIndex.foreach { case (fastResp, i) =>
633      fastResp.valid                 := memIO.feedbackIO(i).feedbackFast.valid
634      fastResp.bits.addrOH           := UIntToOH(memIO.feedbackIO(i).feedbackFast.bits.rsIdx)
635      fastResp.bits.respType         := memIO.feedbackIO(i).feedbackFast.bits.sourceType
636      fastResp.bits.dataInvalidSqIdx := 0.U.asTypeOf(fastResp.bits.dataInvalidSqIdx)
637      fastResp.bits.rfWen := DontCare
638      fastResp.bits.fuType := DontCare
639    }
640
641    statusArray.io.fromMem.get.memWaitUpdateReq := memIO.checkWait.memWaitUpdateReq
642    statusArray.io.fromMem.get.stIssuePtr := memIO.checkWait.stIssuePtr
643  }
644
645  io.deq.zipWithIndex.foreach { case (deq, i) =>
646    deq.bits.common.sqIdx.get := payloadArrayRdata(i).sqIdx
647    deq.bits.common.lqIdx.get := payloadArrayRdata(i).lqIdx
648    if (params.isLdAddrIQ) {
649      deq.bits.common.ftqIdx.get := payloadArrayRdata(i).ftqPtr
650      deq.bits.common.ftqOffset.get := payloadArrayRdata(i).ftqOffset
651    }
652  }
653}