diff options
| author | Schuyler Eldridge | 2019-10-22 00:48:59 -0400 |
|---|---|---|
| committer | GitHub | 2019-10-22 00:48:59 -0400 |
| commit | f5e6e2bc201c6206a705244d8977bda4b83e6efd (patch) | |
| tree | 3e42e57b110beefd6e13457db199d7c3a7d0bd4c /src/main | |
| parent | b43288d588d04775230456ca85fa231a8cf397fe (diff) | |
| parent | a4cb228161410de4c5ab2029d7756870f32d28b8 (diff) | |
Merge pull request #1204 from freechipsproject/else-if
Emit Verilog else-if for Register Updates
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 58 |
1 files changed, 31 insertions, 27 deletions
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala index d7c73e39..c427e0fc 100644 --- a/src/main/scala/firrtl/Emitter.scala +++ b/src/main/scala/firrtl/Emitter.scala @@ -534,33 +534,37 @@ class VerilogEmitter extends SeqTransform with Emitter { } def regUpdate(r: Expression, clk: Expression, reset: Expression, init: 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") - if (m.tpe == AsyncResetType) throw EmitterException("Cannot emit async reset 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, ";")) - } + def addUpdate(expr: Expression, tabs: String): Seq[Seq[Any]] = expr match { + case m: Mux => + if (m.tpe == ClockType) throw EmitterException("Cannot emit clock muxes directly") + if (m.tpe == AsyncResetType) throw EmitterException("Cannot emit async reset muxes directly") + + lazy val _if = Seq(tabs, "if (", m.cond, ") begin") + lazy val _else = Seq(tabs, "end else begin") + lazy val _ifNot = Seq(tabs, "if (!(", m.cond, ")) begin") + lazy val _end = Seq(tabs, "end") + lazy val _true = addUpdate(m.tval, tabs + tab) + lazy val _false = addUpdate(m.fval, tabs + tab) + lazy val _elseIfFalse = { + val _falsex = addUpdate(m.fval, tabs) // _false, but without an additional tab + Seq(tabs, "end else ", _falsex.head.tail) +: _falsex.tail + } + + /* For a Mux assignment, there are five possibilities: + * 1. Both the true and false condition are self-assignments; do nothing + * 2. The true condition is a self-assignment; invert the false condition and use that only + * 3. The false condition is a self-assignment; skip the false condition + * 4. The false condition is a Mux; use the true condition and use 'else if' for the false condition + * 5. Default; use both the true and false conditions + */ + (m.tval, m.fval) match { + case (t, f) if weq(t, r) && weq(f, r) => Nil + case (t, _) if weq(t, r) => _ifNot +: _false :+ _end + case (_, f) if weq(f, r) => _if +: _true :+ _end + case (_, _: Mux) => (_if +: _true) ++ _elseIfFalse + case _ => (_if +: _true :+ _else) ++ _false :+ _end + } + case e => Seq(Seq(tabs, r, " <= ", e, ";")) } if (weq(init, r)) { // Synchronous Reset noResetAlwaysBlocks.getOrElseUpdate(clk, ArrayBuffer[Seq[Any]]()) ++= addUpdate(netlist(r), "") |
