aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorDavid Biancolin2020-08-21 23:22:24 -0700
committerGitHub2020-08-22 06:22:24 +0000
commit72d3983b313fb20b819c2555a13a627cbb9d63c3 (patch)
tree16093716a5a8b2d41fa83032982577450b389e28 /src/main
parent266ac5fc32865d001409194f426b4126f5d9001b (diff)
Async reset tieoff bug (#1854)
* Elide emission of literals for async reset in sensitivity lists * Deprecate LegalizeClocksTransform Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/firrtl/transforms/LegalizeClocksAndAsyncResets.scala (renamed from src/main/scala/firrtl/transforms/LegalizeClocks.scala)45
-rw-r--r--src/main/scala/firrtl/transforms/package.scala8
2 files changed, 38 insertions, 15 deletions
diff --git a/src/main/scala/firrtl/transforms/LegalizeClocks.scala b/src/main/scala/firrtl/transforms/LegalizeClocksAndAsyncResets.scala
index 248775d9..5a1ccdbf 100644
--- a/src/main/scala/firrtl/transforms/LegalizeClocks.scala
+++ b/src/main/scala/firrtl/transforms/LegalizeClocksAndAsyncResets.scala
@@ -11,20 +11,25 @@ import firrtl.Utils.isCast
// - don't emit "always @(posedge <literal>)"
// Hitting this case is rare, but legal FIRRTL
// TODO This should be unified with all Verilog legalization transforms
-object LegalizeClocksTransform {
+object LegalizeClocksAndAsyncResetsTransform {
// Checks if an Expression is illegal in use in a @(posedge <Expression>) construct
// Legality is defined here by what standard lint tools accept
// Currently only looks for literals nested within casts
- private def illegalClockExpr(expr: Expression): Boolean = expr match {
+ private def isLiteralExpression(expr: Expression): Boolean = expr match {
case _: Literal => true
- case DoPrim(op, args, _, _) if isCast(op) => args.exists(illegalClockExpr)
+ case DoPrim(op, args, _, _) if isCast(op) => args.exists(isLiteralExpression)
case _ => false
}
- /** Legalize Clocks in a Statement
+ // Wraps the above function to check if a Rest is Async to avoid unneeded
+ // hoisting of sync reset literals.
+ private def isAsyncResetLiteralExpr(expr: Expression): Boolean =
+ if (expr.tpe == AsyncResetType) isLiteralExpression(expr) else false
+
+ /** Legalize Clocks and AsyncResets in a Statement
*
- * Enforces legal Verilog semantics on all Clock Expressions.
+ * Enforces legal Verilog semantics on all Clock and AsyncReset Expressions.
* Legal is defined as what standard lint tools accept.
* Currently only Literal Expressions (guarded by casts) are handled.
*
@@ -33,19 +38,29 @@ object LegalizeClocksTransform {
def onStmt(namespace: => Namespace)(stmt: Statement): Statement =
stmt.map(onStmt(namespace)) match {
// Proper union types would deduplicate this code
- case r: DefRegister if illegalClockExpr(r.clock) =>
- val node = DefNode(r.info, namespace.newTemp, r.clock)
- val rx = r.copy(clock = WRef(node))
- Block(Seq(node, rx))
- case p: Print if illegalClockExpr(p.clk) =>
+ case r: DefRegister if (isLiteralExpression(r.clock) || isAsyncResetLiteralExpr(r.reset)) =>
+ val (clockNodeOpt, rxClock) = if (isLiteralExpression(r.clock)) {
+ val node = DefNode(r.info, namespace.newTemp, r.clock)
+ (Some(node), r.copy(clock = WRef(node)))
+ } else {
+ (None, r)
+ }
+ val (resetNodeOpt, rx) = if (isAsyncResetLiteralExpr(r.reset)) {
+ val node = DefNode(r.info, namespace.newTemp, r.reset)
+ (Some(node), rxClock.copy(reset = WRef(node)))
+ } else {
+ (None, rxClock)
+ }
+ Block(clockNodeOpt ++: resetNodeOpt ++: Seq(rx))
+ case p: Print if isLiteralExpression(p.clk) =>
val node = DefNode(p.info, namespace.newTemp, p.clk)
val px = p.copy(clk = WRef(node))
Block(Seq(node, px))
- case s: Stop if illegalClockExpr(s.clk) =>
+ case s: Stop if isLiteralExpression(s.clk) =>
val node = DefNode(s.info, namespace.newTemp, s.clk)
val sx = s.copy(clk = WRef(node))
Block(Seq(node, sx))
- case s: Verification if illegalClockExpr(s.clk) =>
+ case s: Verification if isLiteralExpression(s.clk) =>
val node = DefNode(s.info, namespace.newTemp, s.clk)
val sx = s.copy(clk = WRef(node))
Block(Seq(node, sx))
@@ -62,8 +77,8 @@ object LegalizeClocksTransform {
}
}
-/** Ensure Clocks to be emitted are legal Verilog */
-class LegalizeClocksTransform extends Transform with DependencyAPIMigration {
+/** Ensure Clocks and AsyncResets to be emitted are legal Verilog */
+class LegalizeClocksAndAsyncResetsTransform extends Transform with DependencyAPIMigration {
override def prerequisites = firrtl.stage.Forms.LowFormMinimumOptimized ++
Seq(
@@ -81,7 +96,7 @@ class LegalizeClocksTransform extends Transform with DependencyAPIMigration {
override def invalidates(a: Transform) = false
def execute(state: CircuitState): CircuitState = {
- val modulesx = state.circuit.modules.map(LegalizeClocksTransform.onMod(_))
+ val modulesx = state.circuit.modules.map(LegalizeClocksAndAsyncResetsTransform.onMod(_))
state.copy(circuit = state.circuit.copy(modules = modulesx))
}
}
diff --git a/src/main/scala/firrtl/transforms/package.scala b/src/main/scala/firrtl/transforms/package.scala
new file mode 100644
index 00000000..4043598c
--- /dev/null
+++ b/src/main/scala/firrtl/transforms/package.scala
@@ -0,0 +1,8 @@
+package firrtl
+
+package object transforms {
+ @deprecated("Replaced by LegalizeClocksAndAsyncResetsTransform", "FIRRTL 1.4.0")
+ type LegalizeClocksTransform = LegalizeClocksAndAsyncResetsTransform
+ @deprecated("Replaced by LegalizeClocksAndAsyncResetsTransform", "FIRRTL 1.4.0")
+ val LegalizeClocksTransform = LegalizeClocksAndAsyncResetsTransform
+}