xref: /XiangShan/src/main/scala/xiangshan/backend/issue/EnqEntry.scala (revision e1d5ffc2d93873b72146e78c8f6a904926de8590)
1package xiangshan.backend.issue
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.{HasCircularQueuePtrHelper, GatedValidRegNext}
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 enqDelayIn1         = new EnqDelayInBundle
21  val enqDelayIn2         = new EnqDelayInBundle
22
23  //output
24  val commonOut           = new CommonOutBundle
25
26  def wakeup              = commonIn.wakeUpFromWB ++ commonIn.wakeUpFromIQ
27}
28
29class EnqEntry(isComp: Boolean)(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
30  val io = IO(new EnqEntryIO)
31
32  val common              = Wire(new CommonWireBundle)
33  val entryUpdate         = Wire(new EntryBundle)
34  val entryRegNext        = Wire(new EntryBundle)
35  val enqDelayValidRegNext= Wire(Bool())
36  val hasWakeupIQ         = OptionWrapper(params.hasIQWakeUp, Wire(new CommonIQWakeupBundle))
37
38  val currentStatus               = Wire(new Status())
39  val enqDelaySrcState            = Wire(Vec(params.numRegSrc, SrcState()))
40  val enqDelayDataSources         = Wire(Vec(params.numRegSrc, DataSource()))
41  val enqDelaySrcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, ExuVec())))
42  val enqDelaySrcLoadDependency   = Wire(Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W))))
43  val enqDelayUseRegCache         = OptionWrapper(params.needReadRegCache, Wire(Vec(params.numRegSrc, Bool())))
44  val enqDelayRegCacheIdx         = OptionWrapper(params.needReadRegCache, Wire(Vec(params.numRegSrc, UInt(RegCacheIdxWidth.W))))
45
46  //Reg
47  val validReg = GatedValidRegNext(common.validRegNext, false.B)
48  val entryReg = RegNext(entryRegNext)
49  val enqDelayValidReg = GatedValidRegNext(enqDelayValidRegNext, false.B)
50
51  //Wire
52  CommonWireConnect(common, hasWakeupIQ, validReg, currentStatus, io.commonIn, true)
53
54  when(io.commonIn.enq.valid) {
55    assert(common.enqReady, s"${params.getIQName}'s EnqEntry is not ready when enq is valid\n")
56  }
57
58  when(io.commonIn.enq.valid && common.enqReady) {
59    entryRegNext := io.commonIn.enq.bits
60  }.otherwise {
61    entryRegNext := entryUpdate
62  }
63
64  when(io.commonIn.enq.valid && common.enqReady) {
65    enqDelayValidRegNext := true.B
66  }.otherwise {
67    enqDelayValidRegNext := false.B
68  }
69
70  if (params.hasIQWakeUp) {
71    ShiftLoadDependency(hasWakeupIQ.get)
72    CommonIQWakeupConnect(common, hasWakeupIQ.get, validReg, currentStatus, io.commonIn, true)
73  }
74
75  // enq delay wakeup
76  val enqDelayOut1         = Wire(new EnqDelayOutBundle)
77  val enqDelayOut2         = Wire(new EnqDelayOutBundle)
78  EnqDelayWakeupConnect(io.enqDelayIn1, enqDelayOut1, entryReg.status, delay = 1)
79  EnqDelayWakeupConnect(io.enqDelayIn2, enqDelayOut2, entryReg.status, delay = 2)
80
81  for (i <- 0 until params.numRegSrc) {
82    val enqDelay1WakeUpValid = enqDelayOut1.srcWakeUpByIQVec(i).asUInt.orR
83    val enqDelay1WakeUpOH    = enqDelayOut1.srcWakeUpByIQVec(i)
84    val enqDelay2WakeUpOH    = enqDelayOut2.srcWakeUpByIQVec(i)
85    val enqDelay1IsWakeupByMemIQ = enqDelay1WakeUpOH.zip(io.commonIn.wakeUpFromIQ).filter(_._2.bits.params.isMemExeUnit).map(_._1).fold(false.B)(_ || _)
86    val enqDelay2IsWakeupByMemIQ = enqDelay2WakeUpOH.zip(io.commonIn.wakeUpFromIQ).filter(_._2.bits.params.isMemExeUnit).map(_._1).fold(false.B)(_ || _)
87    val enqDelay2IsWakeupByVfIQ  = enqDelay2WakeUpOH.zip(io.commonIn.wakeUpFromIQ).filter(_._2.bits.params.isVfExeUnit).map(_._1).fold(false.B)(_ || _)
88
89    if (params.inVfSchd && params.readVfRf && params.hasIQWakeUp) {
90      enqDelayDataSources(i).value            := MuxCase(entryReg.status.srcStatus(i).dataSources.value, Seq(
91                                                    (enqDelayOut1.srcWakeUpByIQ(i).asBool && !enqDelay1IsWakeupByMemIQ)  -> DataSource.bypass,
92                                                    (enqDelayOut1.srcWakeUpByIQ(i).asBool && enqDelay1IsWakeupByMemIQ)   -> DataSource.bypass2,
93                                                    (enqDelayOut2.srcWakeUpByIQ(i).asBool && !enqDelay2IsWakeupByMemIQ)  -> DataSource.bypass2,
94                                                 ))
95      enqDelaySrcWakeUpL1ExuOH.get(i)         := Mux(enqDelay1WakeUpValid,
96                                                      Mux1H(enqDelay1WakeUpOH, params.wakeUpSourceExuIdx.map(x => VecInit(MathUtils.IntToOH(x).U(backendParams.numExu.W).asBools)).toSeq),
97                                                      Mux1H(enqDelay2WakeUpOH, params.wakeUpSourceExuIdx.map(x => VecInit(MathUtils.IntToOH(x).U(backendParams.numExu.W).asBools)).toSeq))
98    }
99    else if (params.inMemSchd && params.readVfRf && params.hasIQWakeUp) {
100      enqDelayDataSources(i).value            := MuxCase(entryReg.status.srcStatus(i).dataSources.value, Seq(
101                                                    enqDelayOut1.srcWakeUpByIQ(i).asBool                                 -> DataSource.bypass,
102                                                    (enqDelayOut2.srcWakeUpByIQ(i).asBool && enqDelay2IsWakeupByVfIQ)    -> DataSource.bypass2,
103                                                 ))
104      enqDelaySrcWakeUpL1ExuOH.get(i)         := Mux(enqDelay1WakeUpValid,
105                                                      Mux1H(enqDelay1WakeUpOH, params.wakeUpSourceExuIdx.map(x => VecInit(MathUtils.IntToOH(x).U(backendParams.numExu.W).asBools)).toSeq),
106                                                      Mux1H(enqDelay2WakeUpOH,  params.wakeUpSourceExuIdx.map(x => VecInit(MathUtils.IntToOH(x).U(backendParams.numExu.W).asBools)).toSeq))
107    }
108    else {
109      enqDelayDataSources(i).value            := Mux(enqDelayOut1.srcWakeUpByIQ(i).asBool, DataSource.bypass, entryReg.status.srcStatus(i).dataSources.value)
110      if (params.hasIQWakeUp) {
111        enqDelaySrcWakeUpL1ExuOH.get(i)       := Mux1H(enqDelay1WakeUpOH, params.wakeUpSourceExuIdx.map(x => VecInit(MathUtils.IntToOH(x).U(backendParams.numExu.W).asBools)).toSeq)
112      }
113    }
114
115    enqDelaySrcState(i)                     := (!enqDelayOut1.srcCancelByLoad(i) & entryReg.status.srcStatus(i).srcState) | enqDelayOut1.srcWakeUpByWB(i) | enqDelayOut1.srcWakeUpByIQ(i)
116    if (params.hasIQWakeUp) {
117      enqDelaySrcLoadDependency(i)          := Mux(enqDelay1WakeUpValid, Mux1H(enqDelay1WakeUpOH, enqDelayOut1.shiftedWakeupLoadDependencyByIQVec), entryReg.status.srcStatus(i).srcLoadDependency)
118    } else {
119      enqDelaySrcLoadDependency(i)          := entryReg.status.srcStatus(i).srcLoadDependency
120    }
121
122    if (params.needReadRegCache) {
123      val enqDelay1WakeupSrcExuWriteRC = enqDelay1WakeUpOH.zip(io.enqDelayIn1.wakeUpFromIQ).filter(_._2.bits.params.needWriteRegCache)
124      val enqDelay1WakeupRC    = enqDelay1WakeupSrcExuWriteRC.map(_._1).fold(false.B)(_ || _) && SrcType.isXp(entryReg.status.srcStatus(i).srcType)
125      val enqDelay1WakeupRCIdx = Mux1H(enqDelay1WakeupSrcExuWriteRC.map(_._1), enqDelay1WakeupSrcExuWriteRC.map(_._2.bits.rcDest.get))
126      val enqDelay1ReplaceRC   = enqDelay1WakeupSrcExuWriteRC.map(x => x._2.bits.rfWen && x._2.bits.rcDest.get === entryReg.status.srcStatus(i).regCacheIdx.get).fold(false.B)(_ || _)
127
128      enqDelayUseRegCache.get(i)            := MuxCase(entryReg.status.srcStatus(i).useRegCache.get, Seq(
129                                                  enqDelayOut1.srcCancelByLoad(i)  -> false.B,
130                                                  enqDelay1WakeupRC                -> true.B,
131                                                  enqDelay1ReplaceRC               -> false.B,
132                                               ))
133      enqDelayRegCacheIdx.get(i)            := Mux(enqDelay1WakeupRC, enqDelay1WakeupRCIdx, entryReg.status.srcStatus(i).regCacheIdx.get)
134    }
135  }
136
137  // current status
138  currentStatus                             := entryReg.status
139  when (enqDelayValidReg) {
140    currentStatus.srcStatus.zipWithIndex.foreach { case (srcStatus, srcIdx) =>
141      srcStatus.srcState                    := enqDelaySrcState(srcIdx)
142      srcStatus.dataSources                 := enqDelayDataSources(srcIdx)
143      srcStatus.srcLoadDependency           := enqDelaySrcLoadDependency(srcIdx)
144      srcStatus.useRegCache.foreach(_       := enqDelayUseRegCache.get(srcIdx))
145      srcStatus.regCacheIdx.foreach(_       := enqDelayRegCacheIdx.get(srcIdx))
146    }
147  }
148
149  if (params.hasIQWakeUp) {
150    currentStatus.srcStatus.map(_.srcWakeUpL1ExuOH.get).zip(entryReg.status.srcStatus.map(_.srcWakeUpL1ExuOH.get)).zip(enqDelaySrcWakeUpL1ExuOH.get).foreach {
151      case ((currExuOH, regExuOH), enqDelayExuOH) =>
152        currExuOH := 0.U.asTypeOf(currExuOH)
153        params.wakeUpSourceExuIdx.foreach(x => currExuOH(x) := Mux(enqDelayValidReg, enqDelayExuOH(x), regExuOH(x)))
154    }
155  }
156
157  EntryRegCommonConnect(common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true)
158
159  //output
160  CommonOutConnect(io.commonOut, common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true, isComp)
161}
162
163class EnqEntryVecMem(isComp: Boolean)(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry(isComp)
164  with HasCircularQueuePtrHelper {
165
166  require(params.isVecMemIQ, "EnqEntryVecMem can only be instance of VecMem IQ")
167
168  EntryVecMemConnect(io.commonIn, common, validReg, entryReg, entryRegNext, entryUpdate)
169}
170
171object EnqEntry {
172  def apply(isComp: Boolean)(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = {
173    iqParams.schdType match {
174      case IntScheduler() => new EnqEntry(isComp)
175      case FpScheduler()  => new EnqEntry(isComp)
176      case MemScheduler() =>
177        if (iqParams.isVecMemIQ) new EnqEntryVecMem(isComp)
178        else new EnqEntry(isComp)
179      case VfScheduler() => new EnqEntry(isComp)
180      case _ => null
181    }
182  }
183}