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