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