Skip to content

Commit

Permalink
Optimize BitPat equals, overlap, and cover (#3285)
Browse files Browse the repository at this point in the history
(cherry picked from commit f590ac9)
  • Loading branch information
jackkoenig authored and mergify[bot] committed May 17, 2023
1 parent 600009c commit a3abb58
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/main/scala/chisel3/util/BitPat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down Expand Up @@ -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`.
*
Expand Down
51 changes: 51 additions & 0 deletions src/test/scala/chiselTests/util/BitSetSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit a3abb58

Please sign in to comment.