1package xiangshan.backend.issue 2 3import chipsalliance.rocketchip.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} 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(ExuVec(backendParams.numExu)) 23 val og1Cancel = Input(ExuVec(backendParams.numExu)) 24 val ldCancel = Vec(backendParams.LduCnt, 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, ExuVec()))) 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 deqPortIdxRead = Output(UInt(1.W)) 41 val issueTimerRead = Output(UInt(2.W)) 42 // mem only 43 val fromMem = if(params.isMemAddrIQ) Some(new Bundle { 44 val stIssuePtr = Input(new SqPtr) 45 val memWaitUpdateReq = Flipped(new MemWaitUpdateReq) 46 }) else None 47 48 def wakeup = wakeUpFromWB ++ wakeUpFromIQ 49} 50 51class OthersEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 52 val io = IO(new OthersEntryIO) 53 54 val validReg = RegInit(false.B) 55 val entryReg = Reg(new EntryBundle) 56 57 val validRegNext = Wire(Bool()) 58 val entryRegNext = Wire(new EntryBundle) 59 val flushed = Wire(Bool()) 60 val clear = Wire(Bool()) 61 val deqSuccess = Wire(Bool()) 62 val srcWakeUp = Wire(Vec(params.numRegSrc, Bool())) 63 val srcCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool()))) 64 val srcLoadCancelVec = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Bool()))) 65 val srcWakeUpByIQVec = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool()))) 66 val wakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W)))) 67 val shiftedWakeupLoadDependencyByIQVec = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W)))) 68 69 //Reg 70 validReg := validRegNext 71 entryReg := entryRegNext 72 73 //Wire 74 flushed := entryReg.status.robIdx.needFlush(io.flush) 75 clear := flushed || deqSuccess 76 deqSuccess := io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.fuIdle && !srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B) 77 srcWakeUp := io.wakeup.map(bundle => bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid)).transpose.map(VecInit(_).asUInt.orR) 78 79 shiftedWakeupLoadDependencyByIQVec 80 .zip(wakeupLoadDependencyByIQVec) 81 .zip(params.wakeUpInExuSources.map(_.name)).foreach { 82 case ((deps, originalDeps), name) => deps.zip(originalDeps).zipWithIndex.foreach { 83 case ((dep, originalDep), deqPortIdx) => 84 if (name.contains("LDU") && name.replace("LDU", "").toInt == deqPortIdx) 85 dep := originalDep << 1 | 1.U 86 else 87 dep := originalDep << 1 88 } 89 } 90 91 when(io.enq.valid && io.transSel) { 92 validRegNext := true.B 93 }.elsewhen(clear) { 94 validRegNext := false.B 95 }.otherwise { 96 validRegNext := validReg 97 } 98 99 if (params.hasIQWakeUp) { 100 srcCancelVec.get.zip(srcLoadCancelVec.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach { case (((srcCancel, srcLoadCancel), wakeUpByIQVec), srcIdx) => 101 // level1 cancel: A(s)->C, A(s) are the level1 cancel 102 val l1Cancel = (io.og0Cancel.asUInt & entryReg.status.srcWakeUpL1ExuOH.get(srcIdx).asUInt).orR && 103 entryReg.status.srcTimer.get(srcIdx) === 1.U 104 val ldTransCancel = Mux( 105 wakeUpByIQVec.asUInt.orR, 106 Mux1H(wakeUpByIQVec, wakeupLoadDependencyByIQVec.map(dep => LoadShouldCancel(Some(dep), io.ldCancel))), 107 false.B 108 ) 109 srcLoadCancel := LoadShouldCancel(entryReg.status.srcLoadDependency.map(_(srcIdx)), io.ldCancel) 110 srcCancel := l1Cancel || srcLoadCancel || ldTransCancel 111 } 112 } 113 114 if (io.wakeUpFromIQ.isEmpty) { 115 srcWakeUpByIQVec := 0.U.asTypeOf(srcWakeUpByIQVec) 116 wakeupLoadDependencyByIQVec := 0.U.asTypeOf(wakeupLoadDependencyByIQVec) 117 } else { 118 val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.wakeUpFromIQ.map((bundle: ValidIO[IssueQueueIQWakeUpBundle]) => 119 bundle.bits.wakeUp(entryReg.status.psrc zip entryReg.status.srcType, bundle.valid) 120 ).transpose 121 srcWakeUpByIQVec := wakeupVec.map(x => VecInit(x)) 122 wakeupLoadDependencyByIQVec := io.wakeUpFromIQ.map(_.bits.loadDependency) 123 } 124 125 when(io.enq.valid && io.transSel) { 126 entryRegNext := io.enq.bits 127 }.otherwise { 128 //update status 129 entryRegNext.status.srcState.zip(entryReg.status.srcState).zip(srcWakeUp).zipWithIndex.foreach { case (((stateNext, state), wakeup), srcIdx) => 130 val cancel = srcCancelVec.map(_ (srcIdx)).getOrElse(false.B) 131 stateNext := Mux(cancel, false.B, wakeup | state) 132 } 133 entryRegNext.status.dataSources.zip(entryReg.status.dataSources).zip(srcWakeUpByIQVec).foreach { 134 case ((dataSourceNext: DataSource, dataSource: DataSource), wakeUpByIQOH: Vec[Bool]) => 135 when(wakeUpByIQOH.asUInt.orR) { 136 dataSourceNext.value := DataSource.forward 137 }.elsewhen(dataSource.value === DataSource.forward) { 138 dataSourceNext.value := DataSource.bypass 139 }.otherwise { 140 dataSourceNext.value := DataSource.reg 141 } 142 } 143 if (params.hasIQWakeUp) { 144 entryRegNext.status.srcWakeUpL1ExuOH.get.zip(srcWakeUpByIQVec).zip(srcWakeUp).zipWithIndex.foreach { 145 case (((exuOH: Vec[Bool], wakeUpByIQOH: Vec[Bool]), wakeUp: Bool), srcIdx) => 146 when(wakeUpByIQOH.asUInt.orR) { 147 exuOH := Mux1H(wakeUpByIQOH, io.wakeUpFromIQ.map(x => MathUtils.IntToOH(x.bits.exuIdx).U(backendParams.numExu.W))).asBools 148 }.elsewhen(wakeUp) { 149 exuOH := 0.U.asTypeOf(exuOH) 150 }.otherwise { 151 exuOH := entryReg.status.srcWakeUpL1ExuOH.get(srcIdx) 152 } 153 } 154 entryRegNext.status.srcTimer.get.zip(entryReg.status.srcTimer.get).zip(srcWakeUpByIQVec).zipWithIndex.foreach { 155 case (((srcIssuedTimerNext, srcIssuedTimer), wakeUpByIQOH: Vec[Bool]), srcIdx) => 156 srcIssuedTimerNext := MuxCase(0.U, Seq( 157 // T0: waked up by IQ, T1: reset timer as 1 158 wakeUpByIQOH.asUInt.orR -> 1.U, 159 // do not overflow 160 srcIssuedTimer.andR -> srcIssuedTimer, 161 // T2+: increase if the entry is valid, the src is ready, and the src is woken up by iq 162 (validReg && SrcState.isReady(entryReg.status.srcState(srcIdx)) && entryReg.status.srcWakeUpL1ExuOH.get.asUInt.orR) -> (srcIssuedTimer + 1.U) 163 )) 164 } 165 entryRegNext.status.srcLoadDependency.get.zip(entryReg.status.srcLoadDependency.get).zip(srcWakeUpByIQVec).zip(srcWakeUp).foreach { 166 case (((loadDependencyNext, loadDependency), wakeUpByIQVec), wakeup) => 167 loadDependencyNext := 168 Mux(wakeup, 169 Mux(wakeUpByIQVec.asUInt.orR, Mux1H(wakeUpByIQVec, shiftedWakeupLoadDependencyByIQVec), 0.U.asTypeOf(loadDependency)), 170 Mux(validReg && loadDependency.asUInt.orR, VecInit(loadDependency.map(i => i(i.getWidth - 2, 0) << 1)), loadDependency) 171 ) 172 } 173 } 174 entryRegNext.status.issueTimer := "b11".U //otherwise 175 entryRegNext.status.deqPortIdx := 0.U //otherwise 176 when(io.deqSel){ 177 entryRegNext.status.issueTimer := 1.U 178 entryRegNext.status.deqPortIdx := io.deqPortIdxRead 179 }.elsewhen(entryReg.status.issued){ 180 entryRegNext.status.issueTimer := entryReg.status.issueTimer + 1.U 181 entryRegNext.status.deqPortIdx := entryReg.status.deqPortIdx 182 } 183 entryRegNext.status.psrc := entryReg.status.psrc 184 entryRegNext.status.srcType := entryReg.status.srcType 185 entryRegNext.status.fuType := entryReg.status.fuType 186 entryRegNext.status.robIdx := entryReg.status.robIdx 187 entryRegNext.status.issued := entryReg.status.issued // otherwise 188 when(!entryReg.status.srcReady) { 189 entryRegNext.status.issued := false.B 190 }.elsewhen(srcLoadCancelVec.map(_.reduce(_ || _)).getOrElse(false.B)) { 191 entryRegNext.status.issued := false.B 192 }.elsewhen(io.issueResp.valid) { 193 when(RSFeedbackType.isStageSuccess(io.issueResp.bits.respType)) { 194 entryRegNext.status.issued := true.B 195 }.elsewhen(RSFeedbackType.isBlocked(io.issueResp.bits.respType)) { 196 entryRegNext.status.issued := false.B 197 } 198 } 199 entryRegNext.status.firstIssue := io.deqSel || entryReg.status.firstIssue 200 entryRegNext.status.blocked := false.B //todo 201 //remain imm and payload 202 entryRegNext.imm := entryReg.imm 203 entryRegNext.payload := entryReg.payload 204 if (params.needPc) { 205 entryRegNext.status.pc.get := entryReg.status.pc.get 206 entryRegNext.status.target.get := entryReg.status.target.get 207 } 208 } 209 210 //output 211 io.canIssue := entryReg.status.canIssue && validReg 212 io.clear := clear 213 io.fuType := entryReg.status.fuType 214 io.dataSource := entryReg.status.dataSources 215 io.srcWakeUpL1ExuOH.foreach(_ := entryReg.status.srcWakeUpL1ExuOH.get) 216 io.srcTimer.foreach(_ := entryReg.status.srcTimer.get) 217 io.valid := validReg 218 io.isFirstIssue := !entryReg.status.firstIssue 219 io.entry.valid := validReg 220 io.entry.bits := entryReg 221 io.robIdx := entryReg.status.robIdx 222 io.issueTimerRead := Mux(io.deqSel, 0.U, entryReg.status.issueTimer) 223 io.deqPortIdxRead := Mux(io.deqSel, io.deqPortIdxWrite, entryReg.status.deqPortIdx) 224} 225 226class OthersEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends OthersEntry 227 with HasCircularQueuePtrHelper { 228 229 val fromMem = io.fromMem.get 230 231 val memStatus = entryReg.status.mem.get 232 val memStatusNext = entryRegNext.status.mem.get 233 // load cannot be issued before older store, unless meet some condition 234 val blockedByOlderStore = isAfter(memStatusNext.sqIdx, fromMem.stIssuePtr) 235 236 val deqFailedForStdInvalid = io.issueResp.valid && io.issueResp.bits.respType === RSFeedbackType.dataInvalid 237 238 val staWaitedReleased = Cat( 239 fromMem.memWaitUpdateReq.staIssue.map(x => x.valid && x.bits.uop.robIdx.value === memStatusNext.waitForRobIdx.value) 240 ).orR 241 val stdWaitedReleased = Cat( 242 fromMem.memWaitUpdateReq.stdIssue.map(x => x.valid && x.bits.uop.sqIdx.value === memStatusNext.waitForSqIdx.value) 243 ).orR 244 val olderStaNotViolate = staWaitedReleased && !memStatusNext.strictWait 245 val olderStdReady = stdWaitedReleased && memStatusNext.waitForStd 246 val waitStd = !olderStdReady 247 val waitSta = !olderStaNotViolate 248 249 when(io.enq.valid && io.transSel) { 250 memStatusNext.waitForSqIdx := io.enq.bits.status.mem.get.waitForSqIdx 251 // update by lfst at dispatch stage 252 memStatusNext.waitForRobIdx := io.enq.bits.status.mem.get.waitForRobIdx 253 // new load inst don't known if it is blocked by store data ahead of it 254 memStatusNext.waitForStd := false.B 255 // update by ssit at rename stage 256 memStatusNext.strictWait := io.enq.bits.status.mem.get.strictWait 257 memStatusNext.sqIdx := io.enq.bits.status.mem.get.sqIdx 258 }.elsewhen(deqFailedForStdInvalid) { 259 // Todo: check if need assign statusNext.block 260 memStatusNext.waitForSqIdx := io.issueResp.bits.dataInvalidSqIdx 261 memStatusNext.waitForRobIdx := memStatus.waitForRobIdx 262 memStatusNext.waitForStd := true.B 263 memStatusNext.strictWait := memStatus.strictWait 264 memStatusNext.sqIdx := memStatus.sqIdx 265 }.otherwise { 266 memStatusNext := memStatus 267 } 268 269 val shouldBlock = Mux(io.enq.valid && io.transSel, io.enq.bits.status.blocked, entryReg.status.blocked) 270 val blockNotReleased = waitStd || waitSta 271 val respBlock = deqFailedForStdInvalid 272 entryRegNext.status.blocked := shouldBlock && blockNotReleased && blockedByOlderStore || respBlock 273} 274 275object OthersEntry { 276 def apply(implicit p: Parameters, iqParams: IssueBlockParams): OthersEntry = { 277 iqParams.schdType match { 278 case IntScheduler() => new OthersEntry() 279 case MemScheduler() => 280 if (iqParams.StdCnt == 0) new OthersEntryMem() 281 else new OthersEntry() 282 case VfScheduler() => new OthersEntry() 283 case _ => null 284 } 285 } 286}