Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Commit

Permalink
Merge branch '1.1.x' into release
Browse files Browse the repository at this point in the history
Fix for broken 1dcf990 (#833) cherry-pick - bad regUpdate code.
  • Loading branch information
ucbjrl committed Dec 21, 2018
2 parents 8d4e01b + d899b41 commit 5315457
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 26 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ organization := "edu.berkeley.cs"

name := "firrtl"

version := "1.1.5"
version := "1.1.6"

scalaVersion := "2.12.4"

Expand Down
65 changes: 40 additions & 25 deletions src/main/scala/firrtl/Emitter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -412,31 +412,46 @@ class VerilogEmitter extends SeqTransform with Emitter {
}

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, ";"))
// 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, ";"))
}
}
}

Expand Down

0 comments on commit 5315457

Please sign in to comment.