diff options
Diffstat (limited to 'src/main/scala/firrtl/Compiler.scala')
| -rw-r--r-- | src/main/scala/firrtl/Compiler.scala | 87 |
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 } } |
