diff options
| author | Albert Magyar | 2019-02-28 09:44:19 -0800 |
|---|---|---|
| committer | Adam Izraelevitz | 2019-02-28 09:44:19 -0800 |
| commit | a8e8b5fc0355eb6422c56f19ba5f552207af6386 (patch) | |
| tree | e82e982339d5f804be93d9688e3bdbe01ccf04f4 | |
| parent | 76862eb88adb8a056534fe937f2d7e9353feee94 (diff) | |
[ExpandWhens] Don't create nodes to hold Muxes with >0 void cases (#1039)
* Don't create nodes to hold Muxes with >0 void cases
* Added test case demonstrating void error
* Memoize intermediate expression when checking for WVoid-ness
| -rw-r--r-- | src/main/scala/firrtl/passes/ExpandWhens.scala | 20 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/CheckInitializationSpec.scala | 40 |
2 files changed, 59 insertions, 1 deletions
diff --git a/src/main/scala/firrtl/passes/ExpandWhens.scala b/src/main/scala/firrtl/passes/ExpandWhens.scala index 560a1c1c..956d54bc 100644 --- a/src/main/scala/firrtl/passes/ExpandWhens.scala +++ b/src/main/scala/firrtl/passes/ExpandWhens.scala @@ -73,7 +73,13 @@ object ExpandWhens extends Pass { def expandWhens(m: Module): (Netlist, Simlist, Seq[Attach], Statement, InfoMap) = { val namespace = Namespace(m) val simlist = new Simlist + + // Memoizes if an expression contains any WVoids inserted in this pass + val memoizedVoid = new mutable.HashSet[MemoizedHash[Expression]] += WVoid + + // Memoizes the node that holds a particular expression, if any val nodes = new NodeMap + // Seq of attaches in order lazy val attaches = mutable.ArrayBuffer.empty[Attach] @@ -171,7 +177,21 @@ object ExpandWhens extends Pass { conseqNetlist getOrElse (lvalue, altNetlist(lvalue)) } + // Does an expression contain WVoid inserted in this pass? + def containsVoid(e: Expression): Boolean = e match { + case WVoid => true + case ValidIf(_, value, _) => memoizedVoid(value) + case Mux(_, tv, fv, _) => memoizedVoid(tv) || memoizedVoid(fv) + case _ => false + } + res match { + // Don't create a node to hold mux trees with void values + // "Idiomatic" emission of these muxes isn't a concern because they represent bad code (latches) + case e if containsVoid(e) => + netlist(lvalue) = e + memoizedVoid += e // remember that this was void + EmptyStmt case _: ValidIf | _: Mux | _: DoPrim => nodes get res match { case Some(name) => netlist(lvalue) = WRef(name, res.tpe, NodeKind, MALE) diff --git a/src/test/scala/firrtlTests/CheckInitializationSpec.scala b/src/test/scala/firrtlTests/CheckInitializationSpec.scala index 9ccff256..9b1f3a9c 100644 --- a/src/test/scala/firrtlTests/CheckInitializationSpec.scala +++ b/src/test/scala/firrtlTests/CheckInitializationSpec.scala @@ -24,7 +24,9 @@ class CheckInitializationSpec extends FirrtlFlatSpec { ExpandConnects, RemoveAccesses, ExpandWhens, - CheckInitialization) + CheckInitialization, + InferTypes + ) "Missing assignment in consequence branch" should "trigger a PassException" in { val input = """circuit Test : @@ -54,6 +56,42 @@ class CheckInitializationSpec extends FirrtlFlatSpec { } } } + + "Assign after incomplete assignment" should "work" in { + val input = + """circuit Test : + | module Test : + | input p : UInt<1> + | wire x : UInt<32> + | when p : + | x <= UInt(1) + | x <= UInt(1) + | """.stripMargin + passes.foldLeft(CircuitState(parse(input), UnknownForm)) { + (c: CircuitState, p: Transform) => p.runTransform(c) + } + } + + "Assign after nested incomplete assignment" should "work" in { + val input = + """circuit Test : + | module Test : + | input p : UInt<1> + | input q : UInt<1> + | wire x : UInt<32> + | when p : + | when q : + | x is invalid + | else : + | when q : + | x <= UInt(2) + | x <= UInt(1) + | """.stripMargin + passes.foldLeft(CircuitState(parse(input), UnknownForm)) { + (c: CircuitState, p: Transform) => p.runTransform(c) + } + } + "Missing assignment to submodule port" should "trigger a PassException" in { val input = """circuit Test : |
