Search in sources :

Example 6 with VarRef

use of org.lflang.lf.VarRef in project lingua-franca by lf-lang.

the class ASTUtils method hasMultipleConnections.

/**
 * Return true if the connection involves multiple ports on the left or right side of the connection, or
 * if the port on the left or right of the connection involves a bank of reactors or a multiport.
 * @param connection The connection.
 */
public static boolean hasMultipleConnections(Connection connection) {
    if (connection.getLeftPorts().size() > 1 || connection.getRightPorts().size() > 1) {
        return true;
    }
    VarRef leftPort = connection.getLeftPorts().get(0);
    VarRef rightPort = connection.getRightPorts().get(0);
    Instantiation leftContainer = leftPort.getContainer();
    Instantiation rightContainer = rightPort.getContainer();
    Port leftPortAsPort = (Port) leftPort.getVariable();
    Port rightPortAsPort = (Port) rightPort.getVariable();
    if (leftPortAsPort.getWidthSpec() != null || (leftContainer != null && leftContainer.getWidthSpec() != null) || rightPortAsPort.getWidthSpec() != null || (rightContainer != null && rightContainer.getWidthSpec() != null)) {
        return true;
    }
    return false;
}
Also used : VarRef(org.lflang.lf.VarRef) Port(org.lflang.lf.Port) Instantiation(org.lflang.lf.Instantiation)

Example 7 with VarRef

use of org.lflang.lf.VarRef in project lingua-franca by lf-lang.

the class ASTUtils method rerouteViaDelay.

/**
 * Take a connection and reroute it via an instance of a generated delay
 * reactor. This method returns a list to new connections to substitute
 * the original one.
 * @param connection The connection to reroute.
 * @param delayInstance The delay instance to route the connection through.
 */
private static List<Connection> rerouteViaDelay(Connection connection, Instantiation delayInstance) {
    List<Connection> connections = new ArrayList<>();
    Connection upstream = factory.createConnection();
    Connection downstream = factory.createConnection();
    VarRef input = factory.createVarRef();
    VarRef output = factory.createVarRef();
    Reactor delayClass = toDefinition(delayInstance.getReactorClass());
    // Establish references to the involved ports.
    input.setContainer(delayInstance);
    input.setVariable(delayClass.getInputs().get(0));
    output.setContainer(delayInstance);
    output.setVariable(delayClass.getOutputs().get(0));
    upstream.getLeftPorts().addAll(connection.getLeftPorts());
    upstream.getRightPorts().add(input);
    downstream.getLeftPorts().add(output);
    downstream.getRightPorts().addAll(connection.getRightPorts());
    downstream.setIterated(connection.isIterated());
    connections.add(upstream);
    connections.add(downstream);
    return connections;
}
Also used : VarRef(org.lflang.lf.VarRef) Connection(org.lflang.lf.Connection) ArrayList(java.util.ArrayList) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor)

Example 8 with VarRef

use of org.lflang.lf.VarRef in project lingua-franca by lf-lang.

the class PythonReactionGenerator method generateCPythonInitializers.

/**
 * Generate necessary Python-specific initialization code for <code>reaction<code> that belongs to reactor
 * <code>decl<code>.
 *
 * @param reaction The reaction to generate Python-specific initialization for.
 * @param decl The reactor to which <code>reaction<code> belongs to.
 * @param pyObjectDescriptor For each port object created, a Python-specific descriptor will be added to this that
 *  then can be used as an argument to <code>Py_BuildValue<code>
 *  (@see <a href="https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue">docs.python.org/3/c-api</a>).
 * @param pyObjects A "," delimited list of expressions that would be (or result in a creation of) a PyObject.
 */
private static String generateCPythonInitializers(Reaction reaction, ReactorDecl decl, List<String> pyObjects, ErrorReporter errorReporter) {
    Set<Action> actionsAsTriggers = new LinkedHashSet<>();
    Reactor reactor = ASTUtils.toDefinition(decl);
    CodeBuilder code = new CodeBuilder();
    // TODO: handle triggers
    for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
        if (trigger instanceof VarRef) {
            VarRef triggerAsVarRef = (VarRef) trigger;
            code.pr(generateVariableToSendPythonReaction(triggerAsVarRef, actionsAsTriggers, decl, pyObjects));
        }
    }
    if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
        // NOTE: this does not include contained outputs.
        for (Input input : reactor.getInputs()) {
            PythonPortGenerator.generateInputVariablesToSendToPythonReaction(pyObjects, input, decl);
        }
    }
    // Next add non-triggering inputs.
    for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) {
        code.pr(generateVariableToSendPythonReaction(src, actionsAsTriggers, decl, pyObjects));
    }
    // Next, handle effects
    if (reaction.getEffects() != null) {
        for (VarRef effect : reaction.getEffects()) {
            if (effect.getVariable() instanceof Action) {
                // If it has already appeared as trigger, do not redefine it.
                if (!actionsAsTriggers.contains(effect.getVariable())) {
                    PythonPortGenerator.generateActionVariableToSendToPythonReaction(pyObjects, (Action) effect.getVariable(), decl);
                }
            } else {
                if (effect.getVariable() instanceof Output) {
                    PythonPortGenerator.generateOutputVariablesToSendToPythonReaction(pyObjects, (Output) effect.getVariable());
                } else if (effect.getVariable() instanceof Input) {
                    // It is the input of a contained reactor.
                    code.pr(PythonPortGenerator.generateVariablesForSendingToContainedReactors(pyObjects, effect.getContainer(), (Input) effect.getVariable()));
                } else {
                    errorReporter.reportError(reaction, "In generateReaction(): " + effect.getVariable().getName() + " is neither an input nor an output.");
                }
            }
        }
    }
    return code.toString();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) Input(org.lflang.lf.Input) Output(org.lflang.lf.Output) Reactor(org.lflang.lf.Reactor) TriggerRef(org.lflang.lf.TriggerRef) CodeBuilder(org.lflang.generator.CodeBuilder)

Example 9 with VarRef

use of org.lflang.lf.VarRef in project lingua-franca by lf-lang.

the class PythonReactionGenerator method generatePythonReactionParametersAndInitializations.

/**
 * Generate parameters and their respective initialization code for a reaction function
 * The initialization code is put at the beginning of the reaction before user code
 * @param parameters The parameters used for function definition
 * @param inits The initialization code for those paramters
 * @param decl Reactor declaration
 * @param reaction The reaction to be used to generate parameters for
 */
public static void generatePythonReactionParametersAndInitializations(List<String> parameters, CodeBuilder inits, ReactorDecl decl, Reaction reaction) {
    Reactor reactor = ASTUtils.toDefinition(decl);
    LinkedHashSet<String> generatedParams = new LinkedHashSet<>();
    // Handle triggers
    for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
        if (!(trigger instanceof VarRef)) {
            continue;
        }
        VarRef triggerAsVarRef = (VarRef) trigger;
        if (triggerAsVarRef.getVariable() instanceof Port) {
            if (triggerAsVarRef.getVariable() instanceof Input) {
                if (((Input) triggerAsVarRef.getVariable()).isMutable()) {
                    generatedParams.add("mutable_" + triggerAsVarRef.getVariable().getName() + "");
                    // Create a deep copy
                    if (ASTUtils.isMultiport((Input) triggerAsVarRef.getVariable())) {
                        inits.pr(triggerAsVarRef.getVariable().getName() + " = [Make() for i in range(len(mutable_" + triggerAsVarRef.getVariable().getName() + "))]");
                        inits.pr("for i in range(len(mutable_" + triggerAsVarRef.getVariable().getName() + ")):");
                        inits.pr("    " + triggerAsVarRef.getVariable().getName() + "[i].value = copy.deepcopy(mutable_" + triggerAsVarRef.getVariable().getName() + "[i].value)");
                    } else {
                        inits.pr(triggerAsVarRef.getVariable().getName() + " = Make()");
                        inits.pr(triggerAsVarRef.getVariable().getName() + ".value = copy.deepcopy(mutable_" + triggerAsVarRef.getVariable().getName() + ".value)");
                    }
                } else {
                    generatedParams.add(triggerAsVarRef.getVariable().getName());
                }
            } else {
                // Handle contained reactors' ports
                generatedParams.add(triggerAsVarRef.getContainer().getName() + "_" + triggerAsVarRef.getVariable().getName());
                inits.pr(PythonPortGenerator.generatePythonPortVariableInReaction(triggerAsVarRef));
            }
        } else if (triggerAsVarRef.getVariable() instanceof Action) {
            generatedParams.add(triggerAsVarRef.getVariable().getName());
        }
    }
    // Handle non-triggering inputs
    if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
        for (Input input : ASTUtils.convertToEmptyListIfNull(reactor.getInputs())) {
            generatedParams.add(input.getName());
            if (input.isMutable()) {
                // Create a deep copy
                inits.pr(input.getName() + " = copy.deepcopy(" + input.getName() + ")");
            }
        }
    }
    for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) {
        if (src.getVariable() instanceof Output) {
            // Output of a contained reactor
            generatedParams.add(src.getContainer().getName() + "_" + src.getVariable().getName());
            inits.pr(PythonPortGenerator.generatePythonPortVariableInReaction(src));
        } else {
            generatedParams.add(src.getVariable().getName());
            if (src.getVariable() instanceof Input) {
                if (((Input) src.getVariable()).isMutable()) {
                    // Create a deep copy
                    inits.pr(src.getVariable().getName() + " = copy.deepcopy(" + src.getVariable().getName() + ")");
                }
            }
        }
    }
    // Handle effects
    for (VarRef effect : ASTUtils.convertToEmptyListIfNull(reaction.getEffects())) {
        if (effect.getVariable() instanceof Input) {
            generatedParams.add(effect.getContainer().getName() + "_" + effect.getVariable().getName());
            inits.pr(PythonPortGenerator.generatePythonPortVariableInReaction(effect));
        } else {
            generatedParams.add(effect.getVariable().getName());
            if (effect.getVariable() instanceof Port) {
                if (ASTUtils.isMultiport((Port) effect.getVariable())) {
                // Handle multiports
                }
            }
        }
    }
    for (String s : generatedParams) {
        parameters.add(s);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) VarRef(org.lflang.lf.VarRef) Input(org.lflang.lf.Input) Action(org.lflang.lf.Action) Port(org.lflang.lf.Port) Output(org.lflang.lf.Output) Reactor(org.lflang.lf.Reactor) TriggerRef(org.lflang.lf.TriggerRef)

Example 10 with VarRef

use of org.lflang.lf.VarRef in project lingua-franca by lf-lang.

the class ReactorInstance method listPortInstances.

/**
 * Given a list of port references, as found on either side of a connection,
 * return a list of the port instance ranges referenced. These may be multiports,
 * and may be ports of a contained bank (a port representing ports of the bank
 * members) so the returned list includes ranges of banks and channels.
 *
 * If a given port reference has the form `interleaved(b.m)`, where `b` is
 * a bank and `m` is a multiport, then the corresponding range in the returned
 * list is marked interleaved.
 *
 * For example, if `b` and `m` have width 2, without the interleaved keyword,
 * the returned range represents the sequence `[b0.m0, b0.m1, b1.m0, b1.m1]`.
 * With the interleaved marking, the returned range represents the sequence
 * `[b0.m0, b1.m0, b0.m1, b1.m1]`. Both ranges will have width 4.
 *
 * @param references The variable references on one side of the connection.
 * @param connection The connection.
 */
private List<RuntimeRange<PortInstance>> listPortInstances(List<VarRef> references, Connection connection) {
    List<RuntimeRange<PortInstance>> result = new ArrayList<RuntimeRange<PortInstance>>();
    List<RuntimeRange<PortInstance>> tails = new LinkedList<RuntimeRange<PortInstance>>();
    int count = 0;
    for (VarRef portRef : references) {
        // Simple error checking first.
        if (!(portRef.getVariable() instanceof Port)) {
            reporter.reportError(portRef, "Not a port.");
            return result;
        }
        // First, figure out which reactor we are dealing with.
        // The reactor we want is the container of the port.
        // If the port reference has no container, then the reactor is this one.
        var reactor = this;
        if (portRef.getContainer() != null) {
            reactor = getChildReactorInstance(portRef.getContainer());
        }
        // Skip this portRef so that diagram synthesis can complete.
        if (reactor != null) {
            PortInstance portInstance = reactor.lookupPortInstance((Port) portRef.getVariable());
            Set<ReactorInstance> interleaved = new LinkedHashSet<ReactorInstance>();
            if (portRef.isInterleaved()) {
                // NOTE: Here, we are assuming that the interleaved()
                // keyword is only allowed on the multiports contained by
                // contained reactors.
                interleaved.add(portInstance.parent);
            }
            RuntimeRange<PortInstance> range = new RuntimeRange.Port(portInstance, interleaved);
            // in the hierarchy.
            if (count < references.size() - 1) {
                int portWidth = portInstance.width;
                int portParentWidth = portInstance.parent.width;
                int widthBound = portWidth * portParentWidth;
                // If either of these widths cannot be determined, assume infinite.
                if (portWidth < 0)
                    widthBound = Integer.MAX_VALUE;
                if (portParentWidth < 0)
                    widthBound = Integer.MAX_VALUE;
                if (widthBound < range.width) {
                    // Need to split the range.
                    tails.add(range.tail(widthBound));
                    range = range.head(widthBound);
                }
            }
            result.add(range);
        }
    }
    // Iterate over the tails.
    while (tails.size() > 0) {
        List<RuntimeRange<PortInstance>> moreTails = new LinkedList<RuntimeRange<PortInstance>>();
        count = 0;
        for (RuntimeRange<PortInstance> tail : tails) {
            if (count < tails.size() - 1) {
                int widthBound = tail.instance.width;
                if (tail._interleaved.contains(tail.instance.parent)) {
                    widthBound = tail.instance.parent.width;
                }
                // If the width cannot be determined, assume infinite.
                if (widthBound < 0)
                    widthBound = Integer.MAX_VALUE;
                if (widthBound < tail.width) {
                    // Need to split the range again
                    moreTails.add(tail.tail(widthBound));
                    tail = tail.head(widthBound);
                }
            }
            result.add(tail);
        }
        tails = moreTails;
    }
    return result;
}
Also used : VarRef(org.lflang.lf.VarRef) LinkedHashSet(java.util.LinkedHashSet) Port(org.lflang.lf.Port) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList)

Aggregations

VarRef (org.lflang.lf.VarRef)21 Reactor (org.lflang.lf.Reactor)16 Action (org.lflang.lf.Action)10 Instantiation (org.lflang.lf.Instantiation)9 Reaction (org.lflang.lf.Reaction)8 Input (org.lflang.lf.Input)7 Output (org.lflang.lf.Output)7 Port (org.lflang.lf.Port)7 ArrayList (java.util.ArrayList)6 LinkedHashSet (java.util.LinkedHashSet)6 TriggerRef (org.lflang.lf.TriggerRef)6 Variable (org.lflang.lf.Variable)6 Connection (org.lflang.lf.Connection)5 ImportedReactor (org.lflang.lf.ImportedReactor)5 LfFactory (org.lflang.lf.LfFactory)5 TimeValue (org.lflang.TimeValue)4 Delay (org.lflang.lf.Delay)4 LinkedList (java.util.LinkedList)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3