aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Koenig2018-06-06 21:13:24 -0700
committerGitHub2018-06-06 21:13:24 -0700
commit7c49fa1726ab1860fbb3616156467807de2d7e3c (patch)
treef3fd0f149f22811acd6048ad4bb58722351873e3
parentc9d40a022efc2d4380186912e61c2c91d07e8958 (diff)
ConstProp attached wires if there is also a port (#818)
This enables the pattern of attaching "through" a wire to give better Verilog that also works in Verilator Use WrappedExpression when combining attaches in ExpandWhens to ensure no duplication of references in resulting, combined attaches
-rw-r--r--src/main/scala/firrtl/passes/ExpandWhens.scala9
-rw-r--r--src/main/scala/firrtl/transforms/ConstantPropagation.scala3
-rw-r--r--src/test/scala/firrtlTests/AttachSpec.scala32
3 files changed, 34 insertions, 10 deletions
diff --git a/src/main/scala/firrtl/passes/ExpandWhens.scala b/src/main/scala/firrtl/passes/ExpandWhens.scala
index 4abae636..3665590f 100644
--- a/src/main/scala/firrtl/passes/ExpandWhens.scala
+++ b/src/main/scala/firrtl/passes/ExpandWhens.scala
@@ -235,11 +235,12 @@ object ExpandWhens extends Pass {
*/
private def combineAttaches(attaches: Seq[Attach]): Seq[Attach] = {
// Helper type to add an ordering index to attached Expressions
- case class AttachAcc(exprs: Seq[Expression], idx: Int)
+ case class AttachAcc(exprs: Seq[WrappedExpression], idx: Int)
// Map from every attached expression to its corresponding AttachAcc
// (many keys will point to same value)
val attachMap = mutable.HashMap.empty[WrappedExpression, AttachAcc]
- for (Attach(_, exprs) <- attaches) {
+ for (Attach(_, es) <- attaches) {
+ val exprs = es.map(we(_))
val acc = exprs.map(attachMap.get(_)).flatten match {
case Seq() => // None of these expressions is present in the attachMap
AttachAcc(exprs, attachMap.size)
@@ -247,9 +248,9 @@ object ExpandWhens extends Pass {
val sorted = accs sortBy (_.idx)
AttachAcc((sorted.map(_.exprs) :+ exprs).flatten.distinct, sorted.head.idx)
}
- attachMap ++= acc.exprs.map(e => (we(e) -> acc))
+ attachMap ++= acc.exprs.map(_ -> acc)
}
- attachMap.values.toList.distinct.map(acc => Attach(NoInfo, acc.exprs))
+ attachMap.values.toList.distinct.map(acc => Attach(NoInfo, acc.exprs.map(_.e1)))
}
// Searches nested scopes of defaults for lvalue
// defaults uses mutable Map because we are searching LinkedHashMaps and conversion to immutable is VERY slow
diff --git a/src/main/scala/firrtl/transforms/ConstantPropagation.scala b/src/main/scala/firrtl/transforms/ConstantPropagation.scala
index 5e9a7850..4a4f41d1 100644
--- a/src/main/scala/firrtl/transforms/ConstantPropagation.scala
+++ b/src/main/scala/firrtl/transforms/ConstantPropagation.scala
@@ -396,6 +396,9 @@ class ConstantPropagation extends Transform {
// Propagate connections to references
case Connect(info, lhs, rref @ WRef(rname, _, NodeKind, _)) if !dontTouches.contains(rname) =>
Connect(info, lhs, nodeMap(rname))
+ // If an Attach has at least 1 port, any wires are redundant and can be removed
+ case Attach(info, exprs) if exprs.exists(kind(_) == PortKind) =>
+ Attach(info, exprs.filterNot(kind(_) == WireKind))
case other => other
}
}
diff --git a/src/test/scala/firrtlTests/AttachSpec.scala b/src/test/scala/firrtlTests/AttachSpec.scala
index c9c609df..9bf5fefd 100644
--- a/src/test/scala/firrtlTests/AttachSpec.scala
+++ b/src/test/scala/firrtlTests/AttachSpec.scala
@@ -107,6 +107,31 @@ class InoutVerilogSpec extends FirrtlFlatSpec {
executeTest(input, check, compiler, Seq(dontTouch("Attaching.x")))
}
+ it should "attach port to submodule port through a wire" in {
+ val compiler = new VerilogCompiler
+ val input =
+ """circuit Attaching :
+ | module Attaching :
+ | input an: Analog<3>
+ | wire x: Analog
+ | inst a of A
+ | attach (x, a.an)
+ | attach (x, an)
+ | module A:
+ | input an: Analog<3> """.stripMargin
+ val check =
+ """module Attaching(
+ | inout [2:0] an
+ |);
+ | A a (
+ | .an(an)
+ | );
+ |endmodule
+ |""".stripMargin.split("\n") map normalized
+ executeTest(input, check, compiler, Seq(dontTouch("Attaching.x")))
+ }
+
+
it should "attach multiple sources" in {
val compiler = new VerilogCompiler
val input =
@@ -121,18 +146,13 @@ class InoutVerilogSpec extends FirrtlFlatSpec {
| inout [2:0] a1,
| inout [2:0] a2
|);
- | wire [2:0] x;
| `ifdef SYNTHESIS
- | assign x = a1;
- | assign a1 = x;
- | assign x = a2;
- | assign a2 = x;
| assign a1 = a2;
| assign a2 = a1;
| `elsif verilator
| `error "Verilator does not support alias and thus cannot arbirarily connect bidirectional wires and ports"
| `else
- | alias x = a1 = a2;
+ | alias a1 = a2;
| `endif
|endmodule
|""".stripMargin.split("\n") map normalized