aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Laeufer2020-08-11 11:51:05 -0700
committerGitHub2020-08-11 18:51:05 +0000
commitf7cffd230ede9a483f183182fa8e1bea3c4cdd67 (patch)
tree42f5229632a944182543a4f20c6beb933f6f7e80
parent21ccf68fc0f0a3ff5a990ac9215a20f20807f4ed (diff)
stage: allow a RunFirrtlTransformAnnotation(_:Emitter) annotation to be used in place of a CompilerAnnotation (#1835)
-rw-r--r--src/main/scala/firrtl/stage/FirrtlAnnotations.scala7
-rw-r--r--src/main/scala/firrtl/stage/FirrtlOptions.scala5
-rw-r--r--src/main/scala/firrtl/stage/package.scala23
-rw-r--r--src/main/scala/firrtl/stage/phases/AddDefaults.scala17
-rw-r--r--src/main/scala/firrtl/stage/phases/AddImplicitEmitter.scala8
-rw-r--r--src/main/scala/firrtl/stage/phases/Checks.scala7
-rw-r--r--src/main/scala/firrtl/stage/phases/Compiler.scala9
-rw-r--r--src/test/scala/firrtlTests/stage/FirrtlOptionsViewSpec.scala2
-rw-r--r--src/test/scala/firrtlTests/stage/phases/AddDefaultsSpec.scala7
9 files changed, 53 insertions, 32 deletions
diff --git a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
index 1604e92e..91c5609b 100644
--- a/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
+++ b/src/main/scala/firrtl/stage/FirrtlAnnotations.scala
@@ -6,11 +6,11 @@ import firrtl._
import firrtl.ir.Circuit
import firrtl.annotations.{Annotation, NoTargetAnnotation}
import firrtl.options.{HasShellOptions, OptionsException, ShellOption, Unserializable}
-
-
import java.io.FileNotFoundException
import java.nio.file.NoSuchFileException
+import firrtl.stage.TransformManager.TransformDependency
+
/** Indicates that this is an [[firrtl.annotations.Annotation Annotation]] directly used in the construction of a
* [[FirrtlOptions]] view.
*/
@@ -177,6 +177,9 @@ case class RunFirrtlTransformAnnotation(transform: Transform) extends NoTargetAn
object RunFirrtlTransformAnnotation extends HasShellOptions {
+ def apply(transform: TransformDependency): RunFirrtlTransformAnnotation =
+ RunFirrtlTransformAnnotation(transform.getObject)
+
val options = Seq(
new ShellOption[Seq[String]](
longOption = "custom-transforms",
diff --git a/src/main/scala/firrtl/stage/FirrtlOptions.scala b/src/main/scala/firrtl/stage/FirrtlOptions.scala
index 8028e6f2..61dec7c5 100644
--- a/src/main/scala/firrtl/stage/FirrtlOptions.scala
+++ b/src/main/scala/firrtl/stage/FirrtlOptions.scala
@@ -2,30 +2,25 @@
package firrtl.stage
-import firrtl.Compiler
import firrtl.ir.Circuit
/** Internal options used to control the FIRRTL compiler stage.
* @param outputFileName output file, default: `targetDir/topName.SUFFIX` with `SUFFIX` as determined by the compiler
- * @param compiler which compiler to use (default: [[VerilogCompiler]])
* @param infoModeName the policy for generating [[firrtl.ir Info]] when processing FIRRTL (default: "append")
* @param firrtlCircuit a [[firrtl.ir Circuit]]
*/
class FirrtlOptions private [stage] (
val outputFileName: Option[String] = None,
- val compiler: Compiler = CompilerAnnotation().compiler,
val infoModeName: String = InfoModeAnnotation().modeName,
val firrtlCircuit: Option[Circuit] = None) {
private [stage] def copy(
outputFileName: Option[String] = outputFileName,
- compiler: Compiler = compiler,
infoModeName: String = infoModeName,
firrtlCircuit: Option[Circuit] = firrtlCircuit ): FirrtlOptions = {
new FirrtlOptions(
outputFileName = outputFileName,
- compiler = compiler,
infoModeName = infoModeName,
firrtlCircuit = firrtlCircuit )
}
diff --git a/src/main/scala/firrtl/stage/package.scala b/src/main/scala/firrtl/stage/package.scala
index d0a481fb..5bb7378d 100644
--- a/src/main/scala/firrtl/stage/package.scala
+++ b/src/main/scala/firrtl/stage/package.scala
@@ -3,8 +3,9 @@
package firrtl
import firrtl.annotations.DeletedAnnotation
-import firrtl.options.{OptionsView, Viewer}
+import firrtl.options.OptionsView
import firrtl.stage.phases.WriteEmitted
+import logger.LazyLogging
/** The [[stage]] package provides an implementation of the FIRRTL compiler using the [[firrtl.options]] package. This
* primarily consists of:
@@ -19,7 +20,7 @@ import firrtl.stage.phases.WriteEmitted
* - [[FirrtlStageUtils]] containing miscellaneous utilities for [[stage]]
*/
package object stage {
- implicit object FirrtlOptionsView extends OptionsView[FirrtlOptions] {
+ implicit object FirrtlOptionsView extends OptionsView[FirrtlOptions] with LazyLogging {
/**
* @todo custom transforms are appended as discovered, can this be prepended safely?
@@ -30,30 +31,38 @@ package object stage {
x match {
case OutputFileAnnotation(f) => c.copy(outputFileName = Some(f))
case InfoModeAnnotation(i) => c.copy(infoModeName = i)
- case CompilerAnnotation(cx) => c.copy(compiler = cx)
case FirrtlCircuitAnnotation(cir) => c.copy(firrtlCircuit = Some(cir))
+ case a : CompilerAnnotation => logger.warn(s"Use of CompilerAnnotation is deprecated. Ignoring $a") ; c
}
}
}
- private [firrtl] implicit object FirrtlExecutionResultView extends OptionsView[FirrtlExecutionResult] {
+ private [firrtl] implicit object FirrtlExecutionResultView extends OptionsView[FirrtlExecutionResult] with LazyLogging {
private lazy val dummyWriteEmitted = new WriteEmitted
def view(options: AnnotationSeq): FirrtlExecutionResult = {
- val fopts = Viewer[FirrtlOptions].view(options)
val emittedRes = options
.collect{ case DeletedAnnotation(dummyWriteEmitted.name, a: EmittedAnnotation[_]) => a.value.value }
.mkString("\n")
+ val emitters = options.collect{ case RunFirrtlTransformAnnotation(e: Emitter) => e }
+ if(emitters.length > 1) {
+ logger.warn("More than one emitter used which cannot be accurately represented" +
+ "in the deprecated FirrtlExecutionResult: " + emitters.map(_.name).mkString(", "))
+ }
+ val compilers = options.collect{ case CompilerAnnotation(c) => c }
+ val emitType = emitters.headOption.orElse(compilers.headOption).map(_.name).getOrElse("N/A")
+ val form = emitters.headOption.orElse(compilers.headOption).map(_.outputForm).getOrElse(UnknownForm)
+
options.collectFirst{ case a: FirrtlCircuitAnnotation => a.circuit } match {
case None => FirrtlExecutionFailure("No circuit found in AnnotationSeq!")
case Some(a) => FirrtlExecutionSuccess(
- emitType = fopts.compiler.getClass.getName,
+ emitType = emitType,
emitted = emittedRes,
circuitState = CircuitState(
circuit = a,
- form = fopts.compiler.outputForm,
+ form = form,
annotations = options,
renames = None
))
diff --git a/src/main/scala/firrtl/stage/phases/AddDefaults.scala b/src/main/scala/firrtl/stage/phases/AddDefaults.scala
index 1fb8913c..d4c5bab4 100644
--- a/src/main/scala/firrtl/stage/phases/AddDefaults.scala
+++ b/src/main/scala/firrtl/stage/phases/AddDefaults.scala
@@ -2,10 +2,11 @@
package firrtl.stage.phases
-import firrtl.AnnotationSeq
-import firrtl.options.{Phase, TargetDirAnnotation}
+import firrtl.{AnnotationSeq, VerilogEmitter}
+import firrtl.options.{Dependency, Phase, TargetDirAnnotation}
+import firrtl.stage.TransformManager.TransformDependency
import firrtl.transforms.BlackBoxTargetDirAnno
-import firrtl.stage.{CompilerAnnotation, InfoModeAnnotation, FirrtlOptions}
+import firrtl.stage.{CompilerAnnotation, FirrtlOptions, InfoModeAnnotation, RunFirrtlTransformAnnotation}
/** [[firrtl.options.Phase Phase]] that adds default [[FirrtlOption]] [[firrtl.annotations.Annotation Annotation]]s.
* This is a part of the preprocessing done by [[FirrtlStage]].
@@ -18,14 +19,17 @@ class AddDefaults extends Phase {
override def invalidates(a: Phase) = false
+ val DefaultEmitterTarget: TransformDependency = Dependency[VerilogEmitter]
+
/** Append any missing default annotations to an annotation sequence */
def transform(annotations: AnnotationSeq): AnnotationSeq = {
- var bb, c, im = true
+ var bb, c, em, im = true
annotations.foreach {
case _: BlackBoxTargetDirAnno => bb = false
case _: CompilerAnnotation => c = false
case _: InfoModeAnnotation => im = false
- case a =>
+ case RunFirrtlTransformAnnotation(_ : firrtl.Emitter) => em = false
+ case _ =>
}
val default = new FirrtlOptions()
@@ -34,7 +38,8 @@ class AddDefaults extends Phase {
.getOrElse(TargetDirAnnotation()).directory
(if (bb) Seq(BlackBoxTargetDirAnno(targetDir)) else Seq() ) ++
- (if (c) Seq(CompilerAnnotation(default.compiler)) else Seq() ) ++
+ // if there is no compiler or emitter specified, add the default emitter
+ (if (c && em) Seq(RunFirrtlTransformAnnotation(DefaultEmitterTarget)) else Seq() ) ++
(if (im) Seq(InfoModeAnnotation()) else Seq() ) ++
annotations
}
diff --git a/src/main/scala/firrtl/stage/phases/AddImplicitEmitter.scala b/src/main/scala/firrtl/stage/phases/AddImplicitEmitter.scala
index 4f658aa2..edf62c3a 100644
--- a/src/main/scala/firrtl/stage/phases/AddImplicitEmitter.scala
+++ b/src/main/scala/firrtl/stage/phases/AddImplicitEmitter.scala
@@ -2,7 +2,7 @@
package firrtl.stage.phases
-import firrtl.{AnnotationSeq, EmitAnnotation, EmitCircuitAnnotation}
+import firrtl.{AnnotationSeq, EmitAnnotation, EmitCircuitAnnotation, Emitter}
import firrtl.stage.{CompilerAnnotation, RunFirrtlTransformAnnotation}
import firrtl.options.{Dependency, Phase}
@@ -18,14 +18,16 @@ class AddImplicitEmitter extends Phase {
override def invalidates(a: Phase) = false
def transform(annos: AnnotationSeq): AnnotationSeq = {
- val emitter = annos.collectFirst{ case a: EmitAnnotation => a }
+ val emit = annos.collectFirst{ case a: EmitAnnotation => a }
+ val emitter = annos.collectFirst{ case RunFirrtlTransformAnnotation(e : Emitter) => e }
val compiler = annos.collectFirst{ case CompilerAnnotation(a) => a }
- if (emitter.isEmpty && compiler.nonEmpty) {
+ if (emit.isEmpty && (compiler.nonEmpty || emitter.nonEmpty)) {
annos.flatMap{
case a: CompilerAnnotation => Seq(a,
RunFirrtlTransformAnnotation(compiler.get.emitter),
EmitCircuitAnnotation(compiler.get.emitter.getClass))
+ case a @ RunFirrtlTransformAnnotation(e : Emitter) => Seq(a, EmitCircuitAnnotation(e.getClass))
case a => Some(a)
}
} else {
diff --git a/src/main/scala/firrtl/stage/phases/Checks.scala b/src/main/scala/firrtl/stage/phases/Checks.scala
index 1d16c7db..7ecdc47e 100644
--- a/src/main/scala/firrtl/stage/phases/Checks.scala
+++ b/src/main/scala/firrtl/stage/phases/Checks.scala
@@ -31,7 +31,7 @@ class Checks extends Phase {
* @throws firrtl.options.OptionsException if any checks fail
*/
def transform(annos: AnnotationSeq): AnnotationSeq = {
- val inF, inS, eam, ec, outF, comp, im, inC = collection.mutable.ListBuffer[Annotation]()
+ val inF, inS, eam, ec, outF, comp, emitter, im, inC = collection.mutable.ListBuffer[Annotation]()
annos.foreach(
_ match {
case a: FirrtlFileAnnotation => a +=: inF
@@ -42,6 +42,7 @@ class Checks extends Phase {
case a: CompilerAnnotation => a +=: comp
case a: InfoModeAnnotation => a +=: im
case a: FirrtlCircuitAnnotation => a +=: inC
+ case a @ RunFirrtlTransformAnnotation(_ : firrtl.Emitter) => a +=: emitter
case _ => })
/* At this point, only a FIRRTL Circuit should exist */
@@ -75,8 +76,8 @@ class Checks extends Phase {
s"""|No more than one output file can be specified, but found '${x.mkString(", ")}' specified via:
| - option or annotation: -o, --output-file, OutputFileAnnotation""".stripMargin) }
- /* One mandatory compiler must be specified */
- if (comp.size != 1) {
+ /* One mandatory compiler (or emitter) must be specified */
+ if (comp.size != 1 && emitter.isEmpty) {
val x = comp.map{ case CompilerAnnotation(x) => x }
val (msg, suggest) = if (comp.size == 0) { ("none found", "forget one of") }
else { (s"""found '${x.mkString(", ")}'""", "use multiple of") }
diff --git a/src/main/scala/firrtl/stage/phases/Compiler.scala b/src/main/scala/firrtl/stage/phases/Compiler.scala
index e3a96b0e..b3e902c8 100644
--- a/src/main/scala/firrtl/stage/phases/Compiler.scala
+++ b/src/main/scala/firrtl/stage/phases/Compiler.scala
@@ -98,7 +98,14 @@ class Compiler extends Phase with Translator[AnnotationSeq, Seq[CompilerRun]] {
def f(c: CompilerRun): CompilerRun = {
val targets = c.compiler match {
case Some(d) => c.transforms.reverse.map(Dependency.fromTransform(_)) ++ compilerToTransforms(d)
- case None => throw new PhasePrerequisiteException("No compiler specified!") }
+ case None =>
+ val hasEmitter = c.transforms.collectFirst { case _: firrtl.Emitter => true }.isDefined
+ if(!hasEmitter) {
+ throw new PhasePrerequisiteException("No compiler specified!")
+ } else {
+ c.transforms.reverse.map(Dependency.fromTransform)
+ }
+ }
val tm = new firrtl.stage.transforms.Compiler(targets)
/* Transform order is lazily evaluated. Force it here to remove its resolution time from actual compilation. */
val (timeResolveDependencies, _) = firrtl.Utils.time { tm.flattenedTransformOrder }
diff --git a/src/test/scala/firrtlTests/stage/FirrtlOptionsViewSpec.scala b/src/test/scala/firrtlTests/stage/FirrtlOptionsViewSpec.scala
index 95c2ee93..4161d29b 100644
--- a/src/test/scala/firrtlTests/stage/FirrtlOptionsViewSpec.scala
+++ b/src/test/scala/firrtlTests/stage/FirrtlOptionsViewSpec.scala
@@ -38,7 +38,6 @@ class FirrtlOptionsViewSpec extends AnyFlatSpec with Matchers {
val out = view[FirrtlOptions](annotations)
out.outputFileName should be (Some("bar"))
- out.compiler.getClass should be (classOf[BazCompiler])
out.infoModeName should be ("use")
out.firrtlCircuit should be (Some(grault))
}
@@ -59,7 +58,6 @@ class FirrtlOptionsViewSpec extends AnyFlatSpec with Matchers {
val out = view[FirrtlOptions](annotations ++ overwrites)
out.outputFileName should be (Some("bar_"))
- out.compiler.getClass should be (classOf[Baz_Compiler])
out.infoModeName should be ("gen")
out.firrtlCircuit should be (Some(grault_))
}
diff --git a/src/test/scala/firrtlTests/stage/phases/AddDefaultsSpec.scala b/src/test/scala/firrtlTests/stage/phases/AddDefaultsSpec.scala
index 89f5193c..b600e6c5 100644
--- a/src/test/scala/firrtlTests/stage/phases/AddDefaultsSpec.scala
+++ b/src/test/scala/firrtlTests/stage/phases/AddDefaultsSpec.scala
@@ -7,8 +7,8 @@ import firrtl.NoneCompiler
import firrtl.annotations.Annotation
import firrtl.stage.phases.AddDefaults
import firrtl.transforms.BlackBoxTargetDirAnno
-import firrtl.stage.{CompilerAnnotation, InfoModeAnnotation}
-import firrtl.options.{Phase, TargetDirAnnotation}
+import firrtl.stage.{CompilerAnnotation, InfoModeAnnotation, RunFirrtlTransformAnnotation}
+import firrtl.options.{Dependency, Phase, TargetDirAnnotation}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
@@ -21,7 +21,8 @@ class AddDefaultsSpec extends AnyFlatSpec with Matchers {
it should "add expected default annotations and nothing else" in new Fixture {
val expected = Seq(
(a: Annotation) => a match { case BlackBoxTargetDirAnno(b) => b == TargetDirAnnotation().directory },
- (a: Annotation) => a match { case CompilerAnnotation(b) => b.getClass == CompilerAnnotation().compiler.getClass },
+ (a: Annotation) => a match { case RunFirrtlTransformAnnotation(e: firrtl.Emitter) =>
+ Dependency.fromTransform(e) == Dependency[firrtl.VerilogEmitter] },
(a: Annotation) => a match { case InfoModeAnnotation(b) => b == InfoModeAnnotation().modeName } )
phase.transform(Seq.empty).zip(expected).map { case (x, f) => f(x) should be (true) }