xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision 015fbae33410bd33d4801fd420ae082ec58e15a0)
1package xiangshan.backend.issue
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import xiangshan.backend.rename.FreeListPtr
7import xiangshan.utils._
8
9trait IQConst{
10  val iqSize = 8
11  val iqIdxWidth = log2Up(iqSize)
12}
13
14sealed abstract class IQBundle extends XSBundle with IQConst
15sealed abstract class IQModule extends XSModule with IQConst //with NeedImpl
16
17sealed class CmpInputBundle extends IQBundle{
18  val instRdy = Input(Bool())
19  val roqIdx  = Input(UInt(RoqIdxWidth.W))
20  val iqIdx   = Input(UInt(iqIdxWidth.W))
21
22  def apply(instRdy: Bool,roqIdx: UInt,iqIdx: UInt ) = {
23    this.instRdy := instRdy
24    this.roqIdx := roqIdx
25    this.iqIdx := iqIdx
26    this
27  }
28}
29
30
31object CompareCircuitUnit{
32  def apply(in1: CmpInputBundle, in2: CmpInputBundle) = {
33    val out = Wire(new CmpInputBundle)
34    val roqIdx1 = in1.roqIdx
35    val roqIdx2 = in2.roqIdx
36    val iqIdx1  = in1.iqIdx
37    val iqIdx2  = in2.iqIdx
38
39    val inst1Rdy = in1.instRdy
40    val inst2Rdy = in2.instRdy
41
42    out.instRdy := inst1Rdy | inst2Rdy
43    out.roqIdx := roqIdx2
44    out.iqIdx := iqIdx2
45
46    when((inst1Rdy && !inst2Rdy) || (inst1Rdy && inst2Rdy && (roqIdx1 < roqIdx2))){
47      out.roqIdx := roqIdx1
48      out.iqIdx := iqIdx1
49    }
50    out
51  }
52}
53
54object ParallelSel {
55  def apply(iq: Seq[CmpInputBundle]):  CmpInputBundle = {
56    iq match {
57      case Seq(a) => a
58      case Seq(a, b) => CompareCircuitUnit(a, b)
59      case _ =>
60        apply(Seq(apply(iq take iq.size/2), apply(iq drop iq.size/2)))
61    }
62  }
63}
64
65class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int = 0, val fixedDelay: Int = 1) extends IQModule {
66
67  val useBypass = bypassCnt > 0
68
69  val io = IO(new Bundle() {
70    // flush Issue Queue
71    val redirect = Flipped(ValidIO(new Redirect))
72
73    // enq Ctrl sigs at dispatch-2
74    val enqCtrl = Flipped(DecoupledIO(new MicroOp))
75    // enq Data at next cycle (regfile has 1 cycle latency)
76    val enqData = Flipped(ValidIO(new ExuInput))
77
78    //  broadcast selected uop to other issue queues which has bypasses
79    val selectedUop = if(useBypass) ValidIO(new MicroOp) else null
80
81    // send to exu
82    val deq = DecoupledIO(new ExuInput)
83
84    // listen to write back bus
85    val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput)))
86
87    // use bypass uops to speculative wake-up
88    val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) else null
89    val bypassData = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new ExuOutput))) else null
90  })
91  //---------------------------------------------------------
92  // Issue Queue
93  //---------------------------------------------------------
94
95  //Tag Queue
96  val ctrlFlow = Mem(iqSize,new CtrlFlow)
97  val ctrlSig = Mem(iqSize,new CtrlSignals)
98  val brMask  = Reg(Vec(iqSize, UInt(BrqSize.W)))
99  val brTag  =  Reg(Vec(iqSize, UInt(BrTagWidth.W)))
100  val validReg = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
101  val validWillFalse= WireInit(VecInit(Seq.fill(iqSize)(false.B)))
102  val valid = validReg.asUInt & ~validWillFalse.asUInt
103  val src1Rdy = Reg(Vec(iqSize, Bool()))
104  val src2Rdy = Reg(Vec(iqSize, Bool()))
105  val src3Rdy = Reg(Vec(iqSize, Bool()))
106  val prfSrc1 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
107  val prfSrc2 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
108  val prfSrc3 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
109  val prfDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
110  val oldPDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
111  val freelistAllocPtr = Reg(Vec(iqSize, new FreeListPtr))
112  val roqIdx  = Reg(Vec(iqSize, UInt(RoqIdxWidth.W)))
113
114  val instRdy = WireInit(VecInit(List.tabulate(iqSize)(i => src1Rdy(i) && src2Rdy(i) && src3Rdy(i)&& valid(i))))
115
116
117  //tag enqueue
118  val iqEmty = !valid.asUInt.orR
119  val iqFull =  valid.asUInt.andR
120  val iqAllowIn = !iqFull
121  io.enqCtrl.ready := iqAllowIn
122
123  //enqueue pointer
124  val emptySlot = ~valid.asUInt
125  val enqueueSelect = PriorityEncoder(emptySlot)
126  //assert(!(io.enqCtrl.valid && io.redirect.valid),"enqueue valid should be false when redirect valid")
127  XSError(io.enqCtrl.valid && io.redirect.valid,"enqueue valid should be false when redirect valid")
128  val srcEnqRdy = WireInit(VecInit(false.B, false.B, false.B))
129
130  srcEnqRdy(0) := Mux(io.enqCtrl.bits.ctrl.src1Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src1State === SrcState.rdy)
131  srcEnqRdy(1) := Mux(io.enqCtrl.bits.ctrl.src2Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src2State === SrcState.rdy)
132  //TODO:
133  if(fuTypeInt != FuType.fmac.litValue()){ srcEnqRdy(2) := true.B}
134  else{srcEnqRdy(2) := Mux(io.enqCtrl.bits.ctrl.src3Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src3State === SrcState.rdy)}
135
136  when (io.enqCtrl.fire()) {
137    ctrlFlow(enqueueSelect) := io.enqCtrl.bits.cf
138    ctrlSig(enqueueSelect) := io.enqCtrl.bits.ctrl
139    brMask(enqueueSelect) := io.enqCtrl.bits.brMask
140    brTag(enqueueSelect) := io.enqCtrl.bits.brTag
141    validReg(enqueueSelect) := true.B
142    src1Rdy(enqueueSelect) := srcEnqRdy(0)
143    src2Rdy(enqueueSelect) := srcEnqRdy(1)
144    src3Rdy(enqueueSelect) := srcEnqRdy(2)
145    prfSrc1(enqueueSelect) := io.enqCtrl.bits.psrc1
146    prfSrc2(enqueueSelect) := io.enqCtrl.bits.psrc2
147    prfSrc3(enqueueSelect) := io.enqCtrl.bits.psrc3
148    prfDest(enqueueSelect) := io.enqCtrl.bits.pdest
149    oldPDest(enqueueSelect) := io.enqCtrl.bits.old_pdest
150    freelistAllocPtr(enqueueSelect) := io.enqCtrl.bits.freelistAllocPtr
151    roqIdx(enqueueSelect) := io.enqCtrl.bits.roqIdx
152    XSDebug("[IQ enq]: enqSelect:%d | s1Rd:%d s2Rd:%d s3Rd:%d\n",enqueueSelect.asUInt,
153                                                                        (io.enqCtrl.bits.src1State === SrcState.rdy),
154                                                                        (io.enqCtrl.bits.src2State === SrcState.rdy),
155                                                                        (io.enqCtrl.bits.src3State === SrcState.rdy))
156
157  }
158
159  //Data Queue
160  val src1Data = Reg(Vec(iqSize, UInt(XLEN.W)))
161  val src2Data = Reg(Vec(iqSize, UInt(XLEN.W)))
162  val src3Data = Reg(Vec(iqSize, UInt(XLEN.W)))
163
164
165  val enqSelNext = RegNext(enqueueSelect)
166  val enqFireNext = RegNext(io.enqCtrl.fire())
167
168  // Read RegFile
169  //Ready data will written at next cycle
170  when (enqFireNext) {
171    when(src1Rdy(enqSelNext)){src1Data(enqSelNext) := io.enqData.bits.src1}
172    when(src2Rdy(enqSelNext)){src2Data(enqSelNext) := io.enqData.bits.src2}
173    when(src3Rdy(enqSelNext)){src3Data(enqSelNext) := io.enqData.bits.src3}
174  }
175
176  val psrc = List.tabulate(iqSize)(i => List(prfSrc1(i), prfSrc2(i), prfSrc3(i)))
177  XSDebug("[Reg info-ENQ] enqSelNext:%d | enqFireNext:%d \n",enqSelNext,enqFireNext)
178  XSDebug("[IQ content] valid vr vf| pc  insruction |[rdy|psrc]  src1 |  [rdy|psrc]  src2 |  [rdy|psrc]  src3  |  pdest  \n")
179  for(i <- 0 to (iqSize -1)) {
180    val ins = ctrlFlow(i).instr
181    val pc = ctrlFlow(i).pc
182    XSDebug(valid(i),
183      "[IQ content][%d] %d%d%d |%x  %x|[%d|%d]%x|[%d|%d]%x|[%d|%d]%x| %d  valid|\n",
184      i.asUInt, valid(i), validReg(i), validWillFalse(i), pc, ins, src1Rdy(i), psrc(i)(0), src1Data(i),
185      src2Rdy(i), psrc(i)(1), src2Data(i), src3Rdy(i), psrc(i)(2), src3Data(i),prfDest(i))
186    XSDebug(validReg(i) && validWillFalse(i),
187      "[IQ content][%d] %d%d%d |%x  %x|[%d|%d]%x|[%d|%d]%x|[%d|%d]%x| %d  valid will be False|\n",
188      i.asUInt, valid(i), validReg(i), validWillFalse(i), pc, ins, src1Rdy(i), psrc(i)(0), src1Data(i),
189      src2Rdy(i), psrc(i)(1), src2Data(i), src3Rdy(i), psrc(i)(2), src3Data(i), prfDest(i))
190    XSDebug("[IQ content][%d] %d%d%d |%x  %x|[%d|%d]%x|[%d|%d]%x|[%d|%d]%x| %d\n",
191      i.asUInt, valid(i), validReg(i), validWillFalse(i), pc, ins, src1Rdy(i), psrc(i)(0), src1Data(i),
192      src2Rdy(i), psrc(i)(1), src2Data(i), src3Rdy(i), psrc(i)(2), src3Data(i),prfDest(i))
193  }
194  // From Common Data Bus(wakeUpPort)
195  // chisel claims that firrtl will optimize Mux1H to and/or tree
196  // TODO: ignore ALU'cdb srcRdy, for byPass has done it
197  if(wakeupCnt > 0) {
198    val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid)
199    val cdbrfWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.rfWen) // FIXME: handle fpWen
200    val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data)
201    val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest)
202
203    val srcNum = 3
204    val prfSrc = List(prfSrc1, prfSrc2, prfSrc3)
205    val srcRdy = List(src1Rdy, src2Rdy, src3Rdy)
206    val srcData = List(src1Data, src2Data, src3Data)
207    val srcHitVec = List.tabulate(srcNum)(k =>
208                      List.tabulate(iqSize)(i =>
209                        List.tabulate(wakeupCnt)(j =>
210                          (prfSrc(k)(i) === cdbPdest(j)) && (cdbValid(j) && cdbrfWen(i)))))
211    val srcHit =  List.tabulate(srcNum)(k =>
212                    List.tabulate(iqSize)(i =>
213                      ParallelOR(srcHitVec(k)(i)).asBool()))
214                      // VecInit(srcHitVec(k)(i)).asUInt.orR))
215    for(k <- 0 until srcNum){
216      for(i <- 0 until iqSize)( when (valid(i)) {
217        when(!srcRdy(k)(i) && srcHit(k)(i)) {
218          srcRdy(k)(i) := true.B
219          // srcData(k)(i) := Mux1H(srcHitVec(k)(i), cdbData)
220          srcData(k)(i) := ParallelMux(srcHitVec(k)(i) zip cdbData)
221        }
222        XSDebug(srcHit(k)(i), "Wakeup: Sel:%d Src:%d|%d data:%x srcHitVec:%b cdbValid:%b cdbrfWen:%b\n",
223          i.U, k.U, prfSrc(k)(i), ParallelMux(srcHitVec(k)(i) zip cdbData), VecInit(srcHitVec(k)(i)).asUInt, VecInit(cdbValid).asUInt, VecInit(cdbrfWen).asUInt)
224        for (j <- 0 until wakeupCnt) {
225          XSDebug(srcHitVec(k)(i)(j), "WakeUpHit: Sel:%d Src:%d|%d Wake:%d data:%x valid:%d rfWen:%d roqIdx:%x\n", i.U, k.U, prfSrc(k)(i), j.U, cdbData(j), cdbValid(j), cdbrfWen(j), io.wakeUpPorts(j).bits.uop.roqIdx)
226        }
227      })
228    }
229
230    // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself)
231    // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag
232    // byPassUops is one cycle before byPassDatas
233    if (bypassCnt > 0) {
234      val bypassPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest)
235      val bypassrfWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.rfWen)
236      val bypassValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) // may only need valid not fire()
237      val bypassData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data)
238      val srcBpHitVec = List.tabulate(srcNum)(k =>
239                          List.tabulate(iqSize)(i =>
240                            List.tabulate(bypassCnt)(j =>
241                              (prfSrc(k)(i) === bypassPdest(j)) && (bypassValid(j) && bypassrfWen(i)))))
242      val srcBpHit =  List.tabulate(srcNum)(k =>
243                        List.tabulate(iqSize)(i =>
244                          ParallelOR(srcBpHitVec(k)(i)).asBool()))
245                          // VecInit(srcBpHitVec(k)(i)).asUInt.orR))
246      val srcBpHitVecNext = List.tabulate(srcNum)(k =>
247                              List.tabulate(iqSize)(i =>
248                                List.tabulate(bypassCnt)(j => RegNext(srcBpHitVec(k)(i)(j)))))
249      val srcBpHitNext = List.tabulate(srcNum)(k =>
250                          List.tabulate(iqSize)(i =>
251                            RegNext(srcBpHit(k)(i))))
252      val srcBpData = List.tabulate(srcNum)(k =>
253                        List.tabulate(iqSize)(i =>
254                          ParallelMux(srcBpHitVecNext(k)(i) zip bypassData)))
255                          // Mux1H(srcBpHitVecNext(k)(i), bypassData)))
256      for(k <- 0 until srcNum){
257        for(i <- 0 until iqSize){ when (valid(i)) {
258          when(valid(i) && !srcRdy(k)(i) && srcBpHit(k)(i)) { srcRdy(k)(i) := true.B }
259          when(srcBpHitNext(k)(i)) { srcData(k)(i) := srcBpData(k)(i)}
260        }}
261      }
262
263      // Enqueue Bypass
264      val enqBypass = WireInit(VecInit(false.B, false.B, false.B))
265      val enqBypassHitVec = List(List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc1 === bypassPdest(j) && bypassValid(j) && bypassrfWen(j) && io.enqCtrl.fire()),
266                                 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc2 === bypassPdest(j) && bypassValid(j) && bypassrfWen(j) && io.enqCtrl.fire()),
267                                 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc3 === bypassPdest(j) && bypassValid(j) && bypassrfWen(j) && io.enqCtrl.fire()))
268      val enqBypassHitVecNext = enqBypassHitVec.map(i => i.map(j => RegNext(j)))
269      enqBypass(0) := ParallelOR(enqBypassHitVec(0))
270      enqBypass(1) := ParallelOR(enqBypassHitVec(1))
271      enqBypass(2) := ParallelOR(enqBypassHitVec(2))
272      when(enqBypass(0)) { src1Rdy(enqueueSelect) := true.B }
273      when(enqBypass(1)) { src2Rdy(enqueueSelect) := true.B }
274      when(enqBypass(2)) { src3Rdy(enqueueSelect) := true.B }
275      when(RegNext(enqBypass(0))) { src1Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(0) zip bypassData)}
276      when(RegNext(enqBypass(1))) { src2Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(1) zip bypassData)}
277      when(RegNext(enqBypass(2))) { src3Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(2) zip bypassData)}
278    }
279
280  }
281
282
283  //---------------------------------------------------------
284  // Select Circuit
285  //---------------------------------------------------------
286  val selVec = List.tabulate(iqSize){ i =>
287    Wire(new CmpInputBundle).apply(instRdy(i),roqIdx(i),i.U)
288  }
289  val selResult = ParallelSel(selVec)
290  XSDebug("[Sel Result] ResReady:%d || ResultId:%d\n",selResult.instRdy,selResult.iqIdx.asUInt)
291  //---------------------------------------------------------
292  // Redirect Logic
293  //---------------------------------------------------------
294  val expRedirect = io.redirect.valid && io.redirect.bits.isException
295  val brRedirect = io.redirect.valid && !io.redirect.bits.isException
296
297  List.tabulate(iqSize)( i =>
298    when(brRedirect && (UIntToOH(io.redirect.bits.brTag) & brMask(i)).orR && validReg(i) ){
299        validReg(i) := false.B
300        validWillFalse(i) := true.B
301
302    } .elsewhen(expRedirect) {
303        validReg(i) := false.B
304        validWillFalse(i) := true.B
305    }
306  )
307  //---------------------------------------------------------
308  // Dequeue Logic
309  //---------------------------------------------------------
310  //hold the sel-index to wait for data
311  val selInstIdx = RegInit(0.U(iqIdxWidth.W))
312  val selInstRdy = RegInit(false.B)
313
314  //issue the select instruction
315  val dequeueSelect = Wire(UInt(iqIdxWidth.W))
316  dequeueSelect := selInstIdx
317
318  val brRedirectMaskMatch = (UIntToOH(io.redirect.bits.brTag) & brMask(dequeueSelect)).orR
319  val IQreadyGo = selInstRdy && !expRedirect && (!brRedirect || !brRedirectMaskMatch)
320
321  io.deq.valid := IQreadyGo
322
323  io.deq.bits.uop.cf := ctrlFlow(dequeueSelect)
324  io.deq.bits.uop.ctrl := ctrlSig(dequeueSelect)
325  io.deq.bits.uop.brMask := brMask(dequeueSelect)
326  io.deq.bits.uop.brTag := brTag(dequeueSelect)
327
328  io.deq.bits.uop.psrc1 := prfSrc1(dequeueSelect)
329  io.deq.bits.uop.psrc2 := prfSrc2(dequeueSelect)
330  io.deq.bits.uop.psrc3 := prfSrc3(dequeueSelect)
331  io.deq.bits.uop.pdest := prfDest(dequeueSelect)
332  io.deq.bits.uop.old_pdest := oldPDest(dequeueSelect)
333  io.deq.bits.uop.src1State := SrcState.rdy
334  io.deq.bits.uop.src2State := SrcState.rdy
335  io.deq.bits.uop.src3State := SrcState.rdy
336  io.deq.bits.uop.freelistAllocPtr := freelistAllocPtr(dequeueSelect)
337  io.deq.bits.uop.roqIdx := roqIdx(dequeueSelect)
338
339  io.deq.bits.src1 := src1Data(dequeueSelect)
340  io.deq.bits.src2 := src2Data(dequeueSelect)
341  io.deq.bits.src3 := src3Data(dequeueSelect)
342
343  XSDebug("[Reg Info-Sel] selInstRdy:%d || selIdx:%d\n",selInstRdy,selInstIdx.asUInt)
344  XSDebug(IQreadyGo,"[IQ dequeue] **dequeue fire:%d** roqIdx:%d dequeueSel:%d | src1Rd:%d src1:%d | src2Rd:%d src2:%d\n", io.deq.fire(), io.deq.bits.uop.roqIdx, dequeueSelect.asUInt,
345                            (io.deq.bits.uop.src1State === SrcState.rdy), io.deq.bits.uop.psrc1,
346                            (io.deq.bits.uop.src2State === SrcState.rdy), io.deq.bits.uop.psrc2
347                            )
348
349  //update the index register of instruction that can be issue, unless function unit not allow in
350  //then the issue will be stopped to wait the function unit
351  //clear the validBit of dequeued instruction in issuequeue
352  when(io.deq.fire()){
353    validReg(dequeueSelect) := false.B
354    validWillFalse(dequeueSelect) := true.B
355  }
356
357  val selRegflush = expRedirect || (brRedirect && brRedirectMaskMatch)
358
359  selInstRdy := Mux(selRegflush,false.B,selResult.instRdy)
360  selInstIdx := Mux(selRegflush,0.U,selResult.iqIdx)
361  // SelectedUop (bypass / speculative)
362  if(useBypass) {
363    assert(fixedDelay==1) // only support fixedDelay is 1 now
364    def DelayPipe[T <: Data](a: T, delay: Int = 0) = {
365      // println(delay)
366      if(delay == 0) a
367      else {
368        val storage = Wire(VecInit(Seq.fill(delay+1)(a)))
369        // storage(0) := a
370        for(i <- 1 until delay) {
371          storage(i) := RegNext(storage(i-1))
372        }
373        storage(delay)
374      }
375    }
376    val sel = io.selectedUop
377    val selIQIdx = selResult.iqIdx
378    val delayPipe = DelayPipe(VecInit(selResult.instRdy, prfDest(selIQIdx)), fixedDelay-1)
379    sel.bits := DontCare
380    sel.bits.pdest := delayPipe(fixedDelay-1)(1)
381  }
382}
383