xref: /XiangShan/src/main/scala/xiangshan/backend/fu/wrapper/VIMacU.scala (revision 83ba63b34cf09b33c0a9e1b3203138e51af4491b)
1package xiangshan.backend.fu.wrapper
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utils.XSError
7import xiangshan.backend.fu.FuConfig
8import xiangshan.backend.fu.vector.Bundles.VSew
9import xiangshan.backend.fu.vector.utils.VecDataSplitModule
10import xiangshan.backend.fu.vector.{Mgu, Utils, VecPipedFuncUnit, VecSrcTypeModule}
11import yunsuan.VialuFixType
12import yunsuan.encoding.Opcode.VimacOpcode
13import yunsuan.encoding.{VdType, Vs1IntType, Vs2IntType}
14import yunsuan.{OpType, VimacType}
15import yunsuan.vector.mac.VIMac64b
16
17class VIMacSrcTypeModule extends VecSrcTypeModule {
18
19  private val opcode  = VimacType.getOpcode(fuOpType)
20  private val vs2Sign = VimacType.vs2Sign(fuOpType)
21  private val vs1Sign = VimacType.vs1Sign(fuOpType)
22  private val vdSign  = VimacType.vdSign(fuOpType)
23  private val format  = VimacType.getFormat(fuOpType)
24  private val widen   = format === VimacType.FMT.VVW
25
26  private val vs2IntType = Cat(0.U(1.W), vs2Sign)
27  private val vs1IntType = Cat(0.U(1.W), vs1Sign)
28  private val vdIntType  = Cat(0.U(1.W),  vdSign)
29
30  private val vsewX2 = vsew + 1.U
31
32  private val vs2Type = Cat(vs2IntType, vsew)
33  private val vs1Type = Cat(vs1IntType, vsew)
34  private val vdType  = Cat( vdIntType, Mux(widen, vsewX2, vsew))
35
36  private val widenIllegal = widen && vsewX2 === VSew.e8
37
38  io.out.illegal := widenIllegal
39  io.out.vs2Type := vs2Type
40  io.out.vs1Type := vs1Type
41  io.out.vdType  := vdType
42}
43
44class VIMacU(cfg: FuConfig)(implicit p: Parameters) extends VecPipedFuncUnit(cfg) {
45  XSError(io.in.valid && io.in.bits.ctrl.fuOpType === VimacType.dummy, "VialuF OpType not supported")
46
47  // params alias
48  private val dataWidth = cfg.dataBits
49  private val dataWidthOfDataModule = 64
50  private val numVecModule = dataWidth / dataWidthOfDataModule
51
52  // io alias
53  private val opcode  = VimacType.getOpcode(fuOpType)
54  private val format  = VimacType.getFormat(fuOpType)
55  private val widen   = format === VimacType.FMT.VVW
56  private val exchangeVs2Vd = VimacOpcode.overWriteMultiplicand(opcode)
57
58  // modules
59  private val typeMod = Module(new VIMacSrcTypeModule)
60  private val vs2Split = Module(new VecDataSplitModule(dataWidth, dataWidthOfDataModule))
61  private val vs1Split = Module(new VecDataSplitModule(dataWidth, dataWidthOfDataModule))
62  private val oldVdSplit  = Module(new VecDataSplitModule(dataWidth, dataWidthOfDataModule))
63  private val vimacs = Seq.fill(numVecModule)(Module(new VIMac64b))
64  private val mgu = Module(new Mgu(dataWidth))
65
66  /**
67    * [[typeMod]]'s in connection
68    */
69  typeMod.io.in.fuOpType := fuOpType
70  typeMod.io.in.vsew := vsew
71  typeMod.io.in.isReverse := isReverse
72  typeMod.io.in.isExt := isExt
73  typeMod.io.in.isDstMask := vecCtrl.isDstMask
74  typeMod.io.in.isMove := isMove
75
76  /**
77    * In connection of [[vs2Split]], [[vs1Split]] and [[oldVdSplit]]
78    */
79  vs2Split.io.inVecData := vs2
80  vs1Split.io.inVecData := vs1
81  oldVdSplit.io.inVecData := oldVd
82
83  /**
84    * [[vimacs]]'s in connection
85    */
86  // Vec(vs2(31,0), vs2(63,32), vs2(95,64), vs2(127,96)) ==>
87  // Vec(
88  //   Cat(vs2(95,64),  vs2(31,0)),
89  //   Cat(vs2(127,96), vs2(63,32)),
90  // )
91  private val vs2GroupedVec: Vec[UInt] = VecInit(vs2Split.io.outVec32b.zipWithIndex.groupBy(_._2 % 2).map(x => x._1 -> x._2.map(_._1)).values.map(x => Cat(x.reverse)).toSeq)
92  private val vs1GroupedVec: Vec[UInt] = VecInit(vs1Split.io.outVec32b.zipWithIndex.groupBy(_._2 % 2).map(x => x._1 -> x._2.map(_._1)).values.map(x => Cat(x.reverse)).toSeq)
93
94  private val vs2VecUsed: Vec[UInt] = Mux(widen, vs2GroupedVec, vs2Split.io.outVec64b)
95  private val vs1VecUsed: Vec[UInt] = Mux(widen, vs1GroupedVec, vs1Split.io.outVec64b)
96  private val oldVdVecUsed: Vec[UInt] = WireInit(oldVdSplit.io.outVec64b)
97
98  vimacs.zipWithIndex.foreach {
99    case (mod, i) =>
100      mod.io.info.vm     := vm
101      mod.io.info.ma     := vma
102      mod.io.info.ta     := vta
103      mod.io.info.vlmul  := vlmul
104      mod.io.info.vl     := srcVConfig.vl
105      mod.io.info.vstart := vstart
106      mod.io.info.uopIdx := vuopIdx
107      mod.io.info.vxrm   := vxrm
108      mod.io.srcType(0)  := typeMod.io.out.vs2Type
109      mod.io.srcType(1)  := typeMod.io.out.vs1Type
110      mod.io.vdType      := typeMod.io.out.vdType
111      mod.io.vs1         := vs1VecUsed(i)
112      mod.io.vs2         := Mux(!exchangeVs2Vd, vs2VecUsed(i), oldVdVecUsed(i))
113      mod.io.oldVd       := Mux(!exchangeVs2Vd, oldVdVecUsed(i), vs2VecUsed(i))
114      mod.io.highHalf    := VimacOpcode.highHalf(opcode)
115      mod.io.isMacc      := VimacOpcode.isMacc(opcode)
116      mod.io.isSub       := VimacOpcode.isSub(opcode)
117      mod.io.widen       := widen
118      mod.io.isFixP      := VimacOpcode.isFixP(opcode)
119  }
120
121  /**
122    * [[mgu]]'s in connection
123    */
124  private val outVd = Cat(vimacs.reverse.map(_.io.vd))
125  private val outFormat = VimacType.getFormat(outCtrl.fuOpType)
126  private val outWiden = outFormat === VimacType.FMT.VVW
127
128  private val outEew = Mux(outWiden, outVecCtrl.vsew + 1.U, outVecCtrl.vsew)
129  mgu.io.in.vd := outVd
130  mgu.io.in.oldVd := outOldVd
131  mgu.io.in.mask := outSrcMask
132  mgu.io.in.info.ta := outVecCtrl.vta
133  mgu.io.in.info.ma := outVecCtrl.vma
134  mgu.io.in.info.vl := outVl
135  mgu.io.in.info.vlmul := outVecCtrl.vlmul
136  mgu.io.in.info.valid := io.out.valid
137  mgu.io.in.info.vstart := outVecCtrl.vstart
138  mgu.io.in.info.eew := outEew
139  mgu.io.in.info.vsew := outVecCtrl.vsew
140  mgu.io.in.info.vdIdx := outVecCtrl.vuopIdx
141  mgu.io.in.info.narrow := 0.B
142  mgu.io.in.info.dstMask := 0.B
143
144  io.out.bits.res.data := mgu.io.out.vd
145  io.out.bits.res.vxsat.get := (Cat(vimacs.map(_.io.vxsat)) & mgu.io.out.keep).orR
146}
147