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