aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlbert Magyar2019-02-28 09:44:19 -0800
committerAdam Izraelevitz2019-02-28 09:44:19 -0800
commita8e8b5fc0355eb6422c56f19ba5f552207af6386 (patch)
treee82e982339d5f804be93d9688e3bdbe01ccf04f4 /src
parent76862eb88adb8a056534fe937f2d7e9353feee94 (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
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/passes/ExpandWhens.scala20
-rw-r--r--src/test/scala/firrtlTests/CheckInitializationSpec.scala40
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 :