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