Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix minimum spacing of actions and reference to freed event #2128

Merged
merged 4 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ public static String generateInitializers(ReactorInstance instance) {
? CTypes.getInstance().getTargetTimeExpr(minSpacing)
: CGenerator.UNDEFINED_MIN_SPACING)
+ ";";
var lastTimeInitializer = triggerStructName + ".last_time = NEVER;";
code.addAll(
List.of(
"// Initializing action " + action.getFullName(),
offsetInitializer,
periodInitializer));
periodInitializer,
lastTimeInitializer));

var mode = action.getMode(false);
if (mode != null) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/org/lflang/generator/c/CGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1253,7 +1253,7 @@ private void generateInteractingContainedReactors(
constructorCode.pr(
String.join(
"\n",
portOnSelf + "_trigger.last = NULL;",
portOnSelf + "_trigger.last_time = NEVER;",
portOnSelf + "_trigger.number_of_reactions = " + triggered.size() + ";"));

// Set the physical_time_of_arrival
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ private static void createTriggerT(
var varName = variable.getName();
// variable is a port, a timer, or an action.
body.pr("trigger_t _lf__" + varName + ";");
constructorCode.pr("self->_lf__" + varName + ".last = NULL;");
constructorCode.pr("self->_lf__" + varName + ".last_time = NEVER;");
constructorCode.pr(
CExtensionUtils.surroundWithIfFederatedDecentralized(
"self->_lf__"
Expand Down Expand Up @@ -1097,7 +1097,7 @@ public static void generateBuiltinTriggeredReactionsArray(
constructorCode.pr(
String.join(
"\n",
"self->_lf__" + name + ".last = NULL;",
"self->_lf__" + name + ".last_time = NEVER;",
"self->_lf__" + name + ".reactions = &self->_lf__" + name + "_reactions[0];",
"self->_lf__" + name + ".number_of_reactions = " + reactions.size() + ";",
"self->_lf__" + name + ".is_timer = false;"));
Expand Down
45 changes: 45 additions & 0 deletions test/C/src/LastTimeDefer.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Test for https://github.com/lf-lang/reactor-c/issues/145
// This tests the defer policy, which is the default.
target C {
timeout: 1 s
}

main reactor {
timer t(0, 100 ms)
logical action a(1 ms, 300 ms): int
state c: int = 0
state c2: int = 0 // For expected values.
state last: time = 0

reaction(startup) {=
// Unfortunately, a time state variable cannot be initialized with NEVER.
// So we do that here.
self->last = NEVER;
=}

reaction(t) -> a {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Timer) Current: " PRINTF_TIME ", Scheduled: " PRINTF_TIME ", Count: %d",
now.time - start, now.time + MSEC(1) - start, self->c
);
lf_schedule_int(a, 0, self->c++);
=}

reaction(a) {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Action) Current: " PRINTF_TIME ", Microstep: %d, Count: %d",
now.time - start, now.microstep, a->value
);
// Check min_spacing.
if (now.time < self->last + MSEC(300)) {
lf_print_error_and_exit("Minimum spacing of 300ms was violated.");
}
// The value should be equal to the current state c before incrementing.
if (a->value != self->c2++) {
lf_print_error_and_exit("Expected value %d", self->c2 - 1);
}
self->last = now.time;
=}
}
44 changes: 44 additions & 0 deletions test/C/src/LastTimeDrop.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Test for https://github.com/lf-lang/reactor-c/issues/145
// This tests the drop policy.
target C {
timeout: 1 s
}

main reactor {
timer t(0, 100 ms)
logical action a(1 ms, 300 ms, "drop"): int
state c: int = 0
state last: time = 0

reaction(startup) {=
// Unfortunately, a time state variable cannot be initialized with NEVER.
// So we do that here.
self->last = NEVER;
=}

reaction(t) -> a {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Timer) Current: " PRINTF_TIME ", Scheduled: " PRINTF_TIME ", Count: %d",
now.time - start, now.time + MSEC(1) - start, self->c
);
lf_schedule_int(a, 0, self->c++);
=}

reaction(a) {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Action) Current: " PRINTF_TIME ", Microstep: %d, Count: %d",
now.time - start, now.microstep, a->value
);
// Check min_spacing.
if (now.time < self->last + MSEC(300)) {
lf_print_error_and_exit("Minimum spacing of 300ms was violated.");
}
// The value should be equal to the current state c before incrementing.
if (a->value != self->c - 1) {
lf_print_error_and_exit("Expected value %d", self->c - 1);
}
self->last = now.time;
=}
}
44 changes: 44 additions & 0 deletions test/C/src/LastTimeReplace.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Test for https://github.com/lf-lang/reactor-c/issues/145
// This tests the replace policy.
target C {
timeout: 1 s
}

main reactor {
timer t(0, 100 ms)
logical action a(1 ms, 300 ms, "replace"): int
state c: int = 0
state last: time = 0

reaction(startup) {=
// Unfortunately, a time state variable cannot be initialized with NEVER.
// So we do that here.
self->last = NEVER;
=}

reaction(t) -> a {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Timer) Current: " PRINTF_TIME ", Scheduled: " PRINTF_TIME ", Count: %d",
now.time - start, now.time + MSEC(1) - start, self->c
);
lf_schedule_int(a, 0, self->c++);
=}

reaction(a) {=
tag_t now = lf_tag();
instant_t start = lf_time_start();
lf_print("(Action) Current: " PRINTF_TIME ", Microstep: %d, Count: %d",
now.time - start, now.microstep, a->value
);
// Check min_spacing.
if (now.time < self->last + MSEC(300)) {
lf_print_error_and_exit("Minimum spacing of 300ms was violated.");
}
// The value should be equal to the current state c before incrementing.
if (a->value != self->c - 1) {
lf_print_error_and_exit("Expected value %d", self->c - 1);
}
self->last = now.time;
=}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ reactor Receiver(takeBreakAfter: number = 10, breakInterval: time = 550 msec) {
state receivedMessages: number = 0
state totalReceivedMessages: number = 0
state breaks: number = 0
timer t(0, 1 msec) // This will impact the performance
timer t(0, 10 msec) // This will impact the performance

// but forces the logical time to advance Comment this line for a more sensible log output.
reaction(inp) {=
Expand Down
Loading