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