summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'chiselFrontend/src/main')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala21
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala6
2 files changed, 17 insertions, 10 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
index 43e430cd..14011cd9 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -556,6 +556,11 @@ class Bundle(implicit compileOptions: CompileOptions) extends Record {
case _ => None
}
+ // If this Data is an instance of an inner class, record a *guess* at the outer object.
+ // This is only used for cloneType, and is mutable to allow autoCloneType to try guesses other
+ // than the module that was current when the Bundle was constructed.
+ private var _outerInst: Option[Object] = Builder.currentModule
+
override def cloneType : this.type = {
// This attempts to infer constructor and arguments to clone this Bundle subtype without
// requiring the user explicitly overriding cloneType.
@@ -570,16 +575,22 @@ class Bundle(implicit compileOptions: CompileOptions) extends Record {
// Check if this is an inner class, and if so, try to get the outer instance
val clazz = this.getClass
val outerClassInstance = Option(clazz.getEnclosingClass).map { outerClass =>
+ def canAssignOuterClass(x: Object) = outerClass.isAssignableFrom(x.getClass)
val outerInstance = try {
clazz.getDeclaredField("$outer").get(this) // doesn't work in all cases, namely anonymous inner Bundles
} catch {
case _: NoSuchFieldException =>
- this.outerModule.getOrElse(reflectError(s"Unable to determine instance of outer class $outerClass"))
+ // First check if this Bundle is bound and an anonymous inner Bundle of another Bundle
+ this.bindingOpt.collect { case ChildBinding(p) if canAssignOuterClass(p) => p }
+ .orElse(this._outerInst)
+ .getOrElse(reflectError(s"Unable to determine instance of outer class $outerClass"))
}
- if (!outerClass.isAssignableFrom(outerInstance.getClass)) {
+ if (!canAssignOuterClass(outerInstance)) {
reflectError(s"Unable to determine instance of outer class $outerClass," +
s" guessed $outerInstance, but is not assignable to outer class $outerClass")
}
+ // Record the outer instance for future cloning
+ this._outerInst = Some(outerInstance)
(outerClass, outerInstance)
}
@@ -605,7 +616,7 @@ class Bundle(implicit compileOptions: CompileOptions) extends Record {
}
clone match {
case Some(clone) =>
- clone.outerModule = this.outerModule
+ clone._outerInst = this._outerInst
if (!clone.typeEquivalent(this)) {
reflectError(s"Automatically cloned $clone not type-equivalent to base $this." +
" Constructor argument values were not inferred, ensure constructor is deterministic.")
@@ -650,7 +661,7 @@ class Bundle(implicit compileOptions: CompileOptions) extends Record {
require(ctors.size == 1) // should be consistent with Scala constructors
try {
val clone = ctors.head.newInstance(outerClassInstance.get._2).asInstanceOf[this.type]
- clone.outerModule = this.outerModule
+ clone._outerInst = this._outerInst
return clone
} catch {
case e @ (_: java.lang.reflect.InvocationTargetException | _: IllegalArgumentException) =>
@@ -703,7 +714,7 @@ class Bundle(implicit compileOptions: CompileOptions) extends Record {
case None => mirror.reflectClass(classSymbol)
}
val clone = classMirror.reflectConstructor(ctor).apply(ctorParamsVals:_*).asInstanceOf[this.type]
- clone.outerModule = this.outerModule
+ clone._outerInst = this._outerInst
if (!clone.typeEquivalent(this)) {
reflectError(s"Automatically cloned $clone not type-equivalent to base $this." +
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index 35401fa1..1cf50e9f 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -208,11 +208,6 @@ abstract class Data extends HasId {
}
}
- // If this Data is an instance of an inner class, record enclosing class
- // This is only used for cloneType, and is mutable to allow autoCloneType to preserve the
- // original outerModule.
- private[core] var outerModule: Option[BaseModule] = Builder.currentModule
-
// User-specified direction, local at this node only.
// Note that the actual direction of this node can differ from child and parent specifiedDirection.
private var _specifiedDirection: SpecifiedDirection = SpecifiedDirection.Unspecified
@@ -245,6 +240,7 @@ abstract class Data extends HasId {
// This information is supplemental (more than is necessary to generate FIRRTL) and is used to
// perform checks in Chisel, where more informative error messages are possible.
private var _binding: Option[Binding] = None
+ private[core] def bindingOpt = _binding
private[core] def hasBinding = _binding.isDefined
// Only valid after node is bound (synthesizable), crashes otherwise
private[core] def binding = _binding.get