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