xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision 7e471bf8b2982395923bb50201b2ee25880fadfc)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.HasCircularQueuePtrHelper
7import utils._
8import xiangshan._
9import xiangshan.backend.Bundles._
10import xiangshan.backend.datapath.DataConfig.VAddrData
11import xiangshan.backend.datapath.DataSource
12import xiangshan.backend.fu.FuType
13import xiangshan.backend.fu.vector.Utils.NOnes
14import xiangshan.backend.rob.RobPtr
15import xiangshan.mem.{LqPtr, MemWaitUpdateReq, SqPtr}
16import xiangshan.backend.issue.EntryBundles._
17
18class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
19  override def desiredName: String = params.getEntryName
20
21  require(params.numEnq <= 2, "number of enq should be no more than 2")
22
23  private val EnqEntryNum         = params.numEnq
24  private val OthersEntryNum      = params.numEntries - params.numEnq
25  private val SimpEntryNum        = params.numSimp
26  private val CompEntryNum        = params.numComp
27  val io = IO(new EntriesIO)
28
29  // only memAddrIQ use it
30  val memEtyResps: Seq[ValidIO[EntryDeqRespBundle]] = {
31    val resps =
32      if (params.isLdAddrIQ && !params.isStAddrIQ)                                                    //LDU
33        Seq(io.og0Resp, io.og1Resp, io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp)
34      else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ)                           //HYU
35        Seq(io.og0Resp, io.og1Resp, io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp, io.fromMem.get.fastResp, io.fromMem.get.slowResp)
36      else if (params.isStAddrIQ)                                                                     //STU
37        Seq(io.og0Resp, io.og1Resp, io.fromMem.get.slowResp)
38      else if (params.isVecLduIQ) // Vector store IQ need no vecLdIn.resp, but for now vector store share the vector load IQ
39        Seq(io.og0Resp, io.og1Resp, io.vecLdIn.get.resp)
40      else if (params.isVecStuIQ)
41        Seq(io.og0Resp, io.og1Resp, io.fromMem.get.slowResp)
42      else Seq()
43    if (params.isMemAddrIQ) {
44      println(s"[${this.desiredName}] resp: {" +
45        s"og0Resp: ${resps.contains(io.og0Resp)}, " +
46        s"og1Resp: ${resps.contains(io.og1Resp)}, " +
47        s"finalResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.finalIssueResp)}, " +
48        s"loadBorderResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.memAddrIssueResp)}, " +
49        s"memFastResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.fastResp)}, " +
50        s"memSlowResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.slowResp)}, " +
51        s"vecLoadBorderResp: ${io.vecLdIn.nonEmpty && resps.contains(io.vecLdIn.get.resp)}, " +
52        s"}"
53      )
54    }
55    resps.flatten
56  }
57
58  val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = VecInit(io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.og0Resp))
59
60
61
62  //Module
63  val enqEntries          = Seq.fill(EnqEntryNum)(Module(EnqEntry(isComp = true)(p, params)))
64  val othersEntriesSimp   = Seq.fill(SimpEntryNum)(Module(OthersEntry(isComp = false)(p, params)))
65  val othersEntriesComp   = Seq.fill(CompEntryNum)(Module(OthersEntry(isComp = true)(p, params)))
66  val othersEntries       = othersEntriesSimp ++ othersEntriesComp
67  val othersTransPolicy   = OptionWrapper(params.isAllComp || params.isAllSimp, Module(new EnqPolicy))
68  val simpTransPolicy     = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy))
69  val compTransPolicy     = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy))
70
71  //Wire
72  //entries status
73  val entries             = Wire(Vec(params.numEntries, ValidIO(new EntryBundle)))
74  val robIdxVec           = Wire(Vec(params.numEntries, new RobPtr))
75  val validVec            = Wire(Vec(params.numEntries, Bool()))
76  val canIssueVec         = Wire(Vec(params.numEntries, Bool()))
77  val fuTypeVec           = Wire(Vec(params.numEntries, FuType()))
78  val isFirstIssueVec     = Wire(Vec(params.numEntries, Bool()))
79  val issueTimerVec       = Wire(Vec(params.numEntries, UInt(2.W)))
80  val uopIdxVec           = OptionWrapper(params.isVecMemIQ, Wire(Vec(params.numEntries, UopIdx())))
81  //src status
82  val dataSourceVec       = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
83  val loadDependencyVec   = Wire(Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(3.W))))
84  val srcLoadDependencyVec= Wire(Vec(params.numEntries, Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W)))))
85  val srcTimerVec         = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W)))))
86  val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec()))))
87  //deq sel
88  val deqSelVec           = Wire(Vec(params.numEntries, Bool()))
89  val issueRespVec        = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle)))
90  val deqPortIdxWriteVec  = Wire(Vec(params.numEntries, UInt(1.W)))
91  val deqPortIdxReadVec   = Wire(Vec(params.numEntries, UInt(1.W)))
92  //trans sel
93  val othersEntryEnqReadyVec = Wire(Vec(OthersEntryNum, Bool()))
94  val othersEntryEnqVec      = Wire(Vec(OthersEntryNum, Valid(new EntryBundle)))
95  val enqEntryTransVec       = Wire(Vec(EnqEntryNum, Valid(new EntryBundle)))
96  val simpEntryTransVec      = OptionWrapper(params.hasCompAndSimp, Wire(Vec(SimpEntryNum, Valid(new EntryBundle))))
97  val compEnqVec             = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(new EntryBundle))))
98
99  val enqCanTrans2Simp       = OptionWrapper(params.hasCompAndSimp, Wire(Bool()))
100  val enqCanTrans2Comp       = OptionWrapper(params.hasCompAndSimp, Wire(Bool()))
101  val simpCanTrans2Comp      = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Bool())))
102  val simpTransSelVec        = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(UInt(SimpEntryNum.W)))))
103  val compTransSelVec        = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(UInt(CompEntryNum.W)))))
104  val finalSimpTransSelVec   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, UInt(SimpEntryNum.W))))
105  val finalCompTransSelVec   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, UInt(CompEntryNum.W))))
106
107  val enqCanTrans2Others     = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Bool()))
108  val othersTransSelVec      = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(EnqEntryNum, Valid(UInt(OthersEntryNum.W)))))
109  val finalOthersTransSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(EnqEntryNum, UInt(OthersEntryNum.W))))
110
111  val simpEntryEnqReadyVec   = othersEntryEnqReadyVec.take(SimpEntryNum)
112  val compEntryEnqReadyVec   = othersEntryEnqReadyVec.takeRight(CompEntryNum)
113  val simpEntryEnqVec        = othersEntryEnqVec.take(SimpEntryNum)
114  val compEntryEnqVec        = othersEntryEnqVec.takeRight(CompEntryNum)
115  //debug
116  val cancelVec              = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool())))
117  val entryInValidVec        = Wire(Vec(params.numEntries, Bool()))
118  val entryOutDeqValidVec    = Wire(Vec(params.numEntries, Bool()))
119  val entryOutTransValidVec  = Wire(Vec(params.numEntries, Bool()))
120  //cancel bypass
121  val cancelBypassVec        = Wire(Vec(params.numEntries, Bool()))
122
123
124  //enqEntries
125  enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) =>
126    enqEntry.io.commonIn.enq                  := io.enq(entryIdx)
127    enqEntry.io.commonIn.transSel             := (if (params.isAllComp || params.isAllSimp) enqCanTrans2Others.get && othersTransSelVec.get(entryIdx).valid
128                                                  else enqCanTrans2Simp.get && simpTransSelVec.get(entryIdx).valid || enqCanTrans2Comp.get && compTransSelVec.get(entryIdx).valid)
129    EntriesConnect(enqEntry.io.commonIn, enqEntry.io.commonOut, entryIdx)
130    enqEntry.io.enqDelayWakeUpFromWB          := RegEnable(io.wakeUpFromWB, io.enq(entryIdx).valid)
131    enqEntry.io.enqDelayWakeUpFromIQ          := RegEnable(io.wakeUpFromIQ, io.enq(entryIdx).valid)
132    enqEntry.io.enqDelayOg0Cancel             := RegNext(io.og0Cancel.asUInt)
133    enqEntry.io.enqDelayLdCancel              := RegNext(io.ldCancel)
134    enqEntryTransVec(entryIdx)                := enqEntry.io.commonOut.transEntry
135  }
136  //othersEntries
137  othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) =>
138    othersEntry.io.commonIn.enq               := othersEntryEnqVec(entryIdx)
139    othersEntry.io.commonIn.transSel          := (if (params.hasCompAndSimp && (entryIdx < SimpEntryNum))
140                                                    io.simpEntryDeqSelVec.get.zip(simpCanTrans2Comp.get).map(x => x._1(entryIdx) && x._2).reduce(_ | _)
141                                                  else false.B)
142    EntriesConnect(othersEntry.io.commonIn, othersEntry.io.commonOut, entryIdx + EnqEntryNum)
143    othersEntryEnqReadyVec(entryIdx)          := othersEntry.io.commonOut.enqReady
144    if (params.hasCompAndSimp && (entryIdx < SimpEntryNum)) {
145      simpEntryTransVec.get(entryIdx)         := othersEntry.io.commonOut.transEntry
146    }
147  }
148
149
150  deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) =>
151    val deqVec = io.deqSelOH.zip(io.deqReady).map(x => x._1.valid && x._1.bits(i) && x._2)
152    deqPortIdxWrite := OHToUInt(deqVec)
153    deqSel := deqVec.reduce(_ | _)
154  }
155
156
157  if (params.isAllComp || params.isAllSimp) {
158    //transPolicy
159    othersTransPolicy.get.io.canEnq := othersEntryEnqReadyVec.asUInt
160
161    // we only allow all or none of the enq entries transfering to others entries.
162    enqCanTrans2Others.get := PopCount(validVec.take(EnqEntryNum)) <= PopCount(othersEntryEnqReadyVec)
163    // othersTransSelVec(i) is the target others entry for enq entry [i].
164    // note that dispatch does not guarantee the validity of enq entries with low index.
165    // that means in some cases enq entry [0] is invalid while enq entry [1] is valid.
166    // in this case, enq entry [1] should use result [0] of TransPolicy.
167    othersTransSelVec.get(0).valid := othersTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0)
168    othersTransSelVec.get(0).bits  := othersTransPolicy.get.io.enqSelOHVec(0).bits
169    if (params.numEnq == 2) {
170      othersTransSelVec.get(1).valid := Mux(!validVec(0), othersTransPolicy.get.io.enqSelOHVec(0).valid, othersTransPolicy.get.io.enqSelOHVec(1).valid)
171      othersTransSelVec.get(1).bits  := Mux(!validVec(0), othersTransPolicy.get.io.enqSelOHVec(0).bits,  othersTransPolicy.get.io.enqSelOHVec(1).bits)
172    }
173
174    finalOthersTransSelVec.get.zip(othersTransSelVec.get).zipWithIndex.foreach { case ((finalOH, selOH), enqIdx) =>
175      finalOH := Fill(OthersEntryNum, enqCanTrans2Others.get && selOH.valid) & selOH.bits
176    }
177
178    //othersEntryEnq
179    othersEntryEnqVec.zipWithIndex.foreach { case (othersEntryEnq, othersIdx) =>
180      val othersEnqOH = finalOthersTransSelVec.get.map(_(othersIdx))
181      if (othersEnqOH.size == 1)
182        othersEntryEnq := Mux(othersEnqOH.head, enqEntryTransVec.head, 0.U.asTypeOf(enqEntryTransVec.head))
183      else
184        othersEntryEnq := Mux1H(othersEnqOH, enqEntryTransVec)
185    }
186  }
187  else {
188    //transPolicy
189    simpTransPolicy.get.io.canEnq := VecInit(simpEntryEnqReadyVec).asUInt
190    compTransPolicy.get.io.canEnq := VecInit(validVec.takeRight(CompEntryNum).map(!_)).asUInt
191
192    // we only allow all or none of the enq entries transfering to comp/simp entries.
193    // when all of simp entries are empty and comp entries are enough, transfer to comp entries.
194    // otherwise, transfer to simp entries.
195    enqCanTrans2Comp.get := PopCount(validVec.take(EnqEntryNum)) <= PopCount(validVec.takeRight(CompEntryNum).map(!_)) && !validVec.drop(EnqEntryNum).take(SimpEntryNum).reduce(_ || _)
196    enqCanTrans2Simp.get := !enqCanTrans2Comp.get && PopCount(validVec.take(EnqEntryNum)) <= PopCount(simpEntryEnqReadyVec)
197    simpCanTrans2Comp.get.zipWithIndex.foreach { case (canTrans, idx) =>
198      canTrans := !enqCanTrans2Comp.get && PopCount(validVec.takeRight(CompEntryNum).map(!_)) >= (idx + 1).U
199    }
200
201    // simp/compTransSelVec(i) is the target simp/comp entry for enq entry [i].
202    // note that dispatch does not guarantee the validity of enq entries with low index.
203    // that means in some cases enq entry [0] is invalid while enq entry [1] is valid.
204    // in this case, enq entry [1] should use result [0] of TransPolicy.
205    simpTransSelVec.get(0).valid := simpTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0)
206    simpTransSelVec.get(0).bits  := simpTransPolicy.get.io.enqSelOHVec(0).bits
207    compTransSelVec.get(0).valid := compTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0)
208    compTransSelVec.get(0).bits  := compTransPolicy.get.io.enqSelOHVec(0).bits
209    if (params.numEnq == 2) {
210      simpTransSelVec.get(1).valid := Mux(!validVec(0), simpTransPolicy.get.io.enqSelOHVec(0).valid, simpTransPolicy.get.io.enqSelOHVec(1).valid)
211      simpTransSelVec.get(1).bits  := Mux(!validVec(0), simpTransPolicy.get.io.enqSelOHVec(0).bits,  simpTransPolicy.get.io.enqSelOHVec(1).bits)
212      compTransSelVec.get(1).valid := Mux(!validVec(0), compTransPolicy.get.io.enqSelOHVec(0).valid, compTransPolicy.get.io.enqSelOHVec(1).valid)
213      compTransSelVec.get(1).bits  := Mux(!validVec(0), compTransPolicy.get.io.enqSelOHVec(0).bits,  compTransPolicy.get.io.enqSelOHVec(1).bits)
214    }
215
216    finalSimpTransSelVec.get.zip(simpTransSelVec.get).zipWithIndex.foreach { case ((finalOH, selOH), enqIdx) =>
217      finalOH := Fill(SimpEntryNum, enqCanTrans2Simp.get && selOH.valid) & selOH.bits
218    }
219    finalCompTransSelVec.get.zip(compTransSelVec.get).zip(compTransPolicy.get.io.enqSelOHVec).zipWithIndex.foreach {
220      case (((finalOH, selOH), origSelOH), enqIdx) =>
221        finalOH := Mux(enqCanTrans2Comp.get, Fill(CompEntryNum, selOH.valid) & selOH.bits, Fill(CompEntryNum, origSelOH.valid) & origSelOH.bits)
222    }
223
224    //othersEntryEnq
225    simpEntryEnqVec.zipWithIndex.foreach { case (simpEntryEnq, simpIdx) =>
226      val simpEnqOH = finalSimpTransSelVec.get.map(_(simpIdx))
227      // shit Mux1H directly returns in(0) if the seq has only 1 elements
228      if (simpEnqOH.size == 1)
229        simpEntryEnq := Mux(simpEnqOH.head, enqEntryTransVec.head, 0.U.asTypeOf(enqEntryTransVec.head))
230      else
231        simpEntryEnq := Mux1H(simpEnqOH, enqEntryTransVec)
232    }
233
234    compEnqVec.get.zip(enqEntryTransVec).zip(io.simpEntryDeqSelVec.get).foreach { case ((compEnq, enqEntry), deqSel) =>
235      compEnq := Mux(enqCanTrans2Comp.get, enqEntry, Mux1H(deqSel, simpEntryTransVec.get))
236    }
237    compEntryEnqVec.zipWithIndex.foreach { case (compEntryEnq, compIdx) =>
238      val compEnqOH = finalCompTransSelVec.get.map(_(compIdx))
239      // shit Mux1H directly returns in(0) if the seq has only 1 elements
240      if (compEnqOH.size == 1)
241        compEntryEnq := Mux(compEnqOH.head, compEnqVec.get.head, 0.U.asTypeOf(compEnqVec.get.head))
242      else
243        compEntryEnq := Mux1H(compEnqOH, compEnqVec.get)
244    }
245
246    assert(PopCount(simpEntryEnqVec.map(_.valid)) <= params.numEnq.U, "the number of simpEntryEnq is more than numEnq\n")
247    assert(PopCount(compEntryEnqVec.map(_.valid)) <= params.numEnq.U, "the number of compEntryEnq is more than numEnq\n")
248  }
249
250  if(backendParams.debugEn) {
251    dontTouch(othersEntryEnqVec)
252  }
253
254  //issueRespVec
255  if (params.isVecMemIQ) {
256    // vector memory IQ
257    issueRespVec.zip(robIdxVec).zip(uopIdxVec.get).foreach { case ((issueResp, robIdx), uopIdx) =>
258      val hitRespsVec = VecInit(memEtyResps.map(x =>
259        x.valid && x.bits.robIdx === robIdx && x.bits.uopIdx.get === uopIdx
260      ).toSeq)
261      issueResp.valid := hitRespsVec.reduce(_ | _)
262      issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)
263    }
264  } else if (params.isMemAddrIQ) {
265    // scalar memory IQ
266    issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) =>
267      val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq)
268      issueResp.valid := hitRespsVec.reduce(_ | _)
269      issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)
270    }
271  }
272  else {
273    issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) =>
274      val Resp = resps(issueTimer)(deqPortIdx)
275      issueResp := Resp
276    }
277  }
278
279  //deq
280  val enqEntryOldest          = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
281  val simpEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
282  val compEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
283  val othersEntryOldest       = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
284  val enqEntryOldestCancel    = Wire(Vec(params.numDeq, Bool()))
285  val simpEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
286  val compEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
287  val othersEntryOldestCancel = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, Bool())))
288
289  io.enqEntryOldestSel.zipWithIndex.map { case (sel, deqIdx) =>
290    enqEntryOldest(deqIdx) := Mux1H(sel.bits, entries.take(EnqEntryNum))
291    enqEntryOldestCancel(deqIdx) := Mux1H(sel.bits, cancelBypassVec.take(EnqEntryNum))
292  }
293
294  if (params.isAllComp || params.isAllSimp) {
295    io.othersEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
296      othersEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum))
297      othersEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum))
298    }
299  }
300  else {
301    io.simpEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
302      simpEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).take(SimpEntryNum))
303      simpEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).take(SimpEntryNum))
304    }
305    io.compEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
306      compEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).takeRight(CompEntryNum))
307      compEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).takeRight(CompEntryNum))
308    }
309  }
310
311  if (params.deqFuSame) {
312    val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
313    val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool()))
314    val subDeqPolicyCancelBypassVec = Wire(Vec(params.numDeq, Bool()))
315
316    subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U
317    subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U
318
319    if (params.isAllComp || params.isAllSimp) {
320      subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries)
321      subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
322      subDeqPolicyCancelBypassVec(0) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
323      subDeqPolicyCancelBypassVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
324
325      io.deqEntry(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldest.get(0), subDeqPolicyEntryVec(1))
326      io.deqEntry(1) := subDeqPolicyEntryVec(0)
327      io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1))
328      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
329    }
330    else {
331      subDeqPolicyEntryVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
332      subDeqPolicyEntryVec(1) := PriorityMux(io.subDeqRequest.get(0), entries)
333      subDeqPolicyCancelBypassVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
334      subDeqPolicyCancelBypassVec(1) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
335
336      io.deqEntry(0) := Mux(io.compEntryOldestSel.get(0).valid,
337                            compEntryOldest.get(0),
338                            Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldest.get(0), subDeqPolicyEntryVec(1)))
339      io.deqEntry(1) := subDeqPolicyEntryVec(0)
340      io.cancelDeqVec(0) := Mux(io.compEntryOldestSel.get(0).valid,
341                                compEntryOldestCancel.get(0),
342                                Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1)))
343      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
344    }
345
346    when (subDeqPolicyValidVec(0)) {
347      assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n")
348    }
349    when (subDeqPolicyValidVec(1)) {
350      assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n")
351    }
352  }
353  else {
354    if (params.isAllComp || params.isAllSimp) {
355      io.othersEntryOldestSel.get.zipWithIndex.foreach { case (sel, i) =>
356        io.deqEntry(i)     := Mux(sel.valid, othersEntryOldest.get(i), enqEntryOldest(i))
357        io.cancelDeqVec(i) := Mux(sel.valid, othersEntryOldestCancel.get(i), enqEntryOldestCancel(i))
358      }
359    }
360    else {
361      io.compEntryOldestSel.get.zip(io.simpEntryOldestSel.get).zipWithIndex.foreach { case ((compSel, simpSel), i) =>
362        io.deqEntry(i)     := Mux(compSel.valid,
363                                  compEntryOldest.get(i),
364                                  Mux(simpSel.valid, simpEntryOldest.get(i), enqEntryOldest(i)))
365        io.cancelDeqVec(i) := Mux(compSel.valid,
366                                  compEntryOldestCancel.get(i),
367                                  Mux(simpSel.valid, simpEntryOldestCancel.get(i), enqEntryOldestCancel(i)))
368      }
369    }
370  }
371
372  if (params.hasIQWakeUp) {
373    cancelBypassVec.zip(srcWakeUpL1ExuOHVec.get).zip(srcTimerVec.get).zip(srcLoadDependencyVec).foreach{ case (((cancelBypass: Bool, l1ExuOH: Vec[Vec[Bool]]), srcTimer: Vec[UInt]), srcLoadDependency: Vec[Vec[UInt]]) =>
374      val cancelByOg0 = l1ExuOH.zip(srcTimer).map {
375        case(exuOH, srcTimer) =>
376          (exuOH.asUInt & io.og0Cancel.asUInt).orR && srcTimer === 1.U
377      }.reduce(_ | _)
378      val cancelByLd = srcLoadDependency.map(x => LoadShouldCancel(Some(x), io.ldCancel)).reduce(_ | _)
379      cancelBypass := cancelByLd
380    }
381  } else {
382    cancelBypassVec.zip(srcLoadDependencyVec).foreach { case (cancelBypass, srcLoadDependency) =>
383      val cancelByLd = srcLoadDependency.map(x => LoadShouldCancel(Some(x), io.ldCancel)).reduce(_ | _)
384      cancelBypass := cancelByLd
385    }
386  }
387
388  io.valid                          := validVec.asUInt
389  io.canIssue                       := canIssueVec.asUInt
390  io.fuType                         := fuTypeVec
391  io.dataSources                    := dataSourceVec
392  io.srcWakeUpL1ExuOH.foreach(_     := srcWakeUpL1ExuOHVec.get.map(x => VecInit(x.map(_.asUInt))))
393  io.srcTimer.foreach(_             := srcTimerVec.get)
394  io.loadDependency                 := loadDependencyVec
395  io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) =>
396    isFirstIssue                    := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec)
397  }
398  io.simpEntryEnqSelVec.foreach(_   := finalSimpTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(SimpEntryNum, x._2.valid)))
399  io.compEntryEnqSelVec.foreach(_   := finalCompTransSelVec.get.zip(compEnqVec.get).map(x => x._1 & Fill(CompEntryNum, x._2.valid)))
400  io.othersEntryEnqSelVec.foreach(_ := finalOthersTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(OthersEntryNum, x._2.valid)))
401  io.robIdx.foreach(_               := robIdxVec)
402  io.uopIdx.foreach(_               := uopIdxVec.get)
403  io.cancel.foreach(_               := cancelVec.get)               //for debug
404
405
406  def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = {
407    in.flush                    := io.flush
408    in.wakeUpFromWB             := io.wakeUpFromWB
409    in.wakeUpFromIQ             := io.wakeUpFromIQ
410    in.og0Cancel                := io.og0Cancel
411    in.og1Cancel                := io.og1Cancel
412    in.ldCancel                 := io.ldCancel
413    in.deqSel                   := deqSelVec(entryIdx)
414    in.deqPortIdxWrite          := deqPortIdxWriteVec(entryIdx)
415    in.issueResp                := issueRespVec(entryIdx)
416    if (params.isVecMemIQ) {
417      in.fromLsq.get.sqDeqPtr   := io.vecMemIn.get.sqDeqPtr
418      in.fromLsq.get.lqDeqPtr   := io.vecMemIn.get.lqDeqPtr
419    }
420    validVec(entryIdx)          := out.valid
421    canIssueVec(entryIdx)       := out.canIssue
422    fuTypeVec(entryIdx)         := out.fuType
423    robIdxVec(entryIdx)         := out.robIdx
424    dataSourceVec(entryIdx)     := out.dataSource
425    isFirstIssueVec(entryIdx)   := out.isFirstIssue
426    entries(entryIdx)           := out.entry
427    deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead
428    issueTimerVec(entryIdx)     := out.issueTimerRead
429    srcLoadDependencyVec(entryIdx)          := out.srcLoadDependency
430    loadDependencyVec(entryIdx)             := out.entry.bits.status.mergedLoadDependency
431    if (params.hasIQWakeUp) {
432      srcWakeUpL1ExuOHVec.get(entryIdx)       := out.srcWakeUpL1ExuOH.get
433      srcTimerVec.get(entryIdx)               := out.srcTimer.get
434      cancelVec.get(entryIdx)                 := out.cancel.get
435    }
436    if (params.isVecMemIQ) {
437      uopIdxVec.get(entryIdx)       := out.uopIdx.get
438    }
439    entryInValidVec(entryIdx)       := out.entryInValid
440    entryOutDeqValidVec(entryIdx)   := out.entryOutDeqValid
441    entryOutTransValidVec(entryIdx) := out.entryOutTransValid
442  }
443
444  // entries perf counter
445  // enq
446  for (i <- 0 until params.numEnq) {
447    XSPerfAccumulate(s"enqEntry_${i}_in_cnt", entryInValidVec(i))
448    XSPerfAccumulate(s"enqEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i))
449    XSPerfAccumulate(s"enqEntry_${i}_out_trans_cnt", entryOutTransValidVec(i))
450  }
451  // simple
452  for (i <- 0 until params.numSimp) {
453    XSPerfAccumulate(s"simpEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq))
454    XSPerfAccumulate(s"simpEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq))
455    XSPerfAccumulate(s"simpEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq))
456  }
457  // complex
458  for (i <- 0 until params.numComp) {
459    XSPerfAccumulate(s"compEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq + params.numSimp))
460    XSPerfAccumulate(s"compEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq + params.numSimp))
461    XSPerfAccumulate(s"compEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq + params.numSimp))
462  }
463  // total
464  XSPerfAccumulate(s"enqEntry_all_in_cnt", PopCount(entryInValidVec.take(params.numEnq)))
465  XSPerfAccumulate(s"enqEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.take(params.numEnq)))
466  XSPerfAccumulate(s"enqEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.take(params.numEnq)))
467
468  XSPerfAccumulate(s"othersEntry_all_in_cnt", PopCount(entryInValidVec.drop(params.numEnq)))
469  XSPerfAccumulate(s"othersEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.drop(params.numEnq)))
470  XSPerfAccumulate(s"othersEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.drop(params.numEnq)))
471
472  io.vecLdIn.foreach(dontTouch(_))
473}
474
475class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
476  val flush               = Flipped(ValidIO(new Redirect))
477  //enq
478  val enq                 = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
479  val og0Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
480  val og1Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
481  //deq sel
482  val deqReady            = Vec(params.numDeq, Input(Bool()))
483  val deqSelOH            = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W))))
484  val enqEntryOldestSel   = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W))))
485  val simpEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numSimp.W)))))
486  val compEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numComp.W)))))
487  val othersEntryOldestSel= OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W)))))
488  val subDeqRequest       = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
489  val subDeqSelOH         = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
490  // wakeup
491  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
492  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
493  val og0Cancel           = Input(ExuOH(backendParams.numExu))
494  val og1Cancel           = Input(ExuOH(backendParams.numExu))
495  val ldCancel            = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
496  //entries status
497  val valid               = Output(UInt(params.numEntries.W))
498  val canIssue            = Output(UInt(params.numEntries.W))
499  val fuType              = Vec(params.numEntries, Output(FuType()))
500  val dataSources         = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource())))
501  val loadDependency      = Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(3.W)))
502  val srcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuOH()))))
503  val srcTimer            = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(UInt(3.W)))))
504  //deq status
505  val isFirstIssue        = Vec(params.numDeq, Output(Bool()))
506  val deqEntry            = Vec(params.numDeq, ValidIO(new EntryBundle))
507  val cancelDeqVec        = Vec(params.numDeq, Output(Bool()))
508
509  // load/hybird only
510  val fromLoad = OptionWrapper(params.isLdAddrIQ || params.isHyAddrIQ, new Bundle {
511    val finalIssueResp    = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
512    val memAddrIssueResp  = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
513  })
514  // mem only
515  val fromMem = OptionWrapper(params.isMemAddrIQ, new Bundle {
516    val slowResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
517    val fastResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
518  })
519  // vec mem only
520  val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle {
521    val sqDeqPtr          = Input(new SqPtr)
522    val lqDeqPtr          = Input(new LqPtr)
523  })
524  val vecLdIn = OptionWrapper(params.isVecLduIQ, new Bundle {
525    val resp              = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
526  })
527  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
528  val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx())))
529
530  // trans
531  val simpEntryDeqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Input(UInt(params.numSimp.W))))
532  val simpEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numSimp.W))))
533  val compEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numComp.W))))
534  val othersEntryEnqSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numEnq, Output(UInt((params.numEntries - params.numEnq).W))))
535
536  // debug
537  val cancel              = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool())))
538
539  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
540}
541