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