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