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