aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/firrtlTests/MutableRenameMapSpec.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/scala/firrtlTests/MutableRenameMapSpec.scala')
-rw-r--r--src/test/scala/firrtlTests/MutableRenameMapSpec.scala877
1 files changed, 877 insertions, 0 deletions
diff --git a/src/test/scala/firrtlTests/MutableRenameMapSpec.scala b/src/test/scala/firrtlTests/MutableRenameMapSpec.scala
new file mode 100644
index 00000000..f8997b36
--- /dev/null
+++ b/src/test/scala/firrtlTests/MutableRenameMapSpec.scala
@@ -0,0 +1,877 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package firrtlTests
+
+import firrtl.RenameMap
+import firrtl.renamemap.MutableRenameMap
+import firrtl.RenameMap.IllegalRenameException
+import firrtl.annotations._
+import firrtl.annotations.TargetToken.{Instance, OfModule}
+import firrtl.analyses.InstanceKeyGraph
+import firrtl.testutils._
+
+class MutableRenameMapSpec extends FirrtlFlatSpec {
+ val cir = CircuitTarget("Top")
+ val cir2 = CircuitTarget("Pot")
+ val cir3 = CircuitTarget("Cir3")
+ val modA = cir.module("A")
+ val modA2 = cir2.module("A")
+ val modB = cir.module("B")
+ val foo = modA.ref("foo")
+ val foo2 = modA2.ref("foo")
+ val bar = modA.ref("bar")
+ val fizz = modA.ref("fizz")
+ val fooB = modB.ref("foo")
+ val barB = modB.ref("bar")
+
+ val tmb = cir.module("Top").instOf("mid", "Middle").instOf("bot", "Bottom")
+ val tm2b = cir.module("Top").instOf("mid", "Middle2").instOf("bot", "Bottom")
+ val middle = cir.module("Middle")
+ val middle2 = cir.module("Middle2")
+
+ behavior.of("RenameMap")
+
+ it should "return None if it does not rename something" in {
+ val renames = MutableRenameMap()
+ renames.get(modA) should be(None)
+ renames.get(foo) should be(None)
+ }
+
+ it should "return a Seq of renamed things if it does rename something" in {
+ val renames = MutableRenameMap()
+ renames.record(foo, bar)
+ renames.get(foo) should be(Some(Seq(bar)))
+ }
+
+ it should "allow something to be renamed to multiple things" in {
+ val renames = MutableRenameMap()
+ renames.record(foo, bar)
+ renames.record(foo, fizz)
+ renames.get(foo) should be(Some(Seq(bar, fizz)))
+ }
+
+ it should "allow something to be renamed to nothing (ie. deleted)" in {
+ val renames = MutableRenameMap()
+ renames.record(foo, Seq())
+ renames.get(foo) should be(Some(Seq()))
+ }
+
+ it should "return None if something is renamed to itself" in {
+ val renames = MutableRenameMap()
+ renames.record(foo, foo)
+ renames.get(foo) should be(None)
+ }
+
+ it should "allow targets to change module" in {
+ val renames = MutableRenameMap()
+ renames.record(foo, fooB)
+ renames.get(foo) should be(Some(Seq(fooB)))
+ }
+
+ it should "rename targets if their module is renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(modA, modB)
+ renames.get(foo) should be(Some(Seq(fooB)))
+ renames.get(bar) should be(Some(Seq(barB)))
+ }
+
+ it should "not rename already renamed targets if the module of the target is renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(modA, modB)
+ renames.record(foo, bar)
+ renames.get(foo) should be(Some(Seq(bar)))
+ }
+
+ it should "rename modules if their circuit is renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(cir, cir2)
+ renames.get(modA) should be(Some(Seq(modA2)))
+ }
+
+ it should "rename targets if their circuit is renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(cir, cir2)
+ renames.get(foo) should be(Some(Seq(foo2)))
+ }
+
+ val TopCircuit = cir
+ val Top = cir.module("Top")
+ val Top_m = Top.instOf("m", "Middle")
+ val Top_m_l = Top_m.instOf("l", "Leaf")
+ val Top_m_l_a = Top_m_l.ref("a")
+ val Top_m_la = Top_m.ref("l").field("a")
+ val Middle = cir.module("Middle")
+ val Middle2 = cir.module("Middle2")
+ val Middle_la = Middle.ref("l").field("a")
+ val Middle_l_a = Middle.instOf("l", "Leaf").ref("a")
+
+ it should "rename targets if modules in the path are renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(Middle, Middle2)
+ renames.get(Top_m) should be(Some(Seq(Top.instOf("m", "Middle2"))))
+ }
+
+ it should "rename only the instance if instance and module in the path are renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(Middle, Middle2)
+ renames.record(Top.instOf("m", "Middle"), Top.instOf("m2", "Middle"))
+ renames.get(Top_m) should be(Some(Seq(Top.instOf("m2", "Middle"))))
+ }
+
+ it should "rename targets if instance in the path are renamed" in {
+ val renames = MutableRenameMap()
+ renames.record(Top.instOf("m", "Middle"), Top.instOf("m2", "Middle"))
+ renames.get(Top_m) should be(Some(Seq(Top.instOf("m2", "Middle"))))
+ }
+
+ it should "rename targets if instance and ofmodule in the path are renamed" in {
+ val renames = MutableRenameMap()
+ val Top_m2 = Top.instOf("m2", "Middle2")
+ renames.record(Top_m, Top_m2)
+ renames.get(Top_m) should be(Some(Seq(Top_m2)))
+ }
+
+ it should "properly do nothing if no remaps" in {
+ val renames = MutableRenameMap()
+ renames.get(Top_m_l_a) should be(None)
+ }
+
+ it should "properly rename if leaf is inlined" in {
+ val renames = MutableRenameMap()
+ renames.record(Middle_l_a, Middle_la)
+ renames.get(Top_m_l_a) should be(Some(Seq(Top_m_la)))
+ }
+
+ it should "properly rename if middle is inlined" in {
+ val renames = MutableRenameMap()
+ renames.record(Top_m_l, Top.instOf("m_l", "Leaf"))
+ renames.get(Top_m_l_a) should be(Some(Seq(Top.instOf("m_l", "Leaf").ref("a"))))
+ }
+
+ it should "properly rename if leaf and middle are inlined" in {
+ val renames = MutableRenameMap()
+ val inlined = Top.ref("m_l_a")
+ renames.record(Top_m_l_a, inlined)
+ renames.record(Top_m_l, Nil)
+ renames.record(Top_m, Nil)
+ renames.get(Top_m_l_a) should be(Some(Seq(inlined)))
+ }
+
+ it should "quickly rename a target with a long path" in {
+ (0 until 50 by 10).foreach { endIdx =>
+ val renames = MutableRenameMap()
+ renames.record(TopCircuit.module("Y0"), TopCircuit.module("X0"))
+ val deepTarget = (0 until endIdx)
+ .foldLeft(Top: IsModule) { (t, idx) =>
+ t.instOf("a", "A" + idx)
+ }
+ .ref("ref")
+ val (millis, rename) = firrtl.Utils.time(renames.get(deepTarget))
+ //rename should be(None)
+ }
+ }
+
+ it should "rename only once with multiple renames" in {
+ val renames = MutableRenameMap()
+ val Middle2 = cir.module("Middle2")
+ renames.record(Middle, Middle2)
+ renames.record(Middle.ref("l"), Middle.ref("lx"))
+ renames.get(Middle.ref("l")) should be(Some(Seq(Middle.ref("lx"))))
+ }
+
+ it should "rename with fields" in {
+ val Middle_o = Middle.ref("o")
+ val Middle_i = Middle.ref("i")
+ val Middle_o_f = Middle.ref("o").field("f")
+ val Middle_i_f = Middle.ref("i").field("f")
+ val renames = MutableRenameMap()
+ renames.record(Middle_o, Middle_i)
+ renames.get(Middle_o_f) should be(Some(Seq(Middle_i_f)))
+ }
+
+ it should "rename instances with same ofModule" in {
+ val Middle_o = Middle.instOf("o", "O")
+ val Middle_i = Middle.instOf("i", "O")
+ val renames = MutableRenameMap()
+ renames.record(Middle_o, Middle_i)
+ renames.get(Middle.instOf("o", "O")) should be(Some(Seq(Middle.instOf("i", "O"))))
+ }
+
+ it should "not treat references as instances targets" in {
+ val Middle_o = Middle.ref("o")
+ val Middle_i = Middle.ref("i")
+ val renames = MutableRenameMap()
+ renames.record(Middle_o, Middle_i)
+ renames.get(Middle.instOf("o", "O")) should be(None)
+ }
+
+ it should "be able to rename weird stuff" in {
+ // Renaming `from` to each of the `tos` at the same time should be ok
+ case class BadRename(from: CompleteTarget, tos: Seq[CompleteTarget])
+ val badRenames =
+ Seq( //BadRename(foo, Seq(cir)),
+ //BadRename(foo, Seq(modB)),
+ //BadRename(modA, Seq(fooB)),
+ //BadRename(modA, Seq(cir)),
+ //BadRename(cir, Seq(foo)),
+ //BadRename(cir, Seq(modA)),
+ BadRename(cir, Seq(cir2, cir3))
+ )
+ // Run all BadRename tests
+ for (BadRename(from, tos) <- badRenames) {
+ val fromN = from
+ val tosN = tos.mkString(", ")
+ //it should s"error if a $fromN is renamed to $tosN" in {
+ val renames = MutableRenameMap()
+ for (to <- tos) {
+ (from, to) match {
+ case (f: CircuitTarget, t: CircuitTarget) => renames.record(f, t)
+ case (f: IsMember, t: IsMember) => renames.record(f, t)
+ case _ => sys.error("Unexpected!")
+ }
+ }
+ //a [FIRRTLException] shouldBe thrownBy {
+ renames.get(from)
+ //}
+ //}
+ }
+ }
+
+ it should "not error if a circular rename occurs" in {
+ val renames = MutableRenameMap()
+ val top = CircuitTarget("Top")
+ renames.record(top.module("A"), top.module("B").instOf("c", "C"))
+ renames.record(top.module("B"), top.module("A").instOf("c", "C"))
+ renames.get(top.module("A")) should be {
+ Some(Seq(top.module("B").instOf("c", "C")))
+ }
+ }
+
+ it should "not error if a swapping rename occurs" in {
+ val renames = MutableRenameMap()
+ val top = CircuitTarget("Top")
+ renames.record(top.module("A"), top.module("B"))
+ renames.record(top.module("B"), top.module("A"))
+ renames.get(top.module("A")) should be(Some(Seq(top.module("B"))))
+ renames.get(top.module("B")) should be(Some(Seq(top.module("A"))))
+ }
+
+ it should "error if a reference is renamed to a module and vice versa" in {
+ val renames = MutableRenameMap()
+ val top = CircuitTarget("Top")
+ renames.record(top.module("A").ref("ref"), top.module("B"))
+ renames.record(top.module("C"), top.module("D").ref("ref"))
+ a[IllegalRenameException] shouldBe thrownBy {
+ renames.get(top.module("C"))
+ }
+ a[IllegalRenameException] shouldBe thrownBy {
+ renames.get(top.module("A").ref("ref").field("field"))
+ }
+ renames.get(top.module("A").instOf("ref", "R")) should be(None)
+ }
+
+ it should "error if we rename an instance's ofModule into a non-module" in {
+ val renames = MutableRenameMap()
+ val top = CircuitTarget("Top")
+
+ renames.record(top.module("C"), top.module("D").ref("x"))
+ a[IllegalRenameException] shouldBe thrownBy {
+ renames.get(top.module("A").instOf("c", "C"))
+ }
+ }
+
+ it should "error if path is renamed into a non-path" ignore {
+ val renames = MutableRenameMap()
+ val top = CircuitTarget("Top")
+
+ renames.record(top.module("E").instOf("f", "F"), top.module("E").ref("g"))
+
+ a[IllegalRenameException] shouldBe thrownBy {
+ renames.get(top.module("E").instOf("f", "F").ref("g"))
+ }
+ }
+
+ it should "rename reference targets with paths if their corresponding pathless target are renamed" in {
+ val cir = CircuitTarget("Top")
+ val modTop = cir.module("Top")
+ val modA = cir.module("A")
+
+ val aggregate = modA.ref("agg")
+ val subField1 = aggregate.field("field1")
+ val subField2 = aggregate.field("field2")
+
+ val lowered1 = aggregate.copy(ref = "agg_field1")
+ val lowered2 = aggregate.copy(ref = "agg_field2")
+
+ // simulating LowerTypes transform
+ val renames = MutableRenameMap()
+ renames.record(subField1, lowered1)
+ renames.record(subField2, lowered2)
+ renames.record(aggregate, Seq(lowered1, lowered2))
+
+ val path = modTop.instOf("b", "B").instOf("a", "A")
+ val testRef1 = subField1.setPathTarget(path)
+
+ renames.get(testRef1) should be {
+ Some(Seq(testRef1.copy(ref = "agg_field1", component = Nil)))
+ }
+ }
+
+ // ~Top|Module/i1:I1>foo.field, where rename map contains ~Top|Module/i1:I1>foo -> ~Top|Module/i1:I1>bar.
+ it should "properly rename reference targets with the same paths" in {
+ val cir = CircuitTarget("Top")
+ val modTop = cir.module("Top")
+ val mod = cir.module("Module")
+
+ val path = mod.instOf("i1", "I1")
+ val oldAgg = mod.ref("foo").setPathTarget(path)
+ val newAgg = mod.ref("bar").setPathTarget(path)
+
+ val renames = MutableRenameMap()
+ renames.record(oldAgg, newAgg)
+
+ val testRef = oldAgg.field("field")
+ renames.get(testRef) should be {
+ Some(Seq(newAgg.field("field")))
+ }
+ }
+
+ it should "properly rename reference targets with partially matching paths" in {
+ val cir = CircuitTarget("Top")
+ val modTop = cir.module("Top")
+ val modA = cir.module("A")
+ val modB = cir.module("B")
+
+ val path = modB.instOf("a", "A")
+ val oldRef = modA.ref("oldRef").setPathTarget(path)
+ val newRef = modA.ref("newRef").setPathTarget(path)
+
+ val renames = MutableRenameMap()
+ renames.record(oldRef, newRef)
+
+ val testRef = oldRef.addHierarchy("B", "b")
+ renames.get(testRef) should be {
+ Some(Seq(newRef.addHierarchy("B", "b")))
+ }
+ }
+
+ it should "properly rename reference targets with partially matching paths and partially matching target tokens" in {
+ val cir = CircuitTarget("Top")
+ val modTop = cir.module("Top")
+ val modA = cir.module("A")
+ val modB = cir.module("B")
+
+ val path = modB.instOf("a", "A")
+ val oldAgg = modA.ref("oldAgg").setPathTarget(path).field("field1")
+ val newAgg = modA.ref("newAgg").setPathTarget(path)
+
+ val renames = MutableRenameMap()
+ renames.record(oldAgg, newAgg)
+
+ val testRef = oldAgg.addHierarchy("B", "b").field("field2")
+ renames.get(testRef) should be {
+ Some(Seq(newAgg.addHierarchy("B", "b").field("field2")))
+ }
+ }
+
+ it should "rename targets with multiple renames starting from most specific to least specific" in {
+ val cir = CircuitTarget("Top")
+ val modTop = cir.module("Top")
+ val modA = cir.module("A")
+ val modB = cir.module("B")
+ val modC = cir.module("C")
+
+ // from: ~Top|A/b:B/c:C>ref.f1.f2.f3
+ // to: ~Top|A/b:B/c:C>ref.f1.f2.f333
+ // renamed first because it is an exact match
+ val from1 = modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ .field("f2")
+ .field("f3")
+ val to1 = modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ .field("f2")
+ .field("f33")
+
+ // from: ~Top|A/b:B/c:C>ref.f1.f2
+ // to: ~Top|A/b:B/c:C>ref.f1
+ // renamed second because it is a parent target
+ val from2 = modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ .field("f2")
+ val to2 = modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ .field("f22")
+
+ // from: ~Top|B/c:C>ref.f1
+ // to: ~Top|B/c:C>ref.f11
+ // renamed third because it has a smaller hierarchy
+ val from3 = modB
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ val to3 = modB
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f11")
+
+ // from: ~Top|C>ref
+ // to: ~Top|C>refref
+ // renamed last because it has no path
+ val from4 = modC.ref("ref")
+ val to4 = modC.ref("refref")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(from1, to1)
+ renames1.record(from2, to2)
+ renames1.record(from3, to3)
+ renames1.record(from4, to4)
+
+ renames1.get(from1) should be {
+ Some(
+ Seq(
+ modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ .field("f2")
+ .field("f33")
+ )
+ )
+ }
+
+ val renames2 = MutableRenameMap()
+ renames2.record(from2, to2)
+ renames2.record(from3, to3)
+ renames2.record(from4, to4)
+
+ renames2.get(from1) should be {
+ Some(
+ Seq(
+ modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f1")
+ .field("f22")
+ .field("f3")
+ )
+ )
+ }
+
+ val renames3 = MutableRenameMap()
+ renames3.record(from3, to3)
+ renames3.record(from4, to4)
+
+ renames3.get(from1) should be {
+ Some(
+ Seq(
+ modA
+ .instOf("b", "B")
+ .instOf("c", "C")
+ .ref("ref")
+ .field("f11")
+ .field("f2")
+ .field("f3")
+ )
+ )
+ }
+ }
+
+ it should "correctly handle renaming of modules to instances" in {
+ val cir = CircuitTarget("Top")
+ val renames = MutableRenameMap()
+ val from = cir.module("C")
+ val to = cir.module("D").instOf("e", "E").instOf("f", "F")
+ renames.record(from, to)
+ renames.get(cir.module("C")) should be {
+ Some(Seq(cir.module("D").instOf("e", "E").instOf("f", "F")))
+ }
+ renames.get(cir.module("A").instOf("b", "B").instOf("c", "C")) should be {
+ Some(Seq(cir.module("A").instOf("b", "B").instOf("c", "D").instOf("e", "E").instOf("f", "F")))
+ }
+ }
+
+ it should "correctly handle renaming of paths and components at the same time" in {
+ val cir = CircuitTarget("Top")
+ val renames = MutableRenameMap()
+ val from = cir.module("C").ref("foo").field("bar")
+ val to = cir.module("D").instOf("e", "E").instOf("f", "F").ref("foo").field("foo")
+ renames.record(from, to)
+ renames.get(cir.module("A").instOf("b", "B").instOf("c", "C").ref("foo").field("bar")) should be {
+ Some(
+ Seq(
+ cir
+ .module("A")
+ .instOf("b", "B")
+ .instOf("c", "D")
+ .instOf("e", "E")
+ .instOf("f", "F")
+ .ref("foo")
+ .field("foo")
+ )
+ )
+ }
+ }
+
+ it should "error if an instance is renamed to a ReferenceTarget" in {
+ val top = CircuitTarget("Top").module("Top")
+ val renames = MutableRenameMap()
+ val from = top.instOf("a", "A")
+ val to = top.ref("b")
+ renames.record(from, to)
+ a[IllegalRenameException] shouldBe thrownBy {
+ renames.get(from)
+ }
+ }
+
+ it should "not allow renaming of instances even if there is a matching reference rename" in {
+ val top = CircuitTarget("Top").module("Top")
+ val renames = MutableRenameMap()
+ val from = top.ref("a")
+ val to = top.ref("b")
+ renames.record(from, to)
+ renames.get(top.instOf("a", "Foo")) should be(None)
+ }
+
+ it should "correctly chain renames together" in {
+ val top = CircuitTarget("Top")
+
+ val renames1 = MutableRenameMap()
+ val from1 = top.module("A")
+ val to1 = top.module("Top").instOf("b", "B")
+ renames1.record(from1, to1)
+
+ val renames2 = MutableRenameMap()
+ val from2 = top.module("B")
+ val to2 = top.module("B1")
+ renames2.record(from2, to2)
+
+ val renames = renames1.andThen(renames2)
+
+ renames.get(from1) should be {
+ Some(Seq(top.module("Top").instOf("b", "B1")))
+ }
+
+ renames.get(from2) should be {
+ Some(Seq(to2))
+ }
+ }
+
+ it should "correctly chain deleted targets" in {
+ val top = CircuitTarget("Top")
+ val modA = top.module("A")
+ val modA1 = top.module("A1")
+ val modB = top.module("B")
+ val modB1 = top.module("B1")
+
+ val renames1 = MutableRenameMap()
+ renames1.delete(modA)
+ renames1.record(modB, modB1)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(modA, modA1)
+ renames2.delete(modB1)
+
+ val renames = renames1.andThen(renames2)
+
+ renames.get(modA) should be {
+ Some(Seq.empty)
+ }
+ renames.get(modB) should be {
+ Some(Seq.empty)
+ }
+ }
+
+ it should "correctly ++ renameMaps" in {
+ val top = CircuitTarget("Top")
+ val modA = top.module("A")
+ val modA1 = top.module("A1")
+ val modA2 = top.module("A1")
+ val modB = top.module("B")
+ val modB1 = top.module("B1")
+ val modC = top.module("C")
+ val modC1 = top.module("C1")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(modA, modA1)
+ renames1.record(modC, modC1)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(modA, modA2)
+ renames2.record(modB, modB1)
+
+ val renames = renames1 ++ renames2
+ renames.get(modA) should be {
+ Some(Seq(modA2))
+ }
+ renames.get(modB) should be {
+ Some(Seq(modB1))
+ }
+ renames.get(modC) should be {
+ Some(Seq(modC1))
+ }
+ }
+
+ it should "be able to inline instances" in {
+ val top = CircuitTarget("Top")
+ val inlineRename1 = {
+ val inlineMod = top.module("A")
+ val inlineInst = top.module("A").instOf("b", "B")
+ val oldRef = inlineMod.ref("bar")
+ val prefixRef = inlineMod.ref("foo")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(inlineInst, inlineMod)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(oldRef, prefixRef)
+
+ renames1.andThen(renames2)
+ }
+
+ val inlineRename2 = {
+ val inlineMod = top.module("A1")
+ val inlineInst = top.module("A1").instOf("b", "B1")
+ val oldRef = inlineMod.ref("bar")
+ val prefixRef = inlineMod.ref("foo")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(inlineInst, inlineMod)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(oldRef, prefixRef)
+
+ renames1.andThen(renames2)
+ }
+
+ val renames = inlineRename1 ++ inlineRename2
+ renames.get(top.module("A").instOf("b", "B").ref("bar")) should be {
+ Some(Seq(top.module("A").ref("foo")))
+ }
+
+ renames.get(top.module("A1").instOf("b", "B1").ref("bar")) should be {
+ Some(Seq(top.module("A1").ref("foo")))
+ }
+ }
+
+ it should "be able to dedup modules" in {
+ val top = CircuitTarget("Top")
+ val topMod = top.module("Top")
+ val dedupedMod = top.module("A")
+ val dupMod1 = top.module("A1")
+ val dupMod2 = top.module("A2")
+
+ val relPath1 = dupMod1.addHierarchy("Foo", "a") //top.module("Foo").instOf("a", "A1")
+ val relPath2 = dupMod2.addHierarchy("Foo", "a") //top.module("Foo").instOf("a", "A2")
+
+ val absPath1 = relPath1.addHierarchy("Top", "foo")
+ val absPath2 = relPath2.addHierarchy("Top", "foo")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(dupMod1, absPath1)
+ renames1.record(dupMod2, absPath2)
+ renames1.record(relPath1, absPath1)
+ renames1.record(relPath2, absPath2)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(dupMod1, dedupedMod)
+ renames2.record(dupMod2, dedupedMod)
+
+ val renames = renames1.andThen(renames2)
+
+ renames.get(dupMod1.instOf("foo", "Bar").ref("ref")) should be {
+ Some(Seq(absPath1.copy(ofModule = "A").instOf("foo", "Bar").ref("ref")))
+ }
+
+ renames.get(dupMod2.ref("ref")) should be {
+ Some(Seq(absPath2.copy(ofModule = "A").ref("ref")))
+ }
+
+ renames.get(absPath1.instOf("b", "B").ref("ref")) should be {
+ Some(Seq(absPath1.copy(ofModule = "A").instOf("b", "B").ref("ref")))
+ }
+ }
+
+ it should "should able to chain many rename maps" in {
+ val top = CircuitTarget("Top")
+ val inlineRename1 = {
+ val inlineMod = top.module("A")
+ val inlineInst = top.module("A").instOf("b", "B")
+ val oldRef = inlineMod.ref("bar")
+ val prefixRef = inlineMod.ref("foo")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(inlineInst, inlineMod)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(oldRef, prefixRef)
+
+ renames1.andThen(renames2)
+ }
+
+ val inlineRename2 = {
+ val inlineMod = top.module("A1")
+ val inlineInst = top.module("A1").instOf("b", "B1")
+ val oldRef = inlineMod.ref("bar")
+ val prefixRef = inlineMod.ref("foo")
+
+ val renames1 = MutableRenameMap()
+ renames1.record(inlineInst, inlineMod)
+
+ val renames2 = MutableRenameMap()
+ renames2.record(oldRef, prefixRef)
+
+ inlineRename1.andThen(renames1).andThen(renames2)
+ }
+
+ val renames = inlineRename2
+ renames.get(top.module("A").instOf("b", "B").ref("bar")) should be {
+ Some(Seq(top.module("A").ref("foo")))
+ }
+
+ renames.get(top.module("A1").instOf("b", "B1").ref("bar")) should be {
+ Some(Seq(top.module("A1").ref("foo")))
+ }
+ }
+
+ it should "should able to chain chained rename maps" in {
+ val top = CircuitTarget("Top").module("Top")
+ val foo1 = top.instOf("foo1", "Mod")
+ val foo2 = top.instOf("foo2", "Mod")
+ val foo3 = top.instOf("foo3", "Mod")
+
+ val bar1 = top.instOf("bar1", "Mod")
+ val bar2 = top.instOf("bar2", "Mod")
+
+ val foo1Rename = MutableRenameMap()
+ val foo2Rename = MutableRenameMap()
+
+ val bar1Rename = MutableRenameMap()
+ val bar2Rename = MutableRenameMap()
+
+ foo1Rename.record(foo1, foo2)
+ foo2Rename.record(foo2, foo3)
+
+ bar1Rename.record(foo3, bar1)
+ bar2Rename.record(bar1, bar2)
+
+ val chained1 = foo1Rename.andThen(foo2Rename)
+ val chained2 = bar1Rename.andThen(bar2Rename)
+
+ val renames = chained1.andThen(chained2)
+
+ renames.get(foo1) should be {
+ Some(Seq(bar2))
+ }
+ }
+
+ it should "record a self-rename" in {
+ val top = CircuitTarget("Top").module("Top")
+ val foo = top.instOf("foo", "Mod")
+ val bar = top.instOf("bar", "Mod")
+
+ val r = MutableRenameMap()
+
+ r.record(foo, bar)
+ r.record(foo, foo)
+
+ r.get(foo) should not be (empty)
+ (r.get(foo).get should contain).allOf(foo, bar)
+ }
+
+ it should "not record the same rename multiple times" in {
+ val top = CircuitTarget("Top").module("Top")
+ val foo = top.instOf("foo", "Mod")
+ val bar = top.instOf("bar", "Mod")
+
+ val r = MutableRenameMap()
+
+ r.record(foo, bar)
+ r.record(foo, bar)
+
+ r.get(foo) should not be (empty)
+ r.get(foo).get should contain theSameElementsAs Seq(bar)
+ }
+
+ it should "not circularly rename" in {
+ val top = CircuitTarget("Top").module("Top")
+ val foo = top.instOf("foo", "Mod")
+ val Mod = CircuitTarget("Top").module("Mod")
+ val Mod2 = CircuitTarget("Top").module("Mod2")
+
+ val r = MutableRenameMap()
+
+ r.record(foo, Mod)
+ r.record(Mod, Mod2)
+
+ r.get(foo) should not be (empty)
+ r.get(foo).get should contain theSameElementsAs Seq(Mod)
+ r.get(Mod).get should contain theSameElementsAs Seq(Mod2)
+ }
+
+ it should "delete instances of deleted modules" in {
+ val top = CircuitTarget("Top").module("Top")
+ val foo = top.instOf("foo", "Mod")
+ val Mod = CircuitTarget("Top").module("Mod")
+
+ val r = MutableRenameMap()
+
+ r.delete(Mod)
+ r.get(foo) should be(Some(Nil))
+ }
+
+ it should "rename an instance if it has been renamed" in {
+ // this could happen if the instance name needed to be uniquified to avoid clashes in LowerTypes
+ val top = CircuitTarget("top").module("top")
+
+ val r = MutableRenameMap()
+ val i = top.instOf("i", "child")
+ val i_ = top.instOf("i_", "child")
+ r.record(i, i_)
+ r.get(i) should be(Some(Seq(i_)))
+ r.get(i.ref("a")) should be(Some(Seq(i_.ref("a"))))
+ }
+
+ it should "rename references to an instance's ports if the ports of the module have been renamed" in {
+ // this could happen if the port name needed to be uniquified to avoid clashes in LowerTypes
+ val top = CircuitTarget("top").module("top")
+ val child = CircuitTarget("top").module("child")
+
+ val r = MutableRenameMap()
+ r.record(child.ref("a"), Seq(child.ref("a_0"), child.ref("a_1")))
+ val i = top.instOf("i", "child")
+ r.get(i.ref("a")) should be(Some(Seq(i.ref("a_0"), i.ref("a_1"))))
+ }
+
+ it should "rename references to renamed instance's ports if the ports of the module have been renamed" in {
+ // this could happen if the instance as well as the port name needed to be uniquified to avoid clashes in LowerTypes
+ val top = CircuitTarget("top").module("top")
+ val child = CircuitTarget("top").module("child")
+
+ val portRenames = MutableRenameMap()
+ portRenames.record(child.ref("a"), Seq(child.ref("a_0"), child.ref("a_1")))
+
+ val instanceRenames = MutableRenameMap()
+ val i = top.instOf("i", "child")
+ val i_ = top.instOf("i_", "child")
+ instanceRenames.record(i, i_)
+
+ // The port and instance renames must be *explicitly* chained!
+ val r = portRenames.andThen(instanceRenames)
+ r.get(i.ref("a")) should be(Some(Seq(i_.ref("a_0"), i_.ref("a_1"))))
+ }
+}