Search in sources :

Example 51 with Reactor

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

the class CReactionGenerator method generateInitializationForReaction.

/**
 * Generate necessary initialization code inside the body of the reaction that belongs to reactor decl.
 * @param body The body of the reaction. Used to check for the DISABLE_REACTION_INITIALIZATION_MARKER.
 * @param reaction The initialization code will be generated for this specific reaction
 * @param decl The reactor that has the reaction
 * @param reactionIndex The index of the reaction relative to other reactions in the reactor, starting from 0
 */
public static String generateInitializationForReaction(String body, Reaction reaction, ReactorDecl decl, int reactionIndex, CTypes types, ErrorReporter errorReporter, Instantiation mainDef, boolean isFederatedAndDecentralized, boolean requiresTypes) {
    Reactor reactor = ASTUtils.toDefinition(decl);
    // Construct the reactionInitialization code to go into
    // the body of the function before the verbatim code.
    CodeBuilder reactionInitialization = new CodeBuilder();
    CodeBuilder code = new CodeBuilder();
    // Define the "self" struct.
    String structType = CUtil.selfType(decl);
    // or anything else. No need to declare it.
    if (structType != null) {
        code.pr(String.join("\n", "#pragma GCC diagnostic push", "#pragma GCC diagnostic ignored \"-Wunused-variable\"", structType + "* self = (" + structType + "*)instance_args;"));
    }
    // to not generate it.
    if (body.startsWith(CGenerator.DISABLE_REACTION_INITIALIZATION_MARKER)) {
        code.pr("#pragma GCC diagnostic pop");
        return code.toString();
    }
    // A reaction may send to or receive from multiple ports of
    // a contained reactor. The variables for these ports need to
    // all be declared as fields of the same struct. Hence, we first
    // collect the fields to be defined in the structs and then
    // generate the structs.
    Map<Instantiation, CodeBuilder> fieldsForStructsForContainedReactors = new LinkedHashMap<>();
    // Actions may appear twice, first as a trigger, then with the outputs.
    // But we need to declare it only once. Collect in this data structure
    // the actions that are declared as triggered so that if they appear
    // again with the outputs, they are not defined a second time.
    // That second redefinition would trigger a compile error.
    Set<Action> actionsAsTriggers = new LinkedHashSet<>();
    // defined so that they can be used in the verbatim code.
    for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
        if (trigger instanceof VarRef) {
            VarRef triggerAsVarRef = (VarRef) trigger;
            if (triggerAsVarRef.getVariable() instanceof Port) {
                generatePortVariablesInReaction(reactionInitialization, fieldsForStructsForContainedReactors, triggerAsVarRef, decl, types);
            } else if (triggerAsVarRef.getVariable() instanceof Action) {
                reactionInitialization.pr(generateActionVariablesInReaction((Action) triggerAsVarRef.getVariable(), decl, types));
                actionsAsTriggers.add((Action) triggerAsVarRef.getVariable());
            }
        }
    }
    if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
        // NOTE: this does not include contained outputs.
        for (Input input : reactor.getInputs()) {
            reactionInitialization.pr(generateInputVariablesInReaction(input, decl, types));
        }
    }
    // Define argument for non-triggering inputs.
    for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) {
        if (src.getVariable() instanceof Port) {
            generatePortVariablesInReaction(reactionInitialization, fieldsForStructsForContainedReactors, src, decl, types);
        } else if (src.getVariable() instanceof Action) {
            // It's a bit odd to read but not be triggered by an action, but
            // OK, I guess we allow it.
            reactionInitialization.pr(generateActionVariablesInReaction((Action) src.getVariable(), decl, types));
            actionsAsTriggers.add((Action) src.getVariable());
        }
    }
    // value that may have been written to that output in an earlier reaction.
    if (reaction.getEffects() != null) {
        for (VarRef effect : reaction.getEffects()) {
            Variable variable = effect.getVariable();
            if (variable instanceof Action) {
                // If it has already appeared as trigger, do not redefine it.
                if (!actionsAsTriggers.contains(effect.getVariable())) {
                    reactionInitialization.pr(CGenerator.variableStructType(variable, decl) + "* " + variable.getName() + " = &self->_lf_" + variable.getName() + ";");
                }
            } else if (effect.getVariable() instanceof Mode) {
                // Mode change effect
                int idx = ASTUtils.allModes(reactor).indexOf((Mode) effect.getVariable());
                String name = effect.getVariable().getName();
                if (idx >= 0) {
                    reactionInitialization.pr("reactor_mode_t* " + name + " = &self->_lf__modes[" + idx + "];\n" + "char _lf_" + name + "_change_type = " + (ModeTransitionType.getModeTransitionType(effect) == ModeTransitionType.HISTORY ? 2 : 1) + ";");
                } else {
                    errorReporter.reportError(reaction, "In generateReaction(): " + name + " not a valid mode of this reactor.");
                }
            } else {
                if (variable instanceof Output) {
                    reactionInitialization.pr(generateOutputVariablesInReaction(effect, decl, errorReporter, requiresTypes));
                } else if (variable instanceof Input) {
                    // It is the input of a contained reactor.
                    generateVariablesForSendingToContainedReactors(reactionInitialization, fieldsForStructsForContainedReactors, effect.getContainer(), (Input) variable);
                } else {
                    errorReporter.reportError(reaction, "In generateReaction(): effect is neither an input nor an output.");
                }
            }
        }
    }
    // generate the structs used for communication to and from contained reactors.
    for (Instantiation containedReactor : fieldsForStructsForContainedReactors.keySet()) {
        String array = "";
        if (containedReactor.getWidthSpec() != null) {
            String containedReactorWidthVar = generateWidthVariable(containedReactor.getName());
            code.pr("int " + containedReactorWidthVar + " = self->_lf_" + containedReactorWidthVar + ";");
            // Windows does not support variables in arrays declared on the stack,
            // so we use the maximum size over all bank members.
            array = "[" + maxContainedReactorBankWidth(containedReactor, null, 0, mainDef) + "]";
        }
        code.pr(String.join("\n", "struct " + containedReactor.getName() + " {", "    " + fieldsForStructsForContainedReactors.get(containedReactor) + "", "} " + containedReactor.getName() + array + ";"));
    }
    // Next generate all the collected setup code.
    code.pr(reactionInitialization.toString());
    code.pr("#pragma GCC diagnostic pop");
    if (reaction.getStp() == null) {
        // Pass down the intended_tag to all input and output effects
        // downstream if the current reaction does not have a STP
        // handler.
        code.pr(generateIntendedTagInheritence(body, reaction, decl, reactionIndex, types, isFederatedAndDecentralized));
    }
    return code.toString();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) Variable(org.lflang.lf.Variable) CUtil.generateWidthVariable(org.lflang.generator.c.CUtil.generateWidthVariable) Port(org.lflang.lf.Port) Mode(org.lflang.lf.Mode) TriggerRef(org.lflang.lf.TriggerRef) CodeBuilder(org.lflang.generator.CodeBuilder) LinkedHashMap(java.util.LinkedHashMap) Input(org.lflang.lf.Input) Output(org.lflang.lf.Output) Reactor(org.lflang.lf.Reactor) Instantiation(org.lflang.lf.Instantiation)

Example 52 with Reactor

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

the class CUtil method deleteBinFiles.

/**
 * Remove files in the bin directory that may have been created.
 * Call this if a compilation occurs so that files from a previous
 * version do not accidentally get executed.
 * @param fileConfig
 */
public static void deleteBinFiles(FileConfig fileConfig) {
    String name = FileUtil.nameWithoutExtension(fileConfig.srcFile);
    String[] files = fileConfig.binPath.toFile().list();
    // FIXME: put this in ASTUtils?
    List<String> federateNames = new LinkedList<>();
    fileConfig.resource.getAllContents().forEachRemaining(node -> {
        if (node instanceof Reactor) {
            Reactor r = (Reactor) node;
            if (r.isFederated()) {
                r.getInstantiations().forEach(inst -> federateNames.add(inst.getName()));
            }
        }
    });
    for (String f : files) {
        // Delete RTI file, if any.
        if (f.equals(name) || f.equals(name + RTI_BIN_SUFFIX) || f.equals(name + RTI_DISTRIBUTION_SCRIPT_SUFFIX)) {
            // noinspection ResultOfMethodCallIgnored
            fileConfig.binPath.resolve(f).toFile().delete();
        }
        // Delete federate executable files, if any.
        for (String federateName : federateNames) {
            if (f.equals(name + "_" + federateName)) {
                // noinspection ResultOfMethodCallIgnored
                fileConfig.binPath.resolve(f).toFile().delete();
            }
        }
    }
}
Also used : Reactor(org.lflang.lf.Reactor) LinkedList(java.util.LinkedList)

Example 53 with Reactor

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

the class InstantiationGraph method buildGraph.

/**
 * Traverse the AST and build this precedence graph relating the
 * encountered instantiations. Also map each reactor to all
 * declarations associated with it and each reactor to the sites of
 * its instantiations.
 */
private void buildGraph(final Instantiation instantiation, final Set<Instantiation> visited) {
    final ReactorDecl decl = instantiation.getReactorClass();
    final Reactor reactor = ASTUtils.toDefinition(decl);
    if (reactor != null) {
        Reactor container = ASTUtils.getEnclosingReactor(instantiation);
        if (visited.add(instantiation)) {
            this.reactorToInstantiation.put(reactor, instantiation);
            this.reactorToDecl.put(reactor, decl);
            if (container != null) {
                this.addEdge(container, reactor);
            } else {
                this.addNode(reactor);
            }
            for (final Instantiation inst : reactor.getInstantiations()) {
                this.buildGraph(inst, visited);
            }
        }
    }
}
Also used : ReactorDecl(org.lflang.lf.ReactorDecl) Reactor(org.lflang.lf.Reactor) Instantiation(org.lflang.lf.Instantiation)

Example 54 with Reactor

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

the class LFScopeProviderImpl method getScopeForVarRef.

protected IScope getScopeForVarRef(VarRef variable, EReference reference) {
    if (reference == LfPackage.Literals.VAR_REF__VARIABLE) {
        // Resolve hierarchical reference
        Reactor reactor;
        Mode mode = null;
        if (variable.eContainer().eContainer() instanceof Reactor) {
            reactor = (Reactor) variable.eContainer().eContainer();
        } else if (variable.eContainer().eContainer() instanceof Mode) {
            mode = (Mode) variable.eContainer().eContainer();
            reactor = (Reactor) variable.eContainer().eContainer().eContainer();
        } else {
            return Scopes.scopeFor(emptyList());
        }
        RefType type = getRefType(variable);
        if (variable.getContainer() != null) {
            // Resolve hierarchical port reference
            var instanceName = nameProvider.getFullyQualifiedName(variable.getContainer());
            var instances = new ArrayList<Instantiation>(reactor.getInstantiations());
            if (mode != null) {
                instances.addAll(mode.getInstantiations());
            }
            if (instanceName != null) {
                for (var instance : instances) {
                    var defn = toDefinition(instance.getReactorClass());
                    if (defn != null && instance.getName().equals(instanceName.toString())) {
                        switch(type) {
                            case TRIGGER:
                            case SOURCE:
                            case CLEFT:
                                return Scopes.scopeFor(allOutputs(defn));
                            case EFFECT:
                            case DEADLINE:
                            case CRIGHT:
                                return Scopes.scopeFor(allInputs(defn));
                        }
                    }
                }
            }
            return Scopes.scopeFor(emptyList());
        } else {
            // Resolve local reference
            switch(type) {
                case TRIGGER:
                    {
                        var candidates = new ArrayList<EObject>();
                        if (mode != null) {
                            candidates.addAll(mode.getActions());
                            candidates.addAll(mode.getTimers());
                        }
                        candidates.addAll(allInputs(reactor));
                        candidates.addAll(allActions(reactor));
                        candidates.addAll(allTimers(reactor));
                        return Scopes.scopeFor(candidates);
                    }
                case SOURCE:
                    return super.getScope(variable, reference);
                case EFFECT:
                    {
                        var candidates = new ArrayList<EObject>();
                        if (mode != null) {
                            candidates.addAll(mode.getActions());
                            candidates.addAll(reactor.getModes());
                        }
                        candidates.addAll(allOutputs(reactor));
                        candidates.addAll(allActions(reactor));
                        return Scopes.scopeFor(candidates);
                    }
                case DEADLINE:
                case CLEFT:
                    return Scopes.scopeFor(allInputs(reactor));
                case CRIGHT:
                    return Scopes.scopeFor(allOutputs(reactor));
                default:
                    return Scopes.scopeFor(emptyList());
            }
        }
    } else {
        // Resolve instance
        return super.getScope(variable, reference);
    }
}
Also used : Mode(org.lflang.lf.Mode) EObject(org.eclipse.emf.ecore.EObject) ArrayList(java.util.ArrayList) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor)

Aggregations

Reactor (org.lflang.lf.Reactor)54 ImportedReactor (org.lflang.lf.ImportedReactor)19 VarRef (org.lflang.lf.VarRef)19 ArrayList (java.util.ArrayList)16 Action (org.lflang.lf.Action)15 Instantiation (org.lflang.lf.Instantiation)14 Reaction (org.lflang.lf.Reaction)13 EObject (org.eclipse.emf.ecore.EObject)12 LinkedHashSet (java.util.LinkedHashSet)11 ReactorInstance (org.lflang.generator.ReactorInstance)9 Connection (org.lflang.lf.Connection)9 Input (org.lflang.lf.Input)9 LfFactory (org.lflang.lf.LfFactory)9 Output (org.lflang.lf.Output)9 Variable (org.lflang.lf.Variable)9 HashSet (java.util.HashSet)8 List (java.util.List)8 PortInstance (org.lflang.generator.PortInstance)8 Model (org.lflang.lf.Model)7 Port (org.lflang.lf.Port)7