xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuConfig.scala (revision 98639abb5c84bb635ff36399547e03aacb7bc2f4)
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, 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 maybeBlock the $fu need ready signal to block internal pipeline
20  * @param writeIntRf the $fu write int regfiles
21  * @param writeFpRf the $fu write float regfiles
22  * @param writeVecRf the $fu write vector regfiles
23  * @param writeFflags the $fu write fflags csr
24  * @param writeVxsat the $fu write vxsat csr
25  * @param dataBits the width of data in the $fu
26  * @param piped if the $fu is pipelined
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  maybeBlock    : Boolean = false,
47  writeIntRf    : Boolean = false,
48  writeFpRf     : Boolean = false,
49  writeVecRf    : Boolean = false,
50  writeFflags   : Boolean = false,
51  writeVxsat    : Boolean = false,
52  dataBits      : Int = 64,
53  piped         : Boolean = false,
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, 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
174object FuConfig {
175  val JmpCfg: FuConfig = FuConfig (
176    name = "jmp",
177    fuType = FuType.jmp,
178    fuGen = (p: Parameters, cfg: FuConfig) => Module(new JumpUnit(cfg)(p)).suggestName("jmp"),
179    srcData = Seq(
180      Seq(IntData()), // jal
181    ),
182    writeIntRf = true,
183    writeFpRf = false,
184    immType = Set(SelImm.IMM_I, SelImm.IMM_UJ, SelImm.IMM_U),
185  )
186
187  val BrhCfg: FuConfig = FuConfig (
188    name = "brh",
189    fuType = FuType.brh,
190    fuGen = (p: Parameters, cfg: FuConfig) => Module(new BranchUnit(cfg)(p).suggestName("brh")),
191    srcData = Seq(
192      Seq(IntData(), IntData()),
193    ),
194    writeIntRf = false,
195    writeFpRf = false,
196    immType = Set(SelImm.IMM_SB),
197  )
198
199  val I2fCfg: FuConfig = FuConfig (
200    name = "i2f",
201    FuType.i2f,
202    fuGen = (p: Parameters, cfg: FuConfig) => Module(new IntToFP(cfg)(p).suggestName("i2f")),
203    srcData = Seq(
204      Seq(IntData()),
205    ),
206    writeIntRf = false,
207    writeFpRf = true,
208    writeFflags = true,
209    latency = CertainLatency(2),
210    needSrcFrm = true,
211  )
212
213  val CsrCfg: FuConfig = FuConfig (
214    name = "csr",
215    fuType = FuType.csr,
216    fuGen = (p: Parameters, cfg: FuConfig) => Module(new CSR(cfg)(p).suggestName("csr")),
217    srcData = Seq(
218      Seq(IntData()),
219    ),
220    writeIntRf = true,
221    writeFpRf = false,
222    exceptionOut = Seq(illegalInstr, breakPoint, ecallU, ecallS, ecallM),
223    flushPipe = true
224  )
225
226  val AluCfg: FuConfig = FuConfig (
227    name = "alu",
228    fuType = FuType.alu,
229    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Alu(cfg)(p).suggestName("Alu")),
230    srcData = Seq(
231      Seq(IntData(), IntData()),
232    ),
233    writeIntRf = true,
234    writeFpRf = false,
235    immType = Set(SelImm.IMM_I, SelImm.IMM_U),
236  )
237
238  val MulCfg: FuConfig = FuConfig (
239    name = "mul",
240    fuType = FuType.mul,
241    fuGen = (p: Parameters, cfg: FuConfig) => Module(new MulUnit(cfg)(p).suggestName("Mul")),
242    srcData = Seq(
243      Seq(IntData(), IntData()),
244    ),
245    writeIntRf = true,
246    writeFpRf = false,
247    latency = CertainLatency(2),
248  )
249
250  val DivCfg: FuConfig = FuConfig (
251    name = "div",
252    fuType = FuType.div,
253    fuGen = (p: Parameters, cfg: FuConfig) => Module(new DivUnit(cfg)(p).suggestName("Div")),
254    srcData = Seq(
255      Seq(IntData(), IntData()),
256    ),
257    writeIntRf = true,
258    writeFpRf = false,
259    latency = UncertainLatency(),
260    hasInputBuffer = (true, 4, true)
261  )
262
263  val FenceCfg: FuConfig = FuConfig (
264    name = "fence",
265    FuType.fence,
266    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Fence(cfg)(p).suggestName("Fence")),
267    srcData = Seq(
268      Seq(IntData(), IntData()),
269    ),
270    writeIntRf = false,
271    writeFpRf = false,
272    latency = UncertainLatency(),
273    exceptionOut = Seq(illegalInstr),
274    flushPipe = true
275  )
276
277  // Todo: split it to simple bitmap exu and complex bku
278  val BkuCfg: FuConfig = FuConfig (
279    name = "bku",
280    fuType = FuType.bku,
281    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Bku(cfg)(p).suggestName("Bku")),
282    srcData = Seq(
283      Seq(IntData(), IntData()),
284    ),
285    writeIntRf = true,
286    writeFpRf = false,
287    latency = CertainLatency(1),
288  )
289
290  val VSetRvfWvfCfg: FuConfig = FuConfig(
291    name = "vsetrvfwvf",
292    fuType = FuType.vsetiwf,
293    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRvfWvf(cfg)(p).suggestName("VSetRvfWvf")),
294    srcData = Seq(
295      Seq(FpData(), FpData()),
296    ),
297    writeIntRf = false,
298    writeFpRf = false,
299    writeVecRf = true,
300    latency = CertainLatency(0),
301    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
302  )
303
304  val VSetRiWvfCfg: FuConfig = FuConfig(
305    name = "vsetriwvf",
306    fuType = FuType.vsetiwf,
307    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWvf(cfg)(p).suggestName("VSetRiWvf")),
308    srcData = Seq(
309      Seq(IntData(), IntData()),
310    ),
311    writeIntRf = false,
312    writeFpRf = false,
313    writeVecRf = true,
314    latency = CertainLatency(0),
315    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
316  )
317
318  val VSetRiWiCfg: FuConfig = FuConfig(
319    name = "vsetriwi",
320    fuType = FuType.vsetiwi,
321    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWi(cfg)(p).suggestName("VSetRiWi")),
322    srcData = Seq(
323      Seq(IntData(), IntData()),
324    ),
325    writeIntRf = true,
326    writeFpRf = false,
327    latency = CertainLatency(0),
328    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
329  )
330
331  val FmacCfg: FuConfig = FuConfig (
332    name = "fmac",
333    fuType = FuType.fmac,
334    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FMA(cfg)(p).suggestName("FMac")),
335    srcData = Seq(
336      Seq(FpData(), FpData()),
337      Seq(FpData(), FpData(), FpData()),
338    ),
339    writeIntRf = false,
340    writeFpRf = true,
341    writeFflags = true,
342    latency = UncertainLatency(),
343    needSrcFrm = true,
344  )
345
346  val F2iCfg: FuConfig = FuConfig (
347    name = "f2i",
348    fuType = FuType.fmisc,
349    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToInt(cfg)(p).suggestName("F2i")),
350    srcData = Seq(
351      Seq(FpData(), FpData()),
352      Seq(FpData()),
353    ),
354    writeIntRf = true,
355    writeFpRf = false,
356    writeFflags = true,
357    latency = CertainLatency(2),
358    needSrcFrm = true,
359  )
360
361  val F2fCfg: FuConfig = FuConfig (
362    name = "f2f",
363    fuType = FuType.fmisc,
364    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToFP(cfg)(p).suggestName("F2f")),
365    srcData = Seq(
366      Seq(FpData(), FpData()),
367      Seq(FpData()),
368    ),
369    writeIntRf = false,
370    writeFpRf = true,
371    writeFflags = true,
372    latency = CertainLatency(2),
373    needSrcFrm = true,
374  )
375
376  val FDivSqrtCfg: FuConfig = FuConfig (
377    name = "fDivSqrt",
378    fuType = FuType.fDivSqrt,
379    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FDivSqrt(cfg)(p).suggestName("FDivSqrt")),
380    srcData = Seq(
381      Seq(FpData(), FpData()),
382    ),
383    writeIntRf = false,
384    writeFpRf = true,
385    writeFflags = true,
386    latency = UncertainLatency(),
387    hasInputBuffer = (true, 8, true),
388    needSrcFrm = true,
389  )
390
391  val LduCfg: FuConfig = FuConfig (
392    name = "ldu",
393    fuType = FuType.ldu,
394    fuGen = null, // Todo
395    srcData = Seq(
396      Seq(IntData()),
397    ),
398    writeIntRf = true,
399    writeFpRf = true,
400    latency = UncertainLatency(),
401    exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault),
402    flushPipe = true,
403    replayInst = true,
404    hasLoadError = true,
405    immType = Set(SelImm.IMM_I),
406  )
407
408  val StaCfg: FuConfig = FuConfig (
409    name = "sta",
410    fuType = FuType.stu,
411    fuGen = null, // Todo
412    srcData = Seq(
413      Seq(IntData()),
414    ),
415    writeIntRf = false,
416    writeFpRf = false,
417    latency = UncertainLatency(),
418    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault),
419    immType = Set(SelImm.IMM_S),
420  )
421
422  val StdCfg: FuConfig = FuConfig (
423    name = "std",
424    fuType = FuType.stu,
425    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Std(cfg)(p).suggestName("Std")),
426    srcData = Seq(
427      Seq(IntData()),
428      Seq(FpData()),
429    ),
430    writeIntRf = false,
431    writeFpRf = false,
432    latency = CertainLatency(1),
433    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault)
434  )
435
436  val MouCfg: FuConfig = FuConfig (
437    name = "mou",
438    fuType = FuType.mou,
439    fuGen = null, // Todo
440    srcData = Seq(
441      Seq(IntData()),
442    ),
443    writeIntRf = true,
444    writeFpRf = false,
445    latency = UncertainLatency(),
446    exceptionOut = (LduCfg.exceptionOut ++ StaCfg.exceptionOut ++ StdCfg.exceptionOut).distinct
447  )
448
449  val MoudCfg: FuConfig = FuConfig (
450    name = "moud",
451    fuType = FuType.mou,
452    fuGen = null, // Todo
453    srcData = Seq(
454      Seq(IntData()),
455    ),
456    writeIntRf = false,
457    writeFpRf = false,
458    latency = UncertainLatency()
459  )
460
461  val VialuCfg = FuConfig (
462    name = "vialu",
463    fuType = FuType.vialuF,
464    fuGen = null,
465    srcData = Seq(
466      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0, vtype&vl
467    ),
468    writeVecRf = true,
469    latency = CertainLatency(1),
470  )
471
472  val VipuCfg: FuConfig = FuConfig (
473    name = "vipu",
474    fuType = FuType.vipu,
475    fuGen = null, // Todo
476    srcData = Seq(
477      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
478    ),
479    writeIntRf = false,
480    writeFpRf = false,
481    writeVecRf = true,
482    latency = UncertainLatency(),
483  )
484
485  val VfpuCfg: FuConfig = FuConfig (
486    name = "vfpu",
487    fuType = FuType.vfpu,
488    fuGen = null, // Todo
489    srcData = Seq(
490      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
491      Seq(FpData(), VecData(), VecData(), MaskSrcData(), VConfigData()),   // f[rs1], vs2, vd_old, v0
492    ),
493    writeIntRf = false,
494    writeFpRf = false,
495    writeVecRf = true,
496    latency = UncertainLatency(),
497  )
498  // Todo
499  // def VlduCfg = FuConfig ()
500  // def VstuCfg = FuConfig ()
501
502}
503
504