diff options
Diffstat (limited to 'src/main/scala/firrtl/options/phases')
5 files changed, 87 insertions, 13 deletions
diff --git a/src/main/scala/firrtl/options/phases/AddDefaults.scala b/src/main/scala/firrtl/options/phases/AddDefaults.scala index f0749b22..2d4e4e40 100644 --- a/src/main/scala/firrtl/options/phases/AddDefaults.scala +++ b/src/main/scala/firrtl/options/phases/AddDefaults.scala @@ -10,14 +10,10 @@ import firrtl.options.{Phase, StageOption, TargetDirAnnotation} * This currently only adds a [[TargetDirAnnotation]]. This isn't necessary for a [[StageOptionsView]], but downstream * tools may expect a [[TargetDirAnnotation]] to exist. */ -object AddDefaults extends Phase { +class AddDefaults extends Phase { def transform(annotations: AnnotationSeq): AnnotationSeq = { - var td = true - annotations.collect { case a: StageOption => a }.map { - case _: TargetDirAnnotation => td = false - case _ => - } + val td = annotations.collectFirst{ case a: TargetDirAnnotation => a}.isEmpty (if (td) Seq(TargetDirAnnotation()) else Seq()) ++ annotations diff --git a/src/main/scala/firrtl/options/phases/Checks.scala b/src/main/scala/firrtl/options/phases/Checks.scala new file mode 100644 index 00000000..0691e9b0 --- /dev/null +++ b/src/main/scala/firrtl/options/phases/Checks.scala @@ -0,0 +1,43 @@ +// See LICENSE for license details. + +package firrtl.options.phases + +import firrtl.AnnotationSeq +import firrtl.annotations.Annotation +import firrtl.options.{OptionsException, OutputAnnotationFileAnnotation, Phase, TargetDirAnnotation} + +/** [[firrtl.options.Phase Phase]] that validates an [[AnnotationSeq]]. If successful, views of this [[AnnotationSeq]] + * as [[StageOptions]] are guaranteed to succeed. + */ +class Checks extends Phase { + + /** Validate an [[AnnotationSeq]] for [[StageOptions]] + * @throws OptionsException if annotations are invalid + */ + def transform(annotations: AnnotationSeq): AnnotationSeq = { + + val td, outA = collection.mutable.ListBuffer[Annotation]() + annotations.foreach { + case a: TargetDirAnnotation => td += a + case a: OutputAnnotationFileAnnotation => outA += a + case _ => + } + + if (td.size != 1) { + val d = td.map{ case TargetDirAnnotation(x) => x } + throw new OptionsException( + s"""|Exactly one target directory must be specified, but found `${d.mkString(", ")}` specified via: + | - explicit target directory: -td, --target-dir, TargetDirAnnotation + | - fallback default value""".stripMargin )} + + if (outA.size > 1) { + val x = outA.map{ case OutputAnnotationFileAnnotation(x) => x } + throw new OptionsException( + s"""|At most one output annotation file can be specified, but found '${x.mkString(", ")}' specified via: + | - an option or annotation: -foaf, --output-annotation-file, OutputAnnotationFileAnnotation""" + .stripMargin )} + + annotations + } + +} diff --git a/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala b/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala index 7ff05370..39f59572 100644 --- a/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala +++ b/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala @@ -7,7 +7,7 @@ import firrtl.annotations.LegacyAnnotation import firrtl.options.Phase /** Convert any [[firrtl.annotations.LegacyAnnotation LegacyAnnotation]]s to non-legacy variants */ -object ConvertLegacyAnnotations extends Phase { +class ConvertLegacyAnnotations extends Phase { def transform(annotations: AnnotationSeq): AnnotationSeq = LegacyAnnotation.convertLegacyAnnos(annotations) diff --git a/src/main/scala/firrtl/options/phases/GetIncludes.scala b/src/main/scala/firrtl/options/phases/GetIncludes.scala index 8156dbbf..9e198c61 100644 --- a/src/main/scala/firrtl/options/phases/GetIncludes.scala +++ b/src/main/scala/firrtl/options/phases/GetIncludes.scala @@ -5,7 +5,7 @@ package firrtl.options.phases import net.jcazevedo.moultingyaml._ import firrtl.AnnotationSeq -import firrtl.annotations.{AnnotationFileNotFoundException, DeletedAnnotation, JsonProtocol, LegacyAnnotation} +import firrtl.annotations.{AnnotationFileNotFoundException, JsonProtocol, LegacyAnnotation} import firrtl.annotations.AnnotationYamlProtocol._ import firrtl.options.{InputAnnotationFileAnnotation, Phase, StageUtils} @@ -15,7 +15,7 @@ import scala.collection.mutable import scala.util.{Try, Failure} /** Recursively expand all [[InputAnnotationFileAnnotation]]s in an [[AnnotationSeq]] */ -object GetIncludes extends Phase { +class GetIncludes extends Phase { /** Read all [[annotations.Annotation]] from a file in JSON or YAML format * @param filename a JSON or YAML file of [[annotations.Annotation]] @@ -46,15 +46,14 @@ object GetIncludes extends Phase { */ private def getIncludes(includeGuard: mutable.Set[String] = mutable.Set()) (annos: AnnotationSeq): AnnotationSeq = { - val phaseName = this.getClass.getName annos.flatMap { case a @ InputAnnotationFileAnnotation(value) => if (includeGuard.contains(value)) { - StageUtils.dramaticWarning("Tried to import the same annotation file twice! (Did you include it twice?)") - Seq(DeletedAnnotation(phaseName, a)) + StageUtils.dramaticWarning(s"Annotation file ($value) already included! (Did you include it more than once?)") + None } else { includeGuard += value - DeletedAnnotation(phaseName, a) +: getIncludes(includeGuard)(readAnnotationsFromFile(value)) + getIncludes(includeGuard)(readAnnotationsFromFile(value)) } case x => Seq(x) } diff --git a/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala b/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala new file mode 100644 index 00000000..66f40d3c --- /dev/null +++ b/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala @@ -0,0 +1,36 @@ +// See LICENSE for license details. + +package firrtl.options.phases + +import firrtl.AnnotationSeq +import firrtl.annotations.{DeletedAnnotation, JsonProtocol} +import firrtl.options.{Phase, StageOptions, Unserializable, Viewer} + +import java.io.PrintWriter + +/** [[firrtl.options.Phase Phase]] that writes an [[AnnotationSeq]] to a file. A file is written if and only if a + * [[StageOptions]] view has a non-empty [[StageOptions.annotationFileOut annotationFileOut]]. + */ +class WriteOutputAnnotations extends Phase { + + /** Write the input [[AnnotationSeq]] to a fie. */ + def transform(annotations: AnnotationSeq): AnnotationSeq = { + val sopts = Viewer.view[StageOptions](annotations) + val serializable = annotations.filter{ + case _: Unserializable => false + case _: DeletedAnnotation => sopts.writeDeleted + case _ => true + } + + sopts.annotationFileOut match { + case None => + case Some(file) => + val pw = new PrintWriter(sopts.getBuildFileName(file, Some(".anno.json"))) + pw.write(JsonProtocol.serialize(serializable)) + pw.close() + } + + annotations + } + +} |
