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