xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision 4ab7f02c251981009225c54bc740213e3937eeab)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.HasCircularQueuePtrHelper
7import utils._
8import utility._
9import xiangshan._
10import xiangshan.backend.Bundles._
11import xiangshan.backend.datapath.DataConfig.VAddrData
12import xiangshan.backend.datapath.DataSource
13import xiangshan.backend.fu.FuType
14import xiangshan.backend.fu.vector.Utils.NOnes
15import xiangshan.backend.rob.RobPtr
16import xiangshan.mem.{LqPtr, MemWaitUpdateReq, SqPtr}
17import xiangshan.backend.issue.EntryBundles._
18
19class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
20  override def desiredName: String = params.getEntryName
21
22  require(params.numEnq <= 2, "number of enq should be no more than 2")
23
24  private val EnqEntryNum         = params.numEnq
25  private val OthersEntryNum      = params.numEntries - params.numEnq
26  private val SimpEntryNum        = params.numSimp
27  private val CompEntryNum        = params.numComp
28  val io = IO(new EntriesIO)
29
30  // only memAddrIQ use it
31  val memEtyResps: Seq[ValidIO[EntryDeqRespBundle]] = {
32    val resps =
33      if (params.isLdAddrIQ && !params.isStAddrIQ)                                                    //LDU
34        Seq(io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp)
35      else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ)                           //HYU
36        Seq(io.fromLoad.get.finalIssueResp, io.fromLoad.get.memAddrIssueResp, io.fromMem.get.fastResp, io.fromMem.get.slowResp)
37      else if (params.isStAddrIQ)                                                                     //STU
38        Seq(io.fromMem.get.slowResp)
39      else if (params.isVecLduIQ && params.isVecStuIQ) // Vector store IQ need no vecLdIn.resp, but for now vector store share the vector load IQ
40        Seq(io.vecLdIn.get.resp, io.fromMem.get.slowResp)
41      else if (params.isVecLduIQ)
42        Seq(io.vecLdIn.get.resp)
43      else if (params.isVecStuIQ)
44        Seq(io.fromMem.get.slowResp)
45      else Seq()
46    if (params.isMemAddrIQ) {
47      println(s"[${this.desiredName}] resp: {" +
48        s"og0Resp: ${resps.contains(io.og0Resp)}, " +
49        s"og1Resp: ${resps.contains(io.og1Resp)}, " +
50        s"finalResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.finalIssueResp)}, " +
51        s"loadBorderResp: ${io.fromLoad.nonEmpty && resps.contains(io.fromLoad.get.memAddrIssueResp)}, " +
52        s"memFastResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.fastResp)}, " +
53        s"memSlowResp: ${io.fromMem.nonEmpty && resps.contains(io.fromMem.get.slowResp)}, " +
54        s"vecLoadBorderResp: ${io.vecLdIn.nonEmpty && resps.contains(io.vecLdIn.get.resp)}, " +
55        s"}"
56      )
57    }
58    resps.flatten
59  }
60
61  val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = {
62    if (params.inVfSchd)
63      VecInit(io.og0Resp, io.og1Resp, io.og2Resp.get, 0.U.asTypeOf(io.og0Resp))
64    else
65      VecInit(io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.og0Resp), 0.U.asTypeOf(io.og0Resp))
66  }
67
68
69
70  //Module
71  val enqEntries          = Seq.fill(EnqEntryNum)(Module(EnqEntry(isComp = true)(p, params)))
72  val othersEntriesSimp   = Seq.fill(SimpEntryNum)(Module(OthersEntry(isComp = false)(p, params)))
73  val othersEntriesComp   = Seq.fill(CompEntryNum)(Module(OthersEntry(isComp = true)(p, params)))
74  val othersEntries       = othersEntriesSimp ++ othersEntriesComp
75  val othersTransPolicy   = OptionWrapper(params.isAllComp || params.isAllSimp, Module(new EnqPolicy))
76  val simpTransPolicy     = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy))
77  val compTransPolicy     = OptionWrapper(params.hasCompAndSimp, Module(new EnqPolicy))
78
79  //Wire
80  //entries status
81  val entries             = Wire(Vec(params.numEntries, ValidIO(new EntryBundle)))
82  val robIdxVec           = Wire(Vec(params.numEntries, new RobPtr))
83  val validVec            = Wire(Vec(params.numEntries, Bool()))
84  val canIssueVec         = Wire(Vec(params.numEntries, Bool()))
85  val fuTypeVec           = Wire(Vec(params.numEntries, FuType()))
86  val isFirstIssueVec     = Wire(Vec(params.numEntries, Bool()))
87  val issueTimerVec       = Wire(Vec(params.numEntries, UInt(2.W)))
88  val sqIdxVec            = OptionWrapper(params.needFeedBackSqIdx, Wire(Vec(params.numEntries, new SqPtr())))
89  //src status
90  val dataSourceVec       = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
91  val loadDependencyVec   = Wire(Vec(params.numEntries, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W))))
92  val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec()))))
93  //deq sel
94  val deqSelVec           = Wire(Vec(params.numEntries, Bool()))
95  val issueRespVec        = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle)))
96  val deqPortIdxWriteVec  = Wire(Vec(params.numEntries, UInt(1.W)))
97  val deqPortIdxReadVec   = Wire(Vec(params.numEntries, UInt(1.W)))
98  //trans sel
99  val othersEntryEnqReadyVec = Wire(Vec(OthersEntryNum, Bool()))
100  val othersEntryEnqVec      = Wire(Vec(OthersEntryNum, Valid(new EntryBundle)))
101  val enqEntryTransVec       = Wire(Vec(EnqEntryNum, Valid(new EntryBundle)))
102  val simpEntryTransVec      = OptionWrapper(params.hasCompAndSimp, Wire(Vec(SimpEntryNum, Valid(new EntryBundle))))
103  val compEnqVec             = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(new EntryBundle))))
104
105  val enqCanTrans2Simp       = OptionWrapper(params.hasCompAndSimp, Wire(Bool()))
106  val enqCanTrans2Comp       = OptionWrapper(params.hasCompAndSimp, Wire(Bool()))
107  val simpCanTrans2Comp      = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Bool())))
108  val simpTransSelVec        = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(UInt(SimpEntryNum.W)))))
109  val compTransSelVec        = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, Valid(UInt(CompEntryNum.W)))))
110  val finalSimpTransSelVec   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, UInt(SimpEntryNum.W))))
111  val finalCompTransSelVec   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(EnqEntryNum, UInt(CompEntryNum.W))))
112
113  val enqCanTrans2Others     = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Bool()))
114  val othersTransSelVec      = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(EnqEntryNum, Valid(UInt(OthersEntryNum.W)))))
115  val finalOthersTransSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(EnqEntryNum, UInt(OthersEntryNum.W))))
116
117  val simpEntryEnqReadyVec   = othersEntryEnqReadyVec.take(SimpEntryNum)
118  val compEntryEnqReadyVec   = othersEntryEnqReadyVec.takeRight(CompEntryNum)
119  val simpEntryEnqVec        = othersEntryEnqVec.take(SimpEntryNum)
120  val compEntryEnqVec        = othersEntryEnqVec.takeRight(CompEntryNum)
121  //debug
122  val entryInValidVec        = Wire(Vec(params.numEntries, Bool()))
123  val entryOutDeqValidVec    = Wire(Vec(params.numEntries, Bool()))
124  val entryOutTransValidVec  = Wire(Vec(params.numEntries, Bool()))
125  val perfLdCancelVec        = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Bool()))))
126  val perfOg0CancelVec       = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Bool()))))
127  val perfWakeupByWBVec      = Wire(Vec(params.numEntries, Vec(params.numRegSrc, Bool())))
128  val perfWakeupByIQVec      = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool())))))
129  //cancel bypass
130  val cancelBypassVec        = Wire(Vec(params.numEntries, Bool()))
131
132
133  //enqEntries
134  enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) =>
135    enqEntry.io.commonIn.enq                  := io.enq(entryIdx)
136    enqEntry.io.commonIn.transSel             := (if (params.isAllComp || params.isAllSimp) enqCanTrans2Others.get && othersTransSelVec.get(entryIdx).valid
137                                                  else enqCanTrans2Simp.get && simpTransSelVec.get(entryIdx).valid || enqCanTrans2Comp.get && compTransSelVec.get(entryIdx).valid)
138    EntriesConnect(enqEntry.io.commonIn, enqEntry.io.commonOut, entryIdx)
139    enqEntry.io.enqDelayIn1.wakeUpFromWB      := RegEnable(io.wakeUpFromWB, io.enq(entryIdx).valid)
140    enqEntry.io.enqDelayIn1.wakeUpFromIQ      := RegEnable(io.wakeUpFromIQ, io.enq(entryIdx).valid)
141    enqEntry.io.enqDelayIn1.srcLoadDependency := RegEnable(VecInit(io.enq(entryIdx).bits.payload.srcLoadDependency.take(params.numRegSrc)), io.enq(entryIdx).valid)
142    enqEntry.io.enqDelayIn1.og0Cancel         := RegNext(io.og0Cancel.asUInt)
143    enqEntry.io.enqDelayIn1.ldCancel          := RegNext(io.ldCancel)
144    // note: these signals with 2 cycle delay should not be enabled by io.enq.valid
145    enqEntry.io.enqDelayIn2.wakeUpFromWB      := DelayN(io.wakeUpFromWB, 2)
146    enqEntry.io.enqDelayIn2.wakeUpFromIQ      := DelayN(io.wakeUpFromIQ, 2)
147    enqEntry.io.enqDelayIn2.srcLoadDependency := DelayN(VecInit(io.enq(entryIdx).bits.payload.srcLoadDependency.take(params.numRegSrc)), 2)
148    enqEntry.io.enqDelayIn2.og0Cancel         := DelayN(io.og0Cancel.asUInt, 2)
149    enqEntry.io.enqDelayIn2.ldCancel          := DelayN(io.ldCancel, 2)
150    enqEntryTransVec(entryIdx)                := enqEntry.io.commonOut.transEntry
151  }
152  //othersEntries
153  othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) =>
154    othersEntry.io.commonIn.enq               := othersEntryEnqVec(entryIdx)
155    othersEntry.io.commonIn.transSel          := (if (params.hasCompAndSimp && (entryIdx < SimpEntryNum))
156                                                    io.simpEntryDeqSelVec.get.zip(simpCanTrans2Comp.get).map(x => x._1(entryIdx) && x._2).reduce(_ | _)
157                                                  else false.B)
158    EntriesConnect(othersEntry.io.commonIn, othersEntry.io.commonOut, entryIdx + EnqEntryNum)
159    othersEntryEnqReadyVec(entryIdx)          := othersEntry.io.commonOut.enqReady
160    if (params.hasCompAndSimp && (entryIdx < SimpEntryNum)) {
161      simpEntryTransVec.get(entryIdx)         := othersEntry.io.commonOut.transEntry
162    }
163  }
164
165
166  deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) =>
167    val deqVec = io.deqSelOH.zip(io.deqReady).map(x => x._1.valid && x._1.bits(i) && x._2)
168    deqPortIdxWrite := OHToUInt(deqVec)
169    deqSel := deqVec.reduce(_ | _)
170  }
171
172
173  if (params.isAllComp || params.isAllSimp) {
174    //transPolicy
175    othersTransPolicy.get.io.canEnq := VecInit(validVec.takeRight(OthersEntryNum).map(!_)).asUInt
176
177    // we only allow all or none of the enq entries transfering to others entries.
178    enqCanTrans2Others.get := PopCount(validVec.take(EnqEntryNum)) <= PopCount(validVec.takeRight(OthersEntryNum).map(!_))
179    // othersTransSelVec(i) is the target others entry for enq entry [i].
180    // note that dispatch does not guarantee the validity of enq entries with low index.
181    // that means in some cases enq entry [0] is invalid while enq entry [1] is valid.
182    // in this case, enq entry [1] should use result [0] of TransPolicy.
183    othersTransSelVec.get(0).valid := othersTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0)
184    othersTransSelVec.get(0).bits  := othersTransPolicy.get.io.enqSelOHVec(0).bits
185    if (params.numEnq == 2) {
186      othersTransSelVec.get(1).valid := Mux(!validVec(0), othersTransPolicy.get.io.enqSelOHVec(0).valid, othersTransPolicy.get.io.enqSelOHVec(1).valid)
187      othersTransSelVec.get(1).bits  := Mux(!validVec(0), othersTransPolicy.get.io.enqSelOHVec(0).bits,  othersTransPolicy.get.io.enqSelOHVec(1).bits)
188    }
189
190    finalOthersTransSelVec.get.zip(othersTransSelVec.get).zipWithIndex.foreach { case ((finalOH, selOH), enqIdx) =>
191      finalOH := Fill(OthersEntryNum, enqCanTrans2Others.get && selOH.valid) & selOH.bits
192    }
193
194    //othersEntryEnq
195    othersEntryEnqVec.zipWithIndex.foreach { case (othersEntryEnq, othersIdx) =>
196      val othersEnqOH = finalOthersTransSelVec.get.map(_(othersIdx))
197      if (othersEnqOH.size == 1)
198        othersEntryEnq := Mux(othersEnqOH.head, enqEntryTransVec.head, 0.U.asTypeOf(enqEntryTransVec.head))
199      else
200        othersEntryEnq := Mux1H(othersEnqOH, enqEntryTransVec)
201    }
202  }
203  else {
204    //transPolicy
205    simpTransPolicy.get.io.canEnq := VecInit(simpEntryEnqReadyVec).asUInt
206    compTransPolicy.get.io.canEnq := VecInit(validVec.takeRight(CompEntryNum).map(!_)).asUInt
207
208    // we only allow all or none of the enq entries transfering to comp/simp entries.
209    // when all of simp entries are empty and comp entries are enough, transfer to comp entries.
210    // otherwise, transfer to simp entries.
211    enqCanTrans2Comp.get := PopCount(validVec.take(EnqEntryNum)) <= PopCount(validVec.takeRight(CompEntryNum).map(!_)) && !validVec.drop(EnqEntryNum).take(SimpEntryNum).reduce(_ || _)
212    enqCanTrans2Simp.get := !enqCanTrans2Comp.get && PopCount(validVec.take(EnqEntryNum)) <= PopCount(simpEntryEnqReadyVec)
213    simpCanTrans2Comp.get.zipWithIndex.foreach { case (canTrans, idx) =>
214      canTrans := !enqCanTrans2Comp.get && PopCount(validVec.takeRight(CompEntryNum).map(!_)) >= (idx + 1).U
215    }
216
217    // simp/compTransSelVec(i) is the target simp/comp entry for enq entry [i].
218    // note that dispatch does not guarantee the validity of enq entries with low index.
219    // that means in some cases enq entry [0] is invalid while enq entry [1] is valid.
220    // in this case, enq entry [1] should use result [0] of TransPolicy.
221    simpTransSelVec.get(0).valid := simpTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0)
222    simpTransSelVec.get(0).bits  := simpTransPolicy.get.io.enqSelOHVec(0).bits
223    compTransSelVec.get(0).valid := compTransPolicy.get.io.enqSelOHVec(0).valid && validVec(0)
224    compTransSelVec.get(0).bits  := compTransPolicy.get.io.enqSelOHVec(0).bits
225    if (params.numEnq == 2) {
226      simpTransSelVec.get(1).valid := Mux(!validVec(0), simpTransPolicy.get.io.enqSelOHVec(0).valid, simpTransPolicy.get.io.enqSelOHVec(1).valid)
227      simpTransSelVec.get(1).bits  := Mux(!validVec(0), simpTransPolicy.get.io.enqSelOHVec(0).bits,  simpTransPolicy.get.io.enqSelOHVec(1).bits)
228      compTransSelVec.get(1).valid := Mux(!validVec(0), compTransPolicy.get.io.enqSelOHVec(0).valid, compTransPolicy.get.io.enqSelOHVec(1).valid)
229      compTransSelVec.get(1).bits  := Mux(!validVec(0), compTransPolicy.get.io.enqSelOHVec(0).bits,  compTransPolicy.get.io.enqSelOHVec(1).bits)
230    }
231
232    finalSimpTransSelVec.get.zip(simpTransSelVec.get).zipWithIndex.foreach { case ((finalOH, selOH), enqIdx) =>
233      finalOH := Fill(SimpEntryNum, enqCanTrans2Simp.get && selOH.valid) & selOH.bits
234    }
235    finalCompTransSelVec.get.zip(compTransSelVec.get).zip(compTransPolicy.get.io.enqSelOHVec).zipWithIndex.foreach {
236      case (((finalOH, selOH), origSelOH), enqIdx) =>
237        finalOH := Mux(enqCanTrans2Comp.get, Fill(CompEntryNum, selOH.valid) & selOH.bits, Fill(CompEntryNum, origSelOH.valid) & origSelOH.bits)
238    }
239
240    //othersEntryEnq
241    simpEntryEnqVec.zipWithIndex.foreach { case (simpEntryEnq, simpIdx) =>
242      val simpEnqOH = finalSimpTransSelVec.get.map(_(simpIdx))
243      // shit Mux1H directly returns in(0) if the seq has only 1 elements
244      if (simpEnqOH.size == 1)
245        simpEntryEnq := Mux(simpEnqOH.head, enqEntryTransVec.head, 0.U.asTypeOf(enqEntryTransVec.head))
246      else
247        simpEntryEnq := Mux1H(simpEnqOH, enqEntryTransVec)
248    }
249
250    compEnqVec.get.zip(enqEntryTransVec).zip(io.simpEntryDeqSelVec.get).foreach { case ((compEnq, enqEntry), deqSel) =>
251      compEnq := Mux(enqCanTrans2Comp.get, enqEntry, Mux1H(deqSel, simpEntryTransVec.get))
252    }
253    compEntryEnqVec.zipWithIndex.foreach { case (compEntryEnq, compIdx) =>
254      val compEnqOH = finalCompTransSelVec.get.map(_(compIdx))
255      // shit Mux1H directly returns in(0) if the seq has only 1 elements
256      if (compEnqOH.size == 1)
257        compEntryEnq := Mux(compEnqOH.head, compEnqVec.get.head, 0.U.asTypeOf(compEnqVec.get.head))
258      else
259        compEntryEnq := Mux1H(compEnqOH, compEnqVec.get)
260    }
261
262    assert(PopCount(simpEntryEnqVec.map(_.valid)) <= params.numEnq.U, "the number of simpEntryEnq is more than numEnq\n")
263    assert(PopCount(compEntryEnqVec.map(_.valid)) <= params.numEnq.U, "the number of compEntryEnq is more than numEnq\n")
264  }
265
266  if(backendParams.debugEn) {
267    dontTouch(othersEntryEnqVec)
268  }
269
270  //issueRespVec
271  if (params.needFeedBackSqIdx) {
272    // vector memory IQ
273    issueRespVec.lazyZip(sqIdxVec.get).lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, sqIdx, (issueTimer, deqPortIdx)) =>
274      val respInDatapath = resps(issueTimer(0))(deqPortIdx)
275      val respAfterDatapath = Wire(chiselTypeOf(respInDatapath))
276      val hitRespsVec = VecInit(memEtyResps.map(x =>
277        x.valid && (x.bits.sqIdx.get === sqIdx)
278      ).toSeq)
279      respAfterDatapath.valid := hitRespsVec.reduce(_ | _)
280      respAfterDatapath.bits  := (if (memEtyResps.size == 1) memEtyResps.head.bits
281                                  else Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq))
282      issueResp := Mux(issueTimer(1), respAfterDatapath, respInDatapath)
283    }
284  } else if (params.isMemAddrIQ) {
285    // scalar memory IQ
286    issueRespVec.lazyZip(robIdxVec).lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, robIdx, (issueTimer, deqPortIdx)) =>
287      val respInDatapath = resps(issueTimer(0))(deqPortIdx)
288      val respAfterDatapath = Wire(chiselTypeOf(respInDatapath))
289      val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq)
290      respAfterDatapath.valid := hitRespsVec.reduce(_ | _)
291      respAfterDatapath.bits  := (if (memEtyResps.size == 1) memEtyResps.head.bits
292                                  else Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq))
293      issueResp := Mux(issueTimer(1), respAfterDatapath, respInDatapath)
294    }
295  }
296  else {
297    issueRespVec.lazyZip(issueTimerVec.lazyZip(deqPortIdxReadVec)).foreach { case (issueResp, (issueTimer, deqPortIdx)) =>
298      val Resp = resps(issueTimer)(deqPortIdx)
299      issueResp := Resp
300    }
301  }
302
303  //deq
304  val enqEntryOldest          = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
305  val simpEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
306  val compEntryOldest         = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
307  val othersEntryOldest       = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, ValidIO(new EntryBundle))))
308  val enqEntryOldestCancel    = Wire(Vec(params.numDeq, Bool()))
309  val simpEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
310  val compEntryOldestCancel   = OptionWrapper(params.hasCompAndSimp, Wire(Vec(params.numDeq, Bool())))
311  val othersEntryOldestCancel = OptionWrapper(params.isAllComp || params.isAllSimp, Wire(Vec(params.numDeq, Bool())))
312
313  io.enqEntryOldestSel.zipWithIndex.map { case (sel, deqIdx) =>
314    enqEntryOldest(deqIdx) := Mux1H(sel.bits, entries.take(EnqEntryNum))
315    enqEntryOldestCancel(deqIdx) := Mux1H(sel.bits, cancelBypassVec.take(EnqEntryNum))
316  }
317
318  if (params.isAllComp || params.isAllSimp) {
319    io.othersEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
320      othersEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum))
321      othersEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum))
322    }
323  }
324  else {
325    io.simpEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
326      simpEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).take(SimpEntryNum))
327      simpEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).take(SimpEntryNum))
328    }
329    io.compEntryOldestSel.get.zipWithIndex.map { case (sel, deqIdx) =>
330      compEntryOldest.get(deqIdx) := Mux1H(sel.bits, entries.drop(EnqEntryNum).takeRight(CompEntryNum))
331      compEntryOldestCancel.get(deqIdx) := Mux1H(sel.bits, cancelBypassVec.drop(EnqEntryNum).takeRight(CompEntryNum))
332    }
333  }
334
335  if (params.deqFuSame) {
336    val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
337    val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool()))
338    val subDeqPolicyCancelBypassVec = Wire(Vec(params.numDeq, Bool()))
339
340    subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U
341    subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U
342
343    if (params.isAllComp || params.isAllSimp) {
344      subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries)
345      subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
346      subDeqPolicyCancelBypassVec(0) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
347      subDeqPolicyCancelBypassVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
348
349      io.deqEntry(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldest.get(0), subDeqPolicyEntryVec(1))
350      io.deqEntry(1) := subDeqPolicyEntryVec(0)
351      io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel.get(0).valid, othersEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1))
352      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
353    }
354    else {
355      subDeqPolicyEntryVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
356      subDeqPolicyEntryVec(1) := PriorityMux(io.subDeqRequest.get(0), entries)
357      subDeqPolicyCancelBypassVec(0) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelBypassVec.reverse)
358      subDeqPolicyCancelBypassVec(1) := PriorityMux(io.subDeqRequest.get(0), cancelBypassVec)
359
360      io.deqEntry(0) := Mux(io.compEntryOldestSel.get(0).valid,
361                            compEntryOldest.get(0),
362                            Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldest.get(0), subDeqPolicyEntryVec(1)))
363      io.deqEntry(1) := subDeqPolicyEntryVec(0)
364      io.cancelDeqVec(0) := Mux(io.compEntryOldestSel.get(0).valid,
365                                compEntryOldestCancel.get(0),
366                                Mux(io.simpEntryOldestSel.get(0).valid, simpEntryOldestCancel.get(0), subDeqPolicyCancelBypassVec(1)))
367      io.cancelDeqVec(1) := subDeqPolicyCancelBypassVec(0)
368    }
369
370    when (subDeqPolicyValidVec(0)) {
371      assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n")
372    }
373    when (subDeqPolicyValidVec(1)) {
374      assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n")
375    }
376  }
377  else {
378    if (params.isAllComp || params.isAllSimp) {
379      io.othersEntryOldestSel.get.zipWithIndex.foreach { case (sel, i) =>
380        io.deqEntry(i)     := Mux(sel.valid, othersEntryOldest.get(i), enqEntryOldest(i))
381        io.cancelDeqVec(i) := Mux(sel.valid, othersEntryOldestCancel.get(i), enqEntryOldestCancel(i))
382      }
383    }
384    else {
385      io.compEntryOldestSel.get.zip(io.simpEntryOldestSel.get).zipWithIndex.foreach { case ((compSel, simpSel), i) =>
386        io.deqEntry(i)     := Mux(compSel.valid,
387                                  compEntryOldest.get(i),
388                                  Mux(simpSel.valid, simpEntryOldest.get(i), enqEntryOldest(i)))
389        io.cancelDeqVec(i) := Mux(compSel.valid,
390                                  compEntryOldestCancel.get(i),
391                                  Mux(simpSel.valid, simpEntryOldestCancel.get(i), enqEntryOldestCancel(i)))
392      }
393    }
394  }
395
396  io.valid                          := validVec.asUInt
397  io.canIssue                       := canIssueVec.asUInt
398  io.fuType                         := fuTypeVec
399  io.dataSources                    := dataSourceVec
400  io.srcWakeUpL1ExuOH.foreach(_     := srcWakeUpL1ExuOHVec.get)
401  io.loadDependency                 := loadDependencyVec
402  io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) =>
403    isFirstIssue                    := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec)
404  }
405  io.simpEntryEnqSelVec.foreach(_   := finalSimpTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(SimpEntryNum, x._2.valid)))
406  io.compEntryEnqSelVec.foreach(_   := finalCompTransSelVec.get.zip(compEnqVec.get).map(x => x._1 & Fill(CompEntryNum, x._2.valid)))
407  io.othersEntryEnqSelVec.foreach(_ := finalOthersTransSelVec.get.zip(enqEntryTransVec).map(x => x._1 & Fill(OthersEntryNum, x._2.valid)))
408  io.robIdx.foreach(_               := robIdxVec)
409
410
411  def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = {
412    in.flush                    := io.flush
413    in.wakeUpFromWB             := io.wakeUpFromWB
414    in.wakeUpFromIQ             := io.wakeUpFromIQ
415    in.vlIsZero                 := io.vlIsZero
416    in.vlIsVlmax                := io.vlIsVlmax
417    in.og0Cancel                := io.og0Cancel
418    in.og1Cancel                := io.og1Cancel
419    in.ldCancel                 := io.ldCancel
420    in.deqSel                   := deqSelVec(entryIdx)
421    in.deqPortIdxWrite          := deqPortIdxWriteVec(entryIdx)
422    in.issueResp                := issueRespVec(entryIdx)
423    if (params.isVecMemIQ) {
424      in.fromLsq.get.sqDeqPtr   := io.vecMemIn.get.sqDeqPtr
425      in.fromLsq.get.lqDeqPtr   := io.vecMemIn.get.lqDeqPtr
426    }
427    validVec(entryIdx)          := out.valid
428    canIssueVec(entryIdx)       := out.canIssue
429    fuTypeVec(entryIdx)         := out.fuType
430    robIdxVec(entryIdx)         := out.robIdx
431    dataSourceVec(entryIdx)     := out.dataSource
432    isFirstIssueVec(entryIdx)   := out.isFirstIssue
433    entries(entryIdx)           := out.entry
434    deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead
435    issueTimerVec(entryIdx)     := out.issueTimerRead
436    loadDependencyVec(entryIdx) := out.entry.bits.status.mergedLoadDependency
437    cancelBypassVec(entryIdx)   := out.cancelBypass
438    if (params.hasIQWakeUp) {
439      srcWakeUpL1ExuOHVec.get(entryIdx)     := out.srcWakeUpL1ExuOH.get
440    }
441    if (params.isVecMemIQ || params.isStAddrIQ) {
442      sqIdxVec.get(entryIdx) := out.entry.bits.payload.sqIdx
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.inVfSchd, 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 vlIsZero            = Input(Bool())
543  val vlIsVlmax           = Input(Bool())
544  val og0Cancel           = Input(ExuOH(backendParams.numExu))
545  val og1Cancel           = Input(ExuOH(backendParams.numExu))
546  val ldCancel            = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
547  //entries status
548  val valid               = 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 srcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuVec()))))
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 resp              = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
576  })
577  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
578
579  // trans
580  val simpEntryDeqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Input(UInt(params.numSimp.W))))
581  val simpEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numSimp.W))))
582  val compEntryEnqSelVec = OptionWrapper(params.hasCompAndSimp, Vec(params.numEnq, Output(UInt(params.numComp.W))))
583  val othersEntryEnqSelVec = OptionWrapper(params.isAllComp || params.isAllSimp, Vec(params.numEnq, Output(UInt((params.numEntries - params.numEnq).W))))
584
585  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
586}
587