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}