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