xref: /XiangShan/src/main/scala/xiangshan/backend/issue/Entries.scala (revision 7531c765d87d92e3c772b0d55aa810c2041ba3e3)
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 respType = RSFeedbackType()   // update credit if needs replay
79  val dataInvalidSqIdx = new SqPtr
80  val rfWen = Bool()
81  val fuType = FuType()
82}
83
84class EntryBundle(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
85  val status = new Status()
86  val imm = UInt(XLEN.W)
87  val payload = new DynInst()
88}
89
90class DeqBundle(implicit p:Parameters, params: IssueBlockParams) extends XSBundle {
91  val isFirstIssue = Output(Bool())
92  val deqSelOH = Flipped(ValidIO(UInt(params.numEntries.W)))
93}
94
95class EntriesIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
96  val flush = Flipped(ValidIO(new Redirect))
97  // status
98  val valid = Output(UInt(params.numEntries.W))
99  val canIssue = Output(UInt(params.numEntries.W))
100  val clear = Output(UInt(params.numEntries.W))
101  val fuType = Output(Vec(params.numEntries, FuType()))
102  val dataSources = Output(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
103  val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, ExuOH()))))
104  val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W)))))
105  val robIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, new RobPtr)))
106  val uopIdx = OptionWrapper(params.isVecMemIQ, Output(Vec(params.numEntries, UopIdx())))
107  //enq
108  val enq = Vec(params.numEnq, Flipped(ValidIO(new EntryBundle)))
109  // wakeup
110  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
111  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
112  val og0Cancel = Input(ExuOH(backendParams.numExu))
113  val og1Cancel = Input(ExuOH(backendParams.numExu))
114  val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO))
115  //deq
116  val deq = Vec(params.numDeq, new DeqBundle)
117  val deqResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
118  val og0Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
119  val og1Resp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
120  val finalIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.LdExuCnt, Flipped(ValidIO(new EntryDeqRespBundle))))
121  val memAddrIssueResp = OptionWrapper(params.LdExuCnt > 0, Vec(params.LdExuCnt, Flipped(ValidIO(new EntryDeqRespBundle))))
122  val transEntryDeqVec = Vec(params.numEnq, ValidIO(new EntryBundle))
123  val deqEntry = Vec(params.numDeq, ValidIO(new EntryBundle))
124  val transSelVec = Output(Vec(params.numEnq, UInt((params.numEntries-params.numEnq).W)))
125
126
127  val rsFeedback = Output(Vec(5, Bool()))
128  // mem only
129  val fromMem = if (params.isMemAddrIQ) Some(new Bundle {
130    val stIssuePtr = Input(new SqPtr)
131    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
132    val slowResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
133    val fastResp = Vec(params.numDeq, Flipped(ValidIO(new EntryDeqRespBundle)))
134  }) else None
135
136  // vector mem only
137  val fromLsq = OptionWrapper(params.isVecMemIQ, new Bundle {
138    val sqDeqPtr = Input(new SqPtr)
139    val lqDeqPtr = Input(new LqPtr)
140  })
141
142  // debug
143  val cancel = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numEntries, Bool())))
144
145  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
146}
147
148class Entries(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
149  private val EnqEntryNum = params.numEnq
150  private val OthersEntryNum = params.numEntries - params.numEnq
151  val io = IO(new EntriesIO)
152
153  // only memAddrIQ use it
154  val memEtyResps: MixedVec[ValidIO[EntryDeqRespBundle]] = {
155    if (params.isLdAddrIQ && !params.isStAddrIQ)
156      MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.memAddrIssueResp.get ++ io.finalIssueResp.get)
157    else if (params.isLdAddrIQ && params.isStAddrIQ || params.isHyAddrIQ)
158      MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.memAddrIssueResp.get ++ io.finalIssueResp.get ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp)
159    else if (params.isMemAddrIQ)
160      MixedVecInit(io.deqResp ++ io.og0Resp ++ io.og1Resp ++ io.fromMem.get.fastResp ++ io.fromMem.get.slowResp)
161    else MixedVecInit(Seq())
162  }
163
164  val resps: Vec[Vec[ValidIO[EntryDeqRespBundle]]] = VecInit(io.deqResp, io.og0Resp, io.og1Resp, 0.U.asTypeOf(io.deqResp))
165
166  //Module
167  val enqEntries = Seq.fill(EnqEntryNum)(Module(EnqEntry(p, params)))
168  val othersEntries = Seq.fill(OthersEntryNum)(Module(OthersEntry(p, params)))
169  val transPolicy = Module(new EnqPolicy)
170
171  //Wire
172  val deqSelVec = Wire(Vec(params.numEntries, Bool()))
173  val transSelVec = Wire(Vec(EnqEntryNum, Vec(OthersEntryNum, Bool())))
174  val issueRespVec = Wire(Vec(params.numEntries, ValidIO(new EntryDeqRespBundle)))
175  val transEntryDeqVec = Wire(Vec(EnqEntryNum, ValidIO(new EntryBundle)))
176  val transEntryEnqVec = Wire(Vec(OthersEntryNum, ValidIO(new EntryBundle)))
177  val entries = Wire(Vec(params.numEntries, ValidIO(new EntryBundle)))
178
179  val validVec = Wire(Vec(params.numEntries, Bool()))
180  val canIssueVec = Wire(Vec(params.numEntries, Bool()))
181  val clearVec = Wire(Vec(params.numEntries, Bool()))
182  val fuTypeVec = Wire(Vec(params.numEntries, FuType()))
183  val dataSourceVec = Wire(Vec(params.numEntries, Vec(params.numRegSrc, DataSource())))
184  val srcWakeUpL1ExuOHVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, ExuOH()))))
185  val srcTimerVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Vec(params.numRegSrc, UInt(3.W)))))
186  val isFirstIssueVec = Wire(Vec(params.numEntries, Bool()))
187  val robIdxVec = Wire(Vec(params.numEntries, new RobPtr))
188  val issueTimerVec = Wire(Vec(params.numEntries, UInt(2.W)))
189  val deqPortIdxWriteVec = Wire(Vec(params.numEntries, UInt(1.W)))
190  val deqPortIdxReadVec = Wire(Vec(params.numEntries, UInt(1.W)))
191  val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numEntries, Bool())))
192  val uopIdxVec = OptionWrapper(params.isVecMemIQ, Wire(Vec(params.numEntries, UopIdx())))
193
194  io.transEntryDeqVec := transEntryDeqVec
195
196  //enqEntries
197  enqEntries.zipWithIndex.foreach { case (enqEntry, entryIdx) =>
198    enqEntry.io.enq := io.enq(entryIdx)
199    enqEntry.io.flush := io.flush
200    enqEntry.io.wakeUpFromWB := io.wakeUpFromWB
201    enqEntry.io.wakeUpFromIQ := io.wakeUpFromIQ
202    enqEntry.io.og0Cancel := io.og0Cancel
203    enqEntry.io.og1Cancel := io.og1Cancel
204    enqEntry.io.ldCancel := io.ldCancel
205    enqEntry.io.deqSel := deqSelVec(entryIdx)
206    enqEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx)
207    enqEntry.io.transSel := transSelVec(entryIdx).asUInt.orR
208    enqEntry.io.issueResp := issueRespVec(entryIdx)
209    validVec(entryIdx) := enqEntry.io.valid
210    canIssueVec(entryIdx) := enqEntry.io.canIssue
211    clearVec(entryIdx) := enqEntry.io.clear
212    fuTypeVec(entryIdx) := enqEntry.io.fuType
213    dataSourceVec(entryIdx) := enqEntry.io.dataSource
214    robIdxVec(entryIdx) := enqEntry.io.robIdx
215    issueTimerVec(entryIdx) := enqEntry.io.issueTimerRead
216    deqPortIdxReadVec(entryIdx) := enqEntry.io.deqPortIdxRead
217    if (params.hasIQWakeUp) {
218      srcWakeUpL1ExuOHVec.get(entryIdx) := enqEntry.io.srcWakeUpL1ExuOH.get
219      srcTimerVec.get(entryIdx) := enqEntry.io.srcTimer.get
220      cancelVec.get(entryIdx) := enqEntry.io.cancel.get
221    }
222    transEntryDeqVec(entryIdx) := enqEntry.io.transEntry
223    isFirstIssueVec(entryIdx) := enqEntry.io.isFirstIssue
224    entries(entryIdx) := enqEntry.io.entry
225    //for mem
226    if (params.isMemAddrIQ) {
227      enqEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr
228      enqEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
229    }
230    if (params.isVecMemIQ) {
231      uopIdxVec.get(entryIdx) := enqEntry.io.uopIdx.get
232      enqEntry.io.fromLsq.get.sqDeqPtr := io.fromLsq.get.sqDeqPtr
233      enqEntry.io.fromLsq.get.lqDeqPtr := io.fromLsq.get.lqDeqPtr
234    }
235  }
236  //othersEntries
237  othersEntries.zipWithIndex.foreach { case (othersEntry, entryIdx) =>
238    othersEntry.io.enq := transEntryEnqVec(entryIdx)
239    othersEntry.io.flush := io.flush
240    othersEntry.io.wakeUpFromWB := io.wakeUpFromWB
241    othersEntry.io.wakeUpFromIQ := io.wakeUpFromIQ
242    othersEntry.io.og0Cancel := io.og0Cancel
243    othersEntry.io.og1Cancel := io.og1Cancel
244    othersEntry.io.ldCancel := io.ldCancel
245    othersEntry.io.deqSel := deqSelVec(entryIdx + EnqEntryNum)
246    othersEntry.io.deqPortIdxWrite := deqPortIdxWriteVec(entryIdx + EnqEntryNum)
247    othersEntry.io.transSel := transSelVec.map(x => x(entryIdx)).reduce(_ | _)
248    othersEntry.io.issueResp := issueRespVec(entryIdx + EnqEntryNum)
249    validVec(entryIdx + EnqEntryNum) := othersEntry.io.valid
250    canIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.canIssue
251    clearVec(entryIdx + EnqEntryNum) := othersEntry.io.clear
252    fuTypeVec(entryIdx + EnqEntryNum) := othersEntry.io.fuType
253    dataSourceVec(entryIdx + EnqEntryNum) := othersEntry.io.dataSource
254    robIdxVec(entryIdx + EnqEntryNum) := othersEntry.io.robIdx
255    issueTimerVec(entryIdx + EnqEntryNum) := othersEntry.io.issueTimerRead
256    deqPortIdxReadVec(entryIdx + EnqEntryNum) := othersEntry.io.deqPortIdxRead
257    if (params.hasIQWakeUp) {
258      srcWakeUpL1ExuOHVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcWakeUpL1ExuOH.get
259      srcTimerVec.get(entryIdx + EnqEntryNum) := othersEntry.io.srcTimer.get
260      cancelVec.get(entryIdx + EnqEntryNum) := othersEntry.io.cancel.get
261    }
262    isFirstIssueVec(entryIdx + EnqEntryNum) := othersEntry.io.isFirstIssue
263    entries(entryIdx + EnqEntryNum) := othersEntry.io.entry
264    //for mem
265    if (params.isMemAddrIQ) {
266      othersEntry.io.fromMem.get.stIssuePtr := io.fromMem.get.stIssuePtr
267      othersEntry.io.fromMem.get.memWaitUpdateReq := io.fromMem.get.memWaitUpdateReq
268    }
269    if (params.isVecMemIQ) {
270      uopIdxVec.get(entryIdx + EnqEntryNum) := othersEntry.io.uopIdx.get
271      othersEntry.io.fromLsq.get.sqDeqPtr := io.fromLsq.get.sqDeqPtr
272      othersEntry.io.fromLsq.get.lqDeqPtr := io.fromLsq.get.lqDeqPtr
273    }
274  }
275
276
277  deqSelVec.zip(deqPortIdxWriteVec).zipWithIndex.foreach { case ((deqSel, deqPortIdxWrite), i) =>
278    val deqVec = io.deq.map(x => x.deqSelOH.valid && x.deqSelOH.bits(i))
279    deqPortIdxWrite := OHToUInt(deqVec)
280    deqSel := deqVec.reduce(_ | _)
281  }
282
283
284  //transPolicy
285  transPolicy.io.valid := VecInit(validVec.slice(EnqEntryNum, params.numEntries)).asUInt
286  transSelVec.zip(transPolicy.io.enqSelOHVec).foreach { case (selBools, selOH) =>
287    selBools.zipWithIndex.foreach { case (selBool, i) =>
288      selBool := transPolicy.io.enqSelOHVec.map(_.valid).reduce(_ & _) && selOH.bits(i)
289    }
290  }
291
292  //transEntryEnq
293  transEntryEnqVec.zipWithIndex.foreach { case (transEntryEnq, othersIdx) =>
294    val transEnqHit = transSelVec.map(x => x(othersIdx))
295    transEntryEnq := Mux1H(transEnqHit, transEntryDeqVec)
296  }
297  dontTouch(transEntryEnqVec)
298
299  //issueRespVec
300  if(params.isMemAddrIQ){
301    issueRespVec.zip(robIdxVec).foreach { case (issueResp, robIdx) =>
302      val hitRespsVec = VecInit(memEtyResps.map(x => x.valid && (x.bits.robIdx === robIdx)).toSeq)
303      issueResp.valid := hitRespsVec.reduce(_ | _)
304      issueResp.bits := Mux1H(hitRespsVec, memEtyResps.map(_.bits).toSeq)
305    }
306  }
307  else {
308    issueRespVec.zip(issueTimerVec).zip(deqPortIdxReadVec).foreach { case ((issueResp, issueTimer), deqPortIdx) =>
309      val Resp = resps(issueTimer)(deqPortIdx)
310      issueResp := Resp
311    }
312  }
313
314  io.valid := validVec.asUInt
315  io.canIssue := canIssueVec.asUInt
316  io.clear := clearVec.asUInt
317  io.fuType := fuTypeVec
318  io.dataSources := dataSourceVec
319  io.srcWakeUpL1ExuOH.foreach(_ := srcWakeUpL1ExuOHVec.get)
320  io.srcTimer.foreach(_ := srcTimerVec.get)
321  io.cancel.foreach(_ := cancelVec.get)
322  io.robIdx.foreach(_ := robIdxVec)
323  io.uopIdx.foreach(_ := uopIdxVec.get)
324  io.rsFeedback := 0.U.asTypeOf(io.rsFeedback) //todo
325  io.deq.foreach{ x =>
326    x.isFirstIssue := Mux(x.deqSelOH.valid, Mux1H(x.deqSelOH.bits, isFirstIssueVec), false.B)
327  }
328  dontTouch(io.deq)
329  io.deqEntry.zip(io.deq.map(_.deqSelOH)).foreach{ case (deqEntry, deqSelOH) =>
330    deqEntry.valid := deqSelOH.valid && entries(OHToUInt(deqSelOH.bits)).valid
331    deqEntry.bits := entries(OHToUInt(deqSelOH.bits)).bits
332  }
333  io.transSelVec.zip(transSelVec).foreach { case (sink, source) =>
334    sink := source.asUInt
335  }
336}
337