summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/RawModule.scala
diff options
context:
space:
mode:
authorJack2022-02-08 02:11:51 +0000
committerJack2022-02-08 02:11:51 +0000
commit4da4f252c3d7c834e13bb8e91a69cfe772996452 (patch)
tree5acc86ebf6c429efc051954c6977ed2394498dbc /core/src/main/scala/chisel3/RawModule.scala
parent93d17165cc5339de3e2dc7cd9e10dd3634b49bac (diff)
parent9d1e2082df4ecb2942a28b7039eb2ff36953380c (diff)
Merge branch '3.5.x' into 3.5-release
Diffstat (limited to 'core/src/main/scala/chisel3/RawModule.scala')
-rw-r--r--core/src/main/scala/chisel3/RawModule.scala39
1 files changed, 23 insertions, 16 deletions
diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala
index b81372d8..12b6a76a 100644
--- a/core/src/main/scala/chisel3/RawModule.scala
+++ b/core/src/main/scala/chisel3/RawModule.scala
@@ -178,11 +178,12 @@ package object internal {
// Private reflective version of "val io" to maintain Chisel.Module semantics without having
// io as a virtual method. See https://github.com/freechipsproject/chisel3/pull/1550 for more
// information about the removal of "val io"
- private def reflectivelyFindValIO(self: BaseModule): Record = {
+ private def reflectivelyFindValIO(self: BaseModule): Option[Record] = {
// Java reflection is faster and works for the common case
def tryJavaReflect: Option[Record] = Try {
self.getClass.getMethod("io").invoke(self).asInstanceOf[Record]
}.toOption
+ .filter(_ != null)
// Anonymous subclasses don't work with Java reflection, so try slower, Scala reflection
def tryScalaReflect: Option[Record] = {
val ru = scala.reflect.runtime.universe
@@ -199,6 +200,7 @@ package object internal {
Try {
im.reflectField(term).get.asInstanceOf[Record]
}.toOption
+ .filter(_ != null)
}
}
@@ -209,13 +211,6 @@ package object internal {
// Fallback if reflection fails, user can wrap in IO(...)
self.findPort("io").collect { case r: Record => r }
}
- .getOrElse(
- throwException(
- s"Compatibility mode Module '$this' must have a 'val io' Bundle. " +
- "If there is such a field and you still see this error, autowrapping has failed (sorry!). " +
- "Please wrap the Bundle declaration in IO(...)."
- )
- )
}
/** Legacy Module class that restricts IOs to just io, clock, and reset, and provides a constructor
@@ -243,17 +238,29 @@ package object internal {
def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) =
this(Option(_clock), Option(_reset))(moduleCompileOptions)
- private lazy val _io: Record = reflectivelyFindValIO(this)
+ // Sort of a DIY lazy val because if the user tries to construct hardware before val io is
+ // constructed, _compatAutoWrapPorts will try to access it but it will be null
+ // In that case, we basically need to delay setting this var until later
+ private var _ioValue: Option[Record] = None
+ private def _io: Option[Record] = _ioValue.orElse {
+ _ioValue = reflectivelyFindValIO(this)
+ _ioValue
+ }
// Allow access to bindings from the compatibility package
- protected def _compatIoPortBound() = portsContains(_io)
+ protected def _compatIoPortBound() = _io.exists(portsContains(_))
private[chisel3] override def generateComponent(): Option[Component] = {
_compatAutoWrapPorts() // pre-IO(...) compatibility hack
// Restrict IO to just io, clock, and reset
- require(_io != null, "Module must have io")
- require(portsContains(_io), "Module must have io wrapped in IO(...)")
+ if (_io.isEmpty || !_compatIoPortBound) {
+ throwException(
+ s"Compatibility mode Module '$this' must have a 'val io' Bundle. " +
+ "If there is such a field and you still see this error, autowrapping has failed (sorry!). " +
+ "Please wrap the Bundle declaration in IO(...)."
+ )
+ }
require(
(portsContains(clock)) && (portsContains(reset)),
"Internal error, module did not have clock or reset as IO"
@@ -264,8 +271,8 @@ package object internal {
}
override def _compatAutoWrapPorts(): Unit = {
- if (!_compatIoPortBound() && _io != null) {
- _bindIoInPlace(_io)
+ if (!_compatIoPortBound()) {
+ _io.foreach(_bindIoInPlace(_))
}
}
}
@@ -283,13 +290,13 @@ package object internal {
implicit moduleCompileOptions: CompileOptions)
extends chisel3.BlackBox(params) {
- override private[chisel3] lazy val _io: Record = reflectivelyFindValIO(this)
+ override private[chisel3] lazy val _io: Option[Record] = reflectivelyFindValIO(this)
// This class auto-wraps the BlackBox with IO(...), allowing legacy code (where IO(...) wasn't
// required) to build.
override def _compatAutoWrapPorts(): Unit = {
if (!_compatIoPortBound()) {
- _bindIoInPlace(_io)
+ _io.foreach(_bindIoInPlace(_))
}
}
}