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