Skip to content

Commit

Permalink
Fix the issue with non-positive parent.width in RuntimeRange by addin…
Browse files Browse the repository at this point in the history
…g logic for inferring width from connections into width() function of ASTUtils.java. (Related PR: #1287).
  • Loading branch information
hokeun committed Jul 11, 2022
1 parent 7ae54d8 commit 31f10da
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 43 deletions.
93 changes: 54 additions & 39 deletions org.lflang/src/org/lflang/ASTUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1434,44 +1434,7 @@ public static int width(WidthSpec spec, List<Instantiation> instantiations) {
return 1;
}
if (spec.isOfVariableLength() && spec.eContainer() instanceof Instantiation) {
// We may be able to infer the width by examining the connections of
// the enclosing reactor definition. This works, for example, with
// delays between multiports or banks of reactors.
// Attempt to infer the width.
for (Connection c : ((Reactor) spec.eContainer().eContainer()).getConnections()) {
int leftWidth = 0;
int rightWidth = 0;
int leftOrRight = 0;
for (VarRef leftPort : c.getLeftPorts()) {
if (leftPort.getContainer() == spec.eContainer()) {
if (leftOrRight != 0) {
throw new InvalidSourceException("Multiple ports with variable width on a connection.");
}
// Indicate that the port is on the left.
leftOrRight = -1;
} else {
leftWidth += inferPortWidth(leftPort, c, instantiations);
}
}
for (VarRef rightPort : c.getRightPorts()) {
if (rightPort.getContainer() == spec.eContainer()) {
if (leftOrRight != 0) {
throw new InvalidSourceException("Multiple ports with variable width on a connection.");
}
// Indicate that the port is on the right.
leftOrRight = 1;
} else {
rightWidth += inferPortWidth(rightPort, c, instantiations);
}
}
if (leftOrRight < 0) {
return rightWidth - leftWidth;
} else if (leftOrRight > 0) {
return leftWidth - rightWidth;
}
}
// A connection was not found with the instantiation.
return -1;
return inferWidthFromConnections(spec, instantiations);
}
var result = 0;
for (WidthTerm term: spec.getTerms()) {
Expand All @@ -1485,7 +1448,11 @@ public static int width(WidthSpec spec, List<Instantiation> instantiations) {
} else if (term.getWidth() > 0) {
result += term.getWidth();
} else {
return -1;
// If the width cannot be determined because term's width <= 0, which means the term's width
// must be inferred, try to infer the width using connections.
if (spec.eContainer() instanceof Instantiation) {
return inferWidthFromConnections(spec, instantiations);
}
}
}
return result;
Expand Down Expand Up @@ -1840,4 +1807,52 @@ private static LinkedHashSet<Reactor> superClasses(Reactor reactor, Set<Reactor>
}
return result;
}

/**
* We may be able to infer the width by examining the connections of
* the enclosing reactor definition. This works, for example, with
* delays between multiports or banks of reactors.
* Attempt to infer the width from connections and return -1 if the width cannot be inferred.
*
* @param spec The width specification or null (to return 1).
* @param instantiations The (optional) list of instantiations.
*
* @return The width, or -1 if the width could not be inferred from connections.
*/
private static int inferWidthFromConnections(WidthSpec spec, List<Instantiation> instantiations) {
for (Connection c : ((Reactor) spec.eContainer().eContainer()).getConnections()) {
int leftWidth = 0;
int rightWidth = 0;
int leftOrRight = 0;
for (VarRef leftPort : c.getLeftPorts()) {
if (leftPort.getContainer() == spec.eContainer()) {
if (leftOrRight != 0) {
throw new InvalidSourceException("Multiple ports with variable width on a connection.");
}
// Indicate that the port is on the left.
leftOrRight = -1;
} else {
leftWidth += inferPortWidth(leftPort, c, instantiations);
}
}
for (VarRef rightPort : c.getRightPorts()) {
if (rightPort.getContainer() == spec.eContainer()) {
if (leftOrRight != 0) {
throw new InvalidSourceException("Multiple ports with variable width on a connection.");
}
// Indicate that the port is on the right.
leftOrRight = 1;
} else {
rightWidth += inferPortWidth(rightPort, c, instantiations);
}
}
if (leftOrRight < 0) {
return rightWidth - leftWidth;
} else if (leftOrRight > 0) {
return leftWidth - rightWidth;
}
}
// A connection was not found with the instantiation.
return -1;
}
}
5 changes: 1 addition & 4 deletions org.lflang/src/org/lflang/generator/RuntimeRange.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,7 @@ public RuntimeRange(
int maxWidth = instance.width; // Initial value.
NamedInstance<?> parent = instance.parent;
while (parent.depth > 0) {
if (parent.width > 0) {
// Skip when width is not positive (e.g., delay reactor instance)
maxWidth *= parent.width;
}
maxWidth *= parent.width;
parent = parent.parent;
}
this.maxWidth = maxWidth;
Expand Down

0 comments on commit 31f10da

Please # to comment.