xref: /XiangShan/src/main/scala/xiangshan/backend/fu/vector/VFPU.scala (revision e2fc343322f681c33dad659b280c0c07575c6e75)
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.{Mux, _}
23import chisel3.util._
24import utils._
25import utility._
26import yunsuan.vector.VectorFloatAdder
27import yunsuan.VfpuType
28import xiangshan.{SrcType, XSCoreParamsKey}
29import xiangshan.backend.fu.fpu.FPUSubModule
30
31class VFPU(implicit p: Parameters) extends FPUSubModule(p(XSCoreParamsKey).VLEN){
32  val Latency = 2
33  val AdderWidth = XLEN
34  val NumAdder = VLEN / XLEN
35  XSError(io.in.valid && io.in.bits.uop.ctrl.fuOpType === VfpuType.dummy, "VFPU OpType not supported")
36  XSError(io.in.valid && (io.in.bits.uop.ctrl.vconfig.vtype.vsew === 0.U), "8 bits not supported in FToVFPU")
37  override val dataModule = null // Only use IO, not dataModule
38
39// rename signal
40  val ctrl = io.in.bits.uop.ctrl
41  val vtype = ctrl.vconfig.vtype
42  val src1Type = io.in.bits.uop.ctrl.srcType
43
44// reg input signal
45  val uopReg0 = Reg(io.in.bits.uop.cloneType)
46  val valid0 = Seq.fill(Latency)(RegInit(false.B))
47  val inHs = io.in.fire()
48  when(inHs){
49    uopReg0 := io.in.bits.uop
50  }
51  valid0.zipWithIndex.foreach{
52    case (valid, idx) =>
53      val _valid = if (idx == 0) Mux(inHs, true.B,false.B) else valid0(idx-1)
54      valid := _valid
55  }
56
57  val vmask = Fill(8, 1.U(1.W)) // TODO:
58
59// connect the input port of VectorFloatAdder
60  val adder = Seq.fill(NumAdder)(Module(new VectorFloatAdder()))
61  val src1 = Mux(src1Type(0) === SrcType.vp, io.in.bits.src(0), VecExtractor(vtype.vsew, io.in.bits.src(0)))
62  val src2 = Mux(src1Type(1) === SrcType.vp, io.in.bits.src(1), VecExtractor(vtype.vsew, io.in.bits.src(1)))
63  for(i <- 0 until NumAdder) {
64    adder(i).io.fp_a := Mux(inHs, src1(AdderWidth*(i+1)-1, AdderWidth*i), 0.U)
65    adder(i).io.fp_b := Mux(inHs, src2(AdderWidth*(i+1)-1, AdderWidth*i), 0.U)
66    adder(i).io.is_vec := true.B // If you can enter, it must be vector
67    adder(i).io.round_mode := rm
68    adder(i).io.fp_format := Mux(inHs, vtype.vsew(1,0), 3.U(2.W))
69    adder(i).io.opb_widening := false.B // TODO
70    adder(i).io.res_widening := false.B // TODO
71    adder(i).io.op_code := Mux(inHs, ctrl.fuOpType, VfpuType.dummy)
72  }
73
74// generate the output : s1_fflags_result s1_adder_result
75  val fflagsResult = VecInit(adder.map(_.io.fflags)).asUInt()
76  val fflags16vl = fflagsGen(vmask, fflagsResult, List.range(0,8))
77  val fflags32vl = fflagsGen(vmask, fflagsResult, List(0,1,4,5))
78  val fflags64vl = fflagsGen(vmask, fflagsResult, List(0,4))
79  val s0_sew = uopReg0.ctrl.vconfig.vtype.vsew
80  val s0_vl = uopReg0.ctrl.vconfig.vl
81  val s0_fflags_result = LookupTree(s0_sew(1, 0), List(
82    "b01".U -> Mux(s0_vl.orR, fflags16vl(s0_vl-1.U),0.U(5.W)),
83    "b10".U -> Mux(s0_vl.orR, fflags32vl(s0_vl-1.U),0.U(5.W)),
84    "b11".U -> Mux(s0_vl.orR, fflags64vl(s0_vl-1.U),0.U(5.W)),
85  ))
86  val s1_fflags_result = RegEnable(s0_fflags_result, valid0(Latency-2))
87
88  val s0_adder_result = LookupTree(s0_sew(1, 0), List(
89    "b01".U -> VecInit(adder.map(_.io.fp_f16_result)).asUInt(),
90    "b10".U -> VecInit(adder.map(_.io.fp_f32_result)).asUInt(),
91    "b11".U -> VecInit(adder.map(_.io.fp_f64_result)).asUInt(),
92  ))
93  val s1_adder_result = RegEnable(s0_adder_result, valid0(Latency-2))
94
95// connect the output port
96  fflags := s1_fflags_result
97
98  io.out.bits.data := s1_adder_result
99  io.out.bits.uop := uopReg0
100
101  io.out.valid := valid0(Latency-1)
102  io.in.ready := !(valid0.foldLeft(false.B)(_|_)) && io.out.ready
103}
104
105object fflagsGen{
106  def fflagsGen(vmask: UInt, fflagsResult:UInt, idx:List[Int] = List(0, 1, 4, 5)): Vec[UInt] = {
107    var num = idx.length
108    val fflags = Seq.fill(num)(Wire(UInt(5.W)))
109    fflags.zip(vmask(num-1, 0).asBools().reverse).zip(idx).foreach {
110      case ((fflags0, mask), id) =>
111        fflags0 := Mux(mask, fflagsResult(id*5+4,id*5+0), 0.U)
112    }
113    val fflagsVl = Wire(Vec(num,UInt(5.W)))
114    for (i <- 0 until num) {
115      val _fflags = if (i == 0) fflags(i) else (fflagsVl(i - 1) | fflags(i))
116      fflagsVl(i) := _fflags
117    }
118    fflagsVl
119  }
120
121  def apply(vmask: UInt, fflagsResult:UInt, idx:List[Int] = List(0, 1, 4, 5)): Vec[UInt] = {
122    fflagsGen(vmask, fflagsResult, idx)
123  }
124}
125
126object VecExtractor{
127  def xf2v_sew(sew: UInt, xf:UInt): UInt = {
128    LookupTree(sew(1, 0), List(
129      "b00".U -> VecInit(Seq.fill(16)(xf(7, 0))).asUInt,
130      "b01".U -> VecInit(Seq.fill(8)(xf(15, 0))).asUInt,
131      "b10".U -> VecInit(Seq.fill(4)(xf(31, 0))).asUInt,
132      "b11".U -> VecInit(Seq.fill(2)(xf(63, 0))).asUInt,
133    ))
134  }
135
136  def apply(sew: UInt, xf: UInt): UInt = {
137    xf2v_sew(sew, xf)
138  }
139}