1package xiangshan.backend.issue 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utils.SeqUtils 7import xiangshan.backend.BackendParams 8import xiangshan.backend.Bundles._ 9import xiangshan.backend.datapath.WbConfig.WbConfig 10import xiangshan.backend.datapath.{WakeUpConfig, WakeUpSource} 11import xiangshan.backend.exu.ExeUnitParams 12import xiangshan.backend.fu.{FuConfig, FuType} 13 14case class IssueBlockParams( 15 // top down 16 exuBlockParams : Seq[ExeUnitParams], 17 numEntries : Int, 18 pregBits : Int, 19 numWakeupFromWB : Int, 20 numEnq : Int, 21 numDeqOutside : Int = 0, 22 numWakeupFromOthers: Int = 0, 23 XLEN : Int = 64, 24 VLEN : Int = 128, 25 vaddrBits : Int = 39, 26 // calculate in scheduler 27 var idxInSchBlk : Int = 0, 28)( 29 implicit 30 val schdType: SchedulerType, 31) { 32 var backendParam: BackendParams = null 33 34 def updateIdx(idx: Int): Unit = { 35 this.idxInSchBlk = idx 36 } 37 38 def inMemSchd: Boolean = schdType == MemScheduler() 39 40 def inIntSchd: Boolean = schdType == IntScheduler() 41 42 def inVfSchd: Boolean = schdType == VfScheduler() 43 44 def isMemAddrIQ: Boolean = inMemSchd && StdCnt == 0 45 46 def isLdAddrIQ: Boolean = inMemSchd && LduCnt > 0 47 48 def isStAddrIQ: Boolean = inMemSchd && StaCnt > 0 49 50 def numExu: Int = exuBlockParams.length 51 52 def numIntSrc: Int = exuBlockParams.map(_.numIntSrc).max 53 54 def numFpSrc: Int = exuBlockParams.map(_.numFpSrc).max 55 56 def numVecSrc: Int = exuBlockParams.map(_.numVecSrc).max 57 58 def numVfSrc: Int = exuBlockParams.map(_.numVfSrc).max 59 60 def numRegSrc: Int = exuBlockParams.map(_.numRegSrc).max 61 62 def numSrc: Int = exuBlockParams.map(_.numSrc).max 63 64 def readIntRf: Boolean = numIntSrc > 0 65 66 def readFpRf: Boolean = numFpSrc > 0 67 68 def readVecRf: Boolean = numVecSrc > 0 69 70 def readVfRf: Boolean = numVfSrc > 0 71 72 def writeIntRf: Boolean = exuBlockParams.map(_.writeIntRf).reduce(_ || _) 73 74 def writeFpRf: Boolean = exuBlockParams.map(_.writeFpRf).reduce(_ || _) 75 76 def writeVecRf: Boolean = exuBlockParams.map(_.writeVecRf).reduce(_ || _) 77 78 def exceptionOut: Seq[Int] = exuBlockParams.map(_.exceptionOut).reduce(_ ++ _).distinct.sorted 79 80 def hasLoadError: Boolean = exuBlockParams.map(_.hasLoadError).reduce(_ || _) 81 82 def flushPipe: Boolean = exuBlockParams.map(_.flushPipe).reduce(_ || _) 83 84 def replayInst: Boolean = exuBlockParams.map(_.replayInst).reduce(_ || _) 85 86 def trigger: Boolean = exuBlockParams.map(_.trigger).reduce(_ || _) 87 88 def needExceptionGen: Boolean = exceptionOut.nonEmpty || flushPipe || replayInst || trigger 89 90 def needPc: Boolean = JmpCnt + BrhCnt + FenceCnt > 0 91 92 def needSrcFrm: Boolean = exuBlockParams.map(_.needSrcFrm).reduce(_ || _) 93 94 def numPcReadPort: Int = (if (needPc) 1 else 0) * numEnq 95 96 def numWriteIntRf: Int = exuBlockParams.count(_.writeIntRf) 97 98 def numWriteFpRf: Int = exuBlockParams.count(_.writeFpRf) 99 100 def numWriteVecRf: Int = exuBlockParams.count(_.writeVecRf) 101 102 def numWriteVfRf: Int = exuBlockParams.count(_.writeVfRf) 103 104 def numNoDataWB: Int = exuBlockParams.count(_.hasNoDataWB) 105 106 def dataBitsMax: Int = if (numVecSrc > 0) VLEN else XLEN 107 108 def numDeq: Int = numDeqOutside + exuBlockParams.length 109 110 def JmpCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.jmp)).sum 111 112 def BrhCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.brh)).sum 113 114 def I2fCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.i2f)).sum 115 116 def CsrCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.csr)).sum 117 118 def AluCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.alu)).sum 119 120 def MulCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.mul)).sum 121 122 def DivCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.div)).sum 123 124 def FenceCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.fence)).sum 125 126 def BkuCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.bku)).sum 127 128 def VsetCnt: Int = exuBlockParams.map(_.fuConfigs.count(x => x.fuType == FuType.vsetiwi || x.fuType == FuType.vsetiwf || x.fuType == FuType.vsetfwf)).sum 129 130 def FmacCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.fmac)).sum 131 132 def FmiscCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.fmisc)).sum 133 134 def fDivSqrtCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.fDivSqrt)).sum 135 136 def LduCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.name == "ldu")).sum 137 138 def StaCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.name == "sta")).sum 139 140 def MouCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.mou)).sum 141 142 def StdCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.name == "std")).sum 143 144 def VipuCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.vipu)).sum 145 146 def VfpuCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.vfpu)).sum 147 148 def VlduCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.vldu)).sum 149 150 def VstuCnt: Int = exuBlockParams.map(_.fuConfigs.count(_.fuType == FuType.vstu)).sum 151 152 def numRedirect: Int = exuBlockParams.count(_.hasRedirect) 153 154 def iqWakeUpSourcePairs: Seq[WakeUpConfig] = exuBlockParams.flatMap(_.iqWakeUpSourcePairs) 155 156 /** Get exu source wake up 157 * @todo replace with 158 * exuBlockParams 159 * .flatMap(_.iqWakeUpSinkPairs) 160 * .map(_.source) 161 * .distinctBy(_.name) 162 * when xiangshan is updated to 2.13.11 163 */ 164 def wakeUpInExuSources: Seq[WakeUpSource] = { 165 SeqUtils.distinctBy( 166 exuBlockParams 167 .flatMap(_.iqWakeUpSinkPairs) 168 .map(_.source) 169 )(_.name) 170 } 171 172 def wakeUpOutExuSources: Seq[WakeUpSource] = { 173 SeqUtils.distinctBy( 174 exuBlockParams 175 .flatMap(_.iqWakeUpSourcePairs) 176 .map(_.source) 177 )(_.name) 178 } 179 180 def wakeUpToExuSinks = exuBlockParams 181 .flatMap(_.iqWakeUpSourcePairs) 182 .map(_.sink).distinct 183 184 def numWakeupFromIQ: Int = wakeUpInExuSources.size 185 186 def numAllWakeUp: Int = numWakeupFromWB + numWakeupFromIQ + numWakeupFromOthers 187 188 def hasIQWakeUp: Boolean = numWakeupFromIQ > 0 189 190 def getFuCfgs: Seq[FuConfig] = exuBlockParams.flatMap(_.fuConfigs).distinct 191 192 // cfgs(exuIdx)(set of exu's wb) 193 def getWbCfgs: Seq[Set[WbConfig]] = { 194 exuBlockParams.map(exu => exu.wbPortConfigs.toSet) 195 } 196 197 def canAccept(fuType: UInt): Bool = { 198 Cat(getFuCfgs.map(_.fuType.U === fuType)).orR 199 } 200 201 def bindBackendParam(param: BackendParams): Unit = { 202 backendParam = param 203 } 204 205 def genExuInputDecoupledBundle(implicit p: Parameters): MixedVec[DecoupledIO[ExuInput]] = { 206 MixedVec(this.exuBlockParams.map(x => DecoupledIO(x.genExuInputBundle))) 207 } 208 209 def genExuOutputDecoupledBundle(implicit p: Parameters): MixedVec[DecoupledIO[ExuOutput]] = { 210 MixedVec(this.exuBlockParams.map(x => DecoupledIO(x.genExuOutputBundle))) 211 } 212 213 def genExuOutputValidBundle(implicit p: Parameters): MixedVec[ValidIO[ExuOutput]] = { 214 MixedVec(this.exuBlockParams.map(x => ValidIO(x.genExuOutputBundle))) 215 } 216 217 def genExuBypassValidBundle(implicit p: Parameters): MixedVec[ValidIO[ExuBypassBundle]] = { 218 MixedVec(this.exuBlockParams.map(x => ValidIO(x.genExuBypassBundle))) 219 } 220 221 def genIssueDecoupledBundle(implicit p: Parameters): MixedVec[DecoupledIO[IssueQueueIssueBundle]] = { 222 MixedVec(exuBlockParams.map(x => DecoupledIO(new IssueQueueIssueBundle(this, x, pregBits, vaddrBits)))) 223 } 224 225 def genWBWakeUpSinkValidBundle: MixedVec[ValidIO[IssueQueueWBWakeUpBundle]] = { 226 val intBundle: Seq[ValidIO[IssueQueueWBWakeUpBundle]] = schdType match { 227 case IntScheduler() | MemScheduler() => backendParam.getIntWBExeGroup.map(x => ValidIO(new IssueQueueWBWakeUpBundle(x._2.map(_.exuIdx), backendParam))).toSeq 228 case _ => Seq() 229 } 230 val vfBundle = schdType match { 231 case VfScheduler() | MemScheduler() => backendParam.getVfWBExeGroup.map(x => ValidIO(new IssueQueueWBWakeUpBundle(x._2.map(_.exuIdx), backendParam))).toSeq 232 case _ => Seq() 233 } 234 MixedVec(intBundle ++ vfBundle) 235 } 236 237 def genIQWakeUpSourceValidBundle(implicit p: Parameters): MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = { 238 MixedVec(exuBlockParams.map(x => ValidIO(new IssueQueueIQWakeUpBundle(x.exuIdx, backendParam)))) 239 } 240 241 def genIQWakeUpSinkValidBundle(implicit p: Parameters): MixedVec[ValidIO[IssueQueueIQWakeUpBundle]] = { 242 MixedVec(this.wakeUpInExuSources.map(x => ValidIO(new IssueQueueIQWakeUpBundle(backendParam.getExuIdx(x.name), backendParam)))) 243 } 244 245 def genOGRespBundle(implicit p: Parameters) = { 246 implicit val issueBlockParams = this 247 MixedVec(exuBlockParams.map(_ => new OGRespBundle)) 248 } 249 250 def genWbFuBusyTableWriteBundle()(implicit p: Parameters) = { 251 implicit val issueBlockParams = this 252 MixedVec(exuBlockParams.map(x => new WbFuBusyTableWriteBundle(x))) 253 } 254 255 def genWbFuBusyTableReadBundle()(implicit p: Parameters) = { 256 implicit val issueBlockParams = this 257 MixedVec(exuBlockParams.map{ x => 258 new WbFuBusyTableReadBundle(x) 259 }) 260 } 261 262 def genWbConflictBundle()(implicit p: Parameters) = { 263 implicit val issueBlockParams = this 264 MixedVec(exuBlockParams.map { x => 265 new WbConflictBundle(x) 266 }) 267 } 268 269 def getIQName = { 270 "IssueQueue" ++ getFuCfgs.map(_.name).distinct.map(_.capitalize).reduce(_ ++ _) 271 } 272} 273