aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/transforms
diff options
context:
space:
mode:
authorJack Koenig2018-05-15 11:29:43 -0700
committerGitHub2018-05-15 11:29:43 -0700
commit84b5fc1bc97e014bc03056a3f752c40ec6100701 (patch)
tree2af78be6b61fbb82c1261d3d30ab9cabbcf401f4 /src/main/scala/firrtl/transforms
parentabcb22d6c34eb51749e7bc848b437a165bc5b330 (diff)
Replace truncating add and sub with addw/subw (#800)
Replaces old VerilogWrap which didn't work with split expressions and was actually buggy anyway. This functionality reduces unnecessary intermediates in emitted Verilog.
Diffstat (limited to 'src/main/scala/firrtl/transforms')
-rw-r--r--src/main/scala/firrtl/transforms/ReplaceTruncatingArithmetic.scala73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/transforms/ReplaceTruncatingArithmetic.scala b/src/main/scala/firrtl/transforms/ReplaceTruncatingArithmetic.scala
new file mode 100644
index 00000000..9c809c5f
--- /dev/null
+++ b/src/main/scala/firrtl/transforms/ReplaceTruncatingArithmetic.scala
@@ -0,0 +1,73 @@
+package firrtl
+package transforms
+
+import firrtl.ir._
+import firrtl.Mappers._
+import firrtl.PrimOps._
+import firrtl.WrappedExpression._
+
+import scala.collection.mutable
+
+object ReplaceTruncatingArithmetic {
+
+ /** Mapping from references to the [[Expression]]s that drive them */
+ type Netlist = mutable.HashMap[WrappedExpression, Expression]
+
+ private val SeqBIOne = Seq(BigInt(1))
+
+ /** Replaces truncating arithmetic in an Expression
+ *
+ * @param netlist a '''mutable''' HashMap mapping references to [[DefNode]]s to their connected
+ * [[Expression]]s. It is '''not''' mutated in this function
+ * @param expr the Expression being transformed
+ * @return Returns expr with truncating arithmetic replaced
+ */
+ def onExpr(netlist: Netlist)(expr: Expression): Expression =
+ expr.map(onExpr(netlist)) match {
+ case orig @ DoPrim(Tail, Seq(e), SeqBIOne, tailtpe) =>
+ netlist.getOrElse(we(e), e) match {
+ case DoPrim(Add, args, cs, _) => DoPrim(Addw, args, cs, tailtpe)
+ case DoPrim(Sub, args, cs, _) => DoPrim(Subw, args, cs, tailtpe)
+ case _ => orig // Not a candidate
+ }
+ case other => other // Not a candidate
+ }
+
+ /** Replaces truncating arithmetic in a Statement
+ *
+ * @param netlist a '''mutable''' HashMap mapping references to [[DefNode]]s to their connected
+ * [[Expression]]s. This function '''will''' mutate it if stmt contains a [[DefNode]]
+ * @param stmt the Statement being searched for nodes and transformed
+ * @return Returns stmt with truncating arithmetic replaced
+ */
+ def onStmt(netlist: Netlist)(stmt: Statement): Statement =
+ stmt.map(onStmt(netlist)).map(onExpr(netlist)) match {
+ case node @ DefNode(_, name, value) =>
+ netlist(we(WRef(name))) = value
+ node
+ case other => other
+ }
+
+ /** Replaces truncating arithmetic in a Module */
+ def onMod(mod: DefModule): DefModule = mod.map(onStmt(new Netlist))
+}
+
+/** Replaces non-expanding arithmetic
+ *
+ * In the case where the result of `add` or `sub` immediately throws away the expanded msb, this
+ * transform will replace the operation with a non-expanding operator `addw` or `subw`
+ * respectively.
+ *
+ * @note This replaces some FIRRTL primops with ops that are not actually legal FIRRTL. They are
+ * useful for emission to languages that support non-expanding arithmetic (like Verilog)
+ */
+class ReplaceTruncatingArithmetic extends Transform {
+ def inputForm = LowForm
+ def outputForm = LowForm
+
+ def execute(state: CircuitState): CircuitState = {
+ val modulesx = state.circuit.modules.map(ReplaceTruncatingArithmetic.onMod(_))
+ state.copy(circuit = state.circuit.copy(modules = modulesx))
+ }
+}
+