diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 6cf3770575..514b775f91 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -227,13 +227,7 @@ public static String generateInitializationForReaction(String body, // 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(); } @@ -310,152 +304,6 @@ public static int maxContainedReactorBankWidth( return result; } - /** - * 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"); - // Go through every trigger of the reaction and check the - // value of intended_tag to choose the minimum. - for (TriggerRef inputTrigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) { - if (inputTrigger instanceof VarRef inputTriggerAsVarRef) { - Variable variable = inputTriggerAsVarRef.getVariable(); - String variableName = inputTriggerAsVarRef.getVariable().getName(); - if (variable instanceof Output outputPort) { - // Output from a contained reactor - String containerName = inputTriggerAsVarRef.getContainer().getName(); - if (ASTUtils.isMultiport(outputPort)) { - intendedTagInheritenceCode.pr(String.join("\n", - "for (int i=0; i < "+containerName+"."+generateWidthVariable(variableName)+"; i++) {", - " if (lf_tag_compare("+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 (lf_tag_compare("+containerName+"."+variableName+"->intended_tag,", - " inherited_min_intended_tag) < 0) {", - " inherited_min_intended_tag = "+containerName+"."+variableName+"->intended_tag;", - "}" - )); - } else if (variable instanceof Port inputPort) { - // Input port - if (ASTUtils.isMultiport(inputPort)) { - intendedTagInheritenceCode.pr(String.join("\n", - "for (int i=0; i < "+generateWidthVariable(variableName)+"; i++) {", - " if (lf_tag_compare("+variableName+"[i]->intended_tag, inherited_min_intended_tag) < 0) {", - " inherited_min_intended_tag = "+variableName+"[i]->intended_tag;", - " }", - "}" - )); - } else { - intendedTagInheritenceCode.pr(String.join("\n", - "if (lf_tag_compare("+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 (lf_tag_compare("+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) { - // No triggers are given, which means the reaction would react to any input. - // We need to check the intended tag for every input. - // NOTE: this does not include contained outputs. - for (Input input : ((Reactor) reaction.eContainer()).getInputs()) { - intendedTagInheritenceCode.pr(String.join("\n", - "if (lf_tag_compare("+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(); - } - /** * Generate code for the body of a reaction that takes an input and * schedules an action with the value of that input. diff --git a/test/C/src/federated/DistributedCountDecentralizedLateDownstream.lf b/test/C/src/federated/DistributedCountDecentralizedLateDownstream.lf deleted file mode 100644 index c987e0d4ff..0000000000 --- a/test/C/src/federated/DistributedCountDecentralizedLateDownstream.lf +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Test a form of a distributed deterministic system - * where a federate that receives timestamped messages has a timer in addition to the messages - * as triggers. Therefore, careful coordination of the advancement of time using Ptides is needed. - * In addition, this test shows that the STP violation is passed down the hierarchy until it is handled. - * - * An STP violation occurs if when a message with intended tag g1 arrives - * on a port p after the receiving federate has progressed far enough that - * it cannot process an event with tag g1 on the port p. - * This test has a fast timer (10 usec period) in the receiving federate - * so that the receiving federate is continually advancing its current tag, - * and hence an STP violation is more likely to occur. - * Furthermore, this test sets the STP threshold to 0, which makes the - * violation extremely likely to occur. It could still not occur, however, - * if the message arrives between ticks of the 10 usec timer. - * - * @author Edward A. Lee - * @author Soroush Bateni - */ -target C { - timeout: 1900 msec, // 9 msec headroom for the last (probably tardy) message to arrive. - coordination: decentralized -}; - -import Count from "../lib/Count.lf"; - -reactor ImportantActuator { - input in:int; - state success:int(0); // Count messages that arrive without STP violation. - state success_stp_violation:int(0); - timer t(0, 10 usec); // Force a timer to be invoke periodically - // to ensure logical time will advance in the - // absence of incoming messages. - state c:int(0); - reaction(in) {= - tag_t current_tag = lf_tag(); - lf_print("ImportantActuator: At tag (%lld, %u) received %d. Intended tag is (%lld, %u).", - lf_time_logical_elapsed(), - lf_tag().microstep, - in->value, - in->intended_tag.time - lf_time_start(), - in->intended_tag.microstep); - if (lf_tag_compare((tag_t){.time=current_tag.time - lf_time_start(), .microstep=current_tag.microstep}, - (tag_t){.time=SEC(1) * self->c, .microstep=0}) == 0) { - self->success++; // Message was on-time - } else { - lf_print_error_and_exit("Normal reaction was invoked, but current tag doesn't match expected tag."); - } - self->c++; - =} STP (0) {= - tag_t current_tag = lf_tag(); - lf_print("ImportantActuator: At tag (%lld, %u), message has violated the STP offset by (%lld, %u).", - current_tag.time - start_time, current_tag.microstep, - current_tag.time - in->intended_tag.time, - current_tag.microstep - in->intended_tag.microstep); - self->success_stp_violation++; - self->c++; - =} - reaction(t) {= - // Do nothing. - =} - - reaction(shutdown) {= - if ((self->success + self->success_stp_violation) != 2) { - lf_print_error_and_exit("Failed to detect STP violation in messages."); - } else { - lf_print("Successfully detected STP violations (%d violations, %d on-time).", self->success_stp_violation, self->success); - } - =} -} - -reactor Print { - input in:int; - reaction(in) {= - tag_t current_tag = lf_tag(); - lf_print("Print reactor: at tag (%lld, %u) received %d. Intended tag is (%lld, %u).", - current_tag.time - lf_time_start(), - current_tag.microstep, - in->value, - in->intended_tag.time - lf_time_start(), - in->intended_tag.microstep); - =} - -} - -reactor Receiver { - input in:int; - timer t(0, 10 msec); // Force a timer to be invoke periodically - // to ensure logical time will advance in the - // absence of incoming messages. - state c:int(0); - p = new Print(); - a = new ImportantActuator(); - reaction(in) -> p.in, a.in {= - lf_set(p.in, in->value + 1); - lf_set(a.in, in->value + 1); - =} - - reaction(t) {= - // Do nothing. - =} -} - -federated reactor { - c = new Count(period = 1 sec); - r = new Receiver(); - c.out -> r.in; // Indicating a 'logical' connection. -}