aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJack Koenig2020-04-14 11:17:38 -0700
committerGitHub2020-04-14 11:17:38 -0700
commit0407a53bd76b41deed44dffbe08ca252536ab53c (patch)
tree86907dad790ba234ea85cc30108af221313f57f6 /src
parentf8546a7c165e0bde4b3e5682dd6edd0a3e199b31 (diff)
parent74ff30cf8dcfb7253458905b626dee89fc9b280c (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.scala15
-rw-r--r--src/test/scala/firrtlTests/AsyncResetSpec.scala14
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"""