aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Lawson2017-01-27 12:19:38 -0800
committerGitHub2017-01-27 12:19:38 -0800
commit91570ec8d7ab6bede24eb8da4a7e005f00ac076f (patch)
tree1abe0499ff53baa702610f8aaaf5d2ee7b7cbe0d /src
parent6c00f2c880a536b61196e7ec63fc861d69c8b764 (diff)
Move BackendCompilationUtilities into a util package for use by chisel3. (#400)
* Move BackendCompilationUtilities into a util package for use by chisel3. Some of this could be moved into a more general tools package, but since chisel3 already has a dependency on firrtl ... * Push util down into firrtl so as not to conflict with scala.util.
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/util/BackendCompilationUtilities.scala130
-rw-r--r--src/test/scala/firrtlTests/DriverSpec.scala1
-rw-r--r--src/test/scala/firrtlTests/FirrtlSpec.scala93
3 files changed, 132 insertions, 92 deletions
diff --git a/src/main/scala/firrtl/util/BackendCompilationUtilities.scala b/src/main/scala/firrtl/util/BackendCompilationUtilities.scala
new file mode 100644
index 00000000..c1ead8b9
--- /dev/null
+++ b/src/main/scala/firrtl/util/BackendCompilationUtilities.scala
@@ -0,0 +1,130 @@
+// See LICENSE for license details.
+
+package firrtl.util
+
+import scala.sys.process._
+import java.io._
+
+import firrtl._
+import firrtl.{Driver, ExecutionOptionsManager}
+
+import scala.sys.process.{ProcessBuilder, ProcessLogger}
+
+
+trait BackendCompilationUtilities {
+ /** Copy the contents of a resource to a destination file.
+ */
+ def copyResourceToFile(name: String, file: File) {
+ val in = getClass.getResourceAsStream(name)
+ if (in == null) {
+ throw new FileNotFoundException(s"Resource '$name'")
+ }
+ val out = new FileOutputStream(file)
+ Iterator.continually(in.read).takeWhile(-1 != _).foreach(out.write)
+ out.close()
+ }
+
+ /** 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
+ }
+
+ def makeHarness(template: String => String, post: String)(f: File): File = {
+ val prefix = f.toString.split("/").last
+ val vf = new File(f.toString + post)
+ val w = new FileWriter(vf)
+ w.write(template(prefix))
+ w.close()
+ vf
+ }
+
+ /**
+ * compule chirrtl to verilog by using a separate process
+ *
+ * @param prefix basename of the file
+ * @param dir directory where file lives
+ * @return true if compiler completed successfully
+ */
+ def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = {
+ Process(
+ Seq("firrtl",
+ "-i", s"$prefix.fir",
+ "-o", s"$prefix.v",
+ "-X", "verilog"),
+ dir)
+ }
+
+ /** Generates a Verilator invocation to convert Verilog sources to C++
+ * simulation sources.
+ *
+ * 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
+ * @param vSources list of additional Verilog sources to compile
+ * @param cppHarness C++ testharness to compile/link against
+ */
+ def verilogToCpp(
+ dutFile: String,
+ dir: File,
+ vSources: Seq[File],
+ cppHarness: File
+ ): ProcessBuilder = {
+ val topModule = dutFile
+ val command = Seq("verilator",
+ "--cc", s"$dutFile.v") ++
+ vSources.map(file => Seq("-v", file.toString)).flatten ++
+ Seq("--assert",
+ "-Wno-fatal",
+ "-Wno-WIDTH",
+ "-Wno-STMTDLY",
+ "--trace",
+ "-O1",
+ "--top-module", topModule,
+ "+define+TOP_TYPE=V" + dutFile,
+ s"+define+PRINTF_COND=!$topModule.reset",
+ s"+define+STOP_COND=!$topModule.reset",
+ "-CFLAGS",
+ s"""-Wno-undefined-bool-conversion -O1 -DTOP_TYPE=V$dutFile -include V$dutFile.h""",
+ "-Mdir", dir.toString,
+ "--exe", cppHarness.toString)
+ System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex
+ command
+ }
+
+ def cppToExe(prefix: String, dir: File): ProcessBuilder =
+ Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}")
+
+ def executeExpectingFailure(
+ prefix: String,
+ dir: File,
+ assertionMsg: String = ""): Boolean = {
+ var triggered = false
+ val assertionMessageSupplied = assertionMsg != ""
+ val e = Process(s"./V${prefix}", dir) !
+ ProcessLogger(line => {
+ triggered = triggered || (assertionMessageSupplied && line.contains(assertionMsg))
+ System.out.println(line) // scalastyle:ignore regex
+ })
+ // Fail if a line contained an assertion or if we get a non-zero exit code
+ // or, we get a SIGABRT (assertion failure) and we didn't provide a specific assertion message
+ triggered || (e != 0 && (e != 134 || !assertionMessageSupplied))
+ }
+
+ def executeExpectingSuccess(prefix: String, dir: File): Boolean = {
+ !executeExpectingFailure(prefix, dir)
+ }
+}
diff --git a/src/test/scala/firrtlTests/DriverSpec.scala b/src/test/scala/firrtlTests/DriverSpec.scala
index 9f29b918..ff888e2e 100644
--- a/src/test/scala/firrtlTests/DriverSpec.scala
+++ b/src/test/scala/firrtlTests/DriverSpec.scala
@@ -8,6 +8,7 @@ import org.scalatest.{FreeSpec, Matchers}
import firrtl.passes.InlineInstances
import firrtl.passes.memlib.{InferReadWrite, ReplSeqMem}
import firrtl._
+import firrtl.util.BackendCompilationUtilities
class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities {
"CommonOptions are some simple options available across the chisel3 ecosystem" - {
diff --git a/src/test/scala/firrtlTests/FirrtlSpec.scala b/src/test/scala/firrtlTests/FirrtlSpec.scala
index a2c880c3..ec3d075e 100644
--- a/src/test/scala/firrtlTests/FirrtlSpec.scala
+++ b/src/test/scala/firrtlTests/FirrtlSpec.scala
@@ -13,98 +13,7 @@ import scala.io.Source
import firrtl._
import firrtl.Parser.IgnoreInfo
import firrtl.annotations
-
-// This trait is borrowed from Chisel3, ideally this code should only exist in one location
-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
- }
-
- /** Copy the contents of a resource to a destination file.
- */
- def copyResourceToFile(name: String, file: File) {
- val in = getClass().getResourceAsStream(name)
- if (in == null) {
- throw new FileNotFoundException(s"Resource '$name'")
- }
- val out = new FileOutputStream(file)
- Iterator.continually(in.read).takeWhile(-1 !=).foreach(out.write)
- out.close()
- }
-
-
- def makeHarness(template: String => String, post: String)(f: File): File = {
- val prefix = f.toString.split("/").last
- val vf = new File(f.toString + post)
- val w = new FileWriter(vf)
- w.write(template(prefix))
- w.close()
- vf
- }
-
- /** Generates a Verilator invocation to convert Verilog sources to C++
- * simulation sources.
- *
- * 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
- * @param vSources list of additional Verilog sources to compile
- * @param cppHarness C++ testharness to compile/link against
- */
- def verilogToCpp(
- dutFile: String,
- dir: File,
- vSources: Seq[File],
- cppHarness: File): ProcessBuilder =
-
- Seq("verilator",
- "--cc", s"$dutFile.v") ++
- vSources.map(file => Seq("-v", file.toString)).flatten ++
- Seq("--assert",
- "--Wno-fatal",
- "--trace",
- "-O2",
- "--top-module", dutFile,
- "+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)
-
- def cppToExe(prefix: String, dir: File): ProcessBuilder =
- Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}")
-
- def executeExpectingFailure(
- prefix: String,
- dir: File,
- assertionMsg: String = "Assertion failed"): Boolean = {
- var triggered = false
- val e = Process(s"./V${prefix}", dir) !
- ProcessLogger(line => {
- triggered = triggered || line.contains(assertionMsg)
- System.out.println(line)
- })
- triggered
- }
-
- def executeExpectingSuccess(prefix: String, dir: File): Boolean = {
- !executeExpectingFailure(prefix, dir)
- }
-}
+import firrtl.util.BackendCompilationUtilities
trait FirrtlRunners extends BackendCompilationUtilities {
def parse(str: String) = Parser.parse(str.split("\n").toIterator, IgnoreInfo)