diff options
| author | Albert Chen | 2018-11-15 08:53:16 -0800 |
|---|---|---|
| committer | Schuyler Eldridge | 2018-11-15 08:53:16 -0800 |
| commit | b90589f5cd9d4048ada2a05d5225874791546170 (patch) | |
| tree | 126699d5955746ecb7e4d5432299c648ec3446d5 /src/main/scala/firrtl/transforms | |
| parent | 6ece732d09b8610ae50545dab312d6759ac2f8e2 (diff) | |
Combine cats (#851)
- Add firrtl.transforms.CombineCats
- Use CombineCats in LowFirrtlOptimization
- Modify Verilog emitter to allow for nested Cat DoPrims
- Modify firrtlEquivalenceTest to write input FIRRTL string to test directory
Diffstat (limited to 'src/main/scala/firrtl/transforms')
| -rw-r--r-- | src/main/scala/firrtl/transforms/CombineCats.scala | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/transforms/CombineCats.scala b/src/main/scala/firrtl/transforms/CombineCats.scala new file mode 100644 index 00000000..1265a5c3 --- /dev/null +++ b/src/main/scala/firrtl/transforms/CombineCats.scala @@ -0,0 +1,68 @@ + +package firrtl +package transforms + +import firrtl.ir._ +import firrtl.Mappers._ +import firrtl.PrimOps._ +import firrtl.WrappedExpression._ +import firrtl.annotations.NoTargetAnnotation + +import scala.collection.mutable + +case class MaxCatLenAnnotation(maxCatLen: Int) extends NoTargetAnnotation + +object CombineCats { + /** Mapping from references to the [[Expression]]s that drive them paired with their Cat length */ + type Netlist = mutable.HashMap[WrappedExpression, (Int, Expression)] + + def expandCatArgs(maxCatLen: Int, netlist: Netlist)(expr: Expression): (Int, Expression) = expr match { + case cat@DoPrim(Cat, args, _, _) => + val (a0Len, a0Expanded) = expandCatArgs(maxCatLen - 1, netlist)(args.head) + val (a1Len, a1Expanded) = expandCatArgs(maxCatLen - a0Len, netlist)(args(1)) + (a0Len + a1Len, cat.copy(args = Seq(a0Expanded, a1Expanded)).asInstanceOf[Expression]) + case other => + netlist.get(we(expr)).collect { + case (len, cat@DoPrim(Cat, _, _, _)) if maxCatLen >= len => expandCatArgs(maxCatLen, netlist)(cat) + }.getOrElse((1, other)) + } + + def onStmt(maxCatLen: Int, netlist: Netlist)(stmt: Statement): Statement = { + stmt.map(onStmt(maxCatLen, netlist)) match { + case node@DefNode(_, name, value) => + val catLenAndVal = value match { + case cat@DoPrim(Cat, _, _, _) => expandCatArgs(maxCatLen, netlist)(cat) + case other => (1, other) + } + netlist(we(WRef(name))) = catLenAndVal + node.copy(value = catLenAndVal._2) + case other => other + } + } + + def onMod(maxCatLen: Int)(mod: DefModule): DefModule = mod.map(onStmt(maxCatLen, new Netlist)) +} + +/** Combine Cat DoPrims + * + * Expands the arguments of any Cat DoPrims if they are references to other Cat DoPrims. + * Operates only on Cat DoPrims that are node values. + * + * Use [[MaxCatLenAnnotation]] to limit the number of elements that can be concatenated. + * The default maximum number of elements is 10. + */ +class CombineCats extends Transform { + def inputForm: LowForm.type = LowForm + def outputForm: LowForm.type = LowForm + val defaultMaxCatLen = 10 + + def execute(state: CircuitState): CircuitState = { + val maxCatLen = state.annotations.collectFirst { + case m: MaxCatLenAnnotation => m.maxCatLen + }.getOrElse(defaultMaxCatLen) + + val modulesx = state.circuit.modules.map(CombineCats.onMod(maxCatLen)) + state.copy(circuit = state.circuit.copy(modules = modulesx)) + } +} + |
