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