diff options
| author | Richard Lin | 2018-02-07 12:04:09 -0800 |
|---|---|---|
| committer | GitHub | 2018-02-07 12:04:09 -0800 |
| commit | 7be9b1c681558695b95fccb22a60c34101c86118 (patch) | |
| tree | eb0eaef935b55ace66ae49bdce0b3428fcc09c5c /chiselFrontend/src/main/scala/chisel3/internal | |
| parent | 1bfca502c69a26edca86d716a1ca9d24e6789e59 (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.scala | 31 |
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) |
