summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core/Module.scala
diff options
context:
space:
mode:
authorJack Koenig2018-06-20 17:09:48 -0700
committerGitHub2018-06-20 17:09:48 -0700
commit980778b1874b93b7e2778eb0c8f666f9691176f1 (patch)
treea42175ff8a8b83e75e4e89eb98264b8cdc8ba584 /chiselFrontend/src/main/scala/chisel3/core/Module.scala
parent4cccd877c25116a1f0b90824aabfc689d7fe50ea (diff)
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.
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/Module.scala')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala56
1 files changed, 40 insertions, 16 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
index 2f365dd7..c4a48fb4 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
@@ -79,6 +79,40 @@ object Module {
def currentModule: Option[BaseModule] = Builder.currentModule
}
+object IO {
+ /** Constructs a port for the current Module
+ *
+ * This must wrap the datatype used to set the io field of any Module.
+ * i.e. All concrete modules must have defined io in this form:
+ * [lazy] val io[: io type] = IO(...[: io type])
+ *
+ * Items in [] are optional.
+ *
+ * The granted iodef must be a chisel type and not be bound to hardware.
+ *
+ * Also registers a Data as a port, also performing bindings. Cannot be called once ports are
+ * requested (so that all calls to ports will return the same information).
+ * Internal API.
+ */
+ def apply[T<:Data](iodef: T): T = {
+ val module = Module.currentModule.get // Impossible to fail
+ require(!module.isClosed, "Can't add more ports after module close")
+ requireIsChiselType(iodef, "io type")
+
+ // Clone the IO so we preserve immutability of data types
+ val iodefClone = try {
+ iodef.cloneTypeFull
+ } catch {
+ // For now this is going to be just a deprecation so we don't suddenly break everyone's code
+ case e: AutoClonetypeException =>
+ Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}"))
+ iodef
+ }
+ module.bindIoInPlace(iodefClone)
+ iodefClone
+ }
+}
+
/** Abstract base class for Modules, an instantiable organizational unit for RTL.
*/
// TODO: seal this?
@@ -99,6 +133,9 @@ abstract class BaseModule extends HasId {
//
protected var _closed = false
+ /** Internal check if a Module is closed */
+ private[core] def isClosed = _closed
+
// Fresh Namespace because in Firrtl, Modules namespaces are disjoint with the global namespace
private[core] val _namespace = Namespace.empty
private val _ids = ArrayBuffer[HasId]()
@@ -243,6 +280,8 @@ abstract class BaseModule extends HasId {
iodef.bind(PortBinding(this))
_ports += iodef
}
+ /** Private accessor for _bindIoInPlace */
+ private[core] def bindIoInPlace(iodef: Data): Unit = _bindIoInPlace(iodef)
/**
* This must wrap the datatype used to set the io field of any Module.
@@ -260,22 +299,7 @@ abstract class BaseModule extends HasId {
* TODO(twigg): Specifically walk the Data definition to call out which nodes
* are problematic.
*/
- protected def IO[T<:Data](iodef: T): T = {
- require(!_closed, "Can't add more ports after module close")
- requireIsChiselType(iodef, "io type")
-
- // Clone the IO so we preserve immutability of data types
- val iodefClone = try {
- iodef.cloneTypeFull
- } catch {
- // For now this is going to be just a deprecation so we don't suddenly break everyone's code
- case e: AutoClonetypeException =>
- Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}"))
- iodef
- }
- _bindIoInPlace(iodefClone)
- iodefClone
- }
+ protected def IO[T<:Data](iodef: T): T = chisel3.core.IO.apply(iodef)
//
// Internal Functions