summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authormergify[bot]2022-02-01 21:37:08 +0000
committerGitHub2022-02-01 21:37:08 +0000
commit0eba2eb109910c1e4b980ccfc7f3ae85a8d0f223 (patch)
treec5785a5954fe59037046b3c9573c50823f0823ce /core/src
parentcb77b061e835044b4f3a2b718fb7ce3971b5d06e (diff)
Improve error reporting (backport #2376) (#2379)
* Improve error reporting (#2376) * Do not trim stack traces of exceptions with no stack trace This prevents us from accidentally giving stack traces to exceptions that don't have them and giving misleading messages telling users to use --full-stacktrace when it won't actually do anything. Also deprecate ChiselException.chiselStackTrace which is no longer being used anywhere in this codebase. * Add exception class for multiple-errors reported New chisel3.internal.Errors replaces old anonymous class that would show up as chisel3.internal.ErrorLog$$anon$1 in error messages. * Add new option --throw-on-first-error This tells Chisel not to aggregate recoverable errors but instead to throw an exception on the first one. This gives a stack trace for users who need it for debugging. (cherry picked from commit ff2e9c92247b3848659fa09fdd53ddde2120036a) * Waive MiMa false positives The waived change is to a package private constructor. Co-authored-by: Jack Koenig <koenig@sifive.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala2
-rw-r--r--core/src/main/scala/chisel3/internal/Builder.scala5
-rw-r--r--core/src/main/scala/chisel3/internal/Error.scala72
3 files changed, 47 insertions, 32 deletions
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
index b498daf0..59b4c692 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
@@ -100,7 +100,7 @@ object Definition extends SourceInfoDoc {
implicit sourceInfo: SourceInfo,
compileOptions: CompileOptions
): Definition[T] = {
- val dynamicContext = new DynamicContext(Nil)
+ val dynamicContext = new DynamicContext(Nil, Builder.captureContext().throwOnFirstError)
Builder.globalNamespace.copyTo(dynamicContext.globalNamespace)
dynamicContext.inDefinition = true
val (ir, module) = Builder.build(Module(proto), dynamicContext, false)
diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala
index fb6ebcc7..a00505a8 100644
--- a/core/src/main/scala/chisel3/internal/Builder.scala
+++ b/core/src/main/scala/chisel3/internal/Builder.scala
@@ -361,7 +361,7 @@ private[chisel3] class ChiselContext() {
val viewNamespace = Namespace.empty
}
-private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq) {
+private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq, val throwOnFirstError: Boolean) {
val globalNamespace = Namespace.empty
val components = ArrayBuffer[Component]()
val annotations = ArrayBuffer[ChiselAnnotation]()
@@ -653,7 +653,8 @@ private[chisel3] object Builder extends LazyLogging {
def errors: ErrorLog = dynamicContext.errors
def error(m: => String): Unit = {
- if (dynamicContextVar.value.isDefined) {
+ // If --throw-on-first-error is requested, throw an exception instead of aggregating errors
+ if (dynamicContextVar.value.isDefined && !dynamicContextVar.value.get.throwOnFirstError) {
errors.error(m)
} else {
throwException(m)
diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala
index c42f39ed..62086870 100644
--- a/core/src/main/scala/chisel3/internal/Error.scala
+++ b/core/src/main/scala/chisel3/internal/Error.scala
@@ -4,6 +4,7 @@ package chisel3.internal
import scala.annotation.tailrec
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
+import scala.util.control.NoStackTrace
import _root_.logger.Logger
object ExceptionHelpers {
@@ -46,31 +47,36 @@ object ExceptionHelpers {
}
// Step 1: Remove elements from the top in the package trimlist
- ((a: Array[StackTraceElement]) => a.dropWhile(inTrimlist))
- // Step 2: Optionally remove elements from the bottom until the anchor
- .andThen(_.reverse)
- .andThen(a =>
- anchor match {
- case Some(b) => a.dropWhile(ste => !ste.getClassName.startsWith(b))
- case None => a
- }
- )
- // Step 3: Remove elements from the bottom in the package trimlist
- .andThen(_.dropWhile(inTrimlist))
- // Step 4: Reverse back to the original order
- .andThen(_.reverse.toArray)
- // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info
- .andThen(a =>
- ellipsis() +:
- a :+
- ellipsis() :+
- ellipsis(
- Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace")
- )
- )
- // Step 5: Mutate the stack trace in this exception
- .andThen(throwable.setStackTrace(_))
- .apply(throwable.getStackTrace)
+ val trimStackTrace =
+ ((a: Array[StackTraceElement]) => a.dropWhile(inTrimlist))
+ // Step 2: Optionally remove elements from the bottom until the anchor
+ .andThen(_.reverse)
+ .andThen(a =>
+ anchor match {
+ case Some(b) => a.dropWhile(ste => !ste.getClassName.startsWith(b))
+ case None => a
+ }
+ )
+ // Step 3: Remove elements from the bottom in the package trimlist
+ .andThen(_.dropWhile(inTrimlist))
+ // Step 4: Reverse back to the original order
+ .andThen(_.reverse.toArray)
+ // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info
+ .andThen(a =>
+ ellipsis() +:
+ a :+
+ ellipsis() :+
+ ellipsis(
+ Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace")
+ )
+ )
+ // Step 5: Mutate the stack trace in this exception
+ .andThen(throwable.setStackTrace(_))
+
+ val stackTrace = throwable.getStackTrace
+ if (stackTrace.nonEmpty) {
+ trimStackTrace(stackTrace)
+ }
}
}
@@ -80,11 +86,11 @@ object ExceptionHelpers {
class ChiselException(message: String, cause: Throwable = null) extends Exception(message, cause, true, true) {
/** Package names whose stack trace elements should be trimmed when generating a trimmed stack trace */
- @deprecated("Use ExceptionHelpers.packageTrimlist. This will be removed in Chisel 3.6", "3.5")
+ @deprecated("Use ExceptionHelpers.packageTrimlist. This will be removed in Chisel 3.6", "Chisel 3.5")
val blacklistPackages: Set[String] = Set("chisel3", "scala", "java", "sun", "sbt")
/** The object name of Chisel's internal `Builder`. Everything stack trace element after this will be trimmed. */
- @deprecated("Use ExceptionHelpers.builderName. This will be removed in Chisel 3.6", "3.5")
+ @deprecated("Use ExceptionHelpers.builderName. This will be removed in Chisel 3.6", "Chisel 3.5")
val builderName: String = chisel3.internal.Builder.getClass.getName
/** Examine a [[Throwable]], to extract all its causes. Innermost cause is first.
@@ -138,6 +144,11 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio
trimmedReverse.toIndexedSeq.reverse.toArray
}
+ @deprecated(
+ "Use extension method trimStackTraceToUserCode defined in ExceptionHelpers.ThrowableHelpers. " +
+ "This will be removed in Chisel 3.6",
+ "Chisel 3.5.0"
+ )
def chiselStackTrace: String = {
val trimmed = trimmedStackTrace(likelyCause)
@@ -151,6 +162,7 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio
sw.toString
}
}
+private[chisel3] class Errors(message: String) extends ChiselException(message) with NoStackTrace
private[chisel3] object throwException {
def apply(s: String, t: Throwable = null): Nothing =
@@ -234,8 +246,10 @@ private[chisel3] class ErrorLog {
}
if (!allErrors.isEmpty) {
- throw new ChiselException("Fatal errors during hardware elaboration. Look above for error list.")
- with scala.util.control.NoStackTrace
+ throw new Errors(
+ "Fatal errors during hardware elaboration. Look above for error list. " +
+ "Rerun with --throw-on-first-error if you wish to see a stack trace."
+ )
} else {
// No fatal errors, clear accumulated warnings since they've been reported
errors.clear()