xref: /XiangShan/src/main/scala/xiangshan/backend/issue/OthersEntry.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}
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, LqPtr}
14
15
16class OthersEntryIO(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(ExuOH(backendParams.numExu))
23  val og1Cancel = Input(ExuOH(backendParams.numExu))
24  val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO))
25  val deqSel = Input(Bool())
26  val transSel = Input(Bool())
27  val issueResp = Flipped(ValidIO(new EntryDeqRespBundle))
28  val deqPortIdxWrite = Input(UInt(1.W))
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, ExuOH())))
36  val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, UInt(3.W))))
37  val isFirstIssue = Output(Bool())
38  val entry = ValidIO(new EntryBundle)
39  val robIdx = Output(new RobPtr)
40  val uopIdx = OptionWrapper(params.isVecMemIQ, Output(UopIdx()))
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  // vector mem only
49  val fromLsq = OptionWrapper(params.isVecMemIQ, new Bundle {
50    val sqDeqPtr = Input(new SqPtr)
51    val lqDeqPtr = Input(new LqPtr)
52  })
53  // debug
54  val cancel = OptionWrapper(params.hasIQWakeUp, Output(Bool()))
55
56  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
57}
58
59class OthersEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
60  val io = IO(new OthersEntryIO)
61
62  val validReg = RegInit(false.B)
63  val entryReg = Reg(new EntryBundle)
64
65  val validRegNext = Wire(Bool())
66  val entryRegNext = Wire(new EntryBundle)
67  val flushed = Wire(Bool())
68  val clear = Wire(Bool())
69  val deqSuccess = Wire(Bool())
70  val srcWakeUp = Wire(Vec(params.numRegSrc, Bool()))
71  val srcCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
72  val srcLoadCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
73  val srcWakeUpByIQVec = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool())))
74  val wakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W))))
75  val shiftedWakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W))))
76  val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
77
78  //Reg
79  validReg := validRegNext
80  entryReg := entryRegNext
81
82  //Wire
83  flushed := entryReg.status.robIdx.needFlush(io.flush)
84  clear := flushed || deqSuccess
85  deqSuccess := io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.fuIdle && !srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B)
86  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
87
88  shiftedWakeupLoadDependencyByIQVec
89    .zip(wakeupLoadDependencyByIQVec)
90    .zip(params.wakeUpInExuSources.map(_.name)).foreach {
91    case ((deps, originalDeps), name) => deps.zip(originalDeps).zipWithIndex.foreach {
92      case ((dep, originalDep), deqPortIdx) =>
93        if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx)
94          dep := originalDep << 1 | 1.U
95        else
96          dep := originalDep << 1
97    }
98  }
99
100  when(io.enq.valid && io.transSel) {
101    validRegNext := true.B
102  }.elsewhen(clear) {
103    validRegNext := false.B
104  }.otherwise {
105    validRegNext := validReg
106  }
107
108  if (params.hasIQWakeUp) {
109    srcCancelVec.get.zip(srcLoadCancelVec.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach { case (((srcCancel, srcLoadCancel), wakeUpByIQVec), srcIdx) =>
110      // level1 cancel: A(s)->C, A(s) are the level1 cancel
111      val l1Cancel = (io.og0Cancel.asUInt & entryReg.status.srcWakeUpL1ExuOH.get(srcIdx).asUInt).orR &&
112        entryReg.status.srcTimer.get(srcIdx) === 1.U
113      val ldTransCancel = Mux(
114        wakeUpByIQVec.asUInt.orR,
115        Mux1H(wakeUpByIQVec, wakeupLoadDependencyByIQVec.map(dep => LoadShouldCancel(Some(dep), io.ldCancel))),
116        false.B
117      )
118      srcLoadCancel := LoadShouldCancel(entryReg.status.srcLoadDependency.map(_(srcIdx)), io.ldCancel)
119      srcCancel := l1Cancel || srcLoadCancel || ldTransCancel
120    }
121    cancelVec.get.foreach(_ := false.B)
122  }
123
124  if (io.wakeUpFromIQ.isEmpty) {
125    srcWakeUpByIQVec := 0.U.asTypeOf(srcWakeUpByIQVec)
126    wakeupLoadDependencyByIQVec := 0.U.asTypeOf(wakeupLoadDependencyByIQVec)
127  } else {
128    val wakeupVec: Seq[Seq[Bool]] = io.wakeUpFromIQ.map((bundle: ValidIO[IssueQueueIQWakeUpBundle]) =>
129      bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)
130    ).toSeq.transpose
131    srcWakeUpByIQVec := wakeupVec.map(x => VecInit(x))
132    wakeupLoadDependencyByIQVec := io.wakeUpFromIQ.map(_.bits.loadDependency).toSeq
133  }
134
135  when(io.enq.valid && io.transSel) {
136    entryRegNext := io.enq.bits
137  }.otherwise {
138    //update status
139    entryRegNext.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    entryRegNext.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      entryRegNext.status.srcWakeUpL1ExuOH.get.zip(srcWakeUpByIQVec).zip(srcWakeUp).zipWithIndex.foreach {
158        case (((exuOH: UInt, wakeUpByIQOH: Vec[Bool]), wakeUp: Bool), srcIdx) =>
159          when(wakeUpByIQOH.asUInt.orR) {
160            exuOH := Mux1H(wakeUpByIQOH, io.wakeUpFromIQ.toSeq.map(x => MathUtils.IntToOH(x.bits.exuIdx).U(backendParams.numExu.W)))
161          }.elsewhen(wakeUp) {
162            exuOH := 0.U.asTypeOf(exuOH)
163          }.otherwise {
164            exuOH := entryReg.status.srcWakeUpL1ExuOH.get(srcIdx)
165          }
166      }
167      entryRegNext.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      entryRegNext.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    entryRegNext.status.issueTimer := "b11".U //otherwise
188    entryRegNext.status.deqPortIdx := 0.U //otherwise
189    when(io.deqSel){
190      entryRegNext.status.issueTimer := 1.U
191      entryRegNext.status.deqPortIdx := io.deqPortIdxRead
192    }.elsewhen(entryReg.status.issued){
193      entryRegNext.status.issueTimer := entryReg.status.issueTimer + 1.U
194      entryRegNext.status.deqPortIdx := entryReg.status.deqPortIdx
195    }
196    entryRegNext.status.psrc := entryReg.status.psrc
197    entryRegNext.status.srcType := entryReg.status.srcType
198    entryRegNext.status.fuType := entryReg.status.fuType
199    entryRegNext.status.robIdx := entryReg.status.robIdx
200    entryRegNext.status.uopIdx.foreach(_ := entryReg.status.uopIdx.get)
201    entryRegNext.status.issued := entryReg.status.issued // otherwise
202    when(!entryReg.status.srcReady) {
203      entryRegNext.status.issued := false.B
204    }.elsewhen(srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B)) {
205      entryRegNext.status.issued := false.B
206    }.elsewhen(io.issueResp.valid) {
207      when(RSFeedbackType.isStageSuccess(io.issueResp.bits.respType)) {
208        entryRegNext.status.issued := true.B
209      }.elsewhen(RSFeedbackType.isBlocked(io.issueResp.bits.respType)) {
210        entryRegNext.status.issued := false.B
211      }
212    }
213    entryRegNext.status.firstIssue := io.deqSel || entryReg.status.firstIssue
214    entryRegNext.status.blocked := false.B //todo
215    //remain imm and payload
216    entryRegNext.imm := entryReg.imm
217    entryRegNext.payload := entryReg.payload
218    if (params.needPc) {
219      entryRegNext.status.pc.get := entryReg.status.pc.get
220    }
221  }
222
223  //output
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.uopIdx.foreach(_ := entryReg.status.uopIdx.get)
236  io.issueTimerRead := Mux(io.deqSel, 0.U, entryReg.status.issueTimer)
237  io.deqPortIdxRead := Mux(io.deqSel, io.deqPortIdxWrite, entryReg.status.deqPortIdx)
238  io.cancel.foreach(_ := cancelVec.get.asUInt.orR)
239}
240
241class OthersEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends OthersEntry
242  with HasCircularQueuePtrHelper {
243
244  val fromMem = io.fromMem.get
245
246  val memStatus = entryReg.status.mem.get
247  val memStatusNext = entryRegNext.status.mem.get
248  // load cannot be issued before older store, unless meet some condition
249  val blockedByOlderStore = isAfter(memStatusNext.sqIdx, fromMem.stIssuePtr)
250
251  val deqFailedForStdInvalid = io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.dataInvalid
252
253  val staWaitedReleased = Cat(
254    fromMem.memWaitUpdateReq.robIdx.map(x => x.valid && x.bits.value === memStatusNext.waitForRobIdx.value)
255  ).orR
256  val stdWaitedReleased = Cat(
257    fromMem.memWaitUpdateReq.sqIdx.map(x => x.valid && x.bits.value === memStatusNext.waitForSqIdx.value)
258  ).orR
259  val olderStaNotViolate = staWaitedReleased && !memStatusNext.strictWait
260  val olderStdReady = stdWaitedReleased && memStatusNext.waitForStd
261  val waitStd = !olderStdReady
262  val waitSta = !olderStaNotViolate
263
264  when(io.enq.valid && io.transSel) {
265    memStatusNext.waitForSqIdx := io.enq.bits.status.mem.get.waitForSqIdx
266    // update by lfst at dispatch stage
267    memStatusNext.waitForRobIdx := io.enq.bits.status.mem.get.waitForRobIdx
268    // new load inst don't known if it is blocked by store data ahead of it
269    memStatusNext.waitForStd := false.B
270    // update by ssit at rename stage
271    memStatusNext.strictWait := io.enq.bits.status.mem.get.strictWait
272    memStatusNext.sqIdx := io.enq.bits.status.mem.get.sqIdx
273  }.elsewhen(deqFailedForStdInvalid) {
274    // Todo: check if need assign statusNext.block
275    memStatusNext.waitForSqIdx := io.issueResp.bits.dataInvalidSqIdx
276    memStatusNext.waitForRobIdx := memStatus.waitForRobIdx
277    memStatusNext.waitForStd := true.B
278    memStatusNext.strictWait := memStatus.strictWait
279    memStatusNext.sqIdx := memStatus.sqIdx
280  }.otherwise {
281    memStatusNext := memStatus
282  }
283
284  val shouldBlock = Mux(io.enq.valid && io.transSel, io.enq.bits.status.blocked, entryReg.status.blocked)
285  val blockNotReleased = waitStd || waitSta
286  val respBlock = deqFailedForStdInvalid
287  entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock
288}
289
290class OthersEntryVecMemAddr()(implicit p: Parameters, params: IssueBlockParams) extends OthersEntryMem {
291
292  require(params.isVecMemAddrIQ, "OthersEntryVecMemAddr can only be instance of VecMemAddr IQ")
293
294  val vecMemStatus = entryReg.status.vecMem.get
295  val vecMemStatusNext = entryRegNext.status.vecMem.get
296  val fromLsq = io.fromLsq.get
297
298  when(io.enq.valid && io.transSel) {
299    vecMemStatusNext.sqIdx := io.enq.bits.status.vecMem.get.sqIdx
300    vecMemStatusNext.lqIdx := io.enq.bits.status.vecMem.get.lqIdx
301  }.otherwise {
302    vecMemStatusNext := vecMemStatus
303  }
304
305  val isLsqHead = {
306    // if (params.isVecLdAddrIQ)
307      entryRegNext.status.vecMem.get.lqIdx <= fromLsq.lqDeqPtr &&
308    // else
309      entryRegNext.status.vecMem.get.sqIdx <= fromLsq.sqDeqPtr
310  }
311  dontTouch(shouldBlock)
312  dontTouch(blockNotReleased)
313  dontTouch(blockedByOlderStore)
314  dontTouch(respBlock)
315  dontTouch(isLsqHead)
316  dontTouch(waitStd)
317  dontTouch(waitSta)
318  dontTouch(memStatusNext)
319  dontTouch(fromMem)
320  dontTouch(io.issueResp)
321  dontTouch(isLsqHead)
322
323  entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock || !isLsqHead
324}
325
326class OthersEntryVecMemData()(implicit p: Parameters, params: IssueBlockParams) extends OthersEntry
327  with HasCircularQueuePtrHelper {
328
329  require(params.isVecStDataIQ, "OthersEntryVecMemData can only be instance of VecMemData IQ")
330
331  val vecMemStatus = entryReg.status.vecMem.get
332  val vecMemStatusNext = entryRegNext.status.vecMem.get
333  val fromLsq = io.fromLsq.get
334
335  when(io.enq.valid && io.transSel) {
336    vecMemStatusNext.sqIdx := io.enq.bits.status.vecMem.get.sqIdx
337    vecMemStatusNext.lqIdx := io.enq.bits.status.vecMem.get.lqIdx
338  }.otherwise {
339    vecMemStatusNext := vecMemStatus
340  }
341
342  val isLsqHead = entryRegNext.status.vecMem.get.sqIdx.value === fromLsq.sqDeqPtr.value
343
344  entryRegNext.status.blocked := !isLsqHead
345}
346
347object OthersEntry {
348  def apply(implicit p: Parameters, iqParams: IssueBlockParams): OthersEntry = {
349    iqParams.schdType match {
350      case IntScheduler() => new OthersEntry()
351      case MemScheduler() =>
352        if (iqParams.isLdAddrIQ || iqParams.isStAddrIQ || iqParams.isHyAddrIQ) new OthersEntryMem()
353        else if (iqParams.isVecMemAddrIQ) new OthersEntryVecMemAddr()
354        else if (iqParams.isVecStDataIQ) new OthersEntryVecMemData()
355        else new OthersEntry()
356      case VfScheduler() => new OthersEntry()
357      case _ => null
358    }
359  }
360}