xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision 27811ea4c4b384371a3a5624679f3f71aafa22a5)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.HasCircularQueuePtrHelper
7import utils.{MathUtils, OptionWrapper, XSError}
8import xiangshan._
9import xiangshan.backend.Bundles._
10import xiangshan.backend.datapath.DataConfig.VAddrData
11import xiangshan.backend.datapath.DataSource
12import xiangshan.backend.fu.FuType
13import xiangshan.backend.fu.vector.Utils.NOnes
14import xiangshan.backend.rob.RobPtr
15import xiangshan.mem.{LqPtr, MemWaitUpdateReq, SqPtr}
16import xiangshan.backend.issue.EntryBundles._
17
18class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
19  override def desiredName: String = params.getEntryName
20
21  require(params.numEnq <= 2, "number of enq should be no more than 2")
22
23  private val EnqEntryNum         = params.numEnq
24  private val OthersEntryNum      = params.numEntries - params.numEnq
25  val io = IO(new EntriesIO)
26
27  // only memAddrIQ use it
28  val memEtyResps: MixedVec[ValidIO[EntryDeqRespBundle]] = {
29    if (params.isLdAddrIQ && !params.isStAddrIQ)
30      MixedVecInit(io.og0Resp ++ io.og1Resp ++ io.finalIssueResp.get)
31    else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ)
32      MixedVecInit(io.og0Resp ++ io.og1Resp ++ io.finalIssueResp.get ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp)
33    else if (params.isMemAddrIQ)
34      MixedVecInit(io.og0Resp ++ io.og1Resp ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp)
35    else MixedVecInit(Seq())
36  }
37
38  val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = VecInit(io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.og0Resp), 0.U.asTypeOf(io.og0Resp))
39
40  //Module
41  val enqEntries          = Seq.fill(EnqEntryNum)(Module(EnqEntry(p, params)))
42  val othersEntries       = Seq.fill(OthersEntryNum)(Module(OthersEntry(p, params)))
43  val transPolicy         = Module(new EnqPolicy)
44
45  //Wire
46  //entries status
47  val entries             = Wire(Vec(params.numEntries, ValidIO(new EntryBundle)))
48  val robIdxVec           = Wire(Vec(params.numEntries, new RobPtr))
49  val validVec            = Wire(Vec(params.numEntries, Bool()))
50  val canIssueVec         = Wire(Vec(params.numEntries, Bool()))
51  val fuTypeVec           = Wire(Vec(params.numEntries, FuType()))
52  val isFirstIssueVec     = Wire(Vec(params.numEntries, Bool()))
53  val issueTimerVec       = Wire(Vec(params.numEntries, UInt(2.W)))
54  //src status
55  val dataSourceVec       = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
56  val srcTimerVec         = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W)))))
57  val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuVec()))))
58  //deq sel
59  val deqSelVec           = Wire(Vec(params.numEntries, Bool()))
60  val issueRespVec        = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle)))
61  val deqPortIdxWriteVec  = Wire(Vec(params.numEntries, UInt(1.W)))
62  val deqPortIdxReadVec   = Wire(Vec(params.numEntries, UInt(1.W)))
63  //trans sel
64  val transSelVec         = Wire(Vec(EnqEntryNum, Vec(OthersEntryNum, Bool())))
65  val transEntryDeqVec    = Wire(Vec(EnqEntryNum, ValidIO(new EntryBundle)))
66  val transEntryEnqVec    = Wire(Vec(OthersEntryNum, ValidIO(new EntryBundle)))
67  //debug
68  val cancelVec           = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool())))
69  //og0Cancel bypass
70  val cancelByOg0Vec      = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool())))
71  val uopIdxVec           = OptionWrapper(params.isVecMemIQ, Wire(Vec(params.numEntries, UopIdx())))
72
73  val canTrans            = Wire(Bool())
74  val enqReadyOthersVec   = Wire(Vec(OthersEntryNum, Bool()))
75  val enqTransSelVec      = Wire(Vec(EnqEntryNum, Valid(UInt(OthersEntryNum.W))))
76
77  io.transEntryDeqVec := transEntryDeqVec
78
79  //enqEntries
80  enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) =>
81    enqEntry.io.commonIn.enq                  := io.enq(entryIdx)
82    enqEntry.io.commonIn.transSel             := canTrans && enqTransSelVec(entryIdx).valid
83    EntriesConnect(enqEntry.io.commonIn, enqEntry.io.commonOut, entryIdx)
84    enqEntry.io.enqDelayWakeUpFromWB          := RegNext(io.wakeUpFromWB)
85    enqEntry.io.enqDelayWakeUpFromIQ          := RegNext(io.wakeUpFromIQ)
86    enqEntry.io.enqDelayOg0Cancel             := RegNext(io.og0Cancel.asUInt)
87    enqEntry.io.enqDelayLdCancel              := RegNext(io.ldCancel)
88    transEntryDeqVec(entryIdx)                := enqEntry.io.transEntry
89    // TODO: move it into EntriesConnect
90    if (params.isVecMemIQ) {
91      enqEntry.io.commonIn.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr
92      enqEntry.io.commonIn.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr
93    }
94  }
95  //othersEntries
96  othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) =>
97    othersEntry.io.commonIn.enq               := transEntryEnqVec(entryIdx)
98    EntriesConnect(othersEntry.io.commonIn, othersEntry.io.commonOut, entryIdx + EnqEntryNum)
99    othersEntry.io.commonIn.transSel          := transSelVec.map(x => x(entryIdx)).reduce(_ | _)
100    enqReadyOthersVec(entryIdx)               := othersEntry.io.enqReady
101    if (params.isVecMemIQ) {
102      othersEntry.io.commonIn.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr
103      othersEntry.io.commonIn.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr
104    }
105  }
106
107
108  deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) =>
109    val deqVec = io.deqSelOH.zip(io.deqReady).map(x => x._1.valid && x._1.bits(i) && x._2)
110    deqPortIdxWrite := OHToUInt(deqVec)
111    deqSel := deqVec.reduce(_ | _)
112  }
113
114
115  //transPolicy
116  transPolicy.io.canEnq := enqReadyOthersVec.asUInt
117  canTrans := PopCount(validVec.take(EnqEntryNum)) <= PopCount(enqReadyOthersVec)
118  enqTransSelVec(0).valid := transPolicy.io.enqSelOHVec(0).valid
119  enqTransSelVec(0).bits := transPolicy.io.enqSelOHVec(0).bits
120  // Todo: comments why enqTransSelVec(1).valid relies on validVec(0)
121  if (params.numEnq == 2) {
122    enqTransSelVec(1).valid := Mux(!validVec(0), transPolicy.io.enqSelOHVec(0).valid, transPolicy.io.enqSelOHVec(1).valid)
123    enqTransSelVec(1).bits := Mux(!validVec(0), transPolicy.io.enqSelOHVec(0).bits, transPolicy.io.enqSelOHVec(1).bits)
124  }
125
126  transSelVec.zip(enqTransSelVec).zipWithIndex.foreach { case ((selBools, selOH), enqIdx) =>
127    selBools.zipWithIndex.foreach { case (selBool, othersIdx) =>
128      selBool := canTrans && validVec(enqIdx) && selOH.valid && selOH.bits(othersIdx)
129    }
130  }
131
132  //transEntryEnq
133  transEntryEnqVec.zipWithIndex.foreach { case (transEntryEnq, othersIdx) =>
134    val transEnqHit = transSelVec.map(x => x(othersIdx))
135    transEntryEnq := Mux1H(transEnqHit, transEntryDeqVec)
136  }
137  if(backendParams.debugEn) {
138    dontTouch(transEntryEnqVec)
139  }
140
141  //issueRespVec
142  if (params.isVecMemIQ) {
143    // vector memory IQ
144    issueRespVec.zip(robIdxVec).zip(uopIdxVec.get).foreach { case ((issueResp, robIdx), uopIdx) =>
145      val hitRespsVec = VecInit(resps.flatten.map(x =>
146        x.valid && x.bits.robIdx === robIdx && x.bits.uopIdx.get === uopIdx
147      ))
148      issueResp.valid := hitRespsVec.reduce(_ | _)
149      issueResp.bits := Mux1H(hitRespsVec, resps.flatten.map(_.bits))
150    }
151  } else if (params.isMemAddrIQ) {
152    // scalar memory IQ
153    issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) =>
154      val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq)
155      issueResp.valid := hitRespsVec.reduce(_ | _)
156      issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)
157    }
158  }
159  else {
160    issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) =>
161      val Resp = resps(issueTimer)(deqPortIdx)
162      issueResp := Resp
163    }
164  }
165
166  //deq
167  val enqEntryOldest = io.enqEntryOldestSel.map { x =>
168    Mux1H(x.bits, entries.take(EnqEntryNum))
169  }
170  val enqEntryOldestCancel = io.enqEntryOldestSel.map { x =>
171    Mux1H(x.bits, cancelByOg0Vec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))).take(EnqEntryNum))
172  }
173  val othersEntryOldest = io.othersEntryOldestSel.map { x =>
174    Mux1H(x.bits, entries.drop(EnqEntryNum))
175  }
176  val othersEntryOldestCancel = io.othersEntryOldestSel.map { x =>
177    Mux1H(x.bits, cancelByOg0Vec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))).drop(EnqEntryNum))
178  }
179
180  if (params.deqFuSame) {
181    val subDeqPolicyEntryVec = Wire(Vec(params.numDeq, ValidIO(new EntryBundle)))
182    val subDeqPolicyValidVec = Wire(Vec(params.numDeq, Bool()))
183    val subDeqPolicyCancelByOg0Vec = Wire(Vec(params.numDeq, Bool()))
184
185    subDeqPolicyEntryVec(0) := PriorityMux(io.subDeqRequest.get(0), entries)
186    subDeqPolicyEntryVec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), entries.reverse)
187    subDeqPolicyValidVec(0) := PopCount(io.subDeqRequest.get(0)) >= 1.U
188    subDeqPolicyValidVec(1) := PopCount(io.subDeqRequest.get(0)) >= 2.U
189    subDeqPolicyCancelByOg0Vec(0) := PriorityMux(io.subDeqRequest.get(0), cancelByOg0Vec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))))
190    subDeqPolicyCancelByOg0Vec(1) := PriorityMux(Reverse(io.subDeqRequest.get(0)), cancelByOg0Vec.getOrElse(VecInit(Seq.fill(params.numEntries)(false.B))).reverse)
191
192    io.deqEntry(0) := Mux(io.othersEntryOldestSel(0).valid, othersEntryOldest(0), subDeqPolicyEntryVec(1))
193    io.deqEntry(1) := subDeqPolicyEntryVec(0)
194    io.cancelDeqVec(0) := Mux(io.othersEntryOldestSel(0).valid, othersEntryOldestCancel(0), subDeqPolicyCancelByOg0Vec(1))
195    io.cancelDeqVec(1) := subDeqPolicyCancelByOg0Vec(0)
196
197    when (subDeqPolicyValidVec(0)) {
198      assert(Mux1H(io.subDeqSelOH.get(0), entries).bits.status.robIdx === subDeqPolicyEntryVec(0).bits.status.robIdx, "subDeqSelOH(0) is not the same\n")
199    }
200    when (subDeqPolicyValidVec(1)) {
201      assert(Mux1H(io.subDeqSelOH.get(1), entries).bits.status.robIdx === subDeqPolicyEntryVec(1).bits.status.robIdx, "subDeqSelOH(1) is not the same\n")
202    }
203  }
204  else {
205    io.othersEntryOldestSel.zipWithIndex.foreach { case (x, i) =>
206      io.deqEntry(i) := Mux(x.valid, othersEntryOldest(i), enqEntryOldest(i))
207      io.cancelDeqVec(i) := Mux(x.valid, othersEntryOldestCancel(i), enqEntryOldestCancel(i))
208    }
209  }
210
211  if (params.hasIQWakeUp) {
212    cancelByOg0Vec.get.zip(srcWakeUpL1ExuOHVec.get).zip(srcTimerVec.get).foreach{ case ((cancelByOg0: Bool, l1ExuOH: Vec[Vec[Bool]]), srcTimer: Vec[UInt]) =>
213      cancelByOg0 := l1ExuOH.zip(srcTimer).map {
214        case(exuOH, srcTimer) =>
215          (exuOH.asUInt & io.og0Cancel.asUInt).orR && srcTimer === 1.U
216      }.reduce(_ | _)
217    }
218  }
219
220  io.valid                      := validVec.asUInt
221  io.canIssue                   := canIssueVec.asUInt
222  io.fuType                     := fuTypeVec
223  io.dataSources                := dataSourceVec
224  io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get.map(x => VecInit(x.map(_.asUInt))))
225  io.srcTimer.foreach(_         := srcTimerVec.get)
226  io.isFirstIssue.zipWithIndex.foreach{ case (isFirstIssue, deqIdx) =>
227    isFirstIssue                := io.deqSelOH(deqIdx).valid && Mux1H(io.deqSelOH(deqIdx).bits, isFirstIssueVec)
228  }
229  io.transSelVec.zip(transSelVec).foreach { case (sink, source) =>
230    sink                        := source.asUInt
231  }
232  io.robIdx.foreach(_           := robIdxVec)
233  io.uopIdx.foreach(_           := uopIdxVec.get)
234  io.rsFeedback                 := 0.U.asTypeOf(io.rsFeedback)  //should be removed
235  io.cancel.foreach(_           := cancelVec.get)               //for debug
236
237  def EntriesConnect(in: CommonInBundle, out: CommonOutBundle, entryIdx: Int) = {
238    in.flush                    := io.flush
239    in.wakeUpFromWB             := io.wakeUpFromWB
240    in.wakeUpFromIQ             := io.wakeUpFromIQ
241    in.og0Cancel                := io.og0Cancel
242    in.og1Cancel                := io.og1Cancel
243    in.ldCancel                 := io.ldCancel
244    in.deqSel                   := deqSelVec(entryIdx)
245    in.deqPortIdxWrite          := deqPortIdxWriteVec(entryIdx)
246    in.issueResp                := issueRespVec(entryIdx)
247    if (params.isMemAddrIQ) {
248      in.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr
249      in.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
250    }
251    if (params.isVecMemIQ) {
252      in.fromLsq.get.sqDeqPtr := io.vecMemIn.get.sqDeqPtr
253      in.fromLsq.get.lqDeqPtr := io.vecMemIn.get.lqDeqPtr
254    }
255    validVec(entryIdx)          := out.valid
256    canIssueVec(entryIdx)       := out.canIssue
257    fuTypeVec(entryIdx)         := out.fuType
258    robIdxVec(entryIdx)         := out.robIdx
259    dataSourceVec(entryIdx)     := out.dataSource
260    isFirstIssueVec(entryIdx)   := out.isFirstIssue
261    entries(entryIdx)           := out.entry
262    deqPortIdxReadVec(entryIdx) := out.deqPortIdxRead
263    issueTimerVec(entryIdx)     := out.issueTimerRead
264    if (params.hasIQWakeUp) {
265      srcWakeUpL1ExuOHVec.get(entryIdx) := out.srcWakeUpL1ExuOH.get
266      srcTimerVec.get(entryIdx) := out.srcTimer.get
267      cancelVec.get(entryIdx)   := out.cancel.get
268    }
269    if (params.isVecMemIQ) {
270      uopIdxVec.get(entryIdx)   := out.uopIdx.get
271    }
272  }
273}
274
275class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
276  val flush               = Flipped(ValidIO(new Redirect))
277  //enq
278  val enq                 = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
279  val og0Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
280  val og1Resp             = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
281  val finalIssueResp      = OptionWrapper(params.LdExuCnt > 0, Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle))))
282  //deq sel
283  val deqReady            = Vec(params.numDeq, Input(Bool()))
284  val deqSelOH            = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEntries.W))))
285  val enqEntryOldestSel   = Vec(params.numDeq, Flipped(ValidIO(UInt(params.numEnq.W))))
286  val othersEntryOldestSel= Vec(params.numDeq, Flipped(ValidIO(UInt((params.numEntries - params.numEnq).W))))
287  val subDeqRequest       = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
288  val subDeqSelOH         = OptionWrapper(params.deqFuSame, Vec(params.numDeq, Input(UInt(params.numEntries.W))))
289  // wakeup
290  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
291  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
292  val og0Cancel           = Input(ExuOH(backendParams.numExu))
293  val og1Cancel           = Input(ExuOH(backendParams.numExu))
294  val ldCancel            = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
295  //trans output
296  val transEntryDeqVec    = Vec(params.numEnq, ValidIO(new EntryBundle))
297  val transSelVec         = Output(Vec(params.numEnq, UInt((params.numEntries - params.numEnq).W)))
298  //entries status
299  val valid               = Output(UInt(params.numEntries.W))
300  val canIssue            = Output(UInt(params.numEntries.W))
301  val fuType              = Vec(params.numEntries, Output(FuType()))
302  val dataSources         = Vec(params.numEntries, Vec(params.numRegSrc, Output(DataSource())))
303  val srcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(ExuOH()))))
304  val srcTimer            = OptionWrapper(params.hasIQWakeUp, Vec(params.numEntries, Vec(params.numRegSrc, Output(UInt(3.W)))))
305  //deq status
306  val isFirstIssue        = Vec(params.numDeq, Output(Bool()))
307  val deqEntry            = Vec(params.numDeq, ValidIO(new EntryBundle))
308  val cancelDeqVec        = Vec(params.numDeq, Output(Bool()))
309  // mem only
310  val fromMem = if (params.isMemAddrIQ) Some(new Bundle {
311    val stIssuePtr        = Input(new SqPtr)
312    val memWaitUpdateReq  = Flipped(new MemWaitUpdateReq)
313    val slowResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
314    val fastResp          = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
315  }) else None
316  val vecMemIn = OptionWrapper(params.isVecMemIQ, new Bundle {
317    val sqDeqPtr = Input(new SqPtr)
318    val lqDeqPtr = Input(new LqPtr)
319  })
320
321  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
322  val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx())))
323
324  val rsFeedback          = Output(Vec(5, Bool()))
325
326  // debug
327  val cancel              = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool())))
328
329  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
330}
331