Search in sources :

Example 1 with WidthTerm

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;
}
Also used : VarRef(org.lflang.lf.VarRef) Assignment(org.lflang.lf.Assignment) Value(org.lflang.lf.Value) Instantiation(org.lflang.lf.Instantiation) WidthTerm(org.lflang.lf.WidthTerm) Delay(org.lflang.lf.Delay) TypeParm(org.lflang.lf.TypeParm) WidthSpec(org.lflang.lf.WidthSpec)

Example 2 with WidthTerm

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;
}
Also used : VarRef(org.lflang.lf.VarRef) InvalidSourceException(org.lflang.generator.InvalidSourceException) Connection(org.lflang.lf.Connection) Instantiation(org.lflang.lf.Instantiation) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor) WidthTerm(org.lflang.lf.WidthTerm)

Example 3 with WidthTerm

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;
                }
            }
        }
    }
}
Also used : Parameter(org.lflang.lf.Parameter) WidthTerm(org.lflang.lf.WidthTerm) WidthSpec(org.lflang.lf.WidthSpec)

Aggregations

WidthTerm (org.lflang.lf.WidthTerm)3 Instantiation (org.lflang.lf.Instantiation)2 VarRef (org.lflang.lf.VarRef)2 WidthSpec (org.lflang.lf.WidthSpec)2 InvalidSourceException (org.lflang.generator.InvalidSourceException)1 Assignment (org.lflang.lf.Assignment)1 Connection (org.lflang.lf.Connection)1 Delay (org.lflang.lf.Delay)1 ImportedReactor (org.lflang.lf.ImportedReactor)1 Parameter (org.lflang.lf.Parameter)1 Reactor (org.lflang.lf.Reactor)1 TypeParm (org.lflang.lf.TypeParm)1 Value (org.lflang.lf.Value)1