aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Emitter.scala
diff options
context:
space:
mode:
authorJack Koenig2018-03-23 18:16:21 -0700
committerGitHub2018-03-23 18:16:21 -0700
commitf806b26ec377882f5adae43f101aa53e92b13f5c (patch)
tree46b94ee2a3d9fabd4ff36bddb15052c2d2eba321 /src/main/scala/firrtl/Emitter.scala
parentebb6847e9d01b424424ae11a0067448a4094e46d (diff)
Make Register Update Flattening a Transform and Delete Dangling Nodes (#692)
Diffstat (limited to 'src/main/scala/firrtl/Emitter.scala')
-rw-r--r--src/main/scala/firrtl/Emitter.scala79
1 files changed, 27 insertions, 52 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
index a94ed37f..2c874392 100644
--- a/src/main/scala/firrtl/Emitter.scala
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -12,6 +12,7 @@ import scala.io.Source
import firrtl.ir._
import firrtl.passes._
+import firrtl.transforms.{DeadCodeElimination, FlattenRegUpdate}
import firrtl.annotations._
import firrtl.Mappers._
import firrtl.PrimOps._
@@ -363,59 +364,31 @@ class VerilogEmitter extends SeqTransform with Emitter {
assigns += Seq("assign ", e, " = ", rand_string(e.tpe), ";")
assigns += Seq("`endif // RANDOMIZE_INVALID_ASSIGN")
}
- def update_and_reset(r: Expression, clk: Expression, reset: Expression, init: Expression) = {
- // We want to flatten Mux trees for reg updates into if-trees for
- // improved QoR for conditional updates. However, unbounded recursion
- // would take exponential time, so don't redundantly flatten the same
- // Mux more than a bounded number of times, preserving linear runtime.
- // The threshold is empirical but ample.
- val flattenThreshold = 4
- val numTimesFlattened = collection.mutable.HashMap[Mux, Int]()
- def canFlatten(m: Mux) = {
- val n = numTimesFlattened.getOrElse(m, 0)
- numTimesFlattened(m) = n + 1
- n < flattenThreshold
- }
-
- def addUpdate(e: Expression, tabs: String): Seq[Seq[Any]] = {
- 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) =>
- if(m.tpe == ClockType) throw EmitterException("Cannot emit clock muxes directly")
- 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, ";"))
- }
+ def regUpdate(r: Expression, clk: Expression) = {
+ def addUpdate(expr: Expression, tabs: String): Seq[Seq[Any]] = {
+ if (weq(expr, r)) Nil // Don't bother emitting connection of register to itself
+ else expr match {
+ case m: Mux =>
+ if (m.tpe == ClockType) throw EmitterException("Cannot emit clock muxes directly")
+ def ifStatement = Seq(tabs, "if (", m.cond, ") begin")
+ val trueCase = addUpdate(m.tval, tabs + tab)
+ val elseStatement = Seq(tabs, "end else begin")
+ def 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 e => Seq(Seq(tabs, r, " <= ", e, ";"))
}
}
-
- at_clock.getOrElseUpdate(clk, ArrayBuffer[Seq[Any]]()) ++= {
- val tv = init
- val fv = netlist(r)
- if (weq(tv, r))
- addUpdate(fv, "")
- else
- addUpdate(Mux(reset, tv, fv, mux_type_and_widths(tv, fv)), "")
- }
+ at_clock.getOrElseUpdate(clk, ArrayBuffer[Seq[Any]]()) ++= addUpdate(netlist(r), "")
}
def update(e: Expression, value: Expression, clk: Expression, en: Expression, info: Info) = {
@@ -519,7 +492,7 @@ class VerilogEmitter extends SeqTransform with Emitter {
case sx: DefRegister =>
declare("reg", sx.name, sx.tpe, sx.info)
val e = wref(sx.name, sx.tpe)
- update_and_reset(e, sx.clock, sx.reset, sx.init)
+ regUpdate(e, sx.clock)
initialize(e)
sx
case sx: DefNode =>
@@ -686,6 +659,8 @@ class VerilogEmitter extends SeqTransform with Emitter {
/** Preamble for every emitted Verilog file */
def transforms = Seq(
+ new FlattenRegUpdate,
+ new DeadCodeElimination,
passes.VerilogModulusCleanup,
passes.VerilogWrap,
passes.VerilogRename,