summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core/Module.scala
diff options
context:
space:
mode:
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