aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorJack Koenig2021-03-18 23:31:51 -0700
committerGitHub2021-03-18 23:31:51 -0700
commitb274b319d4a4014c154f06bfc174beba461d6fce (patch)
tree36f3c83f5ceb3d820bc6d6073d8ad2de202c8773 /src/main
parent94d1bee4c23bd3d8f99dae3ca431ffaa5dc1410d (diff)
Ensure InlineCasts does not inline complex Expressions (#2130)
Previously, InlineCasts could inline complex (ie. non-cast) Expressions into other complex Expressions. Now it will only inline so long as there no more than 1 complex Expression in the current nested Expression. Co-authored-by: Albert Magyar <albert.magyar@gmail.com>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/firrtl/transforms/InlineCasts.scala41
1 files changed, 24 insertions, 17 deletions
diff --git a/src/main/scala/firrtl/transforms/InlineCasts.scala b/src/main/scala/firrtl/transforms/InlineCasts.scala
index 71318eee..761252c1 100644
--- a/src/main/scala/firrtl/transforms/InlineCasts.scala
+++ b/src/main/scala/firrtl/transforms/InlineCasts.scala
@@ -28,23 +28,30 @@ object InlineCastsTransform {
* @param expr the Expression being transformed
* @return Returns expr with [[WRef]]s replaced by values found in replace
*/
- def onExpr(replace: NodeMap)(expr: Expression): Expression = expr match {
- // Anything that may generate a part-select should not be inlined!
- case DoPrim(op, _, _, _) if (isBitExtract(op) || op == Pad) => expr
- case e =>
- e.map(onExpr(replace)) match {
- case e @ WRef(name, _, _, _) =>
- replace
- .get(name)
- .filter(isSimpleCast(castSeen = false))
- .getOrElse(e)
- case e @ DoPrim(op, Seq(WRef(name, _, _, _)), _, _) if isCast(op) =>
- replace
- .get(name)
- .map(value => e.copy(args = Seq(value)))
- .getOrElse(e)
- case other => other // Not a candidate
- }
+ def onExpr(replace: NodeMap)(expr: Expression): Expression = {
+ // Keep track if we've seen any non-cast expressions while recursing
+ def rec(hasNonCastParent: Boolean)(expr: Expression): Expression = expr match {
+ // Skip pads to avoid inlining literals into pads which results in invalid Verilog
+ case DoPrim(op, _, _, _) if (isBitExtract(op) || op == Pad) => expr
+ case e =>
+ e.map(rec(hasNonCastParent || !isCast(e))) match {
+ case e @ WRef(name, _, _, _) =>
+ replace
+ .get(name)
+ .filter(isSimpleCast(castSeen = false))
+ .getOrElse(e)
+ case e @ DoPrim(op, Seq(WRef(name, _, _, _)), _, _) if isCast(op) =>
+ replace
+ .get(name)
+ // Only inline the Expression if there is no non-cast parent in the expression tree OR
+ // if the subtree contains only casts and references.
+ .filter(x => !hasNonCastParent || isSimpleCast(castSeen = true)(x))
+ .map(value => e.copy(args = Seq(value)))
+ .getOrElse(e)
+ case other => other // Not a candidate
+ }
+ }
+ rec(false)(expr)
}
/** Inline casts in a Statement