diff --git a/docs/assets/code/c/src/DecentralizedTimerAfter.lf b/docs/assets/code/c/src/DecentralizedTimerAfter.lf index 20180a31f..488e2cb51 100644 --- a/docs/assets/code/c/src/DecentralizedTimerAfter.lf +++ b/docs/assets/code/c/src/DecentralizedTimerAfter.lf @@ -17,6 +17,7 @@ reactor PrintTimer extends Print { federated reactor { c = new Count() + @maxwait(0) p = new PrintTimer() c.out -> p.in after 10 ms } diff --git a/docs/assets/code/c/src/DecentralizedZeroDelayLoop.lf b/docs/assets/code/c/src/DecentralizedZeroDelayLoop.lf index 0d08e10d2..2e40e7d83 100644 --- a/docs/assets/code/c/src/DecentralizedZeroDelayLoop.lf +++ b/docs/assets/code/c/src/DecentralizedZeroDelayLoop.lf @@ -34,6 +34,7 @@ reactor Double { } federated reactor { + @maxwait(0) c = new CountPrint() p = new Double() c.out -> p.in diff --git a/docs/assets/code/c/src/DecentralizedZeroDelayLoopWithChecker.lf b/docs/assets/code/c/src/DecentralizedZeroDelayLoopWithChecker.lf index f4273acbe..0b1d90c79 100644 --- a/docs/assets/code/c/src/DecentralizedZeroDelayLoopWithChecker.lf +++ b/docs/assets/code/c/src/DecentralizedZeroDelayLoopWithChecker.lf @@ -20,6 +20,7 @@ reactor CountPrintWithChecker extends CountPrint { } federated reactor { + @maxwait(0) c = new CountPrintWithChecker() p = new Double() c.out -> p.in diff --git a/docs/assets/code/py/src/DecentralizedTimerAfter.lf b/docs/assets/code/py/src/DecentralizedTimerAfter.lf index 0d5b15ca0..be8e0e136 100644 --- a/docs/assets/code/py/src/DecentralizedTimerAfter.lf +++ b/docs/assets/code/py/src/DecentralizedTimerAfter.lf @@ -18,6 +18,7 @@ reactor PrintTimer extends Print { federated reactor { c = new Count() + @maxwait(0) p = new PrintTimer() c.out -> p.inp after 10 ms } diff --git a/docs/assets/code/py/src/DecentralizedZeroDelayLoop.lf b/docs/assets/code/py/src/DecentralizedZeroDelayLoop.lf index 23b4180b8..ab99cbe72 100644 --- a/docs/assets/code/py/src/DecentralizedZeroDelayLoop.lf +++ b/docs/assets/code/py/src/DecentralizedZeroDelayLoop.lf @@ -33,6 +33,7 @@ reactor Double { } federated reactor { + @maxwait(0) c = new CountPrint() p = new Double() c.out -> p.inp diff --git a/docs/assets/code/py/src/DecentralizedZeroDelayLoopWithChecker.lf b/docs/assets/code/py/src/DecentralizedZeroDelayLoopWithChecker.lf index 1a9ad2dd1..fef7082e3 100644 --- a/docs/assets/code/py/src/DecentralizedZeroDelayLoopWithChecker.lf +++ b/docs/assets/code/py/src/DecentralizedZeroDelayLoopWithChecker.lf @@ -15,6 +15,7 @@ reactor CountPrintWithChecker extends CountPrint { } federated reactor { + @maxwait(0) c = new CountPrintWithChecker() p = new Double() c.out -> p.inp diff --git a/docs/assets/code/uc/.gitignore b/docs/assets/code/uc/.gitignore new file mode 100644 index 000000000..55f4cfeb1 --- /dev/null +++ b/docs/assets/code/uc/.gitignore @@ -0,0 +1,3 @@ +bin +src-gen +include diff --git a/docs/assets/code/uc/src/Alignment.lf b/docs/assets/code/uc/src/Alignment.lf new file mode 100644 index 000000000..75ccebcf9 --- /dev/null +++ b/docs/assets/code/uc/src/Alignment.lf @@ -0,0 +1,22 @@ +target uC + +@platform("Native") +@timeout(3 sec) +main reactor Alignment { + state s: int = 0 + timer t1(100 msec, 100 msec) + timer t2(200 msec, 200 msec) + timer t4(400 msec, 400 msec) + + reaction(t1) {= + self->s += 1; + =} + + reaction(t2) {= + self->s -= 2; + =} + + reaction(t4) {= + printf("s = %d\n", self->s); + =} +} diff --git a/docs/assets/code/uc/src/Asynchronous.lf b/docs/assets/code/uc/src/Asynchronous.lf new file mode 100644 index 000000000..8c405554a --- /dev/null +++ b/docs/assets/code/uc/src/Asynchronous.lf @@ -0,0 +1,30 @@ +target uC + +@platform("Native") +@keepalive(true) +main reactor { + preamble {= + #include + // Schedule an event roughly every 200 msec. + + void* external(void* ptr) { + Action* physical_action = (Action*)ptr; + while (true) { + usleep(200000); + lf_schedule(physical_action, SEC(0), 0); + } + } + =} + + state thread: pthread_t + physical action a(100 msec): int + + reaction(startup) -> a {= + pthread_create(&self->thread, NULL, &external, a); + =} + + reaction(a) {= + interval_t elapsed_time = env->get_elapsed_logical_time(env); + printf("Action triggered at logical time %lld nsec after start.\n", elapsed_time); + =} +} diff --git a/docs/assets/code/uc/src/BankIndex.lf b/docs/assets/code/uc/src/BankIndex.lf new file mode 100644 index 000000000..1dc3c57b0 --- /dev/null +++ b/docs/assets/code/uc/src/BankIndex.lf @@ -0,0 +1,11 @@ +target uC; +reactor A(bank_index:int = 0, value:int = 0) { + reaction (startup) {= + printf("bank_index: %d, value: %d\n", self->bank_index, self->value); + =} +} +main reactor( + table: int[] = {4, 3, 2, 1} +) { + a = new[4] A(value = {= self->table[bank_index] =}); +} diff --git a/docs/assets/code/uc/src/CheckDeadline.lf b/docs/assets/code/uc/src/CheckDeadline.lf new file mode 100644 index 000000000..b11ba0b5a --- /dev/null +++ b/docs/assets/code/uc/src/CheckDeadline.lf @@ -0,0 +1,22 @@ +target uC; + +reactor Count { + output out:int; + reaction(startup) -> out {= + int count = 0; + while (!lf_check_deadline(self, true)) { + count++; + } + lf_set(out, count); + =} deadline (3 msec) {= + printf("Stopped counting.\n"); + =} +} + +@platform("Native") +main reactor { + c = new Count(); + reaction(c.out) {= + printf("Counted to %d\n", c.out->value); + =} +} diff --git a/docs/assets/code/uc/src/ChildBank.lf b/docs/assets/code/uc/src/ChildBank.lf new file mode 100644 index 000000000..10b191e2a --- /dev/null +++ b/docs/assets/code/uc/src/ChildBank.lf @@ -0,0 +1,17 @@ +target uC; +reactor Child ( + bank_index:int = 0 +) { + reaction(startup) {= + printf("My bank index: %d.\n", self->bank_index); + =} +} +reactor Parent ( + bank_index:int = 0 +) { + c = new[2] Child(); +} +@platform("Native") +main reactor { + p = new[2] Parent(); +} diff --git a/docs/assets/code/uc/src/ChildParentBank.lf b/docs/assets/code/uc/src/ChildParentBank.lf new file mode 100644 index 000000000..30728ce7c --- /dev/null +++ b/docs/assets/code/uc/src/ChildParentBank.lf @@ -0,0 +1,19 @@ +target uC + +reactor Child(bank_index: int = 0, parent_bank_index: int = 0) { + reaction(startup) {= + printf( + "My bank index: %d. My parent's bank index: %d.\n", + self->bank_index, self->parent_bank_index + ); + =} +} + +reactor Parent(bank_index: int = 0) { + c = new[2] Child(parent_bank_index=bank_index) +} + +@platform("Native") +main reactor { + p = new[2] Parent() +} diff --git a/docs/assets/code/uc/src/ChildParentBank2.lf b/docs/assets/code/uc/src/ChildParentBank2.lf new file mode 100644 index 000000000..8e16c8d6b --- /dev/null +++ b/docs/assets/code/uc/src/ChildParentBank2.lf @@ -0,0 +1,24 @@ +target uC + +reactor Child(bank_index: int = 0, parent_bank_index: int = 0) { + output out: int + + reaction(startup) -> out {= + lf_set(out, self->parent_bank_index * 2 + self->bank_index); + =} +} + +reactor Parent(bank_index: int = 0) { + c = new[2] Child(parent_bank_index=bank_index) + + reaction(c.out) {= + for (int i=0; i < c_width; i++) { + printf("Received %d from child %d.\n", c[i].out->value, i); + } + =} +} + +@platform("Native") +main reactor { + p = new[2] Parent() +} diff --git a/docs/assets/code/uc/src/Contained.lf b/docs/assets/code/uc/src/Contained.lf new file mode 100644 index 000000000..ce022914c --- /dev/null +++ b/docs/assets/code/uc/src/Contained.lf @@ -0,0 +1,15 @@ +target uC + +import Overwriting from "Overwriting.lf" + +@platform("Native") +main reactor { + s = new Overwriting() + + reaction(s.y) {= + if (s.y->value != 0 && s.y->value != 1) { + printf("ERROR: Outputs should only be 0 or 1!\n"); + exit(1); + } + =} +} diff --git a/docs/assets/code/uc/src/Count.lf b/docs/assets/code/uc/src/Count.lf new file mode 100644 index 000000000..91b9ce03e --- /dev/null +++ b/docs/assets/code/uc/src/Count.lf @@ -0,0 +1,11 @@ +target uC + +reactor Count { + state count: int = 0 + output y: int + timer t(0, 100 msec) + + reaction(t) -> y {= + lf_set(y, self->count++); + =} +} diff --git a/docs/assets/code/uc/src/Cycle.lf b/docs/assets/code/uc/src/Cycle.lf new file mode 100644 index 000000000..c324357d6 --- /dev/null +++ b/docs/assets/code/uc/src/Cycle.lf @@ -0,0 +1,25 @@ +target uC; +reactor A { + input x:int; + output y:int; + reaction(x) -> y {= + // ... something here ... + =} +} +reactor B { + input x:int; + output y:int; + reaction(x) {= + // ... something here ... + =} + reaction(startup) -> y {= + // ... something here ... + =} +} +@platform("Native") +main reactor { + a = new A(); + b = new B(); + a.y -> b.x; + b.y -> a.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/CycleReordered.lf b/docs/assets/code/uc/src/CycleReordered.lf new file mode 100644 index 000000000..e7168a2c7 --- /dev/null +++ b/docs/assets/code/uc/src/CycleReordered.lf @@ -0,0 +1,24 @@ +target uC; +reactor A { + input x:int; + output y:int; + reaction(x) -> y {= + // ... something here ... + =} +} +reactor B { + input x:int; + output y:int; + reaction(startup) -> y {= + // ... something here ... + =} + reaction(x) {= + // ... something here ... + =} +} +main reactor { + a = new A(); + b = new B(); + a.y -> b.x; + b.y -> a.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/CycleWithDelay.lf b/docs/assets/code/uc/src/CycleWithDelay.lf new file mode 100644 index 000000000..10004e688 --- /dev/null +++ b/docs/assets/code/uc/src/CycleWithDelay.lf @@ -0,0 +1,25 @@ +target uC; +reactor A { + input x:int; + output y:int; + reaction(x) -> y {= + // ... something here ... + =} +} +reactor B { + input x:int; + output y:int; + reaction(x) {= + // ... something here ... + =} + reaction(startup) -> y {= + // ... something here ... + =} +} +@platform("Native") +main reactor { + a = new A(); + b = new B(); + a.y -> b.x after 0; + b.y -> a.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/Deadline.lf b/docs/assets/code/uc/src/Deadline.lf new file mode 100644 index 000000000..d81009960 --- /dev/null +++ b/docs/assets/code/uc/src/Deadline.lf @@ -0,0 +1,13 @@ +target uC; + +@platform("Native") +reactor Deadline { + input x:int; + output d:int; // Produced if the deadline is violated. + reaction(x) -> d {= + printf("Normal reaction.\n"); + =} deadline(10 msec) {= + printf("Deadline violation detected.\n"); + lf_set(d, x->value); + =} +} diff --git a/docs/assets/code/uc/src/DeadlineTest.lf b/docs/assets/code/uc/src/DeadlineTest.lf new file mode 100644 index 000000000..f694bc4ce --- /dev/null +++ b/docs/assets/code/uc/src/DeadlineTest.lf @@ -0,0 +1,28 @@ +target uC + +import Deadline from "Deadline.lf" + +preamble {= + // For lf_sleep(), a reactor-c function. + #include "reactor-uc/reactor-c.h" +=} + +@platform("Native") +main reactor { + logical action a + d = new Deadline() + + reaction(startup) -> d.x, a {= + lf_set(d.x, 0); + lf_schedule(a, 0); + =} + + reaction(a) -> d.x {= + lf_set(d.x, 0); + lf_sleep(MSEC(20)); + =} + + reaction(d.d) {= + printf("Deadline reactor produced an output.\n"); + =} +} diff --git a/docs/assets/code/uc/src/Decentralized.lf b/docs/assets/code/uc/src/Decentralized.lf new file mode 100644 index 000000000..6259132e8 --- /dev/null +++ b/docs/assets/code/uc/src/Decentralized.lf @@ -0,0 +1,12 @@ +target uC + +import Count, Print from "Federated.lf" + +@timeout(5sec) +@platform("native") +federated reactor { + c = new Count(); + @maxwait(10 ms) + p = new Print(); + c.out -> p.in; +} diff --git a/docs/assets/code/uc/src/DecentralizedFeeback.lf b/docs/assets/code/uc/src/DecentralizedFeeback.lf new file mode 100644 index 000000000..34fe1a10f --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedFeeback.lf @@ -0,0 +1,48 @@ +target uC + +reactor CountPrint { + input in: int; + output out: int; + state c: int = 0; + timer t(0, 1 sec); + + reaction(t) -> out {= + lf_set(out, self->c++); + =} + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("CountPrint Received: %d at time %lld\n", in->value, elapsed); + =} tardy {= + printf("Warning: CountPrint tardy message received!\n"); + =} +} + +reactor PrintCount { + input in: int; + output out: int; + timer t(0, 999 msec); + state c: int = 0; + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("PrintCount Received: %d at time %lld\n", in->value, elapsed); + =} tardy {= + printf("Warning: PrintCount tardy message received!\n"); + =} + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + @maxwait(10 ms) + c = new CountPrint(); + @maxwait(10 ms) + p = new PrintCount(); + c.out -> p.in; + p.out -> c.in; +} diff --git a/docs/assets/code/uc/src/DecentralizedFeebackSTA.lf b/docs/assets/code/uc/src/DecentralizedFeebackSTA.lf new file mode 100644 index 000000000..797264466 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedFeebackSTA.lf @@ -0,0 +1,44 @@ +target uC + +reactor CountPrint { + input in: int; + output out: int; + state c: int = 0; + timer t(0, 1 sec); + + reaction(t) -> out {= + lf_set(out, self->c++); + =} + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("CountPrint Received: %d at time %lld\n", in->value, elapsed); + =} +} + +reactor PrintCount { + input in: int; + output out: int; + timer t(0, 1 sec); + state c: int = 0; + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("PrintCount Received: %d at time %lld\n", in->value, elapsed); + =} + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + @maxwait(10 ms) + c = new CountPrint(); + @maxwait(10 ms) + p = new PrintCount(); + c.out -> p.in; + p.out -> c.in; +} diff --git a/docs/assets/code/uc/src/DecentralizedFeebackSplit.lf b/docs/assets/code/uc/src/DecentralizedFeebackSplit.lf new file mode 100644 index 000000000..248aafc62 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedFeebackSplit.lf @@ -0,0 +1,51 @@ +target uC + +reactor Count { + output out: int; + state c: int = 0; + timer t(0, 500 msec); + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +reactor Print { + input in: int; + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Print Received: %d at time %lld\n", in->value, elapsed); + =} tardy {= + printf("Warning: Late message received!\n"); + =} +} + +reactor PrintCount { + input in: int; + output out: int; + timer t(0, 999 msec); + state c: int = 0; + + reaction(in) {= + printf("PrintCount Received: %d\n", in->value); + =} tardy {= + printf("Warning: Late message received!\n"); + =} + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count(); + @maxwait(10 ms) + pr = new Print(); + @maxwait(10 ms) + p = new PrintCount(); + c.out -> p.in; + p.out -> pr.in; +} diff --git a/docs/assets/code/uc/src/DecentralizedFeebackWithAfter.lf b/docs/assets/code/uc/src/DecentralizedFeebackWithAfter.lf new file mode 100644 index 000000000..2b8c2960a --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedFeebackWithAfter.lf @@ -0,0 +1,47 @@ +target uC + +reactor CountPrint { + input in: int; + output out: int; + state c: int = 0; + timer t(0, 500 msec); + + reaction(t) -> out {= + lf_set(out, self->c++); + =} + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("CountPrint Received: %d at time %lld\n", in->value, elapsed); + =} tardy {= + printf("Warning: CountPrint late message received!\n"); + =} +} + +reactor PrintCount { + input in: int; + output out: int; + timer t(0, 999 msec); + state c: int = 0; + + reaction(in) {= + printf("PrintCount Received: %d\n", in->value); + =} tardy {= + printf("Warning: PrintCount late message received!\n"); + =} + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + @maxwait(10 msec) + c = new CountPrint(); + @maxwait(10 msec) + p = new PrintCount(); + c.out -> p.in after 10 msec; + p.out -> c.in after 10 msec; +} diff --git a/docs/assets/code/uc/src/DecentralizedTimer.lf b/docs/assets/code/uc/src/DecentralizedTimer.lf new file mode 100644 index 000000000..e326549b4 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedTimer.lf @@ -0,0 +1,21 @@ +target uC + +import Count, Print from "Federated.lf" + +reactor PrintTimer extends Print { + timer t(0, 1 sec) + + reaction(t) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Timer ticked at %lld\n", elapsed); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + @maxwait(10 ms) + p = new PrintTimer() + c.out -> p.in +} diff --git a/docs/assets/code/uc/src/DecentralizedTimerAfter.lf b/docs/assets/code/uc/src/DecentralizedTimerAfter.lf new file mode 100644 index 000000000..b37dd0dd7 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedTimerAfter.lf @@ -0,0 +1,21 @@ +target uC + +import Count, Print from "Federated.lf" + +reactor PrintTimer extends Print { + timer t(10 ms, 1 sec) + + reaction(t) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Timer ticked at %lld\n", elapsed); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + @maxwait(0) + p = new PrintTimer() + c.out -> p.in after 10 ms +} diff --git a/docs/assets/code/uc/src/DecentralizedTimerHandler.lf b/docs/assets/code/uc/src/DecentralizedTimerHandler.lf new file mode 100644 index 000000000..8b647d6cd --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedTimerHandler.lf @@ -0,0 +1,30 @@ +target uC + +import Count from "Federated.lf" + +reactor PrintTimer { + timer t(0, 1 sec) + input in: int + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Received: %d at %lld\n", in->value, elapsed); + =} tardy {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Warning: Violation handler invoked at %lld\n", elapsed); + =} + + reaction(t) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Timer ticked at %lld\n", elapsed); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + @maxwait(10 s) + p = new PrintTimer() + c.out -> p.in +} diff --git a/docs/assets/code/uc/src/DecentralizedTimerSTA.lf b/docs/assets/code/uc/src/DecentralizedTimerSTA.lf new file mode 100644 index 000000000..e326549b4 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedTimerSTA.lf @@ -0,0 +1,21 @@ +target uC + +import Count, Print from "Federated.lf" + +reactor PrintTimer extends Print { + timer t(0, 1 sec) + + reaction(t) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Timer ticked at %lld\n", elapsed); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + @maxwait(10 ms) + p = new PrintTimer() + c.out -> p.in +} diff --git a/docs/assets/code/uc/src/DecentralizedTimerSTPDeadline.lf b/docs/assets/code/uc/src/DecentralizedTimerSTPDeadline.lf new file mode 100644 index 000000000..2a7579f78 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedTimerSTPDeadline.lf @@ -0,0 +1,24 @@ +target uC + +import Count, Print from "Federated.lf" + +reactor PrintTimer extends Print { + timer t(0, 1 sec) + + reaction(t) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Timer ticked at %lld\n", elapsed); + =} deadline(10 msec) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Deadline violation at %lld\n", elapsed); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + @maxwait(10 ms) + p = new PrintTimer() + c.out -> p.in +} diff --git a/docs/assets/code/uc/src/DecentralizedTimerSTPHandler.lf b/docs/assets/code/uc/src/DecentralizedTimerSTPHandler.lf new file mode 100644 index 000000000..995a47a7d --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedTimerSTPHandler.lf @@ -0,0 +1,30 @@ +target uC + +import Count from "Federated.lf" + +reactor PrintTimer { + timer t(0, 1 sec) + input in: int + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Received: %d at %lld\n", in->value, elapsed); + =} tardy {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Warning: STP violation handler invoked at %lld\n", elapsed); + =} + + reaction(t) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("Timer ticked at %lld\n", elapsed); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + @maxwait(10 ms) + p = new PrintTimer() + c.out -> p.in +} diff --git a/docs/assets/code/uc/src/DecentralizedZeroDelayLoop.lf b/docs/assets/code/uc/src/DecentralizedZeroDelayLoop.lf new file mode 100644 index 000000000..739030581 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedZeroDelayLoop.lf @@ -0,0 +1,38 @@ +target uC + +reactor CountPrint { + input in: int + output out: int + state c: int = 0 + timer t(0, 100 ms) + + reaction(t) -> out {= + lf_set(out, self->c++); + =} + + reaction(in) {= + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("CountPrint Received: %d at time %lld\n", in->value, elapsed); + =} tardy {= + printf("Warning: CountPrint message is tardy!\n"); + =} +} + +reactor Double { + input in: int + output out: int + + reaction(in) -> out {= + lf_set(out, in->value * 2); + =} +} + +@platform("native") +@timeout(3sec) +federated reactor { + @maxwait(forever) + c = new CountPrint() + p = new Double() + c.out -> p.in + p.out -> c.in +} diff --git a/docs/assets/code/uc/src/DecentralizedZeroDelayLoopWithChecker.lf b/docs/assets/code/uc/src/DecentralizedZeroDelayLoopWithChecker.lf new file mode 100644 index 000000000..eb005be60 --- /dev/null +++ b/docs/assets/code/uc/src/DecentralizedZeroDelayLoopWithChecker.lf @@ -0,0 +1,25 @@ +target uC + +import CountPrint, Double from "DecentralizedZeroDelayLoop.lf" + +reactor CountPrintWithChecker extends CountPrint { + + reaction(t, in) {= + if (!lf_is_present(in)) { + instant_t elapsed = env->get_elapsed_logical_time(env); + printf("CountPrint Failed to Receive response at time %lld\n", elapsed); + } + =} tardy {= + printf("CountPrint Received tardy input: %d\n", in->value); + =} +} + +@platform("native") +@timeout(3sec) +federated reactor { + c = new CountPrintWithChecker() + p = new Double() + c.out -> p.in + @absent_after(20 ms) + p.out -> c.in +} diff --git a/docs/assets/code/uc/src/Destination.lf b/docs/assets/code/uc/src/Destination.lf new file mode 100644 index 000000000..926d02705 --- /dev/null +++ b/docs/assets/code/uc/src/Destination.lf @@ -0,0 +1,17 @@ +target uC + +reactor Destination { + input x: int + input y: int + + reaction(x, y) {= + int sum = 0; + if (lf_is_present(x)) { + sum += x->value; + } + if (lf_is_present(y)) { + sum += y->value; + } + printf("Received %d.\n", sum); + =} +} diff --git a/docs/assets/code/uc/src/Double.lf b/docs/assets/code/uc/src/Double.lf new file mode 100644 index 000000000..576ac4b59 --- /dev/null +++ b/docs/assets/code/uc/src/Double.lf @@ -0,0 +1,10 @@ +target uC + +reactor Double { + input x: int + output y: int + + reaction(x) -> y {= + lf_set(y, x->value * 2); + =} +} diff --git a/docs/assets/code/uc/src/Extends.lf b/docs/assets/code/uc/src/Extends.lf new file mode 100644 index 000000000..86af9afbb --- /dev/null +++ b/docs/assets/code/uc/src/Extends.lf @@ -0,0 +1,14 @@ +target uC +reactor A { + input a:int; + output out:int; + reaction(a) -> out {= + lf_set(out, a->value); + =} +} +reactor B extends A { + input b:int; + reaction(a, b) -> out {= + lf_set(out, a->value + b->value); + =} +} diff --git a/docs/assets/code/uc/src/Federated.lf b/docs/assets/code/uc/src/Federated.lf new file mode 100644 index 000000000..aaa15dd78 --- /dev/null +++ b/docs/assets/code/uc/src/Federated.lf @@ -0,0 +1,28 @@ +target uC + +reactor Count { + output out: int + state c: int = 0 + timer t(0, 1 sec) + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +reactor Print { + input in: int + + reaction(in) {= + instant_t current_tag = env->get_logical_time(env); + printf("Received: %d at %lld\n", in->value, current_tag); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + c = new Count() + p = new Print() + c.out -> p.in +} diff --git a/docs/assets/code/uc/src/FederatedFeeback.lf b/docs/assets/code/uc/src/FederatedFeeback.lf new file mode 100644 index 000000000..b3bd81853 --- /dev/null +++ b/docs/assets/code/uc/src/FederatedFeeback.lf @@ -0,0 +1,47 @@ +target uC + +reactor CountPrint { + input in:int; + output out:int; + + state c: int = 0; + timer t(0, 500 msec); + + reaction(t) -> out {= + lf_set(out, self->c++); + =} + + reaction(in) {= + instant_t current_time = env->get_logical_time(env); + + printf("CountPrint Received: %d at time %lld\n", in->value, current_time); + =} +} + +reactor PrintCount { + input in:int; + output out:int; + timer t(0, 1 sec); + state c:int = 0; + + reaction(in) {= + instant_t current_time = env->get_logical_time(env); + + printf("PrintCount Received: %d at time %lld\n", in->value, current_time); + =} + + reaction(t) -> out {= + lf_set(out, self->c++); + =} +} + +@platform("native") +@timeout(5sec) +federated reactor { + @maxwait(10 ms) + c = new CountPrint(); + @maxwait(10 ms) + p = new PrintCount(); + c.out -> p.in after 10ms; + p.out -> c.in after 10ms; +} diff --git a/docs/assets/code/uc/src/GenericDelay.lf b/docs/assets/code/uc/src/GenericDelay.lf new file mode 100644 index 000000000..9317d7ef8 --- /dev/null +++ b/docs/assets/code/uc/src/GenericDelay.lf @@ -0,0 +1,28 @@ +target uC + +reactor Delay(delay: time = 0) { + input in: T + output out: T + logical action a(delay): T + + reaction(a) -> out {= + lf_set(out, a->value); + =} + + reaction(in) -> a {= + lf_schedule_copy(a, self->delay, &in->value, 1); + =} +} + +@platform("Native") +main reactor { + d = new Delay(delay = 100 ms) + + reaction(startup) -> d.in {= + lf_set(d.in, 42); + =} + + reaction(d.out) {= + printf("Received %d at time %lld.\n", d.out->value, env->get_elapsed_logical_time(env)); + =} +} diff --git a/docs/assets/code/uc/src/GenericString.lf b/docs/assets/code/uc/src/GenericString.lf new file mode 100644 index 000000000..6749fccee --- /dev/null +++ b/docs/assets/code/uc/src/GenericString.lf @@ -0,0 +1,15 @@ +target uC + +import Delay from "GenericDelay.lf" + +main reactor { + d = new Delay(delay = 100 ms) + + reaction(startup) -> d.in {= + lf_set(d.in, "foo"); + =} + + reaction(d.out) {= + printf("Received %s at time %lld.\n", d.out->value, lf_time_logical_elapsed()); + =} +} diff --git a/docs/assets/code/uc/src/HelloWorld.lf b/docs/assets/code/uc/src/HelloWorld.lf new file mode 100644 index 000000000..ab6fbbd1a --- /dev/null +++ b/docs/assets/code/uc/src/HelloWorld.lf @@ -0,0 +1,8 @@ +target uC + +@platform("Native") +main reactor { + reaction(startup) {= + printf("Hello World.\n"); + =} +} diff --git a/docs/assets/code/uc/src/Hierarchy.lf b/docs/assets/code/uc/src/Hierarchy.lf new file mode 100644 index 000000000..90615b415 --- /dev/null +++ b/docs/assets/code/uc/src/Hierarchy.lf @@ -0,0 +1,20 @@ +target uC + +import Count from "Count.lf" +import Scale from "Scale.lf" +import TestCount from "TestCount.lf" + +reactor Container(stride: int = 2) { + output y: int + c = new Count() + s = new Scale(factor=stride) + c.y -> s.x + s.y -> y +} + +@platform("Native") +main reactor Hierarchy { + c = new Container(stride=4) + t = new TestCount(stride=4, num_inputs=11) + c.y -> t.x +} diff --git a/docs/assets/code/uc/src/Interleaved.lf b/docs/assets/code/uc/src/Interleaved.lf new file mode 100644 index 000000000..bcae843c3 --- /dev/null +++ b/docs/assets/code/uc/src/Interleaved.lf @@ -0,0 +1,27 @@ +target uC + +reactor Node(num_nodes: size_t = 4, bank_index: int = 0) { + input[num_nodes] in: int + output[num_nodes] out: int + + reaction(startup) -> out {= + lf_set(out[1], 42); + printf("Bank index %d sent 42 on channel 1.\n", self->bank_index); + =} + + reaction(in) {= + for (int i = 0; i < in_width; i++) { + if (lf_is_present(in[i])) { + printf("Bank index %d received %d on channel %d.\n", + self->bank_index, in[i]->value, i + ); + } + } + =} +} + +@platform("Native") +main reactor(num_nodes: size_t = 4) { + nodes = new[num_nodes] Node(num_nodes=num_nodes) + nodes.out -> interleaved(nodes.in) +} diff --git a/docs/assets/code/uc/src/MainReactor.lf b/docs/assets/code/uc/src/MainReactor.lf new file mode 100644 index 000000000..4a6844bcf --- /dev/null +++ b/docs/assets/code/uc/src/MainReactor.lf @@ -0,0 +1,34 @@ +target uC +reactor ReactorA { + output output_port: int + @label("timer (offset, period)") + timer t(0, 100 ms) + @label("reaction A1") + reaction(t) -> output_port {= + =} +} +reactor ReactorB { + input input_port: int + output output_port: int + @label("reaction B1") + reaction(input_port) -> output_port {= + =} +} +reactor ReactorC { + input input_port1: int + input input_port2: int + @label("reaction C1") + reaction(input_port1) {= + =} + @label("reaction C2") + reaction(input_port2) {= + =} +} +main reactor { + a = new ReactorA() + b = new ReactorB() + c = new ReactorC() + a.output_port -> c.input_port2 after 200 ms + a.output_port -> b.input_port after 100 ms + b.output_port -> c.input_port1 after 100 ms +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/Methods.lf b/docs/assets/code/uc/src/Methods.lf new file mode 100644 index 000000000..be4deaa6e --- /dev/null +++ b/docs/assets/code/uc/src/Methods.lf @@ -0,0 +1,19 @@ +target uC + +main reactor Methods { + state foo: int = 2 + + method getFoo(): int {= + return self->foo; + =} + + method add(x: int) {= + self->foo += x; + =} + + reaction(startup) {= + lf_print("Foo is initialized to %d", getFoo()); + add(40); + lf_print("2 + 40 = %d", getFoo()); + =} +} diff --git a/docs/assets/code/uc/src/Microsteps.lf b/docs/assets/code/uc/src/Microsteps.lf new file mode 100644 index 000000000..b21d1e8b1 --- /dev/null +++ b/docs/assets/code/uc/src/Microsteps.lf @@ -0,0 +1,17 @@ +target uC + +@platform("Native") +main reactor { + state count: int = 1 + logical action a + + reaction(startup, a) -> a {= + tag_t tag = env->scheduler->current_tag(env->scheduler); + printf("%d. Logical time is %lld. Microstep is %d.\n", + self->count, tag.time, tag.microstep + ); + if (self->count++ < 5) { + lf_schedule(a, 0); + } + =} +} diff --git a/docs/assets/code/uc/src/Multiport.lf b/docs/assets/code/uc/src/Multiport.lf new file mode 100644 index 000000000..0ae97e911 --- /dev/null +++ b/docs/assets/code/uc/src/Multiport.lf @@ -0,0 +1,25 @@ +target uC; +reactor Source { + output[4] out:int; + reaction(startup) -> out {= + for(int i = 0; i < out_width; i++) { + lf_set(out[i], i); + } + =} +} +reactor Destination { + input[4] in:int; + reaction(in) {= + int sum = 0; + for (int i = 0; i < in_width; i++) { + if (lf_is_present(in[i])) sum += in[i]->value; + } + printf("Sum of received: %d.\n", sum); + =} +} +@platform("Native") +main reactor { + a = new Source(); + b = new Destination(); + a.out -> b.in; +} diff --git a/docs/assets/code/uc/src/MultiportSource.lf b/docs/assets/code/uc/src/MultiportSource.lf new file mode 100644 index 000000000..c39314ab8 --- /dev/null +++ b/docs/assets/code/uc/src/MultiportSource.lf @@ -0,0 +1,12 @@ +target uC + +reactor MultiportSource(bank_index: int = 0) { + timer t(0, 200 msec) + output out: int + state s: int = 0 + + reaction(t) -> out {= + lf_set(out, self->s); + self->s += self->bank_index; + =} +} diff --git a/docs/assets/code/uc/src/MultiportToBank.lf b/docs/assets/code/uc/src/MultiportToBank.lf new file mode 100644 index 000000000..928c8f3f1 --- /dev/null +++ b/docs/assets/code/uc/src/MultiportToBank.lf @@ -0,0 +1,26 @@ +target uC + +reactor Source { + output[3] out: int + + reaction(startup) -> out {= + for(int i = 0; i < out_width; i++) { + lf_set(out[i], i); + } + =} +} + +reactor Destination(bank_index: int = 0) { + input in: int + + reaction(in) {= + printf("Destination %d received %d.\n", self->bank_index, in->value); + =} +} + +@platform("Native") +main reactor MultiportToBank { + a = new Source() + b = new[3] Destination() + a.out -> b.in +} diff --git a/docs/assets/code/uc/src/Overwriting.lf b/docs/assets/code/uc/src/Overwriting.lf new file mode 100644 index 000000000..8e4b65f07 --- /dev/null +++ b/docs/assets/code/uc/src/Overwriting.lf @@ -0,0 +1,18 @@ +target uC + +reactor Overwriting { + output y: int + state s: int = 0 + timer t1(100 msec, 100 msec) + timer t2(200 msec, 200 msec) + + reaction(t1) -> y {= + self->s += 1; + lf_set(y, self->s); + =} + + reaction(t2) -> y {= + self->s -= 2; + lf_set(y, self->s); + =} +} diff --git a/docs/assets/code/uc/src/Physical.lf b/docs/assets/code/uc/src/Physical.lf new file mode 100644 index 000000000..3ebcd19c7 --- /dev/null +++ b/docs/assets/code/uc/src/Physical.lf @@ -0,0 +1,13 @@ +target uC; +reactor Physical { + input x:int; + @max_pending_events(1) + physical action a; + reaction(x) -> a {= + lf_schedule(a, 0); + =} + reaction(a) {= + interval_t elapsed_time = env->get_elapsed_logical_time(env); + printf("Action triggered at logical time %lld nsec after start.\n", elapsed_time); + =} +} diff --git a/docs/assets/code/uc/src/RegressionTest.lf b/docs/assets/code/uc/src/RegressionTest.lf new file mode 100644 index 000000000..d12c2169c --- /dev/null +++ b/docs/assets/code/uc/src/RegressionTest.lf @@ -0,0 +1,16 @@ +target uC + +import Count from "Count.lf" +import Scale from "Scale.lf" +import TestCount from "TestCount.lf" + +@platform("Native") +@timeout(1 sec) +@fast(true) +main reactor RegressionTest { + c = new Count() + s = new Scale(factor=4) + t = new TestCount(stride=4, num_inputs=11) + c.y -> s.x + s.y -> t.x +} diff --git a/docs/assets/code/uc/src/Scale.lf b/docs/assets/code/uc/src/Scale.lf new file mode 100644 index 000000000..b583afacb --- /dev/null +++ b/docs/assets/code/uc/src/Scale.lf @@ -0,0 +1,10 @@ +target uC + +reactor Scale(factor: int = 2) { + input x: int + output y: int + + reaction(x) -> y {= + lf_set(y, x->value * self->factor); + =} +} diff --git a/docs/assets/code/uc/src/Schedule.lf b/docs/assets/code/uc/src/Schedule.lf new file mode 100644 index 000000000..ad469923a --- /dev/null +++ b/docs/assets/code/uc/src/Schedule.lf @@ -0,0 +1,13 @@ +target uC; +reactor Schedule { + input x:int; + @max_pending_events(3) + logical action a; + reaction(x) -> a {= + lf_schedule(a, MSEC(200)); + =} + reaction(a) {= + interval_t elapsed_time = env->get_elapsed_logical_time(env); + printf("Action triggered at logical time %lld nsec after start.\n", elapsed_time); + =} +} diff --git a/docs/assets/code/uc/src/Simultaneous.lf b/docs/assets/code/uc/src/Simultaneous.lf new file mode 100644 index 000000000..3f772a451 --- /dev/null +++ b/docs/assets/code/uc/src/Simultaneous.lf @@ -0,0 +1,32 @@ +target uC + +reactor Destination { + input x: int + input y: int + + reaction(x, y) {= + tag_t tag = env->scheduler->current_tag(env->scheduler); + printf("Time since start: %lld, microstep: %d\n", + env->get_elapsed_logical_time(env), tag.microstep + ); + if (lf_is_present(x)) { + printf(" x is present.\n"); + } + if (lf_is_present(y)) { + printf(" y is present.\n"); + } + =} +} + +@platform("Native") +main reactor { + logical action repeat + d = new Destination() + + reaction(startup) -> d.x, repeat {= + lf_set(d.x, 1); + lf_schedule(repeat, 0); + =} + + reaction(repeat) -> d.y {= lf_set(d.y, 1); =} +} diff --git a/docs/assets/code/uc/src/SlowingClock.lf b/docs/assets/code/uc/src/SlowingClock.lf new file mode 100644 index 000000000..017044188 --- /dev/null +++ b/docs/assets/code/uc/src/SlowingClock.lf @@ -0,0 +1,20 @@ +target uC + +@platform("Native") +main reactor SlowingClock(start: time = 100 ms, incr: time = 100 ms) { + state interval: time = start + logical action a + + reaction(startup) -> a {= + lf_schedule(a, self->start); + =} + + reaction(a) -> a {= + interval_t elapsed_logical_time = env->get_elapsed_logical_time(env); + printf("Logical time since start: %lld nsec.\n", + elapsed_logical_time + ); + self->interval += self->incr; + lf_schedule(a, self->interval); + =} +} diff --git a/docs/assets/code/uc/src/Sparse.lf b/docs/assets/code/uc/src/Sparse.lf new file mode 100644 index 000000000..b898262cc --- /dev/null +++ b/docs/assets/code/uc/src/Sparse.lf @@ -0,0 +1,16 @@ +target uC; +reactor Sparse { + input[100] in: int + reaction(in) {= + // Create an iterator over the input channels. + struct lf_multiport_iterator_t i = lf_multiport_iterator(in); + // Get the least index of a channel with present inputs. + int channel = lf_multiport_next(&i); + // Iterate until no more channels have present inputs. + while(channel >= 0) { + printf("Received %d on channel %d\n", in[channel]->value, channel); + // Get the next channel with a present input. + channel = lf_multiport_next(&i); + } + =} +} diff --git a/docs/assets/code/uc/src/TestCount.lf b/docs/assets/code/uc/src/TestCount.lf new file mode 100644 index 000000000..5a27eb363 --- /dev/null +++ b/docs/assets/code/uc/src/TestCount.lf @@ -0,0 +1,28 @@ +target uC + +reactor TestCount(start: int = 0, stride: int = 1, num_inputs: int = 1) { + state count: int = start + state inputs_received: int = 0 + input x: int + + reaction(x) {= + printf("Received %d.\n", x->value); + if (x->value != self->count) { + printf("ERROR: Expected %d.\n", self->count); + exit(1); + } + self->count += self->stride; + self->inputs_received++; + =} + + reaction(shutdown) {= + printf("Shutdown invoked.\n"); + if (self->inputs_received != self->num_inputs) { + printf("ERROR: Expected to receive %d inputs, but got %d.\n", + self->num_inputs, + self->inputs_received + ); + exit(2); + } + =} +} diff --git a/docs/assets/code/uc/src/TimeElapsed.lf b/docs/assets/code/uc/src/TimeElapsed.lf new file mode 100644 index 000000000..5658f7b6b --- /dev/null +++ b/docs/assets/code/uc/src/TimeElapsed.lf @@ -0,0 +1,13 @@ +target uC + +@platform("Native") +main reactor TimeElapsed { + timer t(0, 1 s) + + reaction(t) {= + printf( + "Elapsed logical time is %lld.\n", + env->get_elapsed_logical_time(env) + ); + =} +} diff --git a/docs/assets/code/uc/src/TimeLag.lf b/docs/assets/code/uc/src/TimeLag.lf new file mode 100644 index 000000000..fd4cf23a6 --- /dev/null +++ b/docs/assets/code/uc/src/TimeLag.lf @@ -0,0 +1,15 @@ +target uC + +@platform("Native") +main reactor TimeLag { + timer t(0, 1 s) + + reaction(t) {= + interval_t tt = env->get_elapsed_logical_time(env); + interval_t T = env->get_elapsed_physical_time(env); + printf( + "Elapsed logical time: %lld, physical time: %lld, lag: %lld\n", + tt, T, T-tt + ); + =} +} diff --git a/docs/assets/code/uc/src/Timer.lf b/docs/assets/code/uc/src/Timer.lf new file mode 100644 index 000000000..77324c48d --- /dev/null +++ b/docs/assets/code/uc/src/Timer.lf @@ -0,0 +1,10 @@ +target uC + +@platform("Native") +main reactor Timer { + timer t(0, 1 sec) + + reaction(t) {= + printf("Logical time is %lld.\n", env->get_logical_time(env)); + =} +} diff --git a/docs/assets/code/uc/src/Triggering.lf b/docs/assets/code/uc/src/Triggering.lf new file mode 100644 index 000000000..7478d57c5 --- /dev/null +++ b/docs/assets/code/uc/src/Triggering.lf @@ -0,0 +1,14 @@ +target uC +reactor Inside { + input x: int + reaction(x) {= + printf("Received %d\n", x->value); + =} +} +@platform("Native") +main reactor { + i = new Inside() + reaction(startup) -> i.x {= + lf_set(i.x, 42); + =} +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/lib/Cos.lf b/docs/assets/code/uc/src/lib/Cos.lf new file mode 100644 index 000000000..27730290e --- /dev/null +++ b/docs/assets/code/uc/src/lib/Cos.lf @@ -0,0 +1,13 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +preamble {= + #include +=} +reactor Cos { + reaction(startup) {= + printf("The cosine of 1 is %f.\n", cos(1)); + =} +} diff --git a/docs/assets/code/uc/src/test/AlignmentTest.lf b/docs/assets/code/uc/src/test/AlignmentTest.lf new file mode 100644 index 000000000..4ec68fe77 --- /dev/null +++ b/docs/assets/code/uc/src/test/AlignmentTest.lf @@ -0,0 +1,21 @@ +target uC { + timeout: 3 secs +} + +main reactor { + state s:int(0); + timer t1(100 msec, 100 msec); + timer t2(200 msec, 200 msec); + timer t4(400 msec, 400 msec); + reaction(t1) {= + self->s += 1; + =} + reaction(t2) {= + self->s -= 2; + =} + reaction(t4) {= + if (self->s != 0) { + lf_print_error_and_exit("Value should be 0!"); + } + =} +} diff --git a/docs/assets/code/uc/src/test/ContainedOverwriting.lf b/docs/assets/code/uc/src/test/ContainedOverwriting.lf new file mode 100644 index 000000000..28d3b9489 --- /dev/null +++ b/docs/assets/code/uc/src/test/ContainedOverwriting.lf @@ -0,0 +1,12 @@ +target uC +import Overwriting from "../Overwriting.lf"; +@platform("Native") +@timeout(1 sec) +main reactor { + s = new Overwriting(); + reaction(s.y) {= + printf("At logical time %lld, s = %d.\n", + env->get_elapsed_logical_time(env), s.y->value + ); + =} +} diff --git a/docs/assets/code/uc/src/test/CountDoubleDestination.lf b/docs/assets/code/uc/src/test/CountDoubleDestination.lf new file mode 100644 index 000000000..1d0b6271c --- /dev/null +++ b/docs/assets/code/uc/src/test/CountDoubleDestination.lf @@ -0,0 +1,23 @@ +target uC { + cmake: false, + compiler: "cc", + flags: "-O3", + fast: true, + logging: log, + timeout: 1 secs +}; +import Count from "../Count.lf"; +import Double from "../Double.lf"; +import Destination from "../Destination.lf"; +import TestCount from "../TestCount.lf"; + +main reactor { + c = new Count(); + d = new Double(); + r = new Destination(); + t = new TestCount(start = 0, stride = 2, num_inputs = 11); + c.y -> d.x; + c.y -> r.x; + d.y -> r.y; + d.y -> t.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/CountScale.lf b/docs/assets/code/uc/src/test/CountScale.lf new file mode 100644 index 000000000..4d0b1a007 --- /dev/null +++ b/docs/assets/code/uc/src/test/CountScale.lf @@ -0,0 +1,16 @@ +target uC + +import Count from "../Count.lf"; +import Scale from "../Scale.lf"; +import TestCount from "../TestCount.lf"; + +@platform("Native") +@timeout(1 sec) +@fast(true) +main reactor { + c = new Count(); + d = new Scale(); + t = new TestCount(start = 0, stride = 2, num_inputs = 11); + c.y -> d.x; + d.y -> t.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/DestinationTest.lf b/docs/assets/code/uc/src/test/DestinationTest.lf new file mode 100644 index 000000000..a933663f4 --- /dev/null +++ b/docs/assets/code/uc/src/test/DestinationTest.lf @@ -0,0 +1,13 @@ +target uC + +import Destination from "../Destination.lf"; + +@platform("Native") +main reactor { + d = new Destination() + reaction(startup) -> d.x, d.y {= + lf_set(d.x, 1); + lf_set(d.y, 2); + =} +} + diff --git a/docs/assets/code/uc/src/test/DoubleTest.lf b/docs/assets/code/uc/src/test/DoubleTest.lf new file mode 100644 index 000000000..ae14acc64 --- /dev/null +++ b/docs/assets/code/uc/src/test/DoubleTest.lf @@ -0,0 +1,15 @@ +target uC + +import Double from "../Double.lf"; + +@platform("Native") +main reactor { + d = new Double() + reaction(startup) -> d.x {= + lf_set(d.x, 1); + =} + reaction(d.y) {= + printf("Double: %d\n", d.y->value); + =} +} + diff --git a/docs/assets/code/uc/src/test/ExtendsTest.lf b/docs/assets/code/uc/src/test/ExtendsTest.lf new file mode 100644 index 000000000..116d0eba0 --- /dev/null +++ b/docs/assets/code/uc/src/test/ExtendsTest.lf @@ -0,0 +1,29 @@ +target uC + +import Count from "../Count.lf"; +import TestCount from "../TestCount.lf"; + +reactor A { + input a:int; + output out:int; + reaction(a) -> out {= + lf_set(out, a->value); + =} +} +reactor B extends A { + input b:int; + reaction(a, b) -> out {= + lf_set(out, a->value + b->value); + =} +} + +@platform("Native") +@timeout(1 sec) +@fast(true) +main reactor { + c = new Count(); + b = new B(); + t = new TestCount(start = 0, stride = 2, num_inputs = 11); + (c.y)+ -> b.a, b.b; + b.out -> t.x; +} diff --git a/docs/assets/code/uc/src/test/HierarchyTest.lf b/docs/assets/code/uc/src/test/HierarchyTest.lf new file mode 100644 index 000000000..d6717b60a --- /dev/null +++ b/docs/assets/code/uc/src/test/HierarchyTest.lf @@ -0,0 +1,21 @@ +target uC { + timeout: 1 sec, + fast: true +} +import Count from "../Count.lf"; +import Scale from "../Scale.lf"; +import TestCount from "../TestCount.lf"; + +reactor Container(stride:int(2)) { + output y:int; + c = new Count(); + s = new Scale(factor = stride); + c.y -> s.x; + s.y -> y; +} + +main reactor { + c = new Container(stride = 4); + t = new TestCount(stride = 4, num_inputs = 11); + c.y -> t.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/MultiportSourceTest.lf b/docs/assets/code/uc/src/test/MultiportSourceTest.lf new file mode 100644 index 000000000..cfa355904 --- /dev/null +++ b/docs/assets/code/uc/src/test/MultiportSourceTest.lf @@ -0,0 +1,34 @@ + // Check bank of reactors sending to bank of reactors. +target uC + +import MultiportSource from "../MultiportSource.lf"; +reactor Destination( + bank_index:int = 0 +) { + state s:int = 0; + input in:int; + reaction(in) {= + printf("Destination %d received: %d.\n", self->bank_index, in->value); + if (in->value != self->s) { + printf("ERROR: Expected %d.\n", self->s); + exit(1); + } + self->s += self->bank_index; + =} + reaction(shutdown) {= + if (self->s == 0 && self->bank_index != 0) { + fprintf(stderr, "ERROR: Destination %d received no input!\n", self->bank_index); + exit(1); + } + printf("Success.\n"); + =} +} + +@platform("Native") +@timeout(2 sec) +@fast(true) +main reactor(width:int = 4) { + a = new[width] MultiportSource(); + b = new[width] Destination(); + a.out -> b.in; +} diff --git a/docs/assets/code/uc/src/test/PhysicalTest.lf b/docs/assets/code/uc/src/test/PhysicalTest.lf new file mode 100644 index 000000000..4cf3dc766 --- /dev/null +++ b/docs/assets/code/uc/src/test/PhysicalTest.lf @@ -0,0 +1,10 @@ +target uC; +import Physical from "../Physical.lf"; +@platform("Native") +main reactor { + timer t(200 msec, 200 msec); + p = new Physical(); + reaction(t) -> p.x {= + lf_set(p.x, 0); + =} +} diff --git a/docs/assets/code/uc/src/test/PreambleTest1.lf b/docs/assets/code/uc/src/test/PreambleTest1.lf new file mode 100644 index 000000000..ce1771e93 --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest1.lf @@ -0,0 +1,14 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +@platform("Native") +main reactor { + preamble {= + #include + =} + reaction(startup) {= + printf("The cosine of 1 is %f.\n", cos(1)); + =} +} diff --git a/docs/assets/code/uc/src/test/PreambleTest2.lf b/docs/assets/code/uc/src/test/PreambleTest2.lf new file mode 100644 index 000000000..cd8179050 --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest2.lf @@ -0,0 +1,23 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +preamble {= + #include +=} +reactor Cos { + reaction(startup) {= + printf("The cosine of 1 is %f.\n", cos(1)); + =} +} +reactor Sin { + reaction(startup) {= + printf("The sine of 1 is %f.\n", sin(1)); + =} +} +@platform("Native") +main reactor { + c = new Cos() + s = new Sin() +} diff --git a/docs/assets/code/uc/src/test/PreambleTest3.lf b/docs/assets/code/uc/src/test/PreambleTest3.lf new file mode 100644 index 000000000..4223c032a --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest3.lf @@ -0,0 +1,19 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +import Cos from "../lib/Cos.lf" +preamble {= + #include +=} +reactor Sin { + reaction(startup) {= + printf("The sine of 1 is %f.\n", sin(1)); + =} +} +@platform("Native") +main reactor { + c = new Cos() + s = new Sin() +} diff --git a/docs/assets/code/uc/src/test/PreambleTest4.lf b/docs/assets/code/uc/src/test/PreambleTest4.lf new file mode 100644 index 000000000..c64ac7e6f --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest4.lf @@ -0,0 +1,19 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +@platform("Native") +main reactor { + preamble {= + int add_42(int i) { + return i + 42; + } + =} + reaction(startup) {= + printf("42 plus 42 is %d.\n", add_42(42)); + =} + reaction(startup) {= + printf("42 plus 1 is %d.\n", add_42(1)); + =} +} diff --git a/docs/assets/code/uc/src/test/PreambleTest5.lf b/docs/assets/code/uc/src/test/PreambleTest5.lf new file mode 100644 index 000000000..792e93111 --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest5.lf @@ -0,0 +1,28 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +preamble {= + int add_42(int i); +=} +reactor Add_42 { + reaction(startup) {= + printf("42 plus 42 is %d.\n", add_42(42)); + =} +} +reactor Add_1 { + reaction(startup) {= + printf("42 plus 1 is %d.\n", add_42(1)); + =} +} +@platform("Native") +main reactor { + preamble {= + int add_42(int i) { + return i + 42; + } + =} + a = new Add_42() + b = new Add_1() +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/PreambleTest6.lf b/docs/assets/code/uc/src/test/PreambleTest6.lf new file mode 100644 index 000000000..0331a7911 --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest6.lf @@ -0,0 +1,26 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +preamble {= + extern const char shared_string[]; +=} +reactor A { + reaction(startup) {= + printf("Reactor A says %s.\n", shared_string); + =} +} +reactor B { + reaction(startup) {= + printf("Reactor B says %s.\n", shared_string); + =} +} +@platform("Native") +main reactor { + preamble {= + const char shared_string[] = "Hello"; + =} + a = new A() + b = new B() +} diff --git a/docs/assets/code/uc/src/test/PreambleTest7.lf b/docs/assets/code/uc/src/test/PreambleTest7.lf new file mode 100644 index 000000000..56f2d58fa --- /dev/null +++ b/docs/assets/code/uc/src/test/PreambleTest7.lf @@ -0,0 +1,15 @@ +/** + * This example is included in Preambles.md, but not automatically imported. + * Success of the test is compiling and running. + */ +target uC +preamble {= + typedef int foo; +=} +@platform("Native") +main reactor { + state x:foo = 0 + reaction(startup) {= + printf("State is %d\n", self->x); + =} +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/ScheduleTest.lf b/docs/assets/code/uc/src/test/ScheduleTest.lf new file mode 100644 index 000000000..4ec1285df --- /dev/null +++ b/docs/assets/code/uc/src/test/ScheduleTest.lf @@ -0,0 +1,12 @@ +target uC +import Schedule from "../Schedule.lf" +import Count from "../Count.lf" + +@platform("Native") +@timeout(1 sec) +@fast(true) +main reactor { + c = new Count() + d = new Schedule() + c.y -> d.x; +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/SlowingClockTest.lf b/docs/assets/code/uc/src/test/SlowingClockTest.lf new file mode 100644 index 000000000..2b7c040a3 --- /dev/null +++ b/docs/assets/code/uc/src/test/SlowingClockTest.lf @@ -0,0 +1,42 @@ +/** + * Events are scheduled with increasing additional delays of 0, 100, 300, 600 + * msec on a logical action with a minimum delay of 100 msec. + * The use of the logical action ensures the elapsed time jumps exactly from + * 0 to 100, 300, 600, and 1000 msec. + */ +target uC { + timeout: 1 sec, + fast: true, +}; +main reactor(start:time(100 msec), incr:time(100 msec)) { + logical action a; + state interval:time(start); + state expected_time:time(start); + reaction(startup) -> a {= + lf_schedule(a, self->start); + =} + reaction(a) -> a {= + instant_t elapsed_logical_time = lf_time_logical_elapsed(); + printf("Logical time since start: \%lld nsec.\n", + elapsed_logical_time + ); + if (elapsed_logical_time != self->expected_time) { + printf("ERROR: Expected time to be: \%lld nsec.\n", + self->expected_time + ); + exit(1); + } + self->interval += self->incr; + lf_schedule(a, self->interval); + self->expected_time += self->interval; + =} + reaction(shutdown) {= + if (self->expected_time != MSEC(1500)) { + printf("ERROR: Expected the next expected time to be: 1500000000 nsec.\n"); + printf("It was: \%lld nsec.\n", self->expected_time); + exit(2); + } else { + printf("Test passes.\n"); + } + =} +} diff --git a/docs/assets/code/uc/src/test/SparseTest.lf b/docs/assets/code/uc/src/test/SparseTest.lf new file mode 100644 index 000000000..98eafcf5e --- /dev/null +++ b/docs/assets/code/uc/src/test/SparseTest.lf @@ -0,0 +1,8 @@ +target uC +import Sparse from "../Sparse.lf" +main reactor { + s = new Sparse() + reaction(startup) -> s.in {= + lf_set(s.in[12], 42); + =} +} \ No newline at end of file diff --git a/docs/assets/code/uc/src/test/StructParameter.lf b/docs/assets/code/uc/src/test/StructParameter.lf new file mode 100644 index 000000000..414e76f8f --- /dev/null +++ b/docs/assets/code/uc/src/test/StructParameter.lf @@ -0,0 +1,16 @@ +target uC; +main reactor(p:hello_t("Earth", 42)) { + preamble {= + typedef struct hello_t { + char* name; + int value; + } hello_t; + =} + reaction(startup) {= + printf("Parameter p.name=\"%s\", value=%d.\n", self->p.name, self->p.value); + if (self->p.value != 42) { + fprintf(stderr, "FAILED: Expected 42.\n"); + exit(1); + } + =} +} diff --git a/docs/assets/images/diagrams/DeadlineTest.svg b/docs/assets/images/diagrams/DeadlineTest.svg index 0f1744bf5..795ea79dc 100644 --- a/docs/assets/images/diagrams/DeadlineTest.svg +++ b/docs/assets/images/diagrams/DeadlineTest.svg @@ -1,216 +1 @@ - - - - -Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Sunday, April 10, 2022 at 10:03:56 AM Pacific Daylight Time - - - - - - - - - - - - DeadlineTest - - - - - - - - - - - - - - - - - - - - - - - Deadline - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 msec - - - - - - - - - - - - - x - - - - - - - - - - - - - d - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - 2 - - - - - - - - - - - - - L - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +DeadlineTestDeadline10 msxd123L \ No newline at end of file diff --git a/docs/assets/images/diagrams/DecentralizedTimerAfter.svg b/docs/assets/images/diagrams/DecentralizedTimerAfter.svg new file mode 100644 index 000000000..3a76e85fe --- /dev/null +++ b/docs/assets/images/diagrams/DecentralizedTimerAfter.svg @@ -0,0 +1 @@ +DecentralizedTimerAfterCount(0, 1 s)outPrintTimer(10 ms, 1 s)12inmaxwait: 010 ms \ No newline at end of file diff --git a/docs/assets/images/diagrams/DecentralizedZeroDelayLoop.svg b/docs/assets/images/diagrams/DecentralizedZeroDelayLoop.svg index 44d651e0d..89ad2ee86 100644 --- a/docs/assets/images/diagrams/DecentralizedZeroDelayLoop.svg +++ b/docs/assets/images/diagrams/DecentralizedZeroDelayLoop.svg @@ -1 +1 @@ -DecentralizedZeroDelayLoopCountPrint(0, 100 ms)12inoutDoubleinout \ No newline at end of file +DecentralizedZeroDelayLoopCountPrint(0, 100 ms)12inoutmaxwait: 0Doubleinoutabsent_after: forever \ No newline at end of file diff --git a/docs/assets/images/diagrams/DecentralizedZeroDelayLoopWithChecker.svg b/docs/assets/images/diagrams/DecentralizedZeroDelayLoopWithChecker.svg index 63ad1278a..c33a45d07 100644 --- a/docs/assets/images/diagrams/DecentralizedZeroDelayLoopWithChecker.svg +++ b/docs/assets/images/diagrams/DecentralizedZeroDelayLoopWithChecker.svg @@ -1 +1 @@ -DecentralizedZeroDelayLoopWithCheckerCountPrintWithChecker(0, 100 ms)123$inoutDoubleinout \ No newline at end of file +DecentralizedZeroDelayLoopWithCheckerCountPrintWithChecker(0, 100 ms)123inpoutmaxwait: 0Doubleinpoutabsent_after: 20 ms \ No newline at end of file diff --git a/docs/assets/images/diagrams/Federated.svg b/docs/assets/images/diagrams/Federated.svg new file mode 100644 index 000000000..1abf8eb6b --- /dev/null +++ b/docs/assets/images/diagrams/Federated.svg @@ -0,0 +1 @@ +FederatedCount(0, 1 s)outPrintin \ No newline at end of file diff --git a/docs/developer/website-development.mdx b/docs/developer/website-development.mdx index 168a5732e..f56bf3b0e 100644 --- a/docs/developer/website-development.mdx +++ b/docs/developer/website-development.mdx @@ -78,20 +78,20 @@ In general, different targets are just a bunch of `Tab` components with `groupId The target selector, which appears on the top, is a `Tab` component with no content. It is defined in `src/components/LinguaFrancaMultiTargetUtils/LanguageSelector.tsx`. ##### Usage -`` where the target languages could be a subset of all targets which we support. The ordering is guaranteed to be `C C++ Python Rust TypeScript`, regardless of the ordering supplied as argument. +`` where the target languages could be a subset of all targets which we support. The ordering is guaranteed to be `C micro-LF C++ Python Rust TypeScript`, regardless of the ordering supplied as argument. ##### Examples -`` +`` :::note[Rendered as] - + ::: -`` +`` :::note[Rendered as] - + ::: @@ -268,23 +268,25 @@ Remember to use relative import! If you don't, you will mess up the versioning. ```tsx import C_HelloWorld from '../assets/code/c/src/HelloWorld.lf'; +import UC_HelloWorld from '../assets/code/uc/src/HelloWorld.lf'; import Cpp_HelloWorld from '../assets/code/cpp/src/HelloWorld.lf'; import Py_HelloWorld from '../assets/code/py/src/HelloWorld.lf'; import Rs_HelloWorld from '../assets/code/rs/src/HelloWorld.lf'; import TS_HelloWorld from '../assets/code/ts/src/HelloWorld.lf'; - + ``` :::note[Rendered as] import C_HelloWorld from '../assets/code/c/src/HelloWorld.lf'; +import UC_HelloWorld from '../assets/code/uc/src/HelloWorld.lf'; import Cpp_HelloWorld from '../assets/code/cpp/src/HelloWorld.lf'; import Py_HelloWorld from '../assets/code/py/src/HelloWorld.lf'; import Rs_HelloWorld from '../assets/code/rs/src/HelloWorld.lf'; import TS_HelloWorld from '../assets/code/ts/src/HelloWorld.lf'; - + ::: diff --git a/docs/embedded/arduino.mdx b/docs/embedded/arduino.mdx index 8cbc473d8..5596894a0 100644 --- a/docs/embedded/arduino.mdx +++ b/docs/embedded/arduino.mdx @@ -3,6 +3,10 @@ title: Arduino description: Developing LF Programs on Arduino. --- +:::note +This page is for the `C` target. For the `uC` target, see [https://micro-lf.org/](https://micro-lf.org/). +::: + ## Overview To run Lingua Franca on an Arduino-compatible microcontroller, you can use the diff --git a/docs/embedded/flexpret.mdx b/docs/embedded/flexpret.mdx index 0d9504b04..ff84ed59b 100644 --- a/docs/embedded/flexpret.mdx +++ b/docs/embedded/flexpret.mdx @@ -2,6 +2,10 @@ title: FlexPRET description: Developing LF Programs for FlexPRET. --- +:::note +This page is for the `C` target. For the `uC` target, see [https://micro-lf.org/](https://micro-lf.org/). +::: + # Overview FlexPRET is a precision-timed (PRET) machine designed for mixed-criticality systems. As of 2024, PRET machines are an open field of research. Refer to its [github page](https://github.com/pretis/flexpret) for more in-depth information. FlexPRET either needs to be emulated or run on a Field-Programmable Gate Array (FPGA). In this guide we will show you how to pair FlexPRET with Lingua Franca, leaving you with precise software execution. diff --git a/docs/embedded/nRF52.mdx b/docs/embedded/nRF52.mdx index 63740b77c..fd4b7028b 100644 --- a/docs/embedded/nRF52.mdx +++ b/docs/embedded/nRF52.mdx @@ -2,6 +2,11 @@ title: nRF52 description: Developing LF Programs for nRF52. --- + +:::note +This page is for the `C` target. For the `uC` target, see [https://micro-lf.org/](https://micro-lf.org/). +::: + # Overview Lingua Franca's C-runtime has rudimentary support for nRF52 platforms. See the [lf-nrf52 repository](https://github.com/lf-lang/lf-nRF52) for more information. diff --git a/docs/embedded/patmos.mdx b/docs/embedded/patmos.mdx index cf2807c03..7020b616a 100644 --- a/docs/embedded/patmos.mdx +++ b/docs/embedded/patmos.mdx @@ -2,11 +2,17 @@ title: Patmos description: Developing LF Programs for Patmos. --- + +:::note +This page is for the `C` target. For the `uC` target, see [https://micro-lf.org/](https://micro-lf.org/). +::: + # Overview Lingua Franca's C-runtime supports [Patmos](https://github.com/t-crest/patmos), a bare-metal execution platform that is optimized for time-predictable execution. The time-predictability aspect of Patmos makes it easier to obtain a worst-case execution time (WCET) for reactions. + ## Prerequisites - Linux or macOS development system. (use WSL on Windows) - DE2-115 Development Kit, which is equipped with Altera Cyclone IV FPGA (optional) diff --git a/docs/embedded/rp2040.mdx b/docs/embedded/rp2040.mdx index 69aa19181..e3b59696c 100644 --- a/docs/embedded/rp2040.mdx +++ b/docs/embedded/rp2040.mdx @@ -2,6 +2,11 @@ title: RP2040 description: Developing LF Programs for RP2040. --- + +:::note +This page is for the `C` target. For the `uC` target, see [https://micro-lf.org/](https://micro-lf.org/). +::: + # Overview Lingua Franca's C-runtime supports the [Raspberry Pi RP2040](https://en.wikipedia.org/wiki/RP2040), an inexpensive microcontroller that is typically used without an operating system ("bare metal"). A [series of lab exercises](https://lf-lang.org/embedded-lab/) have been developed around the [Pololu 3pi+ 2040 robot](https://www.pololu.com/docs/0J86), which is based on the RP2040. The lab serves mainly for instructional use, but is also recommended as the best documentation and guide for getting started developing for the RP2040, and may be adapted to other robots and RP2040 platforms, including the Raspberry Pi Pico boards. diff --git a/docs/embedded/zephyr.mdx b/docs/embedded/zephyr.mdx index dc77a8f1f..361420c0e 100644 --- a/docs/embedded/zephyr.mdx +++ b/docs/embedded/zephyr.mdx @@ -2,6 +2,11 @@ title: Zephyr description: Developing LF Programs for Zephyr RTOS. --- + +:::note +This page is for the `C` target. For the `uC` target, see [https://micro-lf.org/](https://micro-lf.org/). +::: + # Overview Lingua Franca's C-runtime supports the Zephyr RTOS. This enables developing and programming [hundreds](https://docs.zephyrproject.org/latest/boards/index.html) diff --git a/docs/installation.md b/docs/installation.md index a9adaa066..4043948d6 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -4,6 +4,13 @@ title: Installation # Installation +:::note +For Micro-LF (the `uC` target), see [https://micro-lf.org/getting-started/](https://micro-lf.org/getting-started/) for +instructions on installing the code generator `ulfg` and the compiler `ulfc`. +The instructions below for the Visual Studio Code plugin are still useful because the plugin also supports the `uC` target. +For all other targets, continue here. +::: + ## For the Impatient Do one or more of the following: diff --git a/docs/introduction.md b/docs/introduction.md index 7000161f1..82ba774f4 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -16,7 +16,8 @@ A Lingua Franca program specifies the interactions between concurrent components If the application has exploitable parallelism, then it executes transparently on multiple cores or multiple machines without compromising determinacy. The above program shows a simple pipeline chain, where reactions A1, B1, and the reactions in C all can execute in parallel. The logical delays of 100 ms on connections between ports enable such parallel execution. In ReactorC, reactions C1 and C2 do not execute in parallel because they (potentially) share state variables. The deterministic semantics of LF ensures that for the above program, reaction C1 will always process the previous result of B1 (not the one being computed in parallel), which is triggered by the 200ms-old result from A1. Only after reaction C1 completes, reaction C2 will process the 200ms-old result from A1. Hence, despite the parallel execution, and even if this program is distributed across networked hosts, the computation is deterministic and repeatable. -The `lfc` code generator synthesizes one or more programs in the target language, which are then compiled using standard tool chains. A distributed (federated) application translates into multiple programs and scripts to launch those programs on distributed machines. The communication fabric connecting components is synthesized as part of the programs. +For all targets except `uC`, the `lfc` code generator synthesizes one or more programs in the target language, which are then compiled using standard tool chains. A distributed (federated) application translates into multiple programs and scripts to launch those programs on distributed machines. The communication fabric connecting components is synthesized as part of the programs. +For the `uC` target, use the `ulfg` code generator to generate code, or the `ulfc` compiler for the Native platform (Linux or macOS) to generate and compile code (see [https://micro-lf.org](https://micro-lf.org)). ## Reactor-Oriented Programming diff --git a/docs/reference/expressions.mdx b/docs/reference/expressions.mdx index f6ee9eb89..a710974e1 100644 --- a/docs/reference/expressions.mdx +++ b/docs/reference/expressions.mdx @@ -9,7 +9,7 @@ import { ShowIf, ShowIfs, ShowOnly } from '@site/src/components/LinguaFrancaMultiTargetUtils'; - + A subset of LF syntax is used to write _expressions_, which represent values in the target language. Expressions are used to initialize state variable and to give values to parameters. Arbitrary expressions in the target language can always be given within delimiters `{= ... =}`, but simple forms do not require the delimiters. These simple forms are documented here. diff --git a/docs/reference/security.mdx b/docs/reference/security.mdx index 598822a79..5e91bc8c6 100644 --- a/docs/reference/security.mdx +++ b/docs/reference/security.mdx @@ -9,7 +9,7 @@ import { ShowIf, ShowIfs, ShowOnly } from '@site/src/components/LinguaFrancaMultiTargetUtils'; - + By default, there is no secure authentication when a federate joins a federation, and data exchanged between federates is not encrypted. For targets that support it, Lingua Franca provides robust, end-to-end communication security that encrypts all message exchanges and ensures only authorized federates can participate. @@ -248,7 +248,7 @@ If you would like to go back to non-AUTH mode, you would have to remove all cont - + :::note Pluggable communication security (TLS and SST) is currently only supported for the **C** and **Python** targets. Support for other target languages is planned for the future. diff --git a/docs/reference/target-declaration.mdx b/docs/reference/target-declaration.mdx index 4ef09a3e4..bab48452c 100644 --- a/docs/reference/target-declaration.mdx +++ b/docs/reference/target-declaration.mdx @@ -13,6 +13,19 @@ import { # Target Declaration + +Every Lingua Franca program begins with a statement of this form: + +```lf + target uC +``` + +Unlike the other targets, the `uC` target does not use target parameters. +Instead, it uses annotations, as described in [https://micro-lf.org/documentation/annotations/](https://micro-lf.org/documentation/annotations/). + + + + Every Lingua Franca program begins with a statement of this form: ```lf @@ -76,6 +89,27 @@ c={ workers: , };` } +uc={ +`target uC { + auth: + build: , + build-type: , + cmake-args: , + cmake-include: , + compiler: , + compiler-flags: , + docker: , + fast: , + files: , + logging: , + no-compile: , + protobufs: , + single-threaded: , + timeout: