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.{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 common = Wire(new CommonWireBundle) 35 val entryUpdate = Wire(new EntryBundle) 36 val entryRegNext = Wire(new EntryBundle) 37 val enqDelayValidRegNext= Wire(Bool()) 38 val hasWakeupIQ = OptionWrapper(params.hasIQWakeUp, Wire(new CommonIQWakeupBundle)) 39 40 val currentStatus = Wire(new Status()) 41 val enqDelaySrcState = Wire(Vec(params.numRegSrc, SrcState())) 42 val enqDelayDataSources = Wire(Vec(params.numRegSrc, DataSource())) 43 val enqDelaySrcWakeUpL1ExuOH = OptionWrapper(params.hasIQWakeUp, Wire(Vec(params.numRegSrc, ExuOH()))) 44 val enqDelaySrcLoadDependency = Wire(Vec(params.numRegSrc, Vec(LoadPipelineWidth, UInt(3.W)))) 45 46 val enqDelaySrcWakeUpByWB: Vec[UInt] = Wire(Vec(params.numRegSrc, SrcState())) 47 val enqDelaySrcWakeUpByIQ: Vec[UInt] = Wire(Vec(params.numRegSrc, SrcState())) 48 val enqDelaySrcWakeUpByIQVec: Vec[Vec[Bool]] = Wire(Vec(params.numRegSrc, Vec(params.numWakeupFromIQ, Bool()))) 49 val enqDelayShiftedWakeupLoadDependencyByIQVec: Vec[Vec[UInt]] = Wire(Vec(params.numWakeupFromIQ, Vec(LoadPipelineWidth, UInt(3.W)))) 50 51 //Reg 52 val validReg = GatedValidRegNext(common.validRegNext, false.B) 53 val entryReg = RegEnable(entryRegNext, validReg || common.validRegNext) 54 val enqDelayValidReg = GatedValidRegNext(enqDelayValidRegNext, false.B) 55 56 //Wire 57 CommonWireConnect(common, hasWakeupIQ, validReg, currentStatus, io.commonIn, true) 58 59 when(io.commonIn.enq.valid) { 60 assert(common.enqReady, "Entry is not ready when enq is valid\n") 61 } 62 63 when(io.commonIn.enq.valid && common.enqReady) { 64 entryRegNext := io.commonIn.enq.bits 65 }.otherwise { 66 entryRegNext := entryUpdate 67 } 68 69 when(io.commonIn.enq.valid && common.enqReady) { 70 enqDelayValidRegNext := true.B 71 }.otherwise { 72 enqDelayValidRegNext := false.B 73 } 74 75 if (params.hasIQWakeUp) { 76 ShiftLoadDependency(hasWakeupIQ.get) 77 CommonIQWakeupConnect(common, hasWakeupIQ.get, validReg, currentStatus, io.commonIn, true) 78 } 79 80 // enq delay wakeup 81 enqDelaySrcWakeUpByWB.zipWithIndex.foreach { case (wakeup, i) => 82 wakeup := io.enqDelayWakeUpFromWB.map(x => x.bits.wakeUp(Seq((entryReg.status.srcStatus(i).psrc, entryReg.status.srcStatus(i).srcType)), x.valid).head 83 ).reduce(_ || _) 84 } 85 86 if (params.hasIQWakeUp) { 87 val wakeupVec: IndexedSeq[IndexedSeq[Bool]] = io.enqDelayWakeUpFromIQ.map( x => 88 x.bits.wakeUpFromIQ(entryReg.status.srcStatus.map(_.psrc) zip entryReg.status.srcStatus.map(_.srcType)) 89 ).toIndexedSeq.transpose 90 val cancelSel = params.wakeUpSourceExuIdx.zip(io.enqDelayWakeUpFromIQ).map{ case (x, y) => io.enqDelayOg0Cancel(x) && y.bits.is0Lat} 91 enqDelaySrcWakeUpByIQVec := wakeupVec.map(x => VecInit(x.zip(cancelSel).map { case (wakeup, cancel) => wakeup && !cancel })) 92 } else { 93 enqDelaySrcWakeUpByIQVec := 0.U.asTypeOf(enqDelaySrcWakeUpByIQVec) 94 } 95 96 if (params.hasIQWakeUp) { 97 enqDelaySrcWakeUpByIQ.zipWithIndex.foreach { case (wakeup, i) => 98 val ldTransCancel = Mux1H(enqDelaySrcWakeUpByIQVec(i), io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency).map(dp => LoadShouldCancel(Some(dp), io.enqDelayLdCancel)).toSeq) 99 wakeup := enqDelaySrcWakeUpByIQVec(i).asUInt.orR && !ldTransCancel 100 } 101 } else { 102 enqDelaySrcWakeUpByIQ := 0.U.asTypeOf(enqDelaySrcWakeUpByIQ) 103 } 104 105 enqDelayShiftedWakeupLoadDependencyByIQVec.zip(io.enqDelayWakeUpFromIQ.map(_.bits.loadDependency)) 106 .zip(params.wakeUpInExuSources.map(_.name)).foreach { case ((dps, ldps), name) => 107 dps.zip(ldps).zipWithIndex.foreach { case ((dp, ldp), deqPortIdx) => 108 if (params.backendParam.getLdExuIdx(params.backendParam.allExuParams.find(_.name == name).get) == deqPortIdx) 109 dp := (ldp << 2).asUInt | 2.U 110 else 111 dp := ldp << 1 112 } 113 } 114 115 for (i <- 0 until params.numRegSrc) { 116 enqDelaySrcState(i) := entryReg.status.srcStatus(i).srcState | enqDelaySrcWakeUpByWB(i) | enqDelaySrcWakeUpByIQ(i) 117 enqDelayDataSources(i).value := Mux(enqDelaySrcWakeUpByIQ(i).asBool, DataSource.bypass, entryReg.status.srcStatus(i).dataSources.value) 118 if (params.hasIQWakeUp) { 119 val wakeUpValid = enqDelaySrcWakeUpByIQVec(i).asUInt.orR 120 val wakeUpOH = enqDelaySrcWakeUpByIQVec(i) 121 enqDelaySrcWakeUpL1ExuOH.get(i) := Mux1H(wakeUpOH, params.wakeUpSourceExuIdx.map(x => MathUtils.IntToOH(x).U(backendParams.numExu.W)).toSeq) 122 enqDelaySrcLoadDependency(i) := Mux(enqDelaySrcWakeUpByIQVec(i).asUInt.orR, Mux1H(enqDelaySrcWakeUpByIQVec(i), enqDelayShiftedWakeupLoadDependencyByIQVec), entryReg.status.srcStatus(i).srcLoadDependency) 123 } else { 124 enqDelaySrcLoadDependency(i) := entryReg.status.srcStatus(i).srcLoadDependency 125 } 126 } 127 currentStatus := entryReg.status 128 when (enqDelayValidReg) { 129 currentStatus.srcStatus.zipWithIndex.foreach { case (srcStatus, srcIdx) => 130 srcStatus.srcState := enqDelaySrcState(srcIdx) 131 srcStatus.dataSources := enqDelayDataSources(srcIdx) 132 srcStatus.srcLoadDependency := enqDelaySrcLoadDependency(srcIdx) 133 } 134 } 135 136 if (params.hasIQWakeUp) { 137 currentStatus.srcStatus.map(_.srcWakeUpL1ExuOH.get).zip(entryReg.status.srcStatus.map(_.srcWakeUpL1ExuOH.get)).zip(enqDelaySrcWakeUpL1ExuOH.get).foreach { 138 case ((currExuOH, regExuOH), enqDelayExuOH) => 139 currExuOH := 0.U.asTypeOf(currExuOH) 140 params.wakeUpSourceExuIdx.foreach(x => currExuOH(x) := Mux(enqDelayValidReg, enqDelayExuOH(x), regExuOH(x))) 141 } 142 } 143 144 EntryRegCommonConnect(common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true) 145 146 //output 147 CommonOutConnect(io.commonOut, common, hasWakeupIQ, validReg, entryUpdate, entryReg, currentStatus, io.commonIn, true, isComp) 148} 149 150class EnqEntryVecMem(isComp: Boolean)(implicit p: Parameters, params: IssueBlockParams) extends EnqEntry(isComp) 151 with HasCircularQueuePtrHelper { 152 153 require(params.isVecMemIQ, "EnqEntryVecMem can only be instance of VecMem IQ") 154 155 EntryVecMemConnect(io.commonIn, common, validReg, entryReg, entryRegNext, entryUpdate) 156} 157 158object EnqEntry { 159 def apply(isComp: Boolean)(implicit p: Parameters, iqParams: IssueBlockParams): EnqEntry = { 160 iqParams.schdType match { 161 case IntScheduler() => new EnqEntry(isComp) 162 case MemScheduler() => 163 if (iqParams.isVecMemIQ) new EnqEntryVecMem(isComp) 164 else new EnqEntry(isComp) 165 case VfScheduler() => new EnqEntry(isComp) 166 case _ => null 167 } 168 } 169}