summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests/DataEqualitySpec.scala
diff options
context:
space:
mode:
authormergify[bot]2022-08-18 00:30:39 +0000
committerGitHub2022-08-18 00:30:39 +0000
commit16dfc84d6667f1f6bbca46935cb445bc288c96d4 (patch)
treef8c983d91b976859325973c0f8bc7231e85019c4 /src/test/scala/chiselTests/DataEqualitySpec.scala
parent23ef9aa7ffef5bbf8fe124fc9be7683f005c3612 (diff)
Add generic `Data` equality (===) via extension method (#2669) (#2691)
(cherry picked from commit 67cff8253740f19642006dba7eff58b1e5fa1291) Co-authored-by: Jared Barocsi <82000041+jared-barocsi@users.noreply.github.com>
Diffstat (limited to 'src/test/scala/chiselTests/DataEqualitySpec.scala')
-rw-r--r--src/test/scala/chiselTests/DataEqualitySpec.scala257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/test/scala/chiselTests/DataEqualitySpec.scala b/src/test/scala/chiselTests/DataEqualitySpec.scala
new file mode 100644
index 00000000..4ac3292d
--- /dev/null
+++ b/src/test/scala/chiselTests/DataEqualitySpec.scala
@@ -0,0 +1,257 @@
+package chiselTests
+
+import chisel3._
+import chisel3.experimental.VecLiterals._
+import chisel3.experimental.BundleLiterals._
+import chisel3.experimental.{Analog, ChiselEnum, ChiselRange, FixedPoint, Interval}
+import chisel3.stage.ChiselStage
+import chisel3.testers.BasicTester
+import chisel3.util.Valid
+
+class EqualityModule(lhsGen: => Data, rhsGen: => Data) extends Module {
+ val out = IO(Output(Bool()))
+
+ val lhs = lhsGen
+ val rhs = rhsGen
+
+ out := lhs === rhs
+}
+
+class EqualityTester(lhsGen: => Data, rhsGen: => Data) extends BasicTester {
+ val module = Module(new EqualityModule(lhsGen, rhsGen))
+
+ assert(module.out)
+
+ stop()
+}
+
+class AnalogBundle extends Bundle {
+ val analog = Analog(32.W)
+}
+
+class AnalogExceptionModule extends Module {
+ class AnalogExceptionModuleIO extends Bundle {
+ val bundle1 = new AnalogBundle
+ val bundle2 = new AnalogBundle
+ }
+
+ val io = IO(new AnalogExceptionModuleIO)
+}
+
+class AnalogExceptionTester extends BasicTester {
+ val module = Module(new AnalogExceptionModule)
+
+ module.io.bundle1 <> DontCare
+ module.io.bundle2 <> DontCare
+
+ assert(module.io.bundle1 === module.io.bundle2)
+
+ stop()
+}
+
+class DataEqualitySpec extends ChiselFlatSpec with Utils {
+ object MyEnum extends ChiselEnum {
+ val sA, sB = Value
+ }
+ object MyEnumB extends ChiselEnum {
+ val sA, sB = Value
+ }
+ class MyBundle extends Bundle {
+ val a = UInt(8.W)
+ val b = Bool()
+ val c = MyEnum()
+ }
+ class LongBundle extends Bundle {
+ val a = UInt(48.W)
+ val b = SInt(32.W)
+ val c = FixedPoint(16.W, 4.BP)
+ }
+ class RuntimeSensitiveBundle(gen: => Bundle) extends Bundle {
+ val a = UInt(8.W)
+ val b: Bundle = gen
+ }
+
+ behavior.of("UInt === UInt")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(0.U, 0.U)
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(0.U, 1.U)
+ }
+ }
+
+ behavior.of("SInt === SInt")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(0.S, 0.S)
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(0.S, 1.S)
+ }
+ }
+
+ behavior.of("Reset === Reset")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(true.B, true.B)
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(true.B, false.B)
+ }
+ }
+
+ behavior.of("AsyncReset === AsyncReset")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(true.B.asAsyncReset, true.B.asAsyncReset)
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(true.B.asAsyncReset, false.B.asAsyncReset)
+ }
+ }
+
+ behavior.of("Interval === Interval")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(2.I, 2.I)
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(2.I, 3.I)
+ }
+ }
+
+ behavior.of("FixedPoint === FixedPoint")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(4.5.F(16.W, 4.BP), 4.5.F(16.W, 4.BP))
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(4.5.F(16.W, 4.BP), 4.6.F(16.W, 4.BP))
+ }
+ }
+
+ behavior.of("ChiselEnum === ChiselEnum")
+ it should "pass with equal values" in {
+ assertTesterPasses {
+ new EqualityTester(MyEnum.sA, MyEnum.sA)
+ }
+ }
+ it should "fail with differing values" in {
+ assertTesterFails {
+ new EqualityTester(MyEnum.sA, MyEnum.sB)
+ }
+ }
+
+ behavior.of("Vec === Vec")
+ it should "pass with equal sizes, equal values" in {
+ assertTesterPasses {
+ new EqualityTester(
+ Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U),
+ Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U)
+ )
+ }
+ }
+ it should "fail with equal sizes, differing values" in {
+ assertTesterFails {
+ new EqualityTester(
+ Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U),
+ Vec(3, UInt(8.W)).Lit(0 -> 0.U, 1 -> 1.U, 2 -> 2.U)
+ )
+ }
+ }
+ it should "throw a ChiselException with differing sizes" in {
+ (the[ChiselException] thrownBy extractCause[ChiselException] {
+ assertTesterFails {
+ new EqualityTester(
+ Vec(3, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U),
+ Vec(4, UInt(8.W)).Lit(0 -> 1.U, 1 -> 2.U, 2 -> 3.U, 3 -> 4.U)
+ )
+ }
+ }).getMessage should include("Vec sizes differ")
+ }
+
+ behavior.of("Bundle === Bundle")
+ it should "pass with equal type, equal values" in {
+ assertTesterPasses {
+ new EqualityTester(
+ (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB),
+ (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB)
+ )
+ }
+ }
+ it should "fail with equal type, differing values" in {
+ assertTesterFails {
+ new EqualityTester(
+ (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sB),
+ (new MyBundle).Lit(_.a -> 42.U, _.b -> false.B, _.c -> MyEnum.sA)
+ )
+ }
+ }
+ it should "throw a ChiselException with differing runtime types" in {
+ (the[ChiselException] thrownBy extractCause[ChiselException] {
+ assertTesterFails {
+ new EqualityTester(
+ (new RuntimeSensitiveBundle(new MyBundle)).Lit(
+ _.a -> 1.U,
+ _.b -> (new MyBundle).Lit(
+ _.a -> 42.U,
+ _.b -> false.B,
+ _.c -> MyEnum.sB
+ )
+ ),
+ (new RuntimeSensitiveBundle(new LongBundle)).Lit(
+ _.a -> 1.U,
+ _.b -> (new LongBundle).Lit(
+ _.a -> 42.U,
+ _.b -> 0.S,
+ _.c -> 4.5.F(16.W, 4.BP)
+ )
+ )
+ )
+ }
+ }).getMessage should include("Runtime types differ")
+ }
+
+ behavior.of("DontCare === DontCare")
+ it should "pass with two invalids" in {
+ assertTesterPasses {
+ new EqualityTester(Valid(UInt(8.W)).Lit(_.bits -> 123.U), Valid(UInt(8.W)).Lit(_.bits -> 123.U))
+ }
+ }
+ it should "exhibit the same behavior as comparing two invalidated wires" in {
+ // Also check that two invalidated wires are equal
+ assertTesterPasses {
+ new EqualityTester(WireInit(UInt(8.W), DontCare), WireInit(UInt(8.W), DontCare))
+ }
+
+ // Compare the verilog generated from both test cases and verify that they both are equal to true
+ val verilog1 = ChiselStage.emitVerilog(
+ new EqualityModule(Valid(UInt(8.W)).Lit(_.bits -> 123.U), Valid(UInt(8.W)).Lit(_.bits -> 123.U))
+ )
+ val verilog2 =
+ ChiselStage.emitVerilog(new EqualityModule(WireInit(UInt(8.W), DontCare), WireInit(UInt(8.W), DontCare)))
+
+ verilog1 should include("assign out = 1'h1;")
+ verilog2 should include("assign out = 1'h1;")
+ }
+
+ behavior.of("Analog === Analog")
+ it should "throw a ChiselException" in {
+ (the[ChiselException] thrownBy extractCause[ChiselException] {
+ assertTesterFails { new AnalogExceptionTester }
+ }).getMessage should include("Equality isn't defined for Analog values")
+ }
+}