diff options
| author | Schuyler Eldridge | 2018-11-22 23:40:38 -0500 |
|---|---|---|
| committer | GitHub | 2018-11-22 23:40:38 -0500 |
| commit | 27afc3d8defd9e2a85d5e3d2f9d2b35310b9b775 (patch) | |
| tree | 8435ab570e88b60ca6af127e607794c64565bb9c /src/main/scala/firrtl/options/phases/GetIncludes.scala | |
| parent | 4a2211c1602b37a65b4e44c3b7ebe82e8bfeedc0 (diff) | |
| parent | 696bc256a90cc80bcb094aaeada8eea51a643ae0 (diff) | |
Merge pull request #945 from seldridge/add-phase
- Change firrtl.options API, add Phase
Diffstat (limited to 'src/main/scala/firrtl/options/phases/GetIncludes.scala')
| -rw-r--r-- | src/main/scala/firrtl/options/phases/GetIncludes.scala | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/options/phases/GetIncludes.scala b/src/main/scala/firrtl/options/phases/GetIncludes.scala new file mode 100644 index 00000000..8156dbbf --- /dev/null +++ b/src/main/scala/firrtl/options/phases/GetIncludes.scala @@ -0,0 +1,65 @@ +// See LICENSE for license details. + +package firrtl.options.phases + +import net.jcazevedo.moultingyaml._ + +import firrtl.AnnotationSeq +import firrtl.annotations.{AnnotationFileNotFoundException, DeletedAnnotation, JsonProtocol, LegacyAnnotation} +import firrtl.annotations.AnnotationYamlProtocol._ +import firrtl.options.{InputAnnotationFileAnnotation, Phase, StageUtils} + +import java.io.File + +import scala.collection.mutable +import scala.util.{Try, Failure} + +/** Recursively expand all [[InputAnnotationFileAnnotation]]s in an [[AnnotationSeq]] */ +object 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]] + * @throws annotations.AnnotationFileNotFoundException if the file does not exist + */ + private def readAnnotationsFromFile(filename: String): AnnotationSeq = { + val file = new File(filename).getCanonicalFile + if (!file.exists) { throw new AnnotationFileNotFoundException(file) } + JsonProtocol.deserializeTry(file).recoverWith { case jsonException => + // Try old protocol if new one fails + Try { + val yaml = io.Source.fromFile(file).getLines().mkString("\n").parseYaml + val result = yaml.convertTo[List[LegacyAnnotation]] + val msg = s"$file is a YAML file!\n" + (" "*9) + "YAML Annotation files are deprecated! Use JSON" + StageUtils.dramaticWarning(msg) + result + }.orElse { // Propagate original JsonProtocol exception if YAML also fails + Failure(jsonException) + } + }.get + } + + /** Recursively read all [[Annotation]]s from any [[InputAnnotationFileAnnotation]]s while making sure that each file is + * only read once + * @param includeGuard filenames that have already been read + * @param annos a sequence of annotations + * @return the original annotation sequence with any discovered annotations added + */ + 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)) + } else { + includeGuard += value + DeletedAnnotation(phaseName, a) +: getIncludes(includeGuard)(readAnnotationsFromFile(value)) + } + case x => Seq(x) + } + } + + def transform(annotations: AnnotationSeq): AnnotationSeq = getIncludes()(annotations) + +} |
