aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Compiler.scala
diff options
context:
space:
mode:
authorJack Koenig2017-03-06 14:51:20 -0600
committerGitHub2017-03-06 14:51:20 -0600
commit3d58123ae654a2101ba81304ca3863b3be12c4f3 (patch)
tree2e662485fef5327a2697dbd4a9b42a2cdc5bae5f /src/main/scala/firrtl/Compiler.scala
parentc89f74f19dd5162ee533a0a20825819bc52bc73e (diff)
Add ability to emit 1 file per module (#443)
Changes Emitters to also be Transforms and use Annotations for both telling an emitter to do emission as well as getting the emitted result. Helper functions ease the use of the new interface. Also adds a FirrtlExecutionOptions field as well as a command-line option. Use of Writers in Compilers and Emitters is now deprecated.
Diffstat (limited to 'src/main/scala/firrtl/Compiler.scala')
-rw-r--r--src/main/scala/firrtl/Compiler.scala87
1 files changed, 74 insertions, 13 deletions
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
index 808fa435..6251fc5c 100644
--- a/src/main/scala/firrtl/Compiler.scala
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -8,6 +8,7 @@ import annotations._
import firrtl.ir.Circuit
import passes.Pass
+import Utils.throwInternalError
/**
* RenameMap maps old names to modified names. Generated by transformations
@@ -33,10 +34,28 @@ case class AnnotationMap(annotations: Seq[Annotation]) {
* Generally only a return value from [[Transform]]s
*/
case class CircuitState(
- circuit: Circuit,
- form: CircuitForm,
- annotations: Option[AnnotationMap] = None,
- renames: Option[RenameMap] = None)
+ circuit: Circuit,
+ form: CircuitForm,
+ annotations: Option[AnnotationMap] = None,
+ renames: Option[RenameMap] = None) {
+
+ /** Helper for getting just an emitted circuit */
+ def emittedCircuitOption: Option[EmittedCircuit] =
+ emittedComponents collectFirst { case x: EmittedCircuit => x }
+ /** Helper for getting an [[EmittedCircuit]] when it is known to exist */
+ def getEmittedCircuit: EmittedCircuit = emittedCircuitOption match {
+ case Some(emittedCircuit) => emittedCircuit
+ case None => throw new FIRRTLException("No EmittedCircuit found! Check Emitter Annotations")
+ }
+ /** Helper function for extracting emitted components from annotations */
+ def emittedComponents: Seq[EmittedComponent] = {
+ val emittedOpt = annotations map (_.annotations collect {
+ case EmittedCircuitAnnotation(x) => x
+ case EmittedModuleAnnotation(x) => x
+ })
+ emittedOpt.getOrElse(Seq.empty)
+ }
+}
/** Current form of the Firrtl Circuit
*
@@ -137,10 +156,9 @@ abstract class PassBasedTransform extends Transform with PassBased {
}
}
-/** Similar to a Transform except that it writes to a Writer instead of returning a
- * CircuitState
- */
-abstract class Emitter {
+/** Defines old API for Emission. Deprecated */
+trait Emitter extends Transform {
+ @deprecated("Use emission annotations instead", "firrtl 1.0")
def emit(state: CircuitState, writer: Writer): Unit
}
@@ -157,12 +175,13 @@ object CompilerUtils {
Seq.empty
} else {
inputForm match {
- case ChirrtlForm => Seq(new ChirrtlToHighFirrtl) ++ getLoweringTransforms(HighForm, outputForm)
+ case ChirrtlForm =>
+ Seq(new ChirrtlToHighFirrtl) ++ getLoweringTransforms(HighForm, outputForm)
case HighForm =>
Seq(new IRToWorkingIR, new ResolveAndCheck, new transforms.DedupModules,
new HighFirrtlToMiddleFirrtl) ++ getLoweringTransforms(MidForm, outputForm)
case MidForm => Seq(new MiddleFirrtlToLowFirrtl) ++ getLoweringTransforms(LowForm, outputForm)
- case LowForm => error("Internal Error! This shouldn't be possible") // should be caught by if above
+ case LowForm => throwInternalError // should be caught by if above
}
}
}
@@ -212,7 +231,9 @@ object CompilerUtils {
}
trait Compiler {
+ // Emitter is still somewhat special because we want to make sure it is run last
def emitter: Emitter
+
/** The sequence of transforms this compiler will execute
* @note The inputForm of a given transform must be higher than or equal to the ouputForm of the
* preceding transform. See [[CircuitForm]]
@@ -242,10 +263,52 @@ trait Compiler {
* @param customTransforms Any custom [[Transform]]s that will be inserted
* into the compilation process by [[CompilerUtils.mergeTransforms]]
*/
+ @deprecated("Please use compileAndEmit or other compile method instead", "firrtl 1.0")
def compile(state: CircuitState,
writer: Writer,
customTransforms: Seq[Transform] = Seq.empty): CircuitState = {
- val allTransforms = CompilerUtils.mergeTransforms(transforms, customTransforms)
+ val finalState = compileAndEmit(state, customTransforms)
+ finalState.emittedCircuitOption match {
+ case Some(emitted) => writer.write(emitted.value)
+ case _ => throwInternalError
+ }
+ finalState
+ }
+
+ /** Perform compilation and emit the whole Circuit
+ *
+ * This is intended as a convenience method wrapping up Annotation creation for the common case.
+ * It creates a [[EmitCircuitAnnotation]] that will be consumed by this Transform's emitter. The
+ * [[EmittedCircuit]] can be extracted from the returned [[CircuitState]] via
+ * [[CircuitState.emittedCircuitOption]]
+ *
+ * @param state The Firrtl AST to compile
+ * @param customTransforms Any custom [[Transform]]s that will be inserted
+ * into the compilation process by [[CompilerUtils.mergeTransforms]]
+ * @return result of compilation with emitted circuit annotated
+ */
+ def compileAndEmit(state: CircuitState,
+ customTransforms: Seq[Transform] = Seq.empty): CircuitState = {
+ val emitAnno = EmitCircuitAnnotation(emitter.getClass)
+ // TODO This is ridiculous. Fix Annotations
+ val annotations = state.annotations.map(_.annotations).getOrElse(Seq.empty)
+ val annotationMap = AnnotationMap(annotations :+ emitAnno)
+
+ // Run compiler
+ compile(state.copy(annotations = Some(annotationMap)), customTransforms)
+ }
+
+ /** Perform compilation
+ *
+ * Emission will only be performed if [[EmitAnnotation]]s are present
+ *
+ * @param state The Firrtl AST to compile
+ * @param customTransforms Any custom [[Transform]]s that will be inserted into the compilation
+ * process by [[CompilerUtils.mergeTransforms]]
+ * @return result of compilation
+ */
+ def compile(state: CircuitState, customTransforms: Seq[Transform]): CircuitState = {
+ val allTransforms = CompilerUtils.mergeTransforms(transforms, customTransforms) :+ emitter
val finalState = allTransforms.foldLeft(state) { (in, xform) =>
val result = Utils.time(s"***${xform.name}***") { xform.execute(in) }
@@ -273,8 +336,6 @@ trait Compiler {
val newAnnotations = AnnotationMap(remappedAnnotations ++ resultAnnotations)
CircuitState(result.circuit, result.form, Some(newAnnotations))
}
-
- emitter.emit(finalState, writer)
finalState
}
}