aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/firrtl/Emitter.scala52
-rw-r--r--src/test/scala/firrtlTests/IntegrationSpec.scala1
-rw-r--r--test/integration/PipeTester.fir51
3 files changed, 78 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 {
diff --git a/test/integration/PipeTester.fir b/test/integration/PipeTester.fir
new file mode 100644
index 00000000..3ca2f001
--- /dev/null
+++ b/test/integration/PipeTester.fir
@@ -0,0 +1,51 @@
+
+circuit PipeTester :
+ ; This module should simply delay a signal by 2 cycles
+ ; Internal registers reset to 0
+ module Pipe :
+ input clock : Clock
+ input reset : UInt<1>
+ input in : UInt<4>
+ output out : UInt<4>
+
+ ;reg r : UInt<4>, clock with : (reset => (reset, UInt(0)))
+ ;r <= in
+ ; This is equivalent to the above
+
+ reg r : UInt<4>, clock
+ r <= mux(reset, UInt(0), in)
+
+ reg s : UInt<4>, clock with : (reset => (reset, UInt(0)))
+ s <= r
+ out <= s
+
+ module PipeTester :
+ input clock : Clock
+ input reset : UInt<1>
+
+ inst pipe of Pipe
+ pipe.clock <= clock
+ pipe.reset <= reset
+ pipe.in <= UInt(3)
+
+ reg cycle : UInt<4>, clock with : (reset => (reset, UInt<4>(0)))
+ cycle <= tail(add(cycle, UInt(1)), 1)
+
+ wire fail : UInt<1>
+ fail <= UInt(0)
+
+ when fail :
+ printf(clock, not(reset), "Assertion failed!\n")
+ stop(clock, not(reset), 1)
+
+ when not(reset) :
+ when lt(cycle, UInt(2)) :
+ when neq(pipe.out, UInt(0)) :
+ fail <= UInt(1)
+ when eq(cycle, UInt(2)) :
+ when neq(pipe.out, UInt(3)) :
+ fail <= UInt(1)
+ when eq(cycle, UInt(3)) :
+ printf(clock, UInt(1), "Success!\n")
+ stop(clock, UInt(1), 0)
+