summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/internal
diff options
context:
space:
mode:
authorRichard Lin2018-02-07 12:04:09 -0800
committerGitHub2018-02-07 12:04:09 -0800
commit7be9b1c681558695b95fccb22a60c34101c86118 (patch)
treeeb0eaef935b55ace66ae49bdce0b3428fcc09c5c /chiselFrontend/src/main/scala/chisel3/internal
parent1bfca502c69a26edca86d716a1ca9d24e6789e59 (diff)
Better support for autoclonetype of nested Bundles (#769)
* Better support for autoclonetype of nested Bundles * Move bundleStack to dynamicContext * prefer $outer if available, make guesses distinct * Catch IllegalAccessException in autoclonetype In strange circumstances this type of exception can occur when accessing $outer
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/internal')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/Builder.scala31
1 files changed, 31 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
index 0b279347..c9b37fc5 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
@@ -156,6 +156,8 @@ private[chisel3] class DynamicContext() {
var currentClockAndReset: Option[ClockAndReset] = None
val errors = new ErrorLog
val namingStack = new internal.naming.NamingStack
+ // Record the Bundle instance, class name, and reverse stack trace position of open Bundles
+ val bundleStack: ArrayBuffer[(Bundle, String, Int)] = ArrayBuffer()
}
private[chisel3] object Builder {
@@ -223,6 +225,35 @@ private[chisel3] object Builder {
pushCommand(cmd).id
}
+ // Called when Bundle construction begins, used to record a stack of open Bundle constructors to
+ // record candidates for Bundle autoclonetype. This is a best-effort guess.
+ // Returns the current stack of open Bundles
+ // Note: elt will NOT have finished construction, its elements cannot be accessed
+ def updateBundleStack(elt: Bundle): Seq[Bundle] = {
+ val stackClasses = Thread.currentThread().getStackTrace()
+ .map(_.getClassName)
+ .reverse // so stack frame numbers are deterministic across calls
+
+ // Prune the existing Bundle stack of closed Bundles
+ val pruneLength = dynamicContext.bundleStack.reverse.prefixLength { case (_, cname, pos) =>
+ pos >= stackClasses.size || stackClasses(pos) != cname
+ }
+ dynamicContext.bundleStack.trimEnd(pruneLength)
+
+ // Return the stack state before adding the most recent bundle
+ val lastStack = dynamicContext.bundleStack.map(_._1).toSeq
+
+ // Append the current Bundle to the stack, if it's on the stack trace
+ val eltClassName = elt.getClass.getName
+ val eltStackPos = stackClasses.lastIndexOf(eltClassName)
+ if (eltStackPos >= 0) {
+ dynamicContext.bundleStack.append((elt, eltClassName, eltStackPos))
+ }
+ // Otherwise discard the stack frame, this shouldn't fail noisily
+
+ lastStack
+ }
+
def errors: ErrorLog = dynamicContext.errors
def error(m: => String): Unit = errors.error(m)
def warning(m: => String): Unit = errors.warning(m)