xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision 1bc48dd1fa0af361fd194c65bad3b86349ec2903)
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.needOg2Resp)
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 := RegEnable(io.wakeUpFromWB, io.enq(entryIdx).valid)
143    enqEntry.io.enqDelayIn1.wakeUpFromIQ := RegEnable(io.wakeUpFromIQ, io.enq(entryIdx).valid)
144    enqEntry.io.enqDelayIn1.srcLoadDependency := RegEnable(VecInit(io.enq(entryIdx).bits.payload.srcLoadDependency.take(params.numRegSrc)), io.enq(entryIdx).valid)
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 = if (!params.isVecMemIQ) resps(issueTimer(0))(deqPortIdx)
277                           else resps(issueTimer)(deqPortIdx)
278      val respAfterDatapath = Wire(chiselTypeOf(respInDatapath))
279      val hitRespsVec = VecInit(memEtyResps.map(x =>
280        x.valid &&
281        (if (params.needFeedBackSqIdx) x.bits.sqIdx.get === sqIdx else true.B) &&
282        (if (params.needFeedBackLqIdx) x.bits.lqIdx.get === lqIdx else true.B)
283      ).toSeq)
284      respAfterDatapath.valid := hitRespsVec.reduce(_ | _)
285      respAfterDatapath.bits  := (if (memEtyResps.size == 1) memEtyResps.head.bits
286                                  else Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq))
287      issueResp := (if (!params.isVecMemIQ) Mux(issueTimer(1), respAfterDatapath, respInDatapath)
288                    else Mux(issueTimer === "b11".U, respAfterDatapath, respInDatapath))
289    }
290  }
291  else {
292    issueRespVec.lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, (issueTimer, deqPortIdx)) =>
293      val Resp = resps(issueTimer)(deqPortIdx)
294      issueResp := Resp
295    }
296  }
297
298  //deq
299  val enqEntryOldest          = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
300  val simpEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
301  val compEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
302  val othersEntryOldest       = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
303  val enqEntryOldestCancel    = Wire(Vec(params.numDeq, Bool()))
304  val simpEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
305  val compEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
306  val othersEntryOldestCancel = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, Bool())))
307
308  io.enqEntryOldestSel.zipWithIndex.map { case (sel, deqIdx) =>
309    enqEntryOldest(deqIdx) := Mux1H(sel.bits, entries.take(EnqEntryNum))
310    enqEntryOldestCancel(deqIdx) := Mux1H(sel.bits, cancelBypassVec.take(EnqEntryNum))
311  }
312
313  if (params.isAllComp || params.isAllSimp) {
314    io.othersEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
315      othersEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum))
316      othersEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum))
317    }
318  }
319  else {
320    io.simpEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
321      simpEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).take(SimpEntryNum))
322      simpEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).take(SimpEntryNum))
323    }
324    io.compEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
325      compEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).takeRight(CompEntryNum))
326      compEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).takeRight(CompEntryNum))
327    }
328  }
329
330  if (params.deqFuSame) {
331    val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
332    val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool()))
333    val subDeqPolicyCancelBypassVec = Wire(Vec(params.numDeq, Bool()))
334
335    subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U
336    subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U
337
338    if (params.isAllComp || params.isAllSimp) {
339      subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries)
340      subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
341      subDeqPolicyCancelBypassVec(0) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
342      subDeqPolicyCancelBypassVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
343
344      io.deqEntry(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldest.get(0), subDeqPolicyEntryVec(1))
345      io.deqEntry(1) := subDeqPolicyEntryVec(0)
346      io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1))
347      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
348    }
349    else {
350      subDeqPolicyEntryVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
351      subDeqPolicyEntryVec(1) := PriorityMux(io.subDeqRequest.get(0), entries)
352      subDeqPolicyCancelBypassVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
353      subDeqPolicyCancelBypassVec(1) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
354
355      io.deqEntry(0) := Mux(io.compEntryOldestSel.get(0).valid,
356                            compEntryOldest.get(0),
357                            Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldest.get(0), subDeqPolicyEntryVec(1)))
358      io.deqEntry(1) := subDeqPolicyEntryVec(0)
359      io.cancelDeqVec(0) := Mux(io.compEntryOldestSel.get(0).valid,
360                                compEntryOldestCancel.get(0),
361                                Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1)))
362      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
363    }
364
365    when (subDeqPolicyValidVec(0)) {
366      assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n")
367    }
368    when (subDeqPolicyValidVec(1)) {
369      assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n")
370    }
371  }
372  else {
373    if (params.isAllComp || params.isAllSimp) {
374      io.othersEntryOldestSel.get.zipWithIndex.foreach { case (sel, i) =>
375        io.deqEntry(i)     := Mux(sel.valid, othersEntryOldest.get(i), enqEntryOldest(i))
376        io.cancelDeqVec(i) := Mux(sel.valid, othersEntryOldestCancel.get(i), enqEntryOldestCancel(i))
377      }
378    }
379    else {
380      io.compEntryOldestSel.get.zip(io.simpEntryOldestSel.get).zipWithIndex.foreach { case ((compSel, simpSel), i) =>
381        io.deqEntry(i)     := Mux(compSel.valid,
382                                  compEntryOldest.get(i),
383                                  Mux(simpSel.valid, simpEntryOldest.get(i), enqEntryOldest(i)))
384        io.cancelDeqVec(i) := Mux(compSel.valid,
385                                  compEntryOldestCancel.get(i),
386                                  Mux(simpSel.valid, simpEntryOldestCancel.get(i), enqEntryOldestCancel(i)))
387      }
388    }
389  }
390
391  io.valid                          := validVec.asUInt
392  io.issued                         := issuedVec.asUInt
393  io.canIssue                       := canIssueVec.asUInt
394  io.fuType                         := fuTypeVec
395  io.dataSources                    := dataSourceVec
396  io.srcWakeUpL1ExuOH.foreach(_     := srcWakeUpL1ExuOHVec.get)
397  io.loadDependency                 := loadDependencyVec
398  io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) =>
399    isFirstIssue                    := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec)
400  }
401  io.simpEntryEnqSelVec.foreach(_   := finalSimpTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(SimpEntryNum, x._2.valid)))
402  io.compEntryEnqSelVec.foreach(_   := finalCompTransSelVec.get.zip(compEnqVec.get).map(x => x._1 & Fill(CompEntryNum, x._2.valid)))
403  io.othersEntryEnqSelVec.foreach(_ := finalOthersTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(OthersEntryNum, x._2.valid)))
404  io.robIdx.foreach(_               := robIdxVec)
405
406
407  def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = {
408    in.flush                    := io.flush
409    in.wakeUpFromWB             := io.wakeUpFromWB
410    in.wakeUpFromIQ             := io.wakeUpFromIQ
411    in.vlFromIntIsZero          := io.vlFromIntIsZero
412    in.vlFromIntIsVlmax         := io.vlFromIntIsVlmax
413    in.vlFromVfIsZero           := io.vlFromVfIsZero
414    in.vlFromVfIsVlmax          := io.vlFromVfIsVlmax
415    in.og0Cancel                := io.og0Cancel
416    in.og1Cancel                := io.og1Cancel
417    in.ldCancel                 := io.ldCancel
418    in.deqSel                   := deqSelVec(entryIdx)
419    in.deqPortIdxWrite          := deqPortIdxWriteVec(entryIdx)
420    in.issueResp                := issueRespVec(entryIdx)
421    if (params.isVecMemIQ) {
422      in.fromLsq.get.sqDeqPtr   := io.vecMemIn.get.sqDeqPtr
423      in.fromLsq.get.lqDeqPtr   := io.vecMemIn.get.lqDeqPtr
424    }
425    validVec(entryIdx)          := out.valid
426    issuedVec(entryIdx)         := out.issued
427    canIssueVec(entryIdx)       := out.canIssue
428    fuTypeVec(entryIdx)         := out.fuType
429    robIdxVec(entryIdx)         := out.robIdx
430    dataSourceVec(entryIdx)     := out.dataSource
431    isFirstIssueVec(entryIdx)   := out.isFirstIssue
432    entries(entryIdx)           := out.entry
433    deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead
434    issueTimerVec(entryIdx)     := out.issueTimerRead
435    loadDependencyVec(entryIdx) := out.entry.bits.status.mergedLoadDependency
436    cancelBypassVec(entryIdx)   := out.cancelBypass
437    if (params.hasIQWakeUp) {
438      srcWakeUpL1ExuOHVec.get(entryIdx)     := out.srcWakeUpL1ExuOH.get
439    }
440    if (params.needFeedBackSqIdx || params.needFeedBackLqIdx) {
441      sqIdxVec.get(entryIdx) := out.entry.bits.payload.sqIdx
442      lqIdxVec.get(entryIdx) := out.entry.bits.payload.lqIdx
443    }
444    entryInValidVec(entryIdx)       := out.entryInValid
445    entryOutDeqValidVec(entryIdx)   := out.entryOutDeqValid
446    entryOutTransValidVec(entryIdx) := out.entryOutTransValid
447    perfWakeupByWBVec(entryIdx)     := out.perfWakeupByWB
448    if (params.hasIQWakeUp) {
449      perfLdCancelVec.get(entryIdx)   := out.perfLdCancel.get
450      perfOg0CancelVec.get(entryIdx)  := out.perfOg0Cancel.get
451      perfWakeupByIQVec.get(entryIdx) := out.perfWakeupByIQ.get
452    }
453  }
454
455  io.vecLdIn.foreach(dontTouch(_))
456
457  // entries perf counter
458  // enq
459  for (i <- 0 until params.numEnq) {
460    XSPerfAccumulate(s"enqEntry_${i}_in_cnt", entryInValidVec(i))
461    XSPerfAccumulate(s"enqEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i))
462    XSPerfAccumulate(s"enqEntry_${i}_out_trans_cnt", entryOutTransValidVec(i))
463  }
464  // simple
465  for (i <- 0 until params.numSimp) {
466    XSPerfAccumulate(s"simpEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq))
467    XSPerfAccumulate(s"simpEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq))
468    XSPerfAccumulate(s"simpEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq))
469  }
470  // complex
471  for (i <- 0 until params.numComp) {
472    XSPerfAccumulate(s"compEntry_${i}_in_cnt", entryInValidVec(i + params.numEnq + params.numSimp))
473    XSPerfAccumulate(s"compEntry_${i}_out_deq_cnt", entryOutDeqValidVec(i + params.numEnq + params.numSimp))
474    XSPerfAccumulate(s"compEntry_${i}_out_trans_cnt", entryOutTransValidVec(i + params.numEnq + params.numSimp))
475  }
476  // total
477  XSPerfAccumulate(s"enqEntry_all_in_cnt", PopCount(entryInValidVec.take(params.numEnq)))
478  XSPerfAccumulate(s"enqEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.take(params.numEnq)))
479  XSPerfAccumulate(s"enqEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.take(params.numEnq)))
480  for (srcIdx <- 0 until params.numRegSrc) {
481    XSPerfAccumulate(s"enqEntry_all_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.take(params.numEnq).map(_(srcIdx))))
482    if (params.hasIQWakeUp) {
483      XSPerfAccumulate(s"enqEntry_all_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.take(params.numEnq).map(_(srcIdx))))
484      XSPerfAccumulate(s"enqEntry_all_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.take(params.numEnq).map(_(srcIdx))))
485      for (iqIdx <- 0 until params.numWakeupFromIQ) {
486        XSPerfAccumulate(s"enqEntry_all_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.take(params.numEnq).map(_(srcIdx)(iqIdx))))
487      }
488    }
489  }
490
491  XSPerfAccumulate(s"othersEntry_all_in_cnt", PopCount(entryInValidVec.drop(params.numEnq)))
492  XSPerfAccumulate(s"othersEntry_all_out_deq_cnt", PopCount(entryOutDeqValidVec.drop(params.numEnq)))
493  XSPerfAccumulate(s"othersEntry_all_out_trans_cnt", PopCount(entryOutTransValidVec.drop(params.numEnq)))
494
495  for (srcIdx <- 0 until params.numRegSrc) {
496    XSPerfAccumulate(s"othersEntry_all_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.drop(params.numEnq).map(_(srcIdx))))
497    if (params.hasIQWakeUp) {
498      XSPerfAccumulate(s"othersEntry_all_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.drop(params.numEnq).map(_(srcIdx))))
499      XSPerfAccumulate(s"othersEntry_all_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.drop(params.numEnq).map(_(srcIdx))))
500      for (iqIdx <- 0 until params.numWakeupFromIQ) {
501        XSPerfAccumulate(s"othersEntry_all_wakeup_iq_from_exu${params.wakeUpSourceExuIdx(iqIdx)}_src${srcIdx}_cnt", PopCount(perfWakeupByIQVec.get.drop(params.numEnq).map(_(srcIdx)(iqIdx))))
502      }
503    }
504  }
505
506  for (t <- FuType.functionNameMap.keys) {
507    val fuName = FuType.functionNameMap(t)
508    if (params.getFuCfgs.map(_.fuType == t).reduce(_ | _) && params.getFuCfgs.size > 1) {
509      for (srcIdx <- 0 until params.numRegSrc) {
510        XSPerfAccumulate(s"allEntry_futype_${fuName}_wakeup_wb_src${srcIdx}_cnt", PopCount(perfWakeupByWBVec.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) }))
511        if (params.hasIQWakeUp) {
512          XSPerfAccumulate(s"allEntry_futype_${fuName}_ldCancel_src${srcIdx}_cnt", PopCount(perfLdCancelVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) }))
513          XSPerfAccumulate(s"allEntry_futype_${fuName}_og0Cancel_src${srcIdx}_cnt", PopCount(perfOg0CancelVec.get.zip(fuTypeVec).map{ case(x, fu) => x(srcIdx) && fu(t.id) }))
514          for (iqIdx <- 0 until params.numWakeupFromIQ) {
515            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) }))
516          }
517        }
518      }
519    }
520  }
521}
522
523class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
524  val flush               = Flipped(ValidIO(new Redirect))
525  //enq
526  val enq                 = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
527  val og0Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
528  val og1Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
529  val og2Resp             = OptionWrapper(params.needOg2Resp, Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))))
530  //deq sel
531  val deqReady            = Vec(params.numDeq, Input(Bool()))
532  val deqSelOH            = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W))))
533  val enqEntryOldestSel   = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W))))
534  val simpEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numSimp.W)))))
535  val compEntryOldestSel  = OptionWrapper(params.hasCompAndSimp, Vec(params.numDeq, Flipped(ValidIO(UInt(params.numComp.W)))))
536  val othersEntryOldestSel= OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W)))))
537  val subDeqRequest       = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
538  val subDeqSelOH         = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
539  // wakeup
540  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
541  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
542  val vlFromIntIsZero     = Input(Bool())
543  val vlFromIntIsVlmax    = Input(Bool())
544  val vlFromVfIsZero      = Input(Bool())
545  val vlFromVfIsVlmax     = Input(Bool())
546  val og0Cancel           = Input(ExuVec())
547  val og1Cancel           = Input(ExuVec())
548  val ldCancel            = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
549  //entries status
550  val valid               = Output(UInt(params.numEntries.W))
551  val issued              = Output(UInt(params.numEntries.W))
552  val canIssue            = Output(UInt(params.numEntries.W))
553  val fuType              = Vec(params.numEntries, Output(FuType()))
554  val dataSources         = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource())))
555  val loadDependency      = Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W)))
556  val srcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuVec()))))
557  //deq status
558  val isFirstIssue        = Vec(params.numDeq, Output(Bool()))
559  val deqEntry            = Vec(params.numDeq, ValidIO(new EntryBundle))
560  val cancelDeqVec        = Vec(params.numDeq, Output(Bool()))
561
562  // load/hybird only
563  val fromLoad = OptionWrapper(params.isLdAddrIQ || params.isHyAddrIQ, new Bundle {
564    val finalIssueResp    = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
565    val memAddrIssueResp  = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
566  })
567  // mem only
568  val fromMem = OptionWrapper(params.isMemAddrIQ, new Bundle {
569    val slowResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
570    val fastResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
571  })
572  // vec mem only
573  val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle {
574    val sqDeqPtr          = Input(new SqPtr)
575    val lqDeqPtr          = Input(new LqPtr)
576  })
577  val vecLdIn = OptionWrapper(params.isVecLduIQ, new Bundle {
578    val resp              = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
579  })
580  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
581
582  // trans
583  val simpEntryDeqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Input(UInt(params.numSimp.W))))
584  val simpEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numSimp.W))))
585  val compEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numComp.W))))
586  val othersEntryEnqSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numEnq, Output(UInt((params.numEntries - params.numEnq).W))))
587
588  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
589}
590