aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Compiler.scala
diff options
context:
space:
mode:
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
}
}