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