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