summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
diff options
context:
space:
mode:
authorJack Koenig2017-12-28 16:56:05 -0800
committerRichard Lin2018-01-02 13:43:01 -0800
commitade792ee7c5bb718f738f5e4c3886b2e87c68756 (patch)
tree0b3fb00565e1c442abd7885d490cd4324f02d3fe /chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
parent43e4d6dbd0f131c7484dc24cb09ab3a25614cb62 (diff)
Add support for autoclonetype of bound, anonymous inner Bundles
Also change Data.outerModule to Bundle._outerInst since it is only used in autoclonetype. _outerInst is also Option[Object] instead of Option[BaseModule] because the outer object could also be a Bundle.
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala21
1 files changed, 16 insertions, 5 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." +