summaryrefslogtreecommitdiff
path: root/src/main/scala/chisel3/Driver.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/chisel3/Driver.scala')
-rw-r--r--src/main/scala/chisel3/Driver.scala144
1 files changed, 142 insertions, 2 deletions
diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala
index b0c7aeda..dbd9b464 100644
--- a/src/main/scala/chisel3/Driver.scala
+++ b/src/main/scala/chisel3/Driver.scala
@@ -2,11 +2,36 @@
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 {
@@ -32,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",
@@ -105,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
@@ -112,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))
@@ -137,6 +212,71 @@ 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
}