diff --git a/core/src/main/java/org/lflang/pretvm/dag/JobNode.java b/core/src/main/java/org/lflang/pretvm/dag/JobNode.java new file mode 100644 index 0000000000..d544191739 --- /dev/null +++ b/core/src/main/java/org/lflang/pretvm/dag/JobNode.java @@ -0,0 +1,116 @@ +package org.lflang.pretvm.dag; + +import org.lflang.generator.ReactionInstance; + +/** + * Subclass defining a job node, which represents an invocation (job) of a reaction (task). Multiple + * invocations of the same reaction are represented by multiple nodes. + * + * @author Shaokai J. Lin + */ +public class JobNode extends Node { + + ////////////////////////////////////////////////////////////////////// + /// Private Variables + + /** If the node type is REACTION, then point the reaction */ + private ReactionInstance reaction; + + /** + * A DAG node can be associated with a release node, indicating the "timeNode time" of the current + * node. The release node is one with the maximum tag among all of the upstream release nodes wrt + * the current node. + */ + private TimeNode timeNode; + + /** + * If worker B owns another job node J_B that waits for the current job node, J_A, owned by worker + * A to finish, worker B needs to block and wait until worker A to reach the progress index before + * processiong job node J_B. This is necessary to resolve job dependencies in the quasi-static + * schedule. This progress index is assigned only after the schedule have been determined. + */ + private Long progressIndex; + + /** + * An integer that counts the number of times the same reaction instance has repeated in the + * graph. The initial value 0 also means this job is not assigned to a worker. + */ + private int reactionRepeatCount = 0; + + /** Worker ID that owns this job node. The value of -1 means unassigned. */ + private int worker = -1; + + ////////////////////////////////////////////////////////////////////// + /// Constructor + + /** + * Constructor + * + * @param reaction the reaction this node invokes + */ + public JobNode(ReactionInstance reaction) { + this.reaction = reaction; + } + + ////////////////////////////////////////////////////////////////////// + /// Public Methods + + /** A job node is synonymous with another if their reaction instances are the same. */ + public boolean isSynonyous(Node that) { + if (that instanceof JobNode node && this.reaction == node.reaction) return true; + return false; + } + + /** Get the progress index. */ + public Long getProgressIndex() { + return progressIndex; + } + + /** Get the reaction instance this job node invokes. */ + public ReactionInstance getReaction() { + return this.reaction; + } + + /** Get the reaction repeat count. */ + public int getReactionRepeatCount() { + return reactionRepeatCount; + } + + /** Get the time node that marks the logical release time of this reaction invocation. */ + public Node getTimeNode() { + return timeNode; + } + + /** Get the worker that owns the job node. */ + public int getWorker() { + return this.worker; + } + + /** Set the progress index. */ + public void setProgressIndex(Long value) { + progressIndex = value; + } + + /** Set the reaction repeat count. */ + public void setReactionRepeatCount(int reactionRepeatCount) { + this.reactionRepeatCount = reactionRepeatCount; + } + + /** Set the time node that marks the logical release time of this reaction invocation. */ + public void setTimeNode(TimeNode timeNode) { + this.timeNode = timeNode; + } + + /** Set the worker that owns the job node. */ + public void setWorker(int worker) { + this.worker = worker; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + + " node" + + (this.getReaction() == null ? "" : " for " + this.getReaction()) + + (this.reactionRepeatCount == -1 ? "" : " (repeat: " + this.reactionRepeatCount + ")"); + } +} diff --git a/core/src/main/java/org/lflang/pretvm/dag/Node.java b/core/src/main/java/org/lflang/pretvm/dag/Node.java index b92600a792..95aa55c014 100644 --- a/core/src/main/java/org/lflang/pretvm/dag/Node.java +++ b/core/src/main/java/org/lflang/pretvm/dag/Node.java @@ -11,61 +11,14 @@ */ public abstract class Node { - /** - * An integer that counts the number of times the same node has occured in the graph. The value 0 - * means unassigned. - */ - public int count = 0; - - /** - * Worker ID that owns this node, if this node is a reaction node. The value -1 means unassigned. - */ - private int worker = -1; + ////////////////////////////////////////////////////////////////////// + /// Private Variables /** Color of the node for DOT graph */ private String hexColor = "#FFFFFF"; - /** A debug message in the generated DOT */ - private String dotDebugMsg = ""; - - /** A node is synonymous with another if they have the same nodeType, timeStep, and reaction. */ - abstract boolean isSynonyous(Node that); - - public String getColor() { - return this.hexColor; - } - - public void setColor(String hexColor) { - this.hexColor = hexColor; - } - - public int getWorker() { - return this.worker; - } - - public void setWorker(int worker) { - this.worker = worker; - } - - public String getDotDebugMsg() { - return this.dotDebugMsg; - } - - public void setDotDebugMsg(String msg) { - this.dotDebugMsg = msg; - } - - public boolean isAuxiliary() { - return (this instanceof ReleaseNode); - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } + ////////////////////////////////////////////////////////////////////// + /// Public Methods /** * Get instructions generated by this node for a specific worker's instructions. It is important @@ -78,4 +31,22 @@ public void setCount(int count) { public List filterInstructions(List workerInstructions) { return workerInstructions.stream().filter(it -> it.getNodes().contains(this)).toList(); } + + /** Return true if the node is an auxiliary node (i.e., not a job node) */ + public boolean isAuxiliary() { + return !(this instanceof JobNode); + } + + /** Abstract method to be overriden by subclass for checking if two nodes are synonymous. */ + public abstract boolean isSynonyous(Node that); + + /** Get the color of the node rendered in DOT. */ + public String getColor() { + return this.hexColor; + } + + /** Set the color of the node rendered in DOT. */ + public void setColor(String hexColor) { + this.hexColor = hexColor; + } } diff --git a/core/src/main/java/org/lflang/pretvm/dag/ReactionNode.java b/core/src/main/java/org/lflang/pretvm/dag/ReactionNode.java deleted file mode 100644 index 5fca127f9e..0000000000 --- a/core/src/main/java/org/lflang/pretvm/dag/ReactionNode.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.lflang.pretvm.dag; - -import org.lflang.generator.ReactionInstance; - -/** - * Subclass defining a reaction node, which represents a reaction _invocation_. Multiple invocations - * of the same reaction are represented by multiple nodes. - * - * @author Shaokai J. Lin - */ -public class ReactionNode extends Node { - - /** If the node type is REACTION, then point the reaction */ - public ReactionInstance reaction; - - /** - * A DAG node can be associated with a release node, indicating the "releaseNode time" of the - * current node. The release node is one with the maximum tag among all of the upstream release - * nodes wrt the current node. - */ - private ReleaseNode releaseNode; - - /** - * If the dag node is a REACTION node and there is another node owned by another worker waiting - * for the current reaction node to finish, the releaseNode value is the number assigned an WU - * instruction executed by the other worker. The other worker needs to wait until the counter of - * this worker, who owns this reaction node, reaches releaseValue. We store this information - * inside a dag node. This value is assigned only after partitions have been determined. - */ - private Long releaseValue; - - /** - * Constructor - * - * @param reaction the reaction this node invokes - */ - public ReactionNode(ReactionInstance reaction) { - this.reaction = reaction; - } - - public Node getReleaseNode() { - return releaseNode; - } - - /** Get the reaction this node invokes */ - public ReactionInstance getReaction() { - return this.reaction; - } - - public Long getReleaseValue() { - return releaseValue; - } - - public void setReleaseNode(ReleaseNode releaseNode) { - this.releaseNode = releaseNode; - } - - public void setReleaseValue(Long value) { - releaseValue = value; - } - - /** A reaction node is synonymous with another if their reaction instances are the same. */ - @Override - public boolean isSynonyous(Node that) { - if (that instanceof ReactionNode node && this.reaction == node.reaction) return true; - return false; - } - - @Override - public String toString() { - return this.getClass().getSimpleName() - + " node" - + (this.getReaction() == null ? "" : " for " + this.getReaction()) - + (this.count == -1 ? "" : " (count: " + this.count + ")"); - } -} diff --git a/core/src/main/java/org/lflang/pretvm/dag/ReleaseNode.java b/core/src/main/java/org/lflang/pretvm/dag/TimeNode.java similarity index 53% rename from core/src/main/java/org/lflang/pretvm/dag/ReleaseNode.java rename to core/src/main/java/org/lflang/pretvm/dag/TimeNode.java index 20c929a470..ec0aef69ff 100644 --- a/core/src/main/java/org/lflang/pretvm/dag/ReleaseNode.java +++ b/core/src/main/java/org/lflang/pretvm/dag/TimeNode.java @@ -3,25 +3,34 @@ import org.lflang.TimeValue; /** - * Subclass defining a release node, which represents a _logical_ time at which downstream reaction + * Subclass defining a Time Node, which represents a _logical_ time at which downstream reaction * nodes are released. * * @author Shaokai J. Lin */ -public class ReleaseNode extends Node implements Comparable { +public class TimeNode extends Node implements Comparable { + + ////////////////////////////////////////////////////////////////////// + /// Private Variables /** The logical time at which dependent reaction invocations are released */ - public TimeValue time; + private TimeValue time; + + ////////////////////////////////////////////////////////////////////// + /// Constructor /** * Constructor * * @param time the logical release time represented by the node */ - public ReleaseNode(TimeValue time) { + public TimeNode(TimeValue time) { this.time = time; } + ////////////////////////////////////////////////////////////////////// + /// Public Methods + /** * Compare two dag nodes based on their timestamps. * @@ -31,7 +40,7 @@ public ReleaseNode(TimeValue time) { */ @Override public int compareTo(Node that) { - if (that instanceof ReleaseNode node) { + if (that instanceof TimeNode node) { return TimeValue.compare(this.time, node.time); } throw new RuntimeException( @@ -41,15 +50,22 @@ public int compareTo(Node that) { /** A ReleaseNode is synonymous with another if they have the same time. */ @Override public boolean isSynonyous(Node that) { - if (that instanceof ReleaseNode node && this.time.compareTo(node.time) == 0) return true; + if (that instanceof TimeNode node && this.time.compareTo(node.time) == 0) return true; return false; } + /** Get the logical release time. */ + public TimeValue getTime() { + return this.time; + } + + /** Set the logical release time. */ + public void setTime(TimeValue time) { + this.time = time; + } + @Override public String toString() { - return this.getClass().getSimpleName() - + " node" - + (this.time == null ? "" : " @ " + this.time) - + (this.count == -1 ? "" : " (count: " + this.count + ")"); + return this.getClass().getSimpleName() + " node" + (this.time == null ? "" : " @ " + this.time); } }