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