diff options
Diffstat (limited to 'src/main/scala/firrtl/RenameMap.scala')
| -rw-r--r-- | src/main/scala/firrtl/RenameMap.scala | 273 |
1 files changed, 147 insertions, 126 deletions
diff --git a/src/main/scala/firrtl/RenameMap.scala b/src/main/scala/firrtl/RenameMap.scala index 9c848bca..d85998b5 100644 --- a/src/main/scala/firrtl/RenameMap.scala +++ b/src/main/scala/firrtl/RenameMap.scala @@ -38,9 +38,9 @@ object RenameMap { */ // TODO This should probably be refactored into immutable and mutable versions final class RenameMap private ( - val underlying: mutable.HashMap[CompleteTarget, Seq[CompleteTarget]] = mutable.HashMap[CompleteTarget, Seq[CompleteTarget]](), - val chained: Option[RenameMap] = None -) { + val underlying: mutable.HashMap[CompleteTarget, Seq[CompleteTarget]] = + mutable.HashMap[CompleteTarget, Seq[CompleteTarget]](), + val chained: Option[RenameMap] = None) { /** Chain a [[RenameMap]] with this [[RenameMap]] * @param next the map to chain with this map @@ -100,7 +100,7 @@ final class RenameMap private ( * $noteDistinct */ def recordAll(map: collection.Map[CompleteTarget, Seq[CompleteTarget]]): Unit = - map.foreach{ + map.foreach { case (from: IsComponent, tos: Seq[_]) => completeRename(from, tos) case (from: IsModule, tos: Seq[_]) => completeRename(from, tos) case (from: CircuitTarget, tos: Seq[_]) => completeRename(from, tos) @@ -128,7 +128,7 @@ final class RenameMap private ( * @param key Target referencing the original circuit * @return Optionally return sequence of targets that key remaps to */ - def get(key: CircuitTarget): Option[Seq[CircuitTarget]] = completeGet(key).map( _.map { case x: CircuitTarget => x } ) + def get(key: CircuitTarget): Option[Seq[CircuitTarget]] = completeGet(key).map(_.map { case x: CircuitTarget => x }) /** Get renames of a [[firrtl.annotations.IsMember IsMember]] * @param key Target referencing the original member of the circuit @@ -136,12 +136,11 @@ final class RenameMap private ( */ def get(key: IsMember): Option[Seq[IsMember]] = completeGet(key).map { _.map { case x: IsMember => x } } - /** Create new [[RenameMap]] that merges this and renameMap * @param renameMap * @return */ - def ++ (renameMap: RenameMap): RenameMap = { + def ++(renameMap: RenameMap): RenameMap = { val newChained = if (chained.nonEmpty && renameMap.chained.nonEmpty) { Some(chained.get ++ renameMap.chained.get) } else { @@ -168,7 +167,7 @@ final class RenameMap private ( def getReverseRenameMap: RenameMap = { val reverseMap = mutable.HashMap[CompleteTarget, Seq[CompleteTarget]]() - underlying.keysIterator.foreach{ key => + underlying.keysIterator.foreach { key => apply(key).foreach { v => reverseMap(v) = key +: reverseMap.getOrElse(v, Nil) } @@ -181,8 +180,9 @@ final class RenameMap private ( /** Serialize the underlying remapping of keys to new targets * @return */ - def serialize: String = underlying.map { case (k, v) => - k.serialize + "=>" + v.map(_.serialize).mkString(", ") + def serialize: String = underlying.map { + case (k, v) => + k.serialize + "=>" + v.map(_.serialize).mkString(", ") }.mkString("\n") /** Records which local InstanceTargets will require modification. @@ -229,7 +229,8 @@ final class RenameMap private ( val hereRet = (chainedRet.flatMap { target => hereCompleteGet(target).getOrElse(Seq(target)) }).distinct - if (hereRet.size == 1 && hereRet.head == key) { None } else { Some(hereRet) } + if (hereRet.size == 1 && hereRet.head == key) { None } + else { Some(hereRet) } } } else { hereCompleteGet(key) @@ -238,10 +239,11 @@ final class RenameMap private ( private def hereCompleteGet(key: CompleteTarget): Option[Seq[CompleteTarget]] = { val errors = mutable.ArrayBuffer[String]() - val ret = if(hasChanges) { + val ret = if (hasChanges) { val ret = recursiveGet(errors)(key) - if(errors.nonEmpty) { throw IllegalRenameException(errors.mkString("\n")) } - if(ret.size == 1 && ret.head == key) { None } else { Some(ret) } + if (errors.nonEmpty) { throw IllegalRenameException(errors.mkString("\n")) } + if (ret.size == 1 && ret.head == key) { None } + else { Some(ret) } } else { None } ret } @@ -266,50 +268,54 @@ final class RenameMap private ( * @return Renamed targets if a match is found, otherwise None */ private def referenceGet(errors: mutable.ArrayBuffer[String])(key: ReferenceTarget): Option[Seq[IsComponent]] = { - def traverseTokens(key: ReferenceTarget): Option[Seq[IsComponent]] = traverseTokensCache.getOrElseUpdate(key, { - if (underlying.contains(key)) { - Some(underlying(key).flatMap { - case comp: IsComponent => Some(comp) - case other => - errors += s"reference ${key.targetParent} cannot be renamed to a non-component ${other}" - None - }) - } else { - key match { - case t: ReferenceTarget if t.component.nonEmpty => - val last = t.component.last - val parent = t.copy(component = t.component.dropRight(1)) - traverseTokens(parent).map(_.flatMap { x => - (x, last) match { - case (t2: InstanceTarget, Field(f)) => Some(t2.ref(f)) - case (t2: ReferenceTarget, Field(f)) => Some(t2.field(f)) - case (t2: ReferenceTarget, Index(i)) => Some(t2.index(i)) - case other => - errors += s"Illegal rename: ${key.targetParent} cannot be renamed to ${other._1} - must rename $key directly" - None - } - }) - case t: ReferenceTarget => None + def traverseTokens(key: ReferenceTarget): Option[Seq[IsComponent]] = traverseTokensCache.getOrElseUpdate( + key, { + if (underlying.contains(key)) { + Some(underlying(key).flatMap { + case comp: IsComponent => Some(comp) + case other => + errors += s"reference ${key.targetParent} cannot be renamed to a non-component ${other}" + None + }) + } else { + key match { + case t: ReferenceTarget if t.component.nonEmpty => + val last = t.component.last + val parent = t.copy(component = t.component.dropRight(1)) + traverseTokens(parent).map(_.flatMap { x => + (x, last) match { + case (t2: InstanceTarget, Field(f)) => Some(t2.ref(f)) + case (t2: ReferenceTarget, Field(f)) => Some(t2.field(f)) + case (t2: ReferenceTarget, Index(i)) => Some(t2.index(i)) + case other => + errors += s"Illegal rename: ${key.targetParent} cannot be renamed to ${other._1} - must rename $key directly" + None + } + }) + case t: ReferenceTarget => None + } } } - }) - - def traverseHierarchy(key: ReferenceTarget): Option[Seq[IsComponent]] = traverseHierarchyCache.getOrElseUpdate(key, { - val tokenRenamed = traverseTokens(key) - if (tokenRenamed.nonEmpty) { - tokenRenamed - } else { - key match { - case t: ReferenceTarget if t.isLocal => None - case t: ReferenceTarget => - val encapsulatingInstance = t.path.head._1.value - val stripped = t.stripHierarchy(1) - traverseHierarchy(stripped).map(_.map { - _.addHierarchy(t.module, encapsulatingInstance) - }) + ) + + def traverseHierarchy(key: ReferenceTarget): Option[Seq[IsComponent]] = traverseHierarchyCache.getOrElseUpdate( + key, { + val tokenRenamed = traverseTokens(key) + if (tokenRenamed.nonEmpty) { + tokenRenamed + } else { + key match { + case t: ReferenceTarget if t.isLocal => None + case t: ReferenceTarget => + val encapsulatingInstance = t.path.head._1.value + val stripped = t.stripHierarchy(1) + traverseHierarchy(stripped).map(_.map { + _.addHierarchy(t.module, encapsulatingInstance) + }) + } } } - }) + ) traverseHierarchy(key) } @@ -335,64 +341,73 @@ final class RenameMap private ( * @return Renamed targets if a match is found, otherwise None */ private def instanceGet(errors: mutable.ArrayBuffer[String])(key: InstanceTarget): Option[Seq[IsModule]] = { - def traverseLeft(key: InstanceTarget): Option[Seq[IsModule]] = traverseLeftCache.getOrElseUpdate(key, { - val getOpt = underlying.get(key) - - if (getOpt.nonEmpty) { - getOpt.map(_.flatMap { - case isMod: IsModule => Some(isMod) - case other => - errors += s"IsModule: $key cannot be renamed to non-IsModule $other" - None - }) - } else { - key match { - case t: InstanceTarget if t.isLocal => None - case t: InstanceTarget => - val (Instance(outerInst), OfModule(outerMod)) = t.path.head - val stripped = t.copy(path = t.path.tail, module = outerMod) - traverseLeft(stripped).map(_.map { - case absolute if absolute.circuit == absolute.module => absolute - case relative => relative.addHierarchy(t.module, outerInst) - }) + def traverseLeft(key: InstanceTarget): Option[Seq[IsModule]] = traverseLeftCache.getOrElseUpdate( + key, { + val getOpt = underlying.get(key) + + if (getOpt.nonEmpty) { + getOpt.map(_.flatMap { + case isMod: IsModule => Some(isMod) + case other => + errors += s"IsModule: $key cannot be renamed to non-IsModule $other" + None + }) + } else { + key match { + case t: InstanceTarget if t.isLocal => None + case t: InstanceTarget => + val (Instance(outerInst), OfModule(outerMod)) = t.path.head + val stripped = t.copy(path = t.path.tail, module = outerMod) + traverseLeft(stripped).map(_.map { + case absolute if absolute.circuit == absolute.module => absolute + case relative => relative.addHierarchy(t.module, outerInst) + }) + } } } - }) - - def traverseRight(key: InstanceTarget): Option[Seq[IsModule]] = traverseRightCache.getOrElseUpdate(key, { - val findLeft = traverseLeft(key) - if (findLeft.isDefined) { - findLeft - } else { - key match { - case t: InstanceTarget if t.isLocal => None - case t: InstanceTarget => - val (Instance(i), OfModule(m)) = t.path.last - val parent = t.copy(path = t.path.dropRight(1), instance = i, ofModule = m) - traverseRight(parent).map(_.map(_.instOf(t.instance, t.ofModule))) + ) + + def traverseRight(key: InstanceTarget): Option[Seq[IsModule]] = traverseRightCache.getOrElseUpdate( + key, { + val findLeft = traverseLeft(key) + if (findLeft.isDefined) { + findLeft + } else { + key match { + case t: InstanceTarget if t.isLocal => None + case t: InstanceTarget => + val (Instance(i), OfModule(m)) = t.path.last + val parent = t.copy(path = t.path.dropRight(1), instance = i, ofModule = m) + traverseRight(parent).map(_.map(_.instOf(t.instance, t.ofModule))) + } } } - }) + ) traverseRight(key) } private def circuitGet(errors: mutable.ArrayBuffer[String])(key: CircuitTarget): Seq[CircuitTarget] = { - underlying.get(key).map(_.flatMap { - case c: CircuitTarget => Some(c) - case other => - errors += s"Illegal rename: $key cannot be renamed to non-circuit target: $other" - None - }).getOrElse(Seq(key)) + underlying + .get(key) + .map(_.flatMap { + case c: CircuitTarget => Some(c) + case other => + errors += s"Illegal rename: $key cannot be renamed to non-circuit target: $other" + None + }) + .getOrElse(Seq(key)) } private def moduleGet(errors: mutable.ArrayBuffer[String])(key: ModuleTarget): Option[Seq[IsModule]] = { - underlying.get(key).map(_.flatMap { - case mod: IsModule => Some(mod) - case other => - errors += s"Illegal rename: $key cannot be renamed to non-module target: $other" - None - }) + underlying + .get(key) + .map(_.flatMap { + case mod: IsModule => Some(mod) + case other => + errors += s"Illegal rename: $key cannot be renamed to non-module target: $other" + None + }) } // the possible results returned by ofModuleGet @@ -438,10 +453,11 @@ final class RenameMap private ( private def ofModuleGet(errors: mutable.ArrayBuffer[String])(key: IsComponent): OfModuleRenameResult = { val circuit = key.circuit def renameOfModules( - path: Seq[(Instance, OfModule)], - foundRename: Boolean, + path: Seq[(Instance, OfModule)], + foundRename: Boolean, newCircuitOpt: Option[String], - children: Seq[(Instance, OfModule)]): OfModuleRenameResult = { + children: Seq[(Instance, OfModule)] + ): OfModuleRenameResult = { if (path.isEmpty && foundRename) { RenamedOfModules(children) } else if (path.isEmpty) { @@ -489,15 +505,15 @@ final class RenameMap private ( * @return Renamed targets */ private def recursiveGet(errors: mutable.ArrayBuffer[String])(key: CompleteTarget): Seq[CompleteTarget] = { - if(getCache.contains(key)) { + if (getCache.contains(key)) { getCache(key) } else { // rename just the component portion; path/ref/component for ReferenceTargets or path/instance for InstanceTargets val componentRename = key match { - case t: CircuitTarget => None - case t: ModuleTarget => None - case t: InstanceTarget => instanceGet(errors)(t) + case t: CircuitTarget => None + case t: ModuleTarget => None + case t: InstanceTarget => instanceGet(errors)(t) case ref: ReferenceTarget if ref.isLocal => referenceGet(errors)(ref) case ref @ ReferenceTarget(c, m, p, r, t) => val (Instance(inst), OfModule(ofMod)) = p.last @@ -510,7 +526,6 @@ final class RenameMap private ( } } - // if no component rename was found, look for Module renames; root module/OfModules in path val moduleRename = if (componentRename.isDefined) { componentRename @@ -522,7 +537,8 @@ final class RenameMap private ( ofModuleGet(errors)(t) match { case AbsoluteOfModule(absolute) => t match { - case ref: ReferenceTarget => Some(Seq(ref.copy(circuit = absolute.circuit, module = absolute.module, path = absolute.asPath))) + case ref: ReferenceTarget => + Some(Seq(ref.copy(circuit = absolute.circuit, module = absolute.module, path = absolute.asPath))) case inst: InstanceTarget => Some(Seq(absolute)) } case RenamedOfModules(children) => @@ -532,14 +548,16 @@ final class RenameMap private ( val newPath = mod.asPath ++ children t match { - case ref: ReferenceTarget => ref.copy(circuit = mod.circuit, module = mod.module, path = newPath) + case ref: ReferenceTarget => ref.copy(circuit = mod.circuit, module = mod.module, path = newPath) case inst: InstanceTarget => val (Instance(newInst), OfModule(newOfMod)) = newPath.last - inst.copy(circuit = mod.circuit, + inst.copy( + circuit = mod.circuit, module = mod.module, path = newPath.dropRight(1), instance = newInst, - ofModule = newOfMod) + ofModule = newOfMod + ) } } Some(result) @@ -551,14 +569,16 @@ final class RenameMap private ( val newPath = mod.asPath ++ children t match { - case ref: ReferenceTarget => ref.copy(circuit = mod.circuit, module = mod.module, path = newPath) + case ref: ReferenceTarget => ref.copy(circuit = mod.circuit, module = mod.module, path = newPath) case inst: InstanceTarget => val (Instance(newInst), OfModule(newOfMod)) = newPath.last - inst.copy(circuit = mod.circuit, + inst.copy( + circuit = mod.circuit, module = mod.module, path = newPath.dropRight(1), instance = newInst, - ofModule = newOfMod) + ofModule = newOfMod + ) } }) } @@ -579,8 +599,8 @@ final class RenameMap private ( circuitGet(errors)(CircuitTarget(t.circuit)).map { case CircuitTarget(c) => t match { - case ref: ReferenceTarget => ref.copy(circuit = c) - case inst: InstanceTarget => inst.copy(circuit = c) + case ref: ReferenceTarget => ref.copy(circuit = c) + case inst: InstanceTarget => inst.copy(circuit = c) } } } @@ -597,7 +617,7 @@ final class RenameMap private ( * @param tos */ private def completeRename(from: CompleteTarget, tos: Seq[CompleteTarget]): Unit = { - tos.foreach{recordSensitivity(from, _)} + tos.foreach { recordSensitivity(from, _) } val existing = underlying.getOrElse(from, Vector.empty) val updated = (existing ++ tos).distinct underlying(from) = updated @@ -625,29 +645,30 @@ final class RenameMap private ( def delete(name: ComponentName): Unit = underlying(name) = Seq.empty def addMap(map: collection.Map[Named, Seq[Named]]): Unit = - recordAll(map.map { case (key, values) => (Target.convertNamed2Target(key), values.map(Target.convertNamed2Target)) }) + recordAll(map.map { + case (key, values) => (Target.convertNamed2Target(key), values.map(Target.convertNamed2Target)) + }) def get(key: CircuitName): Option[Seq[CircuitName]] = { - get(Target.convertCircuitName2CircuitTarget(key)).map(_.collect{ case c: CircuitTarget => c.toNamed }) + get(Target.convertCircuitName2CircuitTarget(key)).map(_.collect { case c: CircuitTarget => c.toNamed }) } def get(key: ModuleName): Option[Seq[ModuleName]] = { - get(Target.convertModuleName2ModuleTarget(key)).map(_.collect{ case m: ModuleTarget => m.toNamed }) + get(Target.convertModuleName2ModuleTarget(key)).map(_.collect { case m: ModuleTarget => m.toNamed }) } def get(key: ComponentName): Option[Seq[ComponentName]] = { - get(Target.convertComponentName2ReferenceTarget(key)).map(_.collect{ case c: IsComponent => c.toNamed }) + get(Target.convertComponentName2ReferenceTarget(key)).map(_.collect { case c: IsComponent => c.toNamed }) } def get(key: Named): Option[Seq[Named]] = key match { case t: CompleteTarget => get(t) - case other => get(key.toTarget).map(_.collect{ case c: IsComponent => c.toNamed }) + case other => get(key.toTarget).map(_.collect { case c: IsComponent => c.toNamed }) } - // Mutable helpers - APIs that set these are deprecated! private var circuitName: String = "" - private var moduleName: String = "" + private var moduleName: String = "" /** Sets mutable state to record current module we are visiting * @param module @@ -673,7 +694,7 @@ final class RenameMap private ( def rename(from: String, tos: Seq[String]): Unit = { val mn = ModuleName(moduleName, CircuitName(circuitName)) val fromName = ComponentName(from, mn).toTarget - val tosName = tos map { to => ComponentName(to, mn).toTarget } + val tosName = tos.map { to => ComponentName(to, mn).toTarget } record(fromName, tosName) } |
