diff options
Diffstat (limited to 'src/test')
3 files changed, 110 insertions, 7 deletions
diff --git a/src/test/scala/firrtlTests/InlineInstancesTests.scala b/src/test/scala/firrtlTests/InlineInstancesTests.scala index cc7257d2..b54db7cc 100644 --- a/src/test/scala/firrtlTests/InlineInstancesTests.scala +++ b/src/test/scala/firrtlTests/InlineInstancesTests.scala @@ -380,8 +380,12 @@ class InlineInstancesTests extends LowTransformSpec { execute(input, check, Seq(inline("Inline"))) } - case class DummyAnno(target: ReferenceTarget) extends SingleTargetAnnotation[ReferenceTarget] { - override def duplicate(n: ReferenceTarget): Annotation = DummyAnno(n) + case class DummyAnno(targets: CompleteTarget*) extends Annotation { + override def update(renames: RenameMap): Seq[Annotation] = { + Seq(DummyAnno(targets.flatMap { t => + renames.get(t).getOrElse(Seq(t)) + }: _*)) + } } "annotations" should "be renamed" in { val input = @@ -573,6 +577,9 @@ class InlineInstancesTests extends LowTransformSpec { val nestedNotInlined = inlined.instOf("bar", "NestedNoInline") val innerNestedInlined = nestedNotInlined.instOf("foo", "NestedInline") + val inlineModuleTarget = top.copy(module = "Inline") + val nestedInlineModuleTarget = top.copy(module = "NestedInline") + executeWithAnnos( input, check, @@ -586,7 +593,10 @@ class InlineInstancesTests extends LowTransformSpec { DummyAnno(nestedNotInlined.ref("a")), DummyAnno(nestedNotInlined.ref("b")), DummyAnno(innerNestedInlined.ref("a")), - DummyAnno(innerNestedInlined.ref("b")) + DummyAnno(innerNestedInlined.ref("b")), + DummyAnno(inlineModuleTarget.instOf("bar", "NestedNoInline")), + DummyAnno(inlineModuleTarget.ref("a"), inlineModuleTarget.ref("b")), + DummyAnno(nestedInlineModuleTarget.ref("a")) ), Seq( DummyAnno(top.ref("i_a")), @@ -596,7 +606,10 @@ class InlineInstancesTests extends LowTransformSpec { DummyAnno(top.instOf("i_bar", "NestedNoInline").ref("a")), DummyAnno(top.instOf("i_bar", "NestedNoInline").ref("b")), DummyAnno(top.instOf("i_bar", "NestedNoInline").ref("foo_a")), - DummyAnno(top.instOf("i_bar", "NestedNoInline").ref("foo_b")) + DummyAnno(top.instOf("i_bar", "NestedNoInline").ref("foo_b")), + DummyAnno(top.instOf("i_bar", "NestedNoInline")), + DummyAnno(top.ref("i_a"), top.ref("i_b")), + DummyAnno(top.ref("i_foo_a"), top.copy(module = "NestedNoInline").ref("foo_a")) ) ) } diff --git a/src/test/scala/firrtlTests/ReplSeqMemTests.scala b/src/test/scala/firrtlTests/ReplSeqMemTests.scala index 4e00cb3a..cb6dd7a6 100644 --- a/src/test/scala/firrtlTests/ReplSeqMemTests.scala +++ b/src/test/scala/firrtlTests/ReplSeqMemTests.scala @@ -10,6 +10,8 @@ import firrtl.passes.memlib._ import firrtl.testutils.FirrtlCheckers._ import firrtl.testutils._ import firrtl.transforms._ +import firrtl.util.BackendCompilationUtilities.loggingProcessLogger +import scala.sys.process._ class ReplSeqMemSpec extends SimpleTransformSpec { def emitter = new LowFirrtlEmitter @@ -45,6 +47,23 @@ class ReplSeqMemSpec extends SimpleTransformSpec { ) } + def checkGenMemVerilog(input: String, mems: Set[MemConf], additionalAnnos: Annotation*): Unit = { + Seq(true, false).foreach { genBlackBox => + val annos = Seq(GenVerilogMemBehaviorModelAnno(genBlackBox = genBlackBox)) ++ additionalAnnos + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) + // Check correctness of firrtl + parse(res.getEmittedCircuit.value) + // Check the emitted Verilog + mems.foreach { mem => + val file = new java.io.File(mem.name + ".v") + require(file.exists(), s"${file.getName} should be emitted!") + val cmd = Seq("verilator", "--lint-only", file.getAbsolutePath) + assert(cmd.!(loggingProcessLogger) == 0, "Generated Verilog is not valid.") + file.delete() + } + } + } + "ReplSeqMem" should "generate blackbox wrappers for mems of bundle type" in { val input = """ circuit Top : @@ -77,6 +96,8 @@ circuit Top : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "not infinite loop if control signals are derived from registered versions of themselves" in { @@ -102,6 +123,8 @@ circuit Top : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "not fail with FixedPoint types " in { @@ -130,6 +153,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "not fail with Signed types " in { @@ -158,6 +183,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem Utility -- getConnectOrigin" should @@ -232,9 +259,11 @@ circuit CustomMemory : MemConf("mem_1_ext", 7, 16, Map(WritePort -> 1, ReadPort -> 1), None) ) val confLoc = "ReplSeqMemTests.confTEMP" + val noDedupMemAnnotation = + NoDedupMemAnnotation(ComponentName("mem_0", ModuleName("CustomMemory", CircuitName("CustomMemory")))) val annos = Seq( ReplSeqMemAnnotation.parse("-c:CustomMemory:-o:" + confLoc), - NoDedupMemAnnotation(ComponentName("mem_0", ModuleName("CustomMemory", CircuitName("CustomMemory")))) + noDedupMemAnnotation ) val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) // Check correctness of firrtl @@ -247,6 +276,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems, noDedupMemAnnotation) } "ReplSeqMem" should "only not de-duplicate memories with the nodedupe annotation " in { @@ -279,9 +310,11 @@ circuit CustomMemory : MemConf("mem_1_ext", 7, 16, Map(WritePort -> 1, ReadPort -> 1), None) ) val confLoc = "ReplSeqMemTests.confTEMP" + val noDedupMemAnnotation = + NoDedupMemAnnotation(ComponentName("mem_1", ModuleName("CustomMemory", CircuitName("CustomMemory")))) val annos = Seq( ReplSeqMemAnnotation.parse("-c:CustomMemory:-o:" + confLoc), - NoDedupMemAnnotation(ComponentName("mem_1", ModuleName("CustomMemory", CircuitName("CustomMemory")))) + noDedupMemAnnotation ) val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) // Check correctness of firrtl @@ -294,6 +327,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems, noDedupMemAnnotation) } "ReplSeqMem" should "dedup mems with the same instance name as other mems (in other modules) marked NoDedup" in { @@ -337,9 +372,11 @@ circuit CustomMemory : MemConf("mem_0_0_ext", 7, 16, Map(WritePort -> 1, ReadPort -> 1), None) ) val confLoc = "ReplSeqMemTests.confTEMP" + val noDedupMemAnnotation = + NoDedupMemAnnotation(ComponentName("mem_0", ModuleName("ChildMemory", CircuitName("CustomMemory")))) val annos = Seq( ReplSeqMemAnnotation.parse("-c:CustomMemory:-o:" + confLoc), - NoDedupMemAnnotation(ComponentName("mem_0", ModuleName("ChildMemory", CircuitName("CustomMemory")))) + noDedupMemAnnotation ) val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) // Check correctness of firrtl @@ -356,6 +393,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems, noDedupMemAnnotation) } "ReplSeqMem" should "de-duplicate memories without an annotation " in { @@ -391,6 +430,8 @@ circuit CustomMemory : } require(numExtMods == 1) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "not have a mask if there is none" in { @@ -416,6 +457,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "not conjoin enable signal with mask condition" in { @@ -446,6 +489,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "not conjoin enable signal with wmask condition (RW Port)" in { @@ -480,6 +525,8 @@ circuit CustomMemory : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "produce an empty conf file with no SeqMems" in { @@ -501,6 +548,8 @@ circuit NoMemsHere : // Check the emitted conf checkMemConf(res, mems) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, mems) } "ReplSeqMem" should "throw an exception when encountering masks with variable granularity" in { @@ -529,6 +578,10 @@ circuit Top : val annos = Seq(ReplSeqMemAnnotation.parse("-c:Top:-o:" + confLoc)) val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) } + + intercept[ReplaceMemMacros.UnsupportedBlackboxMemoryException] { + checkGenMemVerilog(input, Set.empty) + } } "ReplSeqMem" should "not run a buggy Uniquify" in { @@ -551,6 +604,8 @@ circuit Top : // Just check that it doesn't crash compileAndEmit(CircuitState(parse(input), ChirrtlForm, annos)) (new java.io.File(confLoc)).delete() + + checkGenMemVerilog(input, Set.empty) } } diff --git a/src/test/scala/firrtlTests/annotationTests/AnnotationSpec.scala b/src/test/scala/firrtlTests/annotationTests/AnnotationSpec.scala new file mode 100644 index 00000000..2729b4dc --- /dev/null +++ b/src/test/scala/firrtlTests/annotationTests/AnnotationSpec.scala @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: Apache-2.0 + +package firrtlTests.annotationTests + +import firrtl.RenameMap +import firrtl.annotations._ +import firrtl.testutils.FirrtlFlatSpec + +object AnnotationSpec { + case class TestAnno(pairs: List[(String, ReferenceTarget)]) extends Annotation { + def update(renames: RenameMap): Seq[Annotation] = { + val pairsx = pairs.flatMap { + case (n, t) => + val ts = renames + .get(t) + .map(_.map(_.asInstanceOf[ReferenceTarget])) + .getOrElse(Seq(t)) + ts.map(n -> _) + } + Seq(TestAnno(pairsx)) + } + } +} + +class AnnotationSpec extends FirrtlFlatSpec { + import AnnotationSpec._ + + behavior.of("Annotation.getTargets") + + it should "not stack overflow" in { + val ref = CircuitTarget("Top").module("Foo").ref("vec") + val anno = TestAnno((0 until 10000).map(i => (i.toString, ref.index(i))).toList) + anno.getTargets should be(anno.pairs.map(_._2)) + } +} |
