aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/firrtl/Compiler.scala6
-rw-r--r--src/main/scala/firrtl/Driver.scala65
-rw-r--r--src/main/scala/firrtl/Emitter.scala13
-rw-r--r--src/main/scala/firrtl/Utils.scala79
-rw-r--r--src/main/scala/firrtl/Visitor.scala3
-rw-r--r--src/main/scala/firrtl/annotations/AnnotationUtils.scala6
-rw-r--r--src/main/scala/firrtl/passes/CheckWidths.scala2
-rw-r--r--src/main/scala/firrtl/passes/ConvertFixedToSInt.scala6
-rw-r--r--src/main/scala/firrtl/passes/ExpandWhens.scala2
-rw-r--r--src/main/scala/firrtl/passes/InferWidths.scala2
-rw-r--r--src/main/scala/firrtl/passes/RemoveAccesses.scala2
-rw-r--r--src/main/scala/firrtl/passes/RemoveValidIf.scala2
-rw-r--r--src/main/scala/firrtl/passes/Resolves.scala9
-rw-r--r--src/main/scala/firrtl/passes/Uniquify.scala2
-rw-r--r--src/main/scala/firrtl/passes/clocklist/ClockList.scala2
-rw-r--r--src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala2
-rw-r--r--src/main/scala/firrtl/passes/memlib/YamlUtils.scala2
-rw-r--r--src/main/scala/firrtl/transforms/CheckCombLoops.scala4
-rw-r--r--src/main/scala/firrtl/transforms/ConstantPropagation.scala2
-rw-r--r--src/main/scala/firrtl/transforms/DeadCodeElimination.scala6
-rw-r--r--src/main/scala/firrtl/transforms/RemoveWires.scala2
-rw-r--r--src/test/scala/firrtlTests/InternalErrorSpec.scala46
22 files changed, 199 insertions, 66 deletions
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
index 43596765..504ec85c 100644
--- a/src/main/scala/firrtl/Compiler.scala
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -203,7 +203,7 @@ final case object LowForm extends CircuitForm(0)
* this requirement.
*/
final case object UnknownForm extends CircuitForm(-1) {
- override def compare(that: CircuitForm): Int = { error("Illegal to compare UnknownForm"); 0 }
+ override def compare(that: CircuitForm): Int = { sys.error("Illegal to compare UnknownForm"); 0 }
}
/** The basic unit of operating on a Firrtl AST */
@@ -331,8 +331,8 @@ object CompilerUtils extends LazyLogging {
Seq(new IRToWorkingIR, new ResolveAndCheck, new transforms.DedupModules,
new HighFirrtlToMiddleFirrtl) ++ getLoweringTransforms(MidForm, outputForm)
case MidForm => Seq(new MiddleFirrtlToLowFirrtl) ++ getLoweringTransforms(LowForm, outputForm)
- case LowForm => throwInternalError // should be caught by if above
- case UnknownForm => throwInternalError // should be caught by if above
+ case LowForm => throwInternalError(Some("getLoweringTransforms - LowForm")) // should be caught by if above
+ case UnknownForm => throwInternalError(Some("getLoweringTransforms - UnknownForm")) // should be caught by if above
}
}
}
diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala
index bc5102d2..99ae6d54 100644
--- a/src/main/scala/firrtl/Driver.scala
+++ b/src/main/scala/firrtl/Driver.scala
@@ -5,6 +5,7 @@ package firrtl
import scala.collection._
import scala.io.Source
import scala.sys.process.{BasicIO,stringSeqToProcess}
+import scala.util.control.ControlThrowable
import java.io.{File, FileNotFoundException}
import net.jcazevedo.moultingyaml._
@@ -12,8 +13,9 @@ import logger.Logger
import Parser.{IgnoreInfo, InfoMode}
import annotations._
import firrtl.annotations.AnnotationYamlProtocol._
+import firrtl.passes.PassException
import firrtl.transforms._
-import Utils.throwInternalError
+import firrtl.Utils.throwInternalError
/**
@@ -52,12 +54,23 @@ object Driver {
customTransforms: Seq[Transform] = Seq.empty,
annotations: AnnotationMap = AnnotationMap(Seq.empty)
): String = {
- val parsedInput = Parser.parse(Source.fromFile(input).getLines(), infoMode)
val outputBuffer = new java.io.CharArrayWriter
- compiler.compile(
- CircuitState(parsedInput, ChirrtlForm, Some(annotations)),
- outputBuffer,
- customTransforms)
+ try {
+ val parsedInput = Parser.parse(Source.fromFile(input).getLines(), infoMode)
+ compiler.compile(
+ CircuitState(parsedInput, ChirrtlForm, Some(annotations)),
+ outputBuffer,
+ customTransforms)
+ }
+
+ catch {
+ // Rethrow the exceptions which are expected or due to the runtime environment (out of memory, stack overflow)
+ case p: ControlThrowable => throw p
+ case p: PassException => throw p
+ case p: FIRRTLException => throw p
+ // Treat remaining exceptions as internal errors.
+ case e: Exception => throwInternalError(exception = Some(e))
+ }
val outputFile = new java.io.PrintWriter(output)
val outputString = outputBuffer.toString
@@ -191,19 +204,35 @@ object Driver {
}
}
- val annos = loadAnnotations(optionsManager)
+ var maybeFinalState: Option[CircuitState] = None
+
+ // Wrap compilation in a try/catch to present Scala MatchErrors in a more user-friendly format.
+ try {
+ val annos = loadAnnotations(optionsManager)
- val parsedInput = Parser.parse(firrtlSource, firrtlConfig.infoMode)
+ val parsedInput = Parser.parse(firrtlSource, firrtlConfig.infoMode)
- // Does this need to be before calling compiler?
- optionsManager.makeTargetDir()
+ // Does this need to be before calling compiler?
+ optionsManager.makeTargetDir()
+
+ maybeFinalState = Some(firrtlConfig.compiler.compile(
+ CircuitState(parsedInput,
+ ChirrtlForm,
+ Some(AnnotationMap(annos))),
+ firrtlConfig.customTransforms
+ ))
+ }
+
+ catch {
+ // Rethrow the exceptions which are expected or due to the runtime environment (out of memory, stack overflow)
+ case p: ControlThrowable => throw p
+ case p: PassException => throw p
+ case p: FIRRTLException => throw p
+ // Treat remaining exceptions as internal errors.
+ case e: Exception => throwInternalError(exception = Some(e))
+ }
- val finalState = firrtlConfig.compiler.compile(
- CircuitState(parsedInput,
- ChirrtlForm,
- Some(AnnotationMap(annos))),
- firrtlConfig.customTransforms
- )
+ val finalState = maybeFinalState.get
// Do emission
// Note: Single emission target assumption is baked in here
@@ -217,7 +246,7 @@ object Driver {
emitted.value
case OneFilePerModule(dirName) =>
val emittedModules = finalState.emittedComponents collect { case x: EmittedModule => x }
- if (emittedModules.isEmpty) throwInternalError // There should be something
+ if (emittedModules.isEmpty) throwInternalError() // There should be something
emittedModules.foreach { module =>
val filename = optionsManager.getBuildFileName(firrtlConfig.outputSuffix, s"$dirName/${module.name}")
val outputFile = new java.io.PrintWriter(filename)
@@ -261,7 +290,7 @@ object Driver {
optionsManager.showUsageAsError()
failure
case result =>
- throw new Exception(s"Error: Unknown Firrtl Execution result $result")
+ throwInternalError(Some(s"Error: Unknown Firrtl Execution result $result"))
}
}
else {
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 84b34339..5753fc17 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -120,7 +120,7 @@ sealed abstract class FirrtlEmitter(form: CircuitForm) extends Transform with Em
case WDefInstance(_, _, name, _) =>
modules += map(name)
stmt
- case _: WDefInstanceConnector => throwInternalError
+ case _: WDefInstanceConnector => throwInternalError(Some(s"unrecognized statement: $stmt"))
case other => other map onStmt
}
onStmt(mod.body)
@@ -191,7 +191,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
case (e: WSubField) => remove_root(e)
case (_: WRef) => WRef(ex.name, ex.tpe, InstanceKind, UNKNOWNGENDER)
}
- case _ => error("Shouldn't be here")
+ case _ => throwInternalError(Some(s"shouldn't be here: remove_root($ex)"))
}
/** Turn Params into Verilog Strings */
def stringify(param: Param): String = param match {
@@ -205,7 +205,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
val wx = bitWidth(tpe) - 1
if (wx > 0) s"[$wx:0]" else ""
case ClockType => ""
- case _ => error("Trying to write unsupported type in the Verilog Emitter")
+ case _ => throwInternalError(Some(s"trying to write unsupported type in the Verilog Emitter: $tpe"))
}
def emit(x: Any)(implicit w: Writer) { emit(x, 0) }
def emit(x: Any, top: Int)(implicit w: Writer) {
@@ -214,6 +214,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
case (t: SIntType) => Seq("$signed(",e,")")
case ClockType => e
case AnalogType(_) => e
+ case _ => throwInternalError(Some(s"unrecognized cast: $e"))
}
x match {
case (e: DoPrim) => emit(op_stream(e), top + 1)
@@ -240,7 +241,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
case (s: Seq[Any]) =>
s foreach (emit(_, top + 1))
if (top == 0) w write "\n"
- case x => println(x); throwInternalError;
+ case x => throwInternalError(Some(s"trying to emit unsupported operator: $x"))
}
}
@@ -254,6 +255,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
case '-' => s"-$width'sh${stringLiteral.tail}"
case _ => s"$width'sh${stringLiteral}"
})
+ case _ => throwInternalError(Some(s"attempt to print unrecognized expression: $e"))
}
def op_stream(doprim: DoPrim): Seq[Any] = {
@@ -266,16 +268,19 @@ class VerilogEmitter extends SeqTransform with Emitter {
case Some(_) => e.tpe match {
case (_: SIntType) => Seq("$signed(", e, ")")
case (_: UIntType) => Seq("$signed({1'b0,", e, "})")
+ case _ => throwInternalError(Some(s"unrecognized type: $e"))
}
}
}
def cast(e: Expression): Any = doprim.tpe match {
case (t: UIntType) => e
case (t: SIntType) => Seq("$signed(",e,")")
+ case _ => throwInternalError(Some(s"cast - unrecognized type: $e"))
}
def cast_as(e: Expression): Any = e.tpe match {
case (t: UIntType) => e
case (t: SIntType) => Seq("$signed(",e,")")
+ case _ => throwInternalError(Some(s"cast_as - unrecognized type: $e"))
}
def a0: Expression = doprim.args.head
def a1: Expression = doprim.args(1)
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index 76f58f30..e5a7e6be 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -12,6 +12,20 @@ import scala.collection.mutable.{StringBuilder, ArrayBuffer, LinkedHashMap, Hash
import java.io.PrintWriter
import logger.LazyLogging
+object FIRRTLException {
+ def defaultMessage(message: String, cause: Throwable) = {
+ if (message != null) {
+ message
+ } else if (cause != null) {
+ cause.toString
+ } else {
+ null
+ }
+ }
+}
+class FIRRTLException(val str: String, cause: Throwable = null)
+ extends RuntimeException(FIRRTLException.defaultMessage(str, cause), cause)
+
object seqCat {
def apply(args: Seq[Expression]): Expression = args.length match {
case 0 => Utils.error("Empty Seq passed to seqcat")
@@ -29,7 +43,7 @@ object seqCat {
object toBits {
def apply(e: Expression): Expression = e match {
case ex @ (_: WRef | _: WSubField | _: WSubIndex) => hiercat(ex)
- case t => Utils.error("Invalid operand expression for toBits!")
+ case t => Utils.error(s"Invalid operand expression for toBits: $e")
}
private def hiercat(e: Expression): Expression = e.tpe match {
case t: VectorType => seqCat((0 until t.size).reverse map (i =>
@@ -37,14 +51,14 @@ object toBits {
case t: BundleType => seqCat(t.fields map (f =>
hiercat(WSubField(e, f.name, f.tpe, UNKNOWNGENDER))))
case t: GroundType => DoPrim(AsUInt, Seq(e), Seq.empty, UnknownType)
- case t => Utils.error("Unknown type encountered in toBits!")
+ case t => Utils.error(s"Unknown type encountered in toBits: $e")
}
}
object getWidth {
def apply(t: Type): Width = t match {
case t: GroundType => t.width
- case _ => Utils.error("No width!")
+ case _ => Utils.error(s"No width: $t")
}
def apply(e: Expression): Width = apply(e.tpe)
}
@@ -55,7 +69,7 @@ object bitWidth {
case t: VectorType => t.size * bitWidth(t.tpe)
case t: BundleType => t.fields.map(f => bitWidth(f.tpe)).foldLeft(BigInt(0))(_+_)
case GroundType(IntWidth(width)) => width
- case t => Utils.error("Unknown type encountered in bitWidth!")
+ case t => Utils.error(s"Unknown type encountered in bitWidth: $dt")
}
}
@@ -112,7 +126,7 @@ object fromBits {
(tmpOffset, stmts ++ substmts)
}
case t: GroundType => getPartGround(lhs, t, rhs, offset)
- case t => Utils.error("Unknown type encountered in fromBits!")
+ case t => Utils.error(s"Unknown type encountered in fromBits: $lhst")
}
}
@@ -125,11 +139,46 @@ object flattenType {
def apply(t: Type) = UIntType(IntWidth(bitWidth(t)))
}
-class FIRRTLException(val str: String) extends Exception(str)
-
object Utils extends LazyLogging {
- def throwInternalError =
- error("Internal Error! Please file an issue at https://github.com/ucb-bar/firrtl/issues")
+ /** Unwind the causal chain until we hit the initial exception (which may be the first).
+ *
+ * @param maybeException - possible exception triggering the error,
+ * @param first - true if we want the first (eldest) exception in the chain,
+ * @return first or last Throwable in the chain.
+ */
+ def getThrowable(maybeException: Option[Throwable], first: Boolean): Throwable = {
+ maybeException match {
+ case Some(e: Throwable) => {
+ val t = e.getCause
+ if (t != null) {
+ if (first) {
+ getThrowable(Some(t), first)
+ } else {
+ t
+ }
+ } else {
+ e
+ }
+ }
+ case None | null => null
+ }
+ }
+
+ /** Throw an internal error, possibly due to an exception.
+ *
+ * @param message - possible string to emit,
+ * @param exception - possible exception triggering the error.
+ */
+ def throwInternalError(message: Option[String] = None, exception: Option[Exception] = None) = {
+ // We'll get the first exception in the chain, keeping it intact.
+ val first = true
+ val throwable = getThrowable(exception, true)
+ val string: String = message match {
+ case Some(s: String) => s + "\n"
+ case _ => ""
+ }
+ error("Internal Error! %sPlease file an issue at https://github.com/ucb-bar/firrtl/issues".format(string), throwable)
+ }
private[firrtl] def time[R](block: => R): (Double, R) = {
val t0 = System.nanoTime()
@@ -210,7 +259,7 @@ object Utils extends LazyLogging {
}
}
def get_flip(t: Type, i: Int, f: Orientation): Orientation = {
- if (i >= get_size(t)) error("Shouldn't be here")
+ if (i >= get_size(t)) throwInternalError(Some(s"get_flip: shouldn't be here - $i >= get_size($t)"))
t match {
case (_: GroundType) => f
case (tx: BundleType) =>
@@ -386,7 +435,7 @@ object Utils extends LazyLogging {
//>>>>>>> e54fb610c6bf0a7fe5c9c0f0e0b3acbb3728cfd0
// =================================
- def error(str: String) = throw new FIRRTLException(str)
+ def error(str: String, cause: Throwable = null) = throw new FIRRTLException(str, cause)
//// =============== EXPANSION FUNCTIONS ================
def get_size(t: Type): Int = t match {
@@ -426,7 +475,7 @@ object Utils extends LazyLogging {
ilen + get_size(t1x.tpe), jlen + get_size(t2x.tpe))
}._1
case (ClockType, ClockType) => if (flip1 == flip2) Seq((0, 0)) else Nil
- case _ => Utils.error("shouldn't be here")
+ case _ => throwInternalError(Some(s"get_valid_points: shouldn't be here - ($t1, $t2)"))
}
}
@@ -472,9 +521,9 @@ object Utils extends LazyLogging {
def get_field(v: Type, s: String): Field = v match {
case vx: BundleType => vx.fields find (_.name == s) match {
case Some(ft) => ft
- case None => Utils.error("Shouldn't be here")
+ case None => throwInternalError(Some(s"get_field: shouldn't be here - $v.$s"))
}
- case vx => Utils.error("Shouldn't be here")
+ case vx => throwInternalError(Some(s"get_field: shouldn't be here - $v"))
}
def times(flip: Orientation, d: Direction): Direction = times(flip, d)
@@ -517,7 +566,7 @@ object Utils extends LazyLogging {
case ex: Mux => MALE
case ex: ValidIf => MALE
case WInvalid => MALE
- case ex => println(ex); error("Shouldn't be here")
+ case ex => throwInternalError(Some(s"gender: shouldn't be here - $e"))
}
def get_gender(s: Statement): Gender = s match {
case sx: DefWire => BIGENDER
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index c5a21b23..d0173774 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -11,6 +11,7 @@ import PrimOps._
import FIRRTLParser._
import Parser.{AppendInfo, GenInfo, IgnoreInfo, InfoMode, UseInfo}
import firrtl.ir._
+import Utils.throwInternalError
class Visitor(infoMode: InfoMode) extends FIRRTLBaseVisitor[FirrtlNode] {
@@ -92,7 +93,7 @@ class Visitor(infoMode: InfoMode) extends FIRRTLBaseVisitor[FirrtlNode] {
case (null, str, null, null) => StringParam(name, visitStringLit(str))
case (null, null, dbl, null) => DoubleParam(name, dbl.getText.toDouble)
case (null, null, null, raw) => RawStringParam(name, raw.getText.tail.init) // Remove "\'"s
- case _ => throw new Exception(s"Internal error: Visiting impossible parameter ${ctx.getText}")
+ case _ => throwInternalError(Some(s"visiting impossible parameter ${ctx.getText}"))
}
}
diff --git a/src/main/scala/firrtl/annotations/AnnotationUtils.scala b/src/main/scala/firrtl/annotations/AnnotationUtils.scala
index ab580e88..240c46d6 100644
--- a/src/main/scala/firrtl/annotations/AnnotationUtils.scala
+++ b/src/main/scala/firrtl/annotations/AnnotationUtils.scala
@@ -56,7 +56,7 @@ object AnnotationUtils {
val DecPattern = """([1-9]\d*)""".r
def findClose(tokens: Seq[String], index: Int, nOpen: Int): Seq[String] = {
if(index >= tokens.size) {
- error("Cannot find closing bracket ]")
+ Utils.error("Cannot find closing bracket ]")
} else tokens(index) match {
case "[" => findClose(tokens, index + 1, nOpen + 1)
case "]" if nOpen == 1 => tokens.slice(1, index)
@@ -81,6 +81,8 @@ object AnnotationUtils {
}
if(validComponentName(s)) {
parse(tokenize(s))
- } else error(s"Cannot convert $s into an expression.")
+ } else {
+ Utils.error(s"Cannot convert $s into an expression.")
+ }
}
}
diff --git a/src/main/scala/firrtl/passes/CheckWidths.scala b/src/main/scala/firrtl/passes/CheckWidths.scala
index 8f6ab18f..55391d99 100644
--- a/src/main/scala/firrtl/passes/CheckWidths.scala
+++ b/src/main/scala/firrtl/passes/CheckWidths.scala
@@ -50,7 +50,7 @@ object CheckWidths extends Pass {
def hasWidth(tpe: Type): Boolean = tpe match {
case GroundType(IntWidth(w)) => true
case GroundType(_) => false
- case _ => println(tpe); throwInternalError
+ case _ => throwInternalError(Some(s"hasWidth - $tpe"))
}
def check_width_t(info: Info, mname: String)(t: Type): Type =
diff --git a/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala b/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala
index 05604bd8..b52dacb7 100644
--- a/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala
+++ b/src/main/scala/firrtl/passes/ConvertFixedToSInt.scala
@@ -7,7 +7,7 @@ import firrtl.PrimOps._
import firrtl.ir._
import firrtl._
import firrtl.Mappers._
-import firrtl.Utils.{sub_type, module_type, field_type, max, error}
+import firrtl.Utils.{sub_type, module_type, field_type, max, error, throwInternalError}
/** Replaces FixedType with SIntType, and correctly aligns all binary points
*/
@@ -19,7 +19,7 @@ object ConvertFixedToSInt extends Pass {
} else if (point - p < 0) {
DoPrim(Shr, Seq(e), Seq(p - point), UnknownType)
} else e
- case FixedType(w, p) => error("Shouldn't be here")
+ case FixedType(w, p) => throwInternalError(Some(s"alignArg: shouldn't be here - $e"))
case _ => e
}
def calcPoint(es: Seq[Expression]): BigInt =
@@ -29,7 +29,7 @@ object ConvertFixedToSInt extends Pass {
}).reduce(max(_, _))
def toSIntType(t: Type): Type = t match {
case FixedType(IntWidth(w), IntWidth(p)) => SIntType(IntWidth(w))
- case FixedType(w, p) => error("Shouldn't be here")
+ case FixedType(w, p) => throwInternalError(Some(s"toSIntType: shouldn't be here - $t"))
case _ => t map toSIntType
}
def run(c: Circuit): Circuit = {
diff --git a/src/main/scala/firrtl/passes/ExpandWhens.scala b/src/main/scala/firrtl/passes/ExpandWhens.scala
index 959e824a..519a1e1a 100644
--- a/src/main/scala/firrtl/passes/ExpandWhens.scala
+++ b/src/main/scala/firrtl/passes/ExpandWhens.scala
@@ -169,7 +169,7 @@ object ExpandWhens extends Pass {
}
Block(Seq(conseqStmt, altStmt) ++ memos)
case block: Block => block map expandWhens(netlist, defaults, p)
- case _ => throwInternalError
+ case _ => throwInternalError()
}
val netlist = new Netlist
// Add ports to netlist
diff --git a/src/main/scala/firrtl/passes/InferWidths.scala b/src/main/scala/firrtl/passes/InferWidths.scala
index 11b819ce..aacd3656 100644
--- a/src/main/scala/firrtl/passes/InferWidths.scala
+++ b/src/main/scala/firrtl/passes/InferWidths.scala
@@ -333,7 +333,7 @@ object InferWidths extends Pass {
case wx: MinusWidth => map2(solve(wx.arg1), solve(wx.arg2), {_ - _})
case wx: ExpWidth => map2(Some(BigInt(2)), solve(wx.arg1), pow_minus_one)
case wx: IntWidth => Some(wx.width)
- case wx => println(wx); error("Shouldn't be here"); None;
+ case wx => throwInternalError(Some(s"solve: shouldn't be here - %$wx")); None;
}
solve(w) match {
diff --git a/src/main/scala/firrtl/passes/RemoveAccesses.scala b/src/main/scala/firrtl/passes/RemoveAccesses.scala
index 37b92a9e..9b19b221 100644
--- a/src/main/scala/firrtl/passes/RemoveAccesses.scala
+++ b/src/main/scala/firrtl/passes/RemoveAccesses.scala
@@ -95,7 +95,7 @@ object RemoveAccesses extends Pass {
case (_:WSubAccess| _: WSubField| _: WSubIndex| _: WRef) if hasAccess(e) =>
val rs = getLocations(e)
rs find (x => x.guard != one) match {
- case None => error("Shouldn't be here")
+ case None => throwInternalError(Some(s"removeMale: shouldn't be here - $e"))
case Some(_) =>
val (wire, temp) = create_temp(e)
val temps = create_exps(temp)
diff --git a/src/main/scala/firrtl/passes/RemoveValidIf.scala b/src/main/scala/firrtl/passes/RemoveValidIf.scala
index 68d16c30..7d714be7 100644
--- a/src/main/scala/firrtl/passes/RemoveValidIf.scala
+++ b/src/main/scala/firrtl/passes/RemoveValidIf.scala
@@ -24,7 +24,7 @@ object RemoveValidIf extends Pass {
case _: UIntType => UIntZero
case _: SIntType => SIntZero
case ClockType => ClockZero
- case other => throwInternalError
+ case other => throwInternalError()
}
// Recursive. Replaces IsInvalid with connecting zero
diff --git a/src/main/scala/firrtl/passes/Resolves.scala b/src/main/scala/firrtl/passes/Resolves.scala
index c8ba43bf..b601c81e 100644
--- a/src/main/scala/firrtl/passes/Resolves.scala
+++ b/src/main/scala/firrtl/passes/Resolves.scala
@@ -5,6 +5,7 @@ package firrtl.passes
import firrtl._
import firrtl.ir._
import firrtl.Mappers._
+import Utils.throwInternalError
object ResolveKinds extends Pass {
type KindMap = collection.mutable.LinkedHashMap[String, Kind]
@@ -84,19 +85,19 @@ object CInferMDir extends Pass {
mports get e.name match {
case None =>
case Some(p) => mports(e.name) = (p, dir) match {
- case (MInfer, MInfer) => Utils.error("Shouldn't be here")
+ case (MInfer, MInfer) => throwInternalError(Some(s"infer_mdir_e: shouldn't be here - $p, $dir"))
case (MInfer, MWrite) => MWrite
case (MInfer, MRead) => MRead
case (MInfer, MReadWrite) => MReadWrite
- case (MWrite, MInfer) => Utils.error("Shouldn't be here")
+ case (MWrite, MInfer) => throwInternalError(Some(s"infer_mdir_e: shouldn't be here - $p, $dir"))
case (MWrite, MWrite) => MWrite
case (MWrite, MRead) => MReadWrite
case (MWrite, MReadWrite) => MReadWrite
- case (MRead, MInfer) => Utils.error("Shouldn't be here")
+ case (MRead, MInfer) => throwInternalError(Some(s"infer_mdir_e: shouldn't be here - $p, $dir"))
case (MRead, MWrite) => MReadWrite
case (MRead, MRead) => MRead
case (MRead, MReadWrite) => MReadWrite
- case (MReadWrite, MInfer) => Utils.error("Shouldn't be here")
+ case (MReadWrite, MInfer) => throwInternalError(Some(s"infer_mdir_e: shouldn't be here - $p, $dir"))
case (MReadWrite, MWrite) => MReadWrite
case (MReadWrite, MRead) => MReadWrite
case (MReadWrite, MReadWrite) => MReadWrite
diff --git a/src/main/scala/firrtl/passes/Uniquify.scala b/src/main/scala/firrtl/passes/Uniquify.scala
index 54b94939..661dbf4e 100644
--- a/src/main/scala/firrtl/passes/Uniquify.scala
+++ b/src/main/scala/firrtl/passes/Uniquify.scala
@@ -109,7 +109,7 @@ object Uniquify extends Transform {
}
recUniquifyNames(t, namespace) match {
case tx: BundleType => tx
- case tx => error("Shouldn't be here")
+ case tx => throwInternalError(Some(s"uniquifyNames: shouldn't be here - $tx"))
}
}
diff --git a/src/main/scala/firrtl/passes/clocklist/ClockList.scala b/src/main/scala/firrtl/passes/clocklist/ClockList.scala
index 073eb050..be4d99fc 100644
--- a/src/main/scala/firrtl/passes/clocklist/ClockList.scala
+++ b/src/main/scala/firrtl/passes/clocklist/ClockList.scala
@@ -44,7 +44,7 @@ class ClockList(top: String, writer: Writer) extends Pass {
val modulesToInline = (c.modules.collect { case Module(_, n, _, _) if n != top => ModuleName(n, CircuitName(c.main)) }).toSet
val inlineTransform = new InlineInstances
val inlinedCircuit = inlineTransform.run(onlyClockCircuit, modulesToInline, Set(), None).circuit
- val topModule = inlinedCircuit.modules.find(_.name == top).getOrElse(throwInternalError)
+ val topModule = inlinedCircuit.modules.find(_.name == top).getOrElse(throwInternalError(Some("no top module")))
// Build a hashmap of connections to use for getOrigins
val connects = getConnects(topModule)
diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala
index b18ed289..bf0612ac 100644
--- a/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala
+++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemMacros.scala
@@ -224,7 +224,7 @@ class ReplaceMemMacros(writer: ConfWriter) extends Transform {
val pins = getMyAnnotations(state) match {
case Nil => Nil
case Seq(PinAnnotation(CircuitName(c), pins)) => pins
- case _ => throwInternalError
+ case _ => throwInternalError(Some(s"execute: getMyAnnotations - ${getMyAnnotations(state)}"))
}
val annos = (pins.foldLeft(Seq[Annotation]()) { (seq, pin) =>
seq ++ memMods.collect {
diff --git a/src/main/scala/firrtl/passes/memlib/YamlUtils.scala b/src/main/scala/firrtl/passes/memlib/YamlUtils.scala
index 4cc28e42..3e0c6a44 100644
--- a/src/main/scala/firrtl/passes/memlib/YamlUtils.scala
+++ b/src/main/scala/firrtl/passes/memlib/YamlUtils.scala
@@ -31,7 +31,7 @@ class YamlFileReader(file: String) {
catch { case e: Exception => None }
)
}
- else error("Yaml file doesn't exist!")
+ else sys.error("Yaml file doesn't exist!")
}
}
diff --git a/src/main/scala/firrtl/transforms/CheckCombLoops.scala b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
index bb2ffea9..98d6c3d1 100644
--- a/src/main/scala/firrtl/transforms/CheckCombLoops.scala
+++ b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
@@ -71,9 +71,9 @@ class CheckCombLoops extends Transform {
memport.expr match {
case memref: WRef =>
LogicNode(s.name,Some(memref.name),Some(memport.name))
- case _ => throwInternalError
+ case _ => throwInternalError(Some(s"toLogicNode: unrecognized subsubfield expression - $memport"))
}
- case _ => throwInternalError
+ case _ => throwInternalError(Some(s"toLogicNode: unrecognized subfield expression - $s"))
}
}
diff --git a/src/main/scala/firrtl/transforms/ConstantPropagation.scala b/src/main/scala/firrtl/transforms/ConstantPropagation.scala
index d08a7e6b..086f1cee 100644
--- a/src/main/scala/firrtl/transforms/ConstantPropagation.scala
+++ b/src/main/scala/firrtl/transforms/ConstantPropagation.scala
@@ -320,7 +320,7 @@ class ConstantPropagation extends Transform {
case node: DefNode => node.copy(name = newName)
case wire: DefWire => wire.copy(name = newName)
case reg: DefRegister => reg.copy(name = newName)
- case other => throwInternalError
+ case other => throwInternalError()
}
case other => other map backPropStmt
}
diff --git a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
index 22e7da6e..054705c0 100644
--- a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
+++ b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
@@ -63,7 +63,7 @@ class DeadCodeElimination extends Transform {
case ref @ (_: WRef | _: WSubField) => refs += ref
case nested @ (_: Mux | _: DoPrim | _: ValidIf) => nested map rec
case ignore @ (_: Literal) => // Do nothing
- case unexpected => throwInternalError
+ case unexpected => throwInternalError()
}
e
}
@@ -136,7 +136,7 @@ class DeadCodeElimination extends Transform {
// Add all ports as vertices
mod.ports.foreach {
case Port(_, name, _, _: GroundType) => depGraph.addVertex(LogicNode(mod.name, name))
- case other => throwInternalError
+ case other => throwInternalError()
}
onStmt(mod.body)
}
@@ -261,7 +261,7 @@ class DeadCodeElimination extends Transform {
None
}
else {
- if (ext.ports != portsx) throwInternalError // Sanity check
+ if (ext.ports != portsx) throwInternalError() // Sanity check
Some(ext.copy(ports = portsx))
}
}
diff --git a/src/main/scala/firrtl/transforms/RemoveWires.scala b/src/main/scala/firrtl/transforms/RemoveWires.scala
index a1fb32db..931288d9 100644
--- a/src/main/scala/firrtl/transforms/RemoveWires.scala
+++ b/src/main/scala/firrtl/transforms/RemoveWires.scala
@@ -99,7 +99,7 @@ class RemoveWires extends Transform {
otherStmts += other
case EmptyStmt => // Dont bother keeping EmptyStmts around
case block: Block => block map onStmt
- case _ => throwInternalError
+ case _ => throwInternalError()
}
stmt
}
diff --git a/src/test/scala/firrtlTests/InternalErrorSpec.scala b/src/test/scala/firrtlTests/InternalErrorSpec.scala
new file mode 100644
index 00000000..85c9c67d
--- /dev/null
+++ b/src/test/scala/firrtlTests/InternalErrorSpec.scala
@@ -0,0 +1,46 @@
+// See LICENSE for license details.
+
+package firrtlTests
+
+import java.io.File
+
+import firrtl._
+import firrtl.Utils.getThrowable
+import firrtl.util.BackendCompilationUtilities
+import org.scalatest.{FreeSpec, Matchers}
+
+
+class InternalErrorSpec extends FreeSpec with Matchers with BackendCompilationUtilities {
+ "Unexpected exceptions" - {
+ val input =
+ """
+ |circuit Dummy :
+ | module Dummy :
+ | input clock : Clock
+ | input x : UInt<1>
+ | output y : UInt<1>
+ | output io : { flip in : UInt<16>, out : UInt<16> }
+ | y <= shr(x, UInt(1)); this should generate an exception in PrimOps.scala:127.
+ | """.stripMargin
+
+ var exception: Exception = null
+ "should throw a FIRRTLException" in {
+ val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = "Dummy")
+ firrtlOptions = FirrtlExecutionOptions(firrtlSource = Some(input), compilerName = "low")
+ }
+ exception = intercept[FIRRTLException] {
+ firrtl.Driver.execute(manager)
+ }
+ }
+
+ "should contain the expected string" in {
+ assert(exception.getMessage.contains("Internal Error! Please file an issue"))
+ }
+
+ "should contain the name of the file originating the exception in the stack trace" in {
+ val first = true
+ assert(getThrowable(Some(exception), first).getStackTrace exists (_.getFileName.contains("PrimOps.scala")))
+ }
+ }
+}