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