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