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