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)))