diff options
| author | Adam Izraelevitz | 2018-10-27 22:44:00 -0700 |
|---|---|---|
| committer | GitHub | 2018-10-27 22:44:00 -0700 |
| commit | 223bad6d9ddd93e48678da7c3ab50b6656809157 (patch) | |
| tree | bf9efdcd7e1c8fb50175686810531be07747e8a9 /src/main/scala/firrtl/transforms/Dedup.scala | |
| parent | 7e2f787e125227dc389d5cf1d09717748ecfed2e (diff) | |
Revert "Instance Annotations (#865)" (#925)
This reverts commit 7e2f787e125227dc389d5cf1d09717748ecfed2e.
Diffstat (limited to 'src/main/scala/firrtl/transforms/Dedup.scala')
| -rw-r--r-- | src/main/scala/firrtl/transforms/Dedup.scala | 266 |
1 files changed, 84 insertions, 182 deletions
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 } |
