aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala
diff options
context:
space:
mode:
authorSchuyler Eldridge2020-06-25 15:24:01 -0400
committerGitHub2020-06-25 15:24:01 -0400
commit672e2a9a4e8876580d97269d0e3d218a7c5ce491 (patch)
tree4c28b5fcd4c1ce87f10176fa49366f9efff27aa2 /src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala
parent04f60431454f030c03dd196e276d97fccc7e6c64 (diff)
parent72ab5ef044dc79e12a3af29770349a33193415d4 (diff)
Merge pull request #1638 from freechipsproject/manipulate-names-issues-refactor
Refactor ManipulateNames to use Target
Diffstat (limited to 'src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala')
-rw-r--r--src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala b/src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala
new file mode 100644
index 00000000..b1e2eeb9
--- /dev/null
+++ b/src/test/scala/firrtlTests/transforms/ManipulateNamesSpec.scala
@@ -0,0 +1,229 @@
+// See LICENSE for license details.
+
+package firrtlTests.transforms
+
+import firrtl.{
+ ir,
+ CircuitState,
+ FirrtlUserException,
+ Namespace,
+ Parser,
+ RenameMap
+}
+import firrtl.annotations.CircuitTarget
+import firrtl.options.Dependency
+import firrtl.testutils.FirrtlCheckers._
+import firrtl.transforms.{
+ ManipulateNames,
+ ManipulateNamesBlocklistAnnotation,
+ ManipulateNamesAllowlistAnnotation,
+ ManipulateNamesAllowlistResultAnnotation
+}
+
+import org.scalatest.flatspec.AnyFlatSpec
+import org.scalatest.matchers.should.Matchers
+
+object ManipulateNamesSpec {
+
+ class AddPrefix extends ManipulateNames {
+ override def manipulate = (a: String, b: Namespace) => Some(b.newName("prefix_" + a))
+ }
+
+}
+
+class ManipulateNamesSpec extends AnyFlatSpec with Matchers {
+
+ import ManipulateNamesSpec._
+
+ class CircuitFixture {
+ protected val input =
+ """|circuit Foo:
+ | module Bar:
+ | node a = UInt<1>(0)
+ | module Foo:
+ | inst bar of Bar
+ | inst bar2 of Bar
+ |""".stripMargin
+ val `~Foo` = CircuitTarget("Foo")
+ val `~Foo|Foo` = `~Foo`.module("Foo")
+ val `~Foo|Foo/bar:Bar` = `~Foo|Foo`.instOf("bar", "Bar")
+ val `~Foo|Foo/bar2:Bar` = `~Foo|Foo`.instOf("bar2", "Bar")
+ val `~Foo|Bar` = `~Foo`.module("Bar")
+ val `~Foo|Bar>a` = `~Foo|Bar`.ref("a")
+ val tm = new firrtl.stage.transforms.Compiler(Seq(Dependency[AddPrefix]))
+ }
+
+ behavior of "ManipulateNames"
+
+ it should "rename everything by default" in new CircuitFixture {
+ val state = CircuitState(Parser.parse(input), Seq.empty)
+ val statex = tm.execute(state)
+ val expected: Seq[PartialFunction[Any, Boolean]] = Seq(
+ { case ir.Circuit(_, _, "prefix_Foo") => true },
+ { case ir.Module(_, "prefix_Foo", _, _) => true},
+ { case ir.Module(_, "prefix_Bar", _, _) => true}
+ )
+ expected.foreach(statex should containTree (_))
+ }
+
+ it should "do nothing if the circuit is blocklisted" in new CircuitFixture {
+ val annotations = Seq(ManipulateNamesBlocklistAnnotation(Seq(Seq(`~Foo`)), Dependency[AddPrefix]))
+ val state = CircuitState(Parser.parse(input), annotations)
+ val statex = tm.execute(state)
+ state.circuit.serialize should be (statex.circuit.serialize)
+ }
+
+ it should "not rename the circuit if the top module is blocklisted" in new CircuitFixture {
+ val annotations = Seq(ManipulateNamesBlocklistAnnotation(Seq(Seq(`~Foo|Foo`)), Dependency[AddPrefix]))
+ val state = CircuitState(Parser.parse(input), annotations)
+ val expected: Seq[PartialFunction[Any, Boolean]] = Seq(
+ { case ir.Circuit(_, _, "Foo") => true },
+ { case ir.Module(_, "Foo", _, _) => true},
+ { case ir.Module(_, "prefix_Bar", _, _) => true}
+ )
+ val statex = tm.execute(state)
+ expected.foreach(statex should containTree (_))
+ }
+
+ it should "not rename instances if blocklisted" in new CircuitFixture {
+ val annotations = Seq(ManipulateNamesBlocklistAnnotation(Seq(Seq(`~Foo|Foo/bar:Bar`)), Dependency[AddPrefix]))
+ val state = CircuitState(Parser.parse(input), annotations)
+ val expected: Seq[PartialFunction[Any, Boolean]] = Seq(
+ { case ir.DefInstance(_, "bar", "prefix_Bar", _) => true},
+ { case ir.Module(_, "prefix_Bar", _, _) => true}
+ )
+ val statex = tm.execute(state)
+ expected.foreach(statex should containTree (_))
+ }
+
+ it should "do nothing if the circuit is not allowlisted" in new CircuitFixture {
+ val annotations = Seq(
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo|Foo`)), Dependency[AddPrefix])
+ )
+ val state = CircuitState(Parser.parse(input), annotations)
+ val statex = tm.execute(state)
+ state.circuit.serialize should be (statex.circuit.serialize)
+ }
+
+ it should "rename only the circuit if allowlisted" in new CircuitFixture {
+ val annotations = Seq(
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo`)), Dependency[AddPrefix]),
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo|Foo`)), Dependency[AddPrefix])
+ )
+ val state = CircuitState(Parser.parse(input), annotations)
+ val statex = tm.execute(state)
+ val expected: Seq[PartialFunction[Any, Boolean]] = Seq(
+ { case ir.Circuit(_, _, "prefix_Foo") => true },
+ { case ir.Module(_, "prefix_Foo", _, _) => true},
+ { case ir.DefInstance(_, "bar", "Bar", _) => true},
+ { case ir.DefInstance(_, "bar2", "Bar", _) => true},
+ { case ir.Module(_, "Bar", _, _) => true},
+ { case ir.DefNode(_, "a", _) => true}
+ )
+ expected.foreach(statex should containTree (_))
+ }
+
+ it should "rename an instance via allowlisting" in new CircuitFixture {
+ val annotations = Seq(
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo`)), Dependency[AddPrefix]),
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo|Foo/bar:Bar`)), Dependency[AddPrefix])
+ )
+ val state = CircuitState(Parser.parse(input), annotations)
+ val statex = tm.execute(state)
+ val expected: Seq[PartialFunction[Any, Boolean]] = Seq(
+ { case ir.Circuit(_, _, "Foo") => true },
+ { case ir.Module(_, "Foo", _, _) => true},
+ { case ir.DefInstance(_, "prefix_bar", "Bar", _) => true},
+ { case ir.DefInstance(_, "bar2", "Bar", _) => true},
+ { case ir.Module(_, "Bar", _, _) => true},
+ { case ir.DefNode(_, "a", _) => true}
+ )
+ expected.foreach(statex should containTree (_))
+ }
+
+ it should "rename a node via allowlisting" in new CircuitFixture {
+ val annotations = Seq(
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo`)), Dependency[AddPrefix]),
+ ManipulateNamesAllowlistAnnotation(Seq(Seq(`~Foo|Bar>a`)), Dependency[AddPrefix])
+ )
+ val state = CircuitState(Parser.parse(input), annotations)
+ val statex = tm.execute(state)
+ val expected: Seq[PartialFunction[Any, Boolean]] = Seq(
+ { case ir.Circuit(_, _, "Foo") => true },
+ { case ir.Module(_, "Foo", _, _) => true},
+ { case ir.DefInstance(_, "bar", "Bar", _) => true},
+ { case ir.DefInstance(_, "bar2", "Bar", _) => true},
+ { case ir.Module(_, "Bar", _, _) => true},
+ { case ir.DefNode(_, "prefix_a", _) => true}
+ )
+ expected.foreach(statex should containTree (_))
+ }
+
+ it should "throw user errors on circuits that haven't been run through LowerTypes" in {
+ val input =
+ """|circuit Foo:
+ | module Foo:
+ | wire bar: {a: UInt<1>, b: UInt<1>}
+ | node baz = bar.a
+ |""".stripMargin
+ val state = CircuitState(Parser.parse(input), Seq.empty)
+ intercept [FirrtlUserException] {
+ (new AddPrefix).transform(state)
+ }.getMessage should include ("LowerTypes")
+ }
+
+ behavior of "ManipulateNamesBlocklistAnnotation"
+
+ it should "throw an exception if a non-local target is skipped" in new CircuitFixture {
+ val barA = CircuitTarget("Foo").module("Foo").instOf("bar", "Bar").ref("a")
+ assertThrows[java.lang.IllegalArgumentException]{
+ Seq(ManipulateNamesBlocklistAnnotation(Seq(Seq(barA)), Dependency[AddPrefix]))
+ }
+ }
+
+ behavior of "ManipulateNamesAllowlistResultAnnotation"
+
+ it should "delete itself if the new target is deleted" in {
+ val `~Foo|Bar` = CircuitTarget("Foo").module("Bar")
+ val `~Foo|prefix_Bar` = CircuitTarget("Foo").module("prefix_Bar")
+
+ val a = ManipulateNamesAllowlistResultAnnotation(
+ targets = Seq(Seq(`~Foo|prefix_Bar`)),
+ transform = Dependency[AddPrefix],
+ oldTargets = Seq(Seq(`~Foo|Bar`))
+ )
+
+ val r = RenameMap()
+ r.delete(`~Foo|prefix_Bar`)
+
+ a.update(r) should be (empty)
+ }
+
+ it should "drop a deleted target" in {
+ val `~Foo|Bar` = CircuitTarget("Foo").module("Bar")
+ val `~Foo|prefix_Bar` = CircuitTarget("Foo").module("prefix_Bar")
+ val `~Foo|Baz` = CircuitTarget("Foo").module("Baz")
+ val `~Foo|prefix_Baz` = CircuitTarget("Foo").module("prefix_Baz")
+
+ val a = ManipulateNamesAllowlistResultAnnotation(
+ targets = Seq(Seq(`~Foo|prefix_Bar`), Seq(`~Foo|prefix_Baz`)),
+ transform = Dependency[AddPrefix],
+ oldTargets = Seq(Seq(`~Foo|Bar`), Seq(`~Foo|Baz`))
+ )
+
+ val r = RenameMap()
+ r.delete(`~Foo|prefix_Bar`)
+
+ val ax = a.update(r).collect {
+ case b: ManipulateNamesAllowlistResultAnnotation[_] => b
+ }
+
+ ax should not be length (1)
+
+ val keys = ax.head.toRenameMap.getUnderlying.keys
+
+ keys should not contain (`~Foo|Bar`)
+ keys should contain (`~Foo|Baz`)
+ }
+
+}