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