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