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