aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJack Koenig2017-06-28 11:50:25 -0700
committerGitHub2017-06-28 11:50:25 -0700
commit8eb69dd91e58915f8dad5e42da0a3fe686c628d8 (patch)
treec282e0dfe37de7a49271d9a1da364606fe35cf1a /src
parentf8572ba6532359e8a0f1bc34f3eb8241a29129ab (diff)
parentca01018fb144dcd206735973e5aa302dbc552ea8 (diff)
Merge pull request #615 from freechipsproject/remove-reset
Remove reset and fix bug in register update Verilog emission
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Emitter.scala52
-rw-r--r--src/main/scala/firrtl/LoweringCompilers.scala1
-rw-r--r--src/main/scala/firrtl/transforms/RemoveReset.scala43
-rw-r--r--src/test/scala/firrtlTests/IntegrationSpec.scala1
4 files changed, 71 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/main/scala/firrtl/LoweringCompilers.scala b/src/main/scala/firrtl/LoweringCompilers.scala
index 0df052af..66ae1673 100644
--- a/src/main/scala/firrtl/LoweringCompilers.scala
+++ b/src/main/scala/firrtl/LoweringCompilers.scala
@@ -85,6 +85,7 @@ class MiddleFirrtlToLowFirrtl extends CoreTransform {
passes.ResolveGenders,
passes.InferWidths,
passes.Legalize,
+ new firrtl.transforms.RemoveReset,
new firrtl.transforms.CheckCombLoops)
}
diff --git a/src/main/scala/firrtl/transforms/RemoveReset.scala b/src/main/scala/firrtl/transforms/RemoveReset.scala
new file mode 100644
index 00000000..bfec76a2
--- /dev/null
+++ b/src/main/scala/firrtl/transforms/RemoveReset.scala
@@ -0,0 +1,43 @@
+// See LICENSE for license details.
+
+package firrtl
+package transforms
+
+import firrtl.ir._
+import firrtl.Mappers._
+
+import scala.collection.mutable
+
+/** Remove Synchronous Reset
+ *
+ * @note This pass must run after LowerTypes
+ */
+class RemoveReset extends Transform {
+ def inputForm = MidForm
+ def outputForm = MidForm
+
+ private case class Reset(cond: Expression, value: Expression)
+
+ private def onModule(m: DefModule): DefModule = {
+ val resets = mutable.HashMap.empty[String, Reset]
+ def onStmt(stmt: Statement): Statement = {
+ stmt match {
+ case reg @ DefRegister(_, rname, _, _, reset, init) if reset != Utils.zero =>
+ // Add register reset to map
+ resets(rname) = Reset(reset, init)
+ reg.copy(reset = Utils.zero, init = WRef(reg))
+ case Connect(info, ref @ WRef(rname, _, RegKind, _), expr) if resets.contains(rname) =>
+ val reset = resets(rname)
+ val muxType = Utils.mux_type_and_widths(reset.value, expr)
+ Connect(info, ref, Mux(reset.cond, reset.value, expr, muxType))
+ case other => other map onStmt
+ }
+ }
+ m.map(onStmt)
+ }
+
+ def execute(state: CircuitState): CircuitState = {
+ val c = state.circuit.map(onModule)
+ state.copy(circuit = c)
+ }
+}
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 {