diff options
Diffstat (limited to 'src/main/scala/firrtl/checks')
| -rw-r--r-- | src/main/scala/firrtl/checks/CheckResets.scala | 75 |
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 + } +} + |
