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