From 7f1ab3ce79508c81e760f6b1e5640a0958b3dc6a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 11:13:57 -0700 Subject: [PATCH] Fix literal handling for views of empty Aggregates (backport #4071) (#4074) * Fix literal handling for views of empty Aggregates (#4071) Previously, a view of an empty Record or Vec would always have a litValue of 0. (cherry picked from commit 11c3f51c68ae05fbdb572ece2a5ce5d3037c18cb) # Conflicts: # src/test/scala/chiselTests/experimental/DataView.scala * Fixup backport conflicts --------- Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/Aggregate.scala | 9 +++++ .../chiselTests/experimental/DataView.scala | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/core/src/main/scala/chisel3/Aggregate.scala b/core/src/main/scala/chisel3/Aggregate.scala index 34fcd95bd08..9030e2c59d9 100644 --- a/core/src/main/scala/chisel3/Aggregate.scala +++ b/core/src/main/scala/chisel3/Aggregate.scala @@ -42,6 +42,15 @@ sealed abstract class Aggregate extends Data { } topBindingOpt match { + // Don't accidentally invent a literal value for a view that is empty + case Some(_: AggregateViewBinding) if this.getElements.isEmpty => + reifySingleData(this) match { + case Some(target: Aggregate) => target.checkingLitOption(checkForDontCares) + case _ => + val msg = + s"It should not be possible to have an empty Aggregate view that doesn't reify to a single target, but got $this" + Builder.exception(msg)(UnlocatableSourceInfo) + } case Some(_: BundleLitBinding | _: VecLitBinding | _: AggregateViewBinding) => // Records store elements in reverse order and higher indices are more significant in Vecs this.getElements.foldRight(Option(BigInt(0)))(shiftAdd) diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index fdd862422f8..3dc5252631b 100644 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ b/src/test/scala/chiselTests/experimental/DataView.scala @@ -6,6 +6,8 @@ import chisel3._ import chisel3.experimental.conversions._ import chisel3.experimental.dataview._ import chisel3.experimental.{Analog, HWTuple2} +import chisel3.experimental.BundleLiterals._ +import chisel3.experimental.VecLiterals._ import chisel3.reflect.DataMirror.internal.chiselTypeClone import chisel3.util.{Decoupled, DecoupledIO, Valid, ValidIO} import chiselTests.ChiselFlatSpec @@ -999,6 +1001,38 @@ class DataViewSpec extends ChiselFlatSpec { ChiselStage.emitCHIRRTL(new MyModule) } + it should "NOT invent literal values for views of empty Aggregates" in { + class MyModule extends Module { + val emptyBundle = IO(Output(new Bundle {})) + val emptyVec = IO(Output(Vec(0, UInt(8.W)))) + + val bundleView = emptyBundle.viewAs[Bundle] + val vecView = emptyVec.viewAs[Vec[UInt]] + + emptyBundle.litOption should be(None) + bundleView.litOption should be(None) + emptyVec.litOption should be(None) + vecView.litOption should be(None) + } + ChiselStage.emitCHIRRTL(new MyModule) + } + + it should "support literal values for views of empty Aggregates" in { + class MyModule extends Module { + val emptyBundle = (new Bundle {}).Lit() + val emptyVec = Vec(0, UInt(8.W)).Lit() + + val bundleView = emptyBundle.viewAs[Bundle] + val vecView = emptyVec.viewAs[Vec[UInt]] + + emptyBundle.litOption should be(Some(0)) + bundleView.litOption should be(Some(0)) + emptyVec.litOption should be(Some(0)) + vecView.litOption should be(Some(0)) + } + ChiselStage.emitCHIRRTL(new MyModule) + } + behavior.of("PartialDataView") it should "still error if the mapping is non-total in the view" in {