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