diff options
| author | Jack Koenig | 2017-03-06 14:51:20 -0600 |
|---|---|---|
| committer | GitHub | 2017-03-06 14:51:20 -0600 |
| commit | 3d58123ae654a2101ba81304ca3863b3be12c4f3 (patch) | |
| tree | 2e662485fef5327a2697dbd4a9b42a2cdc5bae5f /src/test | |
| parent | c89f74f19dd5162ee533a0a20825819bc52bc73e (diff) | |
Add ability to emit 1 file per module (#443)
Changes Emitters to also be Transforms and use Annotations for both
telling an emitter to do emission as well as getting the emitted result.
Helper functions ease the use of the new interface. Also adds a
FirrtlExecutionOptions field as well as a command-line option. Use of
Writers in Compilers and Emitters is now deprecated.
Diffstat (limited to 'src/test')
20 files changed, 179 insertions, 180 deletions
diff --git a/src/test/scala/firrtlTests/AnnotationTests.scala b/src/test/scala/firrtlTests/AnnotationTests.scala index 8acada93..29f8f51a 100644 --- a/src/test/scala/firrtlTests/AnnotationTests.scala +++ b/src/test/scala/firrtlTests/AnnotationTests.scala @@ -2,7 +2,7 @@ package firrtlTests -import java.io.{File, FileWriter, StringWriter, Writer} +import java.io.{File, FileWriter, Writer} import firrtl.annotations.AnnotationYamlProtocol._ import firrtl.annotations._ @@ -20,14 +20,14 @@ trait AnnotationSpec extends LowTransformSpec { def transform = new CustomResolveAndCheck(LowForm) // Check if Annotation Exception is thrown - override def failingexecute(writer: Writer, annotations: AnnotationMap, input: String): Exception = { + override def failingexecute(annotations: AnnotationMap, input: String): Exception = { intercept[AnnotationException] { - compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), writer) + compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), Seq.empty) } } - def execute(writer: Writer, annotations: AnnotationMap, input: String, check: Annotation): Unit = { - val cr = compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), writer) - cr.annotations.get.annotations should be (Seq(check)) + def execute(annotations: AnnotationMap, input: String, check: Annotation): Unit = { + val cr = compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), Seq.empty) + cr.annotations.get.annotations should contain (check) } } @@ -53,9 +53,8 @@ class AnnotationTests extends AnnotationSpec with Matchers { val cName = ComponentName("c", mName) "Loose and Sticky annotation on a node" should "pass through" in { - val w = new StringWriter() val ta = Annotation(cName, classOf[Transform], "") - execute(w, getAMap(ta), input, ta) + execute(getAMap(ta), input, ta) } "Annotations" should "be readable from file" in { diff --git a/src/test/scala/firrtlTests/AttachSpec.scala b/src/test/scala/firrtlTests/AttachSpec.scala index 5eed33bd..c29a7e43 100644 --- a/src/test/scala/firrtlTests/AttachSpec.scala +++ b/src/test/scala/firrtlTests/AttachSpec.scala @@ -12,14 +12,6 @@ import firrtl.passes._ import firrtl.Parser.IgnoreInfo class InoutVerilogSpec extends FirrtlFlatSpec { - private def executeTest(input: String, expected: Seq[String], compiler: Compiler) = { - val writer = new StringWriter() - compiler.compile(CircuitState(parse(input), ChirrtlForm), writer) - val lines = writer.toString().split("\n") map normalized - expected foreach { e => - lines should contain(e) - } - } behavior of "Analog" diff --git a/src/test/scala/firrtlTests/CInferMDirSpec.scala b/src/test/scala/firrtlTests/CInferMDirSpec.scala index 3721543b..773a0bf3 100644 --- a/src/test/scala/firrtlTests/CInferMDirSpec.scala +++ b/src/test/scala/firrtlTests/CInferMDirSpec.scala @@ -70,9 +70,8 @@ circuit foo : """.stripMargin val annotationMap = AnnotationMap(Nil) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(annotationMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(annotationMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) } } diff --git a/src/test/scala/firrtlTests/ChirrtlMemSpec.scala b/src/test/scala/firrtlTests/ChirrtlMemSpec.scala index 2bbe46c8..fd984661 100644 --- a/src/test/scala/firrtlTests/ChirrtlMemSpec.scala +++ b/src/test/scala/firrtlTests/ChirrtlMemSpec.scala @@ -77,10 +77,9 @@ circuit foo : """.stripMargin val annotationMap = AnnotationMap(Nil) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(annotationMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(annotationMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) } "Combinational Memory" should "have correct enable signals" in { @@ -104,9 +103,8 @@ circuit foo : """.stripMargin val annotationMap = AnnotationMap(Nil) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(annotationMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(annotationMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) } } diff --git a/src/test/scala/firrtlTests/CompilerTests.scala b/src/test/scala/firrtlTests/CompilerTests.scala index a9fce0c2..39d54755 100644 --- a/src/test/scala/firrtlTests/CompilerTests.scala +++ b/src/test/scala/firrtlTests/CompilerTests.scala @@ -2,8 +2,6 @@ package firrtlTests -import java.io.StringWriter - import org.scalatest.FlatSpec import org.scalatest.Matchers import org.scalatest.junit.JUnitRunner @@ -29,13 +27,12 @@ import firrtl.{ */ abstract class CompilerSpec extends FlatSpec { def parse (s: String): Circuit = Parser.parse(s.split("\n").toIterator) - val writer = new StringWriter() def compiler: Compiler def input: String def check: String def getOutput: String = { - compiler.compile(CircuitState(parse(input), ChirrtlForm), writer) - writer.toString() + val res = compiler.compileAndEmit(CircuitState(parse(input), ChirrtlForm)) + res.getEmittedCircuit.value } } @@ -170,6 +167,6 @@ circuit Top : "endmodule\n" ).reduce(_ + "\n" + _) "A circuit's verilog output" should "match the given string" in { - (getOutput) should be (check) + getOutput should be (check) } } diff --git a/src/test/scala/firrtlTests/ConstantPropagationTests.scala b/src/test/scala/firrtlTests/ConstantPropagationTests.scala index 4506f4ec..95785717 100644 --- a/src/test/scala/firrtlTests/ConstantPropagationTests.scala +++ b/src/test/scala/firrtlTests/ConstantPropagationTests.scala @@ -3,7 +3,6 @@ package firrtlTests import org.scalatest.Matchers -import java.io.{StringWriter,Writer} import firrtl.ir.Circuit import firrtl.Parser.IgnoreInfo import firrtl.Parser diff --git a/src/test/scala/firrtlTests/DriverSpec.scala b/src/test/scala/firrtlTests/DriverSpec.scala index 4e1add39..9cbeb6f9 100644 --- a/src/test/scala/firrtlTests/DriverSpec.scala +++ b/src/test/scala/firrtlTests/DriverSpec.scala @@ -66,7 +66,7 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities val firrtlOptions = optionsManager.firrtlOptions val inputFileName = optionsManager.getBuildFileName("fir", firrtlOptions.inputFileNameOverride) inputFileName should be ("./cat.fir") - val outputFileName = optionsManager.getBuildFileName("v", firrtlOptions.outputFileNameOverride) + val outputFileName = firrtlOptions.getTargetFile(optionsManager) outputFileName should be ("./cat.v") } "input and output file names can be overridden, overrides do not use targetDir" in { @@ -79,7 +79,7 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities val firrtlOptions = optionsManager.firrtlOptions val inputFileName = optionsManager.getBuildFileName("fir", firrtlOptions.inputFileNameOverride) inputFileName should be ("./bob.fir") - val outputFileName = optionsManager.getBuildFileName("v", firrtlOptions.outputFileNameOverride) + val outputFileName = firrtlOptions.getTargetFile(optionsManager) outputFileName should be ("carol.v") } "various annotations can be created from command line, currently:" - { @@ -142,26 +142,31 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities annotationsTestFile.delete() } - val input = - """ - |circuit Dummy : - | module Dummy : - | input x : UInt<1> - | output y : UInt<1> - | y <= x - """.stripMargin - - "Driver produces files with different names depending on the compiler" - { - "compiler changes the default name of the output file" in { - + "Circuits are emitted on properly" - { + val input = + """|circuit Top : + | module Top : + | output foo : UInt<32> + | inst c of Child + | inst e of External + | foo <= tail(add(c.foo, e.foo), 1) + | module Child : + | output foo : UInt<32> + | inst e of External + | foo <= e.foo + | extmodule External : + | output foo : UInt<32> + """.stripMargin + + "To a single file with file extension depending on the compiler by default" in { Seq( - "low" -> "./Dummy.lo.fir", - "high" -> "./Dummy.hi.fir", - "middle" -> "./Dummy.mid.fir", - "verilog" -> "./Dummy.v" + "low" -> "./Top.lo.fir", + "high" -> "./Top.hi.fir", + "middle" -> "./Top.mid.fir", + "verilog" -> "./Top.v" ).foreach { case (compilerName, expectedOutputFileName) => val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions { - commonOptions = CommonOptions(topName = "Dummy") + commonOptions = CommonOptions(topName = "Top") firrtlOptions = FirrtlExecutionOptions(firrtlSource = Some(input), compilerName = compilerName) } @@ -172,8 +177,33 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities file.delete() } } + "To a single file per module if OneFilePerModule is specified" in { + Seq( + "low" -> Seq("./Top.lo.fir", "./Child.lo.fir"), + "high" -> Seq("./Top.hi.fir", "./Child.hi.fir"), + "middle" -> Seq("./Top.mid.fir", "./Child.mid.fir"), + "verilog" -> Seq("./Top.v", "./Child.v") + ).foreach { case (compilerName, expectedOutputFileNames) => + println(s"$compilerName -> $expectedOutputFileNames") + val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions { + commonOptions = CommonOptions(topName = "Top") + firrtlOptions = FirrtlExecutionOptions(firrtlSource = Some(input), + compilerName = compilerName, + emitOneFilePerModule = true) + } + + firrtl.Driver.execute(manager) + + for (name <- expectedOutputFileNames) { + val file = new File(name) + file.exists() should be (true) + file.delete() + } + } + } } + "Directory deleter is handy for cleaning up after tests" - { "for example making a directory tree, and deleting it looks like" in { FileUtils.makeDirectory("dog/fox/wolf") diff --git a/src/test/scala/firrtlTests/FirrtlSpec.scala b/src/test/scala/firrtlTests/FirrtlSpec.scala index 7dd439e4..6bf73a80 100644 --- a/src/test/scala/firrtlTests/FirrtlSpec.scala +++ b/src/test/scala/firrtlTests/FirrtlSpec.scala @@ -16,15 +16,13 @@ import firrtl.annotations import firrtl.util.BackendCompilationUtilities trait FirrtlRunners extends BackendCompilationUtilities { - def parse(str: String) = Parser.parse(str.split("\n").toIterator, IgnoreInfo) lazy val cppHarness = new File(s"/top.cpp") /** Compiles input Firrtl to Verilog */ def compileToVerilog(input: String, annotations: AnnotationMap = AnnotationMap(Seq.empty)): String = { val circuit = Parser.parse(input.split("\n").toIterator) val compiler = new VerilogCompiler - val writer = new java.io.StringWriter - compiler.compile(CircuitState(circuit, HighForm, Some(annotations)), writer) - writer.toString + val res = compiler.compileAndEmit(CircuitState(circuit, HighForm, Some(annotations))) + res.getEmittedCircuit.value } /** Compile a Firrtl file * @@ -40,13 +38,15 @@ trait FirrtlRunners extends BackendCompilationUtilities { val testDir = createTestDirectory(prefix) copyResourceToFile(s"${srcDir}/${prefix}.fir", new File(testDir, s"${prefix}.fir")) - Driver.compile( - s"$testDir/$prefix.fir", - s"$testDir/$prefix.v", - new VerilogCompiler(), - Parser.IgnoreInfo, - customTransforms, - annotations) + val optionsManager = new ExecutionOptionsManager(prefix) with HasFirrtlOptions { + commonOptions = CommonOptions(topName = prefix, targetDirName = testDir.getPath) + firrtlOptions = FirrtlExecutionOptions( + infoModeName = "ignore", + customTransforms = customTransforms, + annotations = annotations.annotations.toList) + } + firrtl.Driver.execute(optionsManager) + testDir } /** Execute a Firrtl Test @@ -79,7 +79,7 @@ trait FirrtlRunners extends BackendCompilationUtilities { } } -trait FirrtlMatchers { +trait FirrtlMatchers extends Matchers { // Replace all whitespace with a single space and remove leading and // trailing whitespace // Note this is intended for single-line strings, no newlines @@ -87,11 +87,23 @@ trait FirrtlMatchers { require(!s.contains("\n")) s.replaceAll("\\s+", " ").trim } + def parse(str: String) = Parser.parse(str.split("\n").toIterator, IgnoreInfo) + /** Helper for executing tests + * compiler will be run on input then emitted result will each be split into + * lines and normalized. + */ + def executeTest(input: String, expected: Seq[String], compiler: Compiler) = { + val finalState = compiler.compileAndEmit(CircuitState(parse(input), ChirrtlForm)) + val lines = finalState.getEmittedCircuit.value split "\n" map normalized + for (e <- expected) { + lines should contain (e) + } + } } abstract class FirrtlPropSpec extends PropSpec with PropertyChecks with FirrtlRunners with LazyLogging -abstract class FirrtlFlatSpec extends FlatSpec with Matchers with FirrtlRunners with FirrtlMatchers with LazyLogging +abstract class FirrtlFlatSpec extends FlatSpec with FirrtlRunners with FirrtlMatchers with LazyLogging /** Super class for execution driven Firrtl tests */ abstract class ExecutionTest(name: String, dir: String, vFiles: Seq[String] = Seq.empty) extends FirrtlPropSpec { diff --git a/src/test/scala/firrtlTests/InferReadWriteSpec.scala b/src/test/scala/firrtlTests/InferReadWriteSpec.scala index a5eea147..91dc911c 100644 --- a/src/test/scala/firrtlTests/InferReadWriteSpec.scala +++ b/src/test/scala/firrtlTests/InferReadWriteSpec.scala @@ -42,6 +42,7 @@ class InferReadWriteSpec extends SimpleTransformSpec { def passSeq = Seq(InferReadWriteCheckPass) } + def emitter = new MiddleFirrtlEmitter def transforms = Seq( new ChirrtlToHighFirrtl, new IRToWorkingIR, @@ -76,10 +77,9 @@ circuit sram6t : """.stripMargin val annotationMap = AnnotationMap(Seq(memlib.InferReadWriteAnnotation("sram6t"))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(annotationMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(annotationMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) } "Infer ReadWrite Ports" should "not infer readwrite ports for the difference clocks" in { @@ -108,9 +108,8 @@ circuit sram6t : """.stripMargin val annotationMap = AnnotationMap(Seq(memlib.InferReadWriteAnnotation("sram6t"))) - val writer = new java.io.StringWriter intercept[InferReadWriteCheckException] { - compile(CircuitState(parse(input), ChirrtlForm, Some(annotationMap)), writer) + compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(annotationMap))) } } } diff --git a/src/test/scala/firrtlTests/InlineInstancesTests.scala b/src/test/scala/firrtlTests/InlineInstancesTests.scala index 89862145..25a194d4 100644 --- a/src/test/scala/firrtlTests/InlineInstancesTests.scala +++ b/src/test/scala/firrtlTests/InlineInstancesTests.scala @@ -2,8 +2,6 @@ package firrtlTests -import java.io.StringWriter - import org.scalatest.FlatSpec import org.scalatest.Matchers import org.scalatest.junit.JUnitRunner @@ -49,9 +47,8 @@ class InlineInstancesTests extends LowTransformSpec { | i$b <= i$a | b <= i$b | i$a <= a""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("Inline", CircuitName("Top"))))) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "The all instances of Simple" should "be inlined" in { @@ -83,9 +80,8 @@ class InlineInstancesTests extends LowTransformSpec { | b <= i1$b | i0$a <= a | i1$a <= i0$b""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("Simple", CircuitName("Top"))))) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "Only one instance of Simple" should "be inlined" in { @@ -119,9 +115,8 @@ class InlineInstancesTests extends LowTransformSpec { | input a : UInt<32> | output b : UInt<32> | b <= a""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ComponentName("i0",ModuleName("Top", CircuitName("Top")))))) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "All instances of A" should "be inlined" in { @@ -165,9 +160,8 @@ class InlineInstancesTests extends LowTransformSpec { | i$b <= i$a | b <= i$b | i$a <= a""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("A", CircuitName("Top"))))) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "Non-inlined instances" should "still prepend prefix" in { @@ -205,9 +199,8 @@ class InlineInstancesTests extends LowTransformSpec { | input a : UInt<32> | output b : UInt<32> | b <= a""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("A", CircuitName("Top"))))) - execute(writer, aMap, input, check) + execute(aMap, input, check) } // ---- Errors ---- @@ -224,9 +217,8 @@ class InlineInstancesTests extends LowTransformSpec { | extmodule A : | input a : UInt<32> | output b : UInt<32>""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("A", CircuitName("Top"))))) - failingexecute(writer, aMap, input) + failingexecute(aMap, input) } // 2) ext instance "External instance" should "not be inlined" in { @@ -241,9 +233,8 @@ class InlineInstancesTests extends LowTransformSpec { | extmodule A : | input a : UInt<32> | output b : UInt<32>""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("A", CircuitName("Top"))))) - failingexecute(writer, aMap, input) + failingexecute(aMap, input) } // 3) no module "Inlined module" should "exist" in { @@ -253,9 +244,8 @@ class InlineInstancesTests extends LowTransformSpec { | input a : UInt<32> | output b : UInt<32> | b <= a""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("A", CircuitName("Top"))))) - failingexecute(writer, aMap, input) + failingexecute(aMap, input) } // 4) no inst "Inlined instance" should "exist" in { @@ -265,9 +255,8 @@ class InlineInstancesTests extends LowTransformSpec { | input a : UInt<32> | output b : UInt<32> | b <= a""".stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(InlineAnnotation(ModuleName("A", CircuitName("Top"))))) - failingexecute(writer, aMap, input) + failingexecute(aMap, input) } } diff --git a/src/test/scala/firrtlTests/IntegrationSpec.scala b/src/test/scala/firrtlTests/IntegrationSpec.scala index 335922bd..52fbb611 100644 --- a/src/test/scala/firrtlTests/IntegrationSpec.scala +++ b/src/test/scala/firrtlTests/IntegrationSpec.scala @@ -2,13 +2,51 @@ package firrtlTests +import firrtl._ import org.scalatest._ import org.scalatest.prop._ +import java.io.File + class GCDExecutionTest extends ExecutionTest("GCDTester", "/integration") class RightShiftExecutionTest extends ExecutionTest("RightShiftTester", "/integration") class MemExecutionTest extends ExecutionTest("MemTester", "/integration") +// This is a bit custom some kind of one off +class GCDSplitEmissionExecutionTest extends FirrtlFlatSpec { + "GCDTester" should "work even when the modules are emitted to different files" in { + val top = "GCDTester" + val testDir = createTestDirectory("GCDTesterSplitEmission") + val sourceFile = new File(testDir, s"$top.fir") + copyResourceToFile(s"/integration/$top.fir", sourceFile) + + val optionsManager = new ExecutionOptionsManager("GCDTesterSplitEmission") with HasFirrtlOptions { + commonOptions = CommonOptions(topName = top, targetDirName = testDir.getPath) + firrtlOptions = FirrtlExecutionOptions( + inputFileNameOverride = sourceFile.getPath, + compilerName = "verilog", + infoModeName = "ignore", + emitOneFilePerModule = true) + } + firrtl.Driver.execute(optionsManager) + + // expected filenames + val dutFile = new File(testDir, "DecoupledGCD.v") + val topFile = new File(testDir, s"$top.v") + dutFile should exist + topFile should exist + + // Copy harness over + val harness = new File(testDir, s"top.cpp") + copyResourceToFile(cppHarness.toString, harness) + + // topFile will be compiled by Verilator command by default but we need to also include dutFile + verilogToCpp(top, testDir, Seq(dutFile), harness).! + cppToExe(top, testDir).! + assert(executeExpectingSuccess(top, testDir)) + } +} + class RocketCompilationTest extends CompilationTest("rocket", "/regress") class RocketFirrtlCompilationTest extends CompilationTest("rocket-firrtl", "/regress") class BOOMRobCompilationTest extends CompilationTest("Rob", "/regress") diff --git a/src/test/scala/firrtlTests/MultiThreadingSpec.scala b/src/test/scala/firrtlTests/MultiThreadingSpec.scala index 1698c462..444faebc 100644 --- a/src/test/scala/firrtlTests/MultiThreadingSpec.scala +++ b/src/test/scala/firrtlTests/MultiThreadingSpec.scala @@ -13,10 +13,9 @@ class MultiThreadingSpec extends FirrtlPropSpec { property("The FIRRTL compiler should be thread safe") { // Run the compiler we're testing def runCompiler(input: Seq[String], compiler: firrtl.Compiler): String = { - val writer = new java.io.StringWriter val parsedInput = firrtl.Parser.parse(input) - compiler.compile(CircuitState(parsedInput, ChirrtlForm), writer) - writer.toString + val res = compiler.compileAndEmit(CircuitState(parsedInput, ChirrtlForm)) + res.getEmittedCircuit.value } // The parameters we're testing with val compilers = Seq( diff --git a/src/test/scala/firrtlTests/PassTests.scala b/src/test/scala/firrtlTests/PassTests.scala index c417c4fb..df56c097 100644 --- a/src/test/scala/firrtlTests/PassTests.scala +++ b/src/test/scala/firrtlTests/PassTests.scala @@ -9,50 +9,28 @@ import org.scalatest.junit.JUnitRunner import firrtl.ir.Circuit import firrtl.Parser.UseInfo import firrtl.passes.{Pass, PassExceptions, RemoveEmpty} -import firrtl.{ - Transform, - AnnotationMap, - PassBasedTransform, - CircuitState, - CircuitForm, - ChirrtlForm, - HighForm, - MidForm, - LowForm, - SimpleRun, - ChirrtlToHighFirrtl, - IRToWorkingIR, - ResolveAndCheck, - HighFirrtlToMiddleFirrtl, - MiddleFirrtlToLowFirrtl, - FirrtlEmitter, - Compiler, - Parser -} - +import firrtl._ // An example methodology for testing Firrtl Passes // Spec class should extend this class abstract class SimpleTransformSpec extends FlatSpec with Matchers with Compiler with LazyLogging { - def emitter = new FirrtlEmitter - // Utility function def parse(s: String): Circuit = Parser.parse(s.split("\n").toIterator, infoMode = UseInfo) def squash(c: Circuit): Circuit = RemoveEmpty.run(c) // Executes the test. Call in tests. - def execute(writer: Writer, annotations: AnnotationMap, input: String, check: String): Unit = { - compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), writer) - val actual = RemoveEmpty.run(parse(writer.toString)).serialize + def execute(annotations: AnnotationMap, input: String, check: String): Unit = { + val finalState = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(annotations))) + val actual = RemoveEmpty.run(parse(finalState.getEmittedCircuit.value)).serialize val expected = parse(check).serialize logger.debug(actual) logger.debug(expected) (actual) should be (expected) } // Executes the test, should throw an error - def failingexecute(writer: Writer, annotations: AnnotationMap, input: String): Exception = { + def failingexecute(annotations: AnnotationMap, input: String): Exception = { intercept[PassExceptions] { - compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), writer) + compile(CircuitState(parse(input), ChirrtlForm, Some(annotations)), Seq.empty) } } } @@ -65,6 +43,7 @@ class CustomResolveAndCheck(form: CircuitForm) extends PassBasedTransform { } trait LowTransformSpec extends SimpleTransformSpec { + def emitter = new LowFirrtlEmitter def transform: Transform def transforms = Seq( new ChirrtlToHighFirrtl(), @@ -78,6 +57,7 @@ trait LowTransformSpec extends SimpleTransformSpec { } trait MiddleTransformSpec extends SimpleTransformSpec { + def emitter = new MiddleFirrtlEmitter def transform: Transform def transforms = Seq( new ChirrtlToHighFirrtl(), @@ -90,6 +70,7 @@ trait MiddleTransformSpec extends SimpleTransformSpec { } trait HighTransformSpec extends SimpleTransformSpec { + def emitter = new HighFirrtlEmitter def transform: Transform def transforms = Seq( new ChirrtlToHighFirrtl(), diff --git a/src/test/scala/firrtlTests/ReplSeqMemTests.scala b/src/test/scala/firrtlTests/ReplSeqMemTests.scala index 01a4501b..1a5b44e6 100644 --- a/src/test/scala/firrtlTests/ReplSeqMemTests.scala +++ b/src/test/scala/firrtlTests/ReplSeqMemTests.scala @@ -9,6 +9,7 @@ import firrtl.passes.memlib._ import annotations._ class ReplSeqMemSpec extends SimpleTransformSpec { + def emitter = new LowFirrtlEmitter def transforms = Seq( new ChirrtlToHighFirrtl(), new IRToWorkingIR(), @@ -62,10 +63,9 @@ circuit Top : """.stripMargin val confLoc = "ReplSeqMemTests.confTEMP" val aMap = AnnotationMap(Seq(ReplSeqMemAnnotation("-c:Top:-o:"+confLoc))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) (new java.io.File(confLoc)).delete() } @@ -85,10 +85,9 @@ circuit Top : """.stripMargin val confLoc = "ReplSeqMemTests.confTEMP" val aMap = AnnotationMap(Seq(ReplSeqMemAnnotation("-c:Top:-o:"+confLoc))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) (new java.io.File(confLoc)).delete() } @@ -111,10 +110,9 @@ circuit CustomMemory : """.stripMargin val confLoc = "ReplSeqMemTests.confTEMP" val aMap = AnnotationMap(Seq(ReplSeqMemAnnotation("-c:CustomMemory:-o:"+confLoc))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) (new java.io.File(confLoc)).delete() } @@ -137,10 +135,9 @@ circuit CustomMemory : """.stripMargin val confLoc = "ReplSeqMemTests.confTEMP" val aMap = AnnotationMap(Seq(ReplSeqMemAnnotation("-c:CustomMemory:-o:"+confLoc))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - parse(writer.toString) + parse(res.getEmittedCircuit.value) (new java.io.File(confLoc)).delete() } @@ -213,10 +210,9 @@ circuit CustomMemory : val aMap = AnnotationMap(Seq( ReplSeqMemAnnotation("-c:CustomMemory:-o:"+confLoc), NoDedupMemAnnotation(ComponentName("mem_0", ModuleName("CustomMemory",CircuitName("CustomMemory")))))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - val circuit = parse(writer.toString) + val circuit = parse(res.getEmittedCircuit.value) val numExtMods = circuit.modules.count { case e: ExtModule => true case _ => false @@ -254,10 +250,9 @@ circuit CustomMemory : val aMap = AnnotationMap(Seq( ReplSeqMemAnnotation("-c:CustomMemory:-o:"+confLoc), NoDedupMemAnnotation(ComponentName("mem_1", ModuleName("CustomMemory",CircuitName("CustomMemory")))))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - val circuit = parse(writer.toString) + val circuit = parse(res.getEmittedCircuit.value) val numExtMods = circuit.modules.count { case e: ExtModule => true case _ => false @@ -289,10 +284,9 @@ circuit CustomMemory : """ val confLoc = "ReplSeqMemTests.confTEMP" val aMap = AnnotationMap(Seq(ReplSeqMemAnnotation("-c:CustomMemory:-o:"+confLoc))) - val writer = new java.io.StringWriter - compile(CircuitState(parse(input), ChirrtlForm, Some(aMap)), writer) + val res = compileAndEmit(CircuitState(parse(input), ChirrtlForm, Some(aMap))) // Check correctness of firrtl - val circuit = parse(writer.toString) + val circuit = parse(res.getEmittedCircuit.value) val numExtMods = circuit.modules.count { case e: ExtModule => true case _ => false diff --git a/src/test/scala/firrtlTests/UnitTests.scala b/src/test/scala/firrtlTests/UnitTests.scala index ec328818..3cf25d3a 100644 --- a/src/test/scala/firrtlTests/UnitTests.scala +++ b/src/test/scala/firrtlTests/UnitTests.scala @@ -107,7 +107,7 @@ class UnitTests extends FirrtlFlatSpec { (c: Circuit, p: Pass) => p.run(c) } val writer = new StringWriter() - (new FirrtlEmitter).emit(CircuitState(c_result, HighForm), writer) + (new HighFirrtlEmitter).emit(CircuitState(c_result, HighForm), writer) (parse(writer.toString())) should be (parse(check)) } @@ -129,7 +129,8 @@ class UnitTests extends FirrtlFlatSpec { intercept[PassException] { val c = Parser.parse(splitExpTestCode.split("\n").toIterator) val c2 = passes.foldLeft(c)((c, p) => p run c) - (new VerilogEmitter).emit(CircuitState(c2, LowForm), new StringWriter) + val writer = new StringWriter() + (new VerilogEmitter).emit(CircuitState(c2, LowForm), writer) } } @@ -140,7 +141,8 @@ class UnitTests extends FirrtlFlatSpec { InferTypes) val c = Parser.parse(splitExpTestCode.split("\n").toIterator) val c2 = passes.foldLeft(c)((c, p) => p run c) - (new VerilogEmitter).emit(CircuitState(c2, LowForm), new StringWriter) + val writer = new StringWriter() + (new VerilogEmitter).emit(CircuitState(c2, LowForm), writer) } "Simple compound expressions" should "be split" in { diff --git a/src/test/scala/firrtlTests/VerilogEmitterTests.scala b/src/test/scala/firrtlTests/VerilogEmitterTests.scala index 862a9605..6928718a 100644 --- a/src/test/scala/firrtlTests/VerilogEmitterTests.scala +++ b/src/test/scala/firrtlTests/VerilogEmitterTests.scala @@ -12,14 +12,6 @@ import firrtl.passes._ import firrtl.Parser.IgnoreInfo class DoPrimVerilog extends FirrtlFlatSpec { - private def executeTest(input: String, expected: Seq[String], compiler: Compiler) = { - val writer = new StringWriter() - compiler.compile(CircuitState(parse(input), ChirrtlForm), writer) - val lines = writer.toString().split("\n") map normalized - expected foreach { e => - lines should contain(e) - } - } "Xorr" should "emit correctly" in { val compiler = new VerilogCompiler val input = diff --git a/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala b/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala index 0c30b59e..39da2a33 100644 --- a/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala +++ b/src/test/scala/firrtlTests/fixed/FixedPointMathSpec.scala @@ -2,8 +2,6 @@ package firrtlTests.fixed -import java.io.StringWriter - import firrtl.{CircuitState, ChirrtlForm, LowFirrtlCompiler, Parser, AnnotationMap} import firrtl.Parser.IgnoreInfo import firrtlTests.FirrtlFlatSpec @@ -41,11 +39,9 @@ class FixedPointMathSpec extends FirrtlFlatSpec { val lowerer = new LowFirrtlCompiler - val writer = new StringWriter() - - lowerer.compile(CircuitState(parse(input), ChirrtlForm), writer) + val res = lowerer.compileAndEmit(CircuitState(parse(input), ChirrtlForm)) - val output = writer.toString.split("\n") + val output = res.getEmittedCircuit.value split "\n" def inferredAddWidth: Int = { val binaryDifference = binaryPoint1 - binaryPoint2 diff --git a/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala b/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala index 44fa1d29..37209786 100644 --- a/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala +++ b/src/test/scala/firrtlTests/fixed/FixedTypeInferenceSpec.scala @@ -20,14 +20,6 @@ class FixedTypeInferenceSpec extends FirrtlFlatSpec { lines should contain(e) } } - private def executeTest(input: String, expected: Seq[String], compiler: Compiler) = { - val writer = new StringWriter() - compiler.compile(CircuitState(parse(input), ChirrtlForm), writer) - val lines = writer.toString().split("\n") map normalized - expected foreach { e => - lines should contain(e) - } - } "Fixed types" should "infer add correctly" in { val passes = Seq( diff --git a/src/test/scala/firrtlTests/transforms/BlacklBoxSourceHelperSpec.scala b/src/test/scala/firrtlTests/transforms/BlacklBoxSourceHelperSpec.scala index b037accf..8cd51b2a 100644 --- a/src/test/scala/firrtlTests/transforms/BlacklBoxSourceHelperSpec.scala +++ b/src/test/scala/firrtlTests/transforms/BlacklBoxSourceHelperSpec.scala @@ -2,8 +2,6 @@ package firrtlTests.transforms -import java.io.StringWriter - import firrtl.annotations.{Annotation, CircuitName, ModuleName} import firrtl.transforms._ import firrtl.{AnnotationMap, FIRRTLException, Transform, VerilogCompiler} @@ -80,13 +78,12 @@ class BlacklBoxSourceHelperTransformSpec extends LowTransformSpec { "annotated external modules" should "appear in output directory" in { - val writer = new StringWriter() val aMap = AnnotationMap(Seq( Annotation(moduleName, classOf[BlackBoxSourceHelper], BlackBoxTargetDir("test_run_dir").serialize), Annotation(moduleName, classOf[BlackBoxSourceHelper], BlackBoxResource("/blackboxes/AdderExtModule.v").serialize) )) - execute(writer, aMap, input, output) + execute(aMap, input, output) new java.io.File("test_run_dir/AdderExtModule.v").exists should be (true) new java.io.File(s"test_run_dir/${BlackBoxSourceHelper.FileListName}").exists should be (true) diff --git a/src/test/scala/firrtlTests/transforms/DedupTests.scala b/src/test/scala/firrtlTests/transforms/DedupTests.scala index 62015388..7148dd11 100644 --- a/src/test/scala/firrtlTests/transforms/DedupTests.scala +++ b/src/test/scala/firrtlTests/transforms/DedupTests.scala @@ -3,8 +3,6 @@ package firrtlTests package transform -import java.io.StringWriter - import org.scalatest.FlatSpec import org.scalatest.Matchers import org.scalatest.junit.JUnitRunner @@ -48,9 +46,8 @@ class DedupModuleTests extends HighTransformSpec { | output x: UInt<1> | x <= UInt(1) """.stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Nil) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "The module A and B" should "be deduped" in { val input = @@ -86,9 +83,8 @@ class DedupModuleTests extends HighTransformSpec { | output x: UInt<1> | x <= UInt(1) """.stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Nil) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "The module A and B with comments" should "be deduped" in { val input = @@ -124,9 +120,8 @@ class DedupModuleTests extends HighTransformSpec { | output x: UInt<1> | x <= UInt(1) """.stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Nil) - execute(writer, aMap, input, check) + execute(aMap, input, check) } "The module B, but not A, with comments" should "be deduped if not annotated" in { val input = @@ -153,9 +148,8 @@ class DedupModuleTests extends HighTransformSpec { | output x: UInt<1> @[xx 1:1] | x <= UInt(1) """.stripMargin - val writer = new StringWriter() val aMap = new AnnotationMap(Seq(NoDedupAnnotation(ModuleName("A", CircuitName("Top"))))) - execute(writer, aMap, input, check) + execute(aMap, input, check) } } |
