xref: /XiangShan/src/main/scala/xiangshan/backend/issue/EnqEntry.scala (revision 55cbdb858ce15144f66bf76edf3f9e0a0fa7b538)
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 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 common              = Wire(new CommonWireBundle)
35  val entryUpdate         = Wire(new EntryBundle)
36  val entryRegNext        = Wire(new EntryBundle)
37  val enqDelayValidRegNext= Wire(Bool())
38  val hasWakeupIQ         = OptionWrapper(params.hasIQWakeUp, Wire(new CommonIQWakeupBundle))
39
40  val currentStatus               = Wire(new Status())
41  val enqDelaySrcState            = Wire(Vec(params.numRegSrc, SrcState()))
42  val enqDelayDataSources         = Wire(Vec(params.numRegSrc, DataSource()))
43  val enqDelaySrcWakeUpL1ExuOH    = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, ExuOH())))
44  val enqDelaySrcLoadDependency   = Wire(Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W))))
45
46  val enqDelaySrcWakeUpByWB: Vec[UInt]                            = Wire(Vec(params.numRegSrc, SrcState()))
47  val enqDelaySrcWakeUpByIQ: Vec[UInt]                            = Wire(Vec(params.numRegSrc, SrcState()))
48  val enqDelaySrcWakeUpByIQVec: Vec[Vec[Bool]]                    = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool())))
49  val enqDelayShiftedWakeupLoadDependencyByIQVec: Vec[Vec[UInt]]  = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W))))
50
51  //Reg
52  val validReg = GatedValidRegNext(common.validRegNext, false.B)
53  val entryReg = RegEnable(entryRegNext, validReg || common.validRegNext)
54  val enqDelayValidReg = GatedValidRegNext(enqDelayValidRegNext, false.B)
55
56  //Wire
57  CommonWireConnect(common, hasWakeupIQ, validReg, currentStatus, io.commonIn, true)
58
59  when(io.commonIn.enq.valid) {
60    assert(common.enqReady, "Entry is not ready when enq is valid\n")
61  }
62
63  when(io.commonIn.enq.valid && common.enqReady) {
64    entryRegNext := io.commonIn.enq.bits
65  }.otherwise {
66    entryRegNext := entryUpdate
67  }
68
69  when(io.commonIn.enq.valid && common.enqReady) {
70    enqDelayValidRegNext := true.B
71  }.otherwise {
72    enqDelayValidRegNext := false.B
73  }
74
75  if (params.hasIQWakeUp) {
76    ShiftLoadDependency(hasWakeupIQ.get)
77    CommonIQWakeupConnect(common, hasWakeupIQ.get, validReg, currentStatus, io.commonIn, true)
78  }
79
80  // enq delay wakeup
81  enqDelaySrcWakeUpByWB.zipWithIndex.foreach { case (wakeup, i) =>
82    wakeup := io.enqDelayWakeUpFromWB.map(x => x.bits.wakeUp(Seq((entryReg.status.srcStatus(i).psrc, entryReg.status.srcStatus(i).srcType)), x.valid).head
83    ).reduce(_ || _)
84  }
85
86  if (params.hasIQWakeUp) {
87    val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.enqDelayWakeUpFromIQ.map( x =>
88      x.bits.wakeUpFromIQ(entryReg.status.srcStatus.map(_.psrc) zip entryReg.status.srcStatus.map(_.srcType))
89    ).toIndexedSeq.transpose
90    val cancelSel = params.wakeUpSourceExuIdx.zip(io.enqDelayWakeUpFromIQ).map{ case (x, y) => io.enqDelayOg0Cancel(x) && y.bits.is0Lat}
91    enqDelaySrcWakeUpByIQVec := wakeupVec.map(x => VecInit(x.zip(cancelSel).map { case (wakeup, cancel) => wakeup && !cancel }))
92  } else {
93    enqDelaySrcWakeUpByIQVec := 0.U.asTypeOf(enqDelaySrcWakeUpByIQVec)
94  }
95
96  if (params.hasIQWakeUp) {
97    enqDelaySrcWakeUpByIQ.zipWithIndex.foreach { case (wakeup, i) =>
98      val ldTransCancel = Mux1H(enqDelaySrcWakeUpByIQVec(i), io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency).map(dp => LoadShouldCancel(Some(dp), io.enqDelayLdCancel)).toSeq)
99      wakeup := enqDelaySrcWakeUpByIQVec(i).asUInt.orR && !ldTransCancel
100    }
101  } else {
102    enqDelaySrcWakeUpByIQ := 0.U.asTypeOf(enqDelaySrcWakeUpByIQ)
103  }
104
105  enqDelayShiftedWakeupLoadDependencyByIQVec.zip(io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency))
106    .zip(params.wakeUpInExuSources.map(_.name)).foreach { case ((dps, ldps), name) =>
107    dps.zip(ldps).zipWithIndex.foreach { case ((dp, ldp), deqPortIdx) =>
108      if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx)
109        dp := (ldp << 2).asUInt | 2.U
110      else
111        dp := ldp << 1
112    }
113  }
114
115  for (i <- 0 until params.numRegSrc) {
116    enqDelaySrcState(i)                     := entryReg.status.srcStatus(i).srcState | enqDelaySrcWakeUpByWB(i) | enqDelaySrcWakeUpByIQ(i)
117    enqDelayDataSources(i).value            := Mux(enqDelaySrcWakeUpByIQ(i).asBool, DataSource.bypass, entryReg.status.srcStatus(i).dataSources.value)
118    if (params.hasIQWakeUp) {
119      val wakeUpValid = enqDelaySrcWakeUpByIQVec(i).asUInt.orR
120      val wakeUpOH = enqDelaySrcWakeUpByIQVec(i)
121      enqDelaySrcWakeUpL1ExuOH.get(i)       := Mux1H(wakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)).toSeq)
122      enqDelaySrcLoadDependency(i)          := Mux(enqDelaySrcWakeUpByIQVec(i).asUInt.orR, Mux1H(enqDelaySrcWakeUpByIQVec(i), enqDelayShiftedWakeupLoadDependencyByIQVec), entryReg.status.srcStatus(i).srcLoadDependency)
123    } else {
124      enqDelaySrcLoadDependency(i)          := entryReg.status.srcStatus(i).srcLoadDependency
125    }
126  }
127  currentStatus                             := entryReg.status
128  when (enqDelayValidReg) {
129    currentStatus.srcStatus.zipWithIndex.foreach { case (srcStatus, srcIdx) =>
130      srcStatus.srcState                    := enqDelaySrcState(srcIdx)
131      srcStatus.dataSources                 := enqDelayDataSources(srcIdx)
132      srcStatus.srcLoadDependency           := enqDelaySrcLoadDependency(srcIdx)
133    }
134  }
135
136  if (params.hasIQWakeUp) {
137    currentStatus.srcStatus.map(_.srcWakeUpL1ExuOH.get).zip(entryReg.status.srcStatus.map(_.srcWakeUpL1ExuOH.get)).zip(enqDelaySrcWakeUpL1ExuOH.get).foreach {
138      case ((currExuOH, regExuOH), enqDelayExuOH) =>
139        currExuOH := 0.U.asTypeOf(currExuOH)
140        params.wakeUpSourceExuIdx.foreach(x => currExuOH(x) := Mux(enqDelayValidReg, enqDelayExuOH(x), regExuOH(x)))
141    }
142  }
143
144  EntryRegCommonConnect(common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true)
145
146  //output
147  CommonOutConnect(io.commonOut, common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true, isComp)
148}
149
150class EnqEntryVecMem(isComp: Boolean)(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry(isComp)
151  with HasCircularQueuePtrHelper {
152
153  require(params.isVecMemIQ, "EnqEntryVecMem can only be instance of VecMem IQ")
154
155  EntryVecMemConnect(io.commonIn, common, validReg, entryReg, entryRegNext, entryUpdate)
156}
157
158object EnqEntry {
159  def apply(isComp: Boolean)(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = {
160    iqParams.schdType match {
161      case IntScheduler() => new EnqEntry(isComp)
162      case MemScheduler() =>
163        if (iqParams.isVecMemIQ) new EnqEntryVecMem(isComp)
164        else new EnqEntry(isComp)
165      case VfScheduler() => new EnqEntry(isComp)
166      case _ => null
167    }
168  }
169}