xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision b9bb7e73438a31df16f2d84ca85df237df04ce84)
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
177  XSDebug("[Reg info-ENQ] enqSelNext:%d | enqFireNext:%d \n",enqSelNext,enqFireNext)
178  XSDebug("[IQ content] valid vr vf| pc  insruction |   src1rdy  src1 |  src2Rdy  src2 |  src3Rdy  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| %x %x | %x %x | %x %x | %d  valid|\n",
184      i.asUInt, valid(i), validReg(i), validWillFalse(i), pc,ins,src1Rdy(i), src1Data(i),
185      src2Rdy(i), src2Data(i),src3Rdy(i), src3Data(i),prfDest(i))
186    XSDebug(validReg(i) && validWillFalse(i),
187      "[IQ content][%d] %d%d%d |%x  %x| %x %x | %x %x | %x %x | %d  valid will be False|\n",
188      i.asUInt, valid(i), validReg(i), validWillFalse(i),pc,ins, src1Rdy(i), src1Data(i),
189      src2Rdy(i), src2Data(i),src3Rdy(i), src3Data(i),prfDest(i))
190    XSDebug("[IQ content][%d] %d%d%d |%x  %x| %x %x | %x %x | %x %x | %d\n",
191      i.asUInt, valid(i), validReg(i), validWillFalse(i),pc,ins, src1Rdy(i), src1Data(i),
192      src2Rdy(i), src2Data(i),src3Rdy(i), 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 cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data)
200    val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest)
201
202    val srcNum = 3
203    val prfSrc = List(prfSrc1, prfSrc2, prfSrc3)
204    val srcRdy = List(src1Rdy, src2Rdy, src3Rdy)
205    val srcData = List(src1Data, src2Data, src3Data)
206    val srcHitVec = List.tabulate(srcNum)(k =>
207                      List.tabulate(iqSize)(i =>
208                        List.tabulate(wakeupCnt)(j =>
209                          (prfSrc(k)(i) === cdbPdest(j)) && cdbValid(j))))
210    val srcHit =  List.tabulate(srcNum)(k =>
211                    List.tabulate(iqSize)(i =>
212                      ParallelOR(srcHitVec(k)(i)).asBool()))
213                      // VecInit(srcHitVec(k)(i)).asUInt.orR))
214    for(k <- 0 until srcNum){
215      for(i <- 0 until iqSize)( when (valid(i)) {
216        when(!srcRdy(k)(i) && srcHit(k)(i)) {
217          srcRdy(k)(i) := true.B
218          // srcData(k)(i) := Mux1H(srcHitVec(k)(i), cdbData)
219          srcData(k)(i) := ParallelMux(srcHitVec(k)(i) zip cdbData)
220        }
221      })
222    }
223    // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself)
224    // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag
225    // byPassUops is one cycle before byPassDatas
226    if (bypassCnt > 0) {
227      val bypassPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest)
228      val bypassValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) // may only need valid not fire()
229      val bypassData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data)
230      val srcBpHitVec = List.tabulate(srcNum)(k =>
231                          List.tabulate(iqSize)(i =>
232                            List.tabulate(bypassCnt)(j =>
233                              (prfSrc(k)(i) === bypassPdest(j)) && bypassValid(j))))
234      val srcBpHit =  List.tabulate(srcNum)(k =>
235                        List.tabulate(iqSize)(i =>
236                          ParallelOR(srcBpHitVec(k)(i)).asBool()))
237                          // VecInit(srcBpHitVec(k)(i)).asUInt.orR))
238      val srcBpHitVecNext = List.tabulate(srcNum)(k =>
239                              List.tabulate(iqSize)(i =>
240                                List.tabulate(bypassCnt)(j => RegNext(srcBpHitVec(k)(i)(j)))))
241      val srcBpHitNext = List.tabulate(srcNum)(k =>
242                          List.tabulate(iqSize)(i =>
243                            RegNext(srcBpHit(k)(i))))
244      val srcBpData = List.tabulate(srcNum)(k =>
245                        List.tabulate(iqSize)(i =>
246                          ParallelMux(srcBpHitVecNext(k)(i) zip bypassData)))
247                          // Mux1H(srcBpHitVecNext(k)(i), bypassData)))
248      for(k <- 0 until srcNum){
249        for(i <- 0 until iqSize){ when (valid(i)) {
250          when(valid(i) && !srcRdy(k)(i) && srcBpHit(k)(i)) { srcRdy(k)(i) := true.B }
251          when(srcBpHitNext(k)(i)) { srcData(k)(i) := srcBpData(k)(i)}
252        }}
253      }
254
255      // Enqueue Bypass
256      val enqBypass = WireInit(VecInit(false.B, false.B, false.B))
257      val enqBypassHitVec = List(List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc1 === bypassPdest(j) && bypassValid(j) && io.enqCtrl.fire()),
258                                 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc2 === bypassPdest(j) && bypassValid(j) && io.enqCtrl.fire()),
259                                 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc3 === bypassPdest(j) && bypassValid(j) && io.enqCtrl.fire()))
260      val enqBypassHitVecNext = enqBypassHitVec.map(i => i.map(j => RegNext(j)))
261      enqBypass(0) := ParallelOR(enqBypassHitVec(0))
262      enqBypass(1) := ParallelOR(enqBypassHitVec(1))
263      enqBypass(2) := ParallelOR(enqBypassHitVec(2))
264      when(enqBypass(0)) { src1Rdy(enqueueSelect) := true.B }
265      when(enqBypass(1)) { src2Rdy(enqueueSelect) := true.B }
266      when(enqBypass(2)) { src3Rdy(enqueueSelect) := true.B }
267      when(RegNext(enqBypass(0))) { src1Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(0) zip bypassData)}
268      when(RegNext(enqBypass(1))) { src2Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(1) zip bypassData)}
269      when(RegNext(enqBypass(2))) { src3Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(2) zip bypassData)}
270    }
271
272  }
273
274
275  //---------------------------------------------------------
276  // Select Circuit
277  //---------------------------------------------------------
278  val selVec = List.tabulate(iqSize){ i =>
279    Wire(new CmpInputBundle).apply(instRdy(i),roqIdx(i),i.U)
280  }
281  val selResult = ParallelSel(selVec)
282  XSDebug("[Sel Result] ResReady:%d || ResultId:%d\n",selResult.instRdy,selResult.iqIdx.asUInt)
283  //---------------------------------------------------------
284  // Redirect Logic
285  //---------------------------------------------------------
286  val expRedirect = io.redirect.valid && io.redirect.bits.isException
287  val brRedirect = io.redirect.valid && !io.redirect.bits.isException
288
289  List.tabulate(iqSize)( i =>
290    when(brRedirect && (UIntToOH(io.redirect.bits.brTag) & brMask(i)).orR && validReg(i) ){
291        validReg(i) := false.B
292        validWillFalse(i) := true.B
293
294    } .elsewhen(expRedirect) {
295        validReg(i) := false.B
296        validWillFalse(i) := true.B
297    }
298  )
299  //---------------------------------------------------------
300  // Dequeue Logic
301  //---------------------------------------------------------
302  //hold the sel-index to wait for data
303  val selInstIdx = RegInit(0.U(iqIdxWidth.W))
304  val selInstRdy = RegInit(false.B)
305
306  //issue the select instruction
307  val dequeueSelect = Wire(UInt(iqIdxWidth.W))
308  dequeueSelect := selInstIdx
309
310  val brRedirectMaskMatch = (UIntToOH(io.redirect.bits.brTag) & brMask(dequeueSelect)).orR
311  val IQreadyGo = selInstRdy && !expRedirect && (!brRedirect || !brRedirectMaskMatch)
312
313  io.deq.valid := IQreadyGo
314
315  io.deq.bits.uop.cf := ctrlFlow(dequeueSelect)
316  io.deq.bits.uop.ctrl := ctrlSig(dequeueSelect)
317  io.deq.bits.uop.brMask := brMask(dequeueSelect)
318  io.deq.bits.uop.brTag := brTag(dequeueSelect)
319
320  io.deq.bits.uop.psrc1 := prfSrc1(dequeueSelect)
321  io.deq.bits.uop.psrc2 := prfSrc2(dequeueSelect)
322  io.deq.bits.uop.psrc3 := prfSrc3(dequeueSelect)
323  io.deq.bits.uop.pdest := prfDest(dequeueSelect)
324  io.deq.bits.uop.old_pdest := oldPDest(dequeueSelect)
325  io.deq.bits.uop.src1State := SrcState.rdy
326  io.deq.bits.uop.src2State := SrcState.rdy
327  io.deq.bits.uop.src3State := SrcState.rdy
328  io.deq.bits.uop.freelistAllocPtr := freelistAllocPtr(dequeueSelect)
329  io.deq.bits.uop.roqIdx := roqIdx(dequeueSelect)
330
331  io.deq.bits.src1 := src1Data(dequeueSelect)
332  io.deq.bits.src2 := src2Data(dequeueSelect)
333  io.deq.bits.src3 := src3Data(dequeueSelect)
334
335  XSDebug("[Reg Info-Sel] selInstRdy:%d || selIdx:%d\n",selInstRdy,selInstIdx.asUInt)
336  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,
337                            (io.deq.bits.uop.src1State === SrcState.rdy), io.deq.bits.uop.psrc1,
338                            (io.deq.bits.uop.src2State === SrcState.rdy), io.deq.bits.uop.psrc2
339                            )
340
341  //update the index register of instruction that can be issue, unless function unit not allow in
342  //then the issue will be stopped to wait the function unit
343  //clear the validBit of dequeued instruction in issuequeue
344  when(io.deq.fire()){
345    validReg(dequeueSelect) := false.B
346    validWillFalse(dequeueSelect) := true.B
347  }
348
349  val selRegflush = expRedirect || (brRedirect && brRedirectMaskMatch)
350
351  selInstRdy := Mux(selRegflush,false.B,selResult.instRdy)
352  selInstIdx := Mux(selRegflush,0.U,selResult.iqIdx)
353  // SelectedUop (bypass / speculative)
354  if(useBypass) {
355    assert(fixedDelay==1) // only support fixedDelay is 1 now
356    def DelayPipe[T <: Data](a: T, delay: Int = 0) = {
357      if(delay == 0) a
358      else {
359        val storage = Wire(VecInit(Seq.fill(delay+1)(a)))
360        // storage(0) := a
361        for(i <- 1 until delay) {
362          storage(i) := RegNext(storage(i-1))
363        }
364        storage(delay)
365      }
366    }
367    val sel = io.selectedUop
368    val selIQIdx = selResult.iqIdx
369    val delayPipe = DelayPipe(VecInit(selResult.instRdy, prfDest(selIQIdx)), fixedDelay-1)
370    sel.bits := DontCare
371    sel.valid := selResult.instRdy
372    sel.bits.pdest := delayPipe(fixedDelay-1)(1)
373  }
374}
375
376class IssueQueueCpt(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int = 0, val fixedDelay: Int = 1) extends IQModule {
377
378  val useBypass = bypassCnt > 0
379  val src2Use = true
380  val src3Use = true
381  val src2Listen = true
382  val src3Listen = true
383
384  val io = IO(new Bundle() {
385    // flush Issue Queue
386    val redirect = Flipped(ValidIO(new Redirect))
387
388    // enq Ctrl sigs at dispatch-2
389    val enqCtrl = Flipped(DecoupledIO(new MicroOp))
390    // enq Data at next cycle (regfile has 1 cycle latency)
391    val enqData = Flipped(ValidIO(new ExuInput))
392
393    //  broadcast selected uop to other issue queues which has bypasses
394    val selectedUop = if(useBypass) ValidIO(new MicroOp) else null
395
396    // send to exu
397    val deq = DecoupledIO(new ExuInput)
398
399    // listen to write back bus
400    val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput)))
401
402    // use bypass uops to speculative wake-up
403    val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) else null
404    val bypassData = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new ExuOutput))) else null
405  })
406
407  val srcAllNum = 3
408  val srcUseNum = 1 + (if(src2Use) 1 else 0) + (if(src3Use) 1 else 0)// when src2Use is false, then src3Use must be false
409  val srcListenNum = 1 + (if(src2Listen) 1 else 0) + (if(src3Listen) 1 else 0) // when src2Listen is false, then src3Listen must be false
410  // when use is false, Listen must be false
411  require(!(!src2Use && src2Listen))
412  require(!(!src3Use && src3Listen))
413  require(!(!src2Use && src3Use))
414  require(!(!src2Listen && src3Listen))
415
416  // Issue Queue
417  // val issQue = IndexableMem(iqSize, new ExuInput, mem = false, init = None)
418  val issQue = Mem(iqSize, new ExuInput)
419  // val issQue = Reg(Vec(iqSize, new ExuInput))
420  val validQue = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
421  val idQue = RegInit(VecInit((0 until iqSize).map(_.U(iqIdxWidth.W))))
422  val idValidQue = VecInit((0 until iqSize).map(i => validQue(idQue(i)))).asUInt
423  val tailAll = RegInit(0.U((iqIdxWidth+1).W))
424  val tail = tailAll(iqIdxWidth-1, 0)
425  val full = tailAll(iqIdxWidth)
426  // alias failed, turn to independent storage(Reg)
427  val psrc = VecInit(List.tabulate(iqSize)(i => VecInit(List(issQue(i.U).uop.psrc1, issQue(i.U).uop.psrc2, issQue(i.U).uop.psrc3)))) // TODO: why issQue can not use Int as index, but idQue is ok?? // NOTE: indexed by IssQue's idx
428  // val srcRdyVec = Reg(Vec(iqSize, Vec(srcListenNum, Bool())))
429  val srcRdyVec = Reg(Vec(iqSize, Vec(srcAllNum, Bool()))) // NOTE: indexed by IssQue's idx
430  // val srcData = Reg(Vec(iqSize, Vec(srcUseNum, UInt(XLEN.W)))) // NOTE: Bundle/MicroOp need merge "src1/src2/src3" into a Vec. so that IssueQueue could have Vec
431  val srcData = Reg(Vec(iqSize, Vec(srcAllNum, UInt(XLEN.W)))) // NOTE: indexed by IssQue's idx
432  val srcRdy = VecInit(srcRdyVec.map(i => ParallelAND(i))) // NOTE: indexed by IssQue's idx
433  val srcIdRdy = VecInit((0 until iqSize).map(i => srcRdy(idQue(i)))).asUInt // NOTE: indexed by IdQue's idx
434  val srcType = List.tabulate(iqSize)(i => List(issQue(i).uop.ctrl.src1Type, issQue(i).uop.ctrl.src2Type, issQue(i).uop.ctrl.src3Type))
435
436  val srcDataWire = srcData
437  srcData := srcDataWire
438
439  // there is three stage
440  // |-------------|--------------------|--------------|
441  // |Enq:get state|Deq: select/get data| fire stage   |
442  // |-------------|--------------------|--------------|
443
444  //-----------------------------------------
445  // Enqueue
446  //-----------------------------------------
447  val enqRedHit = Wire(Bool())
448  val enqFire = io.enqCtrl.fire() && !enqRedHit
449  val deqFire = io.deq.fire()
450  val popOne = Wire(Bool())
451  io.enqCtrl.ready := !full || popOne
452  val enqSel = idQue(tail)
453
454  // state enq
455  when (enqFire) {
456    issQue(enqSel).uop := io.enqCtrl.bits
457    validQue(enqSel) := true.B
458    assert(!validQue(enqSel))
459
460    srcRdyVec(enqSel)(0) := io.enqCtrl.bits.src1State === SrcState.rdy
461    if(src2Listen) { srcRdyVec(enqSel)(1) := io.enqCtrl.bits.src2State === SrcState.rdy }
462    if(src3Listen) { srcRdyVec(enqSel)(2) := io.enqCtrl.bits.src3State === SrcState.rdy }
463  }
464
465  // data enq
466  val enqSelNext = RegEnable(enqSel, enqFire)
467  // val enqSelNext = RegNext(enqSel)
468  val enqFireNext = RegInit(false.B)
469  when (enqFireNext) { enqFireNext := false.B }
470  when (enqFire) { enqFireNext := true.B }
471
472  val enqDataVec = List(io.enqData.bits.src1, io.enqData.bits.src2, io.enqData.bits.src3)
473  when (enqFireNext) {
474    for(i <- 0 until srcUseNum) {
475      srcDataWire(enqSelNext)(i) := enqDataVec(i)
476    }
477  }
478
479  //-----------------------------------------
480  // tail
481  //-----------------------------------------
482  val tailInc = enqFire
483  val tailDec = popOne
484  val tailKeep = tailInc === tailDec
485  val tailAdd = tailAll + 1.U
486  val tailSub = tailAll - 1.U
487  tailAll := Mux(tailKeep, tailAll, Mux(tailInc, tailAdd, tailSub))
488  assert(tailAll < 9.U)
489  // Select to Dequeue
490  val deqSel = PriorityEncoder(idValidQue & srcIdRdy) //may not need idx, just need oneHot, idx by IdQue's idx
491  val deqSelIq = idQue(deqSel)
492  val deqSelOH = PriorityEncoderOH(idValidQue & srcIdRdy)
493  val has1Rdy = ParallelOR((validQue.asUInt & srcRdy.asUInt).asBools).asBool()
494
495  //-----------------------------------------
496  // idQue Move
497  //-----------------------------------------
498  def UIntToMHP(in: UInt) = {
499    // UInt to Multi-Hot plus 1: 1.U -> "11".U; 2.U(2.W) -> "0111".U; 3.U(3.W) -> "00001111".W
500    val a = Seq.fill(in.getWidth)(2).product
501    val s = (1 << (a-1)).S
502    Reverse((s(a-1,0).asSInt >> in)(a-1,0).asUInt)
503  }
504  def UIntToMH(in: UInt) = {
505    val a = Seq.fill(in.getWidth)(2).product
506    val s = (1 << (a-1)).S
507    Reverse((s(a-1,0).asSInt >> in)(a-1,0).asUInt) ^ UIntToOH(in)
508  }
509  def PriorityDot(in: UInt) = {
510    // "1100".U -> "0111".U; "1010".U -> "0011".U; "0000".U -> "0000".U
511    val a = Array.fill(iqSize)(1)
512    for(i <- 1 until in.getWidth) {
513      a(i) = a(i-1)*2 + 1
514    }
515    Mux(in===0.U, 0.U(in.getWidth.W), PriorityMux(in, a.map(_.U(in.getWidth.W))))
516  }
517  val tailDot = Mux(full, VecInit(Seq.fill(iqSize)(true.B)).asUInt, UIntToMHP(tail))
518  val tailDot2 = Mux(full, VecInit(Seq.fill(iqSize)(true.B)).asUInt, UIntToMH(tail))
519  val selDot = UIntToMHP(deqSel) // FIXIT: PriorityEncoder -> UIntToMHP means long latency
520  val nonValid = ~(idValidQue | ~tailDot2)
521  val popSel = PriorityEncoder(nonValid) // Note: idxed by IDque's index
522  val popDot = PriorityDot(nonValid)
523  val isPop = ParallelOR(nonValid.asBools).asBool()
524  val moveDot = Mux(isPop, tailDot ^ popDot, tailDot ^ selDot)
525
526  assert(!(popOne&&moveDot(0)))
527  when (popOne) {
528    for(i <- 1 until iqSize) {
529      when (moveDot(i)) { idQue(i-1) := idQue(i) }
530    }
531    val ptr_tmp = Mux(full, VecInit(Seq.fill(iqIdxWidth)(true.B)).asUInt, tail)
532    idQue(ptr_tmp) := idQue(Mux(isPop, popSel, deqSel))
533  }
534  assert(ParallelAND(List.tabulate(iqSize)(i => ParallelOR(List.tabulate(iqSize)(j => i.U === idQue(j))))).asBool)
535
536  //-----------------------------------------
537  // Redirect
538  //-----------------------------------------
539  // redirect enq
540  enqRedHit := io.redirect.valid && (io.redirect.bits.isException || ParallelOR((UIntToOH(io.redirect.bits.brTag) & io.enqCtrl.bits.brMask).asBools).asBool)
541
542  // redirect issQue
543  val redHitVec = List.tabulate(iqSize)(i => io.redirect.valid && (io.redirect.bits.isException || ParallelOR((UIntToOH(io.redirect.bits.brTag) & issQue(i).uop.brMask).asBools).asBool))
544  for (i <- 0 until iqSize) {
545    when (redHitVec(i) && validQue(i)) {
546      validQue(i) := false.B
547    }
548  }
549  // reditect deq(issToExu)
550  val redIdHitVec = List.tabulate(iqSize)(i => io.redirect.valid && (io.redirect.bits.isException || ParallelOR((UIntToOH(io.redirect.bits.brTag) & issQue(idQue(i)).uop.brMask).asBools).asBool))
551  val selIsRed = ParallelOR((deqSelOH & VecInit(redIdHitVec).asUInt).asBools).asBool
552
553  //-----------------------------------------
554  // Dequeue (or to Issue Stage)
555  //-----------------------------------------
556  val issueToExu = Reg(new ExuInput)
557  val issueToExuValid = RegInit(false.B)
558  val deqCanIn = !issueToExuValid || deqFire
559  val deqFlushHit = io.redirect.valid && (io.redirect.bits.isException ||
560                 ParallelOR((issueToExu.uop.brMask & UIntToOH(io.redirect.bits.brTag)).asBools).asBool)
561  val toIssFire = deqCanIn && has1Rdy && !isPop && !selIsRed
562  popOne := deqCanIn && (has1Rdy || isPop) // send a empty or valid term to issueStage
563
564  when (toIssFire) {
565    issueToExu := issQue(deqSelIq)
566    issueToExuValid := true.B
567    validQue(deqSelIq) := false.B
568    assert(validQue(deqSelIq))
569    issueToExu.src1 := srcDataWire(deqSelIq)(0)
570    if (src2Use) { issueToExu.src2 := srcDataWire(deqSelIq)(1) } else { issueToExu.src2 := DontCare }
571    if (src3Use) { issueToExu.src3 := srcDataWire(deqSelIq)(2) } else { issueToExu.src3 := DontCare }
572  }
573  when (deqFire || deqFlushHit) {
574    issueToExuValid := false.B
575  }
576
577  io.deq.valid := issueToExuValid && !deqFlushHit
578  io.deq.bits := issueToExu
579
580  //-----------------------------------------
581  // Wakeup and Bypass
582  //-----------------------------------------
583  if (wakeupCnt > 0) {
584    val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid)
585    val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data)
586    val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest)
587    val cdbrfWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.rfWen)
588    val cdbfpWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.fpWen)
589
590    for(i <- 0 until iqSize) {
591      for(j <- 0 until srcListenNum) {
592        val hitVec = List.tabulate(wakeupCnt)(k => psrc(i)(j) === cdbPdest(k) && cdbValid(k) && (srcType(i)(j)===SrcType.reg && cdbrfWen(k) || srcType(i)(j)===SrcType.fp && cdbfpWen(k)))
593        val hit = ParallelOR(hitVec).asBool
594        val data = ParallelMux(hitVec zip cdbData)
595        when (validQue(i) && !srcRdyVec(i)(j) && hit) {
596          srcDataWire(i)(j) := data
597          srcRdyVec(i)(j) := true.B
598        }
599        // 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)
600        for (k <- 0 until wakeupCnt) {
601          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)
602        }
603      }
604    }
605  }
606  if (useBypass) {
607    val bpPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest)
608    val bpValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid)
609    val bpData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data)
610    val bprfWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.rfWen)
611    val bpfpWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.fpWen)
612
613    for (i <- 0 until iqSize) {
614      for (j <- 0 until srcListenNum) {
615        val hitVec = List.tabulate(bypassCnt)(k => psrc(i)(j) === bpPdest(k) && bpValid(k) && (srcType(i)(j)===SrcType.reg && bprfWen(k) || srcType(i)(j)===SrcType.fp && bpfpWen(k)))
616        val hitVecNext = hitVec.map(RegNext(_))
617        val hit = ParallelOR(hitVec).asBool
618        when (validQue(i) && !srcRdyVec(i)(j) && hit) {
619          srcRdyVec(i)(j) := true.B // FIXME: if uncomment the up comment, will cause combiantional loop, but it is Mem type??
620        }
621        when (RegNext(validQue(i) && !srcRdyVec(i)(j) && hit)) {
622          srcDataWire(i)(j) := PriorityMux(hitVecNext zip bpData)
623        }
624        // 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)
625        for (k <- 0 until bypassCnt) {
626          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)
627        }
628        // 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))
629        for (k <- 0 until bypassCnt) {
630          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)
631        }
632      }
633    }
634
635    // Enqueue Bypass
636    val enqCtrl = io.enqCtrl
637    val enqPsrc = List(enqCtrl.bits.psrc1, enqCtrl.bits.psrc2, enqCtrl.bits.psrc3)
638    val enqSrcRdy = List(enqCtrl.bits.src1State===SrcState.rdy, enqCtrl.bits.src2State===SrcState.rdy, enqCtrl.bits.src3State===SrcState.rdy)
639    val enqSrcType = List(enqCtrl.bits.ctrl.src1Type, enqCtrl.bits.ctrl.src2Type, enqCtrl.bits.ctrl.src3Type)
640    for (i <- 0 until srcListenNum) {
641      val hitVec = List.tabulate(bypassCnt)(j => enqPsrc(i)===bpPdest(j) && bpValid(j) && (enqSrcType(i)===SrcType.reg && bprfWen(j) || enqSrcType(i)===SrcType.fp && bpfpWen(j)))
642      val hitVecNext = hitVec.map(RegNext(_))
643      val hit = ParallelOR(hitVec).asBool
644      when (enqFire && hit && !enqSrcRdy(i)) {
645        srcRdyVec(enqSel)(i) := true.B
646      }
647      when (RegNext(enqFire && hit && !enqSrcRdy(i))) {
648        srcDataWire(enqSelNext)(i) := ParallelMux(hitVecNext zip bpData)
649      }
650      // XSDebug(enqFire && hit, "EnqBypassCtrl: enqSel:%d Src:(%d|%d) Hit:%d HitVec:%b \n", enqSel, i.U, enqPsrc(i), hit, VecInit(hitVec).asUInt)
651      for (k <- 0 until bypassCnt) {
652        XSDebug(enqFire && hit && !enqSrcRdy(i) && hitVec(k), "EnqBypassCtrlHit: enqSel:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", enqSel, i.U, enqPsrc(i), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
653      }
654      // XSDebug(RegNext(enqFire && hit), "EnqBypassData: enqSelNext:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", enqSelNext, i.U, enqPsrc(i), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData))
655      for (k <- 0 until bypassCnt) {
656        XSDebug(RegNext(enqFire && hit && !enqSrcRdy(i) && hitVec(k)), "EnqBypassDataHit: enqSel:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", enqSel, i.U, enqPsrc(i), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx)
657      }
658    }
659
660    // send out bypass
661    assert(fixedDelay==1) // only support fixedDelay is 1 now
662    val sel = io.selectedUop
663    sel.valid := toIssFire
664    sel.bits := DontCare
665    sel.bits.pdest := issQue(deqSelIq).uop.pdest
666    sel.bits.cf.pc := issQue(deqSelIq).uop.cf.pc
667    sel.bits.roqIdx := issQue(deqSelIq).uop.roqIdx
668    sel.bits.ctrl.rfWen := issQue(deqSelIq).uop.ctrl.rfWen
669    sel.bits.ctrl.fpWen := issQue(deqSelIq).uop.ctrl.fpWen
670  }
671  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, VecInit(redHitVec).asUInt, VecInit(redIdHitVec).asUInt, enqRedHit, selIsRed)
672  XSInfo(enqFire, "EnqCtrl(%d %d) enqSel:%d Psrc/Rdy(%d:%d %d:%d %d:%d) Dest:%d oldDest:%d pc:%x roqIdx:%x\n", io.enqCtrl.valid, io.enqCtrl.ready, enqSel
673    , 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)
674  XSInfo(enqFireNext, "EnqData: src1:%x src2:%x src3:%x (for last cycle's Ctrl)\n", io.enqData.bits.src1, io.enqData.bits.src2, io.enqData.bits.src3)
675  XSInfo(deqFire, "Deq:(%d %d) [%d|%x][%d|%x][%d|%x] pdest:%d pc:%x roqIdx:%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)
676  XSDebug("tailAll:%d KID(%d%d%d) tailDot:%b tailDot2:%b selDot:%b popDot:%b moveDot:%b\n", tailAll, tailKeep, tailInc, tailDec, tailDot, tailDot2, selDot, popDot, moveDot)
677  if(useBypass) {
678    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)
679  } else {
680    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)
681  }
682  XSDebug("id| v|r |psrc|r|   src1          |psrc|r|   src2          |psrc|r|   src3          |brMask|  pc  |roqIdx\n")
683  for (i <- 0 until iqSize) {
684    when (i.U===tail && tailAll=/=8.U) {
685      XSDebug("%d|%d|%d|%d|%b|%x|%d|%b|%x|%d|%b|%x| %x|%x|%x <-\n", idQue(i), idValidQue(i), srcRdy(idQue(i)), psrc(idQue(i))(0), srcRdyVec(idQue(i))(0), srcData(idQue(i))(0), psrc(idQue(i))(1), srcRdyVec(idQue(i))(1), srcData(idQue(i))(1), psrc(idQue(i))(2), srcRdyVec(idQue(i))(2), srcData(idQue(i))(2), issQue(idQue(i)).uop.brMask, issQue(idQue(i)).uop.cf.pc, issQue(idQue(i)).uop.roqIdx)
686    }.otherwise {
687      XSDebug("%d|%d|%d|%d|%b|%x|%d|%b|%x|%d|%b|%x| %x|%x|%x\n", idQue(i), idValidQue(i), srcRdy(idQue(i)), psrc(idQue(i))(0), srcRdyVec(idQue(i))(0), srcData(idQue(i))(0), psrc(idQue(i))(1), srcRdyVec(idQue(i))(1), srcData(idQue(i))(1), psrc(idQue(i))(2), srcRdyVec(idQue(i))(2), srcData(idQue(i))(2), issQue(idQue(i)).uop.brMask, issQue(idQue(i)).uop.cf.pc, issQue(idQue(i)).uop.roqIdx)
688    }
689  }
690
691}