diff options
| author | Albert Chen | 2020-04-10 20:12:19 -0700 |
|---|---|---|
| committer | GitHub | 2020-04-11 03:12:19 +0000 |
| commit | eb52a5c6aafab90bf923bc9a7904fc8daf983ad4 (patch) | |
| tree | 4631afb66934c9a946f2159936a7cd6df16ad4bd /src | |
| parent | 54ff9451f285cc18bca0ab519e013ff8326538b8 (diff) | |
EliminateTargetPaths: don't duplicate modules with only one instance (#1504)
* EliminateTargetPaths: add lone instance test cases
* EliminateTargetPaths: don't rename lone instances
* get rid of trailing comma
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/annotations/transforms/EliminateTargetPaths.scala | 46 | ||||
| -rw-r--r-- | src/test/scala/firrtlTests/annotationTests/EliminateTargetPathsSpec.scala | 62 |
2 files changed, 104 insertions, 4 deletions
diff --git a/src/main/scala/firrtl/annotations/transforms/EliminateTargetPaths.scala b/src/main/scala/firrtl/annotations/transforms/EliminateTargetPaths.scala index e741a32b..00f2ad6a 100644 --- a/src/main/scala/firrtl/annotations/transforms/EliminateTargetPaths.scala +++ b/src/main/scala/firrtl/annotations/transforms/EliminateTargetPaths.scala @@ -155,7 +155,51 @@ class EliminateTargetPaths extends Transform { throw NoSuchTargetException(s"""Some targets have illegal paths that cannot be resolved/eliminated: $string""") } - val (newCircuit, renameMap) = run(state.circuit, targets) + // get rid of path prefixes of modules with only one instance so we don't rename them + val isSingleInstMod: String => Boolean = { + val cache = mutable.Map.empty[String, Boolean] + mod => cache.getOrElseUpdate(mod, iGraph.findInstancesInHierarchy(mod).size == 1) + } + val firstRenameMap = RenameMap() + val nonSingletonTargets = targets.foldLeft(Seq.empty[IsMember]) { + case (acc, t: IsComponent) if t.asPath.nonEmpty => + val origPath = t.asPath + val (singletonPrefix, rest) = origPath.partition { + case (_, OfModule(mod)) => + isSingleInstMod(mod) + } + + if (singletonPrefix.size > 0) { + val module = singletonPrefix.last._2.value + val circuit = t.circuit + val newIsModule = + if (rest.isEmpty) { + ModuleTarget(circuit, module) + } else { + val (Instance(inst), OfModule(ofMod)) = rest.last + val path = rest.dropRight(1) + InstanceTarget(circuit, module, path, inst, ofMod) + } + val newTarget = t match { + case r: ReferenceTarget => r.setPathTarget(newIsModule) + case i: InstanceTarget => newIsModule + } + firstRenameMap.record(t, Seq(newTarget)) + newTarget +: acc + } else { + t +: acc + } + case (acc, t) => t +: acc + } + + val (newCircuit, nextRenameMap) = run(state.circuit, nonSingletonTargets) + + val renameMap = + if (firstRenameMap.hasChanges) { + firstRenameMap andThen nextRenameMap + } else { + nextRenameMap + } val iGraphx = new InstanceGraph(newCircuit) val newlyUnreachableModules = iGraphx.unreachableModules diff iGraph.unreachableModules diff --git a/src/test/scala/firrtlTests/annotationTests/EliminateTargetPathsSpec.scala b/src/test/scala/firrtlTests/annotationTests/EliminateTargetPathsSpec.scala index 5b610890..ba8f1698 100644 --- a/src/test/scala/firrtlTests/annotationTests/EliminateTargetPathsSpec.scala +++ b/src/test/scala/firrtlTests/annotationTests/EliminateTargetPathsSpec.scala @@ -402,20 +402,76 @@ class EliminateTargetPathsSpec extends FirrtlPropSpec with FirrtlMatchers { val input = """|circuit Foo: | module Baz: - | skip + | node foo = UInt<1>(0) | module Bar: + | node foo = UInt<1>(0) | inst baz of Baz | skip | module Foo: + | node foo = UInt<1>(0) | inst bar of Bar |""".stripMargin val targets = Seq( - CircuitTarget("Foo").module("Foo").instOf("bar", "Bar").instOf("baz", "Baz") + CircuitTarget("Foo").module("Foo").instOf("bar", "Bar").instOf("baz", "Baz"), + CircuitTarget("Foo").module("Foo").instOf("bar", "Bar"), + CircuitTarget("Foo").module("Foo") ) - val output = CircuitState(passes.ToWorkingIR.run(Parser.parse(input)), UnknownForm, Nil) + val dontTouches = targets.map(t => DontTouchAnnotation(t.ref("foo"))) + val inputCircuit = Parser.parse(input) + val output = CircuitState(passes.ToWorkingIR.run(inputCircuit), UnknownForm, dontTouches) .resolvePaths(targets) info(output.circuit.serialize) + output.circuit.serialize should be (inputCircuit.serialize) + output.annotations.collect { + case a: DontTouchAnnotation => a + } should contain allOf ( + DontTouchAnnotation(ModuleTarget("Foo", "Foo").ref("foo")), + DontTouchAnnotation(ModuleTarget("Foo", "Bar").ref("foo")), + DontTouchAnnotation(ModuleTarget("Foo", "Baz").ref("foo")) + ) + } + + property("It should not rename parent lone instances but still rename children") { + val input = + """|circuit FooBar: + | module Bar: + | node baz = UInt<1>(0) + | module FooBar: + | inst foo of Foo + | module Foo: + | inst bar of Bar + | inst barBar of Bar + |""".stripMargin + + // modules Foo and FooBar should not be renamed + val checks = + """circuit FooBar : + | module Foo : + | module FooBar : + | inst foo of Foo""".stripMargin.split("\n") + + val targets = Seq( + CircuitTarget("FooBar").module("FooBar").instOf("foo", "Foo").instOf("bar", "Bar"), + CircuitTarget("FooBar").module("FooBar").instOf("foo", "Foo").instOf("barBar", "Bar") + ) + val dontTouches = targets.map(t => DontTouchAnnotation(t.ref("baz"))) + val output = CircuitState(passes.ToWorkingIR.run(Parser.parse(input)), UnknownForm, dontTouches) + .resolvePaths(targets) + + info(output.circuit.serialize) + + val outputLines = output.circuit.serialize.split("\n") + checks.foreach { line => + outputLines should contain (line) + } + + output.annotations.collect { + case a: DontTouchAnnotation => a + } should contain allOf ( + DontTouchAnnotation(ModuleTarget("FooBar", "Bar___Foo_bar").ref("baz")), + DontTouchAnnotation(ModuleTarget("FooBar", "Bar___Foo_barBar").ref("baz")) + ) } } |
