aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/firrtl/options/DependencyManager.scala37
-rw-r--r--src/main/scala/firrtl/options/Phase.scala30
2 files changed, 44 insertions, 23 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`).