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