aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/transforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/firrtl/transforms')
-rw-r--r--src/main/scala/firrtl/transforms/CheckCombLoops.scala6
-rw-r--r--src/main/scala/firrtl/transforms/ConstantPropagation.scala7
-rw-r--r--src/main/scala/firrtl/transforms/DeadCodeElimination.scala7
-rw-r--r--src/main/scala/firrtl/transforms/Dedup.scala266
-rw-r--r--src/main/scala/firrtl/transforms/OptimizationAnnotations.scala8
5 files changed, 94 insertions, 200 deletions
diff --git a/src/main/scala/firrtl/transforms/CheckCombLoops.scala b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
index 44785c62..98033a2f 100644
--- a/src/main/scala/firrtl/transforms/CheckCombLoops.scala
+++ b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
@@ -26,9 +26,9 @@ case object DontCheckCombLoopsAnnotation extends NoTargetAnnotation
case class CombinationalPath(sink: ComponentName, sources: Seq[ComponentName]) extends Annotation {
override def update(renames: RenameMap): Seq[Annotation] = {
- val newSources: Seq[IsComponent] = sources.flatMap { s => renames.get(s).getOrElse(Seq(s.toTarget)) }.collect {case x: IsComponent if x.isLocal => x}
- val newSinks = renames.get(sink).getOrElse(Seq(sink.toTarget)).collect { case x: IsComponent if x.isLocal => x}
- newSinks.map(snk => CombinationalPath(snk.toNamed, newSources.map(_.toNamed)))
+ val newSources = sources.flatMap { s => renames.get(s).getOrElse(Seq(s)) }
+ val newSinks = renames.get(sink).getOrElse(Seq(sink))
+ newSinks.map(snk => CombinationalPath(snk, newSources))
}
}
diff --git a/src/main/scala/firrtl/transforms/ConstantPropagation.scala b/src/main/scala/firrtl/transforms/ConstantPropagation.scala
index da7f1a46..0d30446c 100644
--- a/src/main/scala/firrtl/transforms/ConstantPropagation.scala
+++ b/src/main/scala/firrtl/transforms/ConstantPropagation.scala
@@ -12,7 +12,6 @@ import firrtl.PrimOps._
import firrtl.graph.DiGraph
import firrtl.WrappedExpression.weq
import firrtl.analyses.InstanceGraph
-import firrtl.annotations.TargetToken.Ref
import annotation.tailrec
import collection.mutable
@@ -47,13 +46,11 @@ object ConstantPropagation {
}
}
-class ConstantPropagation extends Transform with ResolvedAnnotationPaths {
+class ConstantPropagation extends Transform {
import ConstantPropagation._
def inputForm = LowForm
def outputForm = LowForm
- override val annotationClasses: Traversable[Class[_]] = Seq(classOf[DontTouchAnnotation])
-
trait FoldCommutativeOp {
def fold(c1: Literal, c2: Literal): Expression
def simplify(e: Expression, lhs: Literal, rhs: Expression): Expression
@@ -523,7 +520,7 @@ class ConstantPropagation extends Transform with ResolvedAnnotationPaths {
def execute(state: CircuitState): CircuitState = {
val dontTouches: Seq[(String, String)] = state.annotations.collect {
- case DontTouchAnnotation(Target(_, Some(m), Seq(Ref(c)))) => m -> c
+ case DontTouchAnnotation(ComponentName(c, ModuleName(m, _))) => m -> c
}
// Map from module name to component names
val dontTouchMap: Map[String, Set[String]] =
diff --git a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
index 523c997b..c98b892c 100644
--- a/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
+++ b/src/main/scala/firrtl/transforms/DeadCodeElimination.scala
@@ -30,7 +30,7 @@ import java.io.{File, FileWriter}
* circumstances of their instantiation in their parent module, they will still not be removed. To
* remove such modules, use the [[NoDedupAnnotation]] to prevent deduplication.
*/
-class DeadCodeElimination extends Transform with ResolvedAnnotationPaths {
+class DeadCodeElimination extends Transform {
def inputForm = LowForm
def outputForm = LowForm
@@ -321,12 +321,9 @@ class DeadCodeElimination extends Transform with ResolvedAnnotationPaths {
state.copy(circuit = newCircuit, renames = Some(renames))
}
- override val annotationClasses: Traversable[Class[_]] =
- Seq(classOf[DontTouchAnnotation], classOf[OptimizableExtModuleAnnotation])
-
def execute(state: CircuitState): CircuitState = {
val dontTouches: Seq[LogicNode] = state.annotations.collect {
- case DontTouchAnnotation(component: ReferenceTarget) if component.isLocal => LogicNode(component)
+ case DontTouchAnnotation(component) => LogicNode(component)
}
val doTouchExtMods: Seq[String] = state.annotations.collect {
case OptimizableExtModuleAnnotation(ModuleName(name, _)) => name
diff --git a/src/main/scala/firrtl/transforms/Dedup.scala b/src/main/scala/firrtl/transforms/Dedup.scala
index 1c20b448..5630cecf 100644
--- a/src/main/scala/firrtl/transforms/Dedup.scala
+++ b/src/main/scala/firrtl/transforms/Dedup.scala
@@ -6,18 +6,17 @@ package transforms
import firrtl.ir._
import firrtl.Mappers._
import firrtl.analyses.InstanceGraph
-import firrtl.annotations.TargetToken.{Instance, OfModule, Ref}
import firrtl.annotations._
import firrtl.passes.{InferTypes, MemPortUtils}
-import firrtl.Utils.throwInternalError
// Datastructures
import scala.collection.mutable
-/** A component, e.g. register etc. Must be declared only once under the TopAnnotation */
+/** A component, e.g. register etc. Must be declared only once under the TopAnnotation
+ */
case class NoDedupAnnotation(target: ModuleName) extends SingleTargetAnnotation[ModuleName] {
- def duplicate(n: ModuleName): NoDedupAnnotation = NoDedupAnnotation(n)
+ def duplicate(n: ModuleName) = NoDedupAnnotation(n)
}
/** Only use on legal Firrtl.
@@ -29,63 +28,62 @@ class DedupModules extends Transform {
def inputForm: CircuitForm = HighForm
def outputForm: CircuitForm = HighForm
- /** Deduplicate a Circuit
+ /**
+ * Deduplicate a Circuit
* @param state Input Firrtl AST
* @return A transformed Firrtl AST
*/
def execute(state: CircuitState): CircuitState = {
val noDedups = state.annotations.collect { case NoDedupAnnotation(ModuleName(m, c)) => m }
- val (newC, renameMap) = run(state.circuit, noDedups, state.annotations)
+ val (newC, renameMap) = run(state.circuit, noDedups)
state.copy(circuit = newC, renames = Some(renameMap))
}
- /** Deduplicates a circuit, and records renaming
+ /**
+ * Deduplicates a circuit, and records renaming
* @param c Circuit to dedup
* @param noDedups Modules not to dedup
* @return Deduped Circuit and corresponding RenameMap
*/
- def run(c: Circuit, noDedups: Seq[String], annos: Seq[Annotation]): (Circuit, RenameMap) = {
+ def run(c: Circuit, noDedups: Seq[String]): (Circuit, RenameMap) = {
// RenameMap
val renameMap = RenameMap()
renameMap.setCircuit(c.main)
// Maps module name to corresponding dedup module
- val dedupMap = DedupModules.deduplicate(c, noDedups.toSet, annos, renameMap)
+ val dedupMap = DedupModules.deduplicate(c, noDedups.toSet, renameMap)
// Use old module list to preserve ordering
val dedupedModules = c.modules.map(m => dedupMap(m.name)).distinct
val cname = CircuitName(c.main)
- val map = dedupMap.map { case (from, to) =>
+ renameMap.addMap(dedupMap.map { case (from, to) =>
logger.debug(s"[Dedup] $from -> ${to.name}")
ModuleName(from, cname) -> List(ModuleName(to.name, cname))
- }
- renameMap.recordAll(
- map.map {
- case (k: ModuleName, v: List[ModuleName]) => Target.convertNamed2Target(k) -> v.map(Target.convertNamed2Target)
- }
- )
+ })
(InferTypes.run(c.copy(modules = dedupedModules)), renameMap)
}
}
-/** Utility functions for [[DedupModules]] */
+/**
+ * Utility functions for [[DedupModules]]
+ */
object DedupModules {
-
- /** Change's a module's internal signal names, types, infos, and modules.
+ /**
+ * Change's a module's internal signal names, types, infos, and modules.
* @param rename Function to rename a signal. Called on declaration and references.
* @param retype Function to retype a signal. Called on declaration, references, and subfields
* @param reinfo Function to re-info a statement
- * @param renameOfModule Function to rename an instance's module
+ * @param renameModule Function to rename an instance's module
* @param module Module to change internals
* @return Changed Module
*/
def changeInternals(rename: String=>String,
retype: String=>Type=>Type,
reinfo: Info=>Info,
- renameOfModule: (String, String)=>String
+ renameModule: String=>String
)(module: DefModule): DefModule = {
def onPort(p: Port): Port = Port(reinfo(p.info), rename(p.name), p.direction, retype(p.name)(p.tpe))
def onExp(e: Expression): Expression = e match {
@@ -101,9 +99,9 @@ object DedupModules {
}
def onStmt(s: Statement): Statement = s match {
case WDefInstance(i, n, m, t) =>
- val newmod = renameOfModule(n, m)
+ val newmod = renameModule(m)
WDefInstance(reinfo(i), rename(n), newmod, retype(n)(t))
- case DefInstance(i, n, m) => DefInstance(reinfo(i), rename(n), renameOfModule(n, m))
+ case DefInstance(i, n, m) => DefInstance(reinfo(i), rename(n), renameModule(m))
case d: DefMemory =>
val oldType = MemPortUtils.memType(d)
val newType = retype(d.name)(oldType)
@@ -131,79 +129,49 @@ object DedupModules {
module map onPort map onStmt
}
- def uniquifyField(ref: String, depth: Int, field: String): String = ref + depth + field
-
- /** Turns a module into a name-agnostic module
+ /**
+ * Turns a module into a name-agnostic module
* @param module module to change
* @return name-agnostic module
*/
- def agnostify(top: CircuitTarget,
- module: DefModule,
- renameMap: RenameMap
- ): DefModule = {
-
-
+ def agnostify(module: DefModule, name2tag: mutable.HashMap[String, String], tag2name: mutable.HashMap[String, String]): DefModule = {
val namespace = Namespace()
+ val nameMap = mutable.HashMap[String, String]()
val typeMap = mutable.HashMap[String, Type]()
-
- renameMap.setCircuit(top.circuitOpt.get)
- renameMap.setModule(module.name)
-
def rename(name: String): String = {
- val ret = renameMap.get(top.module(module.name).ref(name))
- ret match {
- case Some(Seq(Target(_, _, Seq(Ref(x))))) => x
- case None =>
- val newName = namespace.newTemp
- renameMap.rename(name, newName)
- newName
- case other => throwInternalError(other.toString)
+ if (nameMap.contains(name)) nameMap(name) else {
+ val newName = namespace.newTemp
+ nameMap(name) = newName
+ newName
}
}
-
def retype(name: String)(tpe: Type): Type = {
if (typeMap.contains(name)) typeMap(name) else {
- def onType(depth: Int)(tpe: Type): Type = tpe map onType(depth + 1) match {
- //TODO bugfix: ref.data.data and ref.datax.data will not rename to the right tags, even if they should be
- case BundleType(fields) =>
- BundleType(fields.map(f => Field(rename(uniquifyField(name, depth, f.name)), f.flip, f.tpe)))
+ def onType(tpe: Type): Type = tpe map onType match {
+ case BundleType(fields) => BundleType(fields.map(f => Field(rename(f.name), f.flip, f.tpe)))
case other => other
}
- val newType = onType(0)(tpe)
+ val newType = onType(tpe)
typeMap(name) = newType
newType
}
}
-
- def reOfModule(instance: String, ofModule: String): String = {
- renameMap.get(top.module(ofModule)) match {
- case Some(Seq(Target(_, Some(ofModuleTag), Nil))) => ofModuleTag
- case None => ofModule
- case other => throwInternalError(other.toString)
- }
- }
-
- val renamedModule = changeInternals(rename, retype, {i: Info => NoInfo}, reOfModule)(module)
- renamedModule
+ def remodule(name: String): String = tag2name(name2tag(name))
+ changeInternals(rename, retype, {i: Info => NoInfo}, remodule)(module)
}
/** Dedup a module's instances based on dedup map
*
* Will fixes up module if deduped instance's ports are differently named
*
- * @param top CircuitTarget of circuit
- * @param originalModule Module name who's instances will be deduped
+ * @param moduleName Module name who's instances will be deduped
* @param moduleMap Map of module name to its original module
* @param name2name Map of module name to the module deduping it. Not mutated in this function.
* @param renameMap Will be modified to keep track of renames in this function
* @return fixed up module deduped instances
*/
- def dedupInstances(top: CircuitTarget,
- originalModule: String,
- moduleMap: Map[String, DefModule],
- name2name: Map[String, String],
- renameMap: RenameMap): DefModule = {
- val module = moduleMap(originalModule)
+ def dedupInstances(moduleName: String, moduleMap: Map[String, DefModule], name2name: mutable.Map[String, String], renameMap: RenameMap): DefModule = {
+ val module = moduleMap(moduleName)
// If black box, return it (it has no instances)
if (module.isInstanceOf[ExtModule]) return module
@@ -219,14 +187,7 @@ object DedupModules {
moduleMap(name2name(old))
}
// Define rename functions
- def renameOfModule(instance: String, ofModule: String): String = {
- val newOfModule = name2name(ofModule)
- renameMap.record(
- top.module(originalModule).instOf(instance, ofModule),
- top.module(originalModule).instOf(instance, newOfModule)
- )
- newOfModule
- }
+ def renameModule(name: String): String = getNewModule(name).name
val typeMap = mutable.HashMap[String, Type]()
def retype(name: String)(tpe: Type): Type = {
if (typeMap.contains(name)) typeMap(name) else {
@@ -237,155 +198,96 @@ object DedupModules {
case (old, nuu) => renameMap.rename(old.serialize, nuu.serialize)
}
newType
- } else {
- tpe
- }
+ } else tpe
}
}
renameMap.setModule(module.name)
// Change module internals
- changeInternals({n => n}, retype, {i => i}, renameOfModule)(module)
+ changeInternals({n => n}, retype, {i => i}, renameModule)(module)
}
- //scalastyle:off
- /** Returns
- * 1) map of tag to all matching module names,
- * 2) renameMap of module name to tag (agnostic name)
- * 3) maps module name to agnostic renameMap
- * @param top CircuitTarget
- * @param moduleLinearization Sequence of modules from leaf to top
- * @param noDedups Set of modules to not dedup
- * @param annotations All annotations to check if annotations are identical
- * @return
+ /**
+ * Deduplicate
+ * @param circuit Circuit
+ * @param noDedups list of modules to not dedup
+ * @param renameMap rename map to populate when deduping
+ * @return Map of original Module name -> Deduped Module
*/
- def buildRTLTags(top: CircuitTarget,
- moduleLinearization: Seq[DefModule],
- noDedups: Set[String],
- annotations: Seq[Annotation]
- ): (collection.Map[String, collection.Set[String]], RenameMap, collection.Map[String, RenameMap]) = {
+ def deduplicate(circuit: Circuit,
+ noDedups: Set[String],
+ renameMap: RenameMap): Map[String, DefModule] = {
+ // Order of modules, from leaf to top
+ val moduleLinearization = new InstanceGraph(circuit).moduleOrder.map(_.name).reverse
- // Maps a module name to its agnostic name
- val tagMap = RenameMap()
+ // Maps module name to original module
+ val moduleMap = circuit.modules.map(m => m.name -> m).toMap
- // Maps a tag to all matching module names
- val tag2all = mutable.HashMap.empty[String, mutable.HashSet[String]]
+ // Maps a module's tag to its deduplicated module
+ val tag2name = mutable.HashMap.empty[String, String]
- val module2Annotations = mutable.HashMap.empty[String, mutable.HashSet[Annotation]]
- annotations.foreach { a =>
- a.getTargets.foreach { t =>
- val annos = module2Annotations.getOrElseUpdate(t.moduleOpt.get, mutable.HashSet.empty[Annotation])
- annos += a
- }
- }
+ // Maps a module's name to its tag
+ val name2tag = mutable.HashMap.empty[String, String]
+
+ // Maps a tag to all matching module names
+ val tag2all = mutable.HashMap.empty[String, mutable.Set[String]]
- val agnosticModuleMap = RenameMap()
- val agnosticRenames = mutable.HashMap[String, RenameMap]()
+ // Build dedupMap
+ moduleLinearization.foreach { moduleName =>
+ // Get original module
+ val originalModule = moduleMap(moduleName)
- moduleLinearization.foreach { originalModule =>
// Replace instance references to new deduped modules
val dontcare = RenameMap()
dontcare.setCircuit("dontcare")
-
- val agnosticRename = RenameMap.create(agnosticModuleMap.getUnderlying)
- agnosticRenames(originalModule.name) = agnosticRename
+ //val fixedModule = DedupModules.dedupInstances(originalModule, tag2module, name2tag, name2module, dontcare)
if (noDedups.contains(originalModule.name)) {
// Don't dedup. Set dedup module to be the same as fixed module
- tag2all(originalModule.name) = mutable.HashSet(originalModule.name)
+ name2tag(originalModule.name) = originalModule.name
+ tag2name(originalModule.name) = originalModule.name
+ //templateModules += originalModule.name
} else { // Try to dedup
// Build name-agnostic module
- val agnosticModule = DedupModules.agnostify(top, originalModule, agnosticRename)
- agnosticRename.record(top.module(originalModule.name), top.module("thisModule"))
- val agnosticAnnos = module2Annotations.getOrElse(
- originalModule.name, mutable.HashSet.empty[Annotation]
- ).map(_.update(agnosticRename))
- agnosticRename.delete(top.module(originalModule.name))
+ val agnosticModule = DedupModules.agnostify(originalModule, name2tag, tag2name)
// Build tag
- val builder = new mutable.ArrayBuffer[Any]()
- agnosticModule.ports.foreach { builder ++= _.serialize }
- builder ++= agnosticAnnos
-
- agnosticModule match {
- case Module(i, n, ps, b) => builder ++= b.serialize
+ val tag = (agnosticModule match {
+ case Module(i, n, ps, b) =>
+ ps.map(_.serialize).mkString + b.serialize
case ExtModule(i, n, ps, dn, p) =>
- builder ++= dn
- p.foreach { builder ++= _.serialize }
- }
- val tag = builder.hashCode().toString
+ ps.map(_.serialize).mkString + dn + p.map(_.serialize).mkString
+ }).hashCode().toString
// Match old module name to its tag
- agnosticRename.record(top.module(originalModule.name), top.module(tag))
- agnosticModuleMap.record(top.module(originalModule.name), top.module(tag))
- tagMap.record(top.module(originalModule.name), top.module(tag))
+ name2tag(originalModule.name) = tag
// Set tag's module to be the first matching module
- val all = tag2all.getOrElseUpdate(tag, mutable.HashSet.empty[String])
- all += originalModule.name
+ if (!tag2name.contains(tag)) {
+ tag2name(tag) = originalModule.name
+ tag2all(tag) = mutable.Set(originalModule.name)
+ } else {
+ tag2all(tag) += originalModule.name
+ }
}
}
- (tag2all, tagMap, agnosticRenames)
- }
- //scalastyle:on
- /** Deduplicate
- * @param circuit Circuit
- * @param noDedups list of modules to not dedup
- * @param renameMap rename map to populate when deduping
- * @return Map of original Module name -> Deduped Module
- */
- def deduplicate(circuit: Circuit,
- noDedups: Set[String],
- annotations: Seq[Annotation],
- renameMap: RenameMap): Map[String, DefModule] = {
-
- val (moduleMap, moduleLinearization) = {
- val iGraph = new InstanceGraph(circuit)
- (iGraph.moduleMap, iGraph.moduleOrder.reverse)
- }
- val top = CircuitTarget(circuit.main)
-
- val (tag2all, tagMap, agnosticRenames) = buildRTLTags(top, moduleLinearization, noDedups, annotations)
// Set tag2name to be the best dedup module name
val moduleIndex = circuit.modules.zipWithIndex.map{case (m, i) => m.name -> i}.toMap
def order(l: String, r: String): String = if (moduleIndex(l) < moduleIndex(r)) l else r
-
- // Maps a module's tag to its deduplicated module
- val tag2name = mutable.HashMap.empty[String, String]
tag2all.foreach { case (tag, all) => tag2name(tag) = all.reduce(order)}
// Create map from original to dedup name
- val name2name = moduleMap.keysIterator.map{ originalModule =>
- tagMap.get(top.module(originalModule)) match {
- case Some(Seq(Target(_, Some(tag), Nil))) => originalModule -> tag2name(tag)
- case None => originalModule -> originalModule
- case other => throwInternalError(other.toString)
- }
- }.toMap
+ val name2name = name2tag.map({ case (name, tag) => name -> tag2name(tag) })
// Build Remap for modules with deduped module references
- val dedupedName2module = tag2name.map({ case (tag, name) => name -> DedupModules.dedupInstances(top, name, moduleMap, name2name, renameMap) })
+ val tag2module = tag2name.map({ case (tag, name) => tag -> DedupModules.dedupInstances(name, moduleMap, name2name, renameMap) })
// Build map from original name to corresponding deduped module
- val name2module = tag2all.flatMap({ case (tag, names) => names.map(n => n -> dedupedName2module(tag2name(tag))) })
-
- val reversedAgnosticRenames = mutable.HashMap[String, RenameMap]()
- name2module.foreach { case (originalModuleName, dedupedModule) =>
- if(!reversedAgnosticRenames.contains(dedupedModule.name)) {
- reversedAgnosticRenames(dedupedModule.name) = agnosticRenames(dedupedModule.name).getReverseRenameMap
- }
- agnosticRenames(originalModuleName).keys.foreach { key =>
- if(key.isInstanceOf[IsComponent]) {
- val tag = agnosticRenames(originalModuleName)(key).head
- val newKey = reversedAgnosticRenames(dedupedModule.name).apply(tag)
- renameMap.record(key.asInstanceOf[IsMember], newKey.asInstanceOf[Seq[IsMember]])
- }
- }
- }
+ val name2module = name2tag.map({ case (name, tag) => name -> tag2module(tag) })
name2module.toMap
}
diff --git a/src/main/scala/firrtl/transforms/OptimizationAnnotations.scala b/src/main/scala/firrtl/transforms/OptimizationAnnotations.scala
index a66bd4ce..fab540da 100644
--- a/src/main/scala/firrtl/transforms/OptimizationAnnotations.scala
+++ b/src/main/scala/firrtl/transforms/OptimizationAnnotations.scala
@@ -4,7 +4,6 @@ package transforms
import firrtl.annotations._
import firrtl.passes.PassException
-import firrtl.transforms
/** Indicate that DCE should not be run */
case object NoDCEAnnotation extends NoTargetAnnotation
@@ -13,14 +12,13 @@ case object NoDCEAnnotation extends NoTargetAnnotation
*
* DCE treats the component as a top-level sink of the circuit
*/
-case class DontTouchAnnotation(target: ReferenceTarget) extends SingleTargetAnnotation[ReferenceTarget] {
- def targets = Seq(target)
- def duplicate(n: ReferenceTarget) = this.copy(n)
+case class DontTouchAnnotation(target: ComponentName) extends SingleTargetAnnotation[ComponentName] {
+ def duplicate(n: ComponentName) = this.copy(n)
}
object DontTouchAnnotation {
class DontTouchNotFoundException(module: String, component: String) extends PassException(
- s"Target marked dontTouch ($module.$component) not found!\n" +
+ s"Component marked dontTouch ($module.$component) not found!\n" +
"It was probably accidentally deleted. Please check that your custom transforms are not" +
"responsible and then file an issue on Github."
)