summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorChick Markley2019-06-03 16:22:43 -0700
committerGitHub2019-06-03 16:22:43 -0700
commit821fe17b110e2a9017a335516227cb491c18cf43 (patch)
tree22fe46c8f675ca3739f893890efc2479f367d9a1 /src/test
parent820e2688f0cb966d4528ff074fdbdc623ed8f940 (diff)
parent23641521174ba828feb32dc1c65c13a3d6b46970 (diff)
Merge pull request #1004 from freechipsproject/chisel-stage
Chisel stage
Diffstat (limited to 'src/test')
-rw-r--r--src/test/scala/chisel3/stage/phases/DriverCompatibilitySpec.scala70
-rw-r--r--src/test/scala/chiselTests/DriverSpec.scala9
-rw-r--r--src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala65
-rw-r--r--src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala40
-rw-r--r--src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala42
-rw-r--r--src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala49
-rw-r--r--src/test/scala/chiselTests/stage/phases/ChecksSpec.scala43
-rw-r--r--src/test/scala/chiselTests/stage/phases/ConvertSpec.scala62
-rw-r--r--src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala46
-rw-r--r--src/test/scala/chiselTests/stage/phases/EmitterSpec.scala60
10 files changed, 486 insertions, 0 deletions
diff --git a/src/test/scala/chisel3/stage/phases/DriverCompatibilitySpec.scala b/src/test/scala/chisel3/stage/phases/DriverCompatibilitySpec.scala
new file mode 100644
index 00000000..c478db27
--- /dev/null
+++ b/src/test/scala/chisel3/stage/phases/DriverCompatibilitySpec.scala
@@ -0,0 +1,70 @@
+// See LICENSE for license details.
+
+package chisel3.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3.stage.{NoRunFirrtlCompilerAnnotation, ChiselOutputFileAnnotation}
+
+import firrtl.options.{OutputAnnotationFileAnnotation, StageOptions}
+import firrtl.options.Viewer.view
+import firrtl.stage.phases.DriverCompatibility.TopNameAnnotation
+
+class DriverCompatibilitySpec extends FlatSpec with Matchers {
+
+ behavior of classOf[DriverCompatibility.AddImplicitOutputFile].toString
+
+ it should "do nothing if a ChiselOutputFileAnnotation is present" in {
+ val annotations = Seq(
+ ChiselOutputFileAnnotation("Foo"),
+ TopNameAnnotation("Bar") )
+ (new DriverCompatibility.AddImplicitOutputFile).transform(annotations).toSeq should be (annotations)
+ }
+
+ it should "add a ChiselOutputFileAnnotation derived from a TopNameAnnotation" in {
+ val annotations = Seq( TopNameAnnotation("Bar") )
+ val expected = ChiselOutputFileAnnotation("Bar") +: annotations
+ (new DriverCompatibility.AddImplicitOutputFile).transform(annotations).toSeq should be (expected)
+ }
+
+ behavior of classOf[DriverCompatibility.AddImplicitOutputAnnotationFile].toString
+
+ it should "do nothing if an OutputAnnotationFileAnnotation is present" in {
+ val annotations = Seq(
+ OutputAnnotationFileAnnotation("Foo"),
+ TopNameAnnotation("Bar") )
+ (new DriverCompatibility.AddImplicitOutputAnnotationFile).transform(annotations).toSeq should be (annotations)
+ }
+
+ it should "add an OutputAnnotationFileAnnotation derived from a TopNameAnnotation" in {
+ val annotations = Seq( TopNameAnnotation("Bar") )
+ val expected = OutputAnnotationFileAnnotation("Bar") +: annotations
+ (new DriverCompatibility.AddImplicitOutputAnnotationFile).transform(annotations).toSeq should be (expected)
+ }
+
+ behavior of classOf[DriverCompatibility.DisableFirrtlStage].toString
+
+ it should "add a NoRunFirrtlCompilerAnnotation if one does not exist" in {
+ val annos = Seq(NoRunFirrtlCompilerAnnotation)
+ val expected = DriverCompatibility.RunFirrtlCompilerAnnotation +: annos
+ (new DriverCompatibility.DisableFirrtlStage).transform(Seq.empty).toSeq should be (expected)
+ }
+
+ it should "NOT add a NoRunFirrtlCompilerAnnotation if one already exists" in {
+ val annos = Seq(NoRunFirrtlCompilerAnnotation)
+ (new DriverCompatibility.DisableFirrtlStage).transform(annos).toSeq should be (annos)
+ }
+
+ behavior of classOf[DriverCompatibility.ReEnableFirrtlStage].toString
+
+ it should "NOT strip a NoRunFirrtlCompilerAnnotation if NO RunFirrtlCompilerAnnotation is present" in {
+ val annos = Seq(NoRunFirrtlCompilerAnnotation, DriverCompatibility.RunFirrtlCompilerAnnotation)
+ (new DriverCompatibility.ReEnableFirrtlStage).transform(annos).toSeq should be (Seq.empty)
+ }
+
+ it should "strip a NoRunFirrtlCompilerAnnotation if a RunFirrtlCompilerAnnotation is present" in {
+ val annos = Seq(NoRunFirrtlCompilerAnnotation)
+ (new DriverCompatibility.ReEnableFirrtlStage).transform(annos).toSeq should be (annos)
+ }
+
+}
diff --git a/src/test/scala/chiselTests/DriverSpec.scala b/src/test/scala/chiselTests/DriverSpec.scala
index 612bdef2..8fc58e21 100644
--- a/src/test/scala/chiselTests/DriverSpec.scala
+++ b/src/test/scala/chiselTests/DriverSpec.scala
@@ -28,6 +28,7 @@ class DriverSpec extends FreeSpec with Matchers {
val exts = List("anno.json", "fir", "v")
for (ext <- exts) {
val dummyOutput = new File(targetDir, "DummyModule" + "." + ext)
+ info(s"${dummyOutput.toString} exists")
dummyOutput.exists() should be(true)
dummyOutput.delete()
}
@@ -44,6 +45,7 @@ class DriverSpec extends FreeSpec with Matchers {
val exts = List("anno.json", "fir", "v")
for (ext <- exts) {
val dummyOutput = new File(targetDir, "dm" + "." + ext)
+ info(s"${dummyOutput.toString} exists")
dummyOutput.exists() should be(true)
dummyOutput.delete()
}
@@ -53,14 +55,21 @@ class DriverSpec extends FreeSpec with Matchers {
}
}
+
"execute returns a chisel execution result" in {
val targetDir = "test_run_dir"
val args = Array("--compiler", "low", "--target-dir", targetDir)
+
+ info("Driver returned a ChiselExecutionSuccess")
val result = Driver.execute(args, () => new DummyModule)
result shouldBe a[ChiselExecutionSuccess]
+
+ info("emitted circuit included 'circuit DummyModule'")
val successResult = result.asInstanceOf[ChiselExecutionSuccess]
successResult.emitted should include ("circuit DummyModule")
+
val dummyOutput = new File(targetDir, "DummyModule.lo.fir")
+ info(s"${dummyOutput.toString} exists")
dummyOutput.exists() should be(true)
dummyOutput.delete()
}
diff --git a/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala b/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala
new file mode 100644
index 00000000..c89955f2
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/ChiselAnnotationsSpec.scala
@@ -0,0 +1,65 @@
+// See LICENSE for license details.
+
+package chiselTests.stage
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3._
+import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation}
+import chisel3.experimental.RawModule
+
+import firrtl.options.OptionsException
+
+class ChiselAnnotationsSpecFoo extends RawModule {
+ val in = IO(Input(Bool()))
+ val out = IO(Output(Bool()))
+ out := ~in
+}
+
+class ChiselAnnotationsSpecBaz(name: String) extends ChiselAnnotationsSpecFoo {
+ override val desiredName = name
+}
+
+class ChiselAnnotationsSpecQux extends ChiselAnnotationsSpecFoo {
+ /* This printf requires an implicit clock and reset, but RawModule has none. This will thereby fail elaboration. */
+ printf("hello")
+}
+
+class ChiselAnnotation
+
+class ChiselAnnotationsSpec extends FlatSpec with Matchers {
+
+ behavior of "ChiselGeneratorAnnotation elaboration"
+
+ it should "elaborate to a ChiselCircuitAnnotation" in {
+ val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecFoo)
+ annotation.elaborate shouldBe a [ChiselCircuitAnnotation]
+ }
+
+ it should "throw an exception if elaboration fails" in {
+ val annotation = ChiselGeneratorAnnotation(() => new ChiselAnnotationsSpecQux)
+ intercept [ChiselException] { annotation.elaborate }
+ }
+
+ behavior of "ChiselGeneratorAnnotation when stringly constructing from Module names"
+
+ it should "elaborate from a String" in {
+ val annotation = ChiselGeneratorAnnotation("chiselTests.stage.ChiselAnnotationsSpecFoo")
+ annotation.elaborate shouldBe a [ChiselCircuitAnnotation]
+ }
+
+ it should "throw an exception if elaboration from a String refers to nonexistant class" in {
+ val bar = "chiselTests.stage.ChiselAnnotationsSpecBar"
+ val annotation = ChiselGeneratorAnnotation(bar)
+ intercept [OptionsException] { annotation.elaborate }
+ .getMessage should startWith (s"Unable to locate module '$bar'")
+ }
+
+ it should "throw an exception if elaboration from a String refers to an anonymous class" in {
+ val baz = "chiselTests.stage.ChiselAnnotationsSpecBaz"
+ val annotation = ChiselGeneratorAnnotation(baz)
+ intercept [OptionsException] { annotation.elaborate }
+ .getMessage should startWith (s"Unable to create instance of module '$baz'")
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala b/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala
new file mode 100644
index 00000000..7dbeb9fa
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/ChiselOptionsViewSpec.scala
@@ -0,0 +1,40 @@
+// See LICENSE for license details.
+
+package chiselTests.stage
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import firrtl.options.Viewer.view
+
+import chisel3.stage._
+import chisel3.internal.firrtl.Circuit
+
+class ChiselOptionsViewSpec extends FlatSpec with Matchers {
+
+ behavior of ChiselOptionsView.getClass.getName
+
+ it should "construct a view from an AnnotationSeq" in {
+ val bar = Circuit("bar", Seq.empty, Seq.empty)
+ val annotations = Seq(
+ NoRunFirrtlCompilerAnnotation,
+ PrintFullStackTraceAnnotation,
+ ChiselOutputFileAnnotation("foo"),
+ ChiselCircuitAnnotation(bar)
+ )
+ val out = view[ChiselOptions](annotations)
+
+ info("runFirrtlCompiler was set to false")
+ out.runFirrtlCompiler should be (false)
+
+ info("printFullStackTrace was set to true")
+ out.printFullStackTrace should be (true)
+
+ info("outputFile was set to 'foo'")
+ out.outputFile should be (Some("foo"))
+
+ info("chiselCircuit was set to circuit 'bar'")
+ out.chiselCircuit should be (Some(bar))
+
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala
new file mode 100644
index 00000000..f5fe0440
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputAnnotationFileSpec.scala
@@ -0,0 +1,42 @@
+// See LICENSE for license details.
+
+package chiselTests.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3.experimental.RawModule
+import chisel3.stage.ChiselGeneratorAnnotation
+import chisel3.stage.phases.{AddImplicitOutputAnnotationFile, Elaborate}
+
+import firrtl.AnnotationSeq
+import firrtl.options.{OutputAnnotationFileAnnotation, Phase}
+
+class AddImplicitOutputAnnotationFileSpec extends FlatSpec with Matchers {
+
+ class Foo extends RawModule { override val desiredName = "Foo" }
+
+ class Fixture { val phase: Phase = new AddImplicitOutputAnnotationFile }
+
+ behavior of classOf[AddImplicitOutputAnnotationFile].toString
+
+ it should "not override an existing OutputAnnotationFileAnnotation" in new Fixture {
+ val annotations: AnnotationSeq = Seq(
+ ChiselGeneratorAnnotation(() => new Foo),
+ OutputAnnotationFileAnnotation("Bar") )
+
+ Seq( new Elaborate, phase )
+ .foldLeft(annotations)((a, p) => p.transform(a))
+ .collect{ case a: OutputAnnotationFileAnnotation => a.file }
+ .toSeq should be (Seq("Bar"))
+ }
+
+ it should "generate an OutputAnnotationFileAnnotation from a ChiselCircuitAnnotation" in new Fixture {
+ val annotations: AnnotationSeq = Seq( ChiselGeneratorAnnotation(() => new Foo) )
+
+ Seq( new Elaborate, phase )
+ .foldLeft(annotations)((a, p) => p.transform(a))
+ .collect{ case a: OutputAnnotationFileAnnotation => a.file }
+ .toSeq should be (Seq("Foo"))
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala
new file mode 100644
index 00000000..411aa6ba
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/phases/AddImplicitOutputFileSpec.scala
@@ -0,0 +1,49 @@
+// See LICENSE for license details.
+
+package chiselTests.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3.experimental.RawModule
+import chisel3.stage.{ChiselGeneratorAnnotation, ChiselOutputFileAnnotation}
+import chisel3.stage.phases.{AddImplicitOutputFile, Elaborate}
+
+import firrtl.AnnotationSeq
+import firrtl.options.{Phase, StageOptions, TargetDirAnnotation}
+import firrtl.options.Viewer.view
+
+class AddImplicitOutputFileSpec extends FlatSpec with Matchers {
+
+ class Foo extends RawModule { override val desiredName = "Foo" }
+
+ class Fixture { val phase: Phase = new AddImplicitOutputFile }
+
+ behavior of classOf[AddImplicitOutputFile].toString
+
+ it should "not override an existing ChiselOutputFileAnnotation" in new Fixture {
+ val annotations: AnnotationSeq = Seq(
+ ChiselGeneratorAnnotation(() => new Foo),
+ ChiselOutputFileAnnotation("Bar") )
+
+ Seq( new Elaborate, phase )
+ .foldLeft(annotations)((a, p) => p.transform(a))
+ .collect{ case a: ChiselOutputFileAnnotation => a.file }
+ .toSeq should be (Seq("Bar"))
+ }
+
+ it should "generate a ChiselOutputFileAnnotation from a ChiselCircuitAnnotation" in new Fixture {
+ val annotations: AnnotationSeq = Seq(
+ ChiselGeneratorAnnotation(() => new Foo),
+ TargetDirAnnotation("test_run_dir") )
+
+ Seq( new Elaborate, phase )
+ .foldLeft(annotations)((a, p) => p.transform(a))
+ .collect{ case a: ChiselOutputFileAnnotation => a.file }
+ .toSeq should be (Seq("Foo"))
+ }
+
+ it should "do nothing to an empty annotation sequence" in new Fixture {
+ phase.transform(AnnotationSeq(Seq.empty)).toSeq should be (empty)
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala b/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala
new file mode 100644
index 00000000..6d01e38e
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/phases/ChecksSpec.scala
@@ -0,0 +1,43 @@
+// See LICENSE for license details.
+
+package chiselTests.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3.stage.{ChiselOutputFileAnnotation, NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation}
+import chisel3.stage.phases.Checks
+
+import firrtl.AnnotationSeq
+import firrtl.annotations.NoTargetAnnotation
+import firrtl.options.{OptionsException, Phase}
+
+class ChecksSpec extends FlatSpec with Matchers {
+
+ def checkExceptionMessage(phase: Phase, annotations: AnnotationSeq, messageStart: String): Unit =
+ intercept[OptionsException]{ phase.transform(annotations) }.getMessage should startWith(messageStart)
+
+ class Fixture { val phase: Phase = new Checks }
+
+ behavior of classOf[Checks].toString
+
+ it should "do nothing on sane annotation sequences" in new Fixture {
+ val a = Seq(NoRunFirrtlCompilerAnnotation, PrintFullStackTraceAnnotation)
+ phase.transform(a).toSeq should be (a)
+ }
+
+ it should "throw an OptionsException if more than one NoRunFirrtlCompilerAnnotation is specified" in new Fixture {
+ val a = Seq(NoRunFirrtlCompilerAnnotation, NoRunFirrtlCompilerAnnotation)
+ checkExceptionMessage(phase, a, "At most one NoRunFirrtlCompilerAnnotation")
+ }
+
+ it should "throw an OptionsException if more than one PrintFullStackTraceAnnotation is specified" in new Fixture {
+ val a = Seq(PrintFullStackTraceAnnotation, PrintFullStackTraceAnnotation)
+ checkExceptionMessage(phase, a, "At most one PrintFullStackTraceAnnotation")
+ }
+
+ it should "throw an OptionsException if more than one ChiselOutputFileAnnotation is specified" in new Fixture {
+ val a = Seq(ChiselOutputFileAnnotation("foo"), ChiselOutputFileAnnotation("bar"))
+ checkExceptionMessage(phase, a, "At most one Chisel output file")
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala b/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala
new file mode 100644
index 00000000..30fad4f5
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/phases/ConvertSpec.scala
@@ -0,0 +1,62 @@
+// See LICENSE for license details.
+
+package chiselTests.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3._
+import chisel3.experimental.{ChiselAnnotation, RawModule, RunFirrtlTransform}
+import chisel3.stage.ChiselGeneratorAnnotation
+import chisel3.stage.phases.{Convert, Elaborate}
+
+import firrtl.{AnnotationSeq, CircuitForm, CircuitState, Transform, UnknownForm}
+import firrtl.annotations.{Annotation, NoTargetAnnotation}
+import firrtl.options.Phase
+import firrtl.stage.{FirrtlCircuitAnnotation, RunFirrtlTransformAnnotation}
+
+class ConvertSpecFirrtlTransform extends Transform {
+ def inputForm: CircuitForm = UnknownForm
+ def outputForm: CircuitForm = UnknownForm
+ def execute(state: CircuitState): CircuitState = state
+}
+
+case class ConvertSpecFirrtlAnnotation(name: String) extends NoTargetAnnotation
+
+case class ConvertSpecChiselAnnotation(name: String) extends ChiselAnnotation with RunFirrtlTransform {
+ def toFirrtl: Annotation = ConvertSpecFirrtlAnnotation(name)
+ def transformClass: Class[_ <: Transform] = classOf[ConvertSpecFirrtlTransform]
+}
+
+class ConvertSpecFoo extends RawModule {
+ override val desiredName: String = "foo"
+
+ val in = IO(Input(Bool()))
+ val out = IO(Output(Bool()))
+
+ experimental.annotate(ConvertSpecChiselAnnotation("bar"))
+}
+
+class ConvertSpec extends FlatSpec with Matchers {
+
+ class Fixture { val phase: Phase = new Convert }
+
+ behavior of classOf[Convert].toString
+
+ it should "convert a Chisel Circuit to a FIRRTL Circuit" in new Fixture {
+ val annos: AnnotationSeq = Seq(ChiselGeneratorAnnotation(() => new ConvertSpecFoo))
+
+ val annosx = Seq(new Elaborate, phase)
+ .foldLeft(annos)( (a, p) => p.transform(a) )
+
+ info("FIRRTL circuit generated")
+ annosx.collect{ case a: FirrtlCircuitAnnotation => a.circuit.main }.toSeq should be (Seq("foo"))
+
+ info("FIRRTL annotations generated")
+ annosx.collect{ case a: ConvertSpecFirrtlAnnotation => a.name }.toSeq should be (Seq("bar"))
+
+ info("FIRRTL transform annotations generated")
+ annosx.collect{ case a: RunFirrtlTransformAnnotation => a.transform.getClass}
+ .toSeq should be (Seq(classOf[ConvertSpecFirrtlTransform]))
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala b/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala
new file mode 100644
index 00000000..4d99b24c
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/phases/ElaborateSpec.scala
@@ -0,0 +1,46 @@
+// See LICENSE for license details.
+
+package chiselTests.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3._
+import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation}
+import chisel3.stage.phases.Elaborate
+
+import firrtl.options.Phase
+
+class ElaborateSpec extends FlatSpec with Matchers {
+
+ class Foo extends Module {
+ override def desiredName: String = "Foo"
+ val io = IO(
+ new Bundle {
+ val in = Input(Bool())
+ val out = Output(Bool())
+ })
+
+ io.out := ~io.in
+ }
+
+ class Bar extends Foo {
+ override def desiredName: String = "Bar"
+ }
+
+ class Fixture { val phase: Phase = new Elaborate }
+
+ behavior of classOf[Elaborate].toString
+
+ it should "expand ChiselGeneratorAnnotations into ChiselCircuitAnnotations and delete originals" in new Fixture {
+ val annotations = Seq( ChiselGeneratorAnnotation(() => new Foo),
+ ChiselGeneratorAnnotation(() => new Bar) )
+ val out = phase.transform(annotations)
+
+ info("original annotations removed")
+ out.collect{ case a: ChiselGeneratorAnnotation => a } should be (empty)
+
+ info("circuits created with the expected names")
+ out.collect{ case a: ChiselCircuitAnnotation => a.circuit.name } should be (Seq("Foo", "Bar"))
+ }
+
+}
diff --git a/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala b/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala
new file mode 100644
index 00000000..63498adb
--- /dev/null
+++ b/src/test/scala/chiselTests/stage/phases/EmitterSpec.scala
@@ -0,0 +1,60 @@
+// See LICENSE for license details.
+
+package chiselTests.stage.phases
+
+import org.scalatest.{FlatSpec, Matchers}
+
+import chisel3.experimental.RawModule
+import chisel3.stage.{ChiselCircuitAnnotation, ChiselGeneratorAnnotation, ChiselOutputFileAnnotation}
+import chisel3.stage.phases.{Convert, Elaborate, Emitter}
+
+import firrtl.{AnnotationSeq, EmittedFirrtlCircuitAnnotation}
+import firrtl.annotations.DeletedAnnotation
+import firrtl.options.{Phase, TargetDirAnnotation}
+
+import java.io.File
+
+class EmitterSpec extends FlatSpec with Matchers {
+
+ class FooModule extends RawModule { override val desiredName = "Foo" }
+ class BarModule extends RawModule { override val desiredName = "Bar" }
+
+ class Fixture { val phase: Phase = new Emitter }
+
+ behavior of classOf[Emitter].toString
+
+ it should "do nothing if no ChiselOutputFileAnnotations are present" in new Fixture {
+ val dir = new File("test_run_dir/EmitterSpec")
+ val annotations = (new Elaborate).transform(Seq( TargetDirAnnotation(dir.toString),
+ ChiselGeneratorAnnotation(() => new FooModule) ))
+ val annotationsx = phase.transform(annotations)
+
+ val Seq(fooFile, barFile) = Seq("Foo.fir", "Bar.fir").map(f => new File(dir + "/" + f))
+
+ info(s"$fooFile does not exist")
+ fooFile should not (exist)
+
+ info("annotations are unmodified")
+ annotationsx.toSeq should be (annotations.toSeq)
+ }
+
+ it should "emit a ChiselCircuitAnnotation to a specific file" in new Fixture {
+ val dir = new File("test_run_dir/EmitterSpec")
+ val circuit = (new Elaborate)
+ .transform(Seq(ChiselGeneratorAnnotation(() => new BarModule)))
+ .collectFirst{ case a: ChiselCircuitAnnotation => a}
+ .get
+ val annotations = phase.transform(Seq( TargetDirAnnotation(dir.toString),
+ circuit,
+ ChiselOutputFileAnnotation("Baz") ))
+
+ val bazFile = new File(dir + "/Baz.fir")
+
+ info(s"$bazFile exists")
+ bazFile should (exist)
+
+ info("a deleted EmittedFirrtlCircuitAnnotation should be generated")
+ annotations.collect{ case a @ DeletedAnnotation(_, _: EmittedFirrtlCircuitAnnotation) => a }.size should be (1)
+ }
+
+}