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