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 debug = false 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 io.out.instRdy := inst1Rdy | inst2Rdy 42 io.out.roqIdx := roqIdx2 43 io.out.iqIdx := iqIdx2 44 45 when((inst1Rdy && !inst2Rdy) || (inst1Rdy && inst2Rdy && (roqIdx1 < roqIdx2))){ 46 io.out.roqIdx := roqIdx1 47 io.out.iqIdx := iqIdx1 48 } 49 if(debug && (layer==3)) { 50 printf("(%d)[CCU(L%did%d)] in1.ready:%d in1.index:%d || in1.ready:%d in1.index:%d || out.ready:%d out.index:%d\n",GTimer(),layer.asUInt,id.asUInt,inst1Rdy,iqIdx1,inst2Rdy,iqIdx2,io.out.instRdy,io.out.iqIdx) 51 } 52 53 54} 55 56class IssueQueue(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int = 0, val fixedDelay: Int = 1) extends IQModule { 57 58 val useBypass = bypassCnt > 0 59 60 val io = IO(new Bundle() { 61 // flush Issue Queue 62 val redirect = Flipped(ValidIO(new Redirect)) 63 64 // enq Ctrl sigs at dispatch-2 65 val enqCtrl = Flipped(DecoupledIO(new MicroOp)) 66 // enq Data at next cycle (regfile has 1 cycle latency) 67 val enqData = Flipped(ValidIO(new ExuInput)) 68 69 // broadcast selected uop to other issue queues which has bypasses 70 val selectedUop = if(useBypass) ValidIO(new MicroOp) else null 71 72 // send to exu 73 val deq = DecoupledIO(new ExuInput) 74 75 // listen to write back bus 76 val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput))) 77 78 // use bypass uops to speculative wake-up 79 val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) else null 80 val bypassData = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new ExuOutput))) else null 81 }) 82 //--------------------------------------------------------- 83 // Issue Queue 84 //--------------------------------------------------------- 85 86 //Tag Queue 87 val ctrlFlow = Mem(iqSize,new CtrlFlow) 88 val ctrlSig = Mem(iqSize,new CtrlSignals) 89 val brMask = RegInit(VecInit(Seq.fill(iqSize)(0.U(BrqSize.W)))) 90 val brTag = RegInit(VecInit(Seq.fill(iqSize)(0.U(BrTagWidth.W)))) 91 val validReg = RegInit(VecInit(Seq.fill(iqSize)(false.B))) 92 val validFire= WireInit(VecInit(Seq.fill(iqSize)(false.B))) 93 val valid = validReg.asUInt & ~validFire.asUInt 94 val src1Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B))) 95 val src2Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B))) 96 val src3Rdy = RegInit(VecInit(Seq.fill(iqSize)(false.B))) 97 val prfSrc1 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W))) 98 val prfSrc2 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W))) 99 val prfSrc3 = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W))) 100 val prfDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W))) 101 val oldPDest = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W))) 102 val freelistAllocPtr = Reg(Vec(iqSize, UInt(PhyRegIdxWidth.W))) 103 val roqIdx = Reg(Vec(iqSize, UInt(RoqIdxWidth.W))) 104 105 val instRdy = WireInit(VecInit(List.tabulate(iqSize)(i => src1Rdy(i) && src2Rdy(i) && src3Rdy(i)&& valid(i)))) 106 107 108 //tag enqueue 109 val iqEmty = !valid.asUInt.orR 110 val iqFull = valid.asUInt.andR 111 val iqAllowIn = !iqFull 112 io.enqCtrl.ready := iqAllowIn 113 114 //enqueue pointer 115 val emptySlot = ~valid.asUInt 116 val enqueueSelect = PriorityEncoder(emptySlot) 117 assert(!(io.enqCtrl.valid && io.redirect.valid),"enqueue valid should be false when redirect valid") 118 119 val srcEnqRdy = WireInit(VecInit(false.B, false.B, false.B)) 120 121 srcEnqRdy(0) := Mux(io.enqCtrl.bits.ctrl.src1Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src1State === SrcState.rdy) 122 srcEnqRdy(1) := Mux(io.enqCtrl.bits.ctrl.src2Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src2State === SrcState.rdy) 123 srcEnqRdy(2) := Mux(io.enqCtrl.bits.ctrl.src3Type =/= SrcType.reg , true.B ,io.enqCtrl.bits.src3State === SrcState.rdy) 124 125 when (io.enqCtrl.fire()) { 126 ctrlFlow(enqueueSelect) := io.enqCtrl.bits.cf 127 ctrlSig(enqueueSelect) := io.enqCtrl.bits.ctrl 128 brMask(enqueueSelect) := io.enqCtrl.bits.brMask 129 brTag(enqueueSelect) := io.enqCtrl.bits.brTag 130 validReg(enqueueSelect) := true.B 131 src1Rdy(enqueueSelect) := srcEnqRdy(0) 132 src2Rdy(enqueueSelect) := srcEnqRdy(1) 133 src3Rdy(enqueueSelect) := srcEnqRdy(2) 134 prfSrc1(enqueueSelect) := io.enqCtrl.bits.psrc1 135 prfSrc2(enqueueSelect) := io.enqCtrl.bits.psrc2 136 prfSrc3(enqueueSelect) := io.enqCtrl.bits.psrc3 137 prfDest(enqueueSelect) := io.enqCtrl.bits.pdest 138 oldPDest(enqueueSelect) := io.enqCtrl.bits.old_pdest 139 freelistAllocPtr(enqueueSelect) := io.enqCtrl.bits.freelistAllocPtr 140 roqIdx(enqueueSelect) := io.enqCtrl.bits.roqIdx 141 if(debug) {printf("(%d)[IQ enq]: enqSelect:%d | s1Rd:%d s2Rd:%d s3Rd:%d\n",GTimer(),enqueueSelect.asUInt, 142 (io.enqCtrl.bits.src1State === SrcState.rdy), 143 (io.enqCtrl.bits.src2State === SrcState.rdy), 144 (io.enqCtrl.bits.src3State === SrcState.rdy))} 145 146 } 147 148 //Data Queue 149 val src1Data = Reg(Vec(iqSize, UInt(XLEN.W))) 150 val src2Data = Reg(Vec(iqSize, UInt(XLEN.W))) 151 val src3Data = Reg(Vec(iqSize, UInt(XLEN.W))) 152 153 154 val enqSelNext = RegNext(enqueueSelect) 155 val enqFireNext = RegNext(io.enqCtrl.fire()) 156 157 // Read RegFile 158 //Ready data will written at next cycle 159 when (enqFireNext) { 160 when(src1Rdy(enqSelNext)){src1Data(enqSelNext) := io.enqData.bits.src1} 161 when(src2Rdy(enqSelNext)){src2Data(enqSelNext) := io.enqData.bits.src2} 162 when(src3Rdy(enqSelNext)){src3Data(enqSelNext) := io.enqData.bits.src3} 163 } 164 165 if(debug) { 166 printf("(%d)[Reg info] enqSelNext:%d | enqFireNext:%d \n",GTimer(),enqSelNext,enqFireNext) 167 printf("(%d)[IQ content] valid | src1rdy src1 | src2Rdy src2 pdest \n",GTimer()) 168 for(i <- 0 to (iqSize -1)){ 169 printf("(%d)[IQ content][%d] %d%d%d | %x %x | %x %x | %d",GTimer(),i.asUInt, valid(i), validReg(i), validFire(i), src1Rdy(i), src1Data(i), src2Rdy(i), src2Data(i),prfDest(i)) 170 when(valid(i)){printf(" valid")} 171 printf(" |\n") 172 } 173 } 174 // From Common Data Bus(wakeUpPort) 175 // chisel claims that firrtl will optimize Mux1H to and/or tree 176 // TODO: ignore ALU'cdb srcRdy, for byPass has done it 177 if(wakeupCnt > 0) { 178 val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid) 179 val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data) 180 val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest) 181 182 val srcNum = 3 183 val prfSrc = List(prfSrc1, prfSrc2, prfSrc3) 184 val srcRdy = List(src1Rdy, src2Rdy, src3Rdy) 185 val srcData = List(src1Data, src2Data, src3Data) 186 val srcHitVec = List.tabulate(srcNum)(k => 187 List.tabulate(iqSize)(i => 188 List.tabulate(wakeupCnt)(j => 189 (prfSrc(k)(i) === cdbPdest(j)) && cdbValid(j)))) 190 val srcHit = List.tabulate(srcNum)(k => 191 List.tabulate(iqSize)(i => 192 ParallelOR(srcHitVec(k)(i)).asBool())) 193 // VecInit(srcHitVec(k)(i)).asUInt.orR)) 194 for(k <- 0 until srcNum){ 195 for(i <- 0 until iqSize)( when (valid(i)) { 196 when(!srcRdy(k)(i) && srcHit(k)(i)) { 197 srcRdy(k)(i) := true.B 198 // srcData(k)(i) := Mux1H(srcHitVec(k)(i), cdbData) 199 srcData(k)(i) := ParallelMux(srcHitVec(k)(i) zip cdbData) 200 } 201 }) 202 } 203 // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself) 204 // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag 205 // byPassUops is one cycle before byPassDatas 206 if (bypassCnt > 0) { 207 val bypassPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest) 208 val bypassValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) // may only need valid not fire() 209 val bypassData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data) 210 val srcBpHitVec = List.tabulate(srcNum)(k => 211 List.tabulate(iqSize)(i => 212 List.tabulate(bypassCnt)(j => 213 (prfSrc(k)(i) === bypassPdest(j)) && bypassValid(j)))) 214 val srcBpHit = List.tabulate(srcNum)(k => 215 List.tabulate(iqSize)(i => 216 ParallelOR(srcBpHitVec(k)(i)).asBool())) 217 // VecInit(srcBpHitVec(k)(i)).asUInt.orR)) 218 val srcBpHitVecNext = List.tabulate(srcNum)(k => 219 List.tabulate(iqSize)(i => 220 List.tabulate(bypassCnt)(j => RegNext(srcBpHitVec(k)(i)(j))))) 221 val srcBpHitNext = List.tabulate(srcNum)(k => 222 List.tabulate(iqSize)(i => 223 RegNext(srcBpHit(k)(i)))) 224 val srcBpData = List.tabulate(srcNum)(k => 225 List.tabulate(iqSize)(i => 226 ParallelMux(srcBpHitVecNext(k)(i) zip bypassData))) 227 // Mux1H(srcBpHitVecNext(k)(i), bypassData))) 228 for(k <- 0 until srcNum){ 229 for(i <- 0 until iqSize){ when (valid(i)) { 230 when(valid(i) && !srcRdy(k)(i) && srcBpHit(k)(i)) { srcRdy(k)(i) := true.B } 231 when(srcBpHitNext(k)(i)) { srcData(k)(i) := srcBpData(k)(i)} 232 }} 233 } 234 235 // Enqueue Bypass 236 val enqBypass = WireInit(VecInit(false.B, false.B, false.B)) 237 val enqBypassHitVec = List(List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc1 === bypassPdest(j) && bypassValid(j) && io.enqCtrl.fire()), 238 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc2 === bypassPdest(j) && bypassValid(j) && io.enqCtrl.fire()), 239 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc3 === bypassPdest(j) && bypassValid(j) && io.enqCtrl.fire())) 240 val enqBypassHitVecNext = enqBypassHitVec.map(i => i.map(j => RegNext(j))) 241 enqBypass(0) := ParallelOR(enqBypassHitVec(0)) 242 enqBypass(1) := ParallelOR(enqBypassHitVec(1)) 243 enqBypass(2) := ParallelOR(enqBypassHitVec(2)) 244 when(enqBypass(0)) { src1Rdy(enqueueSelect) := true.B } 245 when(enqBypass(1)) { src2Rdy(enqueueSelect) := true.B } 246 when(enqBypass(2)) { src3Rdy(enqueueSelect) := true.B } 247 when(RegNext(enqBypass(0))) { src1Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(0) zip bypassData)} 248 when(RegNext(enqBypass(1))) { src2Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(1) zip bypassData)} 249 when(RegNext(enqBypass(2))) { src3Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(2) zip bypassData)} 250 } 251 252 } 253 254 255 //--------------------------------------------------------- 256 // Select Circuit 257 //--------------------------------------------------------- 258 //layer 1 259 val layer1CCUs = (0 until layer1Size by 2) map { i => 260 val CCU_1 = Module(new CompareCircuitUnit(layer = 1, id = i/2)) 261 CCU_1.io.in1.instRdy := instRdy(i) 262 CCU_1.io.in1.roqIdx := roqIdx(i) 263 CCU_1.io.in1.iqIdx := i.U 264 265 CCU_1.io.in2.instRdy := instRdy(i+1) 266 CCU_1.io.in2.roqIdx := roqIdx(i+1) 267 CCU_1.io.in2.iqIdx := (i+1).U 268 269 CCU_1 270 } 271 272 //layer 2 273 val layer2CCUs = (0 until layer2Size by 2) map { i => 274 val CCU_2 = Module(new CompareCircuitUnit(layer = 2, id = i/2)) 275 CCU_2.io.in1.instRdy := layer1CCUs(i).io.out.instRdy 276 CCU_2.io.in1.roqIdx := layer1CCUs(i).io.out.roqIdx 277 CCU_2.io.in1.iqIdx := layer1CCUs(i).io.out.iqIdx 278 279 CCU_2.io.in2.instRdy := layer1CCUs(i+1).io.out.instRdy 280 CCU_2.io.in2.roqIdx := layer1CCUs(i+1).io.out.roqIdx 281 CCU_2.io.in2.iqIdx := layer1CCUs(i+1).io.out.iqIdx 282 283 CCU_2 284 } 285 286 //layer 3 287 val CCU_3 = Module(new CompareCircuitUnit(layer = 3, id = 0)) 288 CCU_3.io.in1.instRdy := layer2CCUs(0).io.out.instRdy 289 CCU_3.io.in1.roqIdx := layer2CCUs(0).io.out.roqIdx 290 CCU_3.io.in1.iqIdx := layer2CCUs(0).io.out.iqIdx 291 292 CCU_3.io.in2.instRdy := layer2CCUs(1).io.out.instRdy 293 CCU_3.io.in2.roqIdx := layer2CCUs(1).io.out.roqIdx 294 CCU_3.io.in2.iqIdx := layer2CCUs(1).io.out.iqIdx 295 296 297 //--------------------------------------------------------- 298 // Redirect Logic 299 //--------------------------------------------------------- 300 val expRedirect = io.redirect.valid && io.redirect.bits.isException 301 val brRedirect = io.redirect.valid && !io.redirect.bits.isException 302 303 List.tabulate(iqSize)( i => 304 when(brRedirect && (UIntToOH(io.redirect.bits.brTag) & brMask(i)).orR && valid(i) ){ 305 validReg(i) := false.B 306 validFire(dequeueSelect) := true.B 307 308 } .elsewhen(expRedirect) { 309 validReg(i) := false.B 310 validFire(dequeueSelect) := true.B 311 312 } 313 ) 314 //--------------------------------------------------------- 315 // Dequeue Logic 316 //--------------------------------------------------------- 317 //hold the sel-index to wait for data 318 val selInstIdx = RegInit(0.U(iqIdxWidth.W)) 319 val selInstRdy = RegInit(false.B) 320 321 //issue the select instruction 322 val dequeueSelect = Wire(UInt(iqIdxWidth.W)) 323 dequeueSelect := selInstIdx 324 325 val brRedirectMaskMatch = (UIntToOH(io.redirect.bits.brTag) & brMask(dequeueSelect)).orR 326 val IQreadyGo = selInstRdy && !expRedirect && (!brRedirect || !brRedirectMaskMatch) 327 328 io.deq.valid := IQreadyGo 329 330 io.deq.bits.uop.cf := ctrlFlow(dequeueSelect) 331 io.deq.bits.uop.ctrl := ctrlSig(dequeueSelect) 332 io.deq.bits.uop.brMask := brMask(dequeueSelect) 333 io.deq.bits.uop.brTag := brTag(dequeueSelect) 334 335 io.deq.bits.uop.psrc1 := prfSrc1(dequeueSelect) 336 io.deq.bits.uop.psrc2 := prfSrc2(dequeueSelect) 337 io.deq.bits.uop.psrc3 := prfSrc3(dequeueSelect) 338 io.deq.bits.uop.pdest := prfDest(dequeueSelect) 339 io.deq.bits.uop.old_pdest := oldPDest(dequeueSelect) 340 io.deq.bits.uop.src1State := SrcState.rdy 341 io.deq.bits.uop.src2State := SrcState.rdy 342 io.deq.bits.uop.src3State := SrcState.rdy 343 io.deq.bits.uop.freelistAllocPtr := freelistAllocPtr(dequeueSelect) 344 io.deq.bits.uop.roqIdx := roqIdx(dequeueSelect) 345 346 io.deq.bits.src1 := src1Data(dequeueSelect) 347 io.deq.bits.src2 := src2Data(dequeueSelect) 348 io.deq.bits.src3 := src3Data(dequeueSelect) 349 350 if(debug) { 351 printf("(%d)[Sel Reg] selInstRdy:%d || selIdx:%d\n",GTimer(),selInstRdy,selInstIdx.asUInt) 352 when(IQreadyGo){printf("(%d)[IQ dequeue] **fire:%d** roqIdx:%d dequeueSel:%d | src1Rd:%d src1:%d | src2Rd:%d src2:%d\n",GTimer(), io.deq.fire(), io.deq.bits.uop.roqIdx, dequeueSelect.asUInt, 353 (io.deq.bits.uop.src1State === SrcState.rdy), io.deq.bits.uop.psrc1, 354 (io.deq.bits.uop.src2State === SrcState.rdy), io.deq.bits.uop.psrc2 355 )} 356 } 357 358 //update the index register of instruction that can be issue, unless function unit not allow in 359 //then the issue will be stopped to wait the function unit 360 //clear the validBit of dequeued instruction in issuequeue 361 when(io.deq.fire()){ 362 validReg(dequeueSelect) := false.B 363 validFire(dequeueSelect) := true.B 364 } 365 366 val selRegflush = expRedirect || (brRedirect && brRedirectMaskMatch) 367 selInstRdy := Mux(selRegflush,false.B,CCU_3.io.out.instRdy) 368 selInstIdx := Mux(selRegflush,0.U,CCU_3.io.out.iqIdx) 369 // SelectedUop (bypass / speculative) 370 if(useBypass) { 371 assert(fixedDelay==1) // only support fixedDelay is 1 now 372 def DelayPipe[T <: Data](a: T, delay: Int = 0) = { 373 // println(delay) 374 if(delay == 0) a 375 else { 376 val storage = Wire(VecInit(Seq.fill(delay+1)(a))) 377 // storage(0) := a 378 for(i <- 1 until delay) { 379 storage(i) := RegNext(storage(i-1)) 380 } 381 storage(delay) 382 } 383 } 384 val sel = io.selectedUop 385 val selIQIdx = CCU_3.io.out.iqIdx 386 val delayPipe = DelayPipe(VecInit(CCU_3.io.out.instRdy, prfDest(selIQIdx)), fixedDelay-1) 387 sel.valid := delayPipe(fixedDelay-1)(0) && io.deq.ready 388 sel.bits := DontCare 389 sel.bits.pdest := delayPipe(fixedDelay-1)(1) 390 } 391} 392