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.backend.issue.EntryBundles._ 14import xiangshan.mem.{MemWaitUpdateReq, SqPtr, LqPtr} 15 16 17class EnqEntryIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 18 //input 19 val commonIn = new CommonInBundle 20 val enqDelayWakeUpFromWB: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = Flipped(params.genWBWakeUpSinkValidBundle) 21 val enqDelayWakeUpFromIQ: MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = Flipped(params.genIQWakeUpSinkValidBundle) 22 val enqDelayOg0Cancel = Input(ExuOH(backendParams.numExu)) 23 val enqDelayLdCancel = Vec(backendParams.LdExuCnt, Flipped(new LoadCancelIO)) 24 25 //output 26 val commonOut = new CommonOutBundle 27 val transEntry = ValidIO(new EntryBundle) 28 29 def wakeup = commonIn.wakeUpFromWB ++ commonIn.wakeUpFromIQ 30} 31 32class EnqEntry(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 33 val io = IO(new EnqEntryIO) 34 35 val validReg = RegInit(false.B) 36 val enqDelayValidReg = RegInit(false.B) 37 val entryReg = Reg(new EntryBundle) 38 39 val common = Wire(new CommonWireBundle) 40 val entryUpdate = Wire(new EntryBundle) 41 val entryRegNext = Wire(new EntryBundle) 42 val enqDelayValidRegNext= Wire(Bool()) 43 val hasWakeupIQ = OptionWrapper(params.hasIQWakeUp, Wire(new CommonIQWakeupBundle)) 44 45 val currentStatus = Wire(new Status()) 46 val enqDelaySrcState = Wire(Vec(params.numRegSrc, SrcState())) 47 val enqDelayDataSources = Wire(Vec(params.numRegSrc, DataSource())) 48 val enqDelaySrcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, ExuOH()))) 49 val enqDelaySrcTimer = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, UInt(3.W)))) 50 val enqDelaySrcLoadDependency = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W))))) 51 52 val enqDelaySrcWakeUpByWB: Vec[UInt] = Wire(Vec(params.numRegSrc, SrcState())) 53 val enqDelaySrcWakeUpByIQ: Vec[UInt] = Wire(Vec(params.numRegSrc, SrcState())) 54 val enqDelaySrcWakeUpByIQVec: Vec[Vec[Bool]] = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool()))) 55 val enqDelayShiftedWakeupLoadDependencyByIQVec: Vec[Vec[UInt]] = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W)))) 56 57 //Reg 58 validReg := common.validRegNext 59 entryReg := entryRegNext 60 enqDelayValidReg := enqDelayValidRegNext 61 62 //Wire 63 CommonWireConnect(common, hasWakeupIQ, validReg, entryReg, io.commonIn, true) 64 65 when(io.commonIn.enq.valid && common.enqReady) { 66 entryRegNext := io.commonIn.enq.bits 67 }.otherwise { 68 entryRegNext := entryUpdate 69 } 70 71 when(io.commonIn.enq.valid && common.enqReady) { 72 enqDelayValidRegNext := true.B 73 }.otherwise { 74 enqDelayValidRegNext := false.B 75 } 76 77 if (params.hasIQWakeUp) { 78 ShiftLoadDependency(hasWakeupIQ.get) 79 CommonIQWakeupConnect(common, hasWakeupIQ.get, validReg, entryReg.status, io.commonIn, true) 80 } 81 82 // enq delay wakeup 83 enqDelaySrcWakeUpByWB.zipWithIndex.foreach { case (wakeup, i) => 84 wakeup := io.enqDelayWakeUpFromWB.map(x => x.bits.wakeUp(Seq((entryReg.status.srcStatus(i).psrc, entryReg.status.srcStatus(i).srcType)), x.valid).head 85 ).reduce(_ || _) 86 } 87 88 if (params.hasIQWakeUp) { 89 val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.enqDelayWakeUpFromIQ.map( x => 90 x.bits.wakeUpFromIQ(entryReg.status.srcStatus.map(_.psrc) zip entryReg.status.srcStatus.map(_.srcType)) 91 ).toIndexedSeq.transpose 92 val cancelSel = params.wakeUpSourceExuIdx.zip(io.enqDelayWakeUpFromIQ).map{ case (x, y) => io.enqDelayOg0Cancel(x) && y.bits.is0Lat} 93 enqDelaySrcWakeUpByIQVec := wakeupVec.map(x => VecInit(x.zip(cancelSel).map { case (wakeup, cancel) => wakeup && !cancel })) 94 } else { 95 enqDelaySrcWakeUpByIQVec := 0.U.asTypeOf(enqDelaySrcWakeUpByIQVec) 96 } 97 98 if (params.hasIQWakeUp) { 99 enqDelaySrcWakeUpByIQ.zipWithIndex.foreach { case (wakeup, i) => 100 val ldTransCancel = Mux1H(enqDelaySrcWakeUpByIQVec(i), io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency).map(dp => LoadShouldCancel(Some(dp), io.enqDelayLdCancel)).toSeq) 101 wakeup := enqDelaySrcWakeUpByIQVec(i).asUInt.orR && !ldTransCancel 102 } 103 } else { 104 enqDelaySrcWakeUpByIQ := 0.U.asTypeOf(enqDelaySrcWakeUpByIQ) 105 } 106 107 enqDelayShiftedWakeupLoadDependencyByIQVec.zip(io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency)) 108 .zip(params.wakeUpInExuSources.map(_.name)).foreach { case ((dps, ldps), name) => 109 dps.zip(ldps).zipWithIndex.foreach { case ((dp, ldp), deqPortIdx) => 110 if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx) 111 dp := (ldp << 2).asUInt | 2.U 112 else 113 dp := ldp << 1 114 } 115 } 116 117 for (i <- 0 until params.numRegSrc) { 118 enqDelaySrcState(i) := entryReg.status.srcStatus(i).srcState | enqDelaySrcWakeUpByWB(i) | enqDelaySrcWakeUpByIQ(i) 119 enqDelayDataSources(i).value := Mux(enqDelaySrcWakeUpByIQ(i).asBool, DataSource.bypass, DataSource.reg) 120 if (params.hasIQWakeUp) { 121 val wakeUpValid = enqDelaySrcWakeUpByIQVec(i).asUInt.orR 122 val wakeUpOH = enqDelaySrcWakeUpByIQVec(i) 123 enqDelaySrcWakeUpL1ExuOH.get(i) := Mux1H(wakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)).toSeq) 124 enqDelaySrcTimer.get(i) := Mux(wakeUpValid, 2.U, 3.U) 125 enqDelaySrcLoadDependency.get(i) := Mux(wakeUpValid, Mux1H(wakeUpOH, enqDelayShiftedWakeupLoadDependencyByIQVec), entryReg.status.srcStatus(i).srcLoadDependency.get) 126 } 127 } 128 currentStatus := entryReg.status 129 when (enqDelayValidReg) { 130 currentStatus.srcStatus.zipWithIndex.foreach { case (srcStatus, srcIdx) => 131 srcStatus.srcState := enqDelaySrcState(srcIdx) 132 srcStatus.dataSources := enqDelayDataSources(srcIdx) 133 srcStatus.srcTimer.foreach(_ := enqDelaySrcTimer.get(srcIdx)) 134 srcStatus.srcLoadDependency.foreach(_ := enqDelaySrcLoadDependency.get(srcIdx)) 135 } 136 } 137 138 if (params.hasIQWakeUp) { 139 currentStatus.srcStatus.map(_.srcWakeUpL1ExuOH.get).zip(entryReg.status.srcStatus.map(_.srcWakeUpL1ExuOH.get)).zip(enqDelaySrcWakeUpL1ExuOH.get).foreach { 140 case ((currExuOH, regExuOH), enqDelayExuOH) => 141 currExuOH := 0.U.asTypeOf(currExuOH) 142 params.wakeUpSourceExuIdx.foreach(x => currExuOH(x) := Mux(enqDelayValidReg, enqDelayExuOH(x), regExuOH(x))) 143 } 144 } 145 146 EntryRegCommonConnect(common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true) 147 148 CommonOutConnect(io.commonOut, common, hasWakeupIQ, validReg, entryReg, currentStatus, io.commonIn, true) 149 io.transEntry.valid := validReg && !common.flushed && !common.deqSuccess 150 io.transEntry.bits := entryUpdate 151} 152 153class EnqEntryMem()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry 154 with HasCircularQueuePtrHelper { 155 entryUpdate.status.blocked := EntryMemConnect(io.commonIn, common, validReg, entryReg, entryRegNext, true) 156 val memStatusUpdate = entryUpdate.status.mem.get 157 val memStatus = entryReg.status.mem.get 158 val deqFailedForStdInvalid = io.commonIn.issueResp.valid && io.commonIn.issueResp.bits.respType === RSFeedbackType.dataInvalid 159 160 when(deqFailedForStdInvalid) { 161 memStatusUpdate.waitForSqIdx := io.commonIn.issueResp.bits.dataInvalidSqIdx 162 memStatusUpdate.waitForRobIdx := memStatus.waitForRobIdx 163 memStatusUpdate.waitForStd := true.B 164 memStatusUpdate.strictWait := memStatus.strictWait 165 memStatusUpdate.sqIdx := memStatus.sqIdx 166 }.otherwise { 167 memStatusUpdate := memStatus 168 } 169 170} 171 172class EnqEntryVecMemAddr()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntryMem { 173 174 require(params.isVecMemAddrIQ, "EnqEntryVecMemAddr can only be instance of VecMemAddr IQ") 175 176 val vecMemStatus = entryReg.status.vecMem.get 177 val vecMemStatusNext = entryRegNext.status.vecMem.get 178 val vecMemStatusUpdate = entryUpdate.status.vecMem.get 179 val fromLsq = io.commonIn.fromLsq.get 180 181 when (io.commonIn.enq.valid && common.enqReady) { 182 vecMemStatusNext.sqIdx := io.commonIn.enq.bits.status.vecMem.get.sqIdx 183 vecMemStatusNext.lqIdx := io.commonIn.enq.bits.status.vecMem.get.lqIdx 184 }.otherwise { 185 vecMemStatusNext := vecMemStatusUpdate 186 } 187 vecMemStatusUpdate := vecMemStatus 188 189 val isLsqHead = { 190 // if (params.isVecLdAddrIQ) 191 entryRegNext.status.vecMem.get.lqIdx <= fromLsq.lqDeqPtr && 192 // else 193 entryRegNext.status.vecMem.get.sqIdx <= fromLsq.sqDeqPtr 194 } 195 196 entryUpdate.status.vecMem.get.uopIdx := entryReg.status.vecMem.get.uopIdx 197} 198 199class EnqEntryVecMemData()(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry 200 with HasCircularQueuePtrHelper { 201 202 require(params.isVecStDataIQ, "EnqEntryVecMemData can only be instance of VecMemData IQ") 203 204 val vecMemStatus = entryReg.status.vecMem.get 205 val vecMemStatusNext = entryRegNext.status.vecMem.get 206 val vecMemStatusUpdate = entryUpdate.status.vecMem.get 207 val fromLsq = io.commonIn.fromLsq.get 208 209 when (io.commonIn.enq.valid && common.enqReady) { 210 vecMemStatusNext.sqIdx := io.commonIn.enq.bits.status.vecMem.get.sqIdx 211 vecMemStatusNext.lqIdx := io.commonIn.enq.bits.status.vecMem.get.lqIdx 212 }.otherwise { 213 vecMemStatusNext := vecMemStatusUpdate 214 } 215 vecMemStatusUpdate := vecMemStatus 216 217 val isLsqHead = entryRegNext.status.vecMem.get.sqIdx.value === fromLsq.sqDeqPtr.value 218 219 entryRegNext.status.blocked := !isLsqHead 220 entryUpdate.status.blocked := !isLsqHead 221 entryUpdate.status.vecMem.get.uopIdx := entryReg.status.vecMem.get.uopIdx 222} 223 224object EnqEntry { 225 def apply(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = { 226 iqParams.schdType match { 227 case IntScheduler() => new EnqEntry() 228 case MemScheduler() => 229 if (iqParams.isLdAddrIQ || iqParams.isStAddrIQ || iqParams.isHyAddrIQ) new EnqEntryMem() 230 else if (iqParams.isVecMemAddrIQ) new EnqEntryVecMemAddr() 231 else if (iqParams.isVecStDataIQ) new EnqEntryVecMemData() 232 else new EnqEntry() 233 case VfScheduler() => new EnqEntry() 234 case _ => null 235 } 236 } 237}