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 assert(io.enqCtrl.valid && io.redirect.valid,"enqueue valid should be false when redirect valid") 108 109 when(io.enqCtrl.fire()){ 110 ctrlFlow(enqueueSelect) := io.enqCtrl.bits.cf 111 ctrlSig(enqueueSelect) := io.enqCtrl.bits.ctrl 112 brMask(enqueueSelect) := io.enqCtrl.bits.brMask 113 valid(enqueueSelect) := true.B 114 src1Rdy(enqueueSelect) := io.enqCtrl.bits.src1State === SrcState.rdy 115 src2Rdy(enqueueSelect) := io.enqCtrl.bits.src2State === SrcState.rdy 116 src3Rdy(enqueueSelect) := io.enqCtrl.bits.src3State === SrcState.rdy 117 prfSrc1(enqueueSelect) := io.enqCtrl.bits.psrc1 118 prfSrc2(enqueueSelect) := io.enqCtrl.bits.psrc2 119 prfSrc3(enqueueSelect) := io.enqCtrl.bits.psrc3 120 prfDest(enqueueSelect) := io.enqCtrl.bits.pdest 121 oldPDest(enqueueSelect) := io.enqCtrl.bits.old_pdest 122 freelistAllocPtr(enqueueSelect) := io.enqCtrl.bits.freelistAllocPtr 123 roqIdx(enqueueSelect) := io.enqCtrl.bits.roqIdx 124 125 } 126 127 //Data Queue 128 val src1Data = Reg(Vec(iqSize, UInt(XLEN.W))) 129 val src2Data = Reg(Vec(iqSize, UInt(XLEN.W))) 130 val src3Data = Reg(Vec(iqSize, UInt(XLEN.W))) 131 132 val enqSelNext = RegNext(enqueueSelect) 133 val enqFireNext = RegNext(io.enqCtrl.fire()) 134 135 // Read RegFile 136 when (enqFireNext) { 137 src1Data(enqSelNext) := io.enqData.bits.src1 138 src2Data(enqSelNext) := io.enqData.bits.src2 139 src3Data(enqSelNext) := io.enqData.bits.src3 140 } 141 142 // From Common Data Bus(wakeUpPort) 143 // TODO: the when-style may causes long-long-long Mux(which means long latency) 144 // TODO: ignore ALU'cdb srcRdy, for byPass has done it 145 val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid) 146 val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data) 147 val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest) 148 List.tabulate(iqSize)(i => 149 when (valid(i)) { 150 List.tabulate(wakeupCnt)(j => { 151 when(!src1Rdy(i) && prfSrc1(i) === cdbPdest(j) && cdbValid(j)) { 152 src1Rdy(i) := true.B 153 src1Data(i) := cdbData(j) 154 } 155 when(!src2Rdy(i) && prfSrc2(i) === cdbPdest(j) && cdbValid(j)) { 156 src2Rdy(i) := true.B 157 src2Data(i) := cdbData(j) 158 } 159 when(!src3Rdy(i) && prfSrc3(i) === cdbPdest(j) && cdbValid(j)) { 160 src3Rdy(i) := true.B 161 src3Data(i) := cdbData(j) 162 } 163 }) 164 } 165 ) 166 167 // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself) 168 // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag 169 // byPassUops is one cycle before byPassDatas 170 // TODO: the when-style may causes long-long-long Mux(which means long latency) 171 val selUopPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest) 172 val selUopValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) // may only need valid not fire() 173 List.tabulate(iqSize)(i => 174 when (valid(i)) { 175 List.tabulate(bypassCnt)(j => { 176 when(!src1Rdy(i) && prfSrc1(i) === selUopPdest(j) && selUopValid(j)) { 177 src1Rdy(i) := true.B 178 } 179 when(!src2Rdy(i) && prfSrc2(i) === selUopPdest(j) && selUopValid(j)) { 180 src2Rdy(i) := true.B 181 } 182 when(!src3Rdy(i) && prfSrc3(i) === selUopPdest(j) && selUopValid(j)) { 183 src3Rdy(i) := true.B 184 } 185 }) 186 } 187 ) 188 189 //--------------------------------------------------------- 190 // Select Circuit 191 //--------------------------------------------------------- 192 //layer 1 193 val layer1CCUs = (0 until layer1Size by 2) map { i => 194 val CCU_1 = Module(new CompareCircuitUnit(layer = 1, id = i/2)) 195 CCU_1.io.in1.instRdy := instRdy(i) 196 CCU_1.io.in1.roqIdx := roqIdx(i) 197 CCU_1.io.in1.iqIdx := i.U 198 199 CCU_1.io.in2.instRdy := instRdy(i+1) 200 CCU_1.io.in2.roqIdx := roqIdx(i+1) 201 CCU_1.io.in2.iqIdx := (i+1).U 202 203 CCU_1 204 } 205 206 //layer 2 207 val layer2CCUs = (0 until layer2Size by 2) map { i => 208 val CCU_2 = Module(new CompareCircuitUnit(layer = 2, id = i/2)) 209 CCU_2.io.in1.instRdy := layer1CCUs(i).io.out.instRdy 210 CCU_2.io.in1.roqIdx := layer1CCUs(i).io.out.roqIdx 211 CCU_2.io.in1.iqIdx := layer1CCUs(i).io.out.iqIdx 212 213 CCU_2.io.in2.instRdy := layer1CCUs(i+1).io.out.instRdy 214 CCU_2.io.in2.roqIdx := layer1CCUs(i+1).io.out.roqIdx 215 CCU_2.io.in2.iqIdx := layer1CCUs(i+1).io.out.iqIdx 216 217 CCU_2 218 } 219 220 //layer 3 221 val CCU_3 = Module(new CompareCircuitUnit(layer = 3, id = 0)) 222 CCU_3.io.in1.instRdy := layer2CCUs(0).io.out.instRdy 223 CCU_3.io.in1.roqIdx := layer2CCUs(0).io.out.roqIdx 224 CCU_3.io.in1.iqIdx := layer2CCUs(0).io.out.iqIdx 225 226 CCU_3.io.in2.instRdy := layer2CCUs(1).io.out.instRdy 227 CCU_3.io.in2.roqIdx := layer2CCUs(1).io.out.roqIdx 228 CCU_3.io.in2.iqIdx := layer2CCUs(1).io.out.iqIdx 229 230 231 //Dequeue Logic 232 //hold the sel-index to wait for data 233 val selInstIdx = RegNext(CCU_3.io.out.iqIdx) 234 val selInstRdy = RegNext(CCU_3.io.out.instRdy) 235 236 //issue the select instruction 237 val dequeueSelect = Wire(UInt(iqIdxWidth.W)) 238 dequeueSelect := selInstIdx 239 240 val IQreadyGo = selInstRdy 241 242 io.deq.valid := IQreadyGo 243 244 io.deq.bits.uop.psrc1 := prfSrc1(dequeueSelect) 245 io.deq.bits.uop.psrc2 := prfSrc2(dequeueSelect) 246 io.deq.bits.uop.psrc3 := prfSrc3(dequeueSelect) 247 io.deq.bits.uop.pdest := prfDest(dequeueSelect) 248 io.deq.bits.uop.old_pdest := oldPDest(dequeueSelect) 249 io.deq.bits.uop.src1State := SrcState.rdy 250 io.deq.bits.uop.src2State := SrcState.rdy 251 io.deq.bits.uop.src3State := SrcState.rdy 252 io.deq.bits.uop.freelistAllocPtr := freelistAllocPtr(dequeueSelect) 253 io.deq.bits.uop.roqIdx := roqIdx(dequeueSelect) 254 255 //TODO 256 io.deq.bits.redirect := DontCare 257 258 io.deq.bits.src1 := src1Data(dequeueSelect) 259 io.deq.bits.src2 := src2Data(dequeueSelect) 260 io.deq.bits.src3 := src3Data(dequeueSelect) 261 262 //clear the validBit of dequeued instruction in issuequeue 263 when(io.deq.fire()){ 264 valid(dequeueSelect) := false.B 265 } 266 267 //--------------------------------------------------------- 268 // Redirect Logic 269 //--------------------------------------------------------- 270 val expRedirect = io.redirect.valid && io.redirect.bits.isException 271 val brRedirect = io.redirect.valid && !io.redirect.bits.isException 272 273 UIntToOH(io.redirect.bits.brTag) 274 List.tabulate(iqSize)( 275 when(brRedirect && (UIntToOH(io.redirect.bits.brTag) & brMask(i)).orR && valid(i) ){ 276 valid(i) := false.B 277 } .elsewhen(expRedirect) { 278 valid(i) := false.B 279 } 280 ) 281 282 283 284 285 286 287} 288