xref: /XiangShan/src/main/scala/xiangshan/backend/issue/IssueQueue.scala (revision 7003bf16a4e7aa2841e4fc416e5bbb7f29da4af1)
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.iqIdx   := Mux(inst1Rdy,Mux(inst2Rdy,iqIdx2,iqIdx1)
41
42  when((inst1Rdy && !inst2Rdy) || (inst1Rdy && inst2Rdy && (roqIdx1 < roqIdx2))){
43    io.out.roqIdx := roqIdx1
44    io.out.iqIdx := iqIdx1
45  }
46
47  when((inst2Rdy && !inst1Rdy) || (inst2Rdy && inst1Rdy && (roqIdx2 < roqIdx1))){
48    io.out.roqIdx := roqIdx2
49    io.out.iqIdx := iqIdx2
50  }
51
52
53}
54
55class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int) extends IQModule {
56
57  val useBypass = bypassCnt > 0
58
59  val io = IO(new Bundle() {
60    // flush Issue Queue
61    val redirect = Flipped(ValidIO(new Redirect))
62
63    // enq Ctrl sigs at dispatch-2
64    val enqCtrl = Flipped(DecoupledIO(new MicroOp))
65    // enq Data at next cycle (regfile has 1 cycle latency)
66    val enqData = Flipped(ValidIO(new ExuInput))
67
68    //  broadcast selected uop to other issue queues which has bypasses
69    val selectedUop = if(useBypass) DecoupledIO(new MicroOp) else null
70
71    // send to exu
72    val deq = DecoupledIO(new ExuInput)
73
74    // listen to write back bus
75    val wakeUpPorts = Vec(wakeupCnt, Flipped(DecoupledIO(new ExuOutput)))
76
77    // use bypass uops to speculative wake-up
78    val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(DecoupledIO(new MicroOp))) else null
79    val bypassData = if(useBypass) Vec(bypassCnt, Flipped(DecoupledIO(new ExuOutput))) else null
80  })
81  //---------------------------------------------------------
82  // Issue Queue
83  //---------------------------------------------------------
84
85  //Tag Queue
86  val ctrlFlow = Mem(iqSize,new CtrlFlow)
87  val ctrlSig = Mem(iqSize,new CtrlSignals)
88  val brMask  = RegInit(VecInit(Seq.fill(iqSize)(0.U(BrqSize.W))))
89  val valid   = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
90  val src1Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
91  val src2Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
92  val src3Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B)))
93  val prfSrc1 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
94  val prfSrc2 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
95  val prfSrc3 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
96  val prfDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
97  val oldPDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
98  val freelistAllocPrt = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W)))
99  val roqIdx  = Reg(Vec(iqSize, UInt(RoqIdxWidth.W)))
100
101  val instRdy = WireInit(VecInit(List.tabulate(iqSize)(i => src1Rdy(i) && src2Rdy(i) && valid(i))))
102
103
104  //tag enqueue
105  val iqEmty = !valid.asUInt.orR
106  val iqFull =  valid.asUInt.andR
107  val iqAllowIn = !iqFull
108  io.enqCtrl.ready := iqAllowIn
109
110  //enqueue pointer
111  val emptySlot = ~valid.asUInt
112  val enqueueSelect = PriorityEncoder(emptySlot)
113
114  when(io.enqCtrl.fire()){
115    ctrlFlow(enqueueSelect) := io.enqCtrl.bits.cf
116    ctrlSig(enqueueSelect) := io.enqCtrl.bits.ctrl
117    brMask(enqueueSelect) := io.enqCtrl.bits.brMask
118    valid(enqueueSelect) := true.B
119    src1Rdy(enqueueSelect) := io.enqCtrl.bits.src1State === SrcState.rdy
120    src2Rdy(enqueueSelect) := io.enqCtrl.bits.src2State === SrcState.rdy
121    src3Rdy(enqueueSelect) := io.enqCtrl.bits.src3State === SrcState.rdy
122    prfSrc1(enqueueSelect) := io.enqCtrl.bits.psrc1
123    prfSrc2(enqueueSelect) := io.enqCtrl.bits.psrc2
124    prfSrc3(enqueueSelect) := io.enqCtrl.bits.psrc3
125    prfDest(enqueueSelect) := io.enqCtrl.bits.pdest
126    oldPDest(enqueueSelect) := io.enqCtrl.bits.old_pdest
127    freelistAllocPrt(enqueueSelect) := io.enqCtrl.bits.freelistAllocPtr
128    roqIdx(enqueueSelect) := io.enqCtrl.bits.roqIdx
129
130  }
131
132  //Data Queue
133  val src1Data = Reg(Vec(iqSize, UInt(XLEN.W)))
134  val src2Data = Reg(Vec(iqSize, UInt(XLEN.W)))
135  val src3Data = Reg(Vec(iqSize, UInt(XLEN.W)))
136
137  val enqSelNext = RegNext(enqueueSelect)
138  val enqFireNext = RegNext(io.enqCtrl.fire())
139
140  // Read RegFile
141  when (enqFireNext) {
142    src1Data(enqSelNext) := io.enqData.bits.src1
143    src2Data(enqSelNext) := io.enqData.bits.src2
144    src3Data(enqSelNext) := io.enqData.bits.src3
145  }
146  // From Common Data Bus(wakeUpPort)
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  List.tabulate(iqSize)(i =>
151    when (valid(i)) {
152      List.tabulate(wakeupCnt)(j =>
153        when(!src1Rdy(i) && prfSrc1(i) === cdbPdest(j) && cdbValid(j)) {
154          src1Rdy(i) := true.B
155          src1Data(i) := cdbData(j)
156        }
157      )
158      List.tabulate(wakeupCnt)(j =>
159        when(!src2Rdy(i) && prfSrc2(i) === cdbPdest(j) && cdbValid(j)) {
160          src2Rdy(i) := true.B
161          src2Data(i) := cdbData(j)
162        }
163      )
164      List.tabulate(wakeupCnt)(j =>
165        when(!src3Rdy(i) && prfSrc3(i) === cdbPdest(j) && cdbValid(j)) {
166          src3Rdy(i) := true.B
167          src3Data(i) := cdbData(j)
168        }
169      )
170    }
171  )
172
173  // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself)
174  // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag
175
176
177  //---------------------------------------------------------
178  // Select Circuit
179  //---------------------------------------------------------
180  //layer 1
181  val layer1CCUs = (0 until layer1Size by 2) map { i =>
182    val CCU_1 = Module(new CompareCircuitUnit(layer = 1, id = i/2))
183    CCU_1.io.in1.instRdy := instRdy(i)
184    CCU_1.io.in1.roqIdx  := roqIdx(i)
185    CCU_1.io.in1.iqIdx   := i.U
186
187    CCU_1.io.in2.instRdy := instRdy(i+1)
188    CCU_1.io.in2.roqIdx  := roqIdx(i+1)
189    CCU_1.io.in2.iqIdx   := (i+1).U
190
191    CCU_1
192  }
193
194  //layer 2
195  val layer2CCUs = (0 until layer2Size by 2) map { i =>
196    val CCU_2 = Module(new CompareCircuitUnit(layer = 2, id = i/2))
197    CCU_2.io.in1.instRdy := layer1CCUs(i).io.out.instRdy
198    CCU_2.io.in1.roqIdx  := layer1CCUs(i).io.out.roqIdx
199    CCU_2.io.in1.iqIdx   := layer1CCUs(i).io.out.iqIdx
200
201    CCU_2.io.in2.instRdy := layer1CCUs(i+1).io.out.instRdy
202    CCU_2.io.in2.roqIdx  := layer1CCUs(i+1).io.out.roqIdx
203    CCU_2.io.in2.iqIdx   := layer1CCUs(i+1).io.out.iqIdx
204
205    CCU_2
206  }
207
208  //layer 3
209  val CCU_3 = Module(new CompareCircuitUnit(layer = 3, id = 0))
210  CCU_3.io.in1.instRdy := layer2CCUs(0).io.out.instRdy
211  CCU_3.io.in1.roqIdx  := layer2CCUs(0).io.out.roqIdx
212  CCU_3.io.in1.iqIdx   := layer2CCUs(0).io.out.iqIdx
213
214  CCU_3.io.in2.instRdy := layer2CCUs(1).io.out.instRdy
215  CCU_3.io.in2.roqIdx  := layer2CCUs(1).io.out.roqIdx
216  CCU_3.io.in2.iqIdx   := layer2CCUs(1).io.out.iqIdx
217
218
219
220
221
222
223}
224