xref: /XiangShan/src/main/scala/xiangshan/backend/fu/wrapper/FCVT.scala (revision 6639e9a467468f4e1b05a25a5de4500772aedeb1)
1package xiangshan.backend.fu.wrapper
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import chisel3.util.experimental.decode._
7import utility.XSError
8import xiangshan.backend.fu.FuConfig
9import xiangshan.backend.fu.fpu.FpPipedFuncUnit
10import xiangshan.backend.fu.vector.Bundles.VSew
11import xiangshan.FuOpType
12import yunsuan.{VfcvtType, VfpuType}
13import yunsuan.scalar.FPCVT
14import yunsuan.util._
15
16
17class FCVT(cfg: FuConfig)(implicit p: Parameters) extends FpPipedFuncUnit(cfg) {
18  XSError(io.in.valid && io.in.bits.ctrl.fuOpType === VfpuType.dummy, "Vfcvt OpType not supported")
19
20  // io alias
21  private val opcode = fuOpType(8, 0)
22  private val src0 = inData.src(0)
23  private val sew = fp_fmt
24
25  private val isFround  = opcode === VfcvtType.fround
26  private val isFoundnx = opcode === VfcvtType.froundnx
27  private val isFcvtmod = opcode === VfcvtType.fcvtmod_w_d
28
29  private val isRtz = opcode(2) & opcode(1) | isFcvtmod
30  private val isRod = opcode(2) & !opcode(1) & opcode(0)
31  private val isFrm = !isRtz && !isRod
32  private val vfcvtRm = Mux1H(
33    Seq(isRtz, isRod, isFrm),
34    Seq(1.U, 6.U, rm)
35  )
36
37  val widen = opcode(4, 3) // 0->single 1->widen 2->norrow => width of result
38  val isSingleCvt = !widen(1) & !widen(0)
39  val isWidenCvt = !widen(1) & widen(0)
40  val isNarrowCvt = widen(1) & !widen(0)
41  val fire = io.in.valid
42  val fireReg = GatedValidRegNext(fire)
43
44  // output width 8, 16, 32, 64
45  val output1H = Wire(UInt(4.W))
46  output1H := chisel3.util.experimental.decode.decoder(
47    widen ## sew,
48    TruthTable(
49      Seq(
50        BitPat("b00_01") -> BitPat("b0010"), // 16
51        BitPat("b00_10") -> BitPat("b0100"), // 32
52        BitPat("b00_11") -> BitPat("b1000"), // 64
53
54        BitPat("b01_00") -> BitPat("b0010"), // 16
55        BitPat("b01_01") -> BitPat("b0100"), // 32
56        BitPat("b01_10") -> BitPat("b1000"), // 64
57
58        BitPat("b10_00") -> BitPat("b0001"), // 8
59        BitPat("b10_01") -> BitPat("b0010"), // 16
60        BitPat("b10_10") -> BitPat("b0100"), // 32
61
62        BitPat("b11_01") -> BitPat("b1000"), // f16->f64/i64/ui64
63        BitPat("b11_11") -> BitPat("b0010"), // f64->f16
64      ),
65      BitPat.N(4)
66    )
67  )
68  if(backendParams.debugEn) {
69    dontTouch(output1H)
70  }
71  val outputWidth1H = output1H
72  val outIs16bits = RegNext(RegNext(outputWidth1H(1)))
73  val outIs32bits = RegNext(RegNext(outputWidth1H(2)))
74  val outIsInt = !outCtrl.fuOpType(6)
75  val outIsMvInst = outCtrl.fuOpType === FuOpType.FMVXF
76
77  // modules
78  val fcvt = Module(new FPCVT(XLEN))
79  fcvt.io.fire := fire
80  fcvt.io.src := src0
81  fcvt.io.opType := opcode(7, 0)
82  fcvt.io.sew := sew
83  fcvt.io.rm := vfcvtRm
84  fcvt.io.isFpToVecInst := true.B
85  fcvt.io.isFround := Cat(isFoundnx, isFround)
86  fcvt.io.isFcvtmod := isFcvtmod
87
88
89  //cycle2
90  val isNarrowCycle2 = RegEnable(RegEnable(isNarrowCvt, fire), fireReg)
91  val outputWidth1HCycle2 = RegEnable(RegEnable(outputWidth1H, fire), fireReg)
92
93  val fcvtResult = fcvt.io.result
94  io.out.bits.res.fflags.get := Mux(outIsMvInst, 0.U, fcvt.io.fflags)
95
96  //fmv box
97  val result_fmv = Mux1H(Seq(
98    (sew === VSew.e8) -> Fill(56, src0(7)) ## src0(7, 0),
99    (sew === VSew.e16) -> Fill(48, src0(15)) ## src0(15, 0),
100    (sew === VSew.e32) -> Fill(32, src0(31)) ## src0(31, 0),
101    (sew === VSew.e64) -> src0,
102  ))
103  // for scalar f2i cvt inst
104  val isFpToInt32 = outIs32bits && outIsInt
105  // for f2i mv inst
106  val result = Mux(outIsMvInst, RegEnable(RegEnable(result_fmv, fire), fireReg),
107    // for scalar fp32 fp16 result
108    Mux(
109      outIs32bits && !outIsInt,
110      Cat(Fill(32, 1.U), fcvtResult(31,0)),
111      Mux(outIs16bits && !outIsInt, Cat(Fill(48, 1.U), fcvtResult(15,0)), fcvtResult)
112    )
113  )
114
115  io.out.bits.res.data := Mux(isFpToInt32,
116    Fill(32, result(31)) ## result(31, 0),
117    result
118  )
119}
120