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