diff options
| author | Jack Koenig | 2019-08-13 12:09:27 +0530 |
|---|---|---|
| committer | GitHub | 2019-08-13 12:09:27 +0530 |
| commit | f08f8dbb3c480220f92923a7f3242fcbb644b65e (patch) | |
| tree | 45cdb7543f6252ad2feb5aaf4e0e0580d3d27565 /src/main/scala/firrtl/checks | |
| parent | 63e88b6e1696e2c8d6da91f6f5eb128a9d0395ae (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.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 + } +} + |
