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 val psrc = List.tabulate(iqSize)(i => List(prfSrc1(i), prfSrc2(i), prfSrc3(i))) 177 XSDebug("[Reg info-ENQ] enqSelNext:%d | enqFireNext:%d \n",enqSelNext,enqFireNext) 178 XSDebug("[IQ content] valid vr vf| pc insruction |[rdy|psrc] src1 | [rdy|psrc] src2 | [rdy|psrc] 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|[%d|%d]%x|[%d|%d]%x|[%d|%d]%x| %d valid|\n", 184 i.asUInt, valid(i), validReg(i), validWillFalse(i), pc, ins, src1Rdy(i), psrc(i)(0), src1Data(i), 185 src2Rdy(i), psrc(i)(1), src2Data(i), src3Rdy(i), psrc(i)(2), src3Data(i),prfDest(i)) 186 XSDebug(validReg(i) && validWillFalse(i), 187 "[IQ content][%d] %d%d%d |%x %x|[%d|%d]%x|[%d|%d]%x|[%d|%d]%x| %d valid will be False|\n", 188 i.asUInt, valid(i), validReg(i), validWillFalse(i), pc, ins, src1Rdy(i), psrc(i)(0), src1Data(i), 189 src2Rdy(i), psrc(i)(1), src2Data(i), src3Rdy(i), psrc(i)(2), src3Data(i), prfDest(i)) 190 XSDebug("[IQ content][%d] %d%d%d |%x %x|[%d|%d]%x|[%d|%d]%x|[%d|%d]%x| %d\n", 191 i.asUInt, valid(i), validReg(i), validWillFalse(i), pc, ins, src1Rdy(i), psrc(i)(0), src1Data(i), 192 src2Rdy(i), psrc(i)(1), src2Data(i), src3Rdy(i), psrc(i)(2), 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 cdbrfWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.rfWen) // FIXME: handle fpWen 200 val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data) 201 val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest) 202 203 val srcNum = 3 204 val prfSrc = List(prfSrc1, prfSrc2, prfSrc3) 205 val srcRdy = List(src1Rdy, src2Rdy, src3Rdy) 206 val srcData = List(src1Data, src2Data, src3Data) 207 val srcHitVec = List.tabulate(srcNum)(k => 208 List.tabulate(iqSize)(i => 209 List.tabulate(wakeupCnt)(j =>{ 210 (prfSrc(k)(i) === cdbPdest(j)) && (cdbValid(j) && cdbrfWen(j)) 211 }))) 212 val srcHit = List.tabulate(srcNum)(k => 213 List.tabulate(iqSize)(i => 214 ParallelOR(srcHitVec(k)(i)).asBool())) 215 // VecInit(srcHitVec(k)(i)).asUInt.orR)) 216 for(k <- 0 until srcNum){ 217 for(i <- 0 until iqSize)( when (valid(i)) { 218 when(!srcRdy(k)(i) && srcHit(k)(i)) { 219 srcRdy(k)(i) := true.B 220 // srcData(k)(i) := Mux1H(srcHitVec(k)(i), cdbData) 221 srcData(k)(i) := ParallelMux(srcHitVec(k)(i) zip cdbData) 222 } 223 XSDebug(srcHit(k)(i), "Wakeup: Sel:%d Src:%d|%d data:%x srcHitVec:%b cdbValid:%b cdbrfWen:%b\n", 224 i.U, k.U, prfSrc(k)(i), ParallelMux(srcHitVec(k)(i) zip cdbData), VecInit(srcHitVec(k)(i)).asUInt, VecInit(cdbValid).asUInt, VecInit(cdbrfWen).asUInt) 225 for (j <- 0 until wakeupCnt) { 226 XSDebug(srcHitVec(k)(i)(j), "WakeUpHit: Sel:%d Src:%d|%d Wake:%d data:%x valid:%d rfWen:%d roqIdx:%x\n", i.U, k.U, prfSrc(k)(i), j.U, cdbData(j), cdbValid(j), cdbrfWen(j), io.wakeUpPorts(j).bits.uop.roqIdx) 227 } 228 }) 229 } 230 231 // From byPass [speculative] (just for ALU to listen to other ALU's res, include itself) 232 // just need Tag(Ctrl). send out Tag when Tag is decided. other ALUIQ listen to them and decide Tag 233 // byPassUops is one cycle before byPassDatas 234 if (bypassCnt > 0) { 235 val bypassPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest) 236 val bypassrfWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.rfWen) 237 val bypassValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) // may only need valid not fire() 238 val bypassData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data) 239 val srcBpHitVec = List.tabulate(srcNum)(k => 240 List.tabulate(iqSize)(i => 241 List.tabulate(bypassCnt)(j => 242 (prfSrc(k)(i) === bypassPdest(j)) && (bypassValid(j) && bypassrfWen(j))))) 243 val srcBpHit = List.tabulate(srcNum)(k => 244 List.tabulate(iqSize)(i => 245 ParallelOR(srcBpHitVec(k)(i)).asBool())) 246 // VecInit(srcBpHitVec(k)(i)).asUInt.orR)) 247 val srcBpHitVecNext = List.tabulate(srcNum)(k => 248 List.tabulate(iqSize)(i => 249 List.tabulate(bypassCnt)(j => RegNext(srcBpHitVec(k)(i)(j))))) 250 val srcBpHitNext = List.tabulate(srcNum)(k => 251 List.tabulate(iqSize)(i => 252 RegNext(srcBpHit(k)(i)))) 253 val srcBpData = List.tabulate(srcNum)(k => 254 List.tabulate(iqSize)(i => 255 ParallelMux(srcBpHitVecNext(k)(i) zip bypassData))) 256 // Mux1H(srcBpHitVecNext(k)(i), bypassData))) 257 for(k <- 0 until srcNum){ 258 for(i <- 0 until iqSize){ when (valid(i)) { 259 when(valid(i) && !srcRdy(k)(i) && srcBpHit(k)(i)) { srcRdy(k)(i) := true.B } 260 when(srcBpHitNext(k)(i)) { srcData(k)(i) := srcBpData(k)(i)} 261 }} 262 } 263 264 // Enqueue Bypass 265 val enqBypass = WireInit(VecInit(false.B, false.B, false.B)) 266 val enqBypassHitVec = List(List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc1 === bypassPdest(j) && bypassValid(j) && bypassrfWen(j) && io.enqCtrl.fire()), 267 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc2 === bypassPdest(j) && bypassValid(j) && bypassrfWen(j) && io.enqCtrl.fire()), 268 List.tabulate(bypassCnt)(j => io.enqCtrl.bits.psrc3 === bypassPdest(j) && bypassValid(j) && bypassrfWen(j) && io.enqCtrl.fire())) 269 val enqBypassHitVecNext = enqBypassHitVec.map(i => i.map(j => RegNext(j))) 270 enqBypass(0) := ParallelOR(enqBypassHitVec(0)) 271 enqBypass(1) := ParallelOR(enqBypassHitVec(1)) 272 enqBypass(2) := ParallelOR(enqBypassHitVec(2)) 273 when(enqBypass(0)) { src1Rdy(enqueueSelect) := true.B } 274 when(enqBypass(1)) { src2Rdy(enqueueSelect) := true.B } 275 when(enqBypass(2)) { src3Rdy(enqueueSelect) := true.B } 276 when(RegNext(enqBypass(0))) { src1Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(0) zip bypassData)} 277 when(RegNext(enqBypass(1))) { src2Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(1) zip bypassData)} 278 when(RegNext(enqBypass(2))) { src3Data(enqSelNext) := ParallelMux(enqBypassHitVecNext(2) zip bypassData)} 279 } 280 281 } 282 283 284 //--------------------------------------------------------- 285 // Select Circuit 286 //--------------------------------------------------------- 287 val selVec = List.tabulate(iqSize){ i => 288 Wire(new CmpInputBundle).apply(instRdy(i),roqIdx(i),i.U) 289 } 290 val selResult = ParallelSel(selVec) 291 XSDebug("[Sel Result] ResReady:%d || ResultId:%d\n",selResult.instRdy,selResult.iqIdx.asUInt) 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 XSDebug("[Reg Info-Sel] selInstRdy:%d || selIdx:%d\n",selInstRdy,selInstIdx.asUInt) 345 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, 346 (io.deq.bits.uop.src1State === SrcState.rdy), io.deq.bits.uop.psrc1, 347 (io.deq.bits.uop.src2State === SrcState.rdy), io.deq.bits.uop.psrc2 348 ) 349 350 //update the index register of instruction that can be issue, unless function unit not allow in 351 //then the issue will be stopped to wait the function unit 352 //clear the validBit of dequeued instruction in issuequeue 353 when(io.deq.fire()){ 354 validReg(dequeueSelect) := false.B 355 validWillFalse(dequeueSelect) := true.B 356 } 357 358 val selRegflush = expRedirect || (brRedirect && brRedirectMaskMatch) 359 360 selInstRdy := Mux(selRegflush,false.B,selResult.instRdy) 361 selInstIdx := Mux(selRegflush,0.U,selResult.iqIdx) 362 // SelectedUop (bypass / speculative) 363 if(useBypass) { 364 assert(fixedDelay==1) // only support fixedDelay is 1 now 365 def DelayPipe[T <: Data](a: T, delay: Int = 0) = { 366 if(delay == 0) a 367 else { 368 val storage = Wire(VecInit(Seq.fill(delay+1)(a))) 369 // storage(0) := a 370 for(i <- 1 until delay) { 371 storage(i) := RegNext(storage(i-1)) 372 } 373 storage(delay) 374 } 375 } 376 val sel = io.selectedUop 377 val selIQIdx = selResult.iqIdx 378 val delayPipe = DelayPipe(VecInit(selResult.instRdy, prfDest(selIQIdx)), fixedDelay-1) 379 sel.bits := DontCare 380 sel.valid := selResult.instRdy 381 sel.bits.pdest := delayPipe(fixedDelay-1)(1) 382 } 383} 384 385class IssueQueueCpt(val fuTypeInt: BigInt, val wakeupCnt: Int, val bypassCnt: Int = 0, val fixedDelay: Int = 1) extends IQModule { 386 387 val useBypass = bypassCnt > 0 388 val src2Use = true 389 val src3Use = fuTypeInt==FuType.fmac.litValue() 390 val src2Listen = true 391 val src3Listen = fuTypeInt==FuType.fmac.litValue() 392 393 val io = IO(new Bundle() { 394 // flush Issue Queue 395 val redirect = Flipped(ValidIO(new Redirect)) 396 397 // enq Ctrl sigs at dispatch-2 398 val enqCtrl = Flipped(DecoupledIO(new MicroOp)) 399 // enq Data at next cycle (regfile has 1 cycle latency) 400 val enqData = Flipped(ValidIO(new ExuInput)) 401 402 // broadcast selected uop to other issue queues which has bypasses 403 val selectedUop = if(useBypass) ValidIO(new MicroOp) else null 404 405 // send to exu 406 val deq = DecoupledIO(new ExuInput) 407 408 // listen to write back bus 409 val wakeUpPorts = Vec(wakeupCnt, Flipped(ValidIO(new ExuOutput))) 410 411 // use bypass uops to speculative wake-up 412 val bypassUops = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new MicroOp))) else null 413 val bypassData = if(useBypass) Vec(bypassCnt, Flipped(ValidIO(new ExuOutput))) else null 414 }) 415 416 val srcAllNum = 3 417 val srcUseNum = 1 + (if(src2Use) 1 else 0) + (if(src3Use) 1 else 0)// when src2Use is false, then src3Use must be false 418 val srcListenNum = 1 + (if(src2Listen) 1 else 0) + (if(src3Listen) 1 else 0) // when src2Listen is false, then src3Listen must be false 419 // when use is false, Listen must be false 420 require(!(!src2Use && src2Listen)) 421 require(!(!src3Use && src3Listen)) 422 require(!(!src2Use && src3Use)) 423 require(!(!src2Listen && src3Listen)) 424 425 // Issue Queue 426 // val issQue = IndexableMem(iqSize, new ExuInput, mem = false, init = None) 427 val issQue = Mem(iqSize, new ExuInput) 428 // val issQue = Reg(Vec(iqSize, new ExuInput)) 429 val validQue = RegInit(VecInit(Seq.fill(iqSize)(false.B))) 430 val idQue = RegInit(VecInit((0 until iqSize).map(_.U(iqIdxWidth.W)))) 431 val idValidQue = VecInit((0 until iqSize).map(i => validQue(idQue(i)))).asUInt 432 val tailAll = RegInit(0.U((iqIdxWidth+1).W)) 433 val tail = tailAll(iqIdxWidth-1, 0) 434 val full = tailAll(iqIdxWidth) 435 436 // alias failed, turn to independent storage(Reg) 437 val psrc = VecInit(List.tabulate(iqSize)(i => VecInit(List(issQue(i.U).uop.psrc1, issQue(i.U).uop.psrc2, issQue(i.U).uop.psrc3)))) // NOTE: indexed by IssQue's idx 438 val srcRdyVec = Reg(Vec(iqSize, Vec(srcAllNum, Bool()))) // NOTE: indexed by IssQue's idx 439 val srcData = Reg(Vec(iqSize, Vec(srcAllNum, UInt(XLEN.W)))) // NOTE: indexed by IssQue's idx 440 val srcRdy = VecInit(srcRdyVec.map(a => if(src3Listen) { if(src2Listen) a(0)&&a(1)&&a(2) else a(0)&&a(2) } else { if(src2Listen) a(0)&&a(1) else a(0) }))// NOTE: indexed by IssQue's idx 441 val srcIdRdy = VecInit((0 until iqSize).map(i => srcRdy(idQue(i)))).asUInt // NOTE: indexed by IdQue's idx 442 val srcType = List.tabulate(iqSize)(i => List(issQue(i).uop.ctrl.src1Type, issQue(i).uop.ctrl.src2Type, issQue(i).uop.ctrl.src3Type)) // NOTE: indexed by IssQue's idx 443 444 // val srcDataWire = Wire(srcData) 445 val srcDataWire = Wire(Vec(iqSize, Vec(srcAllNum, UInt(XLEN.W)))) // NOTE: indexed by IssQue's idx 446 srcDataWire := srcData 447 srcData := srcDataWire 448 449 // there is three stage 450 // |-------------|--------------------|--------------| 451 // |Enq:get state|Deq: select/get data| fire stage | 452 // |-------------|--------------------|--------------| 453 454 //----------------------------------------- 455 // Enqueue 456 //----------------------------------------- 457 val enqRedHit = Wire(Bool()) 458 val enqFire = io.enqCtrl.fire() && !enqRedHit 459 val deqFire = io.deq.fire() 460 val popOne = Wire(Bool()) 461 io.enqCtrl.ready := !full || popOne 462 val enqSel = idQue(tail) 463 val enqSrcRdy = List(Mux(SrcType.isPcImm(io.enqCtrl.bits.src1State), true.B, io.enqCtrl.bits.src1State === SrcState.rdy), Mux(SrcType.isPcImm(io.enqCtrl.bits.src2State), true.B, io.enqCtrl.bits.src2State === SrcState.rdy), Mux(SrcType.isPcImm(io.enqCtrl.bits.src3State), true.B, io.enqCtrl.bits.src3State === SrcState.rdy)) 464 465 // state enq 466 when (enqFire) { 467 issQue(enqSel).uop := io.enqCtrl.bits 468 validQue(enqSel) := true.B 469 assert(!validQue(enqSel)) 470 471 srcRdyVec(enqSel)(0) := enqSrcRdy(0) 472 if(src2Listen) { srcRdyVec(enqSel)(1) := enqSrcRdy(1) } 473 if(src3Listen) { srcRdyVec(enqSel)(2) := enqSrcRdy(2) } 474 } 475 476 // data enq 477 val enqSelNext = RegEnable(enqSel, enqFire) 478 // val enqSelNext = RegNext(enqSel) 479 val enqFireNext = RegInit(false.B) 480 when (enqFireNext) { enqFireNext := false.B } 481 when (enqFire) { enqFireNext := true.B } 482 483 val enqDataVec = List(io.enqData.bits.src1, io.enqData.bits.src2, io.enqData.bits.src3) 484 when (enqFireNext) { 485 for(i <- 0 until srcUseNum) { 486 srcDataWire(enqSelNext)(i) := enqDataVec(i) 487 } 488 } 489 490 //----------------------------------------- 491 // tail 492 //----------------------------------------- 493 val tailInc = enqFire 494 val tailDec = popOne 495 val tailKeep = tailInc === tailDec 496 val tailAdd = tailAll + 1.U 497 val tailSub = tailAll - 1.U 498 tailAll := Mux(tailKeep, tailAll, Mux(tailInc, tailAdd, tailSub)) 499 assert(tailAll < 9.U) 500 // Select to Dequeue 501 val deqSel = PriorityEncoder(idValidQue & srcIdRdy) //may not need idx, just need oneHot, idx by IdQue's idx 502 val deqSelIq = idQue(deqSel) 503 val deqSelOH = PriorityEncoderOH(idValidQue & srcIdRdy) 504 val has1Rdy = ParallelOR((validQue.asUInt & srcRdy.asUInt).asBools).asBool() 505 506 //----------------------------------------- 507 // idQue Move 508 //----------------------------------------- 509 def UIntToMHP(in: UInt) = { 510 // UInt to Multi-Hot plus 1: 1.U -> "11".U; 2.U(2.W) -> "0111".U; 3.U(3.W) -> "00001111".W 511 val a = Seq.fill(in.getWidth)(2).product 512 val s = (1 << (a-1)).S 513 Reverse((s(a-1,0).asSInt >> in)(a-1,0).asUInt) 514 } 515 def UIntToMH(in: UInt) = { 516 val a = Seq.fill(in.getWidth)(2).product 517 val s = (1 << (a-1)).S 518 Reverse((s(a-1,0).asSInt >> in)(a-1,0).asUInt) ^ UIntToOH(in) 519 } 520 def PriorityDot(in: UInt) = { 521 // "1100".U -> "0111".U; "1010".U -> "0011".U; "0000".U -> "0000".U 522 val a = Array.fill(iqSize)(1) 523 for(i <- 1 until in.getWidth) { 524 a(i) = a(i-1)*2 + 1 525 } 526 Mux(in===0.U, 0.U(in.getWidth.W), PriorityMux(in, a.map(_.U(in.getWidth.W)))) 527 } 528 val tailDot = Mux(full, VecInit(Seq.fill(iqSize)(true.B)).asUInt, UIntToMHP(tail)) 529 val tailDot2 = Mux(full, VecInit(Seq.fill(iqSize)(true.B)).asUInt, UIntToMH(tail)) 530 val selDot = UIntToMHP(deqSel) // FIXIT: PriorityEncoder -> UIntToMHP means long latency 531 val nonValid = ~(idValidQue | ~tailDot2) 532 val popSel = PriorityEncoder(nonValid) // Note: idxed by IDque's index 533 val popDot = PriorityDot(nonValid) 534 val isPop = ParallelOR(nonValid.asBools).asBool() 535 val moveDot = Mux(isPop, tailDot ^ popDot, tailDot ^ selDot) 536 537 assert(!(popOne&&moveDot(0))) 538 when (popOne) { 539 for(i <- 1 until iqSize) { 540 when (moveDot(i)) { idQue(i-1) := idQue(i) } 541 } 542 val ptr_tmp = Mux(full, VecInit(Seq.fill(iqIdxWidth)(true.B)).asUInt, tail) 543 idQue(ptr_tmp) := idQue(Mux(isPop, popSel, deqSel)) 544 } 545 assert(ParallelAND(List.tabulate(iqSize)(i => ParallelOR(List.tabulate(iqSize)(j => i.U === idQue(j))))).asBool) 546 547 //----------------------------------------- 548 // Redirect 549 //----------------------------------------- 550 // redirect enq 551 enqRedHit := io.redirect.valid && (io.redirect.bits.isException || ParallelOR((UIntToOH(io.redirect.bits.brTag) & io.enqCtrl.bits.brMask).asBools).asBool) 552 553 // redirect issQue 554 val redHitVec = List.tabulate(iqSize)(i => io.redirect.valid && (io.redirect.bits.isException || ParallelOR((UIntToOH(io.redirect.bits.brTag) & issQue(i).uop.brMask).asBools).asBool)) 555 for (i <- 0 until iqSize) { 556 when (redHitVec(i) && validQue(i)) { 557 validQue(i) := false.B 558 } 559 } 560 // reditect deq(issToExu) 561 val redIdHitVec = List.tabulate(iqSize)(i => io.redirect.valid && (io.redirect.bits.isException || ParallelOR((UIntToOH(io.redirect.bits.brTag) & issQue(idQue(i)).uop.brMask).asBools).asBool)) 562 val selIsRed = ParallelOR((deqSelOH & VecInit(redIdHitVec).asUInt).asBools).asBool 563 564 //----------------------------------------- 565 // Dequeue (or to Issue Stage) 566 //----------------------------------------- 567 val issueToExu = Reg(new ExuInput) 568 val issueToExuValid = RegInit(false.B) 569 val deqCanIn = !issueToExuValid || deqFire 570 val deqFlushHit = io.redirect.valid && (io.redirect.bits.isException || 571 ParallelOR((issueToExu.uop.brMask & UIntToOH(io.redirect.bits.brTag)).asBools).asBool) 572 val toIssFire = deqCanIn && has1Rdy && !isPop && !selIsRed 573 popOne := deqCanIn && (has1Rdy || isPop) // send a empty or valid term to issueStage 574 575 when (toIssFire) { 576 issueToExu := issQue(deqSelIq) 577 issueToExuValid := true.B 578 validQue(deqSelIq) := false.B 579 assert(validQue(deqSelIq)) 580 issueToExu.src1 := srcDataWire(deqSelIq)(0) 581 if (src2Use) { issueToExu.src2 := srcDataWire(deqSelIq)(1) } else { issueToExu.src2 := DontCare } 582 if (src3Use) { issueToExu.src3 := srcDataWire(deqSelIq)(2) } else { issueToExu.src3 := DontCare } 583 } 584 when (deqFire || deqFlushHit) { 585 issueToExuValid := false.B 586 } 587 588 io.deq.valid := issueToExuValid && !deqFlushHit 589 io.deq.bits := issueToExu 590 591 //----------------------------------------- 592 // Wakeup and Bypass 593 //----------------------------------------- 594 if (wakeupCnt > 0) { 595 val cdbValid = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).valid) 596 val cdbData = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.data) 597 val cdbPdest = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.pdest) 598 val cdbrfWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.rfWen) 599 val cdbfpWen = List.tabulate(wakeupCnt)(i => io.wakeUpPorts(i).bits.uop.ctrl.fpWen) 600 601 for(i <- 0 until iqSize) { 602 for(j <- 0 until srcListenNum) { 603 val hitVec = List.tabulate(wakeupCnt)(k => psrc(i)(j) === cdbPdest(k) && cdbValid(k) && (srcType(i)(j)===SrcType.reg && cdbrfWen(k) || srcType(i)(j)===SrcType.fp && cdbfpWen(k))) 604 val hit = ParallelOR(hitVec).asBool 605 val data = ParallelMux(hitVec zip cdbData) 606 when (validQue(i) && !srcRdyVec(i)(j) && hit) { 607 srcDataWire(i)(j) := data 608 srcRdyVec(i)(j) := true.B 609 } 610 // XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "WakeUp: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b Data:%x\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt, data) 611 for (k <- 0 until wakeupCnt) { 612 XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k), "WakeUpHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, cdbData(k), io.wakeUpPorts(k).bits.uop.cf.pc, io.wakeUpPorts(k).bits.uop.roqIdx) 613 } 614 } 615 } 616 } 617 if (useBypass) { 618 val bpPdest = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.pdest) 619 val bpValid = List.tabulate(bypassCnt)(i => io.bypassUops(i).valid) 620 val bpData = List.tabulate(bypassCnt)(i => io.bypassData(i).bits.data) 621 val bprfWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.rfWen) 622 val bpfpWen = List.tabulate(bypassCnt)(i => io.bypassUops(i).bits.ctrl.fpWen) 623 624 for (i <- 0 until iqSize) { 625 for (j <- 0 until srcListenNum) { 626 val hitVec = List.tabulate(bypassCnt)(k => psrc(i)(j) === bpPdest(k) && bpValid(k) && (srcType(i)(j)===SrcType.reg && bprfWen(k) || srcType(i)(j)===SrcType.fp && bpfpWen(k))) 627 val hitVecNext = hitVec.map(RegNext(_)) 628 val hit = ParallelOR(hitVec).asBool 629 when (validQue(i) && !srcRdyVec(i)(j) && hit) { 630 srcRdyVec(i)(j) := true.B // FIXME: if uncomment the up comment, will cause combiantional loop, but it is Mem type?? 631 } 632 when (RegNext(validQue(i) && !srcRdyVec(i)(j) && hit)) { 633 srcDataWire(i)(j) := PriorityMux(hitVecNext zip bpData) 634 } 635 // XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit, "BypassCtrl: Sel:%d Src:(%d|%d) Rdy:%d Hit:%d HitVec:%b\n", i.U, j.U, psrc(i)(j), srcRdyVec(i)(j), hit, VecInit(hitVec).asUInt) 636 for (k <- 0 until bypassCnt) { 637 XSDebug(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k), "BypassCtrlHit: IQIdx:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx) 638 } 639 // XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit), "BypassData: Sel:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", i.U, j.U, psrc(i)(j), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData)) 640 for (k <- 0 until bypassCnt) { 641 XSDebug(RegNext(validQue(i) && !srcRdyVec(i)(j) && hit && hitVec(k)), "BypassDataHit: IQIdx:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", i.U, j.U, psrc(i)(j), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx) 642 } 643 } 644 } 645 646 // Enqueue Bypass 647 val enqCtrl = io.enqCtrl 648 val enqPsrc = List(enqCtrl.bits.psrc1, enqCtrl.bits.psrc2, enqCtrl.bits.psrc3) 649 val enqSrcType = List(enqCtrl.bits.ctrl.src1Type, enqCtrl.bits.ctrl.src2Type, enqCtrl.bits.ctrl.src3Type) 650 for (i <- 0 until srcListenNum) { 651 val hitVec = List.tabulate(bypassCnt)(j => enqPsrc(i)===bpPdest(j) && bpValid(j) && (enqSrcType(i)===SrcType.reg && bprfWen(j) || enqSrcType(i)===SrcType.fp && bpfpWen(j))) 652 val hitVecNext = hitVec.map(RegNext(_)) 653 val hit = ParallelOR(hitVec).asBool 654 when (enqFire && hit && !enqSrcRdy(i)) { 655 srcRdyVec(enqSel)(i) := true.B 656 } 657 when (RegNext(enqFire && hit && !enqSrcRdy(i))) { 658 srcDataWire(enqSelNext)(i) := ParallelMux(hitVecNext zip bpData) 659 } 660 // XSDebug(enqFire && hit, "EnqBypassCtrl: enqSel:%d Src:(%d|%d) Hit:%d HitVec:%b \n", enqSel, i.U, enqPsrc(i), hit, VecInit(hitVec).asUInt) 661 for (k <- 0 until bypassCnt) { 662 XSDebug(enqFire && hit && !enqSrcRdy(i) && hitVec(k), "EnqBypassCtrlHit: enqSel:%d Src%d:%d Ports:%d Pc:%x RoqIdx:%x\n", enqSel, i.U, enqPsrc(i), k.U, io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx) 663 } 664 // XSDebug(RegNext(enqFire && hit), "EnqBypassData: enqSelNext:%d Src:(%d|%d) HitVecNext:%b Data:%x (for last cycle's Ctrl)\n", enqSelNext, i.U, enqPsrc(i), VecInit(hitVecNext).asUInt, ParallelMux(hitVecNext zip bpData)) 665 for (k <- 0 until bypassCnt) { 666 XSDebug(RegNext(enqFire && hit && !enqSrcRdy(i) && hitVec(k)), "EnqBypassDataHit: enqSel:%d Src%d:%d Ports:%d Data:%x Pc:%x RoqIdx:%x\n", enqSel, i.U, enqPsrc(i), k.U, bpData(k), io.bypassUops(k).bits.cf.pc, io.bypassUops(k).bits.roqIdx) 667 } 668 } 669 670 // send out bypass 671 assert(fixedDelay==1) // only support fixedDelay is 1 now 672 val sel = io.selectedUop 673 sel.valid := toIssFire 674 sel.bits := DontCare 675 sel.bits.pdest := issQue(deqSelIq).uop.pdest 676 sel.bits.cf.pc := issQue(deqSelIq).uop.cf.pc 677 sel.bits.roqIdx := issQue(deqSelIq).uop.roqIdx 678 sel.bits.ctrl.rfWen := issQue(deqSelIq).uop.ctrl.rfWen 679 sel.bits.ctrl.fpWen := issQue(deqSelIq).uop.ctrl.fpWen 680 } 681 XSInfo(io.redirect.valid, "Redirect: valid:%d isExp:%d brTag:%d redHitVec:%b redIdHitVec:%b enqHit:%d selIsRed:%d\n", io.redirect.valid, io.redirect.bits.isException, io.redirect.bits.brTag, VecInit(redHitVec).asUInt, VecInit(redIdHitVec).asUInt, enqRedHit, selIsRed) 682 XSInfo(enqFire, "EnqCtrl(%d %d) enqSel:%d Psrc/Rdy(%d:%d %d:%d %d:%d) Dest:%d oldDest:%d pc:%x roqIdx:%x\n", io.enqCtrl.valid, io.enqCtrl.ready, enqSel 683 , io.enqCtrl.bits.psrc1, io.enqCtrl.bits.src1State, io.enqCtrl.bits.psrc2, io.enqCtrl.bits.src2State, io.enqCtrl.bits.psrc3, io.enqCtrl.bits.src3State, io.enqCtrl.bits.pdest, io.enqCtrl.bits.old_pdest, io.enqCtrl.bits.cf.pc, io.enqCtrl.bits.roqIdx) 684 XSInfo(enqFireNext, "EnqData: src1:%x src2:%x src3:%x pc:%x roqIdx:%x(for last cycle's Ctrl)\n", io.enqData.bits.src1, io.enqData.bits.src2, io.enqData.bits.src3, issQue(enqSelNext).uop.cf.pc, issQue(enqSelNext).uop.roqIdx) 685 XSInfo(deqFire, "Deq:(%d %d) [%d|%x][%d|%x][%d|%x] pdest:%d pc:%x roqIdx:%x\n", io.deq.valid, io.deq.ready, io.deq.bits.uop.psrc1, io.deq.bits.src1, io.deq.bits.uop.psrc2, io.deq.bits.src2, io.deq.bits.uop.psrc3, io.deq.bits.src3, io.deq.bits.uop.pdest, io.deq.bits.uop.cf.pc, io.deq.bits.uop.roqIdx) 686 XSDebug("tailAll:%d KID(%d%d%d) tailDot:%b tailDot2:%b selDot:%b popDot:%b moveDot:%b\n", tailAll, tailKeep, tailInc, tailDec, tailDot, tailDot2, selDot, popDot, moveDot) 687 if(useBypass) { 688 XSDebug("popOne:%d isPop:%d popSel:%d deqSel:%d deqCanIn:%d toIssFire:%d has1Rdy:%d selIsRed:%d nonValid:%b SelUop:(%d, %d)\n", popOne, isPop, popSel, deqSel, deqCanIn, toIssFire, has1Rdy, selIsRed, nonValid, io.selectedUop.valid, io.selectedUop.bits.pdest) 689 } else { 690 XSDebug("popOne:%d isPop:%d popSel:%d deqSel:%d deqCanIn:%d toIssFire:%d has1Rdy:%d selIsRed:%d nonValid:%b\n", popOne, isPop, popSel, deqSel, deqCanIn, toIssFire, has1Rdy, selIsRed, nonValid) 691 } 692 XSDebug("id|v|r|psrc|r| src1 |psrc|r| src2 |psrc|r| src3 |brMask| pc |roqIdx FuType:%x\n", fuTypeInt.U) 693 for (i <- 0 until iqSize) { 694 when (i.U===tail && tailAll=/=8.U) { 695 XSDebug("%d |%d|%d| %d|%b|%x| %d|%b|%x| %d|%b|%x| %x |%x|%x <-\n", idQue(i), idValidQue(i), srcRdy(idQue(i)), psrc(idQue(i))(0), srcRdyVec(idQue(i))(0), srcData(idQue(i))(0), psrc(idQue(i))(1), srcRdyVec(idQue(i))(1), srcData(idQue(i))(1), psrc(idQue(i))(2), srcRdyVec(idQue(i))(2), srcData(idQue(i))(2), issQue(idQue(i)).uop.brMask, issQue(idQue(i)).uop.cf.pc, issQue(idQue(i)).uop.roqIdx) 696 }.otherwise { 697 XSDebug("%d |%d|%d| %d|%b|%x| %d|%b|%x| %d|%b|%x| %x |%x|%x\n", idQue(i), idValidQue(i), srcRdy(idQue(i)), psrc(idQue(i))(0), srcRdyVec(idQue(i))(0), srcData(idQue(i))(0), psrc(idQue(i))(1), srcRdyVec(idQue(i))(1), srcData(idQue(i))(1), psrc(idQue(i))(2), srcRdyVec(idQue(i))(2), srcData(idQue(i))(2), issQue(idQue(i)).uop.brMask, issQue(idQue(i)).uop.cf.pc, issQue(idQue(i)).uop.roqIdx) 698 } 699 } 700 XSDebug("IQIdx| src1Wire | src2Wire | src3Wire | This Debug Info should be removed later\n") 701 for (i <- 0 until iqSize) { 702 XSDebug("%d |%x|%x|%x|\n",i.U, srcDataWire(i)(0), srcDataWire(i)(1), srcDataWire(i)(2)) 703 } 704}