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