aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorazidar2016-05-24 10:17:51 -0700
committerjackkoenig2016-05-24 10:42:18 -0700
commitf9e8895b73aeec9bb71449f8e3d0e6f7e7a0a478 (patch)
tree1b9384689555f4625ad7c24279a35b74071707ad
parent243ff24f8eb9aae18bb0c7afe4f4c1e6cd66c084 (diff)
Added Errors class and fixed tests.
Canonicalizes catching/throwing PassExceptions.
-rw-r--r--src/main/scala/firrtl/passes/Checks.scala86
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala11
-rw-r--r--src/test/scala/firrtlTests/CheckSpec.scala2
-rw-r--r--src/test/scala/firrtlTests/UnitTests.scala5
4 files changed, 57 insertions, 47 deletions
diff --git a/src/main/scala/firrtl/passes/Checks.scala b/src/main/scala/firrtl/passes/Checks.scala
index b68b7431..083a18fd 100644
--- a/src/main/scala/firrtl/passes/Checks.scala
+++ b/src/main/scala/firrtl/passes/Checks.scala
@@ -116,7 +116,7 @@ object CheckHighForm extends Pass with LazyLogging {
private var mname: String = ""
private var sinfo: Info = NoInfo
def run (c:Circuit): Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def checkHighFormPrimop(e: DoPrim) = {
def correctNum(ne: Option[Int], nc: Int) = {
ne match {
@@ -289,7 +289,7 @@ object CheckHighForm extends Pass with LazyLogging {
}
sinfo = c.info
if (numTopM != 1) errors.append(new NoTopModuleException(c.main))
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
@@ -326,32 +326,32 @@ object CheckTypes extends Pass with LazyLogging {
def ut () : UIntType = UIntType(UnknownWidth())
def st () : SIntType = SIntType(UnknownWidth())
- def check_types_primop (e:DoPrim, errors:ArrayBuffer[PassException],info:Info) : Unit = {
+ def check_types_primop (e:DoPrim, errors:Errors, info:Info) : Unit = {
def all_same_type (ls:Seq[Expression]) : Unit = {
var error = false
for (x <- ls) {
if (wt(tpe(ls.head)) != wt(tpe(x))) error = true
}
- if (error) errors += new OpNotAllSameType(info,e.op.serialize)
+ if (error) errors.append(new OpNotAllSameType(info,e.op.serialize))
}
def all_ground (ls:Seq[Expression]) : Unit = {
var error = false
for (x <- ls ) {
if (!(tpe(x).typeof[UIntType] || tpe(x).typeof[SIntType])) error = true
}
- if (error) errors += new OpNotGround(info,e.op.serialize)
+ if (error) errors.append(new OpNotGround(info,e.op.serialize))
}
def all_uint (ls:Seq[Expression]) : Unit = {
var error = false
for (x <- ls ) {
if (!(tpe(x).typeof[UIntType])) error = true
}
- if (error) errors += new OpNotAllUInt(info,e.op.serialize)
+ if (error) errors.append(new OpNotAllUInt(info,e.op.serialize))
}
def is_uint (x:Expression) : Unit = {
var error = false
if (!(tpe(x).typeof[UIntType])) error = true
- if (error) errors += new OpNotUInt(info,e.op.serialize,x.serialize)
+ if (error) errors.append(new OpNotUInt(info,e.op.serialize,x.serialize))
}
e.op match {
@@ -391,7 +391,7 @@ object CheckTypes extends Pass with LazyLogging {
}
def run (c:Circuit) : Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def passive (t:Type) : Boolean = {
(t) match {
case (_:UIntType|_:SIntType) => true
@@ -414,39 +414,39 @@ object CheckTypes extends Pass with LazyLogging {
(tpe(e.exp)) match {
case (t:BundleType) => {
val ft = t.fields.find(p => p.name == e.name)
- if (ft == None) errors += new SubfieldNotInBundle(info,e.name)
+ if (ft == None) errors.append(new SubfieldNotInBundle(info,e.name))
}
- case (t) => errors += new SubfieldOnNonBundle(info,e.name)
+ case (t) => errors.append(new SubfieldOnNonBundle(info,e.name))
}
}
case (e:WSubIndex) => {
(tpe(e.exp)) match {
case (t:VectorType) => {
- if (e.value >= t.size) errors += new IndexTooLarge(info,e.value)
+ if (e.value >= t.size) errors.append(new IndexTooLarge(info,e.value))
}
- case (t) => errors += new IndexOnNonVector(info)
+ case (t) => errors.append(new IndexOnNonVector(info))
}
}
case (e:WSubAccess) => {
(tpe(e.exp)) match {
case (t:VectorType) => false
- case (t) => errors += new IndexOnNonVector(info)
+ case (t) => errors.append(new IndexOnNonVector(info))
}
(tpe(e.index)) match {
case (t:UIntType) => false
- case (t) => errors += new AccessIndexNotUInt(info)
+ case (t) => errors.append(new AccessIndexNotUInt(info))
}
}
case (e:DoPrim) => check_types_primop(e,errors,info)
case (e:Mux) => {
- if (wt(tpe(e.tval)) != wt(tpe(e.fval))) errors += new MuxSameType(info)
- if (!passive(tpe(e))) errors += new MuxPassiveTypes(info)
- if (!passive(tpe(e))) errors += new MuxPassiveTypes(info)
- if (!(tpe(e.cond).typeof[UIntType])) errors += new MuxCondUInt(info)
+ if (wt(tpe(e.tval)) != wt(tpe(e.fval))) errors.append(new MuxSameType(info))
+ if (!passive(tpe(e))) errors.append(new MuxPassiveTypes(info))
+ if (!passive(tpe(e))) errors.append(new MuxPassiveTypes(info))
+ if (!(tpe(e.cond).typeof[UIntType])) errors.append(new MuxCondUInt(info))
}
case (e:ValidIf) => {
- if (!passive(tpe(e))) errors += new ValidIfPassiveTypes(info)
- if (!(tpe(e.cond).typeof[UIntType])) errors += new ValidIfCondUInt(info)
+ if (!passive(tpe(e))) errors.append(new ValidIfPassiveTypes(info))
+ if (!(tpe(e.cond).typeof[UIntType])) errors.append(new ValidIfCondUInt(info))
}
case (_:UIntValue|_:SIntValue) => false
}
@@ -479,22 +479,22 @@ object CheckTypes extends Pass with LazyLogging {
def check_types_s (s:Stmt) : Stmt = {
s map (check_types_e(get_info(s))) match {
- case (s:Connect) => if (wt(tpe(s.loc)) != wt(tpe(s.exp))) errors += new InvalidConnect(s.info, s.loc.serialize, s.exp.serialize)
- case (s:DefRegister) => if (wt(s.tpe) != wt(tpe(s.init))) errors += new InvalidRegInit(s.info)
- case (s:BulkConnect) => if (!bulk_equals(tpe(s.loc),tpe(s.exp),DEFAULT,DEFAULT) ) errors += new InvalidConnect(s.info, s.loc.serialize, s.exp.serialize)
+ case (s:Connect) => if (wt(tpe(s.loc)) != wt(tpe(s.exp))) errors.append(new InvalidConnect(s.info, s.loc.serialize, s.exp.serialize))
+ case (s:DefRegister) => if (wt(s.tpe) != wt(tpe(s.init))) errors.append(new InvalidRegInit(s.info))
+ case (s:BulkConnect) => if (!bulk_equals(tpe(s.loc),tpe(s.exp),DEFAULT,DEFAULT) ) errors.append(new InvalidConnect(s.info, s.loc.serialize, s.exp.serialize))
case (s:Stop) => {
- if (wt(tpe(s.clk)) != wt(ClockType()) ) errors += new ReqClk(s.info)
- if (wt(tpe(s.en)) != wt(ut()) ) errors += new EnNotUInt(s.info)
+ if (wt(tpe(s.clk)) != wt(ClockType()) ) errors.append(new ReqClk(s.info))
+ if (wt(tpe(s.en)) != wt(ut()) ) errors.append(new EnNotUInt(s.info))
}
case (s:Print)=> {
for (x <- s.args ) {
- if (wt(tpe(x)) != wt(ut()) && wt(tpe(x)) != wt(st()) ) errors += new PrintfArgNotGround(s.info)
+ if (wt(tpe(x)) != wt(ut()) && wt(tpe(x)) != wt(st()) ) errors.append(new PrintfArgNotGround(s.info))
}
- if (wt(tpe(s.clk)) != wt(ClockType()) ) errors += new ReqClk(s.info)
- if (wt(tpe(s.en)) != wt(ut()) ) errors += new EnNotUInt(s.info)
+ if (wt(tpe(s.clk)) != wt(ClockType()) ) errors.append(new ReqClk(s.info))
+ if (wt(tpe(s.en)) != wt(ut()) ) errors.append(new EnNotUInt(s.info))
}
- case (s:Conditionally) => if (wt(tpe(s.pred)) != wt(ut()) ) errors += new PredNotUInt(s.info)
- case (s:DefNode) => if (!passive(tpe(s.value)) ) errors += new NodePassiveType(s.info)
+ case (s:Conditionally) => if (wt(tpe(s.pred)) != wt(ut()) ) errors.append(new PredNotUInt(s.info))
+ case (s:DefNode) => if (!passive(tpe(s.value)) ) errors.append(new NodePassiveType(s.info))
case (s) => false
}
s map (check_types_s)
@@ -507,7 +507,7 @@ object CheckTypes extends Pass with LazyLogging {
case (m:InModule) => check_types_s(m.body)
}
}
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
@@ -534,7 +534,7 @@ object CheckGenders extends Pass {
}
def run (c:Circuit): Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def get_kind (e:Expression) : Kind = {
(e) match {
case (e:WRef) => e.kind
@@ -574,14 +574,14 @@ object CheckGenders extends Pass {
//println(desired == gender)
//if gender != desired and gender != BI-GENDER:
(gender,desired) match {
- case (MALE, FEMALE) => errors += new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender))
+ case (MALE, FEMALE) => errors.append(new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender)))
case (FEMALE, MALE) =>
if ((kindx == PortKind() || kindx == InstanceKind()) && has_flipQ == false) {
//; OK!
false
} else {
//; Not Ok!
- errors += new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender))
+ errors.append(new WrongGender(info,e.serialize,as_srcsnk(desired),as_srcsnk(gender)))
}
case _ => false
}
@@ -672,7 +672,7 @@ object CheckGenders extends Pass {
case (m:InModule) => check_genders_s(genders)(m.body)
}
}
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
@@ -684,12 +684,12 @@ object CheckWidths extends Pass {
class WidthTooSmall (info:Info,v:String) extends PassException(s"${info} : [module ${mname} Width too small for constant ${v}.")
class NegWidthException(info:Info) extends PassException(s"${info}: [module ${mname}] Width cannot be negative or zero.")
def run (c:Circuit): Circuit = {
- val errors = ArrayBuffer[PassException]()
+ val errors = new Errors()
def check_width_m (m:Module) : Unit = {
def check_width_w (info:Info)(w:Width) : Width = {
(w) match {
- case (w:IntWidth)=> if (w.width <= 0) errors += new NegWidthException(info)
- case (w) => errors += new UninferredWidth(info)
+ case (w:IntWidth)=> if (w.width <= 0) errors.append(new NegWidthException(info))
+ case (w) => errors.append(new UninferredWidth(info))
}
w
}
@@ -699,17 +699,17 @@ object CheckWidths extends Pass {
(e.width) match {
case (w:IntWidth) =>
if (scala.math.max(1,e.value.bitLength) > w.width) {
- errors += new WidthTooSmall(info, serialize(e.value))
+ errors.append(new WidthTooSmall(info, serialize(e.value)))
}
- case (w) => errors += new UninferredWidth(info)
+ case (w) => errors.append(new UninferredWidth(info))
}
check_width_w(info)(e.width)
}
case (e:SIntValue) => {
(e.width) match {
case (w:IntWidth) =>
- if (e.value.bitLength + 1 > w.width) errors += new WidthTooSmall(info, serialize(e.value))
- case (w) => errors += new UninferredWidth(info)
+ if (e.value.bitLength + 1 > w.width) errors.append(new WidthTooSmall(info, serialize(e.value)))
+ case (w) => errors.append(new UninferredWidth(info))
}
check_width_w(info)(e.width)
}
@@ -738,7 +738,7 @@ object CheckWidths extends Pass {
mname = m.name
check_width_m(m)
}
- if (errors.nonEmpty) throw new PassExceptions(errors)
+ errors.trigger
c
}
}
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
index bc11bc9d..c0d5327f 100644
--- a/src/main/scala/firrtl/passes/Passes.scala
+++ b/src/main/scala/firrtl/passes/Passes.scala
@@ -50,6 +50,17 @@ trait Pass extends LazyLogging {
// Error handling
class PassException(message: String) extends Exception(message)
class PassExceptions(exceptions: Seq[PassException]) extends Exception("\n" + exceptions.mkString("\n"))
+class Errors {
+ val errors = ArrayBuffer[PassException]()
+ def append(pe: PassException) = errors.append(pe)
+ def trigger = errors.size match {
+ case 0 =>
+ case 1 => throw errors.head
+ case _ =>
+ append(new PassException(s"${errors.length} errors detected!"))
+ throw new PassExceptions(errors)
+ }
+}
// These should be distributed into separate files
object ToWorkingIR extends Pass {
diff --git a/src/test/scala/firrtlTests/CheckSpec.scala b/src/test/scala/firrtlTests/CheckSpec.scala
index ea0767bb..5c1b1a67 100644
--- a/src/test/scala/firrtlTests/CheckSpec.scala
+++ b/src/test/scala/firrtlTests/CheckSpec.scala
@@ -19,7 +19,7 @@ class CheckSpec extends FlatSpec with Matchers {
| depth => 32
| read-latency => 0
| write-latency => 1""".stripMargin
- intercept[PassExceptions] {
+ intercept[CheckHighForm.MemWithFlipException] {
passes.foldLeft(Parser.parse(input.split("\n").toIterator)) {
(c: Circuit, p: Pass) => p.run(c)
}
diff --git a/src/test/scala/firrtlTests/UnitTests.scala b/src/test/scala/firrtlTests/UnitTests.scala
index dac8a40f..98693c61 100644
--- a/src/test/scala/firrtlTests/UnitTests.scala
+++ b/src/test/scala/firrtlTests/UnitTests.scala
@@ -60,12 +60,11 @@ class UnitTests extends FirrtlFlatSpec {
| input y: {a : UInt<1>}
| output x: {a : UInt<1>, b : UInt<1>}
| x <= y""".stripMargin
- val thrown = intercept[PassExceptions] {
+ intercept[CheckTypes.InvalidConnect] {
passes.foldLeft(parse(input)) {
(c: Circuit, p: Pass) => p.run(c)
}
}
- assert(thrown.getMessage contains "Type mismatch. Cannot connect")
}
"Initializing a register with a different type" should "throw an exception" in {
@@ -83,7 +82,7 @@ class UnitTests extends FirrtlFlatSpec {
| wire x : { valid : UInt<1> }
| reg y : { valid : UInt<1>, bits : UInt<3> }, clk with :
| reset => (reset, x)""".stripMargin
- intercept[PassExceptions] {
+ intercept[CheckTypes.InvalidRegInit] {
passes.foldLeft(parse(input)) {
(c: Circuit, p: Pass) => p.run(c)
}