diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index 9f94a0911d4..3e11c0a1f5b 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -574,6 +574,12 @@ package experimental { _ports.toSeq } + /** Get IOs that are currently bound to this module. + */ + private[chisel3] def getIOs: Seq[Data] = { + _ports.map(_._1).toSeq + } + // These methods allow checking some properties of ports before the module is closed, // mainly for compatibility purposes. protected def portsContains(elem: Data): Boolean = { diff --git a/core/src/main/scala/chisel3/reflect/DataMirror.scala b/core/src/main/scala/chisel3/reflect/DataMirror.scala index bfec9030e96..4bf2af9e6b0 100644 --- a/core/src/main/scala/chisel3/reflect/DataMirror.scala +++ b/core/src/main/scala/chisel3/reflect/DataMirror.scala @@ -212,6 +212,17 @@ object DataMirror { def chiselTypeClone[T <: Data](target: T): T = { target.cloneTypeFull } + + /** 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 } // Old definition of collectLeafMembers diff --git a/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala b/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala index 4a8932f5a03..eb7bbc8e693 100644 --- a/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala +++ b/src/test/scala/chiselTests/reflect/DataMirrorSpec.scala @@ -245,4 +245,24 @@ class DataMirrorSpec extends ChiselFlatSpec { DataMirror.getLayerColor(foo.c) should be(Some(A)) } + "moduleIOs" 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)) + }) + } }