From 980778b1874b93b7e2778eb0c8f666f9691176f1 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Wed, 20 Jun 2018 17:09:48 -0700 Subject: Programmatic Port Creation (#833) Add chisel3.experimental.IO for programmatic port creation in Raw and MultiIOModules. suggestName is required to name ports that cannot be named by reflection. Two ports cannot be given the same name.--- .../src/main/scala/chisel3/core/UserModule.scala | 30 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'chiselFrontend/src/main/scala/chisel3/core/UserModule.scala') diff --git a/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala b/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala index 17b8a09e..831b3707 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala @@ -38,6 +38,22 @@ abstract class UserModule(implicit moduleCompileOptions: CompileOptions) val compileOptions = moduleCompileOptions + private[chisel3] def namePorts(names: HashMap[HasId, String]): Unit = { + for (port <- getModulePorts) { + port.suggestedName.orElse(names.get(port)) match { + case Some(name) => + if (_namespace.contains(name)) { + Builder.error(s"""Unable to name port $port to "$name" in $this,""" + + " name is already taken by another port!") + } + port.setRef(ModuleIO(this, _namespace.name(name))) + case None => Builder.error(s"Unable to name port $port in $this, " + + "try making it a public field of the Module") + } + } + } + + private[core] override def generateComponent(): Component = { require(!_closed, "Can't generate module more than once") _closed = true @@ -45,10 +61,7 @@ abstract class UserModule(implicit moduleCompileOptions: CompileOptions) val names = nameIds(classOf[UserModule]) // Ports get first naming priority, since they are part of a Module's IO spec - for (port <- getModulePorts) { - require(names.contains(port), s"Unable to name port $port in $this") - port.setRef(ModuleIO(this, _namespace.name(names(port)))) - } + namePorts(names) // Then everything else gets named for ((node, name) <- names) { @@ -170,6 +183,15 @@ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) names } + private[chisel3] override def namePorts(names: HashMap[HasId, String]): Unit = { + for (port <- getModulePorts) { + // This should already have been caught + if (!names.contains(port)) throwException(s"Unable to name port $port in $this") + val name = names(port) + port.setRef(ModuleIO(this, _namespace.name(name))) + } + } + private[core] override def generateComponent(): Component = { _compatAutoWrapPorts() // pre-IO(...) compatibility hack -- cgit v1.2.3