xref: /XiangShan/src/main/scala/xiangshan/backend/issue/EnqEntry.scala (revision aa2bcc3199f9e6b199af20fda352a22f9a67c044)
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.backend.issue.EntryBundles._
14import xiangshan.mem.{MemWaitUpdateReq, SqPtr, LqPtr}
15
16
17class EnqEntryIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle {
18  //input
19  val commonIn            = new CommonInBundle
20  val enqDelayWakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle)
21  val enqDelayWakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle)
22  val enqDelayOg0Cancel   = Input(ExuOH(backendParams.numExu))
23  val enqDelayLdCancel    = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO))
24
25  //output
26  val commonOut           = new CommonOutBundle
27  val transEntry          = ValidIO(new EntryBundle)
28
29  def wakeup              = commonIn.wakeUpFromWB ++ commonIn.wakeUpFromIQ
30}
31
32class EnqEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
33  val io = IO(new EnqEntryIO)
34
35  val validReg            = RegInit(false.B)
36  val enqDelayValidReg    = RegInit(false.B)
37  val entryReg            = Reg(new EntryBundle)
38
39  val common              = Wire(new CommonWireBundle)
40  val entryUpdate         = Wire(new EntryBundle)
41  val entryRegNext        = Wire(new EntryBundle)
42  val enqDelayValidRegNext= Wire(Bool())
43  val hasWakeupIQ         = OptionWrapper(params.hasIQWakeUp, Wire(new CommonIQWakeupBundle))
44
45  val currentStatus               = Wire(new Status())
46  val enqDelaySrcState            = Wire(Vec(params.numRegSrc, SrcState()))
47  val enqDelayDataSources         = Wire(Vec(params.numRegSrc, DataSource()))
48  val enqDelaySrcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, ExuOH())))
49  val enqDelaySrcTimer            = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, UInt(3.W))))
50  val enqDelaySrcLoadDependency   = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W)))))
51
52  val enqDelaySrcWakeUpByWB: Vec[UInt]                            = Wire(Vec(params.numRegSrc, SrcState()))
53  val enqDelaySrcWakeUpByIQ: Vec[UInt]                            = Wire(Vec(params.numRegSrc, SrcState()))
54  val enqDelaySrcWakeUpByIQVec: Vec[Vec[Bool]]                    = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool())))
55  val enqDelayShiftedWakeupLoadDependencyByIQVec: Vec[Vec[UInt]]  = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W))))
56
57  //Reg
58  validReg                        := common.validRegNext
59  entryReg                        := entryRegNext
60  enqDelayValidReg                := enqDelayValidRegNext
61
62  //Wire
63  CommonWireConnect(common, hasWakeupIQ, validReg, entryReg, io.commonIn, true)
64
65  when(io.commonIn.enq.valid && common.enqReady) {
66    entryRegNext := io.commonIn.enq.bits
67  }.otherwise {
68    entryRegNext := entryUpdate
69  }
70
71  when(io.commonIn.enq.valid && common.enqReady) {
72    enqDelayValidRegNext := true.B
73  }.otherwise {
74    enqDelayValidRegNext := false.B
75  }
76
77  if (params.hasIQWakeUp) {
78    ShiftLoadDependency(hasWakeupIQ.get)
79    CommonIQWakeupConnect(common, hasWakeupIQ.get, validReg, entryReg.status, io.commonIn, true)
80  }
81
82  // enq delay wakeup
83  enqDelaySrcWakeUpByWB.zipWithIndex.foreach { case (wakeup, i) =>
84    wakeup := io.enqDelayWakeUpFromWB.map(x => x.bits.wakeUp(Seq((entryReg.status.srcStatus(i).psrc, entryReg.status.srcStatus(i).srcType)), x.valid).head
85    ).reduce(_ || _)
86  }
87
88  if (params.hasIQWakeUp) {
89    val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.enqDelayWakeUpFromIQ.map( x =>
90      x.bits.wakeUpFromIQ(entryReg.status.srcStatus.map(_.psrc) zip entryReg.status.srcStatus.map(_.srcType))
91    ).toIndexedSeq.transpose
92    val cancelSel = params.wakeUpSourceExuIdx.zip(io.enqDelayWakeUpFromIQ).map{ case (x, y) => io.enqDelayOg0Cancel(x) && y.bits.is0Lat}
93    enqDelaySrcWakeUpByIQVec := wakeupVec.map(x => VecInit(x.zip(cancelSel).map { case (wakeup, cancel) => wakeup && !cancel }))
94  } else {
95    enqDelaySrcWakeUpByIQVec := 0.U.asTypeOf(enqDelaySrcWakeUpByIQVec)
96  }
97
98  if (params.hasIQWakeUp) {
99    enqDelaySrcWakeUpByIQ.zipWithIndex.foreach { case (wakeup, i) =>
100      val ldTransCancel = Mux1H(enqDelaySrcWakeUpByIQVec(i), io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency).map(dp => LoadShouldCancel(Some(dp), io.enqDelayLdCancel)).toSeq)
101      wakeup := enqDelaySrcWakeUpByIQVec(i).asUInt.orR && !ldTransCancel
102    }
103  } else {
104    enqDelaySrcWakeUpByIQ := 0.U.asTypeOf(enqDelaySrcWakeUpByIQ)
105  }
106
107  enqDelayShiftedWakeupLoadDependencyByIQVec.zip(io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency))
108    .zip(params.wakeUpInExuSources.map(_.name)).foreach { case ((dps, ldps), name) =>
109    dps.zip(ldps).zipWithIndex.foreach { case ((dp, ldp), deqPortIdx) =>
110      if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx)
111        dp := (ldp << 2).asUInt | 2.U
112      else
113        dp := ldp << 1
114    }
115  }
116
117  for (i <- 0 until params.numRegSrc) {
118    enqDelaySrcState(i)                     := entryReg.status.srcStatus(i).srcState | enqDelaySrcWakeUpByWB(i) | enqDelaySrcWakeUpByIQ(i)
119    enqDelayDataSources(i).value            := Mux(enqDelaySrcWakeUpByIQ(i).asBool, DataSource.bypass, DataSource.reg)
120    if (params.hasIQWakeUp) {
121      val wakeUpValid = enqDelaySrcWakeUpByIQVec(i).asUInt.orR
122      val wakeUpOH = enqDelaySrcWakeUpByIQVec(i)
123      enqDelaySrcWakeUpL1ExuOH.get(i)       := Mux1H(wakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)).toSeq)
124      enqDelaySrcTimer.get(i)               := Mux(wakeUpValid, 2.U, 3.U)
125      enqDelaySrcLoadDependency.get(i)      := Mux(wakeUpValid, Mux1H(wakeUpOH, enqDelayShiftedWakeupLoadDependencyByIQVec), entryReg.status.srcStatus(i).srcLoadDependency.get)
126    }
127  }
128  currentStatus                             := entryReg.status
129  when (enqDelayValidReg) {
130    currentStatus.srcStatus.zipWithIndex.foreach { case (srcStatus, srcIdx) =>
131      srcStatus.srcState                    := enqDelaySrcState(srcIdx)
132      srcStatus.dataSources                 := enqDelayDataSources(srcIdx)
133      srcStatus.srcTimer.foreach(_          := enqDelaySrcTimer.get(srcIdx))
134      srcStatus.srcLoadDependency.foreach(_ := enqDelaySrcLoadDependency.get(srcIdx))
135    }
136  }
137
138  if (params.hasIQWakeUp) {
139    currentStatus.srcStatus.map(_.srcWakeUpL1ExuOH.get).zip(entryReg.status.srcStatus.map(_.srcWakeUpL1ExuOH.get)).zip(enqDelaySrcWakeUpL1ExuOH.get).foreach {
140      case ((currExuOH, regExuOH), enqDelayExuOH) =>
141        currExuOH := 0.U.asTypeOf(currExuOH)
142        params.wakeUpSourceExuIdx.foreach(x => currExuOH(x) := Mux(enqDelayValidReg, enqDelayExuOH(x), regExuOH(x)))
143    }
144  }
145
146  EntryRegCommonConnect(common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true)
147
148  CommonOutConnect(io.commonOut, common, hasWakeupIQ, validReg, entryReg, currentStatus, io.commonIn, true)
149  io.transEntry.valid := validReg && !common.flushed && !common.deqSuccess
150  io.transEntry.bits := entryUpdate
151}
152
153class EnqEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry
154  with HasCircularQueuePtrHelper {
155  entryUpdate.status.blocked                        := EntryMemConnect(io.commonIn, common, validReg, entryReg, entryRegNext, true)
156  val memStatusUpdate                                = entryUpdate.status.mem.get
157  val memStatus                                      = entryReg.status.mem.get
158  val deqFailedForStdInvalid                         = io.commonIn.issueResp.valid && io.commonIn.issueResp.bits.respType === RSFeedbackType.dataInvalid
159
160  when(deqFailedForStdInvalid) {
161    memStatusUpdate.waitForSqIdx                    := io.commonIn.issueResp.bits.dataInvalidSqIdx
162    memStatusUpdate.waitForRobIdx                   := memStatus.waitForRobIdx
163    memStatusUpdate.waitForStd                      := true.B
164    memStatusUpdate.strictWait                      := memStatus.strictWait
165    memStatusUpdate.sqIdx                           := memStatus.sqIdx
166  }.otherwise {
167    memStatusUpdate                                 := memStatus
168  }
169
170}
171
172class EnqEntryVecMemAddr()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntryMem {
173
174  require(params.isVecMemAddrIQ, "EnqEntryVecMemAddr can only be instance of VecMemAddr IQ")
175
176  val vecMemStatus = entryReg.status.vecMem.get
177  val vecMemStatusNext = entryRegNext.status.vecMem.get
178  val vecMemStatusUpdate = entryUpdate.status.vecMem.get
179  val fromLsq = io.commonIn.fromLsq.get
180
181  when (io.commonIn.enq.valid && common.enqReady) {
182    vecMemStatusNext.sqIdx := io.commonIn.enq.bits.status.vecMem.get.sqIdx
183    vecMemStatusNext.lqIdx := io.commonIn.enq.bits.status.vecMem.get.lqIdx
184  }.otherwise {
185    vecMemStatusNext := vecMemStatusUpdate
186  }
187  vecMemStatusUpdate := vecMemStatus
188
189  val isLsqHead = {
190    // if (params.isVecLdAddrIQ)
191      entryRegNext.status.vecMem.get.lqIdx <= fromLsq.lqDeqPtr &&
192    // else
193      entryRegNext.status.vecMem.get.sqIdx <= fromLsq.sqDeqPtr
194  }
195
196  entryUpdate.status.vecMem.get.uopIdx := entryReg.status.vecMem.get.uopIdx
197}
198
199class EnqEntryVecMemData()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry
200  with HasCircularQueuePtrHelper {
201
202  require(params.isVecStDataIQ, "EnqEntryVecMemData can only be instance of VecMemData IQ")
203
204  val vecMemStatus = entryReg.status.vecMem.get
205  val vecMemStatusNext = entryRegNext.status.vecMem.get
206  val vecMemStatusUpdate = entryUpdate.status.vecMem.get
207  val fromLsq = io.commonIn.fromLsq.get
208
209  when (io.commonIn.enq.valid && common.enqReady) {
210    vecMemStatusNext.sqIdx := io.commonIn.enq.bits.status.vecMem.get.sqIdx
211    vecMemStatusNext.lqIdx := io.commonIn.enq.bits.status.vecMem.get.lqIdx
212  }.otherwise {
213    vecMemStatusNext := vecMemStatusUpdate
214  }
215  vecMemStatusUpdate := vecMemStatus
216
217  val isLsqHead = entryRegNext.status.vecMem.get.sqIdx.value === fromLsq.sqDeqPtr.value
218
219  entryRegNext.status.blocked := !isLsqHead
220  entryUpdate.status.blocked := !isLsqHead
221  entryUpdate.status.vecMem.get.uopIdx := entryReg.status.vecMem.get.uopIdx
222}
223
224object EnqEntry {
225  def apply(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = {
226    iqParams.schdType match {
227      case IntScheduler() => new EnqEntry()
228      case MemScheduler() =>
229        if (iqParams.isLdAddrIQ || iqParams.isStAddrIQ || iqParams.isHyAddrIQ) new EnqEntryMem()
230        else if (iqParams.isVecMemAddrIQ) new EnqEntryVecMemAddr()
231        else if (iqParams.isVecStDataIQ) new EnqEntryVecMemData()
232        else new EnqEntry()
233      case VfScheduler() => new EnqEntry()
234      case _ => null
235    }
236  }
237}