aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJack Koenig2018-05-23 11:54:50 -0700
committerGitHub2018-05-23 11:54:50 -0700
commit87fe48938a3ccc58b1945bae72f0e7305ac14b3b (patch)
tree8d809eac737083400ae72b9f11bb2eb3fd91aee1 /src
parentb1709242b5c7b60e21308642947d292545eb2e37 (diff)
Add Circuit as option to FirrtlOptions (#814)
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/Driver.scala78
-rw-r--r--src/main/scala/firrtl/ExecutionOptionsManager.scala4
-rw-r--r--src/test/scala/firrtlTests/DriverSpec.scala43
3 files changed, 96 insertions, 29 deletions
diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala
index 10489da4..72128274 100644
--- a/src/main/scala/firrtl/Driver.scala
+++ b/src/main/scala/firrtl/Driver.scala
@@ -148,33 +148,38 @@ object Driver {
LegacyAnnotation.convertLegacyAnnos(annos)
}
- /**
- * Run the firrtl compiler using the provided option
+ // Useful for handling erros in the options
+ case class OptionsException(msg: String) extends Exception(msg)
+
+ /** Get the Circuit from the compile options
*
- * @param optionsManager the desired flags to the compiler
- * @return a FirrtlExecutionResult indicating success or failure, provide access to emitted data on success
- * for downstream tools as desired
+ * Handles the myriad of ways it can be specified
*/
- //scalastyle:off cyclomatic.complexity method.length
- def execute(optionsManager: ExecutionOptionsManager with HasFirrtlOptions): FirrtlExecutionResult = {
- def firrtlConfig = optionsManager.firrtlOptions
-
- Logger.makeScope(optionsManager) {
- val firrtlSource = firrtlConfig.firrtlSource match {
- case Some(text) => text.split("\n").toIterator
- case None =>
+ def getCircuit(optionsManager: ExecutionOptionsManager with HasFirrtlOptions): Try[ir.Circuit] = {
+ val firrtlConfig = optionsManager.firrtlOptions
+ Try {
+ // Check that only one "override" is used
+ val circuitSources = Map(
+ "firrtlSource" -> firrtlConfig.firrtlSource.isDefined,
+ "firrtlCircuit" -> firrtlConfig.firrtlCircuit.isDefined,
+ "inputFileNameOverride" -> firrtlConfig.inputFileNameOverride.nonEmpty)
+ if (circuitSources.values.count(x => x) > 1) {
+ val msg = circuitSources.collect { case (s, true) => s }.mkString(" and ") +
+ " are set, only 1 can be set at a time!"
+ throw new OptionsException(msg)
+ }
+ firrtlConfig.firrtlCircuit.getOrElse {
+ val source = firrtlConfig.firrtlSource.map(_.split("\n").toIterator).getOrElse {
if (optionsManager.topName.isEmpty && firrtlConfig.inputFileNameOverride.isEmpty) {
val message = "either top-name or input-file-override must be set"
- dramaticError(message)
- return FirrtlExecutionFailure(message)
+ throw new OptionsException(message)
}
if (
optionsManager.topName.isEmpty &&
firrtlConfig.inputFileNameOverride.nonEmpty &&
firrtlConfig.outputFileNameOverride.isEmpty) {
val message = "inputFileName set but neither top-name or output-file-override is set"
- dramaticError(message)
- return FirrtlExecutionFailure(message)
+ throw new OptionsException(message)
}
val inputFileName = firrtlConfig.getInputFileName(optionsManager)
try {
@@ -183,26 +188,45 @@ object Driver {
catch {
case _: FileNotFoundException =>
val message = s"Input file $inputFileName not found"
- dramaticError(message)
- return FirrtlExecutionFailure(message)
+ throw new OptionsException(message)
}
+ }
+ Parser.parse(source, firrtlConfig.infoMode)
}
+ }
+ }
- var maybeFinalState: Option[CircuitState] = None
+ /**
+ * Run the firrtl compiler using the provided option
+ *
+ * @param optionsManager the desired flags to the compiler
+ * @return a FirrtlExecutionResult indicating success or failure, provide access to emitted data on success
+ * for downstream tools as desired
+ */
+ //scalastyle:off cyclomatic.complexity method.length
+ def execute(optionsManager: ExecutionOptionsManager with HasFirrtlOptions): FirrtlExecutionResult = {
+ def firrtlConfig = optionsManager.firrtlOptions
+ Logger.makeScope(optionsManager) {
// Wrap compilation in a try/catch to present Scala MatchErrors in a more user-friendly format.
- try {
- val annos = getAnnotations(optionsManager)
+ val finalState = try {
+ val circuit = getCircuit(optionsManager) match {
+ case Success(c) => c
+ case Failure(OptionsException(msg)) =>
+ dramaticError(msg)
+ return FirrtlExecutionFailure(msg)
+ case Failure(e) => throw e
+ }
- val parsedInput = Parser.parse(firrtlSource, firrtlConfig.infoMode)
+ val annos = getAnnotations(optionsManager)
// Does this need to be before calling compiler?
optionsManager.makeTargetDir()
- maybeFinalState = Some(firrtlConfig.compiler.compile(
- CircuitState(parsedInput, ChirrtlForm, annos),
+ firrtlConfig.compiler.compile(
+ CircuitState(circuit, ChirrtlForm, annos),
firrtlConfig.customTransforms
- ))
+ )
}
catch {
// Rethrow the exceptions which are expected or due to the runtime environment (out of memory, stack overflow)
@@ -213,8 +237,6 @@ object Driver {
case e: Exception => throwInternalError(exception = Some(e))
}
- val finalState = maybeFinalState.get
-
// Do emission
// Note: Single emission target assumption is baked in here
// Note: FirrtlExecutionSuccess emitted is only used if we're emitting the whole Circuit
diff --git a/src/main/scala/firrtl/ExecutionOptionsManager.scala b/src/main/scala/firrtl/ExecutionOptionsManager.scala
index 3ee91da0..76426d1e 100644
--- a/src/main/scala/firrtl/ExecutionOptionsManager.scala
+++ b/src/main/scala/firrtl/ExecutionOptionsManager.scala
@@ -4,6 +4,7 @@ package firrtl
import firrtl.annotations._
import firrtl.Parser._
+import firrtl.ir.Circuit
import firrtl.passes.memlib.{InferReadWriteAnnotation, ReplSeqMemAnnotation}
import firrtl.passes.clocklist.ClockListAnnotation
import logger.LogLevel
@@ -184,7 +185,8 @@ case class FirrtlExecutionOptions(
emitOneFilePerModule: Boolean = false,
dontCheckCombLoops: Boolean = false,
noDCE: Boolean = false,
- annotationFileNames: List[String] = List.empty)
+ annotationFileNames: List[String] = List.empty,
+ firrtlCircuit: Option[Circuit] = None)
extends ComposableOptions {
require(!(emitOneFilePerModule && outputFileNameOverride.nonEmpty),
diff --git a/src/test/scala/firrtlTests/DriverSpec.scala b/src/test/scala/firrtlTests/DriverSpec.scala
index b0ce0af9..df49e2bb 100644
--- a/src/test/scala/firrtlTests/DriverSpec.scala
+++ b/src/test/scala/firrtlTests/DriverSpec.scala
@@ -17,6 +17,8 @@ import firrtl._
import firrtl.annotations._
import firrtl.util.BackendCompilationUtilities
+import scala.util.{Try, Success, Failure}
+
class ExceptingTransform extends Transform {
def inputForm = HighForm
def outputForm = HighForm
@@ -124,6 +126,47 @@ class DriverSpec extends FreeSpec with Matchers with BackendCompilationUtilities
val outputFileName = firrtlOptions.getTargetFile(optionsManager)
outputFileName should be ("carol.v")
}
+ val input = """
+ |circuit Top :
+ | module Top :
+ | input x : UInt<8>
+ | output y : UInt<8>
+ | y <= x""".stripMargin
+ val circuit = Parser.parse(input.split("\n").toIterator)
+ "firrtl source can be provided directly" in {
+ val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = "Top")
+ firrtlOptions = FirrtlExecutionOptions(firrtlSource = Some(input))
+ }
+ assert(firrtl.Driver.getCircuit(manager).isSuccess)
+ }
+ "firrtl Circuits can be provided directly" in {
+ val manager = new ExecutionOptionsManager("test") with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = "Top")
+ firrtlOptions = FirrtlExecutionOptions(firrtlCircuit = Some(circuit))
+ }
+ firrtl.Driver.getCircuit(manager) shouldBe Success(circuit)
+ }
+ "Only one of inputFileNameOverride, firrtlSource, and firrtlCircuit can be used at a time" in {
+ val manager1 = new ExecutionOptionsManager("test") with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = "Top")
+ firrtlOptions = FirrtlExecutionOptions(firrtlCircuit = Some(circuit),
+ firrtlSource = Some(input))
+ }
+ val manager2 = new ExecutionOptionsManager("test") with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = "Top")
+ firrtlOptions = FirrtlExecutionOptions(inputFileNameOverride = "hi",
+ firrtlSource = Some(input))
+ }
+ val manager3 = new ExecutionOptionsManager("test") with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = "Top")
+ firrtlOptions = FirrtlExecutionOptions(inputFileNameOverride = "hi",
+ firrtlCircuit = Some(circuit))
+ }
+ assert(firrtl.Driver.getCircuit(manager1).isFailure)
+ assert(firrtl.Driver.getCircuit(manager2).isFailure)
+ assert(firrtl.Driver.getCircuit(manager3).isFailure)
+ }
"various annotations can be created from command line, currently:" - {
"inline annotation" in {
val optionsManager = new ExecutionOptionsManager("test") with HasFirrtlOptions