diff options
| author | ducky | 2015-12-09 17:21:38 -0800 |
|---|---|---|
| committer | ducky | 2015-12-09 17:27:08 -0800 |
| commit | 2785c3337a323e343141fd6a7fe4d2468e7feb34 (patch) | |
| tree | 06815b9314650e40816d41eaff3989fdd2000a21 /src | |
| parent | 996ea685649136229b62579bdc1aecdb7e14d4dc (diff) | |
Refactor testharness generation to create directories and have minimal API
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/Chisel/Driver.scala | 57 | ||||
| -rw-r--r-- | src/main/scala/Chisel/testers/TesterDriver.scala | 21 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Harness.scala | 36 |
3 files changed, 55 insertions, 59 deletions
diff --git a/src/main/scala/Chisel/Driver.scala b/src/main/scala/Chisel/Driver.scala index b57653c3..7f950025 100644 --- a/src/main/scala/Chisel/Driver.scala +++ b/src/main/scala/Chisel/Driver.scala @@ -8,26 +8,20 @@ import java.io._ import internal._ import firrtl._ -trait FileSystemUtilities { - def writeTempFile(pre: String, post: String, contents: String): File = { - val t = File.createTempFile(pre, post) - val w = new FileWriter(t) - w.write(contents) - w.close() - t - } - - // This "fire-and-forgets" the method, which can be lazily read through - // a Stream[String], and accumulates all errors on a StringBuffer - def sourceFilesAt(baseDir: String): (Stream[String], StringBuffer) = { - val buffer = new StringBuffer() - val cmd = Seq("find", baseDir, "-name", "*.scala", "-type", "f") - val lines = cmd lines_! ProcessLogger(buffer append _) - (lines, buffer) +trait BackendCompilationUtilities { + /** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6. + */ + def createTempDirectory(prefix: String): File = { + val temp = File.createTempFile(prefix, "") + if (!temp.delete()) { + throw new IOException(s"Unable to delete temp file '$temp'") + } + if (!temp.mkdir()) { + throw new IOException(s"Unable to create temp directory '$temp'") + } + temp } -} -trait BackendCompilationUtilities { def makeHarness(template: String => String, post: String)(f: File): File = { val prefix = f.toString.split("/").last val vf = new File(f.toString + post) @@ -49,29 +43,33 @@ trait BackendCompilationUtilities { /** Generates a Verilator invocation to convert Verilog sources to C++ * simulation sources. * - * @param prefix output class name + * The Verilator prefix will be V$dutFile, and running this will generate + * C++ sources and headers as well as a makefile to compile them. + * + * Verilator will automatically locate the top-level module as the one among + * all the files which are not included elsewhere. If multiple ones exist, + * the compilation will fail. + * + * @param dutFile name of the DUT .v without the .v extension * @param dir output directory - * @oaran vDut .v file containing the top-level DUR * @param vSources list of additional Verilog sources to compile * @param cppHarness C++ testharness to compile/link against - * @param vH .h file to generate */ def verilogToCpp( - prefix: String, + dutFile: String, dir: File, - vDut: File, vSources: Seq[File], - cppHarness: File, - vH: File): ProcessBuilder = + cppHarness: File): ProcessBuilder = + Seq("verilator", - "--cc", vDut.toString) ++ + "--cc", s"$dutFile.v") ++ vSources.map(file => Seq("-v", file.toString)).flatten ++ Seq("--assert", "--Wno-fatal", "--trace", "-O2", - "+define+TOP_TYPE=V" + prefix, - "-CFLAGS", s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$prefix -include ${vH.toString}""", + "+define+TOP_TYPE=V" + dutFile, + "-CFLAGS", s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""", "-Mdir", dir.toString, "--exe", cppHarness.toString) @@ -91,10 +89,9 @@ trait BackendCompilationUtilities { def executeExpectingSuccess(prefix: String, dir: File): Boolean = { !executeExpectingFailure(prefix, dir) } - } -object Driver extends FileSystemUtilities with BackendCompilationUtilities { +object Driver extends BackendCompilationUtilities { /** Elaborates the Module specified in the gen function into a Circuit * diff --git a/src/main/scala/Chisel/testers/TesterDriver.scala b/src/main/scala/Chisel/testers/TesterDriver.scala index 90dc9355..364480a7 100644 --- a/src/main/scala/Chisel/testers/TesterDriver.scala +++ b/src/main/scala/Chisel/testers/TesterDriver.scala @@ -5,7 +5,7 @@ import Chisel._ import scala.sys.process._ import java.io.File -object TesterDriver extends BackendCompilationUtilities with FileSystemUtilities { +object TesterDriver extends BackendCompilationUtilities { /** For use with modules that should successfully be elaborated by the * frontend, and which can be turned into executeables with assertions. */ def execute(t: () => BasicTester, additionalVSources: Seq[File] = Seq()): Boolean = { @@ -15,23 +15,20 @@ object TesterDriver extends BackendCompilationUtilities with FileSystemUtilities // Set up a bunch of file handlers based on a random temp filename, // plus the quirks of Verilator's naming conventions val target = circuit.name - val fname = File.createTempFile(target, "") - val path = fname.getParentFile.toString + + val path = createTempDirectory(target) + val fname = File.createTempFile(target, "", path) val prefix = fname.toString.split("/").last - val dir = new File(System.getProperty("java.io.tmpdir")) - val vDut = new File(fname.toString + ".v") - val vH = new File(path + "/V" + prefix + ".h") - val cppHarness = new File(fname.toString + ".cpp") + val cppHarness = new File(System.getProperty("user.dir") + "/src/main/resources/top.cpp") // For now, dump the IR out to a file Driver.dumpFirrtl(circuit, Some(new File(fname.toString + ".fir"))) // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe - if (((new File(System.getProperty("user.dir") + "/src/main/resources/top.cpp") #> cppHarness) #&& - firrtlToVerilog(prefix, dir) #&& - verilogToCpp(prefix, dir, vDut, additionalVSources, cppHarness, vH) #&& - cppToExe(prefix, dir)).! == 0) { - executeExpectingSuccess(prefix, dir) + if ((firrtlToVerilog(prefix, path) #&& + verilogToCpp(prefix, path, additionalVSources, cppHarness) #&& + cppToExe(prefix, path)).! == 0) { + executeExpectingSuccess(prefix, path) } else { false } diff --git a/src/test/scala/chiselTests/Harness.scala b/src/test/scala/chiselTests/Harness.scala index 5c2d29d4..1a628e6c 100644 --- a/src/test/scala/chiselTests/Harness.scala +++ b/src/test/scala/chiselTests/Harness.scala @@ -44,34 +44,36 @@ int main(int argc, char **argv, char **env) { } """, ".cpp") _ - val dir = new File(System.getProperty("java.io.tmpdir")) - - def simpleHarnessBackend(make: File => File): String = { + /** Compiles a C++ emulator from Verilog and returns the path to the + * executable and the executable filename as a tuple. + */ + def simpleHarnessBackend(make: File => File): (File, String) = { val target = "test" - val fname = File.createTempFile(target, "") - val path = fname.getParentFile.toString + val path = createTempDirectory(target) + val fname = File.createTempFile(target, "", path) val prefix = fname.toString.split("/").last - val vDut = make(fname) - val vH = new File(path + "/V" + prefix + ".h") + val cppHarness = makeCppHarness(fname) - verilogToCpp(target, dir, vDut, Seq(), cppHarness, vH).! - cppToExe(prefix, dir).! - prefix + + make(fname) + verilogToCpp(prefix, path, Seq(), cppHarness).! + cppToExe(prefix, path).! + (path, prefix) } property("Test making trivial verilog harness and executing") { - val prefix = simpleHarnessBackend(makeTrivialVerilog) + val (path, prefix) = simpleHarnessBackend(makeTrivialVerilog) - assert(executeExpectingSuccess(prefix, dir)) + assert(executeExpectingSuccess(prefix, path)) } property("Test that assertion failues in Verilog are caught") { - val prefix = simpleHarnessBackend(makeFailingVerilog) + val (path, prefix) = simpleHarnessBackend(makeFailingVerilog) - assert(!executeExpectingSuccess(prefix, dir)) - assert(executeExpectingFailure(prefix, dir)) - assert(executeExpectingFailure(prefix, dir, "My specific, expected error message!")) - assert(!executeExpectingFailure(prefix, dir, "A string that doesn't match any test output")) + assert(!executeExpectingSuccess(prefix, path)) + assert(executeExpectingFailure(prefix, path)) + assert(executeExpectingFailure(prefix, path, "My specific, expected error message!")) + assert(!executeExpectingFailure(prefix, path, "A string that doesn't match any test output")) } } |
