summaryrefslogtreecommitdiff
path: root/src/main/scala/chisel3/Driver.scala
diff options
context:
space:
mode:
authorJim Lawson2016-10-24 10:31:26 -0700
committerJim Lawson2016-10-24 10:31:26 -0700
commitb0b5fd3140186651eb558bd6f4ca51c618deacc9 (patch)
tree1393bbb14303af86aeb5e5ed0375f302864b8307 /src/main/scala/chisel3/Driver.scala
parent82625071405672eb4a19363d6f73f359ac28a7f5 (diff)
parent5df30b390ae5817c4793c6d4e0c5466d96d241f1 (diff)
Merge branch 'master' into tobits-deprecation
Diffstat (limited to 'src/main/scala/chisel3/Driver.scala')
-rw-r--r--src/main/scala/chisel3/Driver.scala161
1 files changed, 154 insertions, 7 deletions
diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala
index 5e0a3a0f..a0713379 100644
--- a/src/main/scala/chisel3/Driver.scala
+++ b/src/main/scala/chisel3/Driver.scala
@@ -2,11 +2,37 @@
package chisel3
+import chisel3.internal.firrtl.Emitter
+
import scala.sys.process._
import java.io._
-import internal._
import internal.firrtl._
+import firrtl._
+
+/**
+ * The Driver provides methods to invoke the chisel3 compiler and the firrtl compiler.
+ * By default firrtl is automatically run after chisel. an [[ExecutionOptionsManager]]
+ * is needed to manage options. It can parser command line arguments or coordinate
+ * multiple chisel toolchain tools options.
+ *
+ * @example
+ * {{{
+ * val optionsManager = new ExecutionOptionsManager("chisel3")
+ * with FirrtlExecutionOptions
+ * with ChiselExecutionOptions {
+ * commonOptions = CommonOption(targetDirName = "my_target_dir")
+ * chiselOptions = ChiselExecutionOptions(runFirrtlCompiler = false)
+ * }
+ * chisel3.Driver.execute(optionsManager, () => new Dut)
+ * }}}
+ * or via command line arguments
+ * @example {{{
+ * args = "--no-run-firrtl --target-dir my-target-dir".split(" +")
+ * chisel3.execute(args, () => new DUT)
+ * }}}
+ */
+import BuildInfo._
trait BackendCompilationUtilities {
/** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6.
@@ -31,6 +57,32 @@ trait BackendCompilationUtilities {
vf
}
+ /**
+ * like 'firrtlToVerilog' except it runs the process inside the same JVM
+ *
+ * @param prefix basename of the file
+ * @param dir directory where file lives
+ * @return true if compiler completed successfully
+ */
+ def compileFirrtlToVerilog(prefix: String, dir: File): Boolean = {
+ val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = prefix, targetDirName = dir.getAbsolutePath)
+ firrtlOptions = FirrtlExecutionOptions(compilerName = "verilog")
+ }
+
+ firrtl.Driver.execute(optionsManager) match {
+ case _: FirrtlExecutionSuccess => true
+ case _: FirrtlExecutionFailure => false
+ }
+ }
+
+ /**
+ * 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",
@@ -67,13 +119,13 @@ trait BackendCompilationUtilities {
"-Wno-WIDTH",
"-Wno-STMTDLY",
"--trace",
- "-O2",
+ "-O0",
"--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 -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""",
+ s"""-Wno-undefined-bool-conversion -O0 -DTOP_TYPE=V$dutFile -include V$dutFile.h""",
"-Mdir", dir.toString,
"--exe", cppHarness.toString)
System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex
@@ -86,14 +138,17 @@ trait BackendCompilationUtilities {
def executeExpectingFailure(
prefix: String,
dir: File,
- assertionMsg: String = "Assertion failed"): Boolean = {
+ assertionMsg: String = ""): Boolean = {
var triggered = false
+ val assertionMessageSupplied = assertionMsg != ""
val e = Process(s"./V${prefix}", dir) !
ProcessLogger(line => {
- triggered = triggered || line.contains(assertionMsg)
+ triggered = triggered || (assertionMessageSupplied && line.contains(assertionMsg))
System.out.println(line) // scalastyle:ignore regex
})
- triggered
+ // 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 = {
@@ -101,6 +156,30 @@ trait BackendCompilationUtilities {
}
}
+/**
+ * This family provides return values from the chisel3 and possibly firrtl compile steps
+ */
+trait ChiselExecutionResult
+
+/**
+ *
+ * @param circuitOption Optional circuit, has information like circuit name
+ * @param emitted The emitted Chirrrl text
+ * @param firrtlResultOption Optional Firrtl result, @see ucb-bar/firrtl for details
+ */
+case class ChiselExecutionSucccess(
+ circuitOption: Option[Circuit],
+ emitted: String,
+ firrtlResultOption: Option[FirrtlExecutionResult]
+ ) extends ChiselExecutionResult
+
+/**
+ * Getting one of these indicates failure of some sort
+ *
+ * @param message a clue perhaps will be provided in the here
+ */
+case class ChiselExecutionFailure(message: String) extends ChiselExecutionResult
+
object Driver extends BackendCompilationUtilities {
/** Elaborates the Module specified in the gen function into a Circuit
@@ -108,7 +187,7 @@ object Driver extends BackendCompilationUtilities {
* @param gen a function that creates a Module hierarchy
* @return the resulting Chisel IR in the form of a Circuit (TODO: Should be FIRRTL IR)
*/
- def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen()))
+ def elaborate[T <: Module](gen: () => T): Circuit = internal.Builder.build(Module(gen()))
def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen))
@@ -132,4 +211,72 @@ object Driver extends BackendCompilationUtilities {
}
def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath }
+
+ /**
+ * Run the chisel3 compiler and possibly the firrtl compiler with options specified
+ *
+ * @param optionsManager The options specified
+ * @param dut The device under test
+ * @return An execution result with useful stuff, or failure with message
+ */
+ def execute(
+ optionsManager: ExecutionOptionsManager with HasChiselExecutionOptions with HasFirrtlOptions,
+ dut: () => Module): ChiselExecutionResult = {
+ val circuit = elaborate(dut)
+
+ // this little hack let's us set the topName with the circuit name if it has not been set from args
+ optionsManager.setTopNameIfNotSet(circuit.name)
+
+ val firrtlOptions = optionsManager.firrtlOptions
+ val chiselOptions = optionsManager.chiselOptions
+
+ // use input because firrtl will be reading this
+ val firrtlString = Emitter.emit(circuit)
+ val firrtlFileName = firrtlOptions.getInputFileName(optionsManager)
+ val firrtlFile = new File(firrtlFileName)
+
+ val w = new FileWriter(firrtlFile)
+ w.write(firrtlString)
+ w.close()
+
+ val firrtlExecutionResult = if(chiselOptions.runFirrtlCompiler) {
+ Some(firrtl.Driver.execute(optionsManager))
+ }
+ else {
+ None
+ }
+ ChiselExecutionSucccess(Some(circuit), firrtlString, firrtlExecutionResult)
+ }
+
+ /**
+ * Run the chisel3 compiler and possibly the firrtl compiler with options specified via an array of Strings
+ *
+ * @param args The options specified, command line style
+ * @param dut The device under test
+ * @return An execution result with useful stuff, or failure with message
+ */
+ def execute(args: Array[String], dut: () => Module): ChiselExecutionResult = {
+ val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions
+
+ optionsManager.parse(args) match {
+ case true =>
+ execute(optionsManager, dut)
+ case _ =>
+ ChiselExecutionFailure("could not parse results")
+ }
+ }
+
+ /**
+ * This is just here as command line way to see what the options are
+ * It will not successfully run
+ * TODO: Look into dynamic class loading as way to make this main useful
+ *
+ * @param args unused args
+ */
+ def main(args: Array[String]) {
+ execute(Array("--help"), null)
+ }
+
+ val version = BuildInfo.version
+ val chiselVersionString = BuildInfo.toString
}