xref: /XiangShan/src/main/scala/xiangshan/backend/fu/fpu/FPU.scala (revision 887862dbb8debde8ab099befc426493834a69ee7)
1package xiangshan.backend.fu.fpu
2
3import chisel3._
4import chisel3.util._
5import fudian.FloatPoint
6
7object FPU {
8
9  case class FType(expWidth: Int, precision: Int) {
10    val sigWidth = precision - 1
11    val len = expWidth + precision
12  }
13
14  val f16 = FType(5, 11)
15  val f32 = FType(8, 24)
16  val f64 = FType(11, 53)
17
18  // Appending f16 instead of pushing it from head to avoid potential encoding conflicts.
19  // Todo: use fmt field encoding in riscv FP instructions instead of customized encoding.
20  val ftypes = List(f32, f64, f16)
21  val ftypeWidth = log2Up(ftypes.length)
22
23  val S = ftypes.indexOf(f32).U(ftypeWidth.W)
24  val D = ftypes.indexOf(f64).U(ftypeWidth.W)
25  val H = ftypes.indexOf(f16).U(ftypeWidth.W)
26
27  // Produce zero-extended FPXX data
28  def unbox(x: UInt, typeTag: UInt): UInt = {
29    require(x.getWidth == 64)
30    require(typeTag.getWidth == ftypeWidth)
31    Mux1H(Seq(
32      (typeTag === D) -> x,
33      (typeTag === S) -> Mux(x.head(32).andR, x(f32.len - 1, 0), FloatPoint.defaultNaNUInt(f32.expWidth, f32.precision)),
34      (typeTag === H) -> Mux(x.head(48).andR, x(f16.len - 1, 0), FloatPoint.defaultNaNUInt(f16.expWidth, f16.precision)),
35    ))
36  }
37
38  def box(x: UInt, typeTag: UInt): UInt = {
39    require(x.getWidth == 64)
40    Mux1H(Seq(
41      (typeTag === D) -> x,
42      (typeTag === S) -> Cat(Fill(32, 1.U(1.W)), x(f32.len - 1, 0)),
43      (typeTag === H) -> Cat(Fill(48, 1.U(1.W)), x(f16.len - 1, 0)),
44    ))
45  }
46
47  def box(x: UInt, t: FType): UInt = {
48    if      (t == f64) x(63, 0)
49    else if (t == f32) Cat(Fill(32, 1.U(1.W)), x(31, 0))
50    else if (t == f16) Cat(Fill(48, 1.U(1.W)), x(15, 0))
51    else {
52      assert(cond = false, "Unknown ftype!")
53      0.U
54    }
55  }
56
57}
58