xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision ad55d1948259e3d0033d37bc72e751e33b771a77)
1package xiangshan.backend.issue
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6
7trait IQConst{
8  val iqSize = 8
9  val iqIdxWidth = log2Up(iqSize)
10  val layer1Size = iqSize
11  val layer2Size = iqSize/2
12  val layer3Size = iqSize/4
13}
14
15sealed abstract class IQBundle extends XSBundle with IQConst
16sealed abstract class IQModule extends XSModule with IQConst with NeedImpl
17
18sealed class CmpInputBundle extends IQBundle{
19  val instRdy = Input(Bool())
20  val roqIdx  = Input(UInt(RoqIdxWidth.W))
21  val iqIdx   = Input(UInt(iqIdxWidth.W))
22}
23
24
25sealed class CompareCircuitUnit(layer: Int = 0, id: Int = 0) extends IQModule {
26  val io = IO(new Bundle(){
27    val in1 = new CmpInputBundle
28    val in2 = new CmpInputBundle
29    val out = Flipped(new CmpInputBundle)
30  })
31
32  val roqIdx1 = io.in1.roqIdx
33  val roqIdx2 = io.in2.roqIdx
34  val iqIdx1  = io.in1.iqIdx
35  val iqIdx2  = io.in2.iqIdx
36
37  val inst1Rdy = io.in1.instRdy
38  val inst2Rdy = io.in2.instRdy
39
40  val readySignal = Cat(inst1Rdy,inst2Rdy)
41
42  switch (readySignal) {
43    is ("b00".U) {
44      io.out.instRdy := false.B
45      io.out.roqIdx := DontCare
46      io.out.iqIdx := DontCare
47    }
48    is ("b01".U) {
49      io.out.instRdy := inst2Rdy
50      io.out.roqIdx := roqIdx2
51      io.out.iqIdx := iqIdx2
52     }
53    is ("b10".U) {
54      io.out.instRdy := inst1Rdy
55      io.out.roqIdx := roqIdx1
56      io.out.iqIdx := iqIdx1
57    }
58    is ("b11".U) {
59      when(roqIdx1 < roqIdx2) {
60        io.out.instRdy := inst1Rdy
61        io.out.roqIdx := roqIdx1
62        io.out.iqIdx := iqIdx1
63      } .otherwise {
64        io.out.instRdy := inst2Rdy
65        io.out.roqIdx := roqIdx2
66        io.out.iqIdx := iqIdx2
67      }
68    }
69  }
70
71}
72
73class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int) extends IQModule {
74
75  val useBypass = bypassCnt > 0
76
77  val io = IO(new Bundle() {
78    // flush Issue Queue
79    val redirect = Flipped(ValidIO(new Redirect))
80
81    // enq Ctrl sigs at dispatch-2
82    val enqCtrl = Flipped(DecoupledIO(new MicroOp))
83    // enq Data at next cycle (regfile has 1 cycle latency)
84    val enqData = Flipped(ValidIO(new ExuInput))
85
86    //  broadcast selected uop to other issue queues which has bypasses
87    val selectedUop = if(useBypass) DecoupledIO(new MicroOp) else null
88
89    // send to exu
90    val deq = DecoupledIO(new ExuInput)
91
92    // listen to write back bus
93    val wakeUpPorts = Vec(wakeupCnt, Flipped(DecoupledIO(new ExuOutput)))
94
95    // use bypass uops to speculative wake-up
96    val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(DecoupledIO(new MicroOp))) else null
97  })
98  //---------------------------------------------------------
99  // Issue Queue
100  //---------------------------------------------------------
101
102  //Tag Queue
103  val ctrlFlow = Mem(iqSize,new CtrlFlow)
104  val ctrlSig = Mem(iqSize,new CtrlSignals)
105  val brMask  = RegInit(VecInit(Seq.fill(iqSize)(0.U(BrqSize.W))))
106  val valid   = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
107  val src1Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
108  val src2Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
109  val src3Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
110  val prfSrc1 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
111  val prfSrc2 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
112  val prfSrc3 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
113  val prfDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
114  val oldPDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
115  val freelistAllocPrt = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
116  val roqIdx  = Reg(Vec(iqSize, UInt(RoqIdxWidth.W)))
117
118  val instRdy = WireInit(VecInit(List.tabulate(iqSize)(i => src1Rdy(i) && src2Rdy(i) && valid(i))))
119
120
121  //tag enqueue
122  val iqEmty = !valid.asUInt.orR
123  val iqFull =  valid.asUInt.andR
124  val iqAllowIn = !iqFull
125  io.enqCtrl.ready := iqAllowIn
126
127  //enqueue pointer
128  val emptySlot = ~valid.asUInt
129  val enqueueSelect = PriorityEncoder(emptySlot)
130
131  when(io.enqCtrl.fire()){
132    ctrlFlow(enqueueSelect) := io.enqCtrl.bits.cf
133    ctrlSig(enqueueSelect) := io.enqCtrl.bits.ctrl
134    brMask(enqueueSelect) := io.enqCtrl.bits.brMask
135    valid(enqueueSelect) := true.B
136    src1Rdy(enqueueSelect) := io.enqCtrl.bits.src1State === SrcState.rdy
137    src2Rdy(enqueueSelect) := io.enqCtrl.bits.src2State === SrcState.rdy
138    src3Rdy(enqueueSelect) := io.enqCtrl.bits.src3State === SrcState.rdy
139    prfSrc1(enqueueSelect) := io.enqCtrl.bits.psrc1
140    prfSrc2(enqueueSelect) := io.enqCtrl.bits.psrc2
141    prfSrc3(enqueueSelect) := io.enqCtrl.bits.psrc3
142    prfDest(enqueueSelect) := io.enqCtrl.bits.pdest
143    oldPDest(enqueueSelect) := io.enqCtrl.bits.old_pdest
144    freelistAllocPrt(enqueueSelect) := io.enqCtrl.bits.freelistAllocPtr
145    roqIdx(enqueueSelect) := io.enqCtrl.bits.roqIdx
146
147  }
148
149  //Data Queue
150  val src1Data = Reg(Vec(iqSize, UInt(XLEN.W)))
151  val src2Data = Reg(Vec(iqSize, UInt(XLEN.W)))
152  val src3Data = Reg(Vec(iqSize, UInt(XLEN.W)))
153
154  val enqSelNext = RegNext(enqueueSelect)
155  val enqFireNext = RegNext(io.enqCtrl.fire())
156
157  // Read RegFile
158  when (enqFireNext) {
159    src1Data(enqSelNext) := io.enqData.bits.src1
160    src2Data(enqSelNext) := io.enqData.bits.src2
161    src3Data(enqSelNext) := io.enqData.bits.src3
162  }
163
164  // From Common Data Bus(wakeUpPort)
165  // TODO: the when-style may causes long-long-long Mux(which means long latency)
166  // TODO: ignore ALU'cdb srcRdy, for byPass has done it
167  val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid)
168  val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data)
169  val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest)
170  List.tabulate(iqSize)(i =>
171    when (valid(i)) {
172      List.tabulate(wakeupCnt)(j => {
173        when(!src1Rdy(i) && prfSrc1(i) === cdbPdest(j) && cdbValid(j)) {
174          src1Rdy(i) := true.B
175          src1Data(i) := cdbData(j)
176        }
177        when(!src2Rdy(i) && prfSrc2(i) === cdbPdest(j) && cdbValid(j)) {
178          src2Rdy(i) := true.B
179          src2Data(i) := cdbData(j)
180        }
181        when(!src3Rdy(i) && prfSrc3(i) === cdbPdest(j) && cdbValid(j)) {
182          src3Rdy(i) := true.B
183          src3Data(i) := cdbData(j)
184        }
185      })
186    }
187  )
188
189  // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself)
190  // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag
191  // byPassUops is one cycle before byPassDatas
192  // TODO: the when-style may causes long-long-long Mux(which means long latency)
193  val selUopPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest)
194  val selUopValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) // may only need valid not fire()
195  List.tabulate(iqSize)(i  =>
196    when (valid(i)) {
197      List.tabulate(bypassCnt)(j => {
198        when(!src1Rdy(i) && prfSrc1(i) === selUopPdest(j) && selUopValid(j)) {
199          src1Rdy(i) := true.B
200        }
201        when(!src2Rdy(i) && prfSrc2(i) === selUopPdest(j) && selUopValid(j)) {
202          src2Rdy(i) := true.B
203        }
204        when(!src3Rdy(i) && prfSrc3(i) === selUopPdest(j) && selUopValid(j)) {
205          src3Rdy(i) := true.B
206        }
207      })
208    }
209  )
210
211  //---------------------------------------------------------
212  // Select Circuit
213  //---------------------------------------------------------
214  //layer 1
215  val layer1CCUs = (0 until layer1Size by 2) map { i =>
216    val CCU_1 = Module(new CompareCircuitUnit(layer = 1, id = i/2))
217    CCU_1.io.in1.instRdy := instRdy(i)
218    CCU_1.io.in1.roqIdx  := roqIdx(i)
219    CCU_1.io.in1.iqIdx   := i.U
220
221    CCU_1.io.in2.instRdy := instRdy(i+1)
222    CCU_1.io.in2.roqIdx  := roqIdx(i+1)
223    CCU_1.io.in2.iqIdx   := (i+1).U
224
225    CCU_1
226  }
227
228  //layer 2
229  val layer2CCUs = (0 until layer2Size by 2) map { i =>
230    val CCU_2 = Module(new CompareCircuitUnit(layer = 2, id = i/2))
231    CCU_2.io.in1.instRdy := layer1CCUs(i).io.out.instRdy
232    CCU_2.io.in1.roqIdx  := layer1CCUs(i).io.out.roqIdx
233    CCU_2.io.in1.iqIdx   := layer1CCUs(i).io.out.iqIdx
234
235    CCU_2.io.in2.instRdy := layer1CCUs(i+1).io.out.instRdy
236    CCU_2.io.in2.roqIdx  := layer1CCUs(i+1).io.out.roqIdx
237    CCU_2.io.in2.iqIdx   := layer1CCUs(i+1).io.out.iqIdx
238
239    CCU_2
240  }
241
242  //layer 3
243  val CCU_3 = Module(new CompareCircuitUnit(layer = 3, id = 0))
244  CCU_3.io.in1.instRdy := layer2CCUs(0).io.out.instRdy
245  CCU_3.io.in1.roqIdx  := layer2CCUs(0).io.out.roqIdx
246  CCU_3.io.in1.iqIdx   := layer2CCUs(0).io.out.iqIdx
247
248  CCU_3.io.in2.instRdy := layer2CCUs(1).io.out.instRdy
249  CCU_3.io.in2.roqIdx  := layer2CCUs(1).io.out.roqIdx
250  CCU_3.io.in2.iqIdx   := layer2CCUs(1).io.out.iqIdx
251
252
253}
254