xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuConfig.scala (revision 3f6c8c2c7f193660d0823208dbcd36d7cec65f50)
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
13case class FuConfig (
14  name: String,
15  fuType: Int,
16  fuGen: (Parameters, FuConfig) => FuncUnit,
17  srcData: Seq[Seq[DataConfig]],
18  writeIntRf: Boolean = false,
19  writeFpRf: Boolean = false,
20  writeVecRf: Boolean = false,
21  writeFflags: Boolean = false,
22  writeVxsat: Boolean = false,
23  dataBits: Int = 64,
24  latency: HasFuLatency = CertainLatency(0),
25  hasInputBuffer: (Boolean, Int, Boolean) = (false, 0, false),
26  exceptionOut: Seq[Int] = Seq(),
27  hasLoadError: Boolean = false,
28  flushPipe: Boolean = false,
29  replayInst: Boolean = false,
30  trigger: Boolean = false,
31  needSrcFrm: Boolean = false,
32  immType: Set[UInt] = Set(),
33) {
34  def numIntSrc : Int = srcData.map(_.count(x => IntRegSrcDataSet.contains(x))).max
35  def numFpSrc  : Int = srcData.map(_.count(x => FpRegSrcDataSet.contains(x))).max
36  def numVecSrc : Int = srcData.map(_.count(x => VecRegSrcDataSet.contains(x))).max
37  def numVfSrc  : Int = srcData.map(_.count(x => VfRegSrcDataSet.contains(x))).max
38  def numRegSrc : Int = srcData.map(_.count(x => RegSrcDataSet.contains(x))).max
39  def numSrc    : Int = srcData.map(_.length).max
40
41  def readFp: Boolean = numFpSrc > 0
42
43  def fuSel(uop: ExuInput): Bool = {
44    // Don't add more shit here!!!
45    // Todo: add new FuType to distinguish f2i, f2f
46    if (this.fuType == FuType.fmisc) {
47      this.name match {
48        case FuConfig.F2iCfg.name => uop.rfWen.get
49        case FuConfig.F2fCfg.name => uop.fpu.get.fpWen && !uop.fpu.get.div && !uop.fpu.get.sqrt
50      }
51    } else {
52      uop.fuType === this.fuType.U
53    }
54  }
55
56  /**
57    * params(i): data type set of the ith src port
58    * @return
59    */
60  def getRfReadDataCfgSet: Seq[Set[DataConfig]] = {
61    val numSrcMax = srcData.map(_.length).max
62    // make srcData is uniform sized to avoid exception when transpose
63    val alignedSrcData: Seq[Seq[DataConfig]] = srcData.map(x => x ++ Seq.fill(numSrcMax - x.length)(null))
64    alignedSrcData.transpose.map(_.toSet.intersect(RegSrcDataSet))
65  }
66
67  def getSrcDataType(srcIdx: Int): Set[DataConfig] = {
68    srcData
69      .map((x: Seq[DataConfig]) => if(x.isDefinedAt(srcIdx)) Some(x(srcIdx)) else None)
70      .filter(_.nonEmpty)
71      .map(_.get)
72      .toSet
73  }
74
75  def hasNoDataWB: Boolean = {
76    !(writeIntRf || writeFpRf || writeVecRf)
77  }
78
79  def getSrcMaxWidthVec = {
80    getRfReadDataCfgSet.map(_.map(_.dataWidth).max)
81  }
82
83  def genSrcDataVec: Seq[UInt] = {
84    getSrcMaxWidthVec.map(w => UInt(w.W))
85  }
86
87  // csr's redirect is in its exception bundle
88  def hasRedirect: Boolean = Seq(FuType.jmp, FuType.brh).contains(fuType)
89
90  def hasPredecode: Boolean = Seq(FuType.jmp, FuType.brh, FuType.csr).contains(fuType)
91
92  def needPc: Boolean = Seq(FuType.jmp, FuType.brh, FuType.csr, FuType.fence).contains(fuType)
93
94  def needFPUCtrl: Boolean = {
95    import FuType._
96    Set(fmac, fDivSqrt, fmisc, i2f).contains(fuType)
97  }
98
99  def needVecCtrl: Boolean = {
100    import FuType._
101    Set(vipu, vialuF, vfpu, vppu).contains(fuType)
102  }
103
104  def isMul: Boolean = fuType == FuType.mul
105
106  def isDiv: Boolean = fuType == FuType.div
107
108  def isCsr: Boolean = fuType == FuType.csr
109
110  def isFence: Boolean = fuType == FuType.fence
111}
112
113object FuConfig {
114  val JmpCfg: FuConfig = FuConfig (
115    name = "jmp",
116    fuType = FuType.jmp,
117    fuGen = (p: Parameters, cfg: FuConfig) => Module(new JumpUnit(cfg)(p)).suggestName("jmp"),
118    srcData = Seq(
119      Seq(IntData()), // jal
120    ),
121    writeIntRf = true,
122    writeFpRf = false,
123    immType = Set(SelImm.IMM_I, SelImm.IMM_UJ, SelImm.IMM_U),
124  )
125
126  val BrhCfg: FuConfig = FuConfig (
127    name = "brh",
128    fuType = FuType.brh,
129    fuGen = (p: Parameters, cfg: FuConfig) => Module(new BranchUnit(cfg)(p).suggestName("brh")),
130    srcData = Seq(
131      Seq(IntData(), IntData()),
132    ),
133    writeIntRf = false,
134    writeFpRf = false,
135    immType = Set(SelImm.IMM_SB),
136  )
137
138  val I2fCfg: FuConfig = FuConfig (
139    name = "i2f",
140    FuType.i2f,
141    fuGen = (p: Parameters, cfg: FuConfig) => Module(new IntToFP(cfg)(p).suggestName("i2f")),
142    srcData = Seq(
143      Seq(IntData()),
144    ),
145    writeIntRf = false,
146    writeFpRf = true,
147    writeFflags = true,
148    latency = CertainLatency(2),
149    needSrcFrm = true,
150  )
151
152  val CsrCfg: FuConfig = FuConfig (
153    name = "csr",
154    fuType = FuType.csr,
155    fuGen = (p: Parameters, cfg: FuConfig) => Module(new CSR(cfg)(p).suggestName("csr")),
156    srcData = Seq(
157      Seq(IntData()),
158    ),
159    writeIntRf = true,
160    writeFpRf = false,
161    exceptionOut = Seq(illegalInstr, breakPoint, ecallU, ecallS, ecallM),
162    flushPipe = true
163  )
164
165  val AluCfg: FuConfig = FuConfig (
166    name = "alu",
167    fuType = FuType.alu,
168    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Alu(cfg)(p).suggestName("Alu")),
169    srcData = Seq(
170      Seq(IntData(), IntData()),
171    ),
172    writeIntRf = true,
173    writeFpRf = false,
174    immType = Set(SelImm.IMM_I, SelImm.IMM_U),
175  )
176
177  val MulCfg: FuConfig = FuConfig (
178    name = "mul",
179    fuType = FuType.mul,
180    fuGen = (p: Parameters, cfg: FuConfig) => Module(new MulUnit(cfg)(p).suggestName("Mul")),
181    srcData = Seq(
182      Seq(IntData(), IntData()),
183    ),
184    writeIntRf = true,
185    writeFpRf = false,
186    latency = CertainLatency(2),
187  )
188
189  val DivCfg: FuConfig = FuConfig (
190    name = "div",
191    fuType = FuType.div,
192    fuGen = (p: Parameters, cfg: FuConfig) => Module(new DivUnit(cfg)(p).suggestName("Div")),
193    srcData = Seq(
194      Seq(IntData(), IntData()),
195    ),
196    writeIntRf = true,
197    writeFpRf = false,
198    latency = UncertainLatency(),
199    hasInputBuffer = (true, 4, true)
200  )
201
202  val FenceCfg: FuConfig = FuConfig (
203    name = "fence",
204    FuType.fence,
205    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Fence(cfg)(p).suggestName("Fence")),
206    srcData = Seq(
207      Seq(IntData(), IntData()),
208    ),
209    writeIntRf = false,
210    writeFpRf = false,
211    latency = UncertainLatency(),
212    exceptionOut = Seq(illegalInstr),
213    flushPipe = true
214  )
215
216  // Todo: split it to simple bitmap exu and complex bku
217  val BkuCfg: FuConfig = FuConfig (
218    name = "bku",
219    fuType = FuType.bku,
220    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Bku(cfg)(p).suggestName("Bku")),
221    srcData = Seq(
222      Seq(IntData(), IntData()),
223    ),
224    writeIntRf = true,
225    writeFpRf = false,
226    latency = CertainLatency(1),
227  )
228
229  val VSetRvfWvfCfg: FuConfig = FuConfig(
230    name = "vsetrvfwvf",
231    fuType = FuType.vsetiwf,
232    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRvfWvf(cfg)(p).suggestName("VSetRvfWvf")),
233    srcData = Seq(
234      Seq(FpData(), FpData()),
235    ),
236    writeIntRf = false,
237    writeFpRf = false,
238    writeVecRf = true,
239    latency = CertainLatency(0),
240    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
241  )
242
243  val VSetRiWvfCfg: FuConfig = FuConfig(
244    name = "vsetriwvf",
245    fuType = FuType.vsetiwf,
246    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWvf(cfg)(p).suggestName("VSetRiWvf")),
247    srcData = Seq(
248      Seq(IntData(), IntData()),
249    ),
250    writeIntRf = false,
251    writeFpRf = false,
252    writeVecRf = true,
253    latency = CertainLatency(0),
254    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
255  )
256
257  val VSetRiWiCfg: FuConfig = FuConfig(
258    name = "vsetriwi",
259    fuType = FuType.vsetiwi,
260    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWi(cfg)(p).suggestName("VSetRiWi")),
261    srcData = Seq(
262      Seq(IntData(), IntData()),
263    ),
264    writeIntRf = true,
265    writeFpRf = false,
266    latency = CertainLatency(0),
267    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
268  )
269
270  val FmacCfg: FuConfig = FuConfig (
271    name = "fmac",
272    fuType = FuType.fmac,
273    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FMA(cfg)(p).suggestName("FMac")),
274    srcData = Seq(
275      Seq(FpData(), FpData()),
276      Seq(FpData(), FpData(), FpData()),
277    ),
278    writeIntRf = false,
279    writeFpRf = true,
280    writeFflags = true,
281    latency = UncertainLatency(),
282    needSrcFrm = true,
283  )
284
285  val F2iCfg: FuConfig = FuConfig (
286    name = "f2i",
287    fuType = FuType.fmisc,
288    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToInt(cfg)(p).suggestName("F2i")),
289    srcData = Seq(
290      Seq(FpData(), FpData()),
291      Seq(FpData()),
292    ),
293    writeIntRf = true,
294    writeFpRf = false,
295    writeFflags = true,
296    latency = CertainLatency(2),
297    needSrcFrm = true,
298  )
299
300  val F2fCfg: FuConfig = FuConfig (
301    name = "f2f",
302    fuType = FuType.fmisc,
303    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToFP(cfg)(p).suggestName("F2f")),
304    srcData = Seq(
305      Seq(FpData(), FpData()),
306      Seq(FpData()),
307    ),
308    writeIntRf = false,
309    writeFpRf = true,
310    writeFflags = true,
311    latency = CertainLatency(2),
312    needSrcFrm = true,
313  )
314
315  val FDivSqrtCfg: FuConfig = FuConfig (
316    name = "fDivSqrt",
317    fuType = FuType.fDivSqrt,
318    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FDivSqrt(cfg)(p).suggestName("FDivSqrt")),
319    srcData = Seq(
320      Seq(FpData(), FpData()),
321    ),
322    writeIntRf = false,
323    writeFpRf = true,
324    writeFflags = true,
325    latency = UncertainLatency(),
326    hasInputBuffer = (true, 8, true),
327    needSrcFrm = true,
328  )
329
330  val LduCfg: FuConfig = FuConfig (
331    name = "ldu",
332    fuType = FuType.ldu,
333    fuGen = null, // Todo
334    srcData = Seq(
335      Seq(IntData()),
336    ),
337    writeIntRf = true,
338    writeFpRf = true,
339    latency = UncertainLatency(),
340    exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault),
341    flushPipe = true,
342    replayInst = true,
343    hasLoadError = true,
344    immType = Set(SelImm.IMM_I),
345  )
346
347  val StaCfg: FuConfig = FuConfig (
348    name = "sta",
349    fuType = FuType.stu,
350    fuGen = null, // Todo
351    srcData = Seq(
352      Seq(IntData()),
353    ),
354    writeIntRf = false,
355    writeFpRf = false,
356    latency = UncertainLatency(),
357    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault),
358    immType = Set(SelImm.IMM_S),
359  )
360
361  val StdCfg: FuConfig = FuConfig (
362    name = "std",
363    fuType = FuType.stu,
364    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Std(cfg)(p).suggestName("Std")),
365    srcData = Seq(
366      Seq(IntData()),
367      Seq(FpData()),
368    ),
369    writeIntRf = false,
370    writeFpRf = false,
371    latency = CertainLatency(1),
372    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault)
373  )
374
375  val MouCfg: FuConfig = FuConfig (
376    name = "mou",
377    fuType = FuType.mou,
378    fuGen = null, // Todo
379    srcData = Seq(
380      Seq(IntData()),
381    ),
382    writeIntRf = true,
383    writeFpRf = false,
384    latency = UncertainLatency(),
385    exceptionOut = (LduCfg.exceptionOut ++ StaCfg.exceptionOut ++ StdCfg.exceptionOut).distinct
386  )
387
388  val MoudCfg: FuConfig = FuConfig (
389    name = "moud",
390    fuType = FuType.mou,
391    fuGen = null, // Todo
392    srcData = Seq(
393      Seq(IntData()),
394    ),
395    writeIntRf = false,
396    writeFpRf = false,
397    latency = UncertainLatency()
398  )
399
400  val Vialu = FuConfig (
401    name = "vialu",
402    fuType = FuType.vialuF,
403    fuGen = null,
404    srcData = Seq(
405      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0, vtype&vl
406    ),
407    writeVecRf = true,
408    latency = CertainLatency(1),
409  )
410
411  val VipuCfg: FuConfig = FuConfig (
412    name = "vipu",
413    fuType = FuType.vipu,
414    fuGen = null, // Todo
415    srcData = Seq(
416      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
417      Seq(VecData(), VecData(), VecData(), VecData(), VConfigData()),      // vs1_1, vs2, vs1_2, vs2_2 // no mask and vta
418    ),
419    writeIntRf = false,
420    writeFpRf = false,
421    writeVecRf = true,
422    latency = UncertainLatency(),
423  )
424
425  val VfpuCfg: FuConfig = FuConfig (
426    name = "vfpu",
427    fuType = FuType.vfpu,
428    fuGen = null, // Todo
429    srcData = Seq(
430      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
431      Seq(VecData(), VecData(), VecData(), VecData(), VConfigData()),      // vs1_1, vs2, vs1_2, vs2_2 // no mask and vta
432      Seq(FpData(), VecData(), VecData(), MaskSrcData(), VConfigData()),   // f[rs1], vs2, vd_old, v0
433    ),
434    writeIntRf = false,
435    writeFpRf = false,
436    writeVecRf = true,
437    latency = UncertainLatency(),
438  )
439  // Todo
440  // def VlduCfg = FuConfig ()
441  // def VstuCfg = FuConfig ()
442
443}
444
445