xref: /XiangShan/src/main/scala/xiangshan/backend/fu/vector/Mgu.scala (revision 92b88f30156d46e844042eea94f7121557fd09a1)
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 chipsalliance.rocketchip.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
44  private val maskTailGen = Module(new ByteMaskTailGen(vlen))
45
46  private val eewOH = SewOH(info.eew).oneHot
47
48  private val vstartMapVdIdx = elemIdxMapVdIdx(info.vstart)(2, 0) // 3bits 0~7
49  private val vlMapVdIdx = elemIdxMapVdIdx(info.vl)(3, 0)         // 4bits 0~8
50  private val uvlMax = numBytes.U >> info.eew
51  private val maskDataVec: Vec[UInt] = VecDataToMaskDataVec(in.mask, info.eew)
52  private val maskUsed = maskDataVec(info.vdIdx)
53
54  maskTailGen.io.in.begin := Mux1H(Seq(
55    (vstartMapVdIdx < info.vdIdx) -> 0.U,
56    (vstartMapVdIdx === info.vdIdx) -> elemIdxMapUElemIdx(info.vstart),
57    (vstartMapVdIdx > info.vdIdx) -> uvlMax,
58  ))
59  maskTailGen.io.in.end := Mux1H(Seq(
60    (vlMapVdIdx < info.vdIdx) -> 0.U,
61    (vlMapVdIdx === info.vdIdx) -> elemIdxMapUElemIdx(info.vl),
62    (vlMapVdIdx > info.vdIdx) -> uvlMax,
63  ))
64  maskTailGen.io.in.vma := info.ma
65  maskTailGen.io.in.vta := info.ta
66  maskTailGen.io.in.vsew := info.eew
67  maskTailGen.io.in.maskUsed := maskUsed
68
69  private val keepEn = maskTailGen.io.out.keepEn
70  private val agnosticEn = maskTailGen.io.out.agnosticEn
71
72  private val byte1s: UInt = (~0.U(8.W)).asUInt
73
74  private val resVec = Wire(Vec(numBytes, UInt(8.W)))
75  private val vdVec = io.in.vd.asTypeOf(resVec)
76  private val oldVdVec = io.in.oldVd.asTypeOf(resVec)
77
78  for (i <- 0 until numBytes) {
79    resVec(i) := MuxCase(oldVdVec(i), Seq(
80      keepEn(i) -> vdVec(i),
81      agnosticEn(i) -> byte1s,
82    ))
83  }
84
85  io.out.vd := resVec.asUInt
86
87  io.debugOnly.vstartMapVdIdx := vstartMapVdIdx
88  io.debugOnly.vlMapVdIdx := vlMapVdIdx
89  io.debugOnly.begin := maskTailGen.io.in.begin
90  io.debugOnly.end := maskTailGen.io.in.end
91  io.debugOnly.keepEn := keepEn
92  io.debugOnly.agnosticEn := agnosticEn
93  def elemIdxMapVdIdx(elemIdx: UInt) = {
94    require(elemIdx.getWidth >= log2Up(vlen))
95    // 3 = log2(8)
96    Mux1H(eewOH, Seq.tabulate(eewOH.getWidth)(x => elemIdx(byteWidth - x + 3, byteWidth - x)))
97  }
98
99  def elemIdxMapUElemIdx(elemIdx: UInt) = {
100    Mux1H(eewOH, Seq.tabulate(eewOH.getWidth)(x => elemIdx(byteWidth - x - 1, 0)))
101  }
102}
103
104
105class MguIO(vlen: Int)(implicit p: Parameters) extends Bundle {
106  val in = new Bundle {
107    val vd = Input(UInt(vlen.W))
108    val oldVd = Input(UInt(vlen.W))
109    val mask = Input(UInt(vlen.W))
110    val info = Input(new VecInfo)
111  }
112  val out = new Bundle {
113    val vd = Output(UInt(vlen.W))
114  }
115  val debugOnly = Output(new Bundle {
116    val vstartMapVdIdx = UInt()
117    val vlMapVdIdx = UInt()
118    val begin = UInt()
119    val end = UInt()
120    val keepEn = UInt()
121    val agnosticEn = UInt()
122  })
123}
124
125class VecInfo(implicit p: Parameters) extends Bundle {
126  val ta = Bool()
127  val ma = Bool()
128  val vl = Vl()
129  val vstart = Vl()
130  val eew = VSew()
131  val vdIdx = UInt(3.W) // 0~7
132}
133
134object VerilogMgu extends App {
135  println("Generating the Mgu hardware")
136  val (config, firrtlOpts, firrtlComplier, firtoolOpts) = ArgParser.parse(args)
137  val p = config.alterPartial({case XSCoreParamsKey => config(XSTileKey).head})
138
139  emitVerilog(new Mgu(128)(p), Array("--target-dir", "build/vifu"))
140}
141
142class MguTest extends AnyFlatSpec with ChiselScalatestTester with Matchers {
143
144  val defaultConfig = (new DefaultConfig).alterPartial({
145    case XSCoreParamsKey => XSCoreParameters()
146  })
147
148  println("test start")
149
150  behavior of "Mgu"
151  it should "run" in {
152    test(new Mgu(128)(defaultConfig)).withAnnotations(Seq(VerilatorBackendAnnotation)) {
153      m: Mgu =>
154        m.io.in.vd.poke("h8765_4321_8765_4321_8765_4321_8765_4321".U)
155        m.io.in.oldVd.poke("h7777_7777_7777_7777_7777_7777_7777_7777".U)
156        m.io.in.mask.poke("h0000_0000_0000_0000_0000_0000_ffff_0000".U)
157        m.io.in.info.ta.poke(true.B)
158        m.io.in.info.ma.poke(false.B)
159        m.io.in.info.vl.poke((16 + 7).U)
160        m.io.in.info.vstart.poke((16 + 2).U)
161        m.io.in.info.eew.poke(VSew.e8)
162        m.io.in.info.vdIdx.poke(1.U)
163
164        println("out.vd: " + m.io.out.vd.peek().litValue.toString(16))
165        println("debugOnly.vstartMapVdIdx: " + m.io.debugOnly.vstartMapVdIdx.peek().litValue.toString(16))
166        println("debugOnly.vlMapVdIdx: "     + m.io.debugOnly.vlMapVdIdx.peek().litValue.toString(16))
167        println("debugOnly.begin: "          + m.io.debugOnly.begin.peek().litValue)
168        println("debugOnly.end: "            + m.io.debugOnly.end.peek().litValue)
169        println("debugOnly.keepEn: "         + m.io.debugOnly.keepEn.peek().litValue.toString(2))
170        println("debugOnly.agnosticEn: "     + m.io.debugOnly.agnosticEn.peek().litValue.toString(2))
171    }
172    println("test done")
173  }
174}