xref: /XiangShan/src/main/scala/xiangshan/backend/exu/ExeUnitParams.scala (revision 71dbd663d9e21a16d7e81b8e622be27e4c82b79d)
1730cfbc0SXuan Hupackage xiangshan.backend.exu
2730cfbc0SXuan Hu
383ba63b3SXuan Huimport org.chipsalliance.cde.config.Parameters
4730cfbc0SXuan Huimport chisel3._
5730cfbc0SXuan Huimport chisel3.util._
6dd473fffSXuan Huimport xiangshan.backend.BackendParams
739c59369SXuan Huimport xiangshan.backend.Bundles.{ExuBypassBundle, ExuInput, ExuOutput}
8730cfbc0SXuan Huimport xiangshan.backend.datapath.DataConfig.DataConfig
9730cfbc0SXuan Huimport xiangshan.backend.datapath.RdConfig._
1039c59369SXuan Huimport xiangshan.backend.datapath.WbConfig.{IntWB, PregWB, VfWB}
1139c59369SXuan Huimport xiangshan.backend.datapath.{DataConfig, WakeUpConfig}
12730cfbc0SXuan Huimport xiangshan.backend.fu.{FuConfig, FuType}
134c5a0d77Sxiaofeibao-xjtuimport xiangshan.backend.issue.{IntScheduler, IssueBlockParams, SchedulerType, VfScheduler}
144c5a0d77Sxiaofeibao-xjtuimport scala.collection.mutable
15730cfbc0SXuan Hu
16730cfbc0SXuan Hucase class ExeUnitParams(
1708017d75SXuan Hu  name          : String,
18730cfbc0SXuan Hu  fuConfigs     : Seq[FuConfig],
1939c59369SXuan Hu  wbPortConfigs : Seq[PregWB],
20730cfbc0SXuan Hu  rfrPortConfigs: Seq[Seq[RdConfig]],
214c5a0d77Sxiaofeibao-xjtu  copyWakeupOut: Boolean = false,
220c7ebb58Sxiaofeibao-xjtu  copyDistance: Int = 1,
23670870b3SXuan Hu  fakeUnit      : Boolean = false,
24730cfbc0SXuan Hu)(
25730cfbc0SXuan Hu  implicit
26730cfbc0SXuan Hu  val schdType: SchedulerType,
27730cfbc0SXuan Hu) {
28d387a573SXuan Hu  // calculated configs
29d387a573SXuan Hu  var iqWakeUpSourcePairs: Seq[WakeUpConfig] = Seq()
30d387a573SXuan Hu  var iqWakeUpSinkPairs: Seq[WakeUpConfig] = Seq()
31bf35baadSXuan Hu  // used in bypass to select data of exu output
32bf35baadSXuan Hu  var exuIdx: Int = -1
33dd473fffSXuan Hu  var backendParam: BackendParams = null
34d387a573SXuan Hu
35730cfbc0SXuan Hu  val numIntSrc: Int = fuConfigs.map(_.numIntSrc).max
36730cfbc0SXuan Hu  val numFpSrc: Int = fuConfigs.map(_.numFpSrc).max
37730cfbc0SXuan Hu  val numVecSrc: Int = fuConfigs.map(_.numVecSrc).max
38730cfbc0SXuan Hu  val numVfSrc: Int = fuConfigs.map(_.numVfSrc).max
39730cfbc0SXuan Hu  val numRegSrc: Int = fuConfigs.map(_.numRegSrc).max
40730cfbc0SXuan Hu  val numSrc: Int = fuConfigs.map(_.numSrc).max
41730cfbc0SXuan Hu  val dataBitsMax: Int = fuConfigs.map(_.dataBits).max
42730cfbc0SXuan Hu  val readIntRf: Boolean = numIntSrc > 0
43730cfbc0SXuan Hu  val readFpRf: Boolean = numFpSrc > 0
44730cfbc0SXuan Hu  val readVecRf: Boolean = numVecSrc > 0
45730cfbc0SXuan Hu  val writeIntRf: Boolean = fuConfigs.map(_.writeIntRf).reduce(_ || _)
46730cfbc0SXuan Hu  val writeFpRf: Boolean = fuConfigs.map(_.writeFpRf).reduce(_ || _)
47730cfbc0SXuan Hu  val writeVecRf: Boolean = fuConfigs.map(_.writeVecRf).reduce(_ || _)
48730cfbc0SXuan Hu  val writeVfRf: Boolean = writeFpRf || writeVecRf
49730cfbc0SXuan Hu  val writeFflags: Boolean = fuConfigs.map(_.writeFflags).reduce(_ || _)
50a8db15d8Sfdy  val writeVxsat: Boolean = fuConfigs.map(_.writeVxsat).reduce(_ || _)
51730cfbc0SXuan Hu  val hasNoDataWB: Boolean = fuConfigs.map(_.hasNoDataWB).reduce(_ || _)
52730cfbc0SXuan Hu  val hasRedirect: Boolean = fuConfigs.map(_.hasRedirect).reduce(_ || _)
53730cfbc0SXuan Hu  val hasPredecode: Boolean = fuConfigs.map(_.hasPredecode).reduce(_ || _)
54730cfbc0SXuan Hu  val exceptionOut: Seq[Int] = fuConfigs.map(_.exceptionOut).reduce(_ ++ _).distinct.sorted
55730cfbc0SXuan Hu  val hasLoadError: Boolean = fuConfigs.map(_.hasLoadError).reduce(_ || _)
56730cfbc0SXuan Hu  val flushPipe: Boolean = fuConfigs.map(_.flushPipe).reduce(_ || _)
57730cfbc0SXuan Hu  val replayInst: Boolean = fuConfigs.map(_.replayInst).reduce(_ || _)
58730cfbc0SXuan Hu  val trigger: Boolean = fuConfigs.map(_.trigger).reduce(_ || _)
59730cfbc0SXuan Hu  val needExceptionGen: Boolean = exceptionOut.nonEmpty || flushPipe || replayInst || trigger
60730cfbc0SXuan Hu  val needPc: Boolean = fuConfigs.map(_.needPc).reduce(_ || _)
619d8d7860SXuan Hu  val needTarget: Boolean = fuConfigs.map(_.needTargetPc).reduce(_ || _)
629d8d7860SXuan Hu  val needPdInfo: Boolean = fuConfigs.map(_.needPdInfo).reduce(_ || _)
63730cfbc0SXuan Hu  val needSrcFrm: Boolean = fuConfigs.map(_.needSrcFrm).reduce(_ || _)
64730cfbc0SXuan Hu  val needFPUCtrl: Boolean = fuConfigs.map(_.needFPUCtrl).reduce(_ || _)
65b6b11f60SXuan Hu  val needVPUCtrl: Boolean = fuConfigs.map(_.needVecCtrl).reduce(_ || _)
66bcf0356aSXuan Hu  val isHighestWBPriority: Boolean = wbPortConfigs.forall(_.priority == 0)
6739c59369SXuan Hu
684c5a0d77Sxiaofeibao-xjtu  def copyNum: Int = {
694c5a0d77Sxiaofeibao-xjtu    val setIQ = mutable.Set[IssueBlockParams]()
704c5a0d77Sxiaofeibao-xjtu    iqWakeUpSourcePairs.map(_.sink).foreach{ wakeupSink =>
714c5a0d77Sxiaofeibao-xjtu      backendParam.allIssueParams.map{ issueParams =>
724c5a0d77Sxiaofeibao-xjtu        if (issueParams.exuBlockParams.contains(wakeupSink.getExuParam(backendParam.allExuParams))) {
734c5a0d77Sxiaofeibao-xjtu          setIQ.add(issueParams)
744c5a0d77Sxiaofeibao-xjtu        }
754c5a0d77Sxiaofeibao-xjtu      }
764c5a0d77Sxiaofeibao-xjtu    }
774c5a0d77Sxiaofeibao-xjtu    println(s"[Backend] exuIdx ${exuIdx} numWakeupIQ ${setIQ.size}")
78*71dbd663Sxiaofeibao-xjtu    1 + setIQ.size / copyDistance
794c5a0d77Sxiaofeibao-xjtu  }
8039c59369SXuan Hu  def rdPregIdxWidth: Int = {
8139c59369SXuan Hu    this.pregRdDataCfgSet.map(dataCfg => backendParam.getPregParams(dataCfg).addrWidth).fold(0)(_ max _)
8239c59369SXuan Hu  }
8339c59369SXuan Hu
8439c59369SXuan Hu  def wbPregIdxWidth: Int = {
8539c59369SXuan Hu    this.pregWbDataCfgSet.map(dataCfg => backendParam.getPregParams(dataCfg).addrWidth).fold(0)(_ max _)
8639c59369SXuan Hu  }
87730cfbc0SXuan Hu
882e0a7dc5Sfdy  val writeIntFuConfigs: Seq[FuConfig] = fuConfigs.filter(x => x.writeIntRf)
892e0a7dc5Sfdy  val writeVfFuConfigs: Seq[FuConfig] = fuConfigs.filter(x => x.writeFpRf || x.writeVecRf)
902e0a7dc5Sfdy
91bf44d649SXuan Hu  /**
92bf44d649SXuan Hu    * Check if this exu has certain latency
93bf44d649SXuan Hu    */
94bf44d649SXuan Hu  def latencyCertain: Boolean = fuConfigs.map(x => x.latency.latencyVal.nonEmpty).reduce(_ && _)
95bf44d649SXuan Hu  def intLatencyCertain: Boolean = writeIntFuConfigs.forall(x => x.latency.latencyVal.nonEmpty)
96bf44d649SXuan Hu  def vfLatencyCertain: Boolean = writeVfFuConfigs.forall(x => x.latency.latencyVal.nonEmpty)
97f9f1abd7SXuan Hu  // only load use it
98f9f1abd7SXuan Hu  def hasUncertainLatencyVal: Boolean = fuConfigs.map(x => x.latency.uncertainLatencyVal.nonEmpty).reduce(_ || _)
992e0a7dc5Sfdy
100bf44d649SXuan Hu  /**
101bf44d649SXuan Hu    * Get mapping from FuType to Latency value.
10223c67001SHaojin Tang    * If both [[latencyCertain]] and [[hasUncertainLatencyVal]] are false, get empty [[Map]]
103bf44d649SXuan Hu    *
104239413e5SXuan Hu    * @return Map[ [[BigInt]], Latency]
105bf44d649SXuan Hu    */
106239413e5SXuan Hu  def fuLatencyMap: Map[FuType.OHType, Int] = {
107bf44d649SXuan Hu    if (latencyCertain)
108bf44d649SXuan Hu      fuConfigs.map(x => (x.fuType, x.latency.latencyVal.get)).toMap
10923c67001SHaojin Tang    else if (hasUncertainLatencyVal)
110f9f1abd7SXuan Hu      fuConfigs.map(x => (x.fuType, x.latency.uncertainLatencyVal)).toMap.filter(_._2.nonEmpty).map(x => (x._1, x._2.get))
111bf44d649SXuan Hu    else
112bf44d649SXuan Hu      Map()
113bf44d649SXuan Hu  }
1142e0a7dc5Sfdy
115bf44d649SXuan Hu  /**
116bf44d649SXuan Hu    * Get set of latency of function units.
11723c67001SHaojin Tang    * If both [[latencyCertain]] and [[hasUncertainLatencyVal]] are false, get empty [[Set]]
118bf44d649SXuan Hu    *
119bf44d649SXuan Hu    * @return Set[Latency]
120bf44d649SXuan Hu    */
121bf44d649SXuan Hu  def fuLatancySet: Set[Int] = fuLatencyMap.values.toSet
1222e0a7dc5Sfdy
123bf44d649SXuan Hu  def latencyValMax: Int = fuLatancySet.fold(0)(_ max _)
124bf44d649SXuan Hu
125239413e5SXuan Hu  def intFuLatencyMap: Map[FuType.OHType, Int] = {
126bf44d649SXuan Hu    if (intLatencyCertain)
127bf44d649SXuan Hu      writeIntFuConfigs.map(x => (x.fuType, x.latency.latencyVal.get)).toMap
128bf44d649SXuan Hu    else
129bf44d649SXuan Hu      Map()
130bf44d649SXuan Hu  }
131bf44d649SXuan Hu
132bf44d649SXuan Hu  def intLatencyValMax: Int = intFuLatencyMap.values.fold(0)(_ max _)
133bf44d649SXuan Hu
134239413e5SXuan Hu  def vfFuLatencyMap: Map[FuType.OHType, Int] = {
135bf44d649SXuan Hu    if (vfLatencyCertain)
136bf44d649SXuan Hu      writeVfFuConfigs.map(x => (x.fuType, x.latency.latencyVal.get)).toMap
137bf44d649SXuan Hu    else
138bf44d649SXuan Hu      Map()
139bf44d649SXuan Hu  }
140bf44d649SXuan Hu
141bf44d649SXuan Hu  def vfLatencyValMax: Int = vfFuLatencyMap.values.fold(0)(_ max _)
142bf44d649SXuan Hu
143bf44d649SXuan Hu  /**
144bf44d649SXuan Hu    * Check if this exu has fixed latency
145bf44d649SXuan Hu    */
146bf44d649SXuan Hu  def isFixedLatency: Boolean = {
147bf44d649SXuan Hu    if (latencyCertain)
148bf44d649SXuan Hu      return fuConfigs.map(x => x.latency.latencyVal.get == fuConfigs.head.latency.latencyVal.get).reduce(_ && _)
149bf44d649SXuan Hu    false
150bf44d649SXuan Hu  }
151ea0f92d8Sczw
152730cfbc0SXuan Hu  def hasCSR: Boolean = fuConfigs.map(_.isCsr).reduce(_ || _)
153730cfbc0SXuan Hu
154730cfbc0SXuan Hu  def hasFence: Boolean = fuConfigs.map(_.isFence).reduce(_ || _)
155730cfbc0SXuan Hu
156730cfbc0SXuan Hu  def hasBrhFu = fuConfigs.map(_.fuType == FuType.brh).reduce(_ || _)
157730cfbc0SXuan Hu
158730cfbc0SXuan Hu  def hasJmpFu = fuConfigs.map(_.fuType == FuType.jmp).reduce(_ || _)
159730cfbc0SXuan Hu
160670870b3SXuan Hu  def hasLoadFu = fuConfigs.map(_.name == "ldu").reduce(_ || _)
161730cfbc0SXuan Hu
1624ee69032SzhanglyGit  def hasVLoadFu = fuConfigs.map(_.fuType == FuType.vldu).reduce(_ || _)
1634ee69032SzhanglyGit
16420a5248fSzhanglinjuan  def hasVStoreFu = fuConfigs.map(_.fuType == FuType.vstu).reduce(_ || _)
16520a5248fSzhanglinjuan
166730cfbc0SXuan Hu  def hasStoreAddrFu = fuConfigs.map(_.name == "sta").reduce(_ || _)
167730cfbc0SXuan Hu
168730cfbc0SXuan Hu  def hasStdFu = fuConfigs.map(_.name == "std").reduce(_ || _)
169730cfbc0SXuan Hu
17020a5248fSzhanglinjuan  def hasMemAddrFu = hasLoadFu || hasStoreAddrFu || hasVLoadFu || hasHyldaFu || hasHystaFu || hasVLoadFu || hasVStoreFu
171730cfbc0SXuan Hu
172670870b3SXuan Hu  def hasHyldaFu = fuConfigs.map(_.name == "hylda").reduce(_ || _)
173670870b3SXuan Hu
174670870b3SXuan Hu  def hasHystaFu = fuConfigs.map(_.name == "hysta").reduce(_ || _)
175b133b458SXuan Hu
176272ec6b1SHaojin Tang  def hasLoadExu = hasLoadFu || hasHyldaFu
177272ec6b1SHaojin Tang
178272ec6b1SHaojin Tang  def hasStoreAddrExu = hasStoreAddrFu || hasHystaFu
179272ec6b1SHaojin Tang
180da778e6fSXuan Hu  def hasVecFu = fuConfigs.map(x => FuConfig.VecArithFuConfigs.contains(x)).reduce(_ || _)
181da778e6fSXuan Hu
182730cfbc0SXuan Hu  def getSrcDataType(srcIdx: Int): Set[DataConfig] = {
183730cfbc0SXuan Hu    fuConfigs.map(_.getSrcDataType(srcIdx)).reduce(_ ++ _)
184730cfbc0SXuan Hu  }
185730cfbc0SXuan Hu
186730cfbc0SXuan Hu  def immType: Set[UInt] = fuConfigs.map(x => x.immType).reduce(_ ++ _)
187730cfbc0SXuan Hu
188730cfbc0SXuan Hu  def getWBSource: SchedulerType = {
189730cfbc0SXuan Hu    schdType
190730cfbc0SXuan Hu  }
191730cfbc0SXuan Hu
192730cfbc0SXuan Hu  def hasCrossWb: Boolean = {
193730cfbc0SXuan Hu    schdType match {
194730cfbc0SXuan Hu      case IntScheduler() => writeFpRf || writeVecRf
195730cfbc0SXuan Hu      case VfScheduler() => writeIntRf
196730cfbc0SXuan Hu      case _ => false
197730cfbc0SXuan Hu    }
198730cfbc0SXuan Hu  }
199730cfbc0SXuan Hu
200730cfbc0SXuan Hu  def canAccept(fuType: UInt): Bool = {
201730cfbc0SXuan Hu    Cat(fuConfigs.map(_.fuType.U === fuType)).orR
202730cfbc0SXuan Hu  }
203730cfbc0SXuan Hu
204730cfbc0SXuan Hu  def hasUncertainLatency: Boolean = fuConfigs.map(_.latency.latencyVal.isEmpty).reduce(_ || _)
205730cfbc0SXuan Hu
206dd473fffSXuan Hu  def bindBackendParam(param: BackendParams): Unit = {
207dd473fffSXuan Hu    backendParam = param
208dd473fffSXuan Hu  }
209dd473fffSXuan Hu
210d387a573SXuan Hu  def updateIQWakeUpConfigs(cfgs: Seq[WakeUpConfig]) = {
211bf35baadSXuan Hu    this.iqWakeUpSourcePairs = cfgs.filter(_.source.name == this.name)
212bf35baadSXuan Hu    this.iqWakeUpSinkPairs = cfgs.filter(_.sink.name == this.name)
213b133b458SXuan Hu    if (this.isIQWakeUpSource) {
214670870b3SXuan Hu      require(!this.hasUncertainLatency || hasLoadFu || hasHyldaFu, s"${this.name} is a not-LDU IQ wake up source , but has UncertainLatency")
215bf35baadSXuan Hu    }
216b133b458SXuan Hu  }
217bf35baadSXuan Hu
218bf35baadSXuan Hu  def updateExuIdx(idx: Int): Unit = {
219bf35baadSXuan Hu    this.exuIdx = idx
220d387a573SXuan Hu  }
221d387a573SXuan Hu
222d387a573SXuan Hu  def isIQWakeUpSource = this.iqWakeUpSourcePairs.nonEmpty
223d387a573SXuan Hu
224d387a573SXuan Hu  def isIQWakeUpSink = this.iqWakeUpSinkPairs.nonEmpty
225d387a573SXuan Hu
226730cfbc0SXuan Hu  def getIntWBPort = {
227730cfbc0SXuan Hu    wbPortConfigs.collectFirst {
228730cfbc0SXuan Hu      case x: IntWB => x
229730cfbc0SXuan Hu    }
230730cfbc0SXuan Hu  }
231730cfbc0SXuan Hu
2320162f462Sczw  def getVfWBPort = {
233730cfbc0SXuan Hu    wbPortConfigs.collectFirst {
2340162f462Sczw      case x: VfWB => x
235730cfbc0SXuan Hu    }
236730cfbc0SXuan Hu  }
237730cfbc0SXuan Hu
23839c59369SXuan Hu  /**
23939c59369SXuan Hu    * Get the [[DataConfig]] that this exu need to read
24039c59369SXuan Hu    */
24139c59369SXuan Hu  def pregRdDataCfgSet: Set[DataConfig] = {
24239c59369SXuan Hu    this.rfrPortConfigs.flatten.map(_.getDataConfig).toSet
24339c59369SXuan Hu  }
24439c59369SXuan Hu
24539c59369SXuan Hu  /**
24639c59369SXuan Hu    * Get the [[DataConfig]] that this exu need to write
24739c59369SXuan Hu    */
24839c59369SXuan Hu  def pregWbDataCfgSet: Set[DataConfig] = {
24939c59369SXuan Hu    this.wbPortConfigs.map(_.dataCfg).toSet
25039c59369SXuan Hu  }
25139c59369SXuan Hu
252730cfbc0SXuan Hu  def getRfReadDataCfgSet: Seq[Set[DataConfig]] = {
253730cfbc0SXuan Hu    val fuSrcsCfgSet: Seq[Seq[Set[DataConfig]]] = fuConfigs.map(_.getRfReadDataCfgSet)
254730cfbc0SXuan Hu    val alignedFuSrcsCfgSet: Seq[Seq[Set[DataConfig]]] = fuSrcsCfgSet.map(x => x ++ Seq.fill(numRegSrc - x.length)(Set[DataConfig]()))
255730cfbc0SXuan Hu
256730cfbc0SXuan Hu    val exuSrcsCfgSet = alignedFuSrcsCfgSet.reduce((x, y) => (x zip y).map { case (cfg1, cfg2) => cfg1 union cfg2 })
257730cfbc0SXuan Hu
258730cfbc0SXuan Hu    exuSrcsCfgSet
259730cfbc0SXuan Hu  }
260730cfbc0SXuan Hu
26139c59369SXuan Hu  /**
26239c59369SXuan Hu    * Get the [[DataConfig]] mapped indices of source data of exu
26339c59369SXuan Hu    *
26439c59369SXuan Hu    * @example
26539c59369SXuan Hu    * {{{
26639c59369SXuan Hu    *   fuCfg.srcData = Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData())
26739c59369SXuan Hu    *   getRfReadSrcIdx(VecData()) = Seq(0, 1, 2)
26839c59369SXuan Hu    *   getRfReadSrcIdx(MaskSrcData()) = Seq(3)
26939c59369SXuan Hu    *   getRfReadSrcIdx(VConfigData()) = Seq(4)
27039c59369SXuan Hu    * }}}
27139c59369SXuan Hu    * @return Map[DataConfig -> Seq[indices]]
27239c59369SXuan Hu    */
27339c59369SXuan Hu  def getRfReadSrcIdx: Map[DataConfig, Seq[Int]] = {
27439c59369SXuan Hu    val dataCfgs = DataConfig.RegSrcDataSet
27539c59369SXuan Hu    val rfRdDataCfgSet = this.getRfReadDataCfgSet
27639c59369SXuan Hu    dataCfgs.toSeq.map { cfg =>
27739c59369SXuan Hu      (
27839c59369SXuan Hu        cfg,
27939c59369SXuan Hu        rfRdDataCfgSet.zipWithIndex.map { case (set, srcIdx) =>
28039c59369SXuan Hu          if (set.contains(cfg))
28139c59369SXuan Hu            Option(srcIdx)
28239c59369SXuan Hu          else
28339c59369SXuan Hu            None
28439c59369SXuan Hu        }.filter(_.nonEmpty).map(_.get)
28539c59369SXuan Hu      )
28639c59369SXuan Hu    }.toMap
28739c59369SXuan Hu  }
28839c59369SXuan Hu
289730cfbc0SXuan Hu  def genExuModule(implicit p: Parameters): ExeUnit = {
290730cfbc0SXuan Hu    new ExeUnit(this)
291730cfbc0SXuan Hu  }
292730cfbc0SXuan Hu
293730cfbc0SXuan Hu  def genExuInputBundle(implicit p: Parameters): ExuInput = {
294730cfbc0SXuan Hu    new ExuInput(this)
295730cfbc0SXuan Hu  }
296730cfbc0SXuan Hu
297730cfbc0SXuan Hu  def genExuOutputBundle(implicit p: Parameters): ExuOutput = {
298730cfbc0SXuan Hu    new ExuOutput(this)
299730cfbc0SXuan Hu  }
3005d2b9cadSXuan Hu
3015d2b9cadSXuan Hu  def genExuBypassBundle(implicit p: Parameters): ExuBypassBundle = {
3025d2b9cadSXuan Hu    new ExuBypassBundle(this)
3035d2b9cadSXuan Hu  }
304730cfbc0SXuan Hu}
305