summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Koenig2021-07-08 15:30:28 -0700
committerGitHub2021-07-08 15:30:28 -0700
commit16c0b53e04f3a78ddaaa382936cd660523a57199 (patch)
tree789eb837a11e71c51de86711dee556f47f79a4f6
parentbb520b8573328fda5f7b3c3892e6995fbe1b4239 (diff)
Fix chisel3 <> for Bundles that contain compatibility Bundles (#2023)
BiConnect in chisel3 delegates to FIRRTL <- semantics whenever it hits a Bundle defined in `import Chisel._`. Because chisel3 <> is commutative it needs to be mindful of flippedness when emitting a FIRRTL <- (which is *not* commutative).
-rw-r--r--core/src/main/scala/chisel3/internal/BiConnect.scala25
-rw-r--r--src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala38
2 files changed, 55 insertions, 8 deletions
diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala
index 1ee149ee..fcea4fe2 100644
--- a/core/src/main/scala/chisel3/internal/BiConnect.scala
+++ b/core/src/main/scala/chisel3/internal/BiConnect.scala
@@ -113,14 +113,23 @@ private[chisel3] object BiConnect {
}
}
}
- // Handle Records defined in Chisel._ code (change to NotStrict)
- case (left_r: Record, right_r: Record) => (left_r.compileOptions, right_r.compileOptions) match {
- case (ExplicitCompileOptions.NotStrict, _) =>
- left_r.bulkConnect(right_r)(sourceInfo, ExplicitCompileOptions.NotStrict)
- case (_, ExplicitCompileOptions.NotStrict) =>
- left_r.bulkConnect(right_r)(sourceInfo, ExplicitCompileOptions.NotStrict)
- case _ => recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod)
- }
+ // Handle Records defined in Chisel._ code by emitting a FIRRTL partial connect
+ case pair @ (left_r: Record, right_r: Record) =>
+ val notStrict =
+ Seq(left_r.compileOptions, right_r.compileOptions).contains(ExplicitCompileOptions.NotStrict)
+ if (notStrict) {
+ // chisel3 <> is commutative but FIRRTL <- is not
+ val flipped = {
+ // Everything is flipped when it's the port of a child
+ val childPort = left_r._parent.get != context_mod
+ val isFlipped = left_r.direction == ActualDirection.Bidirectional(ActualDirection.Flipped)
+ isFlipped ^ childPort
+ }
+ val (newLeft, newRight) = if (flipped) pair.swap else pair
+ newLeft.bulkConnect(newRight)(sourceInfo, ExplicitCompileOptions.NotStrict)
+ } else {
+ recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod)
+ }
// Handle Records connected to DontCare (change to NotStrict)
case (left_r: Record, DontCare) =>
diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala
index cfcc4608..8e9f9e7e 100644
--- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala
+++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala
@@ -289,5 +289,43 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec {
}
}
}
+
+ "A chisel3 Bundle that instantiates a Chisel Bundle" should "bulk connect correctly" in {
+ compile {
+ object Compat {
+ import Chisel._
+ class Foo extends Bundle {
+ val a = Input(UInt(8.W))
+ val b = Output(UInt(8.W))
+ }
+ }
+ import chisel3._
+ import Compat._
+ class Bar extends Bundle {
+ val foo1 = new Foo
+ val foo2 = Flipped(new Foo)
+ }
+ // Check every connection both ways to see that chisel3 <>'s commutativity holds
+ class Child extends RawModule {
+ val deq = IO(new Bar)
+ val enq = IO(Flipped(new Bar))
+ enq <> deq
+ deq <> enq
+ }
+ new RawModule {
+ val deq = IO(new Bar)
+ val enq = IO(Flipped(new Bar))
+ // Also important to check connections to child ports
+ val c1 = Module(new Child)
+ val c2 = Module(new Child)
+ c1.enq <> enq
+ enq <> c1.enq
+ c2.enq <> c1.deq
+ c1.deq <> c2.enq
+ deq <> c2.deq
+ c2.deq <> deq
+ }
+ }
+ }
}