Search in sources :

Example 1 with TimeValue

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

the class FedASTUtils method findMaxSTP.

/**
 * Find the maximum STP offset for the given 'port'.
 *
 * An STP offset predicate can be nested in contained reactors in
 * the federate.
 * @param port The port to generate the STP list for.
 * @param generator The GeneratorBase instance used to perform some target-specific actions
 * @param reactor The top-level reactor (not the federate reactor)
 * @return The maximum STP as a TimeValue
 */
private static TimeValue findMaxSTP(Variable port, FederateInstance instance, GeneratorBase generator, Reactor reactor) {
    // Find a list of STP offsets (if any exists)
    List<Value> STPList = new LinkedList<>();
    // First, check if there are any connections to contained reactors that
    // need to be handled
    List<Connection> connectionsWithPort = ASTUtils.allConnections(reactor).stream().filter(c -> c.getLeftPorts().stream().anyMatch((VarRef v) -> v.getVariable().equals(port))).collect(Collectors.toList());
    // Find the list of reactions that have the port as trigger or source
    // (could be a variable name)
    List<Reaction> reactionsWithPort = ASTUtils.allReactions(reactor).stream().filter(r -> {
        // Check the triggers of reaction r first
        return r.getTriggers().stream().anyMatch(t -> {
            if (t instanceof VarRef) {
                // Check if the variables match
                return ((VarRef) t).getVariable() == port;
            } else {
                // Not a network port (startup or shutdown)
                return false;
            }
        }) || // Then check the sources of reaction r
        r.getSources().stream().anyMatch(s -> s.getVariable() == port);
    }).collect(Collectors.toList());
    // Find a list of STP offsets (if any exists)
    if (generator.isFederatedAndDecentralized()) {
        for (Reaction r : safe(reactionsWithPort)) {
            if (!instance.contains(r)) {
                continue;
            }
            // If not, assume it is zero
            if (r.getStp() != null) {
                if (r.getStp().getValue().getParameter() != null) {
                    List<Instantiation> instantList = new ArrayList<>();
                    instantList.add(instance.instantiation);
                    STPList.addAll(ASTUtils.initialValue(r.getStp().getValue().getParameter(), instantList));
                } else {
                    STPList.add(r.getStp().getValue());
                }
            }
        }
        // Check the children for STPs as well
        for (Connection c : safe(connectionsWithPort)) {
            VarRef childPort = c.getRightPorts().get(0);
            Reactor childReactor = (Reactor) childPort.getVariable().eContainer();
            // Find the list of reactions that have the port as trigger or
            // source (could be a variable name)
            List<Reaction> childReactionsWithPort = ASTUtils.allReactions(childReactor).stream().filter(r -> r.getTriggers().stream().anyMatch(t -> {
                if (t instanceof VarRef) {
                    // Check if the variables match
                    return ((VarRef) t).getVariable() == childPort.getVariable();
                } else {
                    // Not a network port (startup or shutdown)
                    return false;
                }
            }) || r.getSources().stream().anyMatch(s -> s.getVariable() == childPort.getVariable())).collect(Collectors.toList());
            for (Reaction r : safe(childReactionsWithPort)) {
                if (!instance.contains(r)) {
                    continue;
                }
                // If not, assume it is zero
                if (r.getStp() != null) {
                    if (r.getStp().getValue() instanceof Parameter) {
                        List<Instantiation> instantList = new ArrayList<>();
                        instantList.add(childPort.getContainer());
                        STPList.addAll(ASTUtils.initialValue(r.getStp().getValue().getParameter(), instantList));
                    } else {
                        STPList.add(r.getStp().getValue());
                    }
                }
            }
        }
    }
    return STPList.stream().map(ASTUtils::getLiteralTimeValue).filter(Objects::nonNull).reduce(TimeValue.ZERO, TimeValue::max);
}
Also used : Variable(org.lflang.lf.Variable) SupportedSerializers(org.lflang.federated.serialization.SupportedSerializers) Delay(org.lflang.lf.Delay) LfFactory(org.lflang.lf.LfFactory) Action(org.lflang.lf.Action) ArrayList(java.util.ArrayList) InferredType(org.lflang.InferredType) Instantiation(org.lflang.lf.Instantiation) Reaction(org.lflang.lf.Reaction) LinkedList(java.util.LinkedList) TimeValue(org.lflang.TimeValue) Connection(org.lflang.lf.Connection) Type(org.lflang.lf.Type) GeneratorBase(org.lflang.generator.GeneratorBase) CoordinationType(org.lflang.TargetProperty.CoordinationType) EcoreUtil(org.eclipse.emf.ecore.util.EcoreUtil) PortInstance(org.lflang.generator.PortInstance) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Parameter(org.lflang.lf.Parameter) List(java.util.List) Value(org.lflang.lf.Value) Reactor(org.lflang.lf.Reactor) ActionOrigin(org.lflang.lf.ActionOrigin) Optional(java.util.Optional) VarRef(org.lflang.lf.VarRef) Collections(java.util.Collections) ASTUtils(org.lflang.ASTUtils) VarRef(org.lflang.lf.VarRef) ASTUtils(org.lflang.ASTUtils) Connection(org.lflang.lf.Connection) ArrayList(java.util.ArrayList) Reaction(org.lflang.lf.Reaction) LinkedList(java.util.LinkedList) TimeValue(org.lflang.TimeValue) Value(org.lflang.lf.Value) Parameter(org.lflang.lf.Parameter) Instantiation(org.lflang.lf.Instantiation) Reactor(org.lflang.lf.Reactor) TimeValue(org.lflang.TimeValue)

Example 2 with TimeValue

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

the class FedASTUtils method addNetworkInputControlReaction.

/**
 * Add a network control reaction for a given input port 'destination' to
 * destination's parent reactor. This reaction will block for
 * any valid logical time until it is known whether the trigger for the
 * action corresponding to the given port is present or absent.
 *
 * @note Used in federated execution
 *
 * @param source The output port of the source federate reactor.
 *  Added as a trigger to the network control reaction to preserve the
 *  overall dependency structure of the program across federates.
 * @param destination The input port of the destination federate reactor.
 * @param recevingPortID The ID of the receiving port
 * @param bankIndex The bank index of the receiving federate, or -1 if not in a bank.
 * @param instance The federate instance is used to keep track of all
 *  network input ports globally
 * @param generator The GeneratorBase instance used to perform some target-specific actions
 */
private static void addNetworkInputControlReaction(PortInstance source, PortInstance destination, int recevingPortID, int bankIndex, FederateInstance instance, GeneratorBase generator) {
    LfFactory factory = LfFactory.eINSTANCE;
    Reaction reaction = factory.createReaction();
    VarRef sourceRef = factory.createVarRef();
    VarRef destRef = factory.createVarRef();
    // If the sender or receiver is in a bank of reactors, then we want
    // these reactions to appear only in the federate whose bank ID matches.
    generator.setReactionBankIndex(reaction, bankIndex);
    // Create a new action that will be used to trigger the
    // input control reactions.
    Action newTriggerForControlReactionInput = factory.createAction();
    newTriggerForControlReactionInput.setOrigin(ActionOrigin.LOGICAL);
    // Set the container and variable according to the network port
    destRef.setContainer(destination.getParent().getDefinition());
    destRef.setVariable(destination.getDefinition());
    sourceRef.setContainer(source.getParent().getDefinition());
    sourceRef.setVariable(source.getDefinition());
    Reactor top = destination.getParent().getParent().reactorDefinition;
    newTriggerForControlReactionInput.setName(ASTUtils.getUniqueIdentifier(top, "inputControlReactionTrigger"));
    // Add the newly created Action to the action list of the federated reactor.
    top.getActions().add(newTriggerForControlReactionInput);
    // Create the trigger for the reaction
    VarRef newTriggerForControlReaction = factory.createVarRef();
    newTriggerForControlReaction.setVariable(newTriggerForControlReactionInput);
    // Add the appropriate triggers to the list of triggers of the reaction
    reaction.getTriggers().add(newTriggerForControlReaction);
    // Add the original output port of the source federate
    // as a trigger to keep the overall dependency structure.
    // This is useful when assigning levels.
    reaction.getTriggers().add(sourceRef);
    // Add this trigger to the list of disconnected network reaction triggers
    instance.remoteNetworkReactionTriggers.add(sourceRef);
    // Add the destination port as an effect of the reaction
    reaction.getEffects().add(destRef);
    // Generate code for the network input control reaction
    reaction.setCode(factory.createCode());
    TimeValue maxSTP = findMaxSTP(destination.getDefinition(), instance, generator, destination.getParent().reactorDefinition);
    reaction.getCode().setBody(generator.generateNetworkInputControlReactionBody(recevingPortID, maxSTP));
    generator.makeUnordered(reaction);
    // Insert the reaction
    top.getReactions().add(reaction);
    // Add the trigger for this reaction to the list of triggers, used to actually
    // trigger the reaction at the beginning of each logical time.
    instance.networkInputControlReactionsTriggers.add(newTriggerForControlReactionInput);
    // Add the network input control reaction to the federate instance's list
    // of network reactions
    instance.networkReactions.add(reaction);
}
Also used : VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) LfFactory(org.lflang.lf.LfFactory) Reaction(org.lflang.lf.Reaction) Reactor(org.lflang.lf.Reactor) TimeValue(org.lflang.TimeValue)

Example 3 with TimeValue

use of org.lflang.TimeValue 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 4 with TimeValue

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

the class CGeneratorExtension method getNetworkDelayLiteral.

/**
 * Given a connection 'delay' predicate, return a string that represents the
 * interval_t value of the additional delay that needs to be applied to the
 * outgoing message.
 *
 * The returned additional delay in absence of after on network connection
 * (i.e., if delay is passed as a null) is  NEVER. This has a special
 * meaning in C library functions that send network messages that carry
 * timestamps (@see send_timed_message and send_port_absent_to_federate
 * in lib/core/federate.c). In this case, the sender will send its current
 * tag as the timestamp of the outgoing message without adding a microstep delay.
 * If the user has assigned an after delay to the network connection (that
 * can be zero) either as a time value (e.g., 200 msec) or as a literal
 * (e.g., a parameter), that delay in nsec will be returned.
 *
 * @param delay
 * @param generator
 * @return
 */
public static String getNetworkDelayLiteral(Delay delay) {
    String additionalDelayString = "NEVER";
    if (delay != null) {
        Parameter p = delay.getParameter();
        TimeValue tv;
        if (delay.getParameter() != null) {
            // The parameter has to be parameter of the main reactor.
            // And that value has to be a Time.
            tv = ASTUtils.getDefaultAsTimeValue(p);
        } else {
            tv = ASTUtils.toTimeValue(delay.getTime());
        }
        additionalDelayString = Long.toString(tv.toNanoSeconds());
    }
    return additionalDelayString;
}
Also used : Parameter(org.lflang.lf.Parameter) TimeValue(org.lflang.TimeValue)

Aggregations

TimeValue (org.lflang.TimeValue)4 Action (org.lflang.lf.Action)3 PortInstance (org.lflang.generator.PortInstance)2 LfFactory (org.lflang.lf.LfFactory)2 Parameter (org.lflang.lf.Parameter)2 Reaction (org.lflang.lf.Reaction)2 Reactor (org.lflang.lf.Reactor)2 VarRef (org.lflang.lf.VarRef)2 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Objects (java.util.Objects)1 Optional (java.util.Optional)1 Collectors (java.util.stream.Collectors)1 EcoreUtil (org.eclipse.emf.ecore.util.EcoreUtil)1 ASTUtils (org.lflang.ASTUtils)1 InferredType (org.lflang.InferredType)1 CoordinationType (org.lflang.TargetProperty.CoordinationType)1 SupportedSerializers (org.lflang.federated.serialization.SupportedSerializers)1