From a3abb58338c0eed89193cae007a0cba6c2768b37 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 17 May 2023 13:03:20 -0700 Subject: [PATCH] Optimize BitPat equals, overlap, and cover (#3285) (cherry picked from commit f590ac9fd86b02d7c2e243b0600d44807218547e) --- src/main/scala/chisel3/util/BitPat.scala | 18 ++++++- .../scala/chiselTests/util/BitSetSpec.scala | 51 +++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 9aef5aeeb02..27ca92defbd 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -327,6 +327,14 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int) def =/=(that: UInt): Bool = macro SourceInfoTransform.thatArg def ##(that: BitPat): BitPat = macro SourceInfoTransform.thatArg + override def equals(obj: Any): Boolean = { + obj match { + case that: BitPat => this.value == that.value && this.mask == that.mask && this.width == that.width + case that: BitSet => super.equals(obj) + case _ => false + } + } + override def hashCode: Int = MurmurHash3.seqHash(Seq(this.value, this.mask, this.width)) @@ -362,14 +370,20 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, val width: Int) * @param that `BitPat` to be checked. * @return true if this and that `BitPat` have overlap. */ - def overlap(that: BitPat): Boolean = ((mask & that.mask) & (value ^ that.value)) == 0 + override def overlap(that: BitSet): Boolean = that match { + case that: BitPat => ((mask & that.mask) & (value ^ that.value)) == 0 + case _ => super.overlap(that) + } /** Check whether this `BitSet` covers that (i.e. forall b matches that, b also matches this) * * @param that `BitPat` to be covered * @return true if this `BitSet` can cover that `BitSet` */ - def cover(that: BitPat): Boolean = (mask & (~that.mask | (value ^ that.value))) == 0 + override def cover(that: BitSet): Boolean = that match { + case that: BitPat => (mask & (~that.mask | (value ^ that.value))) == 0 + case _ => super.cover(that) + } /** Intersect `this` and `that` `BitPat`. * diff --git a/src/test/scala/chiselTests/util/BitSetSpec.scala b/src/test/scala/chiselTests/util/BitSetSpec.scala index 0df2f17fd2b..1edf3e0b3eb 100644 --- a/src/test/scala/chiselTests/util/BitSetSpec.scala +++ b/src/test/scala/chiselTests/util/BitSetSpec.scala @@ -53,6 +53,57 @@ class BitSetSpec extends AnyFlatSpec with Matchers { expected.equals(aBitSet.subtract(bBitSet)) should be(true) } + it should "support checking equality" in { + val set = BitSet.fromString("""b100 + |b101""".stripMargin) + val a = BitPat("b10?") + val a2 = BitPat("b10?") + val b = BitPat("b1??") + + // Check both ways because BitPat overloads equals + assert(a != b) + assert(b != a) + assert(a == a2) + assert(a2 == a) + assert(set == a) + assert(a == set) + } + + it should "support checking for cover" in { + val set = BitSet.fromString("""b110 + |b100 + |b101""".stripMargin) + val a = BitPat("b10?") + val b = BitPat("b1??") + + a.cover(b) should be(false) + b.cover(a) should be(true) + set.cover(a) should be(true) + a.cover(set) should be(false) + set.cover(b) should be(false) + b.cover(set) should be(true) + + } + + it should "support checking for overlap" in { + val set = BitSet.fromString("""b01?0 + |b0000""".stripMargin) + val a = BitPat("b00??") + val b = BitPat("b01?0") + val c = BitPat("b0000") + val d = BitPat("b1000") + + a.overlap(b) should be(false) + a.overlap(c) should be(true) + b.overlap(c) should be(false) + + // Check both ways because BitPat overloads overlap + set.overlap(a) should be(true) + a.overlap(set) should be(true) + set.overlap(d) should be(false) + d.overlap(set) should be(false) + } + it should "be generated from BitPat union" in { val aBitSet = BitSet.fromString("""b001?0 |b000??""".stripMargin)