xref: /XiangShan/src/main/scala/xiangshan/backend/fu/FuConfig.scala (revision a8db15d829fbeffc63c1e3101725a2131cedc087)
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,
19  writeFpRf: Boolean,
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 isMul: Boolean = fuType == FuType.mul
100
101  def isDiv: Boolean = fuType == FuType.div
102
103  def isCsr: Boolean = fuType == FuType.csr
104
105  def isFence: Boolean = fuType == FuType.fence
106}
107
108object FuConfig {
109  val JmpCfg: FuConfig = FuConfig (
110    name = "jmp",
111    fuType = FuType.jmp,
112    fuGen = (p: Parameters, cfg: FuConfig) => Module(new JumpUnit(cfg)(p)).suggestName("jmp"),
113    srcData = Seq(
114      Seq(IntData()), // jal
115    ),
116    writeIntRf = true,
117    writeFpRf = false,
118    immType = Set(SelImm.IMM_I, SelImm.IMM_UJ, SelImm.IMM_U),
119  )
120
121  val BrhCfg: FuConfig = FuConfig (
122    name = "brh",
123    fuType = FuType.brh,
124    fuGen = (p: Parameters, cfg: FuConfig) => Module(new BranchUnit(cfg)(p).suggestName("brh")),
125    srcData = Seq(
126      Seq(IntData(), IntData()),
127    ),
128    writeIntRf = false,
129    writeFpRf = false,
130    immType = Set(SelImm.IMM_SB),
131  )
132
133  val I2fCfg: FuConfig = FuConfig (
134    name = "i2f",
135    FuType.i2f,
136    fuGen = (p: Parameters, cfg: FuConfig) => Module(new IntToFP(cfg)(p).suggestName("i2f")),
137    srcData = Seq(
138      Seq(IntData()),
139    ),
140    writeIntRf = false,
141    writeFpRf = true,
142    writeFflags = true,
143    latency = CertainLatency(2),
144    needSrcFrm = true,
145  )
146
147  val CsrCfg: FuConfig = FuConfig (
148    name = "csr",
149    fuType = FuType.csr,
150    fuGen = (p: Parameters, cfg: FuConfig) => Module(new CSR(cfg)(p).suggestName("csr")),
151    srcData = Seq(
152      Seq(IntData()),
153    ),
154    writeIntRf = true,
155    writeFpRf = false,
156    exceptionOut = Seq(illegalInstr, breakPoint, ecallU, ecallS, ecallM),
157    flushPipe = true
158  )
159
160  val AluCfg: FuConfig = FuConfig (
161    name = "alu",
162    fuType = FuType.alu,
163    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Alu(cfg)(p).suggestName("Alu")),
164    srcData = Seq(
165      Seq(IntData(), IntData()),
166    ),
167    writeIntRf = true,
168    writeFpRf = false,
169    immType = Set(SelImm.IMM_I, SelImm.IMM_U),
170  )
171
172  val MulCfg: FuConfig = FuConfig (
173    name = "mul",
174    fuType = FuType.mul,
175    fuGen = (p: Parameters, cfg: FuConfig) => Module(new MulUnit(cfg)(p).suggestName("Mul")),
176    srcData = Seq(
177      Seq(IntData(), IntData()),
178    ),
179    writeIntRf = true,
180    writeFpRf = false,
181    latency = CertainLatency(2),
182  )
183
184  val DivCfg: FuConfig = FuConfig (
185    name = "div",
186    fuType = FuType.div,
187    fuGen = (p: Parameters, cfg: FuConfig) => Module(new DivUnit(cfg)(p).suggestName("Div")),
188    srcData = Seq(
189      Seq(IntData(), IntData()),
190    ),
191    writeIntRf = true,
192    writeFpRf = false,
193    latency = UncertainLatency(),
194    hasInputBuffer = (true, 4, true)
195  )
196
197  val FenceCfg: FuConfig = FuConfig (
198    name = "fence",
199    FuType.fence,
200    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Fence(cfg)(p).suggestName("Fence")),
201    srcData = Seq(
202      Seq(IntData(), IntData()),
203    ),
204    writeIntRf = false,
205    writeFpRf = false,
206    latency = UncertainLatency(),
207    exceptionOut = Seq(illegalInstr),
208    flushPipe = true
209  )
210
211  // Todo: split it to simple bitmap exu and complex bku
212  val BkuCfg: FuConfig = FuConfig (
213    name = "bku",
214    fuType = FuType.bku,
215    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Bku(cfg)(p).suggestName("Bku")),
216    srcData = Seq(
217      Seq(IntData(), IntData()),
218    ),
219    writeIntRf = true,
220    writeFpRf = false,
221    latency = CertainLatency(1),
222  )
223
224  val VSetRvfWvfCfg: FuConfig = FuConfig(
225    name = "vsetrvfwvf",
226    fuType = FuType.vsetiwf,
227    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRvfWvf(cfg)(p).suggestName("VSetRvfWvf")),
228    srcData = Seq(
229      Seq(FpData(), FpData()),
230    ),
231    writeIntRf = false,
232    writeFpRf = false,
233    writeVecRf = true,
234    latency = CertainLatency(0),
235    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
236  )
237
238  val VSetRiWvfCfg: FuConfig = FuConfig(
239    name = "vsetriwvf",
240    fuType = FuType.vsetiwf,
241    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWvf(cfg)(p).suggestName("VSetRiWvf")),
242    srcData = Seq(
243      Seq(IntData(), IntData()),
244    ),
245    writeIntRf = false,
246    writeFpRf = false,
247    writeVecRf = true,
248    latency = CertainLatency(0),
249    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
250  )
251
252  val VSetRiWiCfg: FuConfig = FuConfig(
253    name = "vsetriwi",
254    fuType = FuType.vsetiwi,
255    fuGen = (p: Parameters, cfg: FuConfig) => Module(new VSetRiWi(cfg)(p).suggestName("VSetRiWi")),
256    srcData = Seq(
257      Seq(IntData(), IntData()),
258    ),
259    writeIntRf = true,
260    writeFpRf = false,
261    latency = CertainLatency(0),
262    immType = Set(SelImm.IMM_VSETVLI, SelImm.IMM_VSETIVLI),
263  )
264
265  val FmacCfg: FuConfig = FuConfig (
266    name = "fmac",
267    fuType = FuType.fmac,
268    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FMA(cfg)(p).suggestName("FMac")),
269    srcData = Seq(
270      Seq(FpData(), FpData()),
271      Seq(FpData(), FpData(), FpData()),
272    ),
273    writeIntRf = false,
274    writeFpRf = true,
275    writeFflags = true,
276    latency = UncertainLatency(),
277    needSrcFrm = true,
278  )
279
280  val F2iCfg: FuConfig = FuConfig (
281    name = "f2i",
282    fuType = FuType.fmisc,
283    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToInt(cfg)(p).suggestName("F2i")),
284    srcData = Seq(
285      Seq(FpData(), FpData()),
286      Seq(FpData()),
287    ),
288    writeIntRf = true,
289    writeFpRf = false,
290    writeFflags = true,
291    latency = CertainLatency(2),
292    needSrcFrm = true,
293  )
294
295  val F2fCfg: FuConfig = FuConfig (
296    name = "f2f",
297    fuType = FuType.fmisc,
298    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FPToFP(cfg)(p).suggestName("F2f")),
299    srcData = Seq(
300      Seq(FpData(), FpData()),
301      Seq(FpData()),
302    ),
303    writeIntRf = false,
304    writeFpRf = true,
305    writeFflags = true,
306    latency = CertainLatency(2),
307    needSrcFrm = true,
308  )
309
310  val FDivSqrtCfg: FuConfig = FuConfig (
311    name = "fDivSqrt",
312    fuType = FuType.fDivSqrt,
313    fuGen = (p: Parameters, cfg: FuConfig) => Module(new FDivSqrt(cfg)(p).suggestName("FDivSqrt")),
314    srcData = Seq(
315      Seq(FpData(), FpData()),
316    ),
317    writeIntRf = false,
318    writeFpRf = true,
319    writeFflags = true,
320    latency = UncertainLatency(),
321    hasInputBuffer = (true, 8, true),
322    needSrcFrm = true,
323  )
324
325  val LduCfg: FuConfig = FuConfig (
326    name = "ldu",
327    fuType = FuType.ldu,
328    fuGen = null, // Todo
329    srcData = Seq(
330      Seq(IntData()),
331    ),
332    writeIntRf = true,
333    writeFpRf = true,
334    latency = UncertainLatency(),
335    exceptionOut = Seq(loadAddrMisaligned, loadAccessFault, loadPageFault),
336    flushPipe = true,
337    replayInst = true,
338    hasLoadError = true,
339    immType = Set(SelImm.IMM_I),
340  )
341
342  val StaCfg: FuConfig = FuConfig (
343    name = "sta",
344    fuType = FuType.stu,
345    fuGen = null, // Todo
346    srcData = Seq(
347      Seq(IntData()),
348    ),
349    writeIntRf = false,
350    writeFpRf = false,
351    latency = UncertainLatency(),
352    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault),
353    immType = Set(SelImm.IMM_S),
354  )
355
356  val StdCfg: FuConfig = FuConfig (
357    name = "std",
358    fuType = FuType.stu,
359    fuGen = (p: Parameters, cfg: FuConfig) => Module(new Std(cfg)(p).suggestName("Std")),
360    srcData = Seq(
361      Seq(IntData()),
362      Seq(FpData()),
363    ),
364    writeIntRf = false,
365    writeFpRf = false,
366    latency = CertainLatency(1),
367    exceptionOut = Seq(storeAddrMisaligned, storeAccessFault, storePageFault)
368  )
369
370  val MouCfg: FuConfig = FuConfig (
371    name = "mou",
372    fuType = FuType.mou,
373    fuGen = null, // Todo
374    srcData = Seq(
375      Seq(IntData()),
376    ),
377    writeIntRf = true,
378    writeFpRf = false,
379    latency = UncertainLatency(),
380    exceptionOut = (LduCfg.exceptionOut ++ StaCfg.exceptionOut ++ StdCfg.exceptionOut).distinct
381  )
382
383  val MoudCfg: FuConfig = FuConfig (
384    name = "moud",
385    fuType = FuType.mou,
386    fuGen = null, // Todo
387    srcData = Seq(
388      Seq(IntData()),
389    ),
390    writeIntRf = false,
391    writeFpRf = false,
392    latency = UncertainLatency()
393  )
394
395  val VipuCfg: FuConfig = FuConfig (
396    name = "vipu",
397    fuType = FuType.vipu,
398    fuGen = null, // Todo
399    srcData = Seq(
400      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
401      Seq(VecData(), VecData(), VecData(), VecData(), VConfigData()),      // vs1_1, vs2, vs1_2, vs2_2 // no mask and vta
402    ),
403    writeIntRf = false,
404    writeFpRf = false,
405    writeVecRf = true,
406    latency = UncertainLatency(),
407  )
408
409  val VfpuCfg: FuConfig = FuConfig (
410    name = "vfpu",
411    fuType = FuType.vfpu,
412    fuGen = null, // Todo
413    srcData = Seq(
414      Seq(VecData(), VecData(), VecData(), MaskSrcData(), VConfigData()),  // vs1, vs2, vd_old, v0
415      Seq(VecData(), VecData(), VecData(), VecData(), VConfigData()),      // vs1_1, vs2, vs1_2, vs2_2 // no mask and vta
416      Seq(FpData(), VecData(), VecData(), MaskSrcData(), VConfigData()),   // f[rs1], vs2, vd_old, v0
417    ),
418    writeIntRf = false,
419    writeFpRf = false,
420    writeVecRf = true,
421    latency = UncertainLatency(),
422  )
423  // Todo
424  // def VlduCfg = FuConfig ()
425  // def VstuCfg = FuConfig ()
426
427}
428
429