xref: /XiangShan/src/main/scala/xiangshan/backend/fu/vector/Mgu.scala (revision cfc9efe485ccfae2c94a79bc4eb8e9ef61344f0a)
1ff38b6c7SXuan Hu/****************************************************************************************
2ff38b6c7SXuan Hu * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3ff38b6c7SXuan Hu * Copyright (c) 2020-2021 Peng Cheng Laboratory
4ff38b6c7SXuan Hu *
5ff38b6c7SXuan Hu * XiangShan is licensed under Mulan PSL v2.
6ff38b6c7SXuan Hu * You can use this software according to the terms and conditions of the Mulan PSL v2.
7ff38b6c7SXuan Hu * You may obtain a copy of Mulan PSL v2 at:
8ff38b6c7SXuan Hu *          http://license.coscl.org.cn/MulanPSL2
9ff38b6c7SXuan Hu *
10ff38b6c7SXuan Hu * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11ff38b6c7SXuan Hu * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12ff38b6c7SXuan Hu * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13ff38b6c7SXuan Hu *
14ff38b6c7SXuan Hu * See the Mulan PSL v2 for more details.
15ff38b6c7SXuan Hu ****************************************************************************************
16ff38b6c7SXuan Hu */
17ff38b6c7SXuan Hu
18ff38b6c7SXuan Hu
19ff38b6c7SXuan Hupackage xiangshan.backend.fu.vector
20ff38b6c7SXuan Hu
2183ba63b3SXuan Huimport org.chipsalliance.cde.config.Parameters
22ff38b6c7SXuan Huimport chisel3._
23ff38b6c7SXuan Huimport chisel3.util._
24f1f37ec2SXuan Huimport chiseltest._
25f1f37ec2SXuan Huimport chiseltest.ChiselScalatestTester
26f1f37ec2SXuan Huimport org.scalatest.flatspec.AnyFlatSpec
27f1f37ec2SXuan Huimport org.scalatest.matchers.must.Matchers
28f1f37ec2SXuan Huimport top.{ArgParser, BaseConfig, DefaultConfig}
29f1f37ec2SXuan Huimport xiangshan._
30f1f37ec2SXuan Huimport xiangshan.backend.fu.vector.Bundles.{VSew, Vl}
31f1f37ec2SXuan Huimport xiangshan.backend.fu.vector.Utils.VecDataToMaskDataVec
32ff38b6c7SXuan Huimport yunsuan.vector._
33ff38b6c7SXuan Hu
34f1f37ec2SXuan Huclass Mgu(vlen: Int)(implicit p: Parameters) extends  Module {
35f1f37ec2SXuan Hu  private val numBytes = vlen / 8
36f1f37ec2SXuan Hu  private val byteWidth = log2Up(numBytes)
37f1f37ec2SXuan Hu
38f1f37ec2SXuan Hu  val io = IO(new MguIO(vlen))
39ff38b6c7SXuan Hu
40ff38b6c7SXuan Hu  val in = io.in
41ff38b6c7SXuan Hu  val out = io.out
42ff38b6c7SXuan Hu  val info = in.info
43cdf8c16cSxgkiri  val vd = in.vd
44cdf8c16cSxgkiri  val oldVd = in.oldVd
45cdf8c16cSxgkiri  val narrow = io.in.info.narrow
46cdf8c16cSxgkiri
47cdf8c16cSxgkiri  private val vdIdx = Mux(narrow, info.vdIdx(2, 1), info.vdIdx)
48ff38b6c7SXuan Hu
49f1f37ec2SXuan Hu  private val maskTailGen = Module(new ByteMaskTailGen(vlen))
50ff38b6c7SXuan Hu
51f1f37ec2SXuan Hu  private val eewOH = SewOH(info.eew).oneHot
52ff38b6c7SXuan Hu
533c14c53aSXuan Hu  private val vstartMapVdIdx = elemIdxMapVdIdx(info.vstart)(2, 0) // 3bits 0~7
543c14c53aSXuan Hu  private val vlMapVdIdx = elemIdxMapVdIdx(info.vl)(3, 0)         // 4bits 0~8
55f1f37ec2SXuan Hu  private val uvlMax = numBytes.U >> info.eew
56b3e2881cSxiaofeibao-xjtu  private val uvlMaxForAssert = numBytes.U >> info.vsew
57b3e2881cSxiaofeibao-xjtu  private val vlMaxForAssert = Mux(io.in.info.vlmul(2), uvlMaxForAssert >> (-io.in.info.vlmul), uvlMaxForAssert << io.in.info.vlmul).asUInt
58c33d4a9eSXuan Hu
5992c6b7edSzhanglinjuan  private val realEw = Mux(in.isIndexedVls, info.vsew, info.eew)
60a45913c6Szhanglinjuan  private val maskDataVec: Vec[UInt] = VecDataToMaskDataVec(in.mask, realEw)
6184286fdbSAnzooooo  protected lazy val maskUsed = maskDataVec(vdIdx)
6292c6b7edSzhanglinjuan
63494bf430Szhanglinjuan  maskTailGen.io.in.begin := info.vstart /*Mux1H(Seq(
64cdf8c16cSxgkiri    (vstartMapVdIdx < vdIdx) -> 0.U,
65cdf8c16cSxgkiri    (vstartMapVdIdx === vdIdx) -> elemIdxMapUElemIdx(info.vstart),
66cdf8c16cSxgkiri    (vstartMapVdIdx > vdIdx) -> uvlMax,
67494bf430Szhanglinjuan  ))*/
68494bf430Szhanglinjuan  maskTailGen.io.in.end := info.vl /*Mux1H(Seq(
69cdf8c16cSxgkiri    (vlMapVdIdx < vdIdx) -> 0.U,
70cdf8c16cSxgkiri    (vlMapVdIdx === vdIdx) -> elemIdxMapUElemIdx(info.vl),
71cdf8c16cSxgkiri    (vlMapVdIdx > vdIdx) -> uvlMax,
72494bf430Szhanglinjuan  ))*/
73f1f37ec2SXuan Hu  maskTailGen.io.in.vma := info.ma
74f1f37ec2SXuan Hu  maskTailGen.io.in.vta := info.ta
7592c6b7edSzhanglinjuan  maskTailGen.io.in.vsew := realEw
76f1f37ec2SXuan Hu  maskTailGen.io.in.maskUsed := maskUsed
77904d2184SZiyue Zhang  maskTailGen.io.in.vdIdx := vdIdx
78f1f37ec2SXuan Hu
7979d52256Schengguanghui  private val activeEn = maskTailGen.io.out.activeEn
80f1f37ec2SXuan Hu  private val agnosticEn = maskTailGen.io.out.agnosticEn
81f1f37ec2SXuan Hu
82cdf8c16cSxgkiri  // the result of normal inst and narrow inst which does not need concat
83f1f37ec2SXuan Hu  private val byte1s: UInt = (~0.U(8.W)).asUInt
84f1f37ec2SXuan Hu
85cdf8c16cSxgkiri  private val resVecByte = Wire(Vec(numBytes, UInt(8.W)))
86cdf8c16cSxgkiri  private val vdVecByte = vd.asTypeOf(resVecByte)
87cdf8c16cSxgkiri  private val oldVdVecByte = oldVd.asTypeOf(resVecByte)
88f1f37ec2SXuan Hu
89f1f37ec2SXuan Hu  for (i <- 0 until numBytes) {
90cdf8c16cSxgkiri    resVecByte(i) := MuxCase(oldVdVecByte(i), Seq(
9179d52256Schengguanghui      activeEn(i) -> vdVecByte(i),
92f1f37ec2SXuan Hu      agnosticEn(i) -> byte1s,
93f1f37ec2SXuan Hu    ))
94ff38b6c7SXuan Hu  }
95ff38b6c7SXuan Hu
96*cfc9efe4SZiyue Zhang  // mask vd is at most 16 bits
97*cfc9efe4SZiyue Zhang  private val maskOldVdBits = splitVdMask(oldVd, SewOH(info.eew))(vdIdx)
98*cfc9efe4SZiyue Zhang  private val maskBits = splitVdMask(in.mask, SewOH(info.eew))(vdIdx)
99*cfc9efe4SZiyue Zhang  private val maskVecByte = Wire(Vec(numBytes, UInt(1.W)))
100*cfc9efe4SZiyue Zhang  maskVecByte.zipWithIndex.foreach { case (mask, i) =>
101*cfc9efe4SZiyue Zhang    mask := Mux(maskBits(i), vd(i), Mux(info.ma, 1.U, maskOldVdBits(i)))
102*cfc9efe4SZiyue Zhang  }
103*cfc9efe4SZiyue Zhang  private val maskVd = maskVecByte.asUInt
104*cfc9efe4SZiyue Zhang
105cdf8c16cSxgkiri  // the result of mask-generating inst
106cdf8c16cSxgkiri  private val maxVdIdx = 8
107cdf8c16cSxgkiri  private val meaningfulBitsSeq = Seq(16, 8, 4, 2)
108cdf8c16cSxgkiri  private val allPossibleResBit = Wire(Vec(4, Vec(maxVdIdx, UInt(vlen.W))))
109cdf8c16cSxgkiri
110cdf8c16cSxgkiri  for (sew <- 0 to 3) {
111cdf8c16cSxgkiri    if (sew == 0) {
112*cfc9efe4SZiyue Zhang      allPossibleResBit(sew)(maxVdIdx - 1) := Cat(maskVd(meaningfulBitsSeq(sew) - 1, 0),
113cdf8c16cSxgkiri        oldVd(meaningfulBitsSeq(sew) * (maxVdIdx - 1) - 1, 0))
114cdf8c16cSxgkiri    } else {
115*cfc9efe4SZiyue Zhang      allPossibleResBit(sew)(maxVdIdx - 1) := Cat(oldVd(vlen - 1, meaningfulBitsSeq(sew) * maxVdIdx),
116*cfc9efe4SZiyue Zhang        maskVd(meaningfulBitsSeq(sew) - 1, 0), oldVd(meaningfulBitsSeq(sew) * (maxVdIdx - 1) - 1, 0))
117cdf8c16cSxgkiri    }
118cdf8c16cSxgkiri    for (i <- 1 until maxVdIdx - 1) {
119*cfc9efe4SZiyue Zhang      allPossibleResBit(sew)(i) := Cat(oldVd(vlen - 1, meaningfulBitsSeq(sew) * (i + 1)),
120*cfc9efe4SZiyue Zhang        maskVd(meaningfulBitsSeq(sew) - 1, 0), oldVd(meaningfulBitsSeq(sew) * i - 1, 0))
121cdf8c16cSxgkiri    }
122*cfc9efe4SZiyue Zhang    allPossibleResBit(sew)(0) := Cat(oldVd(vlen - 1, meaningfulBitsSeq(sew)), maskVd(meaningfulBitsSeq(sew) - 1, 0))
123cdf8c16cSxgkiri  }
124cdf8c16cSxgkiri
125cdf8c16cSxgkiri  private val resVecBit = allPossibleResBit(info.eew)(vdIdx)
126cdf8c16cSxgkiri
127cdf8c16cSxgkiri  io.out.vd := MuxCase(resVecByte.asUInt, Seq(
128cdf8c16cSxgkiri    info.dstMask -> resVecBit.asUInt,
129cdf8c16cSxgkiri  ))
13079d52256Schengguanghui  io.out.active := activeEn
13154cc3a06STang Haojin  io.out.illegal := false.B // (info.vl > vlMaxForAssert) && info.valid
132ff38b6c7SXuan Hu
133f1f37ec2SXuan Hu  io.debugOnly.vstartMapVdIdx := vstartMapVdIdx
134f1f37ec2SXuan Hu  io.debugOnly.vlMapVdIdx := vlMapVdIdx
135f1f37ec2SXuan Hu  io.debugOnly.begin := maskTailGen.io.in.begin
136f1f37ec2SXuan Hu  io.debugOnly.end := maskTailGen.io.in.end
13779d52256Schengguanghui  io.debugOnly.activeEn := activeEn
138f1f37ec2SXuan Hu  io.debugOnly.agnosticEn := agnosticEn
139f1f37ec2SXuan Hu  def elemIdxMapVdIdx(elemIdx: UInt) = {
140f1f37ec2SXuan Hu    require(elemIdx.getWidth >= log2Up(vlen))
141f1f37ec2SXuan Hu    // 3 = log2(8)
1423c14c53aSXuan Hu    Mux1H(eewOH, Seq.tabulate(eewOH.getWidth)(x => elemIdx(byteWidth - x + 3, byteWidth - x)))
143f1f37ec2SXuan Hu  }
144f1f37ec2SXuan Hu
145f1f37ec2SXuan Hu  def elemIdxMapUElemIdx(elemIdx: UInt) = {
146f1f37ec2SXuan Hu    Mux1H(eewOH, Seq.tabulate(eewOH.getWidth)(x => elemIdx(byteWidth - x - 1, 0)))
147f1f37ec2SXuan Hu  }
148*cfc9efe4SZiyue Zhang
149*cfc9efe4SZiyue Zhang  def splitVdMask(maskIn: UInt, sew: SewOH): Vec[UInt] = {
150*cfc9efe4SZiyue Zhang    val maskWidth = maskIn.getWidth
151*cfc9efe4SZiyue Zhang    val result = Wire(Vec(maskWidth / numBytes, UInt(numBytes.W)))
152*cfc9efe4SZiyue Zhang    for ((resultData, i) <- result.zipWithIndex) {
153*cfc9efe4SZiyue Zhang      resultData := Mux1H(Seq(
154*cfc9efe4SZiyue Zhang        sew.is8 -> maskIn(i * numBytes + (numBytes - 1), i * numBytes),
155*cfc9efe4SZiyue Zhang        sew.is16 -> Cat(0.U((numBytes - (numBytes / 2)).W), maskIn(i * (numBytes / 2) + (numBytes / 2) - 1, i * (numBytes / 2))),
156*cfc9efe4SZiyue Zhang        sew.is32 -> Cat(0.U((numBytes - (numBytes / 4)).W), maskIn(i * (numBytes / 4) + (numBytes / 4) - 1, i * (numBytes / 4))),
157*cfc9efe4SZiyue Zhang        sew.is64 -> Cat(0.U((numBytes - (numBytes / 8)).W), maskIn(i * (numBytes / 8) + (numBytes / 8) - 1, i * (numBytes / 8))),
158*cfc9efe4SZiyue Zhang      ))
159*cfc9efe4SZiyue Zhang    }
160*cfc9efe4SZiyue Zhang    result
161*cfc9efe4SZiyue Zhang  }
162f1f37ec2SXuan Hu}
163f1f37ec2SXuan Hu
16484286fdbSAnzoooooclass VldMgu(vlen: Int)(implicit p: Parameters) extends Mgu(vlen) {
16584286fdbSAnzooooo  override lazy val maskUsed = in.mask(15, 0)
16684286fdbSAnzooooo}
167f1f37ec2SXuan Hu
168f1f37ec2SXuan Huclass MguIO(vlen: Int)(implicit p: Parameters) extends Bundle {
169ff38b6c7SXuan Hu  val in = new Bundle {
170f1f37ec2SXuan Hu    val vd = Input(UInt(vlen.W))
171f1f37ec2SXuan Hu    val oldVd = Input(UInt(vlen.W))
172f1f37ec2SXuan Hu    val mask = Input(UInt(vlen.W))
173ff38b6c7SXuan Hu    val info = Input(new VecInfo)
17492c6b7edSzhanglinjuan    val isIndexedVls = Input(Bool())
175ff38b6c7SXuan Hu  }
176ff38b6c7SXuan Hu  val out = new Bundle {
177f1f37ec2SXuan Hu    val vd = Output(UInt(vlen.W))
17879d52256Schengguanghui    val active = Output(UInt((vlen / 8).W))
179c33d4a9eSXuan Hu    val illegal = Output(Bool())
180ff38b6c7SXuan Hu  }
181f1f37ec2SXuan Hu  val debugOnly = Output(new Bundle {
182f1f37ec2SXuan Hu    val vstartMapVdIdx = UInt()
183f1f37ec2SXuan Hu    val vlMapVdIdx = UInt()
184f1f37ec2SXuan Hu    val begin = UInt()
185f1f37ec2SXuan Hu    val end = UInt()
18679d52256Schengguanghui    val activeEn = UInt()
187f1f37ec2SXuan Hu    val agnosticEn = UInt()
188f1f37ec2SXuan Hu  })
189ff38b6c7SXuan Hu}
190ff38b6c7SXuan Hu
191f1f37ec2SXuan Huclass VecInfo(implicit p: Parameters) extends Bundle {
192ff38b6c7SXuan Hu  val ta = Bool()
193ff38b6c7SXuan Hu  val ma = Bool()
194f1f37ec2SXuan Hu  val vl = Vl()
195f1f37ec2SXuan Hu  val vstart = Vl()
196f1f37ec2SXuan Hu  val eew = VSew()
197b3e2881cSxiaofeibao-xjtu  val vsew = VSew()
198f1f37ec2SXuan Hu  val vdIdx = UInt(3.W) // 0~7
199b3e2881cSxiaofeibao-xjtu  val vlmul = UInt(3.W)
200b3e2881cSxiaofeibao-xjtu  val valid = Bool()
201cdf8c16cSxgkiri  val narrow = Bool()
202cdf8c16cSxgkiri  val dstMask = Bool()
203ff38b6c7SXuan Hu}
204ff38b6c7SXuan Hu
205ff38b6c7SXuan Huobject VerilogMgu extends App {
206ff38b6c7SXuan Hu  println("Generating the Mgu hardware")
2076ce10964SXuan Hu  val (config, firrtlOpts, firtoolOpts) = ArgParser.parse(args)
208f1f37ec2SXuan Hu  val p = config.alterPartial({case XSCoreParamsKey => config(XSTileKey).head})
209f1f37ec2SXuan Hu
210cdf8c16cSxgkiri  emitVerilog(new Mgu(128)(p), Array("--target-dir", "build/vifu", "--full-stacktrace"))
211f1f37ec2SXuan Hu}
212f1f37ec2SXuan Hu
213f1f37ec2SXuan Huclass MguTest extends AnyFlatSpec with ChiselScalatestTester with Matchers {
214f1f37ec2SXuan Hu
215f1f37ec2SXuan Hu  val defaultConfig = (new DefaultConfig).alterPartial({
216f1f37ec2SXuan Hu    case XSCoreParamsKey => XSCoreParameters()
217f1f37ec2SXuan Hu  })
218f1f37ec2SXuan Hu
219f1f37ec2SXuan Hu  println("test start")
220f1f37ec2SXuan Hu
221f1f37ec2SXuan Hu  behavior of "Mgu"
222f1f37ec2SXuan Hu  it should "run" in {
223f1f37ec2SXuan Hu    test(new Mgu(128)(defaultConfig)).withAnnotations(Seq(VerilatorBackendAnnotation)) {
224f1f37ec2SXuan Hu      m: Mgu =>
225f1f37ec2SXuan Hu        m.io.in.vd.poke("h8765_4321_8765_4321_8765_4321_8765_4321".U)
226f1f37ec2SXuan Hu        m.io.in.oldVd.poke("h7777_7777_7777_7777_7777_7777_7777_7777".U)
227f1f37ec2SXuan Hu        m.io.in.mask.poke("h0000_0000_0000_0000_0000_0000_ffff_0000".U)
228f1f37ec2SXuan Hu        m.io.in.info.ta.poke(true.B)
229f1f37ec2SXuan Hu        m.io.in.info.ma.poke(false.B)
230f1f37ec2SXuan Hu        m.io.in.info.vl.poke((16 + 7).U)
231f1f37ec2SXuan Hu        m.io.in.info.vstart.poke((16 + 2).U)
232f1f37ec2SXuan Hu        m.io.in.info.eew.poke(VSew.e8)
233f1f37ec2SXuan Hu        m.io.in.info.vdIdx.poke(1.U)
234f1f37ec2SXuan Hu
235f1f37ec2SXuan Hu        println("out.vd: " + m.io.out.vd.peek().litValue.toString(16))
236f1f37ec2SXuan Hu        println("debugOnly.vstartMapVdIdx: " + m.io.debugOnly.vstartMapVdIdx.peek().litValue.toString(16))
237f1f37ec2SXuan Hu        println("debugOnly.vlMapVdIdx: "     + m.io.debugOnly.vlMapVdIdx.peek().litValue.toString(16))
238f1f37ec2SXuan Hu        println("debugOnly.begin: "          + m.io.debugOnly.begin.peek().litValue)
239f1f37ec2SXuan Hu        println("debugOnly.end: "            + m.io.debugOnly.end.peek().litValue)
24079d52256Schengguanghui        println("debugOnly.activeEn: "         + m.io.debugOnly.activeEn.peek().litValue.toString(2))
241f1f37ec2SXuan Hu        println("debugOnly.agnosticEn: "     + m.io.debugOnly.agnosticEn.peek().litValue.toString(2))
242f1f37ec2SXuan Hu    }
243f1f37ec2SXuan Hu    println("test done")
244f1f37ec2SXuan Hu  }
245ff38b6c7SXuan Hu}