xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision b6279fc62b995344eb1f409e6a3b794762f82d5e)
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.vlIsZero                 := io.vlIsZero
413    in.vlIsVlmax                := io.vlIsVlmax
414    in.og0Cancel                := io.og0Cancel
415    in.og1Cancel                := io.og1Cancel
416    in.ldCancel                 := io.ldCancel
417    in.deqSel                   := deqSelVec(entryIdx)
418    in.deqPortIdxWrite          := deqPortIdxWriteVec(entryIdx)
419    in.issueResp                := issueRespVec(entryIdx)
420    if (params.isVecMemIQ) {
421      in.fromLsq.get.sqDeqPtr   := io.vecMemIn.get.sqDeqPtr
422      in.fromLsq.get.lqDeqPtr   := io.vecMemIn.get.lqDeqPtr
423    }
424    validVec(entryIdx)          := out.valid
425    canIssueVec(entryIdx)       := out.canIssue
426    fuTypeVec(entryIdx)         := out.fuType
427    robIdxVec(entryIdx)         := out.robIdx
428    dataSourceVec(entryIdx)     := out.dataSource
429    isFirstIssueVec(entryIdx)   := out.isFirstIssue
430    entries(entryIdx)           := out.entry
431    deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead
432    issueTimerVec(entryIdx)     := out.issueTimerRead
433    srcLoadDependencyVec(entryIdx)          := out.srcLoadDependency
434    loadDependencyVec(entryIdx)             := out.entry.bits.status.mergedLoadDependency
435    if (params.hasIQWakeUp) {
436      srcWakeUpL1ExuOHVec.get(entryIdx)       := out.srcWakeUpL1ExuOH.get
437      srcTimerVec.get(entryIdx)               := out.srcTimer.get
438      cancelVec.get(entryIdx)                 := out.cancel.get
439    }
440    if (params.isVecMemIQ) {
441      uopIdxVec.get(entryIdx)       := out.uopIdx.get
442    }
443    entryInValidVec(entryIdx)       := out.entryInValid
444    entryOutDeqValidVec(entryIdx)   := out.entryOutDeqValid
445    entryOutTransValidVec(entryIdx) := out.entryOutTransValid
446  }
447
448  // entries perf counter
449  // enq
450  for (i <- 0 until params.numEnq) {
451    XSPerfAccumulate(s"enqEntry_${i}_in_cnt", entryInValidVec(i))
452    XSPerfAccumulate(s"enqEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i))
453    XSPerfAccumulate(s"enqEntry_${i}_out_trans_cnt", entryOutTransValidVec(i))
454  }
455  // simple
456  for (i <- 0 until params.numSimp) {
457    XSPerfAccumulate(s"simpEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq))
458    XSPerfAccumulate(s"simpEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq))
459    XSPerfAccumulate(s"simpEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq))
460  }
461  // complex
462  for (i <- 0 until params.numComp) {
463    XSPerfAccumulate(s"compEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq + params.numSimp))
464    XSPerfAccumulate(s"compEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq + params.numSimp))
465    XSPerfAccumulate(s"compEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq + params.numSimp))
466  }
467  // total
468  XSPerfAccumulate(s"enqEntry_all_in_cnt", PopCount(entryInValidVec.take(params.numEnq)))
469  XSPerfAccumulate(s"enqEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.take(params.numEnq)))
470  XSPerfAccumulate(s"enqEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.take(params.numEnq)))
471
472  XSPerfAccumulate(s"othersEntry_all_in_cnt", PopCount(entryInValidVec.drop(params.numEnq)))
473  XSPerfAccumulate(s"othersEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.drop(params.numEnq)))
474  XSPerfAccumulate(s"othersEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.drop(params.numEnq)))
475
476  io.vecLdIn.foreach(dontTouch(_))
477}
478
479class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
480  val flush               = Flipped(ValidIO(new Redirect))
481  //enq
482  val enq                 = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
483  val og0Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
484  val og1Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
485  //deq sel
486  val deqReady            = Vec(params.numDeq, Input(Bool()))
487  val deqSelOH            = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W))))
488  val enqEntryOldestSel   = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W))))
489  val simpEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numSimp.W)))))
490  val compEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numComp.W)))))
491  val othersEntryOldestSel= OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W)))))
492  val subDeqRequest       = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
493  val subDeqSelOH         = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
494  // wakeup
495  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
496  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
497  val vlIsZero            = Input(Bool())
498  val vlIsVlmax           = Input(Bool())
499  val og0Cancel           = Input(ExuOH(backendParams.numExu))
500  val og1Cancel           = Input(ExuOH(backendParams.numExu))
501  val ldCancel            = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
502  //entries status
503  val valid               = Output(UInt(params.numEntries.W))
504  val canIssue            = Output(UInt(params.numEntries.W))
505  val fuType              = Vec(params.numEntries, Output(FuType()))
506  val dataSources         = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource())))
507  val loadDependency      = Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(3.W)))
508  val srcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuOH()))))
509  val srcTimer            = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(UInt(3.W)))))
510  //deq status
511  val isFirstIssue        = Vec(params.numDeq, Output(Bool()))
512  val deqEntry            = Vec(params.numDeq, ValidIO(new EntryBundle))
513  val cancelDeqVec        = Vec(params.numDeq, Output(Bool()))
514
515  // load/hybird only
516  val fromLoad = OptionWrapper(params.isLdAddrIQ || params.isHyAddrIQ, new Bundle {
517    val finalIssueResp    = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
518    val memAddrIssueResp  = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
519  })
520  // mem only
521  val fromMem = OptionWrapper(params.isMemAddrIQ, new Bundle {
522    val slowResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
523    val fastResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
524  })
525  // vec mem only
526  val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle {
527    val sqDeqPtr          = Input(new SqPtr)
528    val lqDeqPtr          = Input(new LqPtr)
529  })
530  val vecLdIn = OptionWrapper(params.isVecLduIQ, new Bundle {
531    val resp              = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
532  })
533  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
534  val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx())))
535
536  // trans
537  val simpEntryDeqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Input(UInt(params.numSimp.W))))
538  val simpEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numSimp.W))))
539  val compEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numComp.W))))
540  val othersEntryEnqSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numEnq, Output(UInt((params.numEntries - params.numEnq).W))))
541
542  // debug
543  val cancel              = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool())))
544
545  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
546}
547