From 19c64e0ab6dabc4d936adc086b66a387c13ad663 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Thu, 13 Apr 2023 18:05:05 -0400 Subject: [PATCH 1/3] Allow DataView of Reset <=> [UInt<1>, AsyncReset] Change what DataView allows in its type checking to enable Reset to be viewed as either a UInt<1> or an AsyncReset. This enables more flexible DataViews which match already allowable Chisel and FIRRTL connection semantics. Signed-off-by: Schuyler Eldridge --- .../experimental/dataview/package.scala | 17 ++++++++-- .../chiselTests/experimental/DataView.scala | 34 +++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 072ce6c6446..f9d2e9ae624 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -103,10 +103,21 @@ package object dataview { val tex = unfoldView(te).find(targetContains).getOrElse(err("Target", te)) val vex = unfoldView(ve).find(viewFieldLookup.contains).getOrElse(err("View", ve)) - if (tex.getClass != vex.getClass) { - val fieldName = viewFieldName(vex) - throw InvalidViewException(s"Field $fieldName specified as view of non-type-equivalent value $tex") + (tex, vex) match { + /* Allow views where the types are equal. */ + case (a, b) if a.getClass == b.getClass => + /* Allow UInt <=> Reset views. */ + case (a: UInt, _: Reset) if a.isWidthKnown && a.getWidth == 1 => true + case (_: Reset, a: UInt) if a.isWidthKnown && a.getWidth == 1 => true + /* Allow AsyncReset <=> Reset views. */ + case (a: AsyncReset, _: Reset) => true + case (_: Reset, a: AsyncReset) => true + /* All other views produce a runtime error. */ + case _ => + val fieldName = viewFieldName(vex) + throw InvalidViewException(s"Field $fieldName specified as view of non-type-equivalent value $tex") } + // View width must be unknown or match target width if (vex.widthKnown && vex.width != tex.width) { def widthAsString(x: Element) = x.widthOption.map("<" + _ + ">").getOrElse("") diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index a443fafe410..5f793ef52bd 100644 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ b/src/test/scala/chiselTests/experimental/DataView.scala @@ -546,6 +546,40 @@ class DataViewSpec extends ChiselFlatSpec { chirrtl should include("dataOut <= vec[addrReg]") } + it should "allow views between reset types" in { + class A extends Bundle { + val uint = AsyncReset() + val asyncreset = AsyncReset() + } + + class B extends Bundle { + val reset_0 = Reset() + val reset_1 = Reset() + } + + class Foo extends RawModule { + val a = Wire(new A) + val b = Wire(new B) + + implicit val view = DataView[A, B]( + _ => new B, + _.uint -> _.reset_0, + _.asyncreset -> _.reset_1 + ) + + a.viewAs[B] := b + } + + (ChiselStage + .emitCHIRRTL(new Foo, Array("--full-stacktrace")) + .split('\n') + .map(_.takeWhile(_ != '@')) + .map(_.trim) should contain).allOf( + "a.uint <= b.reset_0", + "a.asyncreset <= b.reset_1" + ) + } + it should "error if you try to dynamically index a Vec view that does not correspond to a Vec target" in { class MyModule extends Module { val inA, inB = IO(Input(UInt(8.W))) From 15e1ddb1660810957d0ea8a2f97f770dfd1a5ca4 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Sat, 15 Apr 2023 01:57:23 -0400 Subject: [PATCH 2/3] fixup! Allow DataView of Reset <=> [UInt<1>, AsyncReset] --- .../scala/chisel3/experimental/dataview/package.scala | 10 +++++----- src/test/scala/chiselTests/experimental/DataView.scala | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index f9d2e9ae624..8b32023a222 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -106,12 +106,12 @@ package object dataview { (tex, vex) match { /* Allow views where the types are equal. */ case (a, b) if a.getClass == b.getClass => - /* Allow UInt <=> Reset views. */ - case (a: UInt, _: Reset) if a.isWidthKnown && a.getWidth == 1 => true - case (_: Reset, a: UInt) if a.isWidthKnown && a.getWidth == 1 => true + /* allow bool <=> reset views. */ + case (a: Bool, _: Reset) => + case (_: Reset, a: Bool) => /* Allow AsyncReset <=> Reset views. */ - case (a: AsyncReset, _: Reset) => true - case (_: Reset, a: AsyncReset) => true + case (a: AsyncReset, _: Reset) => + case (_: Reset, a: AsyncReset) => /* All other views produce a runtime error. */ case _ => val fieldName = viewFieldName(vex) diff --git a/src/test/scala/chiselTests/experimental/DataView.scala b/src/test/scala/chiselTests/experimental/DataView.scala index 5f793ef52bd..6b1d7785bed 100644 --- a/src/test/scala/chiselTests/experimental/DataView.scala +++ b/src/test/scala/chiselTests/experimental/DataView.scala @@ -548,7 +548,7 @@ class DataViewSpec extends ChiselFlatSpec { it should "allow views between reset types" in { class A extends Bundle { - val uint = AsyncReset() + val bool = Bool() val asyncreset = AsyncReset() } @@ -563,7 +563,7 @@ class DataViewSpec extends ChiselFlatSpec { implicit val view = DataView[A, B]( _ => new B, - _.uint -> _.reset_0, + _.bool -> _.reset_0, _.asyncreset -> _.reset_1 ) @@ -575,7 +575,7 @@ class DataViewSpec extends ChiselFlatSpec { .split('\n') .map(_.takeWhile(_ != '@')) .map(_.trim) should contain).allOf( - "a.uint <= b.reset_0", + "a.bool <= b.reset_0", "a.asyncreset <= b.reset_1" ) } From f4b2ddfcdccfc52e960464cbe8f6498c810497d4 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Sat, 15 Apr 2023 01:58:30 -0400 Subject: [PATCH 3/3] fixup! Allow DataView of Reset <=> [UInt<1>, AsyncReset] --- core/src/main/scala/chisel3/experimental/dataview/package.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 8b32023a222..52c5bfdadf1 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -117,7 +117,6 @@ package object dataview { val fieldName = viewFieldName(vex) throw InvalidViewException(s"Field $fieldName specified as view of non-type-equivalent value $tex") } - // View width must be unknown or match target width if (vex.widthKnown && vex.width != tex.width) { def widthAsString(x: Element) = x.widthOption.map("<" + _ + ">").getOrElse("")