xref: /XiangShan/src/main/scala/xiangshan/backend/issue/EnqEntry.scala (revision 5db4956b8ea14332169fca361912b6eefd5d475f)
1package xiangshan.backend.issue
2
3import chipsalliance.rocketchip.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}
14
15
16class EnqEntryIO(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(ExuVec(backendParams.numExu))
23  val og1Cancel = Input(ExuVec(backendParams.numExu))
24  val deqSel = Input(Bool())
25  val deqPortIdxWrite = Input(UInt(1.W))
26  val transSel = Input(Bool())
27  val issueResp = Flipped(ValidIO(new EntryDeqRespBundle))
28  //output
29  val valid = Output(Bool())
30  val canIssue = Output(Bool())
31  val clear = Output(Bool())
32  val fuType = Output(FuType())
33  val dataSource = Output(Vec(params.numRegSrc, DataSource()))
34  val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, ExuVec())))
35  val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, UInt(3.W))))
36  val transEntry =  ValidIO(new EntryBundle)
37  val isFirstIssue = Output(Bool())
38  val entry = ValidIO(new EntryBundle)
39  val robIdx = Output(new RobPtr)
40  val deqPortIdxRead = Output(UInt(1.W))
41  val issueTimerRead = Output(UInt(2.W))
42  // mem only
43  val fromMem = if(params.isMemAddrIQ) Some(new Bundle {
44    val stIssuePtr = Input(new SqPtr)
45    val memWaitUpdateReq = Flipped(new MemWaitUpdateReq)
46  }) else None
47
48  def wakeup = wakeUpFromWB ++ wakeUpFromIQ
49}
50
51class EnqEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule {
52  val io = IO(new EnqEntryIO)
53
54  val validReg = RegInit(false.B)
55  val entryReg = Reg(new EntryBundle)
56
57  val validRegNext = Wire(Bool())
58  val entryRegNext = Wire(new EntryBundle)
59  val entryUpdate = Wire(new EntryBundle)
60  val enqReady = Wire(Bool())
61  val clear = Wire(Bool())
62  val flushed = Wire(Bool())
63  val deqSuccess = Wire(Bool())
64  val srcWakeUp = Wire(Vec(params.numRegSrc, Bool()))
65  val srcCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool())))
66  val srcWakeUpByIQVec = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool())))
67
68  //Reg
69  validReg := validRegNext
70  entryReg := entryRegNext
71
72  //Wire
73  when(io.enq.valid && enqReady) {
74    validRegNext := true.B
75  }.elsewhen(clear) {
76    validRegNext := false.B
77  }.otherwise {
78    validRegNext := validReg
79  }
80
81  when(io.enq.valid && enqReady) {
82    entryRegNext := io.enq.bits
83  }.otherwise {
84    entryRegNext := entryUpdate
85  }
86
87  enqReady := !validReg || clear
88  clear := flushed || io.transSel || deqSuccess
89  flushed := entryReg.status.robIdx.needFlush(io.flush)
90  deqSuccess := io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.fuIdle
91  srcWakeUp := io.wakeup.map(bundle => bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)).transpose.map(VecInit(_).asUInt.orR)
92
93  if (params.hasIQWakeUp) {
94    srcCancelVec.get.zipWithIndex.foreach { case (srcCancel, srcIdx) =>
95      // level1 cancel: A(s)->C, A(s) are the level1 cancel
96      val l1Cancel = (io.og0Cancel.asUInt & entryReg.status.srcWakeUpL1ExuOH.get(srcIdx).asUInt).orR &&
97        entryReg.status.srcTimer.get(srcIdx) === 1.U
98      srcCancel := l1Cancel
99    }
100  }
101
102  if (io.wakeUpFromIQ.isEmpty) {
103    srcWakeUpByIQVec := 0.U.asTypeOf(srcWakeUpByIQVec)
104  } else {
105    val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.wakeUpFromIQ.map((bundle: ValidIO[IssueQueueIQWakeUpBundle]) =>
106      bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)
107    ).transpose
108    srcWakeUpByIQVec := wakeupVec.map(x => VecInit(x))
109  }
110
111  //entryUpdate
112  entryUpdate.status.srcState.zip(entryReg.status.srcState).zip(srcWakeUp).zipWithIndex.foreach { case (((stateNext, state), wakeup), srcIdx) =>
113    val cancel = srcCancelVec.map(_ (srcIdx)).getOrElse(false.B)
114    stateNext := Mux(cancel, false.B, wakeup | state)
115  }
116  entryUpdate.status.dataSources.zip(entryReg.status.dataSources).zip(srcWakeUpByIQVec).foreach {
117    case ((dataSourceNext: DataSource, dataSource: DataSource), wakeUpByIQOH: Vec[Bool]) =>
118      when(wakeUpByIQOH.asUInt.orR) {
119        dataSourceNext.value := DataSource.forward
120      }.elsewhen(dataSource.value === DataSource.forward) {
121        dataSourceNext.value := DataSource.bypass
122      }.otherwise {
123        dataSourceNext.value := DataSource.reg
124      }
125  }
126  if (params.hasIQWakeUp) {
127    entryUpdate.status.srcWakeUpL1ExuOH.get.zip(srcWakeUpByIQVec).zipWithIndex.foreach {
128      case ((exuOH: Vec[Bool], wakeUpByIQOH: Vec[Bool]), srcIdx) =>
129        when(wakeUpByIQOH.asUInt.orR) {
130          exuOH := Mux1H(wakeUpByIQOH, io.wakeUpFromIQ.map(x => MathUtils.IntToOH(x.bits.exuIdx).U(backendParams.numExu.W))).asBools
131        }.otherwise {
132          exuOH := entryReg.status.srcWakeUpL1ExuOH.get(srcIdx)
133        }
134    }
135    entryUpdate.status.srcTimer.get.zip(entryReg.status.srcTimer.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach {
136      case (((srcIssuedTimerNext, srcIssuedTimer), wakeUpByIQOH: Vec[Bool]), srcIdx) =>
137        srcIssuedTimerNext := MuxCase(0.U, Seq(
138          // T0: waked up by IQ, T1: reset timer as 1
139          wakeUpByIQOH.asUInt.orR -> 1.U,
140          // do not overflow
141          srcIssuedTimer.andR -> srcIssuedTimer,
142          // T2+: increase if this entry has still been valid, and this src has still been ready
143          (validReg && SrcState.isReady(entryReg.status.srcState(srcIdx)) && entryReg.status.srcWakeUpL1ExuOH.get.asUInt.orR) -> (srcIssuedTimer + 1.U)
144        ))
145    }
146  }
147  entryUpdate.status.issueTimer := "b11".U //otherwise
148  entryUpdate.status.deqPortIdx := 0.U //otherwise
149  when(io.deqSel) {
150    entryUpdate.status.issueTimer := 1.U
151    entryUpdate.status.deqPortIdx := io.deqPortIdxWrite
152  }.elsewhen(entryReg.status.issued){
153    entryUpdate.status.issueTimer := entryReg.status.issueTimer + 1.U
154    entryUpdate.status.deqPortIdx := entryReg.status.deqPortIdx
155  }
156  entryUpdate.status.psrc := entryReg.status.psrc
157  entryUpdate.status.srcType := entryReg.status.srcType
158  entryUpdate.status.fuType := entryReg.status.fuType
159  entryUpdate.status.robIdx := entryReg.status.robIdx
160  entryUpdate.status.issued := entryReg.status.issued // otherwise
161  when(!entryReg.status.srcReady){
162    entryUpdate.status.issued := false.B
163  }.elsewhen(io.issueResp.valid) {
164    when(RSFeedbackType.isStageSuccess(io.issueResp.bits.respType)) {
165      entryUpdate.status.issued := true.B
166    }.elsewhen(RSFeedbackType.isBlocked(io.issueResp.bits.respType)) {
167      entryUpdate.status.issued := false.B
168    }
169  }
170  entryUpdate.status.firstIssue := io.deqSel || entryReg.status.firstIssue
171  entryUpdate.status.blocked := false.B //todo
172  //remain imm and payload
173  entryUpdate.imm := entryReg.imm
174  entryUpdate.payload := entryReg.payload
175  if(params.needPc) {
176    entryUpdate.status.pc.get := entryReg.status.pc.get
177    entryUpdate.status.target.get := entryReg.status.target.get
178  }
179
180  //output
181  io.transEntry.valid := validReg && io.transSel && !flushed && !deqSuccess
182  io.transEntry.bits := entryUpdate
183  io.canIssue := entryReg.status.canIssue && validReg
184  io.clear := clear
185  io.fuType := entryReg.status.fuType
186  io.dataSource := entryReg.status.dataSources
187  io.srcWakeUpL1ExuOH.foreach(_ := entryReg.status.srcWakeUpL1ExuOH.get)
188  io.srcTimer.foreach(_ := entryReg.status.srcTimer.get)
189  io.valid := validReg
190  io.isFirstIssue := !entryReg.status.firstIssue
191  io.entry.valid := validReg
192  io.entry.bits := entryReg
193  io.robIdx := entryReg.status.robIdx
194  io.issueTimerRead := Mux(io.deqSel, 0.U, entryReg.status.issueTimer)
195  io.deqPortIdxRead := Mux(io.deqSel, io.deqPortIdxWrite, entryReg.status.deqPortIdx)
196}
197
198class EnqEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry
199  with HasCircularQueuePtrHelper {
200  val fromMem = io.fromMem.get
201
202  val memStatus = entryReg.status.mem.get
203  println("memStatus" + memStatus)
204  val memStatusNext = entryRegNext.status.mem.get
205  val memStatusUpdate = entryUpdate.status.mem.get
206
207  // load cannot be issued before older store, unless meet some condition
208  val blockedByOlderStore = isAfter(memStatusNext.sqIdx, fromMem.stIssuePtr)
209
210  val deqFailedForStdInvalid = io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.dataInvalid
211
212  val staWaitedReleased = Cat(
213    fromMem.memWaitUpdateReq.staIssue.map(x => x.valid && x.bits.uop.robIdx.value === memStatusNext.waitForRobIdx.value)
214  ).orR
215  val stdWaitedReleased = Cat(
216    fromMem.memWaitUpdateReq.stdIssue.map(x => x.valid && x.bits.uop.sqIdx.value === memStatusNext.waitForSqIdx.value)
217  ).orR
218  val olderStaNotViolate = staWaitedReleased && !memStatusNext.strictWait
219  val olderStdReady = stdWaitedReleased && memStatusNext.waitForStd
220  val waitStd = !olderStdReady
221  val waitSta = !olderStaNotViolate
222
223  when (io.enq.valid && enqReady) {
224    memStatusNext.waitForSqIdx := io.enq.bits.status.mem.get.waitForSqIdx
225    // update by lfst at dispatch stage
226    memStatusNext.waitForRobIdx := io.enq.bits.status.mem.get.waitForRobIdx
227    // new load inst don't known if it is blocked by store data ahead of it
228    memStatusNext.waitForStd := false.B
229    // update by ssit at rename stage
230    memStatusNext.strictWait := io.enq.bits.status.mem.get.strictWait
231    memStatusNext.sqIdx := io.enq.bits.status.mem.get.sqIdx
232  }.otherwise {
233    memStatusNext := memStatusUpdate
234  }
235
236  when(deqFailedForStdInvalid) {
237    memStatusUpdate.waitForSqIdx := io.issueResp.bits.dataInvalidSqIdx
238    memStatusUpdate.waitForRobIdx := memStatus.waitForRobIdx
239    memStatusUpdate.waitForStd := true.B
240    memStatusUpdate.strictWait := memStatus.strictWait
241    memStatusUpdate.sqIdx := memStatus.sqIdx
242  }.otherwise {
243    memStatusUpdate := memStatus
244  }
245
246  val shouldBlock = Mux(io.enq.valid && enqReady, io.enq.bits.status.blocked, entryReg.status.blocked)
247  val blockNotReleased = waitStd || waitSta
248  val respBlock = deqFailedForStdInvalid
249  entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock
250  entryUpdate.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock
251
252}
253
254object EnqEntry {
255  def apply(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = {
256    iqParams.schdType match {
257      case IntScheduler() => new EnqEntry()
258      case MemScheduler() =>
259        if (iqParams.StdCnt == 0) new EnqEntryMem()
260        else new EnqEntry()
261      case VfScheduler() => new EnqEntry()
262      case _ => null
263    }
264  }
265}