diff options
| author | Schuyler Eldridge | 2020-04-22 20:26:11 -0400 |
|---|---|---|
| committer | GitHub | 2020-04-22 20:26:11 -0400 |
| commit | 404d419a42c33ce4a68eedce636c336adf7d53be (patch) | |
| tree | 607b55e30774227895c75b60fb8fd67845ed23a8 /src/main/scala/firrtl/options | |
| parent | 65360f886f9b92438d1b6fe609120b34ebb413cf (diff) | |
| parent | ffa6958535292d636923739d9d77b566054e2208 (diff) | |
Merge pull request #1537 from freechipsproject/optionalPrerequisitesOf
Change `dependents` to `optionalPrerequisiteOf`
Diffstat (limited to 'src/main/scala/firrtl/options')
8 files changed, 50 insertions, 29 deletions
diff --git a/src/main/scala/firrtl/options/DependencyManager.scala b/src/main/scala/firrtl/options/DependencyManager.scala index 537f87bd..910d44bb 100644 --- a/src/main/scala/firrtl/options/DependencyManager.scala +++ b/src/main/scala/firrtl/options/DependencyManager.scala @@ -22,10 +22,11 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends override def prerequisites = currentState - override def dependents = Seq.empty override def optionalPrerequisites = Seq.empty + override def optionalPrerequisiteOf = Seq.empty + override def invalidates(a: B): Boolean = (_currentState &~ _targets)(oToD(a)) /** Requested [[firrtl.options.TransformLike TransformLike]]s that should be run. Internally, this will be converted to @@ -121,11 +122,11 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends } /** A directed graph consisting of prerequisites derived from only those transforms which are supposed to run. This - * pulls in dependents for transforms which are not in the target set. + * pulls in optionalPrerequisiteOf for transforms which are not in the target set. */ - private lazy val dependentsGraph: DiGraph[B] = { + private lazy val optionalPrerequisiteOfGraph: DiGraph[B] = { val v = new LinkedHashSet() ++ prerequisiteGraph.getVertices - DiGraph(new LinkedHashMap() ++ v.map(vv => vv -> (v & (vv._dependents).map(dToO)))).reverse + DiGraph(new LinkedHashMap() ++ v.map(vv => vv -> (v & (vv._optionalPrerequisiteOf.toSet).map(dToO)))).reverse } /** A directed graph of *optional* prerequisites. Each optional prerequisite is promoted to a full prerequisite if the @@ -139,11 +140,11 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends /** A directed graph consisting of prerequisites derived from ALL targets. This is necessary for defining targets for * [[DependencyManager]] sub-problems. */ - private lazy val otherDependents: DiGraph[B] = { + private lazy val otherPrerequisites: DiGraph[B] = { val edges = { val x = new LinkedHashMap ++ _targets .map(dependencyToObject) - .map{ a => a -> prerequisiteGraph.getVertices.filter(a._dependents(_)) } + .map{ a => a -> prerequisiteGraph.getVertices.filter(a._optionalPrerequisiteOf(_)) } x .values .reduce(_ ++ _) @@ -152,8 +153,10 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends DiGraph(edges).reverse } - /** A directed graph consisting of all prerequisites, including prerequisites derived from dependents */ - lazy val dependencyGraph: DiGraph[B] = prerequisiteGraph + dependentsGraph + optionalPrerequisitesGraph + /** A directed graph consisting of all prerequisites, including prerequisites derived from optionalPrerequisites and + * optionalPrerequisiteOf + */ + lazy val dependencyGraph: DiGraph[B] = prerequisiteGraph + optionalPrerequisiteOfGraph + optionalPrerequisitesGraph /** A directed graph consisting of invalidation edges */ lazy val invalidateGraph: DiGraph[B] = { @@ -178,9 +181,9 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends /** An ordering of [[firrtl.options.TransformLike TransformLike]]s that causes the requested [[DependencyManager.targets * targets]] to be executed starting from the [[DependencyManager.currentState currentState]]. This ordering respects - * prerequisites, dependents, and invalidates of all constituent [[firrtl.options.TransformLike TransformLike]]s. - * This uses an algorithm that attempts to reduce the number of re-lowerings due to invalidations. Re-lowerings are - * implemented as new [[DependencyManager]]s. + * prerequisites, optionalPrerequisites, optionalPrerequisiteOf, and invalidates of all constituent + * [[firrtl.options.TransformLike TransformLike]]s. This uses an algorithm that attempts to reduce the number of + * re-lowerings due to invalidations. Re-lowerings are implemented as new [[DependencyManager]]s. * @throws DependencyManagerException if a cycle exists in either the [[DependencyManager.dependencyGraph * dependencyGraph]] or the [[DependencyManager.invalidateGraph invalidateGraph]]. */ @@ -199,7 +202,7 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends v.map(vv => vv -> (new LinkedHashSet() ++ (dependencyGraph.getEdges(vv).toSeq.sortWith(cmp)))) } - cyclePossible("prerequisites/dependents", dependencyGraph) { + cyclePossible("prerequisites", dependencyGraph) { DiGraph(edges) .linearize .reverse @@ -209,10 +212,9 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends /* [todo] Seq is inefficient here, but Array has ClassTag problems. Use something else? */ val (s, l) = sorted.foldLeft((_currentState, Seq[B]())){ case ((state, out), in) => - /* The prerequisites are both prerequisites AND dependents. */ val prereqs = in._prerequisites ++ dependencyGraph.getEdges(in).toSeq.map(oToD) ++ - otherDependents.getEdges(in).toSeq.map(oToD) + otherPrerequisites.getEdges(in).toSeq.map(oToD) val preprocessing: Option[B] = { if ((prereqs -- state).nonEmpty) { Some(this.copy(prereqs.toSeq, state.toSeq)) } else { None } @@ -267,7 +269,8 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends /** Get a name of some [[firrtl.options.TransformLike TransformLike]] */ private def transformName(transform: B, suffix: String = ""): String = s""""${transform.name}$suffix"""" - /** Convert all prerequisites, dependents, and invalidates to a Graphviz representation. + /** Convert all prerequisites, optionalPrerequisites, optionalPrerequisiteOf, and invalidates to a Graphviz + * representation. * @param file the name of the output file */ def dependenciesToGraphviz: String = { @@ -291,14 +294,14 @@ trait DependencyManager[A, B <: TransformLike[A] with DependencyAPI[B]] extends val connections = Seq( (prerequisiteGraph, "edge []"), - (dependentsGraph, """edge [style=bold color="#4292c6"]"""), + (optionalPrerequisiteOfGraph, """edge [style=bold color="#4292c6"]"""), (invalidateGraph, """edge [minlen=2 style=dashed constraint=false color="#fb6a4a"]"""), (optionalPrerequisitesGraph, """edge [style=dotted color="#a1d99b"]""") ) .flatMap{ case (a, b) => toGraphviz(a, b) } .mkString("\n") val nodes = - (prerequisiteGraph + dependentsGraph + invalidateGraph + otherDependents) + (prerequisiteGraph + optionalPrerequisiteOfGraph + invalidateGraph + otherPrerequisites) .getVertices .map(v => s"""${transformName(v)} [label="${v.name}"]""") diff --git a/src/main/scala/firrtl/options/Phase.scala b/src/main/scala/firrtl/options/Phase.scala index 847a4cf2..6dd5d969 100644 --- a/src/main/scala/firrtl/options/Phase.scala +++ b/src/main/scala/firrtl/options/Phase.scala @@ -106,11 +106,12 @@ trait IdentityLike[A] { this: TransformLike[A] => * "transforms") * * This trait forms the basis of the Dependency API of the Chisel/FIRRTL Hardware Compiler Framework. Dependencies are - * defined in terms of prerequisistes, dependents, and invalidates. A prerequisite is a transform that must run before - * this transform. A dependent is a transform that must run ''after'' this transform. (This can be viewed as a means of - * injecting a prerequisite into some other transform.) Finally, invalidates define the set of transforms whose effects - * this transform undos/invalidates. (Invalidation then implies that a transform that is invalidated by this transform - * and needed by another transform will need to be re-run.) + * defined in terms of prerequisistes, optional prerequisites, optional prerequisites of, and invalidates. A + * prerequisite is a transform that must run before this transform. An optional prerequisites is transform that should + * run before this transform if the other transform is a target (or the prerequisite of a target). An optional + * prerequisite of is an optional prerequisite injected into another transform. Finally, invalidates define the set of + * transforms whose effects this transform undos/invalidates. (Invalidation then implies that a transform that is + * invalidated by this transform and needed by another transform will need to be re-run.) * * This Dependency API only defines dependencies. A concrete [[DependencyManager]] is expected to be used to statically * resolve a linear ordering of transforms that satisfies dependency requirements. @@ -152,8 +153,25 @@ trait DependencyAPI[A <: DependencyAPI[A]] { this: TransformLike[_] => * @see [[firrtl.passes.CheckTypes]] for an example of an optional checking [[firrtl.Transform]] * $seqNote */ + @deprecated( + "Due to confusion, 'dependents' is being renamed to 'optionalPrerequisiteOf'. Override the latter instead.", + "FIRRTL 1.3" + ) def dependents: Seq[Dependency[A]] = Seq.empty - private[options] lazy val _dependents: LinkedHashSet[Dependency[A]] = new LinkedHashSet() ++ dependents.toSet + + /** A sequence of transforms to add this transform as an `optionalPrerequisite`. The use of `optionalPrerequisiteOf` + * enables the transform declaring them to always run before some other transforms. However, declaring + * `optionalPrerequisiteOf` will not result in the sequence of transforms executing. + * + * This is useful for providing an ordering constraint to guarantee that other transforms (e.g., emitters) will not + * be scheduled before you. + * + * @note This method **will not** result in the listed transforms running. If you want to add multiple transforms at + * once, you should use a `DependencyManager` with multiple targets. + */ + def optionalPrerequisiteOf: Seq[Dependency[A]] = dependents + private[options] lazy val _optionalPrerequisiteOf: LinkedHashSet[Dependency[A]] = + new LinkedHashSet() ++ optionalPrerequisiteOf.toSet /** A function that, given *another* transform (parameter `a`) will return true if this transform invalidates/undos the * effects of the *other* transform (parameter `a`). diff --git a/src/main/scala/firrtl/options/phases/AddDefaults.scala b/src/main/scala/firrtl/options/phases/AddDefaults.scala index 034c502f..79089194 100644 --- a/src/main/scala/firrtl/options/phases/AddDefaults.scala +++ b/src/main/scala/firrtl/options/phases/AddDefaults.scala @@ -14,7 +14,7 @@ class AddDefaults extends Phase with PreservesAll[Phase] { override def prerequisites = Seq(Dependency[GetIncludes], Dependency[ConvertLegacyAnnotations]) - override def dependents = Seq.empty + override def optionalPrerequisiteOf = Seq.empty def transform(annotations: AnnotationSeq): AnnotationSeq = { val td = annotations.collectFirst{ case a: TargetDirAnnotation => a}.isEmpty diff --git a/src/main/scala/firrtl/options/phases/Checks.scala b/src/main/scala/firrtl/options/phases/Checks.scala index 69cbc7ed..ed2f1a28 100644 --- a/src/main/scala/firrtl/options/phases/Checks.scala +++ b/src/main/scala/firrtl/options/phases/Checks.scala @@ -14,7 +14,7 @@ class Checks extends Phase with PreservesAll[Phase] { override def prerequisites = Seq(Dependency[GetIncludes], Dependency[ConvertLegacyAnnotations], Dependency[AddDefaults]) - override def dependents = Seq.empty + override def optionalPrerequisiteOf = Seq.empty /** Validate an [[AnnotationSeq]] for [[StageOptions]] * @throws OptionsException if annotations are invalid diff --git a/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala b/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala index 7611f66f..1eb4c2d9 100644 --- a/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala +++ b/src/main/scala/firrtl/options/phases/ConvertLegacyAnnotations.scala @@ -11,7 +11,7 @@ class ConvertLegacyAnnotations extends Phase with PreservesAll[Phase] { override def prerequisites = Seq(Dependency[GetIncludes]) - override def dependents = Seq.empty + override def optionalPrerequisiteOf = Seq.empty def transform(annotations: AnnotationSeq): AnnotationSeq = LegacyAnnotation.convertLegacyAnnos(annotations) diff --git a/src/main/scala/firrtl/options/phases/DeletedWrapper.scala b/src/main/scala/firrtl/options/phases/DeletedWrapper.scala index 4a112172..76ff21ad 100644 --- a/src/main/scala/firrtl/options/phases/DeletedWrapper.scala +++ b/src/main/scala/firrtl/options/phases/DeletedWrapper.scala @@ -17,7 +17,7 @@ class DeletedWrapper(p: Phase) extends Phase with Translator[AnnotationSeq, (Ann override def prerequisites = Seq.empty - override def dependents = Seq.empty + override def optionalPrerequisiteOf = Seq.empty override lazy val name: String = p.name diff --git a/src/main/scala/firrtl/options/phases/GetIncludes.scala b/src/main/scala/firrtl/options/phases/GetIncludes.scala index 3b26795f..86e451eb 100644 --- a/src/main/scala/firrtl/options/phases/GetIncludes.scala +++ b/src/main/scala/firrtl/options/phases/GetIncludes.scala @@ -20,7 +20,7 @@ class GetIncludes extends Phase with PreservesAll[Phase] { override def prerequisites = Seq.empty - override def dependents = Seq.empty + override def optionalPrerequisiteOf = Seq.empty /** Read all [[annotations.Annotation]] from a file in JSON or YAML format * @param filename a JSON or YAML file of [[annotations.Annotation]] diff --git a/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala b/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala index 79769a81..2d226de1 100644 --- a/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala +++ b/src/main/scala/firrtl/options/phases/WriteOutputAnnotations.scala @@ -20,7 +20,7 @@ class WriteOutputAnnotations extends Phase with PreservesAll[Phase] { Dependency[AddDefaults], Dependency[Checks] ) - override def dependents = Seq.empty + override def optionalPrerequisiteOf = Seq.empty /** Write the input [[AnnotationSeq]] to a fie. */ def transform(annotations: AnnotationSeq): AnnotationSeq = { |
