diff options
| author | Jack Koenig | 2020-04-14 11:17:38 -0700 |
|---|---|---|
| committer | GitHub | 2020-04-14 11:17:38 -0700 |
| commit | 0407a53bd76b41deed44dffbe08ca252536ab53c (patch) | |
| tree | 86907dad790ba234ea85cc30108af221313f57f6 /src | |
| parent | f8546a7c165e0bde4b3e5682dd6edd0a3e199b31 (diff) | |
| parent | 74ff30cf8dcfb7253458905b626dee89fc9b280c (diff) | |
Merge pull request #1525 from freechipsproject/async-self-init-supported
Prevent infinite recursion in CheckResets
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/checks/CheckResets.scala | 15 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/AsyncResetSpec.scala | 14 |
2 files changed, 23 insertions, 6 deletions
diff --git a/src/main/scala/firrtl/checks/CheckResets.scala b/src/main/scala/firrtl/checks/CheckResets.scala index facd5c01..4f7f7060 100644 --- a/src/main/scala/firrtl/checks/CheckResets.scala +++ b/src/main/scala/firrtl/checks/CheckResets.scala @@ -47,6 +47,7 @@ class CheckResets extends Transform with PreservesAll[Transform] { stmt match { case DefNode(_, name, expr) => drivers += we(WRef(name)) -> expr case Connect(_, lhs, rhs) => drivers += we(lhs) -> rhs + case reg @ DefRegister(_, name, _,_,_, init) if weq(WRef(name), init) => // Self-reset, allowed! case reg @ DefRegister(_,_,_,_, reset, init) if reset.tpe == AsyncResetType => regCheck += init -> reg case _ => // Do nothing @@ -54,14 +55,16 @@ class CheckResets extends Transform with PreservesAll[Transform] { stmt.foreach(onStmt(regCheck, drivers)) } + private def wireOrNode(kind: Kind) = (kind == WireKind || kind == NodeKind) + @tailrec private def findDriver(drivers: DirectDriverMap)(expr: Expression): Expression = expr match { - case lit: Literal => lit - case DoPrim(op, args, _,_) if isCast(op) => findDriver(drivers)(args.head) - case other => drivers.get(we(other)) match { - case Some(e) => findDriver(drivers)(e) - case None => other - } + case lit: Literal => lit + case DoPrim(op, args, _,_) if isCast(op) => findDriver(drivers)(args.head) + case other => drivers.get(we(other)) match { + case Some(e) if wireOrNode(Utils.kind(other)) => findDriver(drivers)(e) + case _ => other + } } private def onMod(errors: Errors)(mod: DefModule): Unit = { diff --git a/src/test/scala/firrtlTests/AsyncResetSpec.scala b/src/test/scala/firrtlTests/AsyncResetSpec.scala index 60eab883..34211946 100644 --- a/src/test/scala/firrtlTests/AsyncResetSpec.scala +++ b/src/test/scala/firrtlTests/AsyncResetSpec.scala @@ -117,6 +117,20 @@ class AsyncResetSpec extends FirrtlFlatSpec { } } + "Self-inits" should "NOT cause infinite loops in CheckResets" in { + val result = compileBody(s""" + |input clock : Clock + |input reset : AsyncReset + |input in : UInt<12> + |output out : UInt<10> + | + |reg a : UInt<10>, clock with : + | reset => (reset, a) + |out <= UInt<5>("h15")""".stripMargin + ) + result should containLine("assign out = 10'h15;") + } + "Late non-literals connections" should "NOT be allowed as reset values for AsyncReset" in { an [checks.CheckResets.NonLiteralAsyncResetValueException] shouldBe thrownBy { compileBody(s""" |
