diff options
| author | Jack Koenig | 2019-11-30 01:29:55 -0800 |
|---|---|---|
| committer | Jack Koenig | 2020-01-07 18:35:43 -0800 |
| commit | c16ef85cc76d6693045f1ecb84ad02227bab33c0 (patch) | |
| tree | aeaf4599eddc50790d8e58aeea172a471224014b /src/main/scala/firrtl/transforms | |
| parent | df48d61c3e1cb476f51762b1f009ecc9391221c6 (diff) | |
Remove unnecessary $signed casts for PrimOps in Verilog Emitter
[skip formal checks]
Adds new InlineCastsTransform to the VerilogEmitter which removes
Statements that do nothing but cast by inlining the cast Expression
Diffstat (limited to 'src/main/scala/firrtl/transforms')
| -rw-r--r-- | src/main/scala/firrtl/transforms/InlineCasts.scala | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/transforms/InlineCasts.scala b/src/main/scala/firrtl/transforms/InlineCasts.scala new file mode 100644 index 00000000..e504eb70 --- /dev/null +++ b/src/main/scala/firrtl/transforms/InlineCasts.scala @@ -0,0 +1,70 @@ +package firrtl +package transforms + +import firrtl.ir._ +import firrtl.Mappers._ + +import firrtl.Utils.{isCast, NodeMap} + +object InlineCastsTransform { + + // Checks if an Expression is made up of only casts terminated by a Literal or Reference + // There must be at least one cast + // Note that this can have false negatives but MUST NOT have false positives + private def isSimpleCast(castSeen: Boolean)(expr: Expression): Boolean = expr match { + case _: WRef | _: Literal | _: WSubField => castSeen + case DoPrim(op, args, _,_) if isCast(op) => args.forall(isSimpleCast(true)) + case _ => false + } + + /** Recursively replace [[WRef]]s with new [[Expression]]s + * + * @param replace a '''mutable''' HashMap mapping [[WRef]]s to values with which the [[WRef]] + * will be replaced. It is '''not''' mutated in this function + * @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.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 + } + } + + /** Inline casts in a Statement + * + * @param netlist a '''mutable''' HashMap mapping references to [[firrtl.ir.DefNode DefNode]]s to their connected + * [[firrtl.ir.Expression Expression]]s. This function '''will''' mutate it if stmt is a [[firrtl.ir.DefNode + * DefNode]] with a value that is a cast [[PrimOp]] + * @param stmt the Statement being searched for nodes and transformed + * @return Returns stmt with casts inlined + */ + def onStmt(netlist: NodeMap)(stmt: Statement): Statement = + stmt.map(onStmt(netlist)).map(onExpr(netlist)) match { + case node @ DefNode(_, name, value) => + netlist(name) = value + node + case other => other + } + + /** Replaces truncating arithmetic in a Module */ + def onMod(mod: DefModule): DefModule = mod.map(onStmt(new NodeMap)) +} + +/** Inline nodes that are simple casts */ +class InlineCastsTransform extends Transform { + def inputForm = LowForm + def outputForm = LowForm + + def execute(state: CircuitState): CircuitState = { + val modulesx = state.circuit.modules.map(InlineCastsTransform.onMod(_)) + state.copy(circuit = state.circuit.copy(modules = modulesx)) + } +} |
