1package xiangshan.backend.issue 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility.HasCircularQueuePtrHelper 7import utils.{MathUtils, OptionWrapper} 8import xiangshan._ 9import xiangshan.backend.Bundles._ 10import xiangshan.backend.fu.FuType 11import xiangshan.backend.datapath.DataSource 12import xiangshan.backend.rob.RobPtr 13import xiangshan.mem.{MemWaitUpdateReq, SqPtr, LqPtr} 14 15 16class EnqEntryIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 17 //input 18 val enq = Flipped(ValidIO(new EntryBundle)) 19 val flush = Flipped(ValidIO(new Redirect)) 20 val wakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle) 21 val wakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle) 22 val og0Cancel = Input(ExuOH(backendParams.numExu)) 23 val og1Cancel = Input(ExuOH(backendParams.numExu)) 24 val ldCancel = Vec(backendParams.LduCnt + backendParams.HyuCnt, Flipped(new LoadCancelIO)) 25 val deqSel = Input(Bool()) 26 val deqPortIdxWrite = Input(UInt(1.W)) 27 val transSel = Input(Bool()) 28 val issueResp = Flipped(ValidIO(new EntryDeqRespBundle)) 29 //output 30 val valid = Output(Bool()) 31 val canIssue = Output(Bool()) 32 val clear = Output(Bool()) 33 val fuType = Output(FuType()) 34 val dataSource = Output(Vec(params.numRegSrc, DataSource())) 35 val srcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, ExuOH()))) 36 val srcTimer = OptionWrapper(params.hasIQWakeUp, Output(Vec(params.numRegSrc, UInt(3.W)))) 37 val transEntry = ValidIO(new EntryBundle) 38 val isFirstIssue = Output(Bool()) 39 val entry = ValidIO(new EntryBundle) 40 val robIdx = Output(new RobPtr) 41 val uopIdx = OptionWrapper(params.isVecMemIQ, Output(UopIdx())) 42 val deqPortIdxRead = Output(UInt(1.W)) 43 val issueTimerRead = Output(UInt(2.W)) 44 // mem only 45 val fromMem = if(params.isMemAddrIQ) Some(new Bundle { 46 val stIssuePtr = Input(new SqPtr) 47 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 48 }) else None 49 // vector mem only 50 val fromLsq = OptionWrapper(params.isVecMemIQ, new Bundle { 51 val sqDeqPtr = Input(new SqPtr) 52 val lqDeqPtr = Input(new LqPtr) 53 }) 54 // debug 55 val cancel = OptionWrapper(params.hasIQWakeUp, Output(Bool())) 56 57 def wakeup = wakeUpFromWB ++ wakeUpFromIQ 58} 59 60class EnqEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 61 val io = IO(new EnqEntryIO) 62 63 val validReg = RegInit(false.B) 64 val entryReg = Reg(new EntryBundle) 65 66 val validRegNext = Wire(Bool()) 67 val entryRegNext = Wire(new EntryBundle) 68 val entryUpdate = Wire(new EntryBundle) 69 val enqReady = Wire(Bool()) 70 val clear = Wire(Bool()) 71 val flushed = Wire(Bool()) 72 val deqSuccess = Wire(Bool()) 73 val srcWakeUp = Wire(Vec(params.numRegSrc, Bool())) 74 val srcCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool()))) 75 val srcLoadCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool()))) 76 val srcWakeUpByIQVec = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool()))) 77 val wakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W)))) 78 val shiftedWakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W)))) 79 val cancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool()))) 80 81 //Reg 82 validReg := validRegNext 83 entryReg := entryRegNext 84 85 //Wire 86 when(io.enq.valid && enqReady) { 87 validRegNext := true.B 88 }.elsewhen(clear) { 89 validRegNext := false.B 90 }.otherwise { 91 validRegNext := validReg 92 } 93 94 when(io.enq.valid && enqReady) { 95 entryRegNext := io.enq.bits 96 }.otherwise { 97 entryRegNext := entryUpdate 98 } 99 100 enqReady := !validReg || clear 101 clear := flushed || io.transSel || deqSuccess 102 flushed := entryReg.status.robIdx.needFlush(io.flush) 103 deqSuccess := io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.fuIdle && !srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B) 104 srcWakeUp := io.wakeup.map(bundle => bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)).transpose.map(x => VecInit(x.toSeq).asUInt.orR).toSeq 105 106 shiftedWakeupLoadDependencyByIQVec 107 .zip(wakeupLoadDependencyByIQVec) 108 .zip(params.wakeUpInExuSources.map(_.name)).foreach { 109 case ((deps, originalDeps), name) => deps.zip(originalDeps).zipWithIndex.foreach { 110 case ((dep, originalDep), deqPortIdx) => 111 if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx) 112 dep := (originalDep << 1).asUInt | 1.U 113 else 114 dep := originalDep << 1 115 } 116 } 117 118 if (params.hasIQWakeUp) { 119 srcCancelVec.get.zip(srcLoadCancelVec.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach { case (((srcCancel, srcLoadCancel), wakeUpByIQVec), srcIdx) => 120 // level1 cancel: A(s)->C, A(s) are the level1 cancel 121 val l1Cancel = (io.og0Cancel.asUInt & entryReg.status.srcWakeUpL1ExuOH.get(srcIdx).asUInt).orR && 122 entryReg.status.srcTimer.get(srcIdx) === 1.U 123 val ldTransCancel = Mux( 124 wakeUpByIQVec.asUInt.orR, 125 Mux1H(wakeUpByIQVec, wakeupLoadDependencyByIQVec.map(dep => LoadShouldCancel(Some(dep), io.ldCancel))), 126 false.B 127 ) 128 srcLoadCancel := LoadShouldCancel(entryReg.status.srcLoadDependency.map(_(srcIdx)), io.ldCancel) 129 srcCancel := l1Cancel || srcLoadCancel || ldTransCancel 130 } 131 } 132 133 if (io.wakeUpFromIQ.isEmpty) { 134 srcWakeUpByIQVec := 0.U.asTypeOf(srcWakeUpByIQVec) 135 wakeupLoadDependencyByIQVec := 0.U.asTypeOf(wakeupLoadDependencyByIQVec) 136 } else { 137 val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.wakeUpFromIQ.map((bundle: ValidIO[IssueQueueIQWakeUpBundle]) => 138 bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid) 139 ).toIndexedSeq.transpose 140 srcWakeUpByIQVec := wakeupVec.map(x => VecInit(x)) 141 wakeupLoadDependencyByIQVec := io.wakeUpFromIQ.map(_.bits.loadDependency).toSeq 142 } 143 144 //entryUpdate 145 entryUpdate.status.srcState.zip(entryReg.status.srcState).zip(srcWakeUp).zipWithIndex.foreach { case (((stateNext, state), wakeup), srcIdx) => 146 val cancel = srcCancelVec.map(_ (srcIdx)).getOrElse(false.B) 147 stateNext := Mux(cancel, false.B, wakeup | state) 148 if (params.hasIQWakeUp) { 149 cancelVec.get(srcIdx) := cancel 150 } 151 } 152 entryUpdate.status.dataSources.zip(entryReg.status.dataSources).zip(srcWakeUpByIQVec).foreach { 153 case ((dataSourceNext: DataSource, dataSource: DataSource), wakeUpByIQOH: Vec[Bool]) => 154 when(wakeUpByIQOH.asUInt.orR) { 155 dataSourceNext.value := DataSource.forward 156 }.elsewhen(dataSource.value === DataSource.forward) { 157 dataSourceNext.value := DataSource.bypass 158 }.otherwise { 159 dataSourceNext.value := DataSource.reg 160 } 161 } 162 if (params.hasIQWakeUp) { 163 entryUpdate.status.srcWakeUpL1ExuOH.get.zip(srcWakeUpByIQVec).zip(srcWakeUp).zipWithIndex.foreach { 164 case (((exuOH: UInt, wakeUpByIQOH: Vec[Bool]), wakeUp: Bool), srcIdx) => 165 when(wakeUpByIQOH.asUInt.orR) { 166 exuOH := Mux1H(wakeUpByIQOH, io.wakeUpFromIQ.toSeq.map(x => MathUtils.IntToOH(x.bits.exuIdx).U(backendParams.numExu.W))) 167 }.elsewhen(wakeUp) { 168 exuOH := 0.U.asTypeOf(exuOH) 169 }.otherwise { 170 exuOH := entryReg.status.srcWakeUpL1ExuOH.get(srcIdx) 171 } 172 } 173 entryUpdate.status.srcTimer.get.zip(entryReg.status.srcTimer.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach { 174 case (((srcIssuedTimerNext, srcIssuedTimer), wakeUpByIQOH: Vec[Bool]), srcIdx) => 175 srcIssuedTimerNext := MuxCase(0.U, Seq( 176 // T0: waked up by IQ, T1: reset timer as 1 177 wakeUpByIQOH.asUInt.orR -> 1.U, 178 // do not overflow 179 srcIssuedTimer.andR -> srcIssuedTimer, 180 // T2+: increase if the entry is valid, the src is ready, and the src is woken up by iq 181 (validReg && SrcState.isReady(entryReg.status.srcState(srcIdx)) && entryReg.status.srcWakeUpL1ExuOH.get.asUInt.orR) -> (srcIssuedTimer + 1.U) 182 )) 183 } 184 entryUpdate.status.srcLoadDependency.get.zip(entryReg.status.srcLoadDependency.get).zip(srcWakeUpByIQVec).zip(srcWakeUp).foreach { 185 case (((loadDependencyNext, loadDependency), wakeUpByIQVec), wakeup) => 186 loadDependencyNext := 187 Mux(wakeup, 188 Mux(wakeUpByIQVec.asUInt.orR, Mux1H(wakeUpByIQVec, shiftedWakeupLoadDependencyByIQVec), 0.U.asTypeOf(loadDependency)), 189 Mux(validReg && loadDependency.asUInt.orR, VecInit(loadDependency.map(i => i(i.getWidth - 2, 0) << 1)), loadDependency) 190 ) 191 } 192 } 193 entryUpdate.status.issueTimer := "b11".U //otherwise 194 entryUpdate.status.deqPortIdx := 0.U //otherwise 195 when(io.deqSel) { 196 entryUpdate.status.issueTimer := 1.U 197 entryUpdate.status.deqPortIdx := io.deqPortIdxWrite 198 }.elsewhen(entryReg.status.issued){ 199 entryUpdate.status.issueTimer := entryReg.status.issueTimer + 1.U 200 entryUpdate.status.deqPortIdx := entryReg.status.deqPortIdx 201 } 202 entryUpdate.status.psrc := entryReg.status.psrc 203 entryUpdate.status.srcType := entryReg.status.srcType 204 entryUpdate.status.fuType := entryReg.status.fuType 205 entryUpdate.status.robIdx := entryReg.status.robIdx 206 entryUpdate.status.uopIdx.foreach(_ := entryReg.status.uopIdx.get) 207 entryUpdate.status.issued := entryReg.status.issued // otherwise 208 when(!entryReg.status.srcReady){ 209 entryUpdate.status.issued := false.B 210 }.elsewhen(srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B)) { 211 entryUpdate.status.issued := false.B 212 }.elsewhen(io.issueResp.valid) { 213 when(RSFeedbackType.isStageSuccess(io.issueResp.bits.respType)) { 214 entryUpdate.status.issued := true.B 215 }.elsewhen(RSFeedbackType.isBlocked(io.issueResp.bits.respType)) { 216 entryUpdate.status.issued := false.B 217 } 218 } 219 entryUpdate.status.firstIssue := io.deqSel || entryReg.status.firstIssue 220 entryUpdate.status.blocked := false.B //todo 221 //remain imm and payload 222 entryUpdate.imm := entryReg.imm 223 entryUpdate.payload := entryReg.payload 224 if(params.needPc) { 225 entryUpdate.status.pc.get := entryReg.status.pc.get 226 } 227 228 //output 229 io.transEntry.valid := validReg && io.transSel && !flushed && !deqSuccess 230 io.transEntry.bits := entryUpdate 231 io.canIssue := entryReg.status.canIssue && validReg 232 io.clear := clear 233 io.fuType := entryReg.status.fuType 234 io.dataSource := entryReg.status.dataSources 235 io.srcWakeUpL1ExuOH.foreach(_ := entryReg.status.srcWakeUpL1ExuOH.get) 236 io.srcTimer.foreach(_ := entryReg.status.srcTimer.get) 237 io.valid := validReg 238 io.isFirstIssue := !entryReg.status.firstIssue 239 io.entry.valid := validReg 240 io.entry.bits := entryReg 241 io.robIdx := entryReg.status.robIdx 242 io.uopIdx.foreach(_ := entryReg.status.uopIdx.get) 243 io.issueTimerRead := Mux(io.deqSel, 0.U, entryReg.status.issueTimer) 244 io.deqPortIdxRead := Mux(io.deqSel, io.deqPortIdxWrite, entryReg.status.deqPortIdx) 245 io.cancel.foreach(_ := cancelVec.get.asUInt.orR) 246} 247 248class EnqEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry 249 with HasCircularQueuePtrHelper { 250 val fromMem = io.fromMem.get 251 252 val memStatus = entryReg.status.mem.get 253 println("memStatus" + memStatus) 254 val memStatusNext = entryRegNext.status.mem.get 255 val memStatusUpdate = entryUpdate.status.mem.get 256 257 // load cannot be issued before older store, unless meet some condition 258 val blockedByOlderStore = isAfter(memStatusNext.sqIdx, fromMem.stIssuePtr) 259 260 val deqFailedForStdInvalid = io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.dataInvalid 261 262 val staWaitedReleased = Cat( 263 fromMem.memWaitUpdateReq.robIdx.map(x => x.valid && x.bits.value === memStatusNext.waitForRobIdx.value) 264 ).orR 265 val stdWaitedReleased = Cat( 266 fromMem.memWaitUpdateReq.sqIdx.map(x => x.valid && x.bits.value === memStatusNext.waitForSqIdx.value) 267 ).orR 268 val olderStaNotViolate = staWaitedReleased && !memStatusNext.strictWait 269 val olderStdReady = stdWaitedReleased && memStatusNext.waitForStd 270 val waitStd = !olderStdReady 271 val waitSta = !olderStaNotViolate 272 273 when (io.enq.valid && enqReady) { 274 memStatusNext.waitForSqIdx := io.enq.bits.status.mem.get.waitForSqIdx 275 // update by lfst at dispatch stage 276 memStatusNext.waitForRobIdx := io.enq.bits.status.mem.get.waitForRobIdx 277 // new load inst don't known if it is blocked by store data ahead of it 278 memStatusNext.waitForStd := false.B 279 // update by ssit at rename stage 280 memStatusNext.strictWait := io.enq.bits.status.mem.get.strictWait 281 memStatusNext.sqIdx := io.enq.bits.status.mem.get.sqIdx 282 }.otherwise { 283 memStatusNext := memStatusUpdate 284 } 285 286 when(deqFailedForStdInvalid) { 287 memStatusUpdate.waitForSqIdx := io.issueResp.bits.dataInvalidSqIdx 288 memStatusUpdate.waitForRobIdx := memStatus.waitForRobIdx 289 memStatusUpdate.waitForStd := true.B 290 memStatusUpdate.strictWait := memStatus.strictWait 291 memStatusUpdate.sqIdx := memStatus.sqIdx 292 }.otherwise { 293 memStatusUpdate := memStatus 294 } 295 296 val shouldBlock = Mux(io.enq.valid && enqReady, io.enq.bits.status.blocked, entryReg.status.blocked) 297 val blockNotReleased = waitStd || waitSta 298 val respBlock = deqFailedForStdInvalid 299 entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock 300 entryUpdate.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock 301 302} 303 304class EnqEntryVecMemAddr()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntryMem { 305 306 require(params.isVecMemAddrIQ, "EnqEntryVecMemAddr can only be instance of VecMemAddr IQ") 307 308 val vecMemStatus = entryReg.status.vecMem.get 309 val vecMemStatusNext = entryRegNext.status.vecMem.get 310 val vecMemStatusUpdate = entryUpdate.status.vecMem.get 311 val fromLsq = io.fromLsq.get 312 313 when (io.enq.valid && enqReady) { 314 vecMemStatusNext.sqIdx := io.enq.bits.status.vecMem.get.sqIdx 315 vecMemStatusNext.lqIdx := io.enq.bits.status.vecMem.get.lqIdx 316 }.otherwise { 317 vecMemStatusNext := vecMemStatusUpdate 318 } 319 vecMemStatusUpdate := vecMemStatus 320 321 val isLsqHead = { 322 // if (params.isVecLdAddrIQ) 323 entryRegNext.status.vecMem.get.lqIdx <= fromLsq.lqDeqPtr && 324 // else 325 entryRegNext.status.vecMem.get.sqIdx <= fromLsq.sqDeqPtr 326 } 327 328 entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock || !isLsqHead 329 entryUpdate.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock || !isLsqHead 330} 331 332class EnqEntryVecMemData()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry 333 with HasCircularQueuePtrHelper { 334 335 require(params.isVecStDataIQ, "EnqEntryVecMemData can only be instance of VecMemData IQ") 336 337 val vecMemStatus = entryReg.status.vecMem.get 338 val vecMemStatusNext = entryRegNext.status.vecMem.get 339 val vecMemStatusUpdate = entryUpdate.status.vecMem.get 340 val fromLsq = io.fromLsq.get 341 342 when (io.enq.valid && enqReady) { 343 vecMemStatusNext.sqIdx := io.enq.bits.status.vecMem.get.sqIdx 344 vecMemStatusNext.lqIdx := io.enq.bits.status.vecMem.get.lqIdx 345 }.otherwise { 346 vecMemStatusNext := vecMemStatusUpdate 347 } 348 vecMemStatusUpdate := vecMemStatus 349 350 val isLsqHead = entryRegNext.status.vecMem.get.sqIdx.value === fromLsq.sqDeqPtr.value 351 352 entryRegNext.status.blocked := !isLsqHead 353 entryUpdate.status.blocked := !isLsqHead 354} 355 356object EnqEntry { 357 def apply(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = { 358 iqParams.schdType match { 359 case IntScheduler() => new EnqEntry() 360 case MemScheduler() => 361 if (iqParams.isLdAddrIQ || iqParams.isStAddrIQ || iqParams.isHyAddrIQ) new EnqEntryMem() 362 else if (iqParams.isVecMemAddrIQ) new EnqEntryVecMemAddr() 363 else if (iqParams.isVecStDataIQ) new EnqEntryVecMemData() 364 else new EnqEntry() 365 case VfScheduler() => new EnqEntry() 366 case _ => null 367 } 368 } 369}