xref: /XiangShan/src/main/scala/xiangshan/backend/fu/vector/utils/UIntToCont0s.scala (revision 6ce1096467c77f9a13c9ea0e57b870cd1fb67270)
1package xiangshan.backend.fu.vector.utils
2
3import chisel3._
4import chisel3.util._
5import chiseltest._
6import org.scalatest.flatspec.AnyFlatSpec
7import org.scalatest.matchers.must.Matchers
8import xiangshan.backend.fu.vector.Utils.{NOnes, NZeros}
9
10class UIntToContLow0s(uintWidth: Int) extends Module {
11  private val outWidth = (1 << uintWidth) - 1 // 2^n - 1
12
13  val io = IO(new Bundle {
14    val dataIn = Input(UInt(uintWidth.W))
15    val dataOut = Output(UInt(outWidth.W))
16  })
17
18  io.dataOut := helper(io.dataIn)
19
20  private def helper(data: UInt): UInt = data.getWidth match {
21    case 1 => Mux(data(0), 0.U(1.W), 1.U(1.W))
22    case w => Mux(
23      data(w - 1),
24      Cat(helper(data(w - 2, 0)), NZeros(1 << (w - 1))),
25      Cat(NOnes(1 << (w - 1)), helper(data(w - 2, 0)))
26    )
27  }
28}
29
30object UIntToContLow0s {
31  def apply(uint: UInt): UInt = apply(uint, uint.getWidth)
32
33  def apply(uint: UInt, width: Int): UInt = {
34    val uintToContTail0sMod = Module(new UIntToContLow0s(uint.getWidth)).suggestName(s"uintToContTail0sMod${width}Bits")
35    uintToContTail0sMod.io.dataIn := uint
36    val dataOutWidth = uintToContTail0sMod.io.dataOut.getWidth
37    if (width <= dataOutWidth) {
38      uintToContTail0sMod.io.dataOut(width - 1, 0)
39    } else {
40      Cat(0.U((width - dataOutWidth).W), uintToContTail0sMod.io.dataOut)
41    }
42  }
43}
44
45object UIntToContHigh0s {
46  def apply(uint: UInt): UInt = Reverse(UIntToContLow0s(uint))
47  def apply(uint: UInt, width: Int): UInt = Reverse(UIntToContLow0s(uint, width))
48}
49
50class UIntToContLow0sTest extends AnyFlatSpec with ChiselScalatestTester with Matchers {
51
52  private val uintWidth = 3
53  private val outWidth = (1 << uintWidth) - 1
54
55  private val testSeq = Seq(
56    0.U  -> "b1111111".U,
57    1.U  -> "b1111110".U,
58    2.U  -> "b1111100".U,
59    3.U  -> "b1111000".U,
60    4.U  -> "b1110000".U,
61    5.U  -> "b1100000".U,
62    6.U  -> "b1000000".U,
63    7.U  -> "b0000000".U,
64  )
65
66  behavior of "UIntToContLow0s"
67  it should "run" in {
68    test(new UIntToContLow0s(uintWidth)) {
69      m: UIntToContLow0s =>
70        for (((uint, res), i) <- testSeq.zipWithIndex) {
71          m.io.dataIn.poke(uint)
72
73          val message = "i: " + i +
74            " uint: " + uint.litValue.toInt.toBinaryString +
75            " right result: " + res.litValue.toInt.toBinaryString
76
77          m.io.dataOut.expect(res, message)
78        }
79    }
80  }
81  println("test done")
82}