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}