summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSchuyler Eldridge2020-03-19 14:36:13 -0400
committerGitHub2020-03-19 14:36:13 -0400
commitb8a8d792a0e06520eb1f2acf94e149425234bd3b (patch)
treea0eef32ce759a2c98680ff3c2b8fbde37a97e296
parentd83235f635e4b048c063c8314e1340bca2db395f (diff)
parent3171cdf8472d50a4bcc6011c9b7786199a780514 (diff)
Merge pull request #1374 from freechipsproject/dont-wrap-elaboration-annotations
Don't wrap elaboration annotations
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/Error.scala61
-rw-r--r--src/main/scala/chisel3/stage/ChiselAnnotations.scala2
-rw-r--r--src/test/scala/chiselTests/ChiselSpec.scala5
-rw-r--r--src/test/scala/chiselTests/OneHotMuxSpec.scala16
-rw-r--r--src/test/scala/chiselTests/stage/ChiselMainSpec.scala22
5 files changed, 88 insertions, 18 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala
index 91d9d7de..f50a6579 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala
@@ -2,34 +2,77 @@
package chisel3.internal
+import scala.annotation.tailrec
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
class ChiselException(message: String, cause: Throwable = null) extends Exception(message, cause) {
- val blacklistPackages = Set("chisel3", "scala", "java", "sun", "sbt")
- val builderName = "chisel3.internal.Builder"
+ /** Package names whose stack trace elements should be trimmed when generating a trimmed stack trace */
+ val blacklistPackages: Set[String] = Set("chisel3", "scala", "java", "sun", "sbt")
- /** trims the top of the stack of elements belonging to [[blacklistPackages]]
- * then trims the bottom elements until it reaches [[builderName]]
- * then continues trimming elements belonging to [[blacklistPackages]]
+ /** The object name of Chisel's internal `Builder`. Everything stack trace element after this will be trimmed. */
+ val builderName: String = chisel3.internal.Builder.getClass.getName
+
+ /** Examine a [[Throwable]], recursively searching it's causes, for the first [[Throwable]] that contains a stack
+ * trace including a specific class name.
+ * @param throwable the root exception
+ * @param className a class name string to search for
+ * @return [[Some]] exception if the class name was found, [[None]] otherwise
+ */
+ @tailrec
+ private def findCause(throwable: Throwable, className: String): Option[Throwable] =
+ throwable.getStackTrace().collectFirst {
+ case ste if ste.getClassName().startsWith(className) => throwable
+ } match {
+ case a: Some[_] => a
+ case None => throwable.getCause() match {
+ case null => None
+ case cause: Throwable => findCause(cause, className)
+ }
+ }
+
+ /** Examine this [[ChiselException]] and it's causes for the first [[Throwable]] that contains a stack trace including
+ * a stack trace element whose declaring class is the [[builderName]]. If no such element exists, return this
+ * [[ChiselException]].
*/
- def trimmedStackTrace: Array[StackTraceElement] = {
+ private lazy val likelyCause: Throwable = findCause(this, builderName).getOrElse(this)
+
+ /** For an exception, return a stack trace trimmed to user code only
+ *
+ * This does the following actions:
+ *
+ * 1. Trims the top of the stack trace while elements match [[blacklistPackages]]
+ * 2. Trims the bottom of the stack trace until an element matches [[builderName]]
+ * 3. Trims from the [[builderName]] all [[blacklistPackages]]
+ *
+ * @param throwable the exception whose stack trace should be trimmed
+ * @return an array of stack trace elements
+ */
+ private def trimmedStackTrace(throwable: Throwable): Array[StackTraceElement] = {
def isBlacklisted(ste: StackTraceElement) = {
val packageName = ste.getClassName().takeWhile(_ != '.')
blacklistPackages.contains(packageName)
}
- val trimmedLeft = getStackTrace().view.dropWhile(isBlacklisted)
+ val trimmedLeft = throwable.getStackTrace().view.dropWhile(isBlacklisted)
val trimmedReverse = trimmedLeft.reverse
.dropWhile(ste => !ste.getClassName.startsWith(builderName))
.dropWhile(isBlacklisted)
trimmedReverse.reverse.toArray
}
+ /** trims the top of the stack of elements belonging to [[blacklistPackages]]
+ * then trims the bottom elements until it reaches [[builderName]]
+ * then continues trimming elements belonging to [[blacklistPackages]]
+ */
+ @deprecated("This method will be removed in 3.4", "3.3")
+ def trimmedStackTrace: Array[StackTraceElement] = trimmedStackTrace(this)
+
def chiselStackTrace: String = {
- val trimmed = trimmedStackTrace
+ val trimmed = trimmedStackTrace(likelyCause)
+
val sw = new java.io.StringWriter
- sw.write(toString + "\n")
+ sw.write(likelyCause.toString + "\n")
sw.write("\t...\n")
trimmed.foreach(ste => sw.write(s"\tat $ste\n"))
sw.write("\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n") // scalastyle:ignore line.size.limit
diff --git a/src/main/scala/chisel3/stage/ChiselAnnotations.scala b/src/main/scala/chisel3/stage/ChiselAnnotations.scala
index bfce0e8d..11697d7d 100644
--- a/src/main/scala/chisel3/stage/ChiselAnnotations.scala
+++ b/src/main/scala/chisel3/stage/ChiselAnnotations.scala
@@ -52,7 +52,7 @@ case class ChiselGeneratorAnnotation(gen: () => RawModule) extends NoTargetAnnot
} catch {
case e @ (_: OptionsException | _: ChiselException) => throw e
case e: Throwable =>
- throw new OptionsException(s"Exception thrown when elaborating ChiselGeneratorAnnotation", e)
+ throw new ChiselException(s"Exception thrown when elaborating ChiselGeneratorAnnotation", e)
}
}
diff --git a/src/test/scala/chiselTests/ChiselSpec.scala b/src/test/scala/chiselTests/ChiselSpec.scala
index 9af7e88f..be1b2d60 100644
--- a/src/test/scala/chiselTests/ChiselSpec.scala
+++ b/src/test/scala/chiselTests/ChiselSpec.scala
@@ -7,7 +7,6 @@ import org.scalatest.prop._
import org.scalacheck._
import chisel3._
import chisel3.testers._
-import firrtl.options.OptionsException
import firrtl.{AnnotationSeq, CommonOptions, ExecutionOptionsManager, FirrtlExecutionFailure, FirrtlExecutionSuccess, HasFirrtlOptions}
import firrtl.util.BackendCompilationUtilities
import java.io.ByteArrayOutputStream
@@ -100,7 +99,7 @@ class ChiselTestUtilitiesSpec extends ChiselFlatSpec {
import org.scalatest.exceptions.TestFailedException
// Who tests the testers?
"assertKnownWidth" should "error when the expected width is wrong" in {
- val caught = intercept[OptionsException] {
+ val caught = intercept[ChiselException] {
assertKnownWidth(7) {
Wire(UInt(8.W))
}
@@ -123,7 +122,7 @@ class ChiselTestUtilitiesSpec extends ChiselFlatSpec {
}
"assertInferredWidth" should "error if the width is known" in {
- val caught = intercept[OptionsException] {
+ val caught = intercept[ChiselException] {
assertInferredWidth(8) {
Wire(UInt(8.W))
}
diff --git a/src/test/scala/chiselTests/OneHotMuxSpec.scala b/src/test/scala/chiselTests/OneHotMuxSpec.scala
index 7476ebe2..e6c9add4 100644
--- a/src/test/scala/chiselTests/OneHotMuxSpec.scala
+++ b/src/test/scala/chiselTests/OneHotMuxSpec.scala
@@ -4,6 +4,7 @@ package chiselTests
import chisel3._
import chisel3.experimental.FixedPoint
+import chisel3.internal.ChiselException
import chisel3.testers.BasicTester
import chisel3.util.{Mux1H, UIntToOH}
import org.scalatest._
@@ -31,23 +32,31 @@ class OneHotMuxSpec extends FreeSpec with Matchers with ChiselRunners {
assertTesterPasses(new ParameterizedAggregateOneHotTester)
}
"simple one hot mux with all aggregates containing inferred width fixed values should NOT work" in {
- intercept[ChiselException] {
+ intercept [ChiselException] {
assertTesterPasses(new InferredWidthAggregateOneHotTester)
}
}
"simple one hot mux with all fixed width bundles but with different bundles should Not work" in {
- intercept[IllegalArgumentException] {
+ try {
assertTesterPasses(new DifferentBundleOneHotTester)
+ } catch {
+ case a: ChiselException => a.getCause match {
+ case _: IllegalArgumentException =>
+ }
}
}
"UIntToOH with output width greater than 2^(input width)" in {
assertTesterPasses(new UIntToOHTester)
}
"UIntToOH should not accept width of zero (until zero-width wires are fixed" in {
- intercept[java.lang.IllegalArgumentException] {
+ try {
assertTesterPasses(new BasicTester {
val out = UIntToOH(0.U, 0)
})
+ } catch {
+ case a: ChiselException => a.getCause match {
+ case _: IllegalArgumentException =>
+ }
}
}
@@ -305,4 +314,3 @@ class UIntToOHTester extends BasicTester {
stop()
}
-
diff --git a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala
index 2b3b9c2c..f5b47982 100644
--- a/src/test/scala/chiselTests/stage/ChiselMainSpec.scala
+++ b/src/test/scala/chiselTests/stage/ChiselMainSpec.scala
@@ -25,6 +25,11 @@ object ChiselMainSpec {
out := in
}
+ /** A module that fails a requirement */
+ class FailingRequirementModule extends RawModule {
+ require(false)
+ }
+
}
case class TestClassAspect() extends InspectorAspect[RawModule] ({
@@ -128,7 +133,22 @@ class ChiselMainSpec extends FeatureSpec with GivenWhenThen with Matchers with c
result = 1)
).foreach(runStageExpectFiles)
}
- feature("Aspect library") {
+ feature("Report properly trimmed stack traces") {
+ Seq(
+ ChiselMainTest(args = Array("-X", "low"),
+ generator = Some(classOf[FailingRequirementModule]),
+ stdout = Some("requirement failed"),
+ result = 1),
+ ChiselMainTest(args = Array("-X", "low", "--full-stacktrace"),
+ generator = Some(classOf[FailingRequirementModule]),
+ stdout = Some("chisel3.internal.ChiselException"),
+ result = 1)
+ ).foreach(runStageExpectFiles)
+ }
+
+ info("As an aspect writer")
+ info("I write an aspect")
+ feature("Running aspects via the command line") {
Seq(
ChiselMainTest(args = Array( "-X", "high", "--with-aspect", "chiselTests.stage.TestClassAspect" ),
generator = Some(classOf[SameTypesModule]),