aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/checks
diff options
context:
space:
mode:
authorJack Koenig2019-08-13 12:09:27 +0530
committerGitHub2019-08-13 12:09:27 +0530
commitf08f8dbb3c480220f92923a7f3242fcbb644b65e (patch)
tree45cdb7543f6252ad2feb5aaf4e0e0580d3d27565 /src/main/scala/firrtl/checks
parent63e88b6e1696e2c8d6da91f6f5eb128a9d0395ae (diff)
Infer reset (#1068)
* Add abstract "Reset" which can be inferred to AsyncReset or UInt<1> * Enhance async reset initial value literal check to support aggregates
Diffstat (limited to 'src/main/scala/firrtl/checks')
-rw-r--r--src/main/scala/firrtl/checks/CheckResets.scala75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/checks/CheckResets.scala b/src/main/scala/firrtl/checks/CheckResets.scala
new file mode 100644
index 00000000..d6337f9e
--- /dev/null
+++ b/src/main/scala/firrtl/checks/CheckResets.scala
@@ -0,0 +1,75 @@
+// See LICENSE for license details.
+
+package firrtl.checks
+
+import firrtl._
+import firrtl.passes.{Errors, PassException}
+import firrtl.ir._
+import firrtl.traversals.Foreachers._
+import firrtl.WrappedExpression._
+
+import scala.collection.mutable
+
+object CheckResets {
+ class NonLiteralAsyncResetValueException(info: Info, mname: String, reg: String, init: String) extends PassException(
+ s"$info: [module $mname] AsyncReset Reg '$reg' reset to non-literal '$init'")
+
+ // Map of Initialization Expression to check
+ private type RegCheckList = mutable.ListBuffer[(Expression, DefRegister)]
+ // Record driving for literal propagation
+ // Indicates *driven by*
+ private type DirectDriverMap = mutable.HashMap[WrappedExpression, Expression]
+
+}
+
+// Must run after ExpandWhens
+// Requires
+// - static single connections of ground types
+class CheckResets extends Transform {
+ def inputForm: CircuitForm = MidForm
+ def outputForm: CircuitForm = MidForm
+
+ import CheckResets._
+
+ private def onStmt(regCheck: RegCheckList, drivers: DirectDriverMap)(stmt: Statement): Unit = {
+ stmt match {
+ case DefNode(_, name, expr) => drivers += we(WRef(name)) -> expr
+ case Connect(_, lhs, rhs) => drivers += we(lhs) -> rhs
+ case reg @ DefRegister(_,_,_,_, reset, init) if reset.tpe == AsyncResetType =>
+ regCheck += init -> reg
+ case _ => // Do nothing
+ }
+ stmt.foreach(onStmt(regCheck, drivers))
+ }
+
+ private def findDriver(drivers: DirectDriverMap)(expr: Expression): Expression =
+ drivers.get(we(expr)) match {
+ case Some(lit: Literal) => lit
+ case Some(other) => findDriver(drivers)(other)
+ case None => expr
+ }
+
+ private def onMod(errors: Errors)(mod: DefModule): Unit = {
+ val regCheck = new RegCheckList()
+ val drivers = new DirectDriverMap()
+ mod.foreach(onStmt(regCheck, drivers))
+ for ((init, reg) <- regCheck) {
+ for (subInit <- Utils.create_exps(init)) {
+ findDriver(drivers)(subInit) match {
+ case lit: Literal => // All good
+ case other =>
+ val e = new NonLiteralAsyncResetValueException(reg.info, mod.name, reg.name, other.serialize)
+ errors.append(e)
+ }
+ }
+ }
+ }
+
+ def execute(state: CircuitState): CircuitState = {
+ val errors = new Errors
+ state.circuit.foreach(onMod(errors))
+ errors.trigger()
+ state
+ }
+}
+