xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuConfig.scala (revision 92b88f30156d46e844042eea94f7121557fd09a1)
1package xiangshan.backend.fu
2
3import chipsalliance.rocketchip.config.Parameters
4import chisel3._
5import xiangshan.ExceptionNO._
6import xiangshan.SelImm
7import xiangshan.backend.Std
8import xiangshan.backend.fu.fpu.{FDivSqrt, FMA, FPToFP, FPToInt, IntToFP}
9import xiangshan.backend.fu.wrapper.{Alu, BranchUnit, DivUnit, JumpUnit, MulUnit, VIAluFix, VIMacU, VSetRiWi, VSetRiWvf, VSetRvfWvf}
10import xiangshan.backend.Bundles.ExuInput
11import xiangshan.backend.datapath.DataConfig._
12
13/**
14  *
15  * @param name [[String]] name of fuConfig
16  * @param fuType [[Int]] type of func, select from [[xiangshan.backend.fu.FuType]]
17  * @param fuGen how to create $fu
18  * @param srcData type of src data used by this $fu
19  * @param piped if the $fu is pipelined
20  * @param maybeBlock the $fu need ready signal to block internal pipeline
21  * @param writeIntRf the $fu write int regfiles
22  * @param writeFpRf the $fu write float regfiles
23  * @param writeVecRf the $fu write vector regfiles
24  * @param writeFflags the $fu write fflags csr
25  * @param writeVxsat the $fu write vxsat csr
26  * @param dataBits the width of data in the $fu
27  * @param latency the latency of instuction executed in the $fu
28  * @param hasInputBuffer if the $fu has input buffer
29  * @param exceptionOut the $fu can produce these exception
30  * @param hasLoadError if the $fu has load error out
31  * @param flushPipe if the instuction executed in the $fu need flush out
32  * @param replayInst if the instuction executed in the $fu can replay in some condition
33  * @param trigger if the $fu need trigger out
34  * @param needSrcFrm if the $fu need float rounding mode signal
35  * @param immType the immediate type of this $fu
36  * @param vconfigWakeUp
37  * @param maskWakeUp
38  *
39  * @define fu function unit
40  */
41case class FuConfig (
42  name          : String,
43  fuType        : Int,
44  fuGen         : (Parameters, FuConfig) => FuncUnit,
45  srcData       : Seq[Seq[DataConfig]],
46  piped         : Boolean,
47  maybeBlock    : Boolean = false,
48  writeIntRf    : Boolean = false,
49  writeFpRf     : Boolean = false,
50  writeVecRf    : Boolean = false,
51  writeFflags   : Boolean = false,
52  writeVxsat    : Boolean = false,
53  dataBits      : Int = 64,
54  latency       : HasFuLatency = CertainLatency(0),
55  hasInputBuffer: (Boolean, Int, Boolean) = (false, 0, false),
56  exceptionOut  : Seq[Int] = Seq(),
57  hasLoadError  : Boolean = false,
58  flushPipe     : Boolean = false,
59  replayInst    : Boolean = false,
60  trigger       : Boolean = false,
61  needSrcFrm    : Boolean = false,
62  immType       : Set[UInt] = Set(),
63  // vector
64  vconfigWakeUp : Boolean = false,
65  maskWakeUp    : Boolean = false,
66) {
67  var vconfigIdx = -1
68  var maskSrcIdx = -1
69  if (vconfigWakeUp) {
70    vconfigIdx = getSpecialSrcIdx(VConfigData(), "when vconfigWakeUp is true, srcData must always contains VConfigData()")
71  }
72  if (maskWakeUp) {
73    maskSrcIdx = getSpecialSrcIdx(MaskSrcData(), "when maskWakeUp is true, srcData must always contains MaskSrcData()")
74  }
75
76  require(!piped || piped && latency.latencyVal.isDefined, "The latency value must be set when piped is enable")
77  require(!vconfigWakeUp || vconfigWakeUp && vconfigIdx >= 0, "The index of vl src must be set when vlWakeUp is enable")
78  require(!maskWakeUp || maskWakeUp && maskSrcIdx >= 0, "The index of mask src must be set when vlWakeUp is enable")
79
80  def numIntSrc : Int = srcData.map(_.count(x => IntRegSrcDataSet.contains(x))).max
81  def numFpSrc  : Int = srcData.map(_.count(x => FpRegSrcDataSet.contains(x))).max
82  def numVecSrc : Int = srcData.map(_.count(x => VecRegSrcDataSet.contains(x))).max
83  def numVfSrc  : Int = srcData.map(_.count(x => VfRegSrcDataSet.contains(x))).max
84  def numRegSrc : Int = srcData.map(_.count(x => RegSrcDataSet.contains(x))).max
85  def numSrc    : Int = srcData.map(_.length).max
86
87  def readFp: Boolean = numFpSrc > 0
88
89  def fuSel(uop: ExuInput): Bool = {
90    // Don't add more shit here!!!
91    // Todo: add new FuType to distinguish f2i, f2f
92    if (this.fuType == FuType.fmisc) {
93      this.name match {
94        case FuConfig.F2iCfg.name => uop.rfWen.get
95        case FuConfig.F2fCfg.name => uop.fpu.get.fpWen && !uop.fpu.get.div && !uop.fpu.get.sqrt
96      }
97    } else {
98      uop.fuType === this.fuType.U
99    }
100  }
101
102  /**
103    * params(i): data type set of the ith src port
104    * @return
105    */
106  def getRfReadDataCfgSet: Seq[Set[DataConfig]] = {
107    val numSrcMax = srcData.map(_.length).max
108    // make srcData is uniform sized to avoid exception when transpose
109    val alignedSrcData: Seq[Seq[DataConfig]] = srcData.map(x => x ++ Seq.fill(numSrcMax - x.length)(null))
110    alignedSrcData.transpose.map(_.toSet.intersect(RegSrcDataSet))
111  }
112
113  def getSrcDataType(srcIdx: Int): Set[DataConfig] = {
114    srcData
115      .map((x: Seq[DataConfig]) => if(x.isDefinedAt(srcIdx)) Some(x(srcIdx)) else None)
116      .filter(_.nonEmpty)
117      .map(_.get)
118      .toSet
119  }
120
121  def hasNoDataWB: Boolean = {
122    !(writeIntRf || writeFpRf || writeVecRf)
123  }
124
125  def getSrcMaxWidthVec = {
126    getRfReadDataCfgSet.map(_.map(_.dataWidth).max)
127  }
128
129  def genSrcDataVec: Seq[UInt] = {
130    getSrcMaxWidthVec.map(w => UInt(w.W))
131  }
132
133  // csr's redirect is in its exception bundle
134  def hasRedirect: Boolean = Seq(FuType.jmp, FuType.brh).contains(fuType)
135
136  def hasPredecode: Boolean = Seq(FuType.jmp, FuType.brh, FuType.csr).contains(fuType)
137
138  def needPc: Boolean = Seq(FuType.jmp, FuType.brh, FuType.csr, FuType.fence).contains(fuType)
139
140  def needFPUCtrl: Boolean = {
141    import FuType._
142    Set(fmac, fDivSqrt, fmisc, i2f).contains(fuType)
143  }
144
145  def needVecCtrl: Boolean = {
146    import FuType._
147    Set(vipu, vialuF, vimac, vfpu, vppu).contains(fuType)
148  }
149
150  def isMul: Boolean = fuType == FuType.mul
151
152  def isDiv: Boolean = fuType == FuType.div
153
154  def isCsr: Boolean = fuType == FuType.csr
155
156  def isFence: Boolean = fuType == FuType.fence
157
158  /**
159    * Get index of special src data, like [[VConfigData]], [[MaskSrcData]]
160    * @param data [[DataConfig]]
161    * @param tips tips if get failed
162    * @return the index of special src data
163    */
164  protected def getSpecialSrcIdx(data: DataConfig, tips: String): Int = {
165    val srcIdxVec = srcData.map(x => x.indexOf(data))
166    val idx0 = srcIdxVec.head
167    for (idx <- srcIdxVec) {
168      require(idx >= 0 && idx == idx0, tips + ", and at the same index.")
169    }
170    idx0
171  }
172
173  override def toString: String = {
174    var str = s"${this.name}: "
175    if (vconfigWakeUp) str += s"vconfigIdx($vconfigIdx), "
176    if (maskWakeUp) str += s"maskSrcIdx($maskSrcIdx), "
177    str += s"latency($latency)"
178    str
179  }
180}
181
182object FuConfig {
183  val JmpCfg: FuConfig = FuConfig (
184    name = "jmp",
185    fuType = FuType.jmp,
186    fuGen = (p: Parameters, cfg: FuConfig) => Module(new JumpUnit(cfg)(p)).suggestName("jmp"),
187    srcData = Seq(
188      Seq(IntData()), // jal
189    ),
190    piped = true,
191    writeIntRf = true,
192    immType = Set(SelImm.IMM_I, SelImm.IMM_UJ, SelImm.IMM_U),
193  )
194
195  val BrhCfg: FuConfig = FuConfig (
196    name = "brh",
197    fuType = FuType.brh,
198    fuGen = (p: Parameters, cfg: FuConfig) => Module(new BranchUnit(cfg)(p).suggestName("brh")),
199    srcData = Seq(
200      Seq(IntData(), IntData()),
201    ),
202    piped = true,
203    immType = Set(SelImm.IMM_SB),
204  )
205
206  val I2fCfg: FuConfig = FuConfig (
207    name = "i2f",
208    FuType.i2f,
209    fuGen = (p: Parameters, cfg: FuConfig) => Module(new IntToFP(cfg)(p).suggestName("i2f")),
210    srcData = Seq(
211      Seq(IntData()),
212    ),
213    piped = true,
214    writeFpRf = true,
215    writeFflags = true,
216    latency = CertainLatency(2),
217    needSrcFrm = true,
218  )
219
220  val CsrCfg: FuConfig = FuConfig (
221    name = "csr",
222    fuType = FuType.csr,
223    fuGen = (p: Parameters, cfg: FuConfig) => Module(new CSR(cfg)(p).suggestName("csr")),
224    srcData = Seq(
225      Seq(IntData()),
226    ),
227    piped = true,
228    writeIntRf = true,
229    exceptionOut = Seq(illegalInstr, breakPoint, ecallU, ecallS, ecallM),
230    flushPipe = true,
231  )
232
233  val AluCfg: FuConfig = FuConfig (
234    name = "alu",
235    fuType = FuType.alu,
236    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Alu(cfg)(p).suggestName("Alu")),
237    srcData = Seq(
238      Seq(IntData(), IntData()),
239    ),
240    piped = true,
241    writeIntRf = true,
242    immType = Set(SelImm.IMM_I, SelImm.IMM_U),
243  )
244
245  val MulCfg: FuConfig = FuConfig (
246    name = "mul",
247    fuType = FuType.mul,
248    fuGen = (p: Parameters, cfg: FuConfig) => Module(new MulUnit(cfg)(p).suggestName("Mul")),
249    srcData = Seq(
250      Seq(IntData(), IntData()),
251    ),
252    piped = true,
253    writeIntRf = true,
254    latency = CertainLatency(2),
255  )
256
257  val DivCfg: FuConfig = FuConfig (
258    name = "div",
259    fuType = FuType.div,
260    fuGen = (p: Parameters, cfg: FuConfig) => Module(new DivUnit(cfg)(p).suggestName("Div")),
261    srcData = Seq(
262      Seq(IntData(), IntData()),
263    ),
264    piped = false,
265    writeIntRf = true,
266    latency = UncertainLatency(),
267    hasInputBuffer = (true, 4, true)
268  )
269
270  val FenceCfg: FuConfig = FuConfig (
271    name = "fence",
272    FuType.fence,
273    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Fence(cfg)(p).suggestName("Fence")),
274    srcData = Seq(
275      Seq(IntData(), IntData()),
276    ),
277    piped = true,
278    latency = CertainLatency(0),
279    exceptionOut = Seq(illegalInstr),
280    flushPipe = true
281  )
282
283  // Todo: split it to simple bitmap exu and complex bku
284  val BkuCfg: FuConfig = FuConfig (
285    name = "bku",
286    fuType = FuType.bku,
287    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Bku(cfg)(p).suggestName("Bku")),
288    srcData = Seq(
289      Seq(IntData(), IntData()),
290    ),
291    piped = true,
292    writeIntRf = true,
293    latency = CertainLatency(2),
294  )
295
296  val VSetRvfWvfCfg: FuConfig = FuConfig(
297    name = "vsetrvfwvf",
298    fuType = FuType.vsetiwf,
299    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRvfWvf(cfg)(p).suggestName("VSetRvfWvf")),
300    srcData = Seq(
301      Seq(FpData(), FpData()),
302    ),
303    piped = true,
304    writeVecRf = true,
305    latency = CertainLatency(0),
306    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
307  )
308
309  val VSetRiWvfCfg: FuConfig = FuConfig(
310    name = "vsetriwvf",
311    fuType = FuType.vsetiwf,
312    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWvf(cfg)(p).suggestName("VSetRiWvf")),
313    srcData = Seq(
314      Seq(IntData(), IntData()),
315    ),
316    piped = true,
317    writeVecRf = true,
318    latency = CertainLatency(0),
319    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
320  )
321
322  val VSetRiWiCfg: FuConfig = FuConfig(
323    name = "vsetriwi",
324    fuType = FuType.vsetiwi,
325    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWi(cfg)(p).suggestName("VSetRiWi")),
326    srcData = Seq(
327      Seq(IntData(), IntData()),
328    ),
329    piped = true,
330    writeIntRf = true,
331    latency = CertainLatency(0),
332    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
333  )
334
335  val FmacCfg: FuConfig = FuConfig (
336    name = "fmac",
337    fuType = FuType.fmac,
338    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FMA(cfg)(p).suggestName("FMac")),
339    srcData = Seq(
340      Seq(FpData(), FpData()),
341      Seq(FpData(), FpData(), FpData()),
342    ),
343    piped = false,
344    writeFpRf = true,
345    writeFflags = true,
346    latency = UncertainLatency(),
347    needSrcFrm = true,
348  )
349
350  val F2iCfg: FuConfig = FuConfig (
351    name = "f2i",
352    fuType = FuType.fmisc,
353    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToInt(cfg)(p).suggestName("F2i")),
354    srcData = Seq(
355      Seq(FpData(), FpData()),
356      Seq(FpData()),
357    ),
358    piped = true,
359    writeIntRf = true,
360    writeFflags = true,
361    latency = CertainLatency(2),
362    needSrcFrm = true,
363  )
364
365  val F2fCfg: FuConfig = FuConfig (
366    name = "f2f",
367    fuType = FuType.fmisc,
368    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToFP(cfg)(p).suggestName("F2f")),
369    srcData = Seq(
370      Seq(FpData(), FpData()),
371      Seq(FpData()),
372    ),
373    piped = true,
374    writeFpRf = true,
375    writeFflags = true,
376    latency = CertainLatency(2),
377    needSrcFrm = true,
378  )
379
380  val FDivSqrtCfg: FuConfig = FuConfig (
381    name = "fDivSqrt",
382    fuType = FuType.fDivSqrt,
383    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FDivSqrt(cfg)(p).suggestName("FDivSqrt")),
384    srcData = Seq(
385      Seq(FpData(), FpData()),
386    ),
387    piped = false,
388    writeFpRf = true,
389    writeFflags = true,
390    latency = UncertainLatency(),
391    hasInputBuffer = (true, 8, true),
392    needSrcFrm = true,
393  )
394
395  val LduCfg: FuConfig = FuConfig (
396    name = "ldu",
397    fuType = FuType.ldu,
398    fuGen = null, // Todo
399    srcData = Seq(
400      Seq(IntData()),
401    ),
402    piped = false, // Todo: check it
403    writeIntRf = true,
404    writeFpRf = true,
405    latency = UncertainLatency(),
406    exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault),
407    flushPipe = true,
408    replayInst = true,
409    hasLoadError = true,
410    immType = Set(SelImm.IMM_I),
411  )
412
413  val StaCfg: FuConfig = FuConfig (
414    name = "sta",
415    fuType = FuType.stu,
416    fuGen = null, // Todo
417    srcData = Seq(
418      Seq(IntData()),
419    ),
420    piped = false,
421    latency = UncertainLatency(),
422    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault),
423    immType = Set(SelImm.IMM_S),
424  )
425
426  val StdCfg: FuConfig = FuConfig (
427    name = "std",
428    fuType = FuType.stu,
429    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Std(cfg)(p).suggestName("Std")),
430    srcData = Seq(
431      Seq(IntData()),
432      Seq(FpData()),
433    ),
434    piped = true,
435    latency = CertainLatency(0),
436    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault)
437  )
438
439  val MouCfg: FuConfig = FuConfig (
440    name = "mou",
441    fuType = FuType.mou,
442    fuGen = null, // Todo
443    srcData = Seq(
444      Seq(IntData()),
445    ),
446    piped = false, // Todo: check it
447    writeIntRf = true,
448    latency = UncertainLatency(),
449    exceptionOut = (LduCfg.exceptionOut ++ StaCfg.exceptionOut ++ StdCfg.exceptionOut).distinct
450  )
451
452  val MoudCfg: FuConfig = FuConfig (
453    name = "moud",
454    fuType = FuType.mou,
455    fuGen = null, // Todo
456    srcData = Seq(
457      Seq(IntData()),
458    ),
459    piped = true,
460    latency = CertainLatency(0),
461  )
462
463  val VialuCfg = FuConfig (
464    name = "vialuFix",
465    fuType = FuType.vialuF,
466    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VIAluFix(cfg)(p).suggestName("VialuFix")),
467    srcData = Seq(
468      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0, vtype&vl
469    ),
470    piped = true,
471    writeVecRf = true,
472    writeVxsat = true,
473    latency = CertainLatency(1),
474    vconfigWakeUp = true,
475    maskWakeUp = true,
476    dataBits = 128,
477    immType = Set(SelImm.IMM_OPIVIU, SelImm.IMM_OPIVIS),
478  )
479
480  val VimacCfg = FuConfig (
481    name = "vimac",
482    fuType = FuType.vimac,
483    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VIMacU(cfg)(p).suggestName("Vimac")),
484    srcData = Seq(
485      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()), // vs1, vs2, vd_old, v0, vtype&vl
486    ),
487    piped = true,
488    writeVecRf = true,
489    writeVxsat = true,
490    latency = CertainLatency(2),
491    vconfigWakeUp = true,
492    maskWakeUp = true,
493    dataBits = 128,
494  )
495
496  val VipuCfg: FuConfig = FuConfig (
497    name = "vipu",
498    fuType = FuType.vipu,
499    fuGen = null, // Todo
500    srcData = Seq(
501      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
502    ),
503    piped = false,
504    writeVecRf = true,
505    latency = UncertainLatency(),
506  )
507
508  val VfpuCfg: FuConfig = FuConfig (
509    name = "vfpu",
510    fuType = FuType.vfpu,
511    fuGen = null, // Todo
512    srcData = Seq(
513      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
514      Seq(FpData(), VecData(), VecData(), MaskSrcData(), VConfigData()),   // f[rs1], vs2, vd_old, v0
515    ),
516    piped = false,
517    writeVecRf = true,
518    latency = UncertainLatency(),
519  )
520
521  val VlduCfg: FuConfig = FuConfig (
522    name = "vldu",
523    fuType = FuType.vldu,
524    fuGen = null,
525    srcData = Seq(
526      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  //vs1, vs2, vd_old, v0, vconfig
527    ),
528    piped = false, // Todo: check it
529    writeVecRf = true,
530    latency = UncertainLatency(),
531    exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault),
532    flushPipe = true,
533    replayInst = true,
534    hasLoadError = true,
535    vconfigWakeUp = true,
536    maskWakeUp = true,
537    dataBits = 128,
538  )
539  //TODO
540  // def VstuCfg = FuConfig ()
541
542  def allConfigs = Seq(
543    JmpCfg, BrhCfg, I2fCfg, CsrCfg, AluCfg, MulCfg, DivCfg, FenceCfg, BkuCfg, VSetRvfWvfCfg, VSetRiWvfCfg, VSetRiWiCfg,
544    FmacCfg, F2iCfg, F2fCfg, FDivSqrtCfg, LduCfg, StaCfg, StdCfg, MouCfg, MoudCfg, VialuCfg, VipuCfg, VfpuCfg, VlduCfg
545  )
546
547  def VecArithFuConfigs = Seq(
548    VialuCfg, VimacCfg, VipuCfg, VfpuCfg
549  )
550}
551
552