diff options
| author | Jack Koenig | 2018-03-23 18:16:21 -0700 |
|---|---|---|
| committer | GitHub | 2018-03-23 18:16:21 -0700 |
| commit | f806b26ec377882f5adae43f101aa53e92b13f5c (patch) | |
| tree | 46b94ee2a3d9fabd4ff36bddb15052c2d2eba321 /src/main/scala/firrtl/Emitter.scala | |
| parent | ebb6847e9d01b424424ae11a0067448a4094e46d (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.scala | 79 |
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, |
