1package xiangshan.backend.exu 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import xiangshan.HasXSParameter 7import xiangshan.backend.BackendParams 8import xiangshan.backend.Bundles.{ExuBypassBundle, ExuInput, ExuOutput, WriteBackBundle} 9import xiangshan.backend.datapath.DataConfig.DataConfig 10import xiangshan.backend.datapath.RdConfig._ 11import xiangshan.backend.datapath.WakeUpConfig 12import xiangshan.backend.datapath.WbConfig.{IntWB, VfWB, WbConfig} 13import xiangshan.backend.fu.{FuConfig, FuType} 14import xiangshan.backend.issue.{IntScheduler, SchedulerType, VfScheduler} 15 16case class ExeUnitParams( 17 name : String, 18 fuConfigs : Seq[FuConfig], 19 wbPortConfigs : Seq[WbConfig], 20 rfrPortConfigs: Seq[Seq[RdConfig]], 21)( 22 implicit 23 val schdType: SchedulerType, 24) { 25 // calculated configs 26 var iqWakeUpSourcePairs: Seq[WakeUpConfig] = Seq() 27 var iqWakeUpSinkPairs: Seq[WakeUpConfig] = Seq() 28 // used in bypass to select data of exu output 29 var exuIdx: Int = -1 30 var backendParam: BackendParams = null 31 32 val numIntSrc: Int = fuConfigs.map(_.numIntSrc).max 33 val numFpSrc: Int = fuConfigs.map(_.numFpSrc).max 34 val numVecSrc: Int = fuConfigs.map(_.numVecSrc).max 35 val numVfSrc: Int = fuConfigs.map(_.numVfSrc).max 36 val numRegSrc: Int = fuConfigs.map(_.numRegSrc).max 37 val numSrc: Int = fuConfigs.map(_.numSrc).max 38 val dataBitsMax: Int = fuConfigs.map(_.dataBits).max 39 val readIntRf: Boolean = numIntSrc > 0 40 val readFpRf: Boolean = numFpSrc > 0 41 val readVecRf: Boolean = numVecSrc > 0 42 val writeIntRf: Boolean = fuConfigs.map(_.writeIntRf).reduce(_ || _) 43 val writeFpRf: Boolean = fuConfigs.map(_.writeFpRf).reduce(_ || _) 44 val writeVecRf: Boolean = fuConfigs.map(_.writeVecRf).reduce(_ || _) 45 val writeVfRf: Boolean = writeFpRf || writeVecRf 46 val writeFflags: Boolean = fuConfigs.map(_.writeFflags).reduce(_ || _) 47 val writeVxsat: Boolean = fuConfigs.map(_.writeVxsat).reduce(_ || _) 48 val hasNoDataWB: Boolean = fuConfigs.map(_.hasNoDataWB).reduce(_ || _) 49 val hasRedirect: Boolean = fuConfigs.map(_.hasRedirect).reduce(_ || _) 50 val hasPredecode: Boolean = fuConfigs.map(_.hasPredecode).reduce(_ || _) 51 val exceptionOut: Seq[Int] = fuConfigs.map(_.exceptionOut).reduce(_ ++ _).distinct.sorted 52 val hasLoadError: Boolean = fuConfigs.map(_.hasLoadError).reduce(_ || _) 53 val flushPipe: Boolean = fuConfigs.map(_.flushPipe).reduce(_ || _) 54 val replayInst: Boolean = fuConfigs.map(_.replayInst).reduce(_ || _) 55 val trigger: Boolean = fuConfigs.map(_.trigger).reduce(_ || _) 56 val needExceptionGen: Boolean = exceptionOut.nonEmpty || flushPipe || replayInst || trigger 57 val needPc: Boolean = fuConfigs.map(_.needPc).reduce(_ || _) 58 val needSrcFrm: Boolean = fuConfigs.map(_.needSrcFrm).reduce(_ || _) 59 val needFPUCtrl: Boolean = fuConfigs.map(_.needFPUCtrl).reduce(_ || _) 60 val needVPUCtrl: Boolean = fuConfigs.map(_.needVecCtrl).reduce(_ || _) 61 val wbPregIdxWidth = if (wbPortConfigs.nonEmpty) wbPortConfigs.map(_.pregIdxWidth).max else 0 62 63 val writeIntFuConfigs: Seq[FuConfig] = fuConfigs.filter(x => x.writeIntRf) 64 val writeVfFuConfigs: Seq[FuConfig] = fuConfigs.filter(x => x.writeFpRf || x.writeVecRf) 65 66 /** 67 * Check if this exu has certain latency 68 */ 69 def latencyCertain: Boolean = fuConfigs.map(x => x.latency.latencyVal.nonEmpty).reduce(_ && _) 70 def intLatencyCertain: Boolean = writeIntFuConfigs.forall(x => x.latency.latencyVal.nonEmpty) 71 def vfLatencyCertain: Boolean = writeVfFuConfigs.forall(x => x.latency.latencyVal.nonEmpty) 72 73 /** 74 * Get mapping from FuType to Latency value. 75 * If [[latencyCertain]] is false, get empty [[Map]] 76 * 77 * @return Map[FuType, Latency] 78 */ 79 def fuLatencyMap: Map[Int, Int] = { 80 if (latencyCertain) 81 fuConfigs.map(x => (x.fuType, x.latency.latencyVal.get)).toMap 82 else 83 Map() 84 } 85 86 /** 87 * Get set of latency of function units. 88 * If [[latencyCertain]] is false, get empty [[Set]] 89 * 90 * @return Set[Latency] 91 */ 92 def fuLatancySet: Set[Int] = fuLatencyMap.values.toSet 93 94 def latencyValMax: Int = fuLatancySet.fold(0)(_ max _) 95 96 def intFuLatencyMap: Map[Int, Int] = { 97 if (intLatencyCertain) 98 writeIntFuConfigs.map(x => (x.fuType, x.latency.latencyVal.get)).toMap 99 else 100 Map() 101 } 102 103 def intLatencyValMax: Int = intFuLatencyMap.values.fold(0)(_ max _) 104 105 def vfFuLatencyMap: Map[Int, Int] = { 106 if (vfLatencyCertain) 107 writeVfFuConfigs.map(x => (x.fuType, x.latency.latencyVal.get)).toMap 108 else 109 Map() 110 } 111 112 def vfLatencyValMax: Int = vfFuLatencyMap.values.fold(0)(_ max _) 113 114 /** 115 * Check if this exu has fixed latency 116 */ 117 def isFixedLatency: Boolean = { 118 if (latencyCertain) 119 return fuConfigs.map(x => x.latency.latencyVal.get == fuConfigs.head.latency.latencyVal.get).reduce(_ && _) 120 false 121 } 122 123 def hasCSR: Boolean = fuConfigs.map(_.isCsr).reduce(_ || _) 124 125 def hasFence: Boolean = fuConfigs.map(_.isFence).reduce(_ || _) 126 127 def hasBrhFu = fuConfigs.map(_.fuType == FuType.brh).reduce(_ || _) 128 129 def hasJmpFu = fuConfigs.map(_.fuType == FuType.jmp).reduce(_ || _) 130 131 def hasLoadFu = fuConfigs.map(_.fuType == FuType.ldu).reduce(_ || _) 132 133 def hasVLoadFu = fuConfigs.map(_.fuType == FuType.vldu).reduce(_ || _) 134 135 def hasStoreAddrFu = fuConfigs.map(_.name == "sta").reduce(_ || _) 136 137 def hasStdFu = fuConfigs.map(_.name == "std").reduce(_ || _) 138 139 def hasMemAddrFu = hasLoadFu || hasStoreAddrFu || hasVLoadFu 140 141 def hasVecFu = fuConfigs.map(x => FuConfig.VecArithFuConfigs.contains(x)).reduce(_ || _) 142 143 def getSrcDataType(srcIdx: Int): Set[DataConfig] = { 144 fuConfigs.map(_.getSrcDataType(srcIdx)).reduce(_ ++ _) 145 } 146 147 def immType: Set[UInt] = fuConfigs.map(x => x.immType).reduce(_ ++ _) 148 149 def getWBSource: SchedulerType = { 150 schdType 151 } 152 153 def hasCrossWb: Boolean = { 154 schdType match { 155 case IntScheduler() => writeFpRf || writeVecRf 156 case VfScheduler() => writeIntRf 157 case _ => false 158 } 159 } 160 161 def canAccept(fuType: UInt): Bool = { 162 Cat(fuConfigs.map(_.fuType.U === fuType)).orR 163 } 164 165 def hasUncertainLatency: Boolean = fuConfigs.map(_.latency.latencyVal.isEmpty).reduce(_ || _) 166 167 def bindBackendParam(param: BackendParams): Unit = { 168 backendParam = param 169 } 170 171 def updateIQWakeUpConfigs(cfgs: Seq[WakeUpConfig]) = { 172 this.iqWakeUpSourcePairs = cfgs.filter(_.source.name == this.name) 173 this.iqWakeUpSinkPairs = cfgs.filter(_.sink.name == this.name) 174 if (this.isIQWakeUpSource) 175 require(!this.hasUncertainLatency, s"${this.name} is IQ wake up source, but has UncertainLatency") 176 } 177 178 def updateExuIdx(idx: Int): Unit = { 179 this.exuIdx = idx 180 } 181 182 def isIQWakeUpSource = this.iqWakeUpSourcePairs.nonEmpty 183 184 def isIQWakeUpSink = this.iqWakeUpSinkPairs.nonEmpty 185 186 def getIntWBPort = { 187 wbPortConfigs.collectFirst { 188 case x: IntWB => x 189 } 190 } 191 192 def getVfWBPort = { 193 wbPortConfigs.collectFirst { 194 case x: VfWB => x 195 } 196 } 197 198 def getRfReadDataCfgSet: Seq[Set[DataConfig]] = { 199 val fuSrcsCfgSet: Seq[Seq[Set[DataConfig]]] = fuConfigs.map(_.getRfReadDataCfgSet) 200 val alignedFuSrcsCfgSet: Seq[Seq[Set[DataConfig]]] = fuSrcsCfgSet.map(x => x ++ Seq.fill(numRegSrc - x.length)(Set[DataConfig]())) 201 202 val exuSrcsCfgSet = alignedFuSrcsCfgSet.reduce((x, y) => (x zip y).map { case (cfg1, cfg2) => cfg1 union cfg2 }) 203 204 exuSrcsCfgSet 205 } 206 207 def genExuModule(implicit p: Parameters): ExeUnit = { 208 new ExeUnit(this) 209 } 210 211 def genExuInputBundle(implicit p: Parameters): ExuInput = { 212 new ExuInput(this) 213 } 214 215 def genExuOutputBundle(implicit p: Parameters): ExuOutput = { 216 new ExuOutput(this) 217 } 218 219 def genExuBypassBundle(implicit p: Parameters): ExuBypassBundle = { 220 new ExuBypassBundle(this) 221 } 222} 223