aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorSchuyler Eldridge2018-11-05 16:54:42 -0500
committerGitHub2018-11-05 16:54:42 -0500
commitd04af59c233cec994087df3d0d3fff14e20ac04c (patch)
tree0b7ae45a3901986a40bf06abad24adf3ea6fe15d /src/main
parent3935914116d7289a8b545cc8d758785d9f8dcd13 (diff)
parent2fdc984223393ee4996f7f7fde8d6b12c9fe36c3 (diff)
Merge pull request #932 from seldridge/f269
- Add Target.prettyPrint method - Improve UninferredWidth exception message
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/firrtl/annotations/Target.scala26
-rw-r--r--src/main/scala/firrtl/passes/CheckWidths.scala75
2 files changed, 69 insertions, 32 deletions
diff --git a/src/main/scala/firrtl/annotations/Target.scala b/src/main/scala/firrtl/annotations/Target.scala
index dcf5cb02..8a9d68e8 100644
--- a/src/main/scala/firrtl/annotations/Target.scala
+++ b/src/main/scala/firrtl/annotations/Target.scala
@@ -55,6 +55,32 @@ sealed trait Target extends Named {
}
}
+ /** Pretty serialization, ideal for error messages. Cannot be deserialized.
+ * @return Human-readable serialization
+ */
+ def prettyPrint(tab: String = ""): String = {
+ val circuitString = s"""${tab}circuit ${circuitOpt.getOrElse("???")}:"""
+ val moduleString = s"""\n$tab└── module ${moduleOpt.getOrElse("???")}:"""
+ var depth = 4
+ val tokenString = tokens.map {
+ case Ref(r) => val rx = s"""\n$tab${" "*depth}└── $r"""; depth += 4; rx
+ case Instance(i) => val ix = s"""\n$tab${" "*depth}└── inst $i """; ix
+ case OfModule(o) => val ox = s"of $o:"; depth += 4; ox
+ case Field(f) => s".$f"
+ case Index(v) => s"[$v]"
+ case Clock => s"@clock"
+ case Reset => s"@reset"
+ case Init => s"@init"
+ }.mkString("")
+
+ (moduleOpt.isEmpty, tokens.isEmpty) match {
+ case (true, true) => circuitString
+ case (_, true) => circuitString + moduleString
+ case (_, _) => circuitString + moduleString + tokenString
+ }
+ }
+
+
/** @return Converts this [[Target]] into a [[GenericTarget]] */
def toGenericTarget: GenericTarget = GenericTarget(circuitOpt, moduleOpt, tokens.toVector)
diff --git a/src/main/scala/firrtl/passes/CheckWidths.scala b/src/main/scala/firrtl/passes/CheckWidths.scala
index 7827c55e..4a72b18c 100644
--- a/src/main/scala/firrtl/passes/CheckWidths.scala
+++ b/src/main/scala/firrtl/passes/CheckWidths.scala
@@ -7,42 +7,44 @@ import firrtl.ir._
import firrtl.PrimOps._
import firrtl.Mappers._
import firrtl.Utils._
+import firrtl.annotations.{Target, TargetToken, CircuitTarget, ModuleTarget}
object CheckWidths extends Pass {
/** The maximum allowed width for any circuit element */
val MaxWidth = 1000000
val DshlMaxWidth = ceilLog2(MaxWidth + 1)
- class UninferredWidth (info: Info, mname: String) extends PassException(
- s"$info : [module $mname] Uninferred width.")
+ class UninferredWidth (info: Info, target: String) extends PassException(
+ s"""|$info : Uninferred width for target below. (Did you forget to assign to it?)
+ |$target""".stripMargin)
class WidthTooSmall(info: Info, mname: String, b: BigInt) extends PassException(
- s"$info : [module $mname] Width too small for constant $b.")
+ s"$info : [target $mname] Width too small for constant $b.")
class WidthTooBig(info: Info, mname: String, b: BigInt) extends PassException(
- s"$info : [module $mname] Width $b greater than max allowed width of $MaxWidth bits")
+ s"$info : [target $mname] Width $b greater than max allowed width of $MaxWidth bits")
class DshlTooBig(info: Info, mname: String) extends PassException(
- s"$info : [module $mname] Width of dshl shift amount cannot be larger than $DshlMaxWidth bits.")
+ s"$info : [target $mname] Width of dshl shift amount cannot be larger than $DshlMaxWidth bits.")
class NegWidthException(info:Info, mname: String) extends PassException(
- s"$info: [module $mname] Width cannot be negative or zero.")
+ s"$info: [target $mname] Width cannot be negative or zero.")
class BitsWidthException(info: Info, mname: String, hi: BigInt, width: BigInt, exp: String) extends PassException(
- s"$info: [module $mname] High bit $hi in bits operator is larger than input width $width in $exp.")
+ s"$info: [target $mname] High bit $hi in bits operator is larger than input width $width in $exp.")
class HeadWidthException(info: Info, mname: String, n: BigInt, width: BigInt) extends PassException(
- s"$info: [module $mname] Parameter $n in head operator is larger than input width $width.")
+ s"$info: [target $mname] Parameter $n in head operator is larger than input width $width.")
class TailWidthException(info: Info, mname: String, n: BigInt, width: BigInt) extends PassException(
- s"$info: [module $mname] Parameter $n in tail operator is larger than input width $width.")
+ s"$info: [target $mname] Parameter $n in tail operator is larger than input width $width.")
class AttachWidthsNotEqual(info: Info, mname: String, eName: String, source: String) extends PassException(
- s"$info: [module $mname] Attach source $source and expression $eName must have identical widths.")
+ s"$info: [target $mname] Attach source $source and expression $eName must have identical widths.")
def run(c: Circuit): Circuit = {
val errors = new Errors()
- def check_width_w(info: Info, mname: String)(w: Width): Width = {
+ def check_width_w(info: Info, target: Target)(w: Width): Width = {
w match {
case IntWidth(width) if width >= MaxWidth =>
- errors.append(new WidthTooBig(info, mname, width))
+ errors.append(new WidthTooBig(info, target.serialize, width))
case w: IntWidth if w.width >= 0 =>
case _: IntWidth =>
- errors append new NegWidthException(info, mname)
+ errors append new NegWidthException(info, target.serialize)
case _ =>
- errors append new UninferredWidth(info, mname)
+ errors append new UninferredWidth(info, target.prettyPrint(" "))
}
w
}
@@ -53,62 +55,71 @@ object CheckWidths extends Pass {
case _ => throwInternalError(s"hasWidth - $tpe")
}
- def check_width_t(info: Info, mname: String)(t: Type): Type =
- t map check_width_t(info, mname) map check_width_w(info, mname)
+ def check_width_t(info: Info, target: Target)(t: Type): Type = {
+ val tx = t match {
+ case tt: BundleType => BundleType(tt.fields.map(check_width_f(info, target)))
+ case tt => tt map check_width_t(info, target)
+ }
+ tx map check_width_w(info, target)
+ }
+
+ def check_width_f(info: Info, target: Target)(f: Field): Field = f
+ .copy(tpe = check_width_t(info, target.modify(tokens = target.tokens :+ TargetToken.Field(f.name)))(f.tpe))
- def check_width_e(info: Info, mname: String)(e: Expression): Expression = {
+ def check_width_e(info: Info, target: Target)(e: Expression): Expression = {
e match {
case e: UIntLiteral => e.width match {
case w: IntWidth if math.max(1, e.value.bitLength) > w.width =>
- errors append new WidthTooSmall(info, mname, e.value)
+ errors append new WidthTooSmall(info, target.serialize, e.value)
case _ =>
}
case e: SIntLiteral => e.width match {
case w: IntWidth if e.value.bitLength + 1 > w.width =>
- errors append new WidthTooSmall(info, mname, e.value)
+ errors append new WidthTooSmall(info, target.serialize, e.value)
case _ =>
}
case DoPrim(Bits, Seq(a), Seq(hi, lo), _) if (hasWidth(a.tpe) && bitWidth(a.tpe) <= hi) =>
- errors append new BitsWidthException(info, mname, hi, bitWidth(a.tpe), e.serialize)
+ errors append new BitsWidthException(info, target.serialize, hi, bitWidth(a.tpe), e.serialize)
case DoPrim(Head, Seq(a), Seq(n), _) if (hasWidth(a.tpe) && bitWidth(a.tpe) < n) =>
- errors append new HeadWidthException(info, mname, n, bitWidth(a.tpe))
+ errors append new HeadWidthException(info, target.serialize, n, bitWidth(a.tpe))
case DoPrim(Tail, Seq(a), Seq(n), _) if (hasWidth(a.tpe) && bitWidth(a.tpe) <= n) =>
- errors append new TailWidthException(info, mname, n, bitWidth(a.tpe))
+ errors append new TailWidthException(info, target.serialize, n, bitWidth(a.tpe))
case DoPrim(Dshl, Seq(a, b), _, _) if (hasWidth(a.tpe) && bitWidth(b.tpe) >= DshlMaxWidth) =>
- errors append new DshlTooBig(info, mname)
+ errors append new DshlTooBig(info, target.serialize)
case _ =>
}
//e map check_width_t(info, mname) map check_width_e(info, mname)
- e map check_width_e(info, mname)
+ e map check_width_e(info, target)
}
- def check_width_s(minfo: Info, mname: String)(s: Statement): Statement = {
+ def check_width_s(minfo: Info, target: ModuleTarget)(s: Statement): Statement = {
val info = get_info(s) match { case NoInfo => minfo case x => x }
- s map check_width_e(info, mname) map check_width_s(info, mname) map check_width_t(info, mname) match {
+ val subRef = s match { case sx: HasName => target.ref(sx.name) case _ => target }
+ s map check_width_e(info, target) map check_width_s(info, target) map check_width_t(info, subRef) match {
case Attach(infox, exprs) =>
exprs.tail.foreach ( e =>
if (bitWidth(e.tpe) != bitWidth(exprs.head.tpe))
- errors.append(new AttachWidthsNotEqual(infox, mname, e.serialize, exprs.head.serialize))
+ errors.append(new AttachWidthsNotEqual(infox, target.serialize, e.serialize, exprs.head.serialize))
)
s
case sx: DefRegister =>
sx.reset.tpe match {
case UIntType(IntWidth(w)) if w == 1 =>
- case _ => errors.append(new CheckTypes.IllegalResetType(info, mname, sx.name))
+ case _ => errors.append(new CheckTypes.IllegalResetType(info, target.serialize, sx.name))
}
s
case _ => s
}
}
- def check_width_p(minfo: Info, mname: String)(p: Port): Port = p.copy(tpe = check_width_t(p.info, mname)(p.tpe))
+ def check_width_p(minfo: Info, target: ModuleTarget)(p: Port): Port = p.copy(tpe = check_width_t(p.info, target)(p.tpe))
- def check_width_m(m: DefModule) {
- m map check_width_p(m.info, m.name) map check_width_s(m.info, m.name)
+ def check_width_m(circuit: CircuitTarget)(m: DefModule) {
+ m map check_width_p(m.info, circuit.module(m.name)) map check_width_s(m.info, circuit.module(m.name))
}
- c.modules foreach check_width_m
+ c.modules foreach check_width_m(CircuitTarget(c.main))
errors.trigger()
c
}