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}