xref: /XiangShan/src/main/scala/xiangshan/backend/fu/wrapper/VCVT.scala (revision ac5be754bbbd6fb4720d11aad404ec3d1c6117b7)
166c73034Schengguanghuipackage xiangshan.backend.fu.wrapper
266c73034Schengguanghui
383ba63b3SXuan Huimport org.chipsalliance.cde.config.Parameters
466c73034Schengguanghuiimport chisel3._
566c73034Schengguanghuiimport chisel3.util._
666c73034Schengguanghuiimport chisel3.util.experimental.decode._
7bb2f3f51STang Haojinimport utility.XSError
866c73034Schengguanghuiimport xiangshan.backend.fu.FuConfig
966c73034Schengguanghuiimport xiangshan.backend.fu.vector.{Mgu, VecPipedFuncUnit}
10c33d4a9eSXuan Huimport xiangshan.ExceptionNO
1120b2b626SsinceforYyimport xiangshan.FuOpType
1266c73034Schengguanghuiimport yunsuan.VfpuType
139d3cebe7Schengguanghuiimport yunsuan.vector.VectorConvert.VectorCvt
145f8b6c9eSsinceforYyimport yunsuan.util._
1566c73034Schengguanghui
1666c73034Schengguanghui
1766c73034Schengguanghuiclass VCVT(cfg: FuConfig)(implicit p: Parameters) extends VecPipedFuncUnit(cfg) {
1866c73034Schengguanghui  XSError(io.in.valid && io.in.bits.ctrl.fuOpType === VfpuType.dummy, "Vfcvt OpType not supported")
1966c73034Schengguanghui
2066c73034Schengguanghui  // params alias
212d12882cSxiaofeibao  private val dataWidth = cfg.destDataBits
2266c73034Schengguanghui  private val dataWidthOfDataModule = 64
2366c73034Schengguanghui  private val numVecModule = dataWidth / dataWidthOfDataModule
2466c73034Schengguanghui
2566c73034Schengguanghui  // io alias
26572278faSZiyue Zhang  private val opcode = fuOpType(8, 0)
2766c73034Schengguanghui  private val sew = vsew
289d3cebe7Schengguanghui
299d3cebe7Schengguanghui  private val isRtz = opcode(2) & opcode(1)
309d3cebe7Schengguanghui  private val isRod = opcode(2) & !opcode(1) & opcode(0)
319d3cebe7Schengguanghui  private val isFrm = !isRtz && !isRod
32c6efb121SZiyue Zhang  private val vfcvtRm = Mux1H(
339d3cebe7Schengguanghui    Seq(isRtz, isRod, isFrm),
34c6efb121SZiyue Zhang    Seq(1.U, 6.U, rm)
359d3cebe7Schengguanghui  )
369d3cebe7Schengguanghui
3766c73034Schengguanghui  private val lmul = vlmul // -3->3 => 1/8 ->8
3866c73034Schengguanghui
3966c73034Schengguanghui  val widen = opcode(4, 3) // 0->single 1->widen 2->norrow => width of result
4066c73034Schengguanghui  val isSingleCvt = !widen(1) & !widen(0)
4166c73034Schengguanghui  val isWidenCvt = !widen(1) & widen(0)
4266c73034Schengguanghui  val isNarrowCvt = widen(1) & !widen(0)
43e8e02b74SsinceforYy  val fire = io.in.valid
445f8b6c9eSsinceforYy  val fireReg = GatedValidRegNext(fire)
4566c73034Schengguanghui
4666c73034Schengguanghui  // output width 8, 16, 32, 64
4766c73034Schengguanghui  val output1H = Wire(UInt(4.W))
4866c73034Schengguanghui  output1H := chisel3.util.experimental.decode.decoder(
4966c73034Schengguanghui    widen ## sew,
5066c73034Schengguanghui    TruthTable(
5166c73034Schengguanghui      Seq(
5266c73034Schengguanghui        BitPat("b00_01") -> BitPat("b0010"), // 16
5366c73034Schengguanghui        BitPat("b00_10") -> BitPat("b0100"), // 32
5466c73034Schengguanghui        BitPat("b00_11") -> BitPat("b1000"), // 64
5566c73034Schengguanghui
5666c73034Schengguanghui        BitPat("b01_00") -> BitPat("b0010"), // 16
5766c73034Schengguanghui        BitPat("b01_01") -> BitPat("b0100"), // 32
5866c73034Schengguanghui        BitPat("b01_10") -> BitPat("b1000"), // 64
5966c73034Schengguanghui
6066c73034Schengguanghui        BitPat("b10_00") -> BitPat("b0001"), // 8
6166c73034Schengguanghui        BitPat("b10_01") -> BitPat("b0010"), // 16
6266c73034Schengguanghui        BitPat("b10_10") -> BitPat("b0100"), // 32
6366c73034Schengguanghui      ),
649d3cebe7Schengguanghui      BitPat.N(4)
6566c73034Schengguanghui    )
6666c73034Schengguanghui  )
678d081717Sszw_kaixin  if(backendParams.debugEn) {
6866c73034Schengguanghui    dontTouch(output1H)
698d081717Sszw_kaixin  }
7066c73034Schengguanghui  val outputWidth1H = output1H
71572278faSZiyue Zhang  val outIs32bits = RegNext(RegNext(outputWidth1H(2)))
72572278faSZiyue Zhang  val outIsInt = !outCtrl.fuOpType(6)
73c0a99c00SGuanghui Cheng
74c0a99c00SGuanghui Cheng  // May be useful in the future.
75c0a99c00SGuanghui Cheng  // val outIsMvInst = outCtrl.fuOpType === FuOpType.FMVXF
76c0a99c00SGuanghui Cheng  val outIsMvInst = false.B
7766c73034Schengguanghui
78e8e02b74SsinceforYy  val outEew = RegEnable(RegEnable(Mux1H(output1H, Seq(0,1,2,3).map(i => i.U)), fire), fireReg)
7966c73034Schengguanghui  private val needNoMask = outVecCtrl.fpu.isFpToVecInst
8066c73034Schengguanghui  val maskToMgu = Mux(needNoMask, allMaskTrue, outSrcMask)
8166c73034Schengguanghui
8266c73034Schengguanghui  // modules
8366c73034Schengguanghui  private val vfcvt = Module(new VectorCvtTop(dataWidth, dataWidthOfDataModule))
84ba899681Schengguanghui  private val mgu = Module(new Mgu(dataWidth))
8566c73034Schengguanghui
869d3cebe7Schengguanghui  val vs2Vec = Wire(Vec(numVecModule, UInt(dataWidthOfDataModule.W)))
879d3cebe7Schengguanghui  vs2Vec := vs2.asTypeOf(vs2Vec)
889d3cebe7Schengguanghui
8966c73034Schengguanghui  /**
9066c73034Schengguanghui   * [[vfcvt]]'s in connection
9166c73034Schengguanghui   */
9266c73034Schengguanghui  vfcvt.uopIdx := vuopIdx(0)
939d3cebe7Schengguanghui  vfcvt.src := vs2Vec
94572278faSZiyue Zhang  vfcvt.opType := opcode(7,0)
9566c73034Schengguanghui  vfcvt.sew := sew
96c6efb121SZiyue Zhang  vfcvt.rm := vfcvtRm
9766c73034Schengguanghui  vfcvt.outputWidth1H := outputWidth1H
9866c73034Schengguanghui  vfcvt.isWiden := isWidenCvt
9966c73034Schengguanghui  vfcvt.isNarrow := isNarrowCvt
100e8e02b74SsinceforYy  vfcvt.fire := fire
1019626da3aSchengguanghui  vfcvt.isFpToVecInst := vecCtrl.fpu.isFpToVecInst
1029d3cebe7Schengguanghui  val vfcvtResult = vfcvt.io.result
1039d3cebe7Schengguanghui  val vfcvtFflags = vfcvt.io.fflags
10466c73034Schengguanghui
10566c73034Schengguanghui  /** fflags:
10666c73034Schengguanghui   */
10766c73034Schengguanghui  val eNum1H = chisel3.util.experimental.decode.decoder(sew ## (isWidenCvt || isNarrowCvt),
10866c73034Schengguanghui    TruthTable(
10966c73034Schengguanghui      Seq(                     // 8, 4, 2, 1
11066c73034Schengguanghui        BitPat("b001") -> BitPat("b1000"), //8
11166c73034Schengguanghui        BitPat("b010") -> BitPat("b1000"), //8
11266c73034Schengguanghui        BitPat("b011") -> BitPat("b0100"), //4
11366c73034Schengguanghui        BitPat("b100") -> BitPat("b0100"), //4
11466c73034Schengguanghui        BitPat("b101") -> BitPat("b0010"), //2
11566c73034Schengguanghui        BitPat("b110") -> BitPat("b0010"), //2
11666c73034Schengguanghui      ),
11766c73034Schengguanghui      BitPat.N(4)
11866c73034Schengguanghui    )
11966c73034Schengguanghui  )
120021f6af6Schengguanghui  val eNum1HEffect = Mux(isWidenCvt || isNarrowCvt, eNum1H << 1, eNum1H)
121021f6af6Schengguanghui  val eNumMax1H = Mux(lmul.head(1).asBool, eNum1HEffect >> ((~lmul.tail(1)).asUInt +1.U), eNum1HEffect << lmul.tail(1)).asUInt(6, 0)
12266c73034Schengguanghui  val eNumMax = Mux1H(eNumMax1H, Seq(1,2,4,8,16,32,64).map(i => i.U)) //only for cvt intr, don't exist 128 in cvt
123572278faSZiyue Zhang  val vlForFflags = Mux(vecCtrl.fpu.isFpToVecInst, 1.U, vl)
124572278faSZiyue Zhang  val eNumEffectIdx = Mux(vlForFflags > eNumMax, eNumMax, vlForFflags)
1259d3cebe7Schengguanghui
1269d3cebe7Schengguanghui  val eNum = Mux1H(eNum1H, Seq(1, 2, 4, 8).map(num =>num.U))
1279d3cebe7Schengguanghui  val eStart = vuopIdx * eNum
128572278faSZiyue Zhang  val maskForFflags = Mux(vecCtrl.fpu.isFpToVecInst, allMaskTrue, srcMask)
129572278faSZiyue Zhang  val maskPart = maskForFflags >> eStart
1309d3cebe7Schengguanghui  val mask =  Mux1H(eNum1H, Seq(1, 2, 4, 8).map(num => maskPart(num-1, 0)))
13166c73034Schengguanghui  val fflagsEn = Wire(Vec(4 * numVecModule, Bool()))
1329d3cebe7Schengguanghui
133ba899681Schengguanghui  fflagsEn := mask.asBools.zipWithIndex.map{case(mask, i) => mask & (eNumEffectIdx > eStart + i.U) }
13466c73034Schengguanghui
135e8e02b74SsinceforYy  val fflagsEnCycle2 = RegEnable(RegEnable(fflagsEn, fire), fireReg)
1369d3cebe7Schengguanghui  val fflagsAll = Wire(Vec(8, UInt(5.W)))
1379d3cebe7Schengguanghui  fflagsAll := vfcvtFflags.asTypeOf(fflagsAll)
13866c73034Schengguanghui  val fflags = fflagsEnCycle2.zip(fflagsAll).map{case(en, fflag) => Mux(en, fflag, 0.U(5.W))}.reduce(_ | _)
139572278faSZiyue Zhang  io.out.bits.res.fflags.get := Mux(outIsMvInst, 0.U, fflags)
14066c73034Schengguanghui
14166c73034Schengguanghui
14266c73034Schengguanghui  /**
143ba899681Schengguanghui   * [[mgu]]'s in connection
14466c73034Schengguanghui   */
145ba899681Schengguanghui  val resultDataUInt = Wire(UInt(dataWidth.W))
14666c73034Schengguanghui  resultDataUInt := vfcvtResult
14766c73034Schengguanghui
148e8e02b74SsinceforYy  private val narrow = RegEnable(RegEnable(isNarrowCvt, fire), fireReg)
14917f57ffdSZiyue Zhang  private val narrowNeedCat = outVecCtrl.vuopIdx(0).asBool && narrow
150e03e0c5bSZiyue Zhang  private val outNarrowVd = Mux(narrowNeedCat, Cat(resultDataUInt(dataWidth / 2 - 1, 0), outOldVd(dataWidth / 2 - 1, 0)),
151e03e0c5bSZiyue Zhang                                               Cat(outOldVd(dataWidth - 1, dataWidth / 2), resultDataUInt(dataWidth / 2 - 1, 0)))
15217f57ffdSZiyue Zhang
153*ac5be754Sjunxiong-ji  // mgu.io.in.vd := resultDataUInt
15417f57ffdSZiyue Zhang  mgu.io.in.vd := Mux(narrow, outNarrowVd, resultDataUInt)
15566c73034Schengguanghui  mgu.io.in.oldVd := outOldVd
15666c73034Schengguanghui  mgu.io.in.mask := maskToMgu
15766c73034Schengguanghui  mgu.io.in.info.ta := outVecCtrl.vta
15866c73034Schengguanghui  mgu.io.in.info.ma := outVecCtrl.vma
15966c73034Schengguanghui  mgu.io.in.info.vl := Mux(outVecCtrl.fpu.isFpToVecInst, 1.U, outVl)
16066c73034Schengguanghui  mgu.io.in.info.vlmul := outVecCtrl.vlmul
16166c73034Schengguanghui  mgu.io.in.info.valid := io.out.valid
16266c73034Schengguanghui  mgu.io.in.info.vstart := Mux(outVecCtrl.fpu.isFpToVecInst, 0.U, outVecCtrl.vstart)
16366c73034Schengguanghui  mgu.io.in.info.eew := outEew
16466c73034Schengguanghui  mgu.io.in.info.vsew := outVecCtrl.vsew
16566c73034Schengguanghui  mgu.io.in.info.vdIdx := outVecCtrl.vuopIdx
16617f57ffdSZiyue Zhang  mgu.io.in.info.narrow := narrow
16766c73034Schengguanghui  mgu.io.in.info.dstMask := outVecCtrl.isDstMask
16892c6b7edSzhanglinjuan  mgu.io.in.isIndexedVls := false.B
16966c73034Schengguanghui
170572278faSZiyue Zhang  // for scalar f2i cvt inst
171572278faSZiyue Zhang  val isFp2VecForInt = outVecCtrl.fpu.isFpToVecInst && outIs32bits && outIsInt
172572278faSZiyue Zhang  // for f2i mv inst
173572278faSZiyue Zhang  val result = Mux(outIsMvInst, RegNext(RegNext(vs2.tail(64))), mgu.io.out.vd)
174572278faSZiyue Zhang
175572278faSZiyue Zhang  io.out.bits.res.data := Mux(isFp2VecForInt,
176572278faSZiyue Zhang    Fill(32, result(31)) ## result(31, 0),
177572278faSZiyue Zhang    result
178572278faSZiyue Zhang  )
179c33d4a9eSXuan Hu  io.out.bits.ctrl.exceptionVec.get(ExceptionNO.illegalInstr) := mgu.io.out.illegal
18066c73034Schengguanghui}
18166c73034Schengguanghui
1829d3cebe7Schengguanghuiclass VectorCvtTopIO(vlen: Int, xlen: Int) extends Bundle{
183e8e02b74SsinceforYy  val fire = Input(Bool())
1849d3cebe7Schengguanghui  val uopIdx = Input(Bool())
18566c73034Schengguanghui  val src = Input(Vec(vlen / xlen, UInt(xlen.W)))
18666c73034Schengguanghui  val opType = Input(UInt(8.W))
18766c73034Schengguanghui  val sew = Input(UInt(2.W))
18866c73034Schengguanghui  val rm = Input(UInt(3.W))
18966c73034Schengguanghui  val outputWidth1H = Input(UInt(4.W))
19066c73034Schengguanghui  val isWiden = Input(Bool())
19166c73034Schengguanghui  val isNarrow = Input(Bool())
1929626da3aSchengguanghui  val isFpToVecInst = Input(Bool())
19366c73034Schengguanghui
1949d3cebe7Schengguanghui  val result = Output(UInt(vlen.W))
1959d3cebe7Schengguanghui  val fflags = Output(UInt((vlen/16*5).W))
1969d3cebe7Schengguanghui}
1979d3cebe7Schengguanghui
1989d3cebe7Schengguanghui
1999d3cebe7Schengguanghui
2009d3cebe7Schengguanghui//according to uopindex, 1: high64 0:low64
2019d3cebe7Schengguanghuiclass VectorCvtTop(vlen: Int, xlen: Int) extends Module{
2029d3cebe7Schengguanghui  val io = IO(new VectorCvtTopIO(vlen, xlen))
2039d3cebe7Schengguanghui
2049626da3aSchengguanghui  val (fire, uopIdx, src, opType, sew, rm, outputWidth1H, isWiden, isNarrow, isFpToVecInst) = (
2059626da3aSchengguanghui    io.fire, io.uopIdx, io.src, io.opType, io.sew, io.rm, io.outputWidth1H, io.isWiden, io.isNarrow, io.isFpToVecInst
2069d3cebe7Schengguanghui  )
2075f8b6c9eSsinceforYy  val fireReg = GatedValidRegNext(fire)
20866c73034Schengguanghui
2099626da3aSchengguanghui  val in0 = Mux(isWiden && !isFpToVecInst,
2109d3cebe7Schengguanghui    Mux(uopIdx, src(1).tail(32), src(0).tail(32)),
21166c73034Schengguanghui    src(0)
21266c73034Schengguanghui  )
21366c73034Schengguanghui
21466c73034Schengguanghui  val in1 = Mux(isWiden,
2159d3cebe7Schengguanghui    Mux(uopIdx, src(1).head(32), src(0).head(32)),
21666c73034Schengguanghui    src(1)
21766c73034Schengguanghui  )
21866c73034Schengguanghui
21966c73034Schengguanghui  val vectorCvt0 = Module(new VectorCvt(xlen))
220e8e02b74SsinceforYy  vectorCvt0.fire := fire
22166c73034Schengguanghui  vectorCvt0.src := in0
22266c73034Schengguanghui  vectorCvt0.opType := opType
22366c73034Schengguanghui  vectorCvt0.sew := sew
22466c73034Schengguanghui  vectorCvt0.rm := rm
2259626da3aSchengguanghui  vectorCvt0.isFpToVecInst := isFpToVecInst
22620b2b626SsinceforYy  vectorCvt0.isFround := 0.U
22720b2b626SsinceforYy  vectorCvt0.isFcvtmod := false.B
22866c73034Schengguanghui
22966c73034Schengguanghui  val vectorCvt1 = Module(new VectorCvt(xlen))
230e8e02b74SsinceforYy  vectorCvt1.fire := fire
23166c73034Schengguanghui  vectorCvt1.src := in1
23266c73034Schengguanghui  vectorCvt1.opType := opType
23366c73034Schengguanghui  vectorCvt1.sew := sew
23466c73034Schengguanghui  vectorCvt1.rm := rm
2359626da3aSchengguanghui  vectorCvt1.isFpToVecInst := isFpToVecInst
23620b2b626SsinceforYy  vectorCvt1.isFround := 0.U
23720b2b626SsinceforYy  vectorCvt1.isFcvtmod := false.B
23866c73034Schengguanghui
239e8e02b74SsinceforYy  val isNarrowCycle2 = RegEnable(RegEnable(isNarrow, fire), fireReg)
240e8e02b74SsinceforYy  val outputWidth1HCycle2 = RegEnable(RegEnable(outputWidth1H, fire), fireReg)
24166c73034Schengguanghui
24266c73034Schengguanghui  //cycle2
2439d3cebe7Schengguanghui  io.result := Mux(isNarrowCycle2,
24466c73034Schengguanghui    vectorCvt1.io.result.tail(32) ## vectorCvt0.io.result.tail(32),
2459d3cebe7Schengguanghui    vectorCvt1.io.result ## vectorCvt0.io.result)
24666c73034Schengguanghui
247ba899681Schengguanghui  io.fflags := Mux1H(outputWidth1HCycle2, Seq(
24866c73034Schengguanghui    vectorCvt1.io.fflags ## vectorCvt0.io.fflags,
24966c73034Schengguanghui    Mux(isNarrowCycle2, vectorCvt1.io.fflags.tail(10) ## vectorCvt0.io.fflags.tail(10), vectorCvt1.io.fflags ## vectorCvt0.io.fflags),
25066c73034Schengguanghui    Mux(isNarrowCycle2, vectorCvt1.io.fflags(4,0) ## vectorCvt0.io.fflags(4,0), vectorCvt1.io.fflags.tail(10) ## vectorCvt0.io.fflags.tail(10)),
25166c73034Schengguanghui    vectorCvt1.io.fflags(4,0) ## vectorCvt0.io.fflags(4,0)
25266c73034Schengguanghui  ))
25366c73034Schengguanghui}
25466c73034Schengguanghui
25566c73034Schengguanghui
256