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