xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision e71f3325d7c0370eea7c7003d36ae45bd4cadc36)
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  val readySignal = Cat(inst1Rdy,inst2Rdy)
40
41  switch (readySignal) {
42    is ("b00".U) {
43      io.out.instRdy := false.B
44      io.out.roqIdx := DontCare
45      io.out.iqIdx := DontCare
46    }
47    is ("b01".U) {
48      io.out.instRdy := inst2Rdy
49      io.out.roqIdx := roqIdx2
50      io.out.iqIdx := iqIdx2
51     }
52    is ("b10".U) {
53      io.out.instRdy := inst1Rdy
54      io.out.roqIdx := roqIdx1
55      io.out.iqIdx := iqIdx1
56    }
57    is ("b11".U) {
58      when(roqIdx1 < roqIdx2) {
59        io.out.instRdy := inst1Rdy
60        io.out.roqIdx := roqIdx1
61        io.out.iqIdx := iqIdx1
62      } .otherwise {
63        io.out.instRdy := inst2Rdy
64        io.out.roqIdx := roqIdx2
65        io.out.iqIdx := iqIdx2
66      }
67    }
68  }
69
70}
71
72class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int) extends IQModule {
73
74  val useBypass = bypassCnt > 0
75
76  val io = IO(new Bundle() {
77    // flush Issue Queue
78    val redirect = Flipped(ValidIO(new Redirect))
79
80    // enq Ctrl sigs at dispatch-2
81    val enqCtrl = Flipped(DecoupledIO(new MicroOp))
82    // enq Data at next cycle (regfile has 1 cycle latency)
83    val enqData = Flipped(ValidIO(new ExuInput))
84
85    //  broadcast selected uop to other issue queues which has bypasses
86    val selectedUop = if(useBypass) DecoupledIO(new MicroOp) else null
87
88    // send to exu
89    val deq = DecoupledIO(new ExuInput)
90
91    // listen to write back bus
92    val wakeUpPorts = Vec(wakeupCnt, Flipped(DecoupledIO(new ExuOutput)))
93
94    // use bypass uops to speculative wake-up
95    val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(DecoupledIO(new MicroOp))) else null
96    val bypassData = if(useBypass) Vec(bypassCnt, Flipped(DecoupledIO(new ExuOutput))) 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  // From Common Data Bus(wakeUpPort)
164  val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid)
165  val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data)
166  val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest)
167  List.tabulate(iqSize)(i =>
168    when (valid(i)) {
169      List.tabulate(wakeupCnt)(j =>
170        when(!src1Rdy(i) && prfSrc1(i) === cdbPdest(j) && cdbValid(j)) {
171          src1Rdy(i) := true.B
172          src1Data(i) := cdbData(j)
173        }
174      )
175      List.tabulate(wakeupCnt)(j =>
176        when(!src2Rdy(i) && prfSrc2(i) === cdbPdest(j) && cdbValid(j)) {
177          src2Rdy(i) := true.B
178          src2Data(i) := cdbData(j)
179        }
180      )
181      List.tabulate(wakeupCnt)(j =>
182        when(!src3Rdy(i) && prfSrc3(i) === cdbPdest(j) && cdbValid(j)) {
183          src3Rdy(i) := true.B
184          src3Data(i) := cdbData(j)
185        }
186      )
187    }
188  )
189
190  // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself)
191  // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag
192
193
194  //---------------------------------------------------------
195  // Select Circuit
196  //---------------------------------------------------------
197  //layer 1
198  val layer1CCUs = (0 until layer1Size by 2) map { i =>
199    val CCU_1 = Module(new CompareCircuitUnit(layer = 1, id = i/2))
200    CCU_1.io.in1.instRdy := instRdy(i)
201    CCU_1.io.in1.roqIdx  := roqIdx(i)
202    CCU_1.io.in1.iqIdx   := i.U
203
204    CCU_1.io.in2.instRdy := instRdy(i+1)
205    CCU_1.io.in2.roqIdx  := roqIdx(i+1)
206    CCU_1.io.in2.iqIdx   := (i+1).U
207
208    CCU_1
209  }
210
211  //layer 2
212  val layer2CCUs = (0 until layer2Size by 2) map { i =>
213    val CCU_2 = Module(new CompareCircuitUnit(layer = 2, id = i/2))
214    CCU_2.io.in1.instRdy := layer1CCUs(i).io.out.instRdy
215    CCU_2.io.in1.roqIdx  := layer1CCUs(i).io.out.roqIdx
216    CCU_2.io.in1.iqIdx   := layer1CCUs(i).io.out.iqIdx
217
218    CCU_2.io.in2.instRdy := layer1CCUs(i+1).io.out.instRdy
219    CCU_2.io.in2.roqIdx  := layer1CCUs(i+1).io.out.roqIdx
220    CCU_2.io.in2.iqIdx   := layer1CCUs(i+1).io.out.iqIdx
221
222    CCU_2
223  }
224
225  //layer 3
226  val CCU_3 = Module(new CompareCircuitUnit(layer = 3, id = 0))
227  CCU_3.io.in1.instRdy := layer2CCUs(0).io.out.instRdy
228  CCU_3.io.in1.roqIdx  := layer2CCUs(0).io.out.roqIdx
229  CCU_3.io.in1.iqIdx   := layer2CCUs(0).io.out.iqIdx
230
231  CCU_3.io.in2.instRdy := layer2CCUs(1).io.out.instRdy
232  CCU_3.io.in2.roqIdx  := layer2CCUs(1).io.out.roqIdx
233  CCU_3.io.in2.iqIdx   := layer2CCUs(1).io.out.iqIdx
234
235
236
237
238
239
240}
241