diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index e20aa40ba0b..eb8b95097dc 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -2,7 +2,7 @@ package chisel3 -import chisel3.experimental.dataview.reify +import chisel3.experimental.dataview.{reify, reifySingleData} import scala.language.experimental.macros import chisel3.experimental.{Analog, BaseModule} @@ -644,11 +644,12 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { topBindingOpt match { // DataView case Some(ViewBinding(target)) => reify(target).ref - case Some(AggregateViewBinding(viewMap)) => - viewMap.get(this) match { - case None => materializeWire() // FIXME FIRRTL doesn't have Aggregate Init expressions - // This should not be possible because Element does the lookup in .topBindingOpt - case x: Some[_] => throwException(s"Internal Error: In .ref for $this got '$topBindingOpt' and '$x'") + case Some(_: AggregateViewBinding) => + reifySingleData(this) match { + // If this is an identity view (a view of something of the same type), return ref of target + case Some(target) if this.typeEquivalent(target) => target.ref + // Otherwise, we need to materialize hardware of the correct type + case _ => materializeWire() } // Literals case Some(ElementLitBinding(litArg)) => litArg diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index 3dc5252631b..2eb56f6c089 100644 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ b/src/test/scala/chiselTests/experimental/DataView.scala @@ -553,6 +553,44 @@ class DataViewSpec extends ChiselFlatSpec { verilog should include("assign z = sel ? b : d;") } + it should "support muxing between views of Bundles" in { + import SimpleBundleDataView._ + class MyModule extends Module { + val cond = IO(Input(Bool())) + val in1 = IO(Input(new BundleA(8))) + val in2 = IO(Input(new BundleA(8))) + val out = IO(Output(new BundleB(8))) + + out := Mux(cond, in1.viewAs[BundleB], in2.viewAs[BundleB]) + } + val firrtl = ChiselStage.emitCHIRRTL(new MyModule) + val lines = Seq( + "wire _out_WIRE : { bar : UInt<8>}", + "_out_WIRE.bar <= in1.foo", + "wire _out_WIRE_1 : { bar : UInt<8>}", + "_out_WIRE_1.bar <= in2.foo", + "node _out_T = mux(cond, _out_WIRE, _out_WIRE_1)" + ) + for (line <- lines) { + firrtl should include(line) + } + } + + it should "not generate extra wires when muxing between identity views of Bundles" in { + import SimpleBundleDataView._ + class MyModule extends Module { + val cond = IO(Input(Bool())) + val in1 = IO(Input(new BundleA(8))) + val in2 = IO(Input(new BundleA(8))) + val out = IO(Output(new BundleA(8))) + + out := Mux(cond, in1.viewAs[BundleA], in2.viewAs[BundleA]) + } + val firrtl = ChiselStage.emitCHIRRTL(new MyModule) + firrtl should include("node _out_T = mux(cond, in1, in2)") + firrtl shouldNot include("wire") + } + // This example should be turned into a built-in feature it should "enable viewing Seqs as Vecs" in {