From 68c4db53c110377de9be4b05ff9f8d7be2e7f0cd Mon Sep 17 00:00:00 2001 From: Deborah Soung Date: Tue, 21 May 2024 20:56:31 -0700 Subject: [PATCH 1/2] Add modulePorts and fullModulePorts in DataMirror for Instance (#4076) (cherry picked from commit 62bbad55b1e44690985cccf60f2c4282e9986e71) # Conflicts: # core/src/main/scala/chisel3/reflect/DataMirror.scala # src/test/scala/chiselTests/reflect/DataMirrorSpec.scala --- .../scala/chisel3/reflect/DataMirror.scala | 40 +++++++++- .../chiselTests/reflect/DataMirrorSpec.scala | 78 +++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/core/src/main/scala/chisel3/reflect/DataMirror.scala b/core/src/main/scala/chisel3/reflect/DataMirror.scala index f92eee1e49a..ceb7fa45890 100644 --- a/core/src/main/scala/chisel3/reflect/DataMirror.scala +++ b/core/src/main/scala/chisel3/reflect/DataMirror.scala @@ -6,6 +6,7 @@ import chisel3._ import chisel3.internal._ import chisel3.internal.firrtl.ir._ import chisel3.experimental.{requireIsHardware, BaseModule, SourceInfo} +import chisel3.experimental.hierarchy.Instance import chisel3.properties.Property import scala.reflect.ClassTag @@ -143,6 +144,15 @@ object DataMirror { case (name, port: Data) => (name, port) } + /** Returns the ports of a `chisel3.experimental.hierarchy.Instance` of a module + */ + def modulePorts[T <: BaseModule](inst: Instance[T])(implicit si: SourceInfo): Seq[(String, Data)] = { + // This prevents users from using the _lookup API + implicit val mg = new chisel3.internal.MacroGenerated {} + + inst._lookup { proto: T => modulePorts(proto) } + } + /** Returns a recursive representation of a module's ports with underscore-qualified names * {{{ * class MyModule extends Module { @@ -170,7 +180,7 @@ object DataMirror { * }}} * @note The returned ports are redundant. An [[Aggregate]] port will be present along with all * of its children. - * @see [[DataMirror.modulePorts]] for a non-recursive representation of the ports. + * @see `DataMirror.modulePorts` for a non-recursive representation of the ports. */ def fullModulePorts(target: BaseModule)(implicit si: SourceInfo): Seq[(String, Data)] = { def getPortNames(name: String, data: Data): Seq[(String, Data)] = Seq(name -> data) ++ (data match { @@ -189,6 +199,20 @@ object DataMirror { } } + /** Returns a recursive representation of an `chisel3.experimental.hierarchy.Instance` of a + * module's ports with underscore-qualified names. + * + * @note The returned ports are redundant. An [[Aggregate]] port will be present along with all + * of its children. + * @see `DataMirror.modulePorts` for a non-recursive representation of the ports. + */ + def fullModulePorts[T <: BaseModule](inst: Instance[T])(implicit si: SourceInfo): Seq[(String, Data)] = { + // This prevents users from using the _lookup API + implicit val mg = new chisel3.internal.MacroGenerated {} + + inst._lookup { proto: T => fullModulePorts(proto) } + } + /** Returns the parent module within which a module instance is instantiated * * @note Top-level modules in any given elaboration do not have a parent @@ -204,6 +228,20 @@ object DataMirror { def chiselTypeClone[T <: Data](target: T): T = { target.cloneTypeFull } +<<<<<<< HEAD +======= + + /** Returns the current ports of an in-progress module. + * + * This method does not necessarily return the final ports of the target module. It consults Chisel's internal data + * structures to extract the module's IOs. For this reason, it is generally not safe, and users should prefer + * `DataMirror.modulePorts`, but this method may be used for certain use cases that want the current list of + * ports before the module is closed. + * + * @param target BaseModule to get IOs from + */ + def currentModulePorts(target: BaseModule): Seq[Data] = target.getIOs +>>>>>>> 62bbad55b (Add modulePorts and fullModulePorts in DataMirror for Instance (#4076)) } // Old definition of collectLeafMembers diff --git a/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala b/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala index bea0326dcab..6111abb6def 100644 --- a/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala +++ b/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala @@ -224,4 +224,82 @@ class DataMirrorSpec extends ChiselFlatSpec { assert(DataMirror.isFullyAligned(UInt(8.W))) } +<<<<<<< HEAD +======= + "getLayerColor" should "return a layer color if one exists" in { + object A extends layer.Layer(layer.Convention.Bind) + class Foo extends Bundle { + val a = Bool() + val b = Probe(Bool()) + val c = Probe(Bool(), A) + } + + val foo = new Foo + + info("a non-probe returns None") + DataMirror.getLayerColor(foo.a) should be(None) + + info("an uncolored probe returns None") + DataMirror.getLayerColor(foo.b) should be(None) + + info("a probe colored with A returns Some(A)") + DataMirror.getLayerColor(foo.c) should be(Some(A)) + } + + "currentModulePorts" should "return an in-progress module's IOs" in { + class Foo extends RawModule { + val in = IO(Input(Bool())) + val out = IO(Output(Bool())) + val wire = Wire(Bool()) + val child = Module(new RawModule {}) + + val ports0 = DataMirror.internal.currentModulePorts(this) + + val other = IO(Input(Bool())) + + val ports1 = DataMirror.internal.currentModulePorts(this) + } + + ChiselStage.emitCHIRRTL(new RawModule { + val foo = Module(new Foo) + foo.ports0 should be(Seq(foo.in, foo.out)) + foo.ports1 should be(Seq(foo.in, foo.out, foo.other)) + }) + } + + "modulePorts and fullModulePorts" should "return an Instance of a module's IOs" in { + @instantiable + class Bar extends Module { + @public val io = IO(new Bundle { + val vec = Vec(2, Bool()) + val x = UInt(4.W) + }) + } + + class Foo extends Module { + val definition = Definition(new Bar) + val instA = Instance(definition) + val portsA = DataMirror.modulePorts(instA) + + val instB = (Module(new Bar)).toInstance + val portsB = DataMirror.fullModulePorts(instB) + } + + ChiselStage.emitCHIRRTL(new Module { + val foo = Module(new Foo) + foo.portsA.map(_._1) should be(Seq("clock", "reset", "io")) + foo.portsB.map(_._1) should be( + Seq( + "clock", + "reset", + "io", + "io_x", + "io_vec", + "io_vec_0", + "io_vec_1" + ) + ) + }) + } +>>>>>>> 62bbad55b (Add modulePorts and fullModulePorts in DataMirror for Instance (#4076)) } From f3242810ab7223adb4e75fbf97554f08bc04e243 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 22 May 2024 10:55:50 -0700 Subject: [PATCH 2/2] Resolve backport conflicts --- .../scala/chisel3/reflect/DataMirror.scala | 14 ------ .../chiselTests/reflect/DataMirrorSpec.scala | 44 ------------------- 2 files changed, 58 deletions(-) diff --git a/core/src/main/scala/chisel3/reflect/DataMirror.scala b/core/src/main/scala/chisel3/reflect/DataMirror.scala index ceb7fa45890..af8f154e201 100644 --- a/core/src/main/scala/chisel3/reflect/DataMirror.scala +++ b/core/src/main/scala/chisel3/reflect/DataMirror.scala @@ -228,20 +228,6 @@ object DataMirror { def chiselTypeClone[T <: Data](target: T): T = { target.cloneTypeFull } -<<<<<<< HEAD -======= - - /** Returns the current ports of an in-progress module. - * - * This method does not necessarily return the final ports of the target module. It consults Chisel's internal data - * structures to extract the module's IOs. For this reason, it is generally not safe, and users should prefer - * `DataMirror.modulePorts`, but this method may be used for certain use cases that want the current list of - * ports before the module is closed. - * - * @param target BaseModule to get IOs from - */ - def currentModulePorts(target: BaseModule): Seq[Data] = target.getIOs ->>>>>>> 62bbad55b (Add modulePorts and fullModulePorts in DataMirror for Instance (#4076)) } // Old definition of collectLeafMembers diff --git a/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala b/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala index 6111abb6def..06a75a63d2e 100644 --- a/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala +++ b/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala @@ -224,49 +224,6 @@ class DataMirrorSpec extends ChiselFlatSpec { assert(DataMirror.isFullyAligned(UInt(8.W))) } -<<<<<<< HEAD -======= - "getLayerColor" should "return a layer color if one exists" in { - object A extends layer.Layer(layer.Convention.Bind) - class Foo extends Bundle { - val a = Bool() - val b = Probe(Bool()) - val c = Probe(Bool(), A) - } - - val foo = new Foo - - info("a non-probe returns None") - DataMirror.getLayerColor(foo.a) should be(None) - - info("an uncolored probe returns None") - DataMirror.getLayerColor(foo.b) should be(None) - - info("a probe colored with A returns Some(A)") - DataMirror.getLayerColor(foo.c) should be(Some(A)) - } - - "currentModulePorts" should "return an in-progress module's IOs" in { - class Foo extends RawModule { - val in = IO(Input(Bool())) - val out = IO(Output(Bool())) - val wire = Wire(Bool()) - val child = Module(new RawModule {}) - - val ports0 = DataMirror.internal.currentModulePorts(this) - - val other = IO(Input(Bool())) - - val ports1 = DataMirror.internal.currentModulePorts(this) - } - - ChiselStage.emitCHIRRTL(new RawModule { - val foo = Module(new Foo) - foo.ports0 should be(Seq(foo.in, foo.out)) - foo.ports1 should be(Seq(foo.in, foo.out, foo.other)) - }) - } - "modulePorts and fullModulePorts" should "return an Instance of a module's IOs" in { @instantiable class Bar extends Module { @@ -301,5 +258,4 @@ class DataMirrorSpec extends ChiselFlatSpec { ) }) } ->>>>>>> 62bbad55b (Add modulePorts and fullModulePorts in DataMirror for Instance (#4076)) }