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