xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision b1e920234888fd3e5463ceb2a99c9bdca087f585)
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.{MemWaitUpdateReq, SqPtr, LqPtr}
16
17class StatusMemPart(implicit p:Parameters, params: IssueBlockParams) extends Bundle {
18  val waitForSqIdx = new SqPtr   // generated by store data valid check
19  val waitForRobIdx = new RobPtr // generated by store set
20  val waitForStd = Bool()
21  val strictWait = Bool()
22  val sqIdx = new SqPtr
23}
24
25class StatusVecMemPart(implicit p:Parameters, params: IssueBlockParams) extends Bundle {
26  val sqIdx = new SqPtr
27  val lqIdx = new LqPtr
28}
29
30class Status(implicit p:Parameters, params: IssueBlockParams) extends XSBundle {
31  val srcState = Vec(params.numRegSrc, SrcState())
32
33  val psrc = Vec(params.numRegSrc, UInt(params.rdPregIdxWidth.W))
34  val srcType = Vec(params.numRegSrc, SrcType())
35  val fuType = FuType()
36  val robIdx = new RobPtr
37  val uopIdx = OptionWrapper(params.isVecMemIQ, UopIdx())
38  val issued = Bool()           // for predict issue
39  val firstIssue = Bool()
40  val blocked = Bool()          // for some block reason
41  // read reg or get data from bypass network
42  val dataSources = Vec(params.numRegSrc, DataSource())
43  // if waked up by iq, set when waked up by iq
44  val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Vec(params.numRegSrc, ExuOH()))
45  // src timer, used by cancel signal. It increases every cycle after wakeup src inst issued.
46  val srcTimer = OptionWrapper(params.hasIQWakeUp, Vec(params.numRegSrc, UInt(3.W)))
47  val issueTimer = UInt(2.W)
48  val deqPortIdx = UInt(1.W)
49  val srcLoadDependency = OptionWrapper(params.hasIQWakeUp, Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W))))
50
51
52  // mem only
53  val mem = if (params.isMemAddrIQ) Some(new StatusMemPart) else None
54
55  // vector mem only
56  val vecMem = if (params.isVecMemIQ) Some(new StatusVecMemPart) else None
57
58  // need pc
59  val pc = if (params.needPc) Some(UInt(VAddrData().dataWidth.W)) else None
60
61  def srcReady: Bool = {
62    VecInit(srcState.map(SrcState.isReady)).asUInt.andR
63  }
64
65  def canIssue: Bool = {
66    srcReady && !issued && !blocked
67  }
68
69  def mergedLoadDependency = {
70    srcLoadDependency.map(_.map(_.toSeq).reduce({
71      case (l: Vec[UInt], r: Vec[UInt]) => VecInit(l.zip(r).map(x => x._1 | x._2))
72    }: (Vec[UInt], Vec[UInt]) => Vec[UInt]))
73  }
74}
75
76class EntryDeqRespBundle(implicit p:Parameters, params: IssueBlockParams) extends Bundle {
77  val robIdx = new RobPtr
78  val uopIdx = UopIdx()
79  val respType = RSFeedbackType()   // update credit if needs replay
80  val dataInvalidSqIdx = new SqPtr
81  val rfWen = Bool()
82  val fuType = FuType()
83}
84
85class EntryBundle(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
86  val status = new Status()
87  val imm = UInt(XLEN.W)
88  val payload = new DynInst()
89}
90
91class DeqBundle(implicit p:Parameters, params: IssueBlockParams) extends XSBundle {
92  val isFirstIssue = Output(Bool())
93  val deqSelOH = Flipped(ValidIO(UInt(params.numEntries.W)))
94}
95
96class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
97  val flush = Flipped(ValidIO(new Redirect))
98  // status
99  val valid = Output(UInt(params.numEntries.W))
100  val canIssue = Output(UInt(params.numEntries.W))
101  val clear = Output(UInt(params.numEntries.W))
102  val fuType = Output(Vec(params.numEntries, FuType()))
103  val dataSources = Output(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
104  val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, ExuOH()))))
105  val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W)))))
106  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
107  val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx())))
108  //enq
109  val enq = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
110  // wakeup
111  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
112  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
113  val og0Cancel = Input(ExuOH(backendParams.numExu))
114  val og1Cancel = Input(ExuOH(backendParams.numExu))
115  val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO))
116  //deq
117  val deq = Vec(params.numDeq, new DeqBundle)
118  val deqResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
119  val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
120  val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
121  val finalIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.LdExuCnt, Flipped(ValidIO(new EntryDeqRespBundle))))
122  val memAddrIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.LdExuCnt, Flipped(ValidIO(new EntryDeqRespBundle))))
123  val transEntryDeqVec = Vec(params.numEnq, ValidIO(new EntryBundle))
124  val deqEntry = Vec(params.numDeq, ValidIO(new EntryBundle))
125  val transSelVec = Output(Vec(params.numEnq, UInt((params.numEntries-params.numEnq).W)))
126
127
128  val rsFeedback = Output(Vec(5, Bool()))
129  // mem only
130  val fromMem = if (params.isMemAddrIQ) Some(new Bundle {
131    val stIssuePtr = Input(new SqPtr)
132    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
133    val slowResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
134    val fastResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
135  }) else None
136
137  // vector mem only
138  val fromLsq = OptionWrapper(params.isVecMemIQ, new Bundle {
139    val sqDeqPtr = Input(new SqPtr)
140    val lqDeqPtr = Input(new LqPtr)
141  })
142
143  // debug
144  val cancel = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool())))
145
146  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
147}
148
149class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
150  private val EnqEntryNum = params.numEnq
151  private val OthersEntryNum = params.numEntries - params.numEnq
152  val io = IO(new EntriesIO)
153
154  // only memAddrIQ use it
155  val memEtyResps: MixedVec[ValidIO[EntryDeqRespBundle]] = {
156    if (params.isLdAddrIQ && !params.isStAddrIQ)
157      MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.memAddrIssueResp.get ++ io.finalIssueResp.get)
158    else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ)
159      MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.memAddrIssueResp.get ++ io.finalIssueResp.get ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp)
160    else if (params.isMemAddrIQ)
161      MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp)
162    else MixedVecInit(Seq())
163  }
164
165  val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = VecInit(io.deqResp, io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.deqResp))
166
167  //Module
168  val enqEntries = Seq.fill(EnqEntryNum)(Module(EnqEntry(p, params)))
169  val othersEntries = Seq.fill(OthersEntryNum)(Module(OthersEntry(p, params)))
170  val transPolicy = Module(new EnqPolicy)
171
172  //Wire
173  val deqSelVec = Wire(Vec(params.numEntries, Bool()))
174  val transSelVec = Wire(Vec(EnqEntryNum, Vec(OthersEntryNum, Bool())))
175  val issueRespVec = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle)))
176  val transEntryDeqVec = Wire(Vec(EnqEntryNum, ValidIO(new EntryBundle)))
177  val transEntryEnqVec = Wire(Vec(OthersEntryNum, ValidIO(new EntryBundle)))
178  val entries = Wire(Vec(params.numEntries, ValidIO(new EntryBundle)))
179
180  val validVec = Wire(Vec(params.numEntries, Bool()))
181  val canIssueVec = Wire(Vec(params.numEntries, Bool()))
182  val clearVec = Wire(Vec(params.numEntries, Bool()))
183  val fuTypeVec = Wire(Vec(params.numEntries, FuType()))
184  val dataSourceVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
185  val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuOH()))))
186  val srcTimerVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W)))))
187  val isFirstIssueVec = Wire(Vec(params.numEntries, Bool()))
188  val robIdxVec = Wire(Vec(params.numEntries, new RobPtr))
189  val issueTimerVec = Wire(Vec(params.numEntries, UInt(2.W)))
190  val deqPortIdxWriteVec = Wire(Vec(params.numEntries, UInt(1.W)))
191  val deqPortIdxReadVec = Wire(Vec(params.numEntries, UInt(1.W)))
192  val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool())))
193  val uopIdxVec = OptionWrapper(params.isVecMemIQ, Wire(Vec(params.numEntries, UopIdx())))
194
195  io.transEntryDeqVec := transEntryDeqVec
196
197  //enqEntries
198  enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) =>
199    enqEntry.io.enq := io.enq(entryIdx)
200    enqEntry.io.flush := io.flush
201    enqEntry.io.wakeUpFromWB := io.wakeUpFromWB
202    enqEntry.io.wakeUpFromIQ := io.wakeUpFromIQ
203    enqEntry.io.og0Cancel := io.og0Cancel
204    enqEntry.io.og1Cancel := io.og1Cancel
205    enqEntry.io.ldCancel := io.ldCancel
206    enqEntry.io.deqSel := deqSelVec(entryIdx)
207    enqEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx)
208    enqEntry.io.transSel := transSelVec(entryIdx).asUInt.orR
209    enqEntry.io.issueResp := issueRespVec(entryIdx)
210    validVec(entryIdx) := enqEntry.io.valid
211    canIssueVec(entryIdx) := enqEntry.io.canIssue
212    clearVec(entryIdx) := enqEntry.io.clear
213    fuTypeVec(entryIdx) := enqEntry.io.fuType
214    dataSourceVec(entryIdx) := enqEntry.io.dataSource
215    robIdxVec(entryIdx) := enqEntry.io.robIdx
216    issueTimerVec(entryIdx) := enqEntry.io.issueTimerRead
217    deqPortIdxReadVec(entryIdx) := enqEntry.io.deqPortIdxRead
218    if (params.hasIQWakeUp) {
219      srcWakeUpL1ExuOHVec.get(entryIdx) := enqEntry.io.srcWakeUpL1ExuOH.get
220      srcTimerVec.get(entryIdx) := enqEntry.io.srcTimer.get
221      cancelVec.get(entryIdx) := enqEntry.io.cancel.get
222    }
223    transEntryDeqVec(entryIdx) := enqEntry.io.transEntry
224    isFirstIssueVec(entryIdx) := enqEntry.io.isFirstIssue
225    entries(entryIdx) := enqEntry.io.entry
226    //for mem
227    if (params.isMemAddrIQ) {
228      enqEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr
229      enqEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
230    }
231    if (params.isVecMemIQ) {
232      uopIdxVec.get(entryIdx) := enqEntry.io.uopIdx.get
233      enqEntry.io.fromLsq.get.sqDeqPtr := io.fromLsq.get.sqDeqPtr
234      enqEntry.io.fromLsq.get.lqDeqPtr := io.fromLsq.get.lqDeqPtr
235    }
236  }
237  //othersEntries
238  othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) =>
239    othersEntry.io.enq := transEntryEnqVec(entryIdx)
240    othersEntry.io.flush := io.flush
241    othersEntry.io.wakeUpFromWB := io.wakeUpFromWB
242    othersEntry.io.wakeUpFromIQ := io.wakeUpFromIQ
243    othersEntry.io.og0Cancel := io.og0Cancel
244    othersEntry.io.og1Cancel := io.og1Cancel
245    othersEntry.io.ldCancel := io.ldCancel
246    othersEntry.io.deqSel := deqSelVec(entryIdx + EnqEntryNum)
247    othersEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx + EnqEntryNum)
248    othersEntry.io.transSel := transSelVec.map(x => x(entryIdx)).reduce(_ | _)
249    othersEntry.io.issueResp := issueRespVec(entryIdx + EnqEntryNum)
250    validVec(entryIdx + EnqEntryNum) := othersEntry.io.valid
251    canIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.canIssue
252    clearVec(entryIdx + EnqEntryNum) := othersEntry.io.clear
253    fuTypeVec(entryIdx + EnqEntryNum) := othersEntry.io.fuType
254    dataSourceVec(entryIdx + EnqEntryNum) := othersEntry.io.dataSource
255    robIdxVec(entryIdx + EnqEntryNum) := othersEntry.io.robIdx
256    issueTimerVec(entryIdx + EnqEntryNum) := othersEntry.io.issueTimerRead
257    deqPortIdxReadVec(entryIdx + EnqEntryNum) := othersEntry.io.deqPortIdxRead
258    if (params.hasIQWakeUp) {
259      srcWakeUpL1ExuOHVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcWakeUpL1ExuOH.get
260      srcTimerVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcTimer.get
261      cancelVec.get(entryIdx + EnqEntryNum) := othersEntry.io.cancel.get
262    }
263    isFirstIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.isFirstIssue
264    entries(entryIdx + EnqEntryNum) := othersEntry.io.entry
265    //for mem
266    if (params.isMemAddrIQ) {
267      othersEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr
268      othersEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
269    }
270    if (params.isVecMemIQ) {
271      uopIdxVec.get(entryIdx + EnqEntryNum) := othersEntry.io.uopIdx.get
272      othersEntry.io.fromLsq.get.sqDeqPtr := io.fromLsq.get.sqDeqPtr
273      othersEntry.io.fromLsq.get.lqDeqPtr := io.fromLsq.get.lqDeqPtr
274    }
275  }
276
277
278  deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) =>
279    val deqVec = io.deq.map(x => x.deqSelOH.valid && x.deqSelOH.bits(i))
280    deqPortIdxWrite := OHToUInt(deqVec)
281    deqSel := deqVec.reduce(_ | _)
282  }
283
284
285  //transPolicy
286  transPolicy.io.valid := VecInit(validVec.slice(EnqEntryNum, params.numEntries)).asUInt
287  transSelVec.zip(transPolicy.io.enqSelOHVec).foreach { case (selBools, selOH) =>
288    selBools.zipWithIndex.foreach { case (selBool, i) =>
289      selBool := transPolicy.io.enqSelOHVec.map(_.valid).reduce(_ & _) && selOH.bits(i)
290    }
291  }
292
293  //transEntryEnq
294  transEntryEnqVec.zipWithIndex.foreach { case (transEntryEnq, othersIdx) =>
295    val transEnqHit = transSelVec.map(x => x(othersIdx))
296    transEntryEnq := Mux1H(transEnqHit, transEntryDeqVec)
297  }
298  dontTouch(transEntryEnqVec)
299
300  //issueRespVec
301  if (params.isVecMemIQ) {
302    // vector memory IQ
303    issueRespVec.zip(robIdxVec).zip(uopIdxVec.get).foreach { case ((issueResp, robIdx), uopIdx) =>
304      val hitRespsVec = VecInit(resps.flatten.map(x =>
305        x.valid && x.bits.robIdx === robIdx && x.bits.uopIdx === uopIdx
306      ))
307      issueResp.valid := hitRespsVec.reduce(_ | _)
308      issueResp.bits := Mux1H(hitRespsVec, resps.flatten.map(_.bits))
309    }
310  } else if (params.isMemAddrIQ) {
311    // scalar memory IQ
312    issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) =>
313      val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq)
314      issueResp.valid := hitRespsVec.reduce(_ | _)
315      issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)
316    }
317  }
318  else {
319    issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) =>
320      val Resp = resps(issueTimer)(deqPortIdx)
321      issueResp := Resp
322    }
323  }
324
325  io.valid := validVec.asUInt
326  io.canIssue := canIssueVec.asUInt
327  io.clear := clearVec.asUInt
328  io.fuType := fuTypeVec
329  io.dataSources := dataSourceVec
330  io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get)
331  io.srcTimer.foreach(_ := srcTimerVec.get)
332  io.cancel.foreach(_ := cancelVec.get)
333  io.robIdx.foreach(_ := robIdxVec)
334  io.uopIdx.foreach(_ := uopIdxVec.get)
335  io.rsFeedback := 0.U.asTypeOf(io.rsFeedback) //todo
336  io.deq.foreach{ x =>
337    x.isFirstIssue := Mux(x.deqSelOH.valid, Mux1H(x.deqSelOH.bits, isFirstIssueVec), false.B)
338  }
339  dontTouch(io.deq)
340  io.deqEntry.zip(io.deq.map(_.deqSelOH)).foreach{ case (deqEntry, deqSelOH) =>
341    deqEntry.valid := deqSelOH.valid && entries(OHToUInt(deqSelOH.bits)).valid
342    deqEntry.bits := entries(OHToUInt(deqSelOH.bits)).bits
343  }
344  io.transSelVec.zip(transSelVec).foreach { case (sink, source) =>
345    sink := source.asUInt
346  }
347}
348