xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision 8557b6eccaf5d76a0b292ca79d5b79641dd8de83)
1package xiangshan.backend.issue
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import xiangshan.backend.rename.FreeListPtr
7import xiangshan.utils._
8
9trait IQConst extends HasXSParameter{
10  val iqSize = IssQueSize
11  val iqIdxWidth = log2Up(iqSize)
12}
13
14sealed abstract class IQBundle extends XSBundle with IQConst
15sealed abstract class IQModule extends XSModule with IQConst
16
17object OneCycleFire {
18  def apply(fire: Bool) = {
19    val valid = RegInit(false.B)
20    when (valid) { valid := false.B }
21    when (fire) { valid := true.B }
22    valid
23  }
24}
25
26class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int = 0, val fixedDelay: Int = 1, val fifo: Boolean = false) extends IQModule {
27
28  val useBypass = bypassCnt > 0
29  val src2Use = true
30  val src3Use = fuTypeInt==FuType.fmac.litValue()
31  val src2Listen = true
32  val src3Listen = fuTypeInt==FuType.fmac.litValue()
33
34  val io = IO(new Bundle() {
35    // flush Issue Queue
36    val redirect = Flipped(ValidIO(new Redirect))
37
38    // enq Ctrl sigs at dispatch-2
39    val enqCtrl = Flipped(DecoupledIO(new MicroOp))
40    // enq Data at next cycle (regfile has 1 cycle latency)
41    val enqData = Flipped(ValidIO(new ExuInput))
42
43    //  broadcast selected uop to other issue queues which has bypasses
44    val selectedUop = if(useBypass) ValidIO(new MicroOp) else null
45
46    // send to exu
47    val deq = DecoupledIO(new ExuInput)
48
49    // listen to write back bus
50    val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput)))
51
52    // use bypass uops to speculative wake-up
53    val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) else null
54    val bypassData = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new ExuOutput))) else null
55
56    // to Dispatch
57    val numExist = Output(UInt(iqIdxWidth.W))
58  })
59
60  val srcAllNum = 3
61  val srcUseNum = 1 + (if(src2Use) 1 else 0) + (if(src3Use) 1 else 0)// when src2Use is false, then src3Use must be false
62  val srcListenNum = 1 + (if(src2Listen) 1 else 0) + (if(src3Listen) 1 else 0) // when src2Listen is false, then src3Listen must be false
63  // when use is false, Listen must be false
64  require(!(!src2Use && src2Listen))
65  require(!(!src3Use && src3Listen))
66  require(!(!src2Use && src3Use))
67  require(!(!src2Listen && src3Listen))
68
69  // Issue Queue
70  // val issQue = IndexableMem(iqSize, new ExuInput, mem = false, init = None)
71  val issQue = Mem(iqSize, new ExuInput)
72  // val issQue = Reg(Vec(iqSize, new ExuInput))
73  val validQue = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
74  val idQue = RegInit(VecInit((0 until iqSize).map(_.U(iqIdxWidth.W))))
75  val idValidQue = VecInit((0 until iqSize).map(i => validQue(idQue(i)))).asUInt
76  val tailAll = RegInit(0.U((iqIdxWidth+1).W))
77  val tail = tailAll(iqIdxWidth-1, 0)
78  val full = tailAll(iqIdxWidth)
79
80  // alias failed, turn to independent storage(Reg)
81  val psrc = VecInit(List.tabulate(iqSize)(i => VecInit(List(issQue(i.U).uop.psrc1, issQue(i.U).uop.psrc2, issQue(i.U).uop.psrc3)))) // NOTE: indexed by IssQue's idx
82  val srcRdyVec = Reg(Vec(iqSize, Vec(srcAllNum, Bool()))) // NOTE: indexed by IssQue's idx
83  val srcData = Reg(Vec(iqSize, Vec(srcAllNum, UInt(XLEN.W)))) // NOTE: indexed by IssQue's idx
84  val srcRdy = VecInit(srcRdyVec.map(a => if(src3Listen) { if(src2Listen) a(0)&&a(1)&&a(2) else a(0)&&a(2) } else  { if(src2Listen) a(0)&&a(1) else a(0) }))// NOTE: indexed by IssQue's idx
85  val srcIdRdy = VecInit((0 until iqSize).map(i => srcRdy(idQue(i)))).asUInt // NOTE: indexed by IdQue's idx
86  val srcType = List.tabulate(iqSize)(i => List(issQue(i).uop.ctrl.src1Type, issQue(i).uop.ctrl.src2Type, issQue(i).uop.ctrl.src3Type)) // NOTE: indexed by IssQue's idx
87
88  // val srcDataWire = Wire(srcData)
89  val srcDataWire = Wire(Vec(iqSize, Vec(srcAllNum, UInt(XLEN.W)))) // NOTE: indexed by IssQue's idx
90  srcDataWire := srcData
91  srcData := srcDataWire
92
93  // there are three stages
94  // |-------------|--------------------|--------------|
95  // |Enq:get state|Deq: select/get data| fire stage   |
96  // |-------------|--------------------|--------------|
97
98  //-----------------------------------------
99  // Enqueue
100  //-----------------------------------------
101  val enqRedHit = Wire(Bool())
102  val enqFire = io.enqCtrl.fire() && !enqRedHit
103  val deqFire = io.deq.fire()
104  val popOne = Wire(Bool())
105  io.enqCtrl.ready := !full || popOne
106  val enqSelIq = Wire(UInt(iqIdxWidth.W))
107  val enqSrcRdy = List(Mux(SrcType.isPcImm(io.enqCtrl.bits.ctrl.src1Type), true.B, io.enqCtrl.bits.src1State === SrcState.rdy),
108                       Mux(SrcType.isPcImm(io.enqCtrl.bits.ctrl.src2Type), true.B, io.enqCtrl.bits.src2State === SrcState.rdy),
109                       Mux(SrcType.isPcImm(io.enqCtrl.bits.ctrl.src3Type), true.B, io.enqCtrl.bits.src3State === SrcState.rdy))
110
111  // state enq
112  when (enqFire) {
113    issQue(enqSelIq).uop := io.enqCtrl.bits
114    validQue(enqSelIq) := true.B
115    assert(!validQue(enqSelIq) || popOne/* && idQue(deqSel)===enqSelIq*/)
116
117    srcRdyVec(enqSelIq)(0) := enqSrcRdy(0)
118    if(src2Listen) { srcRdyVec(enqSelIq)(1) := enqSrcRdy(1) }
119    if(src3Listen) { srcRdyVec(enqSelIq)(2) := enqSrcRdy(2) }
120  }
121
122  // data enq
123  val enqSelIqNext = RegEnable(enqSelIq, enqFire)
124  // val enqSelIqNext = RegNext(enqSelIq)
125  val enqFireNext = RegInit(false.B)
126  when (enqFireNext) { enqFireNext := false.B }
127  when (enqFire) { enqFireNext := true.B }
128
129  val enqDataVec = List(io.enqData.bits.src1, io.enqData.bits.src2, io.enqData.bits.src3)
130  when (enqFireNext) {
131    for(i <- 0 until srcUseNum) {
132      srcDataWire(enqSelIqNext)(i) := enqDataVec(i)
133    }
134  }
135
136  //-----------------------------------------
137  // tail
138  //-----------------------------------------
139  val tailInc = enqFire
140  val tailDec = popOne
141  val tailKeep = tailInc === tailDec
142  val tailAdd = tailAll + 1.U
143  val tailSub = tailAll - 1.U
144  tailAll := Mux(tailKeep, tailAll, Mux(tailInc, tailAdd, tailSub))
145  assert(tailAll < 9.U)
146  // Select to Dequeue
147  val deqSel = if (fifo) 0.U else PriorityEncoder(idValidQue & srcIdRdy) //may not need idx, just need oneHot, idx by IdQue's idx
148  val deqSelIq = idQue(deqSel)
149  val deqSelOH = PriorityEncoderOH(idValidQue & srcIdRdy)
150  val has1Rdy = if (fifo) idValidQue(deqSel) && srcIdRdy(deqSel) else ParallelOR((validQue.asUInt & srcRdy.asUInt).asBools).asBool()
151
152  //-----------------------------------------
153  // idQue Move
154  //-----------------------------------------
155  def UIntToMHP(in: UInt) = {
156    // UInt to Multi-Hot plus 1: 1.U -> "11".U; 2.U(2.W) -> "0111".U; 3.U(3.W) -> "00001111".W
157    val a = Seq.fill(in.getWidth)(2).product
158    val s = (1 << (a-1)).S
159    Reverse((s(a-1,0).asSInt >> in)(a-1,0).asUInt)
160  }
161  def UIntToMH(in: UInt) = {
162    val a = Seq.fill(in.getWidth)(2).product
163    val s = (1 << (a-1)).S
164    Reverse((s(a-1,0).asSInt >> in)(a-1,0).asUInt) ^ UIntToOH(in)
165  }
166  def PriorityDot(in: UInt) = {
167    // "1100".U -> "0111".U; "1010".U -> "0011".U; "0000".U -> "0000".U
168    val a = Array.fill(iqSize)(1)
169    for(i <- 1 until in.getWidth) {
170      a(i) = a(i-1)*2 + 1
171    }
172    Mux(in===0.U, 0.U(in.getWidth.W), PriorityMux(in, a.map(_.U(in.getWidth.W))))
173  }
174  val tailDot = Mux(full, VecInit(Seq.fill(iqSize)(true.B)).asUInt, UIntToMHP(tail))
175  val tailDot2 = Mux(full, VecInit(Seq.fill(iqSize)(true.B)).asUInt, UIntToMH(tail))
176  val selDot = UIntToMHP(deqSel) // FIXIT: PriorityEncoder -> UIntToMHP means long latency
177  val nonValid = ~(idValidQue | ~tailDot2)
178  val popSel = PriorityEncoder(nonValid) // Note: idxed by IDque's index
179  val popDot = PriorityDot(nonValid)
180  val isPop = ParallelOR(nonValid.asBools).asBool()
181  val moveDot = Mux(isPop, tailDot ^ popDot, tailDot ^ selDot)
182
183  assert(!(popOne&&moveDot(0)))
184  when (popOne) {
185    for(i <- 1 until iqSize) {
186      when (moveDot(i)) { idQue(i-1) := idQue(i) }
187    }
188    val ptr_tmp = Mux(full, VecInit(Seq.fill(iqIdxWidth)(true.B)).asUInt, tail)
189    idQue(ptr_tmp) := idQue(Mux(isPop, popSel, deqSel))
190  }
191  assert(ParallelAND(List.tabulate(iqSize)(i => ParallelOR(List.tabulate(iqSize)(j => i.U === idQue(j))))).asBool)
192
193  //-----------------------------------------
194  // Redirect
195  //-----------------------------------------
196  // redirect enq
197  enqRedHit := io.redirect.valid && io.enqCtrl.bits.brTag.needFlush(io.redirect)
198
199  // redirect issQue
200  val redHitVec = List.tabulate(iqSize)(i => issQue(i).uop.brTag.needFlush(io.redirect))
201  for (i <- validQue.indices) {
202    when (redHitVec(i) && validQue(i)) {
203      validQue(i) := false.B
204    }
205  }
206  // reditect deq(issToExu)
207  val redIdHitVec = List.tabulate(iqSize)(i => issQue(idQue(i)).uop.brTag.needFlush(io.redirect))
208  val selIsRed = ParallelOR((deqSelOH & VecInit(redIdHitVec).asUInt).asBools).asBool
209
210  //-----------------------------------------
211  // Dequeue (or to Issue Stage)
212  //-----------------------------------------
213  val issueToExu = Reg(new ExuInput)
214  val issueToExuValid = RegInit(false.B)
215  val deqFlushHit = issueToExu.uop.brTag.needFlush(io.redirect)
216  val deqCanIn = !issueToExuValid || io.deq.ready || deqFlushHit
217
218  val toIssFire = deqCanIn && has1Rdy && !isPop && !selIsRed
219  popOne := deqCanIn && (has1Rdy || isPop) // send a empty or valid term to issueStage
220
221  when (toIssFire) {
222    issueToExu := issQue(deqSelIq)
223    issueToExuValid := true.B
224    validQue(deqSelIq) := enqFire && enqSelIq===deqSelIq
225    assert(validQue(deqSelIq))
226    issueToExu.src1 := srcDataWire(deqSelIq)(0)
227    if (src2Use) { issueToExu.src2 := srcDataWire(deqSelIq)(1) } else { issueToExu.src2 := DontCare }
228    if (src3Use) { issueToExu.src3 := srcDataWire(deqSelIq)(2) } else { issueToExu.src3 := DontCare }
229  }
230  when ((deqFire || deqFlushHit) && !toIssFire) {
231    issueToExuValid := false.B
232  }
233
234  io.deq.valid := issueToExuValid && !deqFlushHit
235  io.deq.bits := issueToExu
236
237  enqSelIq := Mux(full,
238    Mux(isPop,
239      idQue(popSel),
240      deqSelIq
241    ),
242    idQue(tail)
243  ) // Note: direct by IQue's idx, different from deqSel
244
245  io.numExist := Mux(tailAll === iqSize.U, (iqSize-1).U, tailAll)
246  assert(tailAll < 9.U)
247
248  //-----------------------------------------
249  // Issue with No Delay
250  //-----------------------------------------
251  // when enq is ready && no other rdy && no pop &&  fireStage is ready && no flush
252  // send out directly without store the data
253  val enqAlreadyRdy = if(src3Listen) { if(src2Listen) enqSrcRdy(0)&&enqSrcRdy(1)&&enqSrcRdy(2) else enqSrcRdy(0)&&enqSrcRdy(2) } else  { if(src2Listen) enqSrcRdy(0)&&enqSrcRdy(1) else enqSrcRdy(0) }
254  val enqALRdyNext = OneCycleFire(enqAlreadyRdy && enqFire)
255  val enqSendFlushHit = issQue(enqSelIqNext).uop.brTag.needFlush(io.redirect)
256  val enqSendEnable = if(fifo) { RegNext(tailAll===0.U) && enqALRdyNext && (!issueToExuValid || deqFlushHit) && (enqSelIqNext === deqSelIq) && !isPop && !enqSendFlushHit/* && has1Rdy*//* && io.deq.ready*/ } else { enqALRdyNext && (!issueToExuValid || deqFlushHit) && (enqSelIqNext === deqSelIq) && !isPop && !enqSendFlushHit/* && has1Rdy*//* && io.deq.ready*/ } // FIXME: has1Rdy has combination loop
257  when (enqSendEnable) {
258    io.deq.valid := true.B
259    io.deq.bits := issQue(enqSelIqNext)
260    io.deq.bits.src1 := enqDataVec(0)
261    if (src2Use) { io.deq.bits.src2 := enqDataVec(1) }
262    if (src3Use) { io.deq.bits.src3 := enqDataVec(2) }
263    issueToExuValid := false.B
264    when (!io.deq.ready) { // if Func Unit is not ready, store it to FireStage
265      issueToExuValid := true.B
266    }
267  }
268
269  //-----------------------------------------
270  // Wakeup and Bypass
271  //-----------------------------------------
272  if (wakeupCnt > 0) {
273    val cdbValid = io.wakeUpPorts.map(_.valid)
274    val cdbData  = io.wakeUpPorts.map(_.bits.data)
275    val cdbPdest = io.wakeUpPorts.map(_.bits.uop.pdest)
276    val cdbrfWen = io.wakeUpPorts.map(_.bits.uop.ctrl.rfWen)
277    val cdbfpWen = io.wakeUpPorts.map(_.bits.uop.ctrl.fpWen)
278
279    for(i <- idQue.indices) { // Should be IssQue.indices but Mem() does not support
280      for(j <- 0 until srcListenNum) {
281        val hitVec = cdbValid.indices.map(k => psrc(i)(j) === cdbPdest(k) && cdbValid(k) && (srcType(i)(j)===SrcType.reg && cdbrfWen(k) || srcType(i)(j)===SrcType.fp && cdbfpWen(k)))
282        val hit = ParallelOR(hitVec).asBool
283        val data = ParallelMux(hitVec zip cdbData)
284        when (validQue(i) && !srcRdyVec(i)(j) && hit) {
285          srcDataWire(i)(j) := data
286          srcRdyVec(i)(j) := true.B
287        }
288        // XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "WakeUp: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b Data:%x\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt, data)
289        for (k <- cdbValid.indices) {
290          XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k), "WakeUpHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, cdbData(k), io.wakeUpPorts(k).bits.uop.cf.pc, io.wakeUpPorts(k).bits.uop.roqIdx)
291        }
292      }
293    }
294  }
295  if (useBypass) {
296    val bpPdest = io.bypassUops.map(_.bits.pdest)
297    val bpValid = io.bypassUops.map(_.valid)
298    val bpData  = io.bypassData.map(_.bits.data)
299    val bprfWen = io.bypassUops.map(_.bits.ctrl.rfWen)
300    val bpfpWen = io.bypassUops.map(_.bits.ctrl.fpWen)
301
302    for (i <- idQue.indices) { // Should be IssQue.indices but Mem() does not support
303      for (j <- 0 until srcListenNum) {
304        val hitVec = bpValid.indices.map(k => psrc(i)(j) === bpPdest(k) && bpValid(k) && (srcType(i)(j)===SrcType.reg && bprfWen(k) || srcType(i)(j)===SrcType.fp && bpfpWen(k)))
305        val hitVecNext = hitVec.map(RegNext(_))
306        val hit = ParallelOR(hitVec).asBool
307        when (validQue(i) && !srcRdyVec(i)(j) && hit) {
308          srcRdyVec(i)(j) := true.B
309        }
310        when (RegNext(validQue(i) && !srcRdyVec(i)(j) && hit)) {
311          srcDataWire(i)(j) := PriorityMux(hitVecNext zip bpData)
312        }
313        // XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "BypassCtrl: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt)
314        for (k <- bpValid.indices) {
315          XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k), "BypassCtrlHit: IQIdx:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
316        }
317        // XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit), "BypassData: Sel:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", i.U, j.U, psrc(i)(j), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
318        for (k <- bpValid.indices) {
319          XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k)), "BypassDataHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
320        }
321      }
322    }
323
324    // Enqueue Bypass
325    val enqCtrl = io.enqCtrl
326    val enqPsrc = List(enqCtrl.bits.psrc1, enqCtrl.bits.psrc2, enqCtrl.bits.psrc3)
327    val enqSrcType = List(enqCtrl.bits.ctrl.src1Type, enqCtrl.bits.ctrl.src2Type, enqCtrl.bits.ctrl.src3Type)
328    for (i <- 0 until srcListenNum) {
329      val hitVec = bpValid.indices.map(j => enqPsrc(i)===bpPdest(j) && bpValid(j) && (enqSrcType(i)===SrcType.reg && bprfWen(j) || enqSrcType(i)===SrcType.fp && bpfpWen(j)))
330      val hitVecNext = hitVec.map(RegNext(_))
331      val hit = ParallelOR(hitVec).asBool
332      when (enqFire && hit && !enqSrcRdy(i)) {
333        srcRdyVec(enqSelIq)(i) := true.B
334      }
335      when (RegNext(enqFire && hit && !enqSrcRdy(i))) {
336        srcDataWire(enqSelIqNext)(i) := ParallelMux(hitVecNext zip bpData)
337      }
338      // XSDebug(enqFire && hit, "EnqBypassCtrl: enqSelIq:%d Src:(%d|%d) Hit:%d HitVec:%b \n", enqSelIq, i.U, enqPsrc(i), hit, VecInit(hitVec).asUInt)
339      for (k <- bpValid.indices) {
340        XSDebug(enqFire && hit && !enqSrcRdy(i) && hitVec(k), "EnqBypassCtrlHit: enqSelIq:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", enqSelIq, i.U, enqPsrc(i), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
341      }
342      // XSDebug(RegNext(enqFire && hit), "EnqBypassData: enqSelIqNext:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", enqSelIqNext, i.U, enqPsrc(i), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
343      for (k <- bpValid.indices) {
344        XSDebug(RegNext(enqFire && hit && !enqSrcRdy(i) && hitVec(k)), "EnqBypassDataHit: enqSelIq:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", enqSelIq, i.U, enqPsrc(i), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
345      }
346    }
347
348    // send out bypass
349    require(fixedDelay==1) // only support fixedDelay is 1 now
350    val sel = io.selectedUop
351    sel.valid := toIssFire
352    sel.bits := DontCare
353    sel.bits.pdest := issQue(deqSelIq).uop.pdest
354    sel.bits.cf.pc := issQue(deqSelIq).uop.cf.pc
355    sel.bits.roqIdx := issQue(deqSelIq).uop.roqIdx
356    sel.bits.ctrl.rfWen := issQue(deqSelIq).uop.ctrl.rfWen
357    sel.bits.ctrl.fpWen := issQue(deqSelIq).uop.ctrl.fpWen
358  }
359  XSInfo(io.redirect.valid, "Redirect: valid:%d isExp:%d brTag:%d redHitVec:%b redIdHitVec:%b enqHit:%d selIsRed:%d\n", io.redirect.valid, io.redirect.bits.isException, io.redirect.bits.brTag.value, VecInit(redHitVec).asUInt, VecInit(redIdHitVec).asUInt, enqRedHit, selIsRed)
360  XSInfo(enqFire, s"EnqCtrl(%d %d) enqSelIq:%d Psrc/Rdy(%d:%d %d:%d %d:%d) Dest:%d oldDest:%d pc:%x roqIdx:%x flptr:%d\n", io.enqCtrl.valid, io.enqCtrl.ready, enqSelIq
361    , io.enqCtrl.bits.psrc1, io.enqCtrl.bits.src1State, io.enqCtrl.bits.psrc2, io.enqCtrl.bits.src2State, io.enqCtrl.bits.psrc3, io.enqCtrl.bits.src3State, io.enqCtrl.bits.pdest, io.enqCtrl.bits.old_pdest, io.enqCtrl.bits.cf.pc, io.enqCtrl.bits.roqIdx, io.enqCtrl.bits.freelistAllocPtr.value)
362  XSInfo(enqFireNext, "EnqData: src1:%x src2:%x src3:%x pc:%x roqIdx:%x(for last cycle's Ctrl)\n", io.enqData.bits.src1, io.enqData.bits.src2, io.enqData.bits.src3, issQue(enqSelIqNext).uop.cf.pc, issQue(enqSelIqNext).uop.roqIdx)
363  XSInfo(deqFire, "Deq:(%d %d) [%d|%x][%d|%x][%d|%x] pdest:%d pc:%x roqIdx:%x flptr:%x\n", io.deq.valid, io.deq.ready, io.deq.bits.uop.psrc1, io.deq.bits.src1, io.deq.bits.uop.psrc2, io.deq.bits.src2, io.deq.bits.uop.psrc3, io.deq.bits.src3, io.deq.bits.uop.pdest, io.deq.bits.uop.cf.pc, io.deq.bits.uop.roqIdx, io.deq.bits.uop.freelistAllocPtr.value)
364  XSDebug("tailAll:%d KID(%d%d%d) tailDot:%b tailDot2:%b selDot:%b popDot:%b moveDot:%b In(%d %d) Out(%d %d)\n", tailAll, tailKeep, tailInc, tailDec, tailDot, tailDot2, selDot, popDot, moveDot, io.enqCtrl.valid, io.enqCtrl.ready, io.deq.valid, io.deq.ready)
365  XSInfo(issueToExuValid, "FireStage:Out(%d %d) src1(%d|%x) src2(%d|%x) src3(%d|%x) deqFlush:%d pc:%x roqIdx:%d\n", io.deq.valid, io.deq.ready, issueToExu.uop.psrc1, issueToExu.src1, issueToExu.uop.psrc2, issueToExu.src2, issueToExu.uop.psrc3, issueToExu.src3, deqFlushHit, issueToExu.uop.cf.pc, issueToExu.uop.roqIdx)
366  if(useBypass) {
367    XSDebug("popOne:%d isPop:%d popSel:%d deqSel:%d deqCanIn:%d toIssFire:%d has1Rdy:%d selIsRed:%d nonValid:%b SelUop:(%d, %d)\n", popOne, isPop, popSel, deqSel, deqCanIn, toIssFire, has1Rdy, selIsRed, nonValid, io.selectedUop.valid, io.selectedUop.bits.pdest)
368  } else {
369    XSDebug("popOne:%d isPop:%d popSel:%d deqSel:%d deqCanIn:%d toIssFire:%d has1Rdy:%d selIsRed:%d nonValid:%b\n", popOne, isPop, popSel, deqSel, deqCanIn, toIssFire, has1Rdy, selIsRed, nonValid)
370  }
371  XSDebug(enqSendEnable, p"NoDelayIss: enqALRdy:${enqAlreadyRdy} *Next:${enqALRdyNext} En:${enqSendEnable} flush:${enqSendFlushHit} enqSelIqNext:${enqSelIqNext} deqSelIq:${deqSelIq} deqReady:${io.deq.ready}\n")
372  XSDebug("id|v|r|psrc|r|   src1         |psrc|r|   src2         |psrc|r|   src3         |brTag|    pc    |roqIdx FuType:%x\n", fuTypeInt.U)
373  for (i <- 0 until iqSize) {
374    when (i.U===tail && tailAll=/=8.U) {
375      XSDebug("%d |%d|%d| %d|%b|%x| %d|%b|%x| %d|%b|%x| %x |%x|%x <-\n",
376        idQue(i),
377        idValidQue(i),
378        srcRdy(idQue(i)),
379        psrc(idQue(i))(0),
380        srcRdyVec(idQue(i))(0),
381        srcData(idQue(i))(0),
382        psrc(idQue(i))(1),
383        srcRdyVec(idQue(i))(1),
384        srcData(idQue(i))(1),
385        psrc(idQue(i))(2),
386        srcRdyVec(idQue(i))(2),
387        srcData(idQue(i))(2),
388        issQue(idQue(i)).uop.brTag.value,
389        issQue(idQue(i)).uop.cf.pc,
390        issQue(idQue(i)).uop.roqIdx
391      )
392    }.otherwise {
393      XSDebug("%d |%d|%d| %d|%b|%x| %d|%b|%x| %d|%b|%x| %x |%x|%x\n",
394        idQue(i),
395        idValidQue(i),
396        srcRdy(idQue(i)),
397        psrc(idQue(i))(0),
398        srcRdyVec(idQue(i))(0),
399        srcData(idQue(i))(0),
400        psrc(idQue(i))(1),
401        srcRdyVec(idQue(i))(1),
402        srcData(idQue(i))(1),
403        psrc(idQue(i))(2),
404        srcRdyVec(idQue(i))(2),
405        srcData(idQue(i))(2),
406        issQue(idQue(i)).uop.brTag.value,
407        issQue(idQue(i)).uop.cf.pc,
408        issQue(idQue(i)).uop.roqIdx
409      )
410    }
411  }
412}