aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJack Koenig2017-06-27 17:25:57 -0700
committerJack Koenig2017-06-27 18:50:15 -0700
commit6f55a30b201716b6a0e72b65f6e5777b6b5d4b81 (patch)
tree61f5f7f7f278afbcd4fe1f5d6f7c4b4e536ce117 /src
parentf8572ba6532359e8a0f1bc34f3eb8241a29129ab (diff)
Emitting reg update mux tree, only walk netlist for wires and nodes
Fixes bug where the Verilog emitter could pull the next value for a register that feeds a second register, removing the first register from the second register's update.
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala52
-rw-r--r--src/test/scala/firrtlTests/IntegrationSpec.scala1
2 files changed, 27 insertions, 26 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index 00b5137e..744de96d 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -355,16 +355,11 @@ class VerilogEmitter extends SeqTransform with Emitter {
def emit_verilog(m: Module, moduleMap: Map[String, DefModule])(implicit w: Writer): DefModule = {
val netlist = mutable.LinkedHashMap[WrappedExpression, Expression]()
- val addrRegs = mutable.HashSet[WrappedExpression]()
val namespace = Namespace(m)
namespace.newName("_RAND") // Start rand names at _RAND_0
def build_netlist(s: Statement): Statement = s map build_netlist match {
case sx: Connect =>
netlist(sx.loc) = sx.expr
- (kind(sx.loc), kind(sx.expr)) match {
- case (MemKind, RegKind) => addrRegs += sx.expr
- case _ =>
- }
sx
case sx: IsInvalid =>
netlist(sx.expr) = wref(namespace.newTemp, sx.expr.tpe)
@@ -423,27 +418,32 @@ class VerilogEmitter extends SeqTransform with Emitter {
}
def addUpdate(e: Expression, tabs: String): Seq[Seq[Any]] = {
- if (weq(e, r)) Nil else netlist getOrElse (e, e) match {
- case m: Mux if canFlatten(m) =>
- val ifStatement = Seq(tabs, "if (", m.cond, ") begin")
- val trueCase =
- // Don't generate mux trees for mem addr pipes
- if (addrRegs(r)) Seq(Seq(tabs + tab, r, " <= ", m.tval, ";"))
- else addUpdate(m.tval, tabs + tab)
- val elseStatement = Seq(tabs, "end else begin")
- val ifNotStatement = Seq(tabs, "if (!(", m.cond, ")) begin")
- val falseCase = addUpdate(m.fval, tabs + tab)
- val endStatement = Seq(tabs, "end")
-
- ((trueCase.nonEmpty, falseCase.nonEmpty): @ unchecked) match {
- case (true, true) =>
- ifStatement +: trueCase ++: elseStatement +: falseCase :+ endStatement
- case (true, false) =>
- ifStatement +: trueCase :+ endStatement
- case (false, true) =>
- ifNotStatement +: falseCase :+ endStatement
- }
- case _ => Seq(Seq(tabs, r, " <= ", e, ";"))
+ if (weq(e, r)) Nil // Don't bother emitting connection of register to itself
+ else {
+ // Only walk netlist for nodes and wires, NOT registers or other state
+ val expr = kind(e) match {
+ case NodeKind | WireKind => netlist.getOrElse(e, e)
+ case _ => e
+ }
+ expr match {
+ case m: Mux if canFlatten(m) =>
+ val ifStatement = Seq(tabs, "if (", m.cond, ") begin")
+ val trueCase = addUpdate(m.tval, tabs + tab)
+ val elseStatement = Seq(tabs, "end else begin")
+ val ifNotStatement = Seq(tabs, "if (!(", m.cond, ")) begin")
+ val falseCase = addUpdate(m.fval, tabs + tab)
+ val endStatement = Seq(tabs, "end")
+
+ ((trueCase.nonEmpty, falseCase.nonEmpty): @ unchecked) match {
+ case (true, true) =>
+ ifStatement +: trueCase ++: elseStatement +: falseCase :+ endStatement
+ case (true, false) =>
+ ifStatement +: trueCase :+ endStatement
+ case (false, true) =>
+ ifNotStatement +: falseCase :+ endStatement
+ }
+ case _ => Seq(Seq(tabs, r, " <= ", e, ";"))
+ }
}
}
diff --git a/src/test/scala/firrtlTests/IntegrationSpec.scala b/src/test/scala/firrtlTests/IntegrationSpec.scala
index 6ac45b6d..647aa91b 100644
--- a/src/test/scala/firrtlTests/IntegrationSpec.scala
+++ b/src/test/scala/firrtlTests/IntegrationSpec.scala
@@ -11,6 +11,7 @@ import java.io.File
class GCDExecutionTest extends ExecutionTest("GCDTester", "/integration")
class RightShiftExecutionTest extends ExecutionTest("RightShiftTester", "/integration")
class MemExecutionTest extends ExecutionTest("MemTester", "/integration")
+class PipeExecutionTest extends ExecutionTest("PipeTester", "/integration")
// This is a bit custom some kind of one off
class GCDSplitEmissionExecutionTest extends FirrtlFlatSpec {