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

Commit

Permalink
Fix broken cherry-pick 1dcf990 - bad regUpdate code
Browse files Browse the repository at this point in the history
  • Loading branch information
ucbjrl committed Dec 21, 2018
1 parent 8f2ce70 commit d899b41
Showing 1 changed file with 40 additions and 25 deletions.
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 d899b41

Please sign in to comment.