diff options
| author | Jack Koenig | 2017-06-27 17:25:57 -0700 |
|---|---|---|
| committer | Jack Koenig | 2017-06-27 18:50:15 -0700 |
| commit | 6f55a30b201716b6a0e72b65f6e5777b6b5d4b81 (patch) | |
| tree | 61f5f7f7f278afbcd4fe1f5d6f7c4b4e536ce117 /src | |
| parent | f8572ba6532359e8a0f1bc34f3eb8241a29129ab (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.scala | 52 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/IntegrationSpec.scala | 1 |
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 { |
