use of org.lflang.lf.WidthTerm in project lingua-franca by lf-lang.
the class ASTUtils method getDelayInstance.
/**
* Create a new instance delay instances using the given reactor class.
* The supplied time value is used to override the default interval (which
* is zero).
* If the target supports parametric polymorphism, then a single class may
* be used for each instantiation, in which case a non-empty string must
* be supplied to parameterize the instance.
* A default name ("delay") is assigned to the instantiation, but this
* name must be overridden at the call site, where checks can be done to
* avoid name collisions in the container in which the instantiation is
* to be placed. Such checks (or modifications of the AST) are not
* performed in this method in order to avoid causing concurrent
* modification exceptions.
* @param delayClass The class to create an instantiation for
* @param connection The connection to create a delay instantiation foe
* @param generic A string that denotes the appropriate type parameter,
* which should be null or empty if the target does not support generics.
* @param defineWidthFromConnection If this is true and if the connection
* is a wide connection, then instantiate a bank of delays where the width
* is given by ports involved in the connection. Otherwise, the width will
* be unspecified indicating a variable length.
*/
private static Instantiation getDelayInstance(Reactor delayClass, Connection connection, String generic, Boolean defineWidthFromConnection) {
Delay delay = connection.getDelay();
Instantiation delayInstance = factory.createInstantiation();
delayInstance.setReactorClass(delayClass);
if (!StringExtensions.isNullOrEmpty(generic)) {
TypeParm typeParm = factory.createTypeParm();
typeParm.setLiteral(generic);
delayInstance.getTypeParms().add(typeParm);
}
if (hasMultipleConnections(connection)) {
WidthSpec widthSpec = factory.createWidthSpec();
if (defineWidthFromConnection) {
// to delay the ports first, and then broadcast the output of the delays.
for (VarRef port : connection.getLeftPorts()) {
WidthTerm term = factory.createWidthTerm();
term.setPort(EcoreUtil.copy(port));
widthSpec.getTerms().add(term);
}
} else {
widthSpec.setOfVariableLength(true);
}
delayInstance.setWidthSpec(widthSpec);
}
Assignment assignment = factory.createAssignment();
assignment.setLhs(delayClass.getParameters().get(0));
Value value = factory.createValue();
if (delay.getParameter() != null) {
value.setParameter(delay.getParameter());
} else {
value.setTime(delay.getTime());
}
assignment.getRhs().add(value);
delayInstance.getParameters().add(assignment);
// This has to be overridden.
delayInstance.setName("delay");
return delayInstance;
}
use of org.lflang.lf.WidthTerm in project lingua-franca by lf-lang.
the class ASTUtils method width.
/**
* Given the width specification of port or instantiation
* and an (optional) list of nested instantiations, return
* the width if it can be determined and -1 if not.
* It will not be able to be determined if either the
* width is variable (in which case you should use
* {@link inferPortWidth(VarRef, Connection, List<Instantiation>})
* or the list of instantiations is incomplete or missing.
* If there are parameter references in the width, they are
* evaluated to the extent possible given the instantiations list.
*
* The instantiations list is as in
* {@link initialValue(Parameter, List<Instantiation>)}.
* If the spec belongs to an instantiation (for a bank of reactors),
* then the first element on this list should be the instantiation
* that contains this instantiation. If the spec belongs to a port,
* then the first element on the list should be the instantiation
* of the reactor that contains the port.
*
* @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 determined.
*
* @throws IllegalArgumentException If an instantiation provided is not as
* given above or if the chain of instantiations is not nested.
*/
public static int width(WidthSpec spec, List<Instantiation> instantiations) {
if (spec == null) {
return 1;
}
if (spec.isOfVariableLength() && spec.eContainer() instanceof Instantiation) {
// 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;
}
var result = 0;
for (WidthTerm term : spec.getTerms()) {
if (term.getParameter() != null) {
Integer termWidth = initialValueInt(term.getParameter(), instantiations);
if (termWidth != null) {
result += termWidth;
} else {
return -1;
}
} else if (term.getWidth() > 0) {
result += term.getWidth();
} else {
return -1;
}
}
return result;
}
use of org.lflang.lf.WidthTerm in project lingua-franca by lf-lang.
the class PortInstance method setInitialWidth.
/**
* Set the initial multiport width, if this is a multiport, from the widthSpec
* in the definition. This will be set to -1 if the width cannot be determined.
* @param errorReporter For reporting errors.
*/
private void setInitialWidth(ErrorReporter errorReporter) {
// If this is a multiport, determine the width.
WidthSpec widthSpec = definition.getWidthSpec();
if (widthSpec != null) {
if (widthSpec.isOfVariableLength()) {
errorReporter.reportError(definition, "Variable-width multiports not supported (yet): " + definition.getName());
} else {
isMultiport = true;
// Determine the initial width, if possible.
// The width may be given by a parameter or even sum of parameters.
width = 0;
for (WidthTerm term : widthSpec.getTerms()) {
Parameter parameter = term.getParameter();
if (parameter != null) {
Integer parameterValue = parent.initialIntParameterValue(parameter);
// Only a Literal is supported.
if (parameterValue != null) {
width += parameterValue;
} else {
width = -1;
return;
}
} else if (term.getWidth() != 0) {
width += term.getWidth();
} else {
width = -1;
return;
}
}
}
}
}
Aggregations