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