diff options
| author | mergify[bot] | 2022-08-18 00:30:39 +0000 |
|---|---|---|
| committer | GitHub | 2022-08-18 00:30:39 +0000 |
| commit | 16dfc84d6667f1f6bbca46935cb445bc288c96d4 (patch) | |
| tree | f8c983d91b976859325973c0f8bc7231e85019c4 /src/test/scala | |
| parent | 23ef9aa7ffef5bbf8fe124fc9be7683f005c3612 (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')
| -rw-r--r-- | src/test/scala/chiselTests/DataEqualitySpec.scala | 257 |
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") + } +} |
