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