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