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