xref: /XiangShan/src/main/scala/xiangshan/backend/issue/EnqEntry.scala (revision 83ba63b34cf09b33c0a9e1b3203138e51af4491b)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.HasCircularQueuePtrHelper
7import utils.{MathUtils, OptionWrapper}
8import xiangshan._
9import xiangshan.backend.Bundles._
10import xiangshan.backend.fu.FuType
11import xiangshan.backend.datapath.DataSource
12import xiangshan.backend.rob.RobPtr
13import xiangshan.mem.{MemWaitUpdateReq, SqPtr}
14
15
16class EnqEntryIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
17  //input
18  val enq = Flipped(ValidIO(new EntryBundle))
19  val flush = Flipped(ValidIO(new Redirect))
20  val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
21  val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
22  val og0Cancel = Input(ExuVec(backendParams.numExu))
23  val og1Cancel = Input(ExuVec(backendParams.numExu))
24  val ldCancel = Vec(backendParams.LduCnt, Flipped(new LoadCancelIO))
25  val deqSel = Input(Bool())
26  val deqPortIdxWrite = Input(UInt(1.W))
27  val transSel = Input(Bool())
28  val issueResp = Flipped(ValidIO(new EntryDeqRespBundle))
29  //output
30  val valid = Output(Bool())
31  val canIssue = Output(Bool())
32  val clear = Output(Bool())
33  val fuType = Output(FuType())
34  val dataSource = Output(Vec(params.numRegSrc, DataSource()))
35  val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, ExuVec())))
36  val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, UInt(3.W))))
37  val transEntry =  ValidIO(new EntryBundle)
38  val isFirstIssue = Output(Bool())
39  val entry = ValidIO(new EntryBundle)
40  val robIdx = Output(new RobPtr)
41  val deqPortIdxRead = Output(UInt(1.W))
42  val issueTimerRead = Output(UInt(2.W))
43  // mem only
44  val fromMem = if(params.isMemAddrIQ) Some(new Bundle {
45    val stIssuePtr = Input(new SqPtr)
46    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
47  }) else None
48  // debug
49  val cancel = OptionWrapper(params.hasIQWakeUp, Output(Bool()))
50
51  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
52}
53
54class EnqEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
55  val io = IO(new EnqEntryIO)
56
57  val validReg = RegInit(false.B)
58  val entryReg = Reg(new EntryBundle)
59
60  val validRegNext = Wire(Bool())
61  val entryRegNext = Wire(new EntryBundle)
62  val entryUpdate = Wire(new EntryBundle)
63  val enqReady = Wire(Bool())
64  val clear = Wire(Bool())
65  val flushed = Wire(Bool())
66  val deqSuccess = Wire(Bool())
67  val srcWakeUp = Wire(Vec(params.numRegSrc, Bool()))
68  val srcCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
69  val srcLoadCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
70  val srcWakeUpByIQVec = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool())))
71  val wakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W))))
72  val shiftedWakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W))))
73  val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
74
75  //Reg
76  validReg := validRegNext
77  entryReg := entryRegNext
78
79  //Wire
80  when(io.enq.valid && enqReady) {
81    validRegNext := true.B
82  }.elsewhen(clear) {
83    validRegNext := false.B
84  }.otherwise {
85    validRegNext := validReg
86  }
87
88  when(io.enq.valid && enqReady) {
89    entryRegNext := io.enq.bits
90  }.otherwise {
91    entryRegNext := entryUpdate
92  }
93
94  enqReady := !validReg || clear
95  clear := flushed || io.transSel || deqSuccess
96  flushed := entryReg.status.robIdx.needFlush(io.flush)
97  deqSuccess := io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.fuIdle && !srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B)
98  srcWakeUp := io.wakeup.map(bundle => bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)).transpose.map(x => VecInit(x.toSeq).asUInt.orR).toSeq
99
100  shiftedWakeupLoadDependencyByIQVec
101    .zip(wakeupLoadDependencyByIQVec)
102    .zip(params.wakeUpInExuSources.map(_.name)).foreach {
103    case ((deps, originalDeps), name) => deps.zip(originalDeps).zipWithIndex.foreach {
104      case ((dep, originalDep), deqPortIdx) =>
105        if (name.contains("LDU") && name.replace("LDU", "").toInt == deqPortIdx)
106          dep := (originalDep << 1).asUInt | 1.U
107        else
108          dep := originalDep << 1
109    }
110  }
111
112  if (params.hasIQWakeUp) {
113    srcCancelVec.get.zip(srcLoadCancelVec.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach { case (((srcCancel, srcLoadCancel), wakeUpByIQVec), srcIdx) =>
114      // level1 cancel: A(s)->C, A(s) are the level1 cancel
115      val l1Cancel = (io.og0Cancel.asUInt & entryReg.status.srcWakeUpL1ExuOH.get(srcIdx).asUInt).orR &&
116        entryReg.status.srcTimer.get(srcIdx) === 1.U
117      val ldTransCancel = Mux(
118        wakeUpByIQVec.asUInt.orR,
119        Mux1H(wakeUpByIQVec, wakeupLoadDependencyByIQVec.map(dep => LoadShouldCancel(Some(dep), io.ldCancel))),
120        false.B
121      )
122      srcLoadCancel := LoadShouldCancel(entryReg.status.srcLoadDependency.map(_(srcIdx)), io.ldCancel)
123      srcCancel := l1Cancel || srcLoadCancel || ldTransCancel
124    }
125  }
126
127  if (io.wakeUpFromIQ.isEmpty) {
128    srcWakeUpByIQVec := 0.U.asTypeOf(srcWakeUpByIQVec)
129    wakeupLoadDependencyByIQVec := 0.U.asTypeOf(wakeupLoadDependencyByIQVec)
130  } else {
131    val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.wakeUpFromIQ.map((bundle: ValidIO[IssueQueueIQWakeUpBundle]) =>
132      bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)
133    ).toIndexedSeq.transpose
134    srcWakeUpByIQVec := wakeupVec.map(x => VecInit(x))
135    wakeupLoadDependencyByIQVec := io.wakeUpFromIQ.map(_.bits.loadDependency).toSeq
136  }
137
138  //entryUpdate
139  entryUpdate.status.srcState.zip(entryReg.status.srcState).zip(srcWakeUp).zipWithIndex.foreach { case (((stateNext, state), wakeup), srcIdx) =>
140    val cancel = srcCancelVec.map(_ (srcIdx)).getOrElse(false.B)
141    stateNext := Mux(cancel, false.B, wakeup | state)
142    if (params.hasIQWakeUp) {
143      cancelVec.get(srcIdx) := cancel
144    }
145  }
146  entryUpdate.status.dataSources.zip(entryReg.status.dataSources).zip(srcWakeUpByIQVec).foreach {
147    case ((dataSourceNext: DataSource, dataSource: DataSource), wakeUpByIQOH: Vec[Bool]) =>
148      when(wakeUpByIQOH.asUInt.orR) {
149        dataSourceNext.value := DataSource.forward
150      }.elsewhen(dataSource.value === DataSource.forward) {
151        dataSourceNext.value := DataSource.bypass
152      }.otherwise {
153        dataSourceNext.value := DataSource.reg
154      }
155  }
156  if (params.hasIQWakeUp) {
157    entryUpdate.status.srcWakeUpL1ExuOH.get.zip(srcWakeUpByIQVec).zip(srcWakeUp).zipWithIndex.foreach {
158      case (((exuOH: Vec[Bool], wakeUpByIQOH: Vec[Bool]), wakeUp: Bool), srcIdx) =>
159        when(wakeUpByIQOH.asUInt.orR) {
160          exuOH := Mux1H(wakeUpByIQOH, io.wakeUpFromIQ.map(x => MathUtils.IntToOH(x.bits.exuIdx).U(backendParams.numExu.W)).toSeq).asBools
161        }.elsewhen(wakeUp) {
162          exuOH := 0.U.asTypeOf(exuOH)
163        }.otherwise {
164          exuOH := entryReg.status.srcWakeUpL1ExuOH.get(srcIdx)
165        }
166    }
167    entryUpdate.status.srcTimer.get.zip(entryReg.status.srcTimer.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach {
168      case (((srcIssuedTimerNext, srcIssuedTimer), wakeUpByIQOH: Vec[Bool]), srcIdx) =>
169        srcIssuedTimerNext := MuxCase(0.U, Seq(
170          // T0: waked up by IQ, T1: reset timer as 1
171          wakeUpByIQOH.asUInt.orR -> 1.U,
172          // do not overflow
173          srcIssuedTimer.andR -> srcIssuedTimer,
174          // T2+: increase if the entry is valid, the src is ready, and the src is woken up by iq
175          (validReg && SrcState.isReady(entryReg.status.srcState(srcIdx)) && entryReg.status.srcWakeUpL1ExuOH.get.asUInt.orR) -> (srcIssuedTimer + 1.U)
176        ))
177    }
178    entryUpdate.status.srcLoadDependency.get.zip(entryReg.status.srcLoadDependency.get).zip(srcWakeUpByIQVec).zip(srcWakeUp).foreach {
179      case (((loadDependencyNext, loadDependency), wakeUpByIQVec), wakeup) =>
180        loadDependencyNext :=
181          Mux(wakeup,
182            Mux(wakeUpByIQVec.asUInt.orR, Mux1H(wakeUpByIQVec, shiftedWakeupLoadDependencyByIQVec), 0.U.asTypeOf(loadDependency)),
183            Mux(validReg && loadDependency.asUInt.orR, VecInit(loadDependency.map(i => i(i.getWidth - 2, 0) << 1)), loadDependency)
184          )
185    }
186  }
187  entryUpdate.status.issueTimer := "b11".U //otherwise
188  entryUpdate.status.deqPortIdx := 0.U //otherwise
189  when(io.deqSel) {
190    entryUpdate.status.issueTimer := 1.U
191    entryUpdate.status.deqPortIdx := io.deqPortIdxWrite
192  }.elsewhen(entryReg.status.issued){
193    entryUpdate.status.issueTimer := entryReg.status.issueTimer + 1.U
194    entryUpdate.status.deqPortIdx := entryReg.status.deqPortIdx
195  }
196  entryUpdate.status.psrc := entryReg.status.psrc
197  entryUpdate.status.srcType := entryReg.status.srcType
198  entryUpdate.status.fuType := entryReg.status.fuType
199  entryUpdate.status.robIdx := entryReg.status.robIdx
200  entryUpdate.status.issued := entryReg.status.issued // otherwise
201  when(!entryReg.status.srcReady){
202    entryUpdate.status.issued := false.B
203  }.elsewhen(srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B)) {
204    entryUpdate.status.issued := false.B
205  }.elsewhen(io.issueResp.valid) {
206    when(RSFeedbackType.isStageSuccess(io.issueResp.bits.respType)) {
207      entryUpdate.status.issued := true.B
208    }.elsewhen(RSFeedbackType.isBlocked(io.issueResp.bits.respType)) {
209      entryUpdate.status.issued := false.B
210    }
211  }
212  entryUpdate.status.firstIssue := io.deqSel || entryReg.status.firstIssue
213  entryUpdate.status.blocked := false.B //todo
214  //remain imm and payload
215  entryUpdate.imm := entryReg.imm
216  entryUpdate.payload := entryReg.payload
217  if(params.needPc) {
218    entryUpdate.status.pc.get := entryReg.status.pc.get
219  }
220
221  //output
222  io.transEntry.valid := validReg && io.transSel && !flushed && !deqSuccess
223  io.transEntry.bits := entryUpdate
224  io.canIssue := entryReg.status.canIssue && validReg
225  io.clear := clear
226  io.fuType := entryReg.status.fuType
227  io.dataSource := entryReg.status.dataSources
228  io.srcWakeUpL1ExuOH.foreach(_ := entryReg.status.srcWakeUpL1ExuOH.get)
229  io.srcTimer.foreach(_ := entryReg.status.srcTimer.get)
230  io.valid := validReg
231  io.isFirstIssue := !entryReg.status.firstIssue
232  io.entry.valid := validReg
233  io.entry.bits := entryReg
234  io.robIdx := entryReg.status.robIdx
235  io.issueTimerRead := Mux(io.deqSel, 0.U, entryReg.status.issueTimer)
236  io.deqPortIdxRead := Mux(io.deqSel, io.deqPortIdxWrite, entryReg.status.deqPortIdx)
237  io.cancel.foreach(_ := cancelVec.get.asUInt.orR)
238}
239
240class EnqEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry
241  with HasCircularQueuePtrHelper {
242  val fromMem = io.fromMem.get
243
244  val memStatus = entryReg.status.mem.get
245  println("memStatus" + memStatus)
246  val memStatusNext = entryRegNext.status.mem.get
247  val memStatusUpdate = entryUpdate.status.mem.get
248
249  // load cannot be issued before older store, unless meet some condition
250  val blockedByOlderStore = isAfter(memStatusNext.sqIdx, fromMem.stIssuePtr)
251
252  val deqFailedForStdInvalid = io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.dataInvalid
253
254  val staWaitedReleased = Cat(
255    fromMem.memWaitUpdateReq.robIdx.map(x => x.valid && x.bits.value === memStatusNext.waitForRobIdx.value)
256  ).orR
257  val stdWaitedReleased = Cat(
258    fromMem.memWaitUpdateReq.sqIdx.map(x => x.valid && x.bits.value === memStatusNext.waitForSqIdx.value)
259  ).orR
260  val olderStaNotViolate = staWaitedReleased && !memStatusNext.strictWait
261  val olderStdReady = stdWaitedReleased && memStatusNext.waitForStd
262  val waitStd = !olderStdReady
263  val waitSta = !olderStaNotViolate
264
265  when (io.enq.valid && enqReady) {
266    memStatusNext.waitForSqIdx := io.enq.bits.status.mem.get.waitForSqIdx
267    // update by lfst at dispatch stage
268    memStatusNext.waitForRobIdx := io.enq.bits.status.mem.get.waitForRobIdx
269    // new load inst don't known if it is blocked by store data ahead of it
270    memStatusNext.waitForStd := false.B
271    // update by ssit at rename stage
272    memStatusNext.strictWait := io.enq.bits.status.mem.get.strictWait
273    memStatusNext.sqIdx := io.enq.bits.status.mem.get.sqIdx
274  }.otherwise {
275    memStatusNext := memStatusUpdate
276  }
277
278  when(deqFailedForStdInvalid) {
279    memStatusUpdate.waitForSqIdx := io.issueResp.bits.dataInvalidSqIdx
280    memStatusUpdate.waitForRobIdx := memStatus.waitForRobIdx
281    memStatusUpdate.waitForStd := true.B
282    memStatusUpdate.strictWait := memStatus.strictWait
283    memStatusUpdate.sqIdx := memStatus.sqIdx
284  }.otherwise {
285    memStatusUpdate := memStatus
286  }
287
288  val shouldBlock = Mux(io.enq.valid && enqReady, io.enq.bits.status.blocked, entryReg.status.blocked)
289  val blockNotReleased = waitStd || waitSta
290  val respBlock = deqFailedForStdInvalid
291  entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock
292  entryUpdate.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock
293
294}
295
296object EnqEntry {
297  def apply(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = {
298    iqParams.schdType match {
299      case IntScheduler() => new EnqEntry()
300      case MemScheduler() =>
301        if (iqParams.StdCnt == 0) new EnqEntryMem()
302        else new EnqEntry()
303      case VfScheduler() => new EnqEntry()
304      case _ => null
305    }
306  }
307}