xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision 99ce5576f0ecce1b5045b7bc0dbbb2debd934fbb)
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.backend.issue.EntryBundles._
17import xiangshan.mem.{LqPtr, SqPtr}
18import xiangshan.mem.Bundles.MemWaitUpdateReqBundle
19
20class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
21  override def desiredName: String = params.getEntryName
22
23  require(params.numEnq <= 2, "number of enq should be no more than 2")
24
25  private val EnqEntryNum         = params.numEnq
26  private val OthersEntryNum      = params.numEntries - params.numEnq
27  private val SimpEntryNum        = params.numSimp
28  private val CompEntryNum        = params.numComp
29  val io = IO(new EntriesIO)
30
31  // only memAddrIQ use it
32  val memEtyResps: Seq[ValidIO[EntryDeqRespBundle]] = {
33    val resps =
34      if (params.isLdAddrIQ && !params.isStAddrIQ)                                                    //LDU
35        Seq(io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp)
36      else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ)                           //HYU
37        Seq(io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp, io.fromMem.get.fastResp, io.fromMem.get.slowResp)
38      else if (params.isStAddrIQ)                                                                     //STU
39        Seq(io.fromMem.get.slowResp)
40      else if (params.isVecLduIQ && params.isVecStuIQ) // Vector store IQ need no vecLdIn.resp, but for now vector store share the vector load IQ
41        Seq(io.vecLdIn.get.resp, io.fromMem.get.slowResp, io.vecLdIn.get.finalIssueResp)
42      else Seq()
43    if (params.isMemAddrIQ) {
44      println(s"[${this.desiredName}] resp: {" +
45        s"og0Resp: ${resps.contains(io.og0Resp)}, " +
46        s"og1Resp: ${resps.contains(io.og1Resp)}, " +
47        s"finalResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.finalIssueResp)}, " +
48        s"loadBorderResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.memAddrIssueResp)}, " +
49        s"memFastResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.fastResp)}, " +
50        s"memSlowResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.slowResp)}, " +
51        s"vecLoadBorderResp: ${io.vecLdIn.nonEmpty && resps.contains(io.vecLdIn.get.resp)}, " +
52        s"}"
53      )
54    }
55    resps.flatten
56  }
57
58  val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = Wire(Vec(4, chiselTypeOf(io.og0Resp)))
59
60  if (params.needOg2Resp)
61    resps := Seq(io.og0Resp, io.og1Resp, io.og2Resp.get, WireDefault(0.U.asTypeOf(io.og0Resp)))
62  else
63    resps := Seq(io.og0Resp, io.og1Resp, WireDefault(0.U.asTypeOf(io.og0Resp)), WireDefault(0.U.asTypeOf(io.og0Resp)))
64
65
66
67  //Module
68  val enqEntries          = Seq.fill(EnqEntryNum)(Module(EnqEntry(isComp = true)(p, params)))
69  val othersEntriesSimp   = Seq.fill(SimpEntryNum)(Module(OthersEntry(isComp = false)(p, params)))
70  val othersEntriesComp   = Seq.fill(CompEntryNum)(Module(OthersEntry(isComp = true)(p, params)))
71  val othersEntries       = othersEntriesSimp ++ othersEntriesComp
72  val othersTransPolicy   = OptionWrapper(params.isAllComp || params.isAllSimp, Module(new EnqPolicy))
73  val simpTransPolicy     = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy))
74  val compTransPolicy     = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy))
75
76  //Wire
77  //entries status
78  val entries             = Wire(Vec(params.numEntries, ValidIO(new EntryBundle)))
79  val robIdxVec           = Wire(Vec(params.numEntries, new RobPtr))
80  val validVec            = Wire(Vec(params.numEntries, Bool()))
81  val issuedVec           = Wire(Vec(params.numEntries, Bool()))
82  val validForTrans       = VecInit(validVec.zip(issuedVec).map(x => x._1 && !x._2))
83  val canIssueVec         = Wire(Vec(params.numEntries, Bool()))
84  val fuTypeVec           = Wire(Vec(params.numEntries, FuType()))
85  val isFirstIssueVec     = Wire(Vec(params.numEntries, Bool()))
86  val issueTimerVec       = Wire(Vec(params.numEntries, UInt(2.W)))
87  val sqIdxVec            = OptionWrapper(params.needFeedBackSqIdx || params.needFeedBackLqIdx, Wire(Vec(params.numEntries, new SqPtr())))
88  val lqIdxVec            = OptionWrapper(params.needFeedBackSqIdx || params.needFeedBackLqIdx, Wire(Vec(params.numEntries, new LqPtr())))
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 exuSourceVec        = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuSource()))))
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 := io.wakeUpFromWBDelayed
140    enqEntry.io.enqDelayIn1.wakeUpFromIQ := io.wakeUpFromIQDelayed
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)
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, 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 && validForTrans(0)
184    othersTransSelVec.get(0).bits  := othersTransPolicy.get.io.enqSelOHVec(0).bits
185    if (params.numEnq == 2) {
186      othersTransSelVec.get(1).valid := Mux(!validForTrans(0), othersTransPolicy.get.io.enqSelOHVec(0).valid, othersTransPolicy.get.io.enqSelOHVec(1).valid) && validForTrans(1)
187      othersTransSelVec.get(1).bits  := Mux(!validForTrans(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 && validForTrans(0)
222    simpTransSelVec.get(0).bits  := simpTransPolicy.get.io.enqSelOHVec(0).bits
223    compTransSelVec.get(0).valid := compTransPolicy.get.io.enqSelOHVec(0).valid && validForTrans(0)
224    compTransSelVec.get(0).bits  := compTransPolicy.get.io.enqSelOHVec(0).bits
225    if (params.numEnq == 2) {
226      simpTransSelVec.get(1).valid := Mux(!validForTrans(0), simpTransPolicy.get.io.enqSelOHVec(0).valid, simpTransPolicy.get.io.enqSelOHVec(1).valid) && validForTrans(1)
227      simpTransSelVec.get(1).bits  := Mux(!validForTrans(0), simpTransPolicy.get.io.enqSelOHVec(0).bits,  simpTransPolicy.get.io.enqSelOHVec(1).bits)
228      compTransSelVec.get(1).valid := Mux(!validForTrans(0), compTransPolicy.get.io.enqSelOHVec(0).valid, compTransPolicy.get.io.enqSelOHVec(1).valid) && validForTrans(1)
229      compTransSelVec.get(1).bits  := Mux(!validForTrans(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.needFeedBackSqIdx || params.needFeedBackLqIdx) {
272    issueRespVec.lazyZip(sqIdxVec.get.zip(lqIdxVec.get)).lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, (sqIdx, lqIdx), (issueTimer, deqPortIdx)) =>
273      val respInDatapath = if (!params.isVecMemIQ) resps(issueTimer(0))(deqPortIdx)
274                           else resps(issueTimer)(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 := (if (!params.isVecMemIQ) Mux(issueTimer(1), respAfterDatapath, respInDatapath)
285                    else Mux(issueTimer === "b11".U, respAfterDatapath, respInDatapath))
286    }
287  }
288  else {
289    issueRespVec.lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, (issueTimer, deqPortIdx)) =>
290      val Resp = resps(issueTimer)(deqPortIdx)
291      issueResp := Resp
292    }
293  }
294
295  //deq
296  val enqEntryOldest          = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
297  val simpEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
298  val compEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
299  val othersEntryOldest       = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
300  val enqEntryOldestCancel    = Wire(Vec(params.numDeq, Bool()))
301  val simpEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
302  val compEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
303  val othersEntryOldestCancel = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, Bool())))
304
305  io.enqEntryOldestSel.zipWithIndex.map { case (sel, deqIdx) =>
306    enqEntryOldest(deqIdx) := Mux1H(sel.bits, entries.take(EnqEntryNum))
307    enqEntryOldestCancel(deqIdx) := Mux1H(sel.bits, cancelBypassVec.take(EnqEntryNum))
308  }
309
310  if (params.isAllComp || params.isAllSimp) {
311    io.othersEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
312      othersEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum))
313      othersEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum))
314    }
315  }
316  else {
317    io.simpEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
318      simpEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).take(SimpEntryNum))
319      simpEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).take(SimpEntryNum))
320    }
321    io.compEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
322      compEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).takeRight(CompEntryNum))
323      compEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).takeRight(CompEntryNum))
324    }
325  }
326
327  if (params.deqFuSame) {
328    val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
329    val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool()))
330    val subDeqPolicyCancelBypassVec = Wire(Vec(params.numDeq, Bool()))
331
332    subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U
333    subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U
334
335    if (params.isAllComp || params.isAllSimp) {
336      subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries)
337      subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
338      subDeqPolicyCancelBypassVec(0) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
339      subDeqPolicyCancelBypassVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
340
341      io.deqEntry(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldest.get(0), subDeqPolicyEntryVec(1))
342      io.deqEntry(1) := subDeqPolicyEntryVec(0)
343      io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1))
344      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
345    }
346    else {
347      subDeqPolicyEntryVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
348      subDeqPolicyEntryVec(1) := PriorityMux(io.subDeqRequest.get(0), entries)
349      subDeqPolicyCancelBypassVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
350      subDeqPolicyCancelBypassVec(1) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
351
352      io.deqEntry(0) := Mux(io.compEntryOldestSel.get(0).valid,
353                            compEntryOldest.get(0),
354                            Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldest.get(0), subDeqPolicyEntryVec(1)))
355      io.deqEntry(1) := subDeqPolicyEntryVec(0)
356      io.cancelDeqVec(0) := Mux(io.compEntryOldestSel.get(0).valid,
357                                compEntryOldestCancel.get(0),
358                                Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1)))
359      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
360    }
361
362    when (subDeqPolicyValidVec(0)) {
363      assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n")
364    }
365    when (subDeqPolicyValidVec(1)) {
366      assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n")
367    }
368  }
369  else {
370    if (params.isAllComp || params.isAllSimp) {
371      io.othersEntryOldestSel.get.zipWithIndex.foreach { case (sel, i) =>
372        io.deqEntry(i)     := Mux(sel.valid, othersEntryOldest.get(i), enqEntryOldest(i))
373        io.cancelDeqVec(i) := Mux(sel.valid, othersEntryOldestCancel.get(i), enqEntryOldestCancel(i))
374      }
375    }
376    else {
377      io.compEntryOldestSel.get.zip(io.simpEntryOldestSel.get).zipWithIndex.foreach { case ((compSel, simpSel), i) =>
378        io.deqEntry(i)     := Mux(compSel.valid,
379                                  compEntryOldest.get(i),
380                                  Mux(simpSel.valid, simpEntryOldest.get(i), enqEntryOldest(i)))
381        io.cancelDeqVec(i) := Mux(compSel.valid,
382                                  compEntryOldestCancel.get(i),
383                                  Mux(simpSel.valid, simpEntryOldestCancel.get(i), enqEntryOldestCancel(i)))
384      }
385    }
386  }
387
388  io.valid                          := validVec.asUInt
389  io.issued                         := issuedVec.asUInt
390  io.canIssue                       := canIssueVec.asUInt
391  io.fuType                         := fuTypeVec
392  io.dataSources                    := dataSourceVec
393  io.exuSources.foreach(_           := exuSourceVec.get)
394  io.loadDependency                 := loadDependencyVec
395  io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) =>
396    isFirstIssue                    := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec)
397  }
398  io.simpEntryEnqSelVec.foreach(_   := finalSimpTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(SimpEntryNum, x._2.valid)))
399  io.compEntryEnqSelVec.foreach(_   := finalCompTransSelVec.get.zip(compEnqVec.get).map(x => x._1 & Fill(CompEntryNum, x._2.valid)))
400  io.othersEntryEnqSelVec.foreach(_ := finalOthersTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(OthersEntryNum, x._2.valid)))
401  io.robIdx.foreach(_               := robIdxVec)
402
403
404  def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = {
405    in.flush                    := io.flush
406    in.wakeUpFromWB             := io.wakeUpFromWB
407    in.wakeUpFromIQ             := io.wakeUpFromIQ
408    in.vlFromIntIsZero          := io.vlFromIntIsZero
409    in.vlFromIntIsVlmax         := io.vlFromIntIsVlmax
410    in.vlFromVfIsZero           := io.vlFromVfIsZero
411    in.vlFromVfIsVlmax          := io.vlFromVfIsVlmax
412    in.og0Cancel                := io.og0Cancel
413    in.og1Cancel                := io.og1Cancel
414    in.ldCancel                 := io.ldCancel
415    in.deqSel                   := deqSelVec(entryIdx)
416    in.deqPortIdxWrite          := deqPortIdxWriteVec(entryIdx)
417    in.issueResp                := issueRespVec(entryIdx)
418    if (params.isVecMemIQ) {
419      in.fromLsq.get.sqDeqPtr   := io.vecMemIn.get.sqDeqPtr
420      in.fromLsq.get.lqDeqPtr   := io.vecMemIn.get.lqDeqPtr
421    }
422    validVec(entryIdx)          := out.valid
423    issuedVec(entryIdx)         := out.issued
424    canIssueVec(entryIdx)       := out.canIssue
425    fuTypeVec(entryIdx)         := out.fuType
426    robIdxVec(entryIdx)         := out.robIdx
427    dataSourceVec(entryIdx)     := out.dataSources
428    isFirstIssueVec(entryIdx)   := out.isFirstIssue
429    entries(entryIdx)           := out.entry
430    deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead
431    issueTimerVec(entryIdx)     := out.issueTimerRead
432    loadDependencyVec(entryIdx) := out.entry.bits.status.mergedLoadDependency
433    cancelBypassVec(entryIdx)   := out.cancelBypass
434    exuSourceVec.foreach(_(entryIdx) := out.exuSources.get)
435    if (params.needFeedBackSqIdx || params.needFeedBackLqIdx) {
436      sqIdxVec.get(entryIdx) := out.entry.bits.payload.sqIdx
437      lqIdxVec.get(entryIdx) := out.entry.bits.payload.lqIdx
438    }
439    entryInValidVec(entryIdx)       := out.entryInValid
440    entryOutDeqValidVec(entryIdx)   := out.entryOutDeqValid
441    entryOutTransValidVec(entryIdx) := out.entryOutTransValid
442    perfWakeupByWBVec(entryIdx)     := out.perfWakeupByWB
443    if (params.hasIQWakeUp) {
444      perfLdCancelVec.get(entryIdx)   := out.perfLdCancel.get
445      perfOg0CancelVec.get(entryIdx)  := out.perfOg0Cancel.get
446      perfWakeupByIQVec.get(entryIdx) := out.perfWakeupByIQ.get
447    }
448  }
449
450  io.vecLdIn.foreach(dontTouch(_))
451
452  // entries perf counter
453  // enq
454  for (i <- 0 until params.numEnq) {
455    XSPerfAccumulate(s"enqEntry_${i}_in_cnt", entryInValidVec(i))
456    XSPerfAccumulate(s"enqEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i))
457    XSPerfAccumulate(s"enqEntry_${i}_out_trans_cnt", entryOutTransValidVec(i))
458  }
459  // simple
460  for (i <- 0 until params.numSimp) {
461    XSPerfAccumulate(s"simpEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq))
462    XSPerfAccumulate(s"simpEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq))
463    XSPerfAccumulate(s"simpEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq))
464  }
465  // complex
466  for (i <- 0 until params.numComp) {
467    XSPerfAccumulate(s"compEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq + params.numSimp))
468    XSPerfAccumulate(s"compEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq + params.numSimp))
469    XSPerfAccumulate(s"compEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq + params.numSimp))
470  }
471  // total
472  XSPerfAccumulate(s"enqEntry_all_in_cnt", PopCount(entryInValidVec.take(params.numEnq)))
473  XSPerfAccumulate(s"enqEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.take(params.numEnq)))
474  XSPerfAccumulate(s"enqEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.take(params.numEnq)))
475  for (srcIdx <- 0 until params.numRegSrc) {
476    XSPerfAccumulate(s"enqEntry_all_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.take(params.numEnq).map(_(srcIdx))))
477    if (params.hasIQWakeUp) {
478      XSPerfAccumulate(s"enqEntry_all_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.take(params.numEnq).map(_(srcIdx))))
479      XSPerfAccumulate(s"enqEntry_all_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.take(params.numEnq).map(_(srcIdx))))
480      for (iqIdx <- 0 until params.numWakeupFromIQ) {
481        XSPerfAccumulate(s"enqEntry_all_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.take(params.numEnq).map(_(srcIdx)(iqIdx))))
482      }
483    }
484  }
485
486  XSPerfAccumulate(s"othersEntry_all_in_cnt", PopCount(entryInValidVec.drop(params.numEnq)))
487  XSPerfAccumulate(s"othersEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.drop(params.numEnq)))
488  XSPerfAccumulate(s"othersEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.drop(params.numEnq)))
489
490  for (srcIdx <- 0 until params.numRegSrc) {
491    XSPerfAccumulate(s"othersEntry_all_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.drop(params.numEnq).map(_(srcIdx))))
492    if (params.hasIQWakeUp) {
493      XSPerfAccumulate(s"othersEntry_all_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.drop(params.numEnq).map(_(srcIdx))))
494      XSPerfAccumulate(s"othersEntry_all_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.drop(params.numEnq).map(_(srcIdx))))
495      for (iqIdx <- 0 until params.numWakeupFromIQ) {
496        XSPerfAccumulate(s"othersEntry_all_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.drop(params.numEnq).map(_(srcIdx)(iqIdx))))
497      }
498    }
499  }
500
501  for (t <- FuType.functionNameMap.keys) {
502    val fuName = FuType.functionNameMap(t)
503    if (params.getFuCfgs.map(_.fuType == t).reduce(_ | _) && params.getFuCfgs.size > 1) {
504      for (srcIdx <- 0 until params.numRegSrc) {
505        XSPerfAccumulate(s"allEntry_futype_${fuName}_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) }))
506        if (params.hasIQWakeUp) {
507          XSPerfAccumulate(s"allEntry_futype_${fuName}_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) }))
508          XSPerfAccumulate(s"allEntry_futype_${fuName}_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) }))
509          for (iqIdx <- 0 until params.numWakeupFromIQ) {
510            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) }))
511          }
512        }
513      }
514    }
515  }
516}
517
518class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
519  val flush               = Flipped(ValidIO(new Redirect))
520  //enq
521  val enq                 = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
522  val og0Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
523  val og1Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
524  val og2Resp             = OptionWrapper(params.needOg2Resp, Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))))
525  //deq sel
526  val deqReady            = Vec(params.numDeq, Input(Bool()))
527  val deqSelOH            = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W))))
528  val enqEntryOldestSel   = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W))))
529  val simpEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numSimp.W)))))
530  val compEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numComp.W)))))
531  val othersEntryOldestSel= OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W)))))
532  val subDeqRequest       = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
533  val subDeqSelOH         = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
534  // wakeup
535  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
536  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
537  val wakeUpFromWBDelayed: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
538  val wakeUpFromIQDelayed: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
539  val vlFromIntIsZero     = Input(Bool())
540  val vlFromIntIsVlmax    = Input(Bool())
541  val vlFromVfIsZero      = Input(Bool())
542  val vlFromVfIsVlmax     = Input(Bool())
543  val og0Cancel           = Input(ExuVec())
544  val og1Cancel           = Input(ExuVec())
545  val ldCancel            = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
546  //entries status
547  val valid               = Output(UInt(params.numEntries.W))
548  val issued              = Output(UInt(params.numEntries.W))
549  val canIssue            = Output(UInt(params.numEntries.W))
550  val fuType              = Vec(params.numEntries, Output(FuType()))
551  val dataSources         = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource())))
552  val loadDependency      = Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W)))
553  val exuSources          = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuSource()))))
554  //deq status
555  val isFirstIssue        = Vec(params.numDeq, Output(Bool()))
556  val deqEntry            = Vec(params.numDeq, ValidIO(new EntryBundle))
557  val cancelDeqVec        = Vec(params.numDeq, Output(Bool()))
558
559  // load/hybird only
560  val fromLoad = OptionWrapper(params.isLdAddrIQ || params.isHyAddrIQ, new Bundle {
561    val finalIssueResp    = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
562    val memAddrIssueResp  = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
563  })
564  // mem only
565  val fromMem = OptionWrapper(params.isMemAddrIQ, new Bundle {
566    val slowResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
567    val fastResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
568  })
569  // vec mem only
570  val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle {
571    val sqDeqPtr          = Input(new SqPtr)
572    val lqDeqPtr          = Input(new LqPtr)
573  })
574  val vecLdIn = OptionWrapper(params.isVecLduIQ, new Bundle {
575    val finalIssueResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
576    val resp              = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
577  })
578  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
579
580  // trans
581  val simpEntryDeqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Input(UInt(params.numSimp.W))))
582  val simpEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numSimp.W))))
583  val compEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numComp.W))))
584  val othersEntryEnqSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numEnq, Output(UInt((params.numEntries - params.numEnq).W))))
585
586  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
587}
588