xref: /XiangShan/src/main/scala/xiangshan/backend/fu/vector/VFPU.scala (revision 94c0d8cf32e956379b700b62516c13d1483cfb7c)
1/****************************************************************************************
2  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3  * Copyright (c) 2020-2021 Peng Cheng Laboratory
4  *
5  * XiangShan is licensed under Mulan PSL v2.
6  * You can use this software according to the terms and conditions of the Mulan PSL v2.
7  * You may obtain a copy of Mulan PSL v2 at:
8  *          http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  *
14  * See the Mulan PSL v2 for more details.
15  ****************************************************************************************
16  */
17
18
19package xiangshan.backend.fu.vector
20
21import chipsalliance.rocketchip.config.Parameters
22import chisel3._
23import chisel3.util._
24import utils._
25import utility._
26import yunsuan.vector.VectorFloatAdder
27import yunsuan.{OpType, VectorElementFormat, VfpuType}
28import xiangshan.{FuType, MicroOp, MulDivExeUnitCfg, SrcType, XSCoreParamsKey}
29import xiangshan.backend.fu.fpu.FPUSubModule
30
31import scala.collection.Seq
32
33class VFPU(implicit p: Parameters) extends FPUSubModule(p(XSCoreParamsKey).VLEN){
34  val AdderWidth = XLEN
35  val NumAdder = VLEN / XLEN
36  XSError(io.in.valid && io.in.bits.uop.ctrl.fuOpType === VfpuType.dummy, "VFPU OpType not supported")
37  XSError(io.in.valid && (io.in.bits.uop.ctrl.vconfig.vtype.vsew === 0.U), "8 bits not supported in FToVFPU")
38  override val dataModule = null // Only use IO, not dataModule
39
40  val uop = io.in.bits.uop
41  val ctrl = uop.ctrl
42  val vtype = ctrl.vconfig.vtype
43  val src1Type = io.in.bits.uop.ctrl.srcType
44
45  val pipe_valid = RegInit(VecInit(Seq.fill(2)(false.B)))
46  val pipe_ready = WireInit(VecInit(Seq.fill(2)(true.B)))
47
48  when(pipe_valid(0) & pipe_ready(1)){pipe_valid(0) := false.B}
49  when(io.in.valid & pipe_ready(0)){pipe_valid(0) := true.B}
50  when(pipe_valid(1) & io.out.ready) {pipe_valid(1) := false.B}
51  when(pipe_valid(0) & pipe_ready(1)) {pipe_valid(1) := true.B}
52
53  pipe_ready(1) := !pipe_valid(1) || io.out.ready
54  pipe_ready(0) := !pipe_valid(0) || pipe_ready(1)
55
56  val uopReg = Seq.fill(2)(Reg(new MicroOp))
57  val v0 = Seq.fill(2)(Reg(UInt(16.W)))
58  val pipe0Hs = io.in.valid && pipe_ready(0)
59  val pipe1Hs = pipe_valid(0) && pipe_ready(1)
60  uopReg(0) := DataHoldBypass(io.in.bits.uop, pipe0Hs)
61  uopReg(1) := Mux(pipe1Hs, uopReg(0), uopReg(1))
62
63  v0(0) := DataHoldBypass(Fill(8, 1.U(1.W)), pipe0Hs)
64  v0(1) := Mux(pipe1Hs,v0(0), v0(1))
65  val vmask = v0(1)
66
67  val src1 = Mux(src1Type(0) === SrcType.vp, io.in.bits.src(0), VecExtractor(vtype.vsew, io.in.bits.src(0)))
68  val src2 = Mux(src1Type(1) === SrcType.vp, io.in.bits.src(1), VecExtractor(vtype.vsew, io.in.bits.src(1)))
69
70  val adder = Seq.fill(NumAdder)(Module(new VectorFloatAdder()))
71
72  for(i <- 0 until NumAdder) {
73    adder(i).io.fp_a := DataHoldBypass(src1(AdderWidth*(i+1)-1, AdderWidth*i), pipe0Hs)
74    adder(i).io.fp_b := DataHoldBypass(src2(AdderWidth*(i+1)-1, AdderWidth*i), pipe0Hs)
75    adder(i).io.is_vec := DataHoldBypass(true.B, pipe0Hs) // If you can enter, it must be vector
76    adder(i).io.round_mode := DataHoldBypass(rm, pipe0Hs)
77    val fp_format0 = DataHoldBypass(vtype.vsew(1,0), pipe0Hs)
78    adder(i).io.fp_format := Mux(fp_format0.orR,fp_format0,3.U(2.W))
79    adder(i).io.opb_widening := DataHoldBypass(false.B, pipe0Hs) // TODO
80    adder(i).io.res_widening := DataHoldBypass(false.B, pipe0Hs) // TODO
81    adder(i).io.op_code := DataHoldBypass(ctrl.fuOpType, pipe0Hs)
82  }
83
84  val adder_result = RegEnable(Mux1H(Seq(
85    (vtype.vsew === 1.U) -> VecInit(adder.map(_.io.fp_f16_result)).asUInt(),
86    (vtype.vsew === 2.U) -> VecInit(adder.map(_.io.fp_f32_result)).asUInt(),
87    (vtype.vsew === 3.U) -> VecInit(adder.map(_.io.fp_f64_result)).asUInt(),
88  )), pipe1Hs)
89
90  val fflagsResult = VecInit(adder.map(_.io.fflags)).asUInt()
91  val fflags16vl = fflagsGen(vmask, fflagsResult, List.range(0,8))
92  val fflags32vl = fflagsGen(vmask, fflagsResult, List(0,1,4,5))
93  val fflags64vl = fflagsGen(vmask, fflagsResult, List(0,4))
94
95  val s0_sew = uopReg(0).asTypeOf(uop.cloneType).ctrl.vconfig.vtype.vsew
96  val s0_vl = uopReg(0).ctrl.vconfig.vl
97  val fflags_result = RegEnable(LookupTree(s0_sew(1, 0), List(
98    "b01".U -> Mux(s0_vl.orR, fflags16vl(s0_vl-1.U),0.U(5.W)),
99    "b10".U -> Mux(s0_vl.orR, fflags32vl(s0_vl-1.U),0.U(5.W)),
100    "b11".U -> Mux(s0_vl.orR, fflags64vl(s0_vl-1.U),0.U(5.W)),
101  )), pipe1Hs)
102
103  fflags := fflags_result
104
105  io.out.bits.data := adder_result
106  io.out.bits.uop := uopReg(1)
107
108  io.out.valid := pipe_valid(1)
109  io.in.ready := pipe_ready(0)
110}
111
112object fflagsGen{
113  def fflagsGen(vmask: UInt, fflagsResult:UInt, idx:List[Int] = List(0, 1, 4, 5)): Vec[UInt] = {
114    var num = idx.length
115    val fflags = Seq.fill(num)(Wire(UInt(5.W)))
116    fflags.zip(vmask(num-1, 0).asBools().reverse).zip(idx).foreach {
117      case ((fflags0, mask), id) =>
118        fflags0 := Mux(mask, fflagsResult(id*5+4,id*5+0), 0.U)
119    }
120    val fflagsVl = Wire(Vec(num,UInt(5.W)))
121    for (i <- 0 until num) {
122      val _fflags = if (i == 0) fflags(i) else (fflagsVl(i - 1) | fflags(i))
123      fflagsVl(i) := _fflags
124    }
125    fflagsVl
126  }
127
128  def apply(vmask: UInt, fflagsResult:UInt, idx:List[Int] = List(0, 1, 4, 5)): Vec[UInt] = {
129    fflagsGen(vmask, fflagsResult, idx)
130  }
131}
132
133object VecExtractor{
134  def xf2v_sew(sew: UInt, xf:UInt): UInt = {
135    LookupTree(sew(1, 0), List(
136      "b00".U -> VecInit(Seq.fill(16)(xf(7, 0))).asUInt,
137      "b01".U -> VecInit(Seq.fill(8)(xf(15, 0))).asUInt,
138      "b10".U -> VecInit(Seq.fill(4)(xf(31, 0))).asUInt,
139      "b11".U -> VecInit(Seq.fill(2)(xf(63, 0))).asUInt,
140    ))
141  }
142
143  def apply(sew: UInt, xf: UInt): UInt = {
144    xf2v_sew(sew, xf)
145  }
146}