Search in sources :

Example 6 with Output

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

the class FederateInstance method indexExcludedTopLevelReactions.

/**
 * Build an index of reactions at the top-level (in the
 * federatedReactor) that don't belong to this federate
 * instance. This index is put in the excludeReactions
 * class variable.
 *
 * @param federatedReactor The top-level federated reactor
 */
private void indexExcludedTopLevelReactions(Reactor federatedReactor) {
    boolean inFederate = false;
    if (excludeReactions != null) {
        throw new IllegalStateException("The index for excluded reactions at the top level is already built.");
    }
    excludeReactions = new LinkedHashSet<Reaction>();
    // Construct the set of excluded reactions for this federate.
    // If a reaction is a network reaction that belongs to this federate, we
    // don't need to perform this analysis.
    Iterable<Reaction> reactions = IterableExtensions.filter(ASTUtils.allReactions(federatedReactor), it -> {
        return !networkReactions.contains(it);
    });
    for (Reaction react : reactions) {
        // Create a collection of all the VarRefs (i.e., triggers, sources, and effects) in the react
        // signature that are ports that reference federates.
        // We then later check that all these VarRefs reference this federate. If not, we will add this
        // react to the list of reactions that have to be excluded (note that mixing VarRefs from
        // different federates is not allowed).
        List<VarRef> allVarRefsReferencingFederates = new ArrayList<VarRef>();
        // Add all the triggers that are outputs
        Stream<VarRef> triggersAsVarRef = react.getTriggers().stream().filter(it -> it instanceof VarRef).map(it -> (VarRef) it);
        allVarRefsReferencingFederates.addAll(triggersAsVarRef.filter(it -> it.getVariable() instanceof Output).collect(Collectors.toList()));
        // Add all the sources that are outputs
        allVarRefsReferencingFederates.addAll(react.getSources().stream().filter(it -> it.getVariable() instanceof Output).collect(Collectors.toList()));
        // Add all the effects that are inputs
        allVarRefsReferencingFederates.addAll(react.getEffects().stream().filter(it -> it.getVariable() instanceof Input).collect(Collectors.toList()));
        inFederate = containsAllVarRefs(allVarRefsReferencingFederates);
        if (!inFederate) {
            excludeReactions.add(react);
        }
    }
}
Also used : VarRef(org.lflang.lf.VarRef) Variable(org.lflang.lf.Variable) Delay(org.lflang.lf.Delay) ErrorReporter(org.lflang.ErrorReporter) Action(org.lflang.lf.Action) Input(org.lflang.lf.Input) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) Instantiation(org.lflang.lf.Instantiation) TriggerInstance(org.lflang.generator.TriggerInstance) Reaction(org.lflang.lf.Reaction) Objects(com.google.common.base.Objects) TimeValue(org.lflang.TimeValue) LinkedHashSet(java.util.LinkedHashSet) GeneratorBase(org.lflang.generator.GeneratorBase) Set(java.util.Set) PortInstance(org.lflang.generator.PortInstance) ReactionInstance(org.lflang.generator.ReactionInstance) Collectors(java.util.stream.Collectors) ActionInstance(org.lflang.generator.ActionInstance) ReactorInstance(org.lflang.generator.ReactorInstance) List(java.util.List) Stream(java.util.stream.Stream) IterableExtensions(org.eclipse.xtext.xbase.lib.IterableExtensions) Reactor(org.lflang.lf.Reactor) ActionOrigin(org.lflang.lf.ActionOrigin) VarRef(org.lflang.lf.VarRef) ASTUtils(org.lflang.ASTUtils) Output(org.lflang.lf.Output) Timer(org.lflang.lf.Timer) TriggerRef(org.lflang.lf.TriggerRef) Input(org.lflang.lf.Input) Output(org.lflang.lf.Output) ArrayList(java.util.ArrayList) Reaction(org.lflang.lf.Reaction)

Example 7 with Output

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

the class FederateInstance method findNearestPhysicalActionTrigger.

/**
 * Find the nearest (shortest) path to a physical action trigger from this
 * 'reaction' in terms of minimum delay.
 *
 * @param reaction The reaction to start with
 * @return The minimum delay found to the nearest physical action and
 *  TimeValue.MAX_VALUE otherwise
 */
public TimeValue findNearestPhysicalActionTrigger(ReactionInstance reaction) {
    TimeValue minDelay = TimeValue.MAX_VALUE;
    for (TriggerInstance<? extends Variable> trigger : reaction.triggers) {
        if (trigger.getDefinition() instanceof Action) {
            Action action = (Action) trigger.getDefinition();
            ActionInstance actionInstance = (ActionInstance) trigger;
            if (action.getOrigin() == ActionOrigin.PHYSICAL) {
                if (actionInstance.getMinDelay().isEarlierThan(minDelay)) {
                    minDelay = actionInstance.getMinDelay();
                }
            } else if (action.getOrigin() == ActionOrigin.LOGICAL) {
                // Follow it upstream inside the reactor
                for (ReactionInstance uReaction : actionInstance.getDependsOnReactions()) {
                    // Avoid a loop
                    if (!Objects.equal(uReaction, reaction)) {
                        TimeValue uMinDelay = actionInstance.getMinDelay().add(findNearestPhysicalActionTrigger(uReaction));
                        if (uMinDelay.isEarlierThan(minDelay)) {
                            minDelay = uMinDelay;
                        }
                    }
                }
            }
        } else if (trigger.getDefinition() instanceof Output) {
            // Outputs of contained reactions
            PortInstance outputInstance = (PortInstance) trigger;
            for (ReactionInstance uReaction : outputInstance.getDependsOnReactions()) {
                TimeValue uMinDelay = findNearestPhysicalActionTrigger(uReaction);
                if (uMinDelay.isEarlierThan(minDelay)) {
                    minDelay = uMinDelay;
                }
            }
        }
    }
    return minDelay;
}
Also used : Action(org.lflang.lf.Action) PortInstance(org.lflang.generator.PortInstance) ActionInstance(org.lflang.generator.ActionInstance) ReactionInstance(org.lflang.generator.ReactionInstance) Output(org.lflang.lf.Output) TimeValue(org.lflang.TimeValue)

Example 8 with Output

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

the class LFValidator method checkReaction.

@Check(CheckType.FAST)
public void checkReaction(Reaction reaction) {
    if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
        warning("Reaction has no trigger.", Literals.REACTION__TRIGGERS);
    }
    HashSet<Variable> triggers = new HashSet<>();
    // Make sure input triggers have no container and output sources do.
    for (TriggerRef trigger : reaction.getTriggers()) {
        if (trigger instanceof VarRef) {
            VarRef triggerVarRef = (VarRef) trigger;
            triggers.add(triggerVarRef.getVariable());
            if (triggerVarRef instanceof Input) {
                if (triggerVarRef.getContainer() != null) {
                    error(String.format("Cannot have an input of a contained reactor as a trigger: %s.%s", triggerVarRef.getContainer().getName(), triggerVarRef.getVariable().getName()), Literals.REACTION__TRIGGERS);
                }
            } else if (triggerVarRef.getVariable() instanceof Output) {
                if (triggerVarRef.getContainer() == null) {
                    error(String.format("Cannot have an output of this reactor as a trigger: %s", triggerVarRef.getVariable().getName()), Literals.REACTION__TRIGGERS);
                }
            }
        }
    }
    // Also check that a source is not already listed as a trigger.
    for (VarRef source : reaction.getSources()) {
        if (triggers.contains(source.getVariable())) {
            error(String.format("Source is already listed as a trigger: %s", source.getVariable().getName()), Literals.REACTION__SOURCES);
        }
        if (source.getVariable() instanceof Input) {
            if (source.getContainer() != null) {
                error(String.format("Cannot have an input of a contained reactor as a source: %s.%s", source.getContainer().getName(), source.getVariable().getName()), Literals.REACTION__SOURCES);
            }
        } else if (source.getVariable() instanceof Output) {
            if (source.getContainer() == null) {
                error(String.format("Cannot have an output of this reactor as a source: %s", source.getVariable().getName()), Literals.REACTION__SOURCES);
            }
        }
    }
    // Make sure output effects have no container and input effects do.
    for (VarRef effect : reaction.getEffects()) {
        if (effect.getVariable() instanceof Input) {
            if (effect.getContainer() == null) {
                error(String.format("Cannot have an input of this reactor as an effect: %s", effect.getVariable().getName()), Literals.REACTION__EFFECTS);
            }
        } else if (effect.getVariable() instanceof Output) {
            if (effect.getContainer() != null) {
                error(String.format("Cannot have an output of a contained reactor as an effect: %s.%s", effect.getContainer().getName(), effect.getVariable().getName()), Literals.REACTION__EFFECTS);
            }
        }
    }
    // // Report error if this reaction is part of a cycle.
    Set<NamedInstance<?>> cycles = this.info.topologyCycles();
    Reactor reactor = ASTUtils.getEnclosingReactor(reaction);
    boolean reactionInCycle = false;
    for (NamedInstance<?> it : cycles) {
        if (it.getDefinition().equals(reaction)) {
            reactionInCycle = true;
        }
    }
    if (reactionInCycle) {
        // Report involved triggers.
        List<CharSequence> trigs = new ArrayList<>();
        for (TriggerRef t : reaction.getTriggers()) {
            if (!(t instanceof VarRef)) {
                continue;
            }
            VarRef tVarRef = (VarRef) t;
            boolean triggerExistsInCycle = false;
            for (NamedInstance<?> c : cycles) {
                if (c.getDefinition().equals(tVarRef.getVariable())) {
                    triggerExistsInCycle = true;
                    break;
                }
            }
            if (triggerExistsInCycle) {
                trigs.add(toText(tVarRef));
            }
        }
        if (trigs.size() > 0) {
            error(String.format("Reaction triggers involved in cyclic dependency in reactor %s: %s.", reactor.getName(), String.join(", ", trigs)), Literals.REACTION__TRIGGERS);
        }
        // Report involved sources.
        List<CharSequence> sources = new ArrayList<>();
        for (VarRef t : reaction.getSources()) {
            boolean sourceExistInCycle = false;
            for (NamedInstance<?> c : cycles) {
                if (c.getDefinition().equals(t.getVariable())) {
                    sourceExistInCycle = true;
                    break;
                }
            }
            if (sourceExistInCycle) {
                sources.add(toText(t));
            }
        }
        if (sources.size() > 0) {
            error(String.format("Reaction sources involved in cyclic dependency in reactor %s: %s.", reactor.getName(), String.join(", ", sources)), Literals.REACTION__SOURCES);
        }
        // Report involved effects.
        List<CharSequence> effects = new ArrayList<>();
        for (VarRef t : reaction.getEffects()) {
            boolean effectExistInCycle = false;
            for (NamedInstance<?> c : cycles) {
                if (c.getDefinition().equals(t.getVariable())) {
                    effectExistInCycle = true;
                    break;
                }
            }
            if (effectExistInCycle) {
                effects.add(toText(t));
            }
        }
        if (effects.size() > 0) {
            error(String.format("Reaction effects involved in cyclic dependency in reactor %s: %s.", reactor.getName(), String.join(", ", effects)), Literals.REACTION__EFFECTS);
        }
        if (trigs.size() + sources.size() == 0) {
            error(String.format("Cyclic dependency due to preceding reaction. Consider reordering reactions within reactor %s to avoid causality loop.", reactor.getName()), reaction.eContainer(), Literals.REACTOR__REACTIONS, reactor.getReactions().indexOf(reaction));
        } else if (effects.size() == 0) {
            error(String.format("Cyclic dependency due to succeeding reaction. Consider reordering reactions within reactor %s to avoid causality loop.", reactor.getName()), reaction.eContainer(), Literals.REACTOR__REACTIONS, reactor.getReactions().indexOf(reaction));
        }
    // Not reporting reactions that are part of cycle _only_ due to reaction ordering.
    // Moving them won't help solve the problem.
    }
// FIXME: improve error message.
}
Also used : VarRef(org.lflang.lf.VarRef) TypedVariable(org.lflang.lf.TypedVariable) Variable(org.lflang.lf.Variable) ArrayList(java.util.ArrayList) TriggerRef(org.lflang.lf.TriggerRef) NamedInstance(org.lflang.generator.NamedInstance) Input(org.lflang.lf.Input) Output(org.lflang.lf.Output) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Check(org.eclipse.xtext.validation.Check)

Example 9 with Output

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

the class CReactionGenerator method generateIntendedTagInheritence.

/**
 * Generate code that passes existing intended tag to all output ports
 * and actions. This intended tag is the minimum intended tag of the
 * triggering inputs of the reaction.
 *
 * @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 generateIntendedTagInheritence(String body, Reaction reaction, ReactorDecl decl, int reactionIndex, CTypes types, boolean isFederatedAndDecentralized) {
    // Construct the intended_tag inheritance code to go into
    // the body of the function.
    CodeBuilder intendedTagInheritenceCode = new CodeBuilder();
    // Check if the coordination mode is decentralized and if the reaction has any effects to inherit the STP violation
    if (isFederatedAndDecentralized && !(reaction.getEffects() == null || reaction.getEffects().isEmpty())) {
        intendedTagInheritenceCode.pr(String.join("\n", "#pragma GCC diagnostic push", "#pragma GCC diagnostic ignored \"-Wunused-variable\"", "if (self->_lf__reaction_" + reactionIndex + ".is_STP_violated == true) {"));
        intendedTagInheritenceCode.indent();
        intendedTagInheritenceCode.pr(String.join("\n", "// The operations inside this if clause (if any exists) are expensive ", "// and must only be done if the reaction has unhandled STP violation.", "// Otherwise, all intended_tag values are (NEVER, 0) by default.", "", "// Inherited intended tag. This will take the minimum", "// intended_tag of all input triggers", types.getTargetTagType() + " inherited_min_intended_tag = (" + types.getTargetTagType() + ") { .time = FOREVER, .microstep = UINT_MAX };"));
        intendedTagInheritenceCode.pr("// Find the minimum intended tag");
        // value of intended_tag to choose the minimum.
        for (TriggerRef inputTrigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
            if (inputTrigger instanceof VarRef) {
                VarRef inputTriggerAsVarRef = (VarRef) inputTrigger;
                Variable variable = inputTriggerAsVarRef.getVariable();
                String variableName = inputTriggerAsVarRef.getVariable().getName();
                if (variable instanceof Output) {
                    // Output from a contained reactor
                    String containerName = inputTriggerAsVarRef.getContainer().getName();
                    Output outputPort = (Output) variable;
                    if (ASTUtils.isMultiport(outputPort)) {
                        intendedTagInheritenceCode.pr(String.join("\n", "for (int i=0; i < " + containerName + "." + generateWidthVariable(variableName) + "; i++) {", "    if (compare_tags(" + containerName + "." + variableName + "[i]->intended_tag,", "                        inherited_min_intended_tag) < 0) {", "        inherited_min_intended_tag = " + containerName + "." + variableName + "[i]->intended_tag;", "    }", "}"));
                    } else
                        intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + containerName + "." + variableName + "->intended_tag,", "                    inherited_min_intended_tag) < 0) {", "    inherited_min_intended_tag = " + containerName + "." + variableName + "->intended_tag;", "}"));
                } else if (variable instanceof Port) {
                    // Input port
                    Port inputPort = (Port) variable;
                    if (ASTUtils.isMultiport(inputPort)) {
                        intendedTagInheritenceCode.pr(String.join("\n", "for (int i=0; i < " + generateWidthVariable(variableName) + "; i++) {", "    if (compare_tags(" + variableName + "[i]->intended_tag, inherited_min_intended_tag) < 0) {", "        inherited_min_intended_tag = " + variableName + "[i]->intended_tag;", "    }", "}"));
                    } else {
                        intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + variableName + "->intended_tag, inherited_min_intended_tag) < 0) {", "    inherited_min_intended_tag = " + variableName + "->intended_tag;", "}"));
                    }
                } else if (variable instanceof Action) {
                    intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + variableName + "->trigger->intended_tag, inherited_min_intended_tag) < 0) {", "    inherited_min_intended_tag = " + variableName + "->trigger->intended_tag;", "}"));
                }
            }
        }
        if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
            // NOTE: this does not include contained outputs.
            for (Input input : ((Reactor) reaction.eContainer()).getInputs()) {
                intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + input.getName() + "->intended_tag, inherited_min_intended_tag) > 0) {", "    inherited_min_intended_tag = " + input.getName() + "->intended_tag;", "}"));
            }
        }
        // Once the minimum intended tag has been found,
        // it will be passed down to the port effects
        // of the reaction. Note that the intended tag
        // will not pass on to actions downstream.
        // Last reaction that sets the intended tag for the effect
        // will be seen.
        intendedTagInheritenceCode.pr(String.join("\n", "// All effects inherit the minimum intended tag of input triggers", "if (inherited_min_intended_tag.time != NEVER) {"));
        intendedTagInheritenceCode.indent();
        for (VarRef effect : ASTUtils.convertToEmptyListIfNull(reaction.getEffects())) {
            Variable effectVar = effect.getVariable();
            Instantiation effContainer = effect.getContainer();
            if (effectVar instanceof Input) {
                if (ASTUtils.isMultiport((Port) effectVar)) {
                    intendedTagInheritenceCode.pr(String.join("\n", "for(int i=0; i < " + effContainer.getName() + "." + generateWidthVariable(effectVar.getName()) + "; i++) {", "    " + effContainer.getName() + "." + effectVar.getName() + "[i]->intended_tag = inherited_min_intended_tag;", "}"));
                } else {
                    if (effContainer.getWidthSpec() != null) {
                        // Contained reactor is a bank.
                        intendedTagInheritenceCode.pr(String.join("\n", "for (int bankIndex = 0; bankIndex < self->_lf_" + generateWidthVariable(effContainer.getName()) + "; bankIndex++) {", "    " + effContainer.getName() + "[bankIndex]." + effectVar.getName() + " = &(self->_lf_" + effContainer.getName() + "[bankIndex]." + effectVar.getName() + ");", "}"));
                    } else {
                        // Input to a contained reaction
                        intendedTagInheritenceCode.pr(String.join("\n", "// Don't reset the intended tag of the output port if it has already been set.", effContainer.getName() + "." + effectVar.getName() + "->intended_tag = inherited_min_intended_tag;"));
                    }
                }
            }
        }
        intendedTagInheritenceCode.unindent();
        intendedTagInheritenceCode.pr("}");
        intendedTagInheritenceCode.unindent();
        intendedTagInheritenceCode.pr("#pragma GCC diagnostic pop");
        intendedTagInheritenceCode.pr("}");
    }
    return intendedTagInheritenceCode.toString();
}
Also used : VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) Input(org.lflang.lf.Input) Variable(org.lflang.lf.Variable) CUtil.generateWidthVariable(org.lflang.generator.c.CUtil.generateWidthVariable) Output(org.lflang.lf.Output) Port(org.lflang.lf.Port) TriggerRef(org.lflang.lf.TriggerRef) Reactor(org.lflang.lf.Reactor) Instantiation(org.lflang.lf.Instantiation) CodeBuilder(org.lflang.generator.CodeBuilder)

Example 10 with Output

use of org.lflang.lf.Output 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)

Aggregations

Output (org.lflang.lf.Output)10 Input (org.lflang.lf.Input)8 Action (org.lflang.lf.Action)7 Reactor (org.lflang.lf.Reactor)7 VarRef (org.lflang.lf.VarRef)7 TriggerRef (org.lflang.lf.TriggerRef)6 LinkedHashSet (java.util.LinkedHashSet)5 CodeBuilder (org.lflang.generator.CodeBuilder)4 Variable (org.lflang.lf.Variable)4 Instantiation (org.lflang.lf.Instantiation)3 Port (org.lflang.lf.Port)3 ArrayList (java.util.ArrayList)2 LinkedHashMap (java.util.LinkedHashMap)2 TimeValue (org.lflang.TimeValue)2 ActionInstance (org.lflang.generator.ActionInstance)2 PortInstance (org.lflang.generator.PortInstance)2 ReactionInstance (org.lflang.generator.ReactionInstance)2 CUtil.generateWidthVariable (org.lflang.generator.c.CUtil.generateWidthVariable)2 ImportedReactor (org.lflang.lf.ImportedReactor)2 Reaction (org.lflang.lf.Reaction)2