xref: /XiangShan/src/main/scala/xiangshan/backend/fu/vector/VIPU.scala (revision 6355a2b735802ef9295b6a7c79554392050cfd4d)
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.VectorIntAdder
27import yunsuan.vector.alu.{VAluOpcode, VIAlu}
28import yunsuan.{VectorElementFormat, VipuType}
29import xiangshan.{SelImm, SrcType, UopDivType, XSCoreParamsKey, XSModule}
30
31import scala.collection.Seq
32
33class VIPU(implicit p: Parameters) extends VPUSubModule(p(XSCoreParamsKey).VLEN) {
34  XSError(io.in.valid && io.in.bits.uop.ctrl.fuOpType === VipuType.dummy, "VIPU OpType not supported")
35
36// extra io
37  val vxrm = IO(Input(UInt(2.W)))
38  val vxsat = IO(Output(UInt(1.W)))
39
40// def some signal
41  val dataReg = Reg(io.out.bits.data.cloneType)
42  val dataWire = Wire(dataReg.cloneType)
43  val s_idle :: s_compute :: s_finish :: Nil = Enum(3)
44  val state = RegInit(s_idle)
45  val vialu = Module(new VIAluWrapper)
46  val outValid = vialu.io.out.valid
47  val outFire = vialu.io.out.fire()
48
49// reg input signal
50  val s0_uopReg = Reg(io.in.bits.uop.cloneType)
51  val inHs = io.in.fire()
52  when(inHs && state === s_idle){
53    s0_uopReg := io.in.bits.uop
54  }
55  dataReg := Mux(outValid, dataWire, dataReg)
56
57// fsm
58  switch (state) {
59    is (s_idle) {
60      state := Mux(inHs, s_compute, s_idle)
61    }
62    is (s_compute) {
63      state := Mux(outValid, Mux(outFire, s_idle, s_finish),
64                             s_compute)
65    }
66    is (s_finish) {
67      state := Mux(io.out.fire(), s_idle, s_finish)
68    }
69  }
70
71// connect VIAlu
72  dataWire := vialu.io.out.bits.data
73  vialu.io.in.bits <> io.in.bits
74  vialu.io.redirectIn := DontCare  // TODO :
75  vialu.vxrm := vxrm
76  io.out.bits.data :=  Mux(state === s_compute && outFire, dataWire, dataReg)
77  io.out.bits.uop := s0_uopReg
78  vxsat := vialu.vxsat
79
80  vialu.io.in.valid := io.in.valid && state === s_idle
81  io.out.valid := state === s_compute && outValid || state === s_finish
82  vialu.io.out.ready := io.out.ready
83  io.in.ready := state === s_idle
84}
85
86class VIAluDecodeResultBundle extends Bundle {
87  val opcode = UInt(6.W)
88  val srcType = Vec(2, UInt(4.W))
89  val vdType = UInt(4.W)
90}
91
92class VIAluDecoder (implicit p: Parameters) extends XSModule {
93  val io = IO(new Bundle{
94    val in = Input(new Bundle{
95      val fuOpType = UInt(8.W)
96      val sew = UInt(2.W)
97    })
98    val out = Output(new VIAluDecodeResultBundle)
99  })
100
101//  val DecodeDefault = List(VAluOpcode.dummy,  VpuDataType.dummy, VpuDataType.dummy, VpuDataType.dummy)
102//  val DecodeTable = Array(
103//    BitPat("b" + Cat(VipuType.add, "b00".U).litValue().toString()) -> List(VAluOpcode.vadd,  VpuDataType.s8, VpuDataType.s8, VpuDataType.s8),
104//    BitPat("b" + Cat(VipuType.add, "b01".U).litValue().toString()) -> List(VAluOpcode.vadd,  VpuDataType.s16, VpuDataType.s16, VpuDataType.s16),
105//    BitPat("b" + Cat(VipuType.add, "b10".U).litValue().toString()) -> List(VAluOpcode.vadd,  VpuDataType.s32, VpuDataType.s32, VpuDataType.s32),
106//    BitPat("b" + Cat(VipuType.add, "b11".U).litValue().toString()) -> List(VAluOpcode.vadd,  VpuDataType.s64, VpuDataType.s64, VpuDataType.s64),
107//  )
108//  val opcode :: srcType1 :: srcType2 :: vdType :: Nil = ListLookup(Cat(io.in.fuOpType, io.in.sew), DecodeDefault, DecodeTable)
109
110// u 00 s 01 f 10 mask 1111
111  val out = LookupTree(io.in.fuOpType, List(
112    VipuType.add -> Cat(VAluOpcode.vadd, Cat(1.U(2.W), io.in.sew), Cat(1.U(2.W), io.in.sew), Cat(1.U(2.W), io.in.sew)).asUInt()
113  )).asTypeOf(new VIAluDecodeResultBundle)
114
115  io.out <> out
116}
117
118class VIAluWrapper(implicit p: Parameters)  extends VPUSubModule(p(XSCoreParamsKey).VLEN) {
119  XSError(io.in.valid && io.in.bits.uop.ctrl.fuOpType === VipuType.dummy, "VIPU OpType not supported")
120
121// extra io
122  val vxrm = IO(Input(UInt(2.W)))
123  val vxsat = IO(Output(UInt(1.W)))
124
125// rename signal
126  val in = io.in.bits
127  val ctrl = in.uop.ctrl
128  val vtype = ctrl.vconfig.vtype
129
130// generate src1 and src2
131  val imm = VecInit(Seq.fill(VLEN/XLEN)(VecImmExtractor(ctrl.selImm, vtype.vsew, ctrl.imm))).asUInt
132  val _src1 = Mux(SrcType.isImm(ctrl.srcType(0)), imm, Mux(ctrl.uopDivType === UopDivType.VEC_MV_LMUL, VecExtractor(vtype.vsew, io.in.bits.src(0)), io.in.bits.src(0)))
133  val _src2 = in.src(1)
134  val src1 = Mux(VipuType.needReverse(ctrl.fuOpType), _src2, _src1)
135  val src2 = Mux(VipuType.needReverse(ctrl.fuOpType), _src1, _src2)
136
137// connect VIAlu
138  val decoder = Module(new VIAluDecoder)
139  val vialu = Module(new VIAlu)
140  decoder.io.in.fuOpType := in.uop.ctrl.fuType
141  decoder.io.in.sew := in.uop.ctrl.vconfig.vtype.vsew(1,0)
142
143  vialu.io.in.bits.opcode := decoder.io.out.opcode
144  vialu.io.in.bits.info.vm := in.uop.ctrl.vm
145  vialu.io.in.bits.info.ma := in.uop.ctrl.vconfig.vtype.vma
146  vialu.io.in.bits.info.ta := in.uop.ctrl.vconfig.vtype.vta
147  vialu.io.in.bits.info.vlmul := in.uop.ctrl.vconfig.vtype.vlmul
148  vialu.io.in.bits.info.vl := in.uop.ctrl.vconfig.vl
149  vialu.io.in.bits.info.vstart := 0.U // TODO :
150  vialu.io.in.bits.info.uopIdx := in.uop.ctrl.uopIdx.value
151  vialu.io.in.bits.info.vxrm := vxrm
152  vialu.io.in.bits.srcType(0) := decoder.io.out.srcType(0)
153  vialu.io.in.bits.srcType(1) := decoder.io.out.srcType(1)
154  vialu.io.in.bits.vdType := decoder.io.out.vdType
155  vialu.io.in.bits.vs1 := src1
156  vialu.io.in.bits.vs2 := src2
157  vialu.io.in.bits.old_vd := in.src(2)
158  vialu.io.in.bits.mask := in.src(3)
159
160  val vdOut = vialu.io.out.bits.vd
161  val vxsatOut = vialu.io.out.bits.vxsat
162
163  vialu.io.in.valid := io.in.valid
164
165// connect io
166  io.out.bits.data := vdOut
167  io.out.bits.uop := DontCare
168  vxsat := vxsatOut
169  io.out.valid := vialu.io.out.valid
170  io.in.ready := DontCare
171}
172
173object VecImmExtractor {
174  def Imm_OPIVIS(imm: UInt): UInt = {
175    SignExt(imm(4,0), 8)
176  }
177  def Imm_OPIVIU(imm: UInt): UInt = {
178    ZeroExt(imm(4,0), 8)
179  }
180
181  def imm_sew(sew: UInt, imm: UInt): UInt = {
182    val _imm = SignExt(imm(7,0), 64)
183    LookupTree(sew(1,0), List(
184      "b00".U -> VecInit(Seq.fill(8)(_imm(7,0))).asUInt,
185      "b01".U -> VecInit(Seq.fill(4)(_imm(15,0))).asUInt,
186      "b10".U -> VecInit(Seq.fill(2)(_imm(31,0))).asUInt,
187      "b11".U -> _imm(63,0),
188    ))
189  }
190
191  def apply(immType: UInt, sew: UInt, imm: UInt): UInt = {
192    val _imm = Mux(immType === SelImm.IMM_OPIVIS, Imm_OPIVIS(imm), Imm_OPIVIU(imm))
193    imm_sew(sew, _imm(7,0))
194  }
195}
196