1package xiangshan.backend.issue 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utility.{HasCircularQueuePtrHelper, GatedValidRegNext} 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.{SqPtr, LqPtr} 15import xiangshan.mem.Bundles.MemWaitUpdateReqBundle 16 17 18class EnqEntryIO(implicit p: Parameters, params: IssueBlockParams) extends XSBundle { 19 //input 20 val commonIn = new CommonInBundle 21 val enqDelayIn1 = new EnqDelayInBundle 22 val enqDelayIn2 = new EnqDelayInBundle 23 24 //output 25 val commonOut = new CommonOutBundle 26 27 def wakeup = commonIn.wakeUpFromWB ++ commonIn.wakeUpFromIQ 28} 29 30class EnqEntry(isComp: Boolean)(implicit p: Parameters, params: IssueBlockParams) extends XSModule { 31 val io = IO(new EnqEntryIO) 32 33 val common = Wire(new CommonWireBundle) 34 val entryUpdate = Wire(new EntryBundle) 35 val entryRegNext = Wire(new EntryBundle) 36 val enqDelayValidRegNext= Wire(Bool()) 37 val hasWakeupIQ = OptionWrapper(params.hasIQWakeUp, Wire(new CommonIQWakeupBundle)) 38 39 val currentStatus = Wire(new Status()) 40 val enqDelaySrcState = Wire(Vec(params.numRegSrc, SrcState())) 41 val enqDelayDataSources = Wire(Vec(params.numRegSrc, DataSource())) 42 val enqDelayExuSources = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, ExuSource()))) 43 val enqDelaySrcLoadDependency = Wire(Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W)))) 44 val enqDelayUseRegCache = OptionWrapper(params.needReadRegCache, Wire(Vec(params.numRegSrc, Bool()))) 45 val enqDelayRegCacheIdx = OptionWrapper(params.needReadRegCache, Wire(Vec(params.numRegSrc, UInt(RegCacheIdxWidth.W)))) 46 47 //Reg 48 val validReg = GatedValidRegNext(common.validRegNext, false.B) 49 val entryReg = RegNext(entryRegNext) 50 val enqDelayValidReg = GatedValidRegNext(enqDelayValidRegNext, false.B) 51 52 //Wire 53 CommonWireConnect(common, hasWakeupIQ, validReg, currentStatus, io.commonIn, true) 54 55 when(io.commonIn.enq.valid) { 56 assert(common.enqReady, s"${params.getIQName}'s EnqEntry is not ready when enq is valid\n") 57 } 58 59 when(io.commonIn.enq.valid && common.enqReady) { 60 entryRegNext := io.commonIn.enq.bits 61 }.otherwise { 62 entryRegNext := entryUpdate 63 } 64 65 when(io.commonIn.enq.valid && common.enqReady) { 66 enqDelayValidRegNext := true.B 67 }.otherwise { 68 enqDelayValidRegNext := false.B 69 } 70 71 if (params.hasIQWakeUp) { 72 ShiftLoadDependency(hasWakeupIQ.get) 73 CommonIQWakeupConnect(common, hasWakeupIQ.get, validReg, currentStatus, io.commonIn, true) 74 } 75 76 // enq delay wakeup 77 val enqDelayOut1 = Wire(new EnqDelayOutBundle) 78 val enqDelayOut2 = Wire(new EnqDelayOutBundle) 79 EnqDelayWakeupConnect(io.enqDelayIn1, enqDelayOut1, entryReg.status, delay = 1) 80 EnqDelayWakeupConnect(io.enqDelayIn2, enqDelayOut2, entryReg.status, delay = 2) 81 82 for (i <- 0 until params.numRegSrc) { 83 val enqDelay1WakeUpValid = enqDelayOut1.srcWakeUpByIQVec(i).asUInt.orR 84 val enqDelay1WakeUpOH = enqDelayOut1.srcWakeUpByIQVec(i) 85 val enqDelay2WakeUpOH = enqDelayOut2.srcWakeUpByIQVec(i) 86 val enqDelay1IsWakeupByMemIQ = enqDelay1WakeUpOH.zip(io.commonIn.wakeUpFromIQ).filter(_._2.bits.params.isMemExeUnit).map(_._1).fold(false.B)(_ || _) 87 val enqDelay2IsWakeupByMemIQ = enqDelay2WakeUpOH.zip(io.commonIn.wakeUpFromIQ).filter(_._2.bits.params.isMemExeUnit).map(_._1).fold(false.B)(_ || _) 88 val enqDelay2IsWakeupByVfIQ = enqDelay2WakeUpOH.zip(io.commonIn.wakeUpFromIQ).filter(_._2.bits.params.isVfExeUnit).map(_._1).fold(false.B)(_ || _) 89 90 if (params.inVfSchd && params.readVfRf && params.hasIQWakeUp) { 91 enqDelayDataSources(i).value := MuxCase(entryReg.status.srcStatus(i).dataSources.value, Seq( 92 (enqDelayOut1.srcWakeUpByIQ(i).asBool && !enqDelay1IsWakeupByMemIQ) -> DataSource.bypass, 93 (enqDelayOut1.srcWakeUpByIQ(i).asBool && enqDelay1IsWakeupByMemIQ) -> DataSource.bypass2, 94 (enqDelayOut2.srcWakeUpByIQ(i).asBool && !enqDelay2IsWakeupByMemIQ) -> DataSource.bypass2, 95 )) 96 enqDelayExuSources.get(i).value := Mux(enqDelay1WakeUpValid, 97 ExuSource().fromExuOH(params, Mux1H(enqDelay1WakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)))), 98 ExuSource().fromExuOH(params, Mux1H(enqDelay2WakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W))))) 99 } 100 else if (params.inMemSchd && params.readVfRf && params.hasIQWakeUp) { 101 enqDelayDataSources(i).value := MuxCase(entryReg.status.srcStatus(i).dataSources.value, Seq( 102 enqDelayOut1.srcWakeUpByIQ(i).asBool -> DataSource.bypass, 103 (enqDelayOut2.srcWakeUpByIQ(i).asBool && enqDelay2IsWakeupByVfIQ) -> DataSource.bypass2, 104 )) 105 enqDelayExuSources.get(i).value := Mux(enqDelay1WakeUpValid, 106 ExuSource().fromExuOH(params, Mux1H(enqDelay1WakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)))), 107 ExuSource().fromExuOH(params, Mux1H(enqDelay2WakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W))))) 108 } 109 else { 110 enqDelayDataSources(i).value := Mux(enqDelayOut1.srcWakeUpByIQ(i).asBool, DataSource.bypass, entryReg.status.srcStatus(i).dataSources.value) 111 if (params.hasIQWakeUp) { 112 enqDelayExuSources.get(i).value := ExuSource().fromExuOH(params, Mux1H(enqDelay1WakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)))) 113 } 114 } 115 116 enqDelaySrcState(i) := (!enqDelayOut1.srcCancelByLoad(i) & entryReg.status.srcStatus(i).srcState) | enqDelayOut1.srcWakeUpByWB(i) | enqDelayOut1.srcWakeUpByIQ(i) 117 if (params.hasIQWakeUp) { 118 enqDelaySrcLoadDependency(i) := Mux(enqDelay1WakeUpValid, Mux1H(enqDelay1WakeUpOH, enqDelayOut1.shiftedWakeupLoadDependencyByIQVec), entryReg.status.srcStatus(i).srcLoadDependency) 119 } else { 120 enqDelaySrcLoadDependency(i) := entryReg.status.srcStatus(i).srcLoadDependency 121 } 122 123 if (params.needReadRegCache) { 124 val enqDelay1WakeupSrcExuWriteRC = enqDelay1WakeUpOH.zip(io.enqDelayIn1.wakeUpFromIQ).filter(_._2.bits.params.needWriteRegCache) 125 val enqDelay1WakeupRC = enqDelay1WakeupSrcExuWriteRC.map(_._1).fold(false.B)(_ || _) && SrcType.isXp(entryReg.status.srcStatus(i).srcType) 126 val enqDelay1WakeupRCIdx = Mux1H(enqDelay1WakeupSrcExuWriteRC.map(_._1), enqDelay1WakeupSrcExuWriteRC.map(_._2.bits.rcDest.get)) 127 val enqDelay1ReplaceRC = enqDelay1WakeupSrcExuWriteRC.map(x => x._2.bits.rfWen && x._2.bits.rcDest.get === entryReg.status.srcStatus(i).regCacheIdx.get).fold(false.B)(_ || _) 128 129 enqDelayUseRegCache.get(i) := entryReg.status.srcStatus(i).useRegCache.get && !(enqDelayOut1.srcCancelByLoad(i) || enqDelay1ReplaceRC) || enqDelay1WakeupRC 130 enqDelayRegCacheIdx.get(i) := Mux(enqDelay1WakeupRC, enqDelay1WakeupRCIdx, entryReg.status.srcStatus(i).regCacheIdx.get) 131 } 132 } 133 134 // current status 135 currentStatus := entryReg.status 136 when (enqDelayValidReg) { 137 currentStatus.srcStatus.zipWithIndex.foreach { case (srcStatus, srcIdx) => 138 srcStatus.srcState := enqDelaySrcState(srcIdx) 139 srcStatus.dataSources := enqDelayDataSources(srcIdx) 140 srcStatus.srcLoadDependency := enqDelaySrcLoadDependency(srcIdx) 141 srcStatus.useRegCache.foreach(_ := enqDelayUseRegCache.get(srcIdx)) 142 srcStatus.regCacheIdx.foreach(_ := enqDelayRegCacheIdx.get(srcIdx)) 143 } 144 } 145 146 if (params.hasIQWakeUp) { 147 currentStatus.srcStatus.map(_.exuSources.get).zip(entryReg.status.srcStatus.map(_.exuSources.get)).zip(enqDelayExuSources.get).foreach { 148 case ((currExu, regExu), enqDelayExu) => 149 currExu := Mux(enqDelayValidReg, enqDelayExu, regExu) 150 } 151 } 152 153 EntryRegCommonConnect(common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true, isComp) 154 155 //output 156 CommonOutConnect(io.commonOut, common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true, isComp) 157} 158 159class EnqEntryVecMem(isComp: Boolean)(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry(isComp) 160 with HasCircularQueuePtrHelper { 161 162 require(params.isVecMemIQ, "EnqEntryVecMem can only be instance of VecMem IQ") 163 164 EntryVecMemConnect(io.commonIn, common, validReg, entryReg, entryRegNext, entryUpdate) 165} 166 167object EnqEntry { 168 def apply(isComp: Boolean)(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = { 169 iqParams.schdType match { 170 case IntScheduler() => new EnqEntry(isComp) 171 case FpScheduler() => new EnqEntry(isComp) 172 case MemScheduler() => 173 if (iqParams.isVecMemIQ) new EnqEntryVecMem(isComp) 174 else new EnqEntry(isComp) 175 case VfScheduler() => new EnqEntry(isComp) 176 case _ => null 177 } 178 } 179} 180