lf-lang / lingua-franca

Intuitive concurrent programming in any language
https://www.lf-lang.org
Other
240 stars 63 forks source link

Composition problem: multi-output to multi-banks. #1843

Open stustd opened 1 year ago

stustd commented 1 year ago

In a reactor, I have two reactor banks. As part of a hierarchically ordered startup procedure I intent to trigger the starting up of the bank reactors as follows:

  a = new[maxn_A] A();
  b = new[maxn_B] B();

  reaction(startup_pre) -> a.startup_pre, b.startup_pre
  {=
    for (int i=0; i<self->maxn_A; i++)
        lf_set(a[i].startup_pre, 0);
    for (int i=0; i<self->maxn_B; i++)
        lf_set(b[i].startup_pre, 0);
  =}

However, the lfc compiler complains with: lfc: error: Error executing EValidator. With only one bank (e.g. removing b and b.startup_pre) it works. So the question is: how to combine multi-outputs to multiple banks? (I couldn't find an example addressing this, but I guess there must be a way...).

edwardalee commented 1 year ago

Please post a full program and error message. I interpolated to get the following program, which compiles fine and runs (using the current master branch, at least):

target C
reactor A {
    input startup_pre:int
}
reactor B {
    input startup_pre:int
}
main reactor(maxn_A:int = 2, maxn_B:int = 3) {
  a = new[maxn_A] A();
  b = new[maxn_B] B();

  reaction(startup) -> a.startup_pre, b.startup_pre
  {=
    for (int i=0; i<self->maxn_A; i++)
        lf_set(a[i].startup_pre, 0);
    for (int i=0; i<self->maxn_B; i++)
        lf_set(b[i].startup_pre, 0);
  =}
}
stustd commented 1 year ago

Verified your run; thanks! Will look further into where I'm getting into trouble. Will update this post.

Update : With the latest LF master (lfc 0.4.1-SNAPSHOT), fortunately, the lfc: error: Error executing EValidator produces a java stacktrace indicating that the problem happens at org.lflang.generator.MixedRadixInt.<init>(MixedRadixInt.java:74):

> Task :cli:lfc:run FAILED
0    [main] ERROR text.validation.CompositeEValidator  - Error executing EValidator
java.lang.IllegalArgumentException: Invalid constructor arguments.
    at org.lflang.generator.MixedRadixInt.<init>(MixedRadixInt.java:74)
    at org.lflang.generator.RuntimeRange.startMR(RuntimeRange.java:387)
    at org.lflang.generator.ReactionInstanceGraph.addDownstreamReactions(ReactionInstanceGraph.java:144)
    at org.lflang.generator.ReactionInstanceGraph.addNodesAndEdges(ReactionInstanceGraph.java:237)
    at org.lflang.generator.ReactionInstanceGraph.addNodesAndEdges(ReactionInstanceGraph.java:243)
    at org.lflang.generator.ReactionInstanceGraph.rebuild(ReactionInstanceGraph.java:81)
    at org.lflang.generator.ReactionInstanceGraph.<init>(ReactionInstanceGraph.java:64)
    at org.lflang.generator.ReactorInstance.assignLevels(ReactorInstance.java:193)
    at org.lflang.generator.ReactorInstance.getCycles(ReactorInstance.java:272)
    at org.lflang.ModelInfo.update(ModelInfo.java:120)
    at org.lflang.validation.LFValidator.checkModel(LFValidator.java:589)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
    at java.base/java.lang.reflect.Method.invoke(Method.java:578)
    at org.eclipse.xtext.validation.AbstractDeclarativeValidator$MethodWrapper.invoke(AbstractDeclarativeValidator.java:129)
    at org.eclipse.xtext.validation.AbstractDeclarativeValidator.internalValidate(AbstractDeclarativeValidator.java:337)
    at org.eclipse.xtext.validation.AbstractInjectableValidator.validate(AbstractInjectableValidator.java:72)
    at org.eclipse.xtext.validation.CompositeEValidator.validate(CompositeEValidator.java:151)
    at org.eclipse.emf.ecore.util.Diagnostician.doValidate(Diagnostician.java:299)
    at org.eclipse.emf.ecore.util.Diagnostician.validate(Diagnostician.java:245)
    at org.eclipse.xtext.validation.CancelableDiagnostician.validate(CancelableDiagnostician.java:41)
    at org.eclipse.emf.ecore.util.Diagnostician.validate(Diagnostician.java:200)
    at org.eclipse.emf.ecore.util.Diagnostician.validate(Diagnostician.java:142)
    at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:147)
    at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:125)
    at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:91)
    at org.lflang.cli.CliBase.validateResource(CliBase.java:256)
    at org.lflang.cli.Lfc.invokeGenerator(Lfc.java:173)
    at org.lflang.cli.Lfc.doRun(Lfc.java:150)
    at org.lflang.cli.CliBase.run(CliBase.java:145)
    at picocli.CommandLine.executeUserObject(CommandLine.java:2026)
    at picocli.CommandLine.access$1500(CommandLine.java:148)
    at picocli.CommandLine$RunLast.executeUserObjectOfLastSubcommandWithSameParent(CommandLine.java:2461)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2453)
    at picocli.CommandLine$RunLast.handle(CommandLine.java:2415)
    at picocli.CommandLine$AbstractParseResultHandler.execute(CommandLine.java:2273)
    at picocli.CommandLine$RunLast.execute(CommandLine.java:2417)
    at picocli.CommandLine.execute(CommandLine.java:2170)
    at org.lflang.cli.CliBase.doExecute(CliBase.java:117)
    at org.lflang.cli.CliBase.cliMain(CliBase.java:109)
    at org.lflang.cli.Lfc.main(Lfc.java:137)
    at org.lflang.cli.Lfc.main(Lfc.java:127)
lfc: error: Error executing EValidator

lfc: fatal error: Aborting due to 1 previous error.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':cli:lfc:run'.
> Process 'command '/usr/lib/jvm/java-19-openjdk-amd64/bin/java'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
20 actionable tasks: 1 executed, 19 up-to-date
ninja: build stopped: subcommand failed.

In trying to figure out my problem, I'm now studying the (for a novice rather cryptic) code at org.lflang.generator.MixedRadixInt.<init>(MixedRadixInt.java:74).

SOLVED: in the parameter list maxn_B: int = 0 wasn't updated to > 0. With a value > 0 everything runs fine. Would an lfc check on non-zero bank sizes be helpful? (Otherwise, sorry for having claimed your time for this).

edwardalee commented 1 year ago

Again, it would be useful to have the full program. This looks like a rather unfriendly response to a programming error, so it's worth catching it in a better way.

stustd commented 1 year ago

The full program is quite involved (5000+ LOC) but the problem is replicated by setting maxn_B:int = 0 in your example program (renamed to problem.lf):


target C                                                                                                                                                           
reactor A {                                                                                                                                                        
input startup_pre:int                                                                                                                                          
}                                                                                                                                                                  
reactor B {                                                                                                                                                        
input startup_pre:int                                                                                                                                          
}                                                                                                                                                                  
main reactor problem(maxn_A:int = 2, maxn_B:int = 0) {                // Notice the "= 0"                                                                                             
a = new[maxn_A] A();                                                                                                                                             
b = new[maxn_B] B();                                                                                                                                             

reaction(startup) -> a.startup_pre, b.startup_pre
{=
for (int i=0; imaxn_A; i++)
lf_set(a[i].startup_pre, 0);
for (int i=0; imaxn_B; i++)
lf_set(b[i].startup_pre, 0);
=}
}

... causing `lfc` to produce the error:

stustd@ax010:[multi-bank_multi-output]: lfc problem.lf

Task :cli:lfc:run FAILED lfc: warning: File 'problem.lf' is not located in an 'src' directory. lfc: warning: Adopting the current working directory as the package root. Generating code for: file:/tmp/multi-bank_multi-output/problem.lf **** mode: STANDALONE **** generated sources: /tmp/multi-bank_multi-output/src-gen/problem Cleaning /tmp/multi-bank_multi-output/include Cleaning /tmp/multi-bank_multi-output/src-gen/problem/build --- Current working directory: /tmp/multi-bank_multi-output/src-gen/problem/build --- Executing command: cmake -DLF_REACTION_GRAPH_BREADTH=1 -DLF_THREADED=1 -DNUMBER_OF_WORKERS=0 -DSCHEDULER=NP -DLOG_LEVEL=2 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/tmp/multi-bank_multi-output -DCMAKE_INSTALL_BINDIR=bin -DLF_FILE_SEPARATOR="/" -DLF_SOURCE_DIRECTORY="/tmp/multi-bank_multi-output" -DLF_PACKAGE_DIRECTORY="/tmp/multi-bank_multi-output/." /tmp/multi-bank_multi-output/src-gen/problem -- The C compiler identification is GNU 12.1.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Including sources for threaded runtime with 0 worker(s) with scheduler=NP and tracing=. -- Including the following sources: tag.c, port.c, mixed_radix.c, reactor_common.c, lf_token.c, reactor_threaded.c, scheduler_adaptive.c, scheduler_GEDF_NP_CI.c, scheduler_GEDF_NP.c, scheduler_NP.c, scheduler_PEDF_NP.c, scheduler_sync_tag_advance.c, watchdog.c, vector.c, pqueue.c, util.c, semaphore.c, hashset.c, hashset_itr.c, modes.c, lf_unix_clock_support.c, lf_unix_syscall_support.c, lf_linux_support.c, lf_macos_support.c, lf_windows_support.c, lf_nrf52_support.c, lf_zephyr_support.c -- Performing Test CMAKE_HAVE_LIBC_PTHREAD -- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success -- Found Threads: TRUE
-- Applying preprocessor definitions... -- LF_REACTION_GRAPH_BREADTH=1 -- LF_THREADED=1 -- LOG_LEVEL=2 -- NUMBER_OF_WORKERS=0 -- SCHEDULER=NP -- LF_SOURCE_DIRECTORY="/tmp/multi-bank_multi-output" -- LF_PACKAGE_DIRECTORY="/tmp/multi-bank_multi-output/." -- LF_FILE_SEPARATOR="/" -- Configuring done (0.3s) -- Generating done (0.0s) -- Build files have been written to: /tmp/multi-bank_multi-output/src-gen/problem/build --- Current working directory: /tmp/multi-bank_multi-output/src-gen/problem/build --- Executing command: cmake --build . --target install --parallel 16 --config Release [ 17%] Building C object core/CMakeFiles/core.dir/threaded/scheduler_GEDF_NP_CI.c.o [ 17%] Building C object core/CMakeFiles/core.dir/mixed_radix.c.o [ 17%] Building C object core/CMakeFiles/core.dir/tag.c.o [ 17%] Building C object core/CMakeFiles/core.dir/port.c.o [ 17%] Building C object core/CMakeFiles/core.dir/lf_token.c.o [ 20%] Building C object core/CMakeFiles/core.dir/reactor_common.c.o [ 20%] Building C object core/CMakeFiles/core.dir/threaded/reactor_threaded.c.o [ 23%] Building C object core/CMakeFiles/core.dir/threaded/scheduler_NP.c.o [ 29%] Building C object core/CMakeFiles/core.dir/threaded/scheduler_PEDF_NP.c.o [ 29%] Building C object core/CMakeFiles/core.dir/threaded/scheduler_adaptive.c.o [ 32%] Building C object core/CMakeFiles/core.dir/threaded/scheduler_GEDF_NP.c.o [ 35%] Building C object core/CMakeFiles/core.dir/threaded/scheduler_sync_tag_advance.c.o [ 38%] Building C object core/CMakeFiles/core.dir/threaded/watchdog.c.o [ 41%] Building C object core/CMakeFiles/core.dir/utils/vector.c.o [ 44%] Building C object core/CMakeFiles/core.dir/utils/pqueue.c.o [ 47%] Building C object core/CMakeFiles/core.dir/utils/util.c.o [ 55%] Building C object core/CMakeFiles/core.dir/utils/semaphore.c.o [ 55%] Building C object core/CMakeFiles/core.dir/utils/hashset/hashset_itr.c.o [ 55%] Building C object core/CMakeFiles/core.dir/utils/hashset/hashset.c.o [ 58%] Building C object core/CMakeFiles/core.dir/modal_models/modes.c.o [ 61%] Building C object core/CMakeFiles/core.dir/platform/lf_unix_clock_support.c.o [ 64%] Building C object core/CMakeFiles/core.dir/platform/lf_unix_syscall_support.c.o [ 67%] Building C object core/CMakeFiles/core.dir/platform/lf_linux_support.c.o [ 73%] Building C object core/CMakeFiles/core.dir/platform/lf_macos_support.c.o [ 73%] Building C object core/CMakeFiles/core.dir/platform/lf_windows_support.c.o [ 76%] Building C object core/CMakeFiles/core.dir/platform/lf_nrf52_support.c.o [ 79%] Building C object core/CMakeFiles/core.dir/platform/lf_zephyr_support.c.o [ 82%] Linking C static library libcore.a /tmp/multi-bank_multi-output/src-gen/problem/problem.c: In function ‘_lf_initialize_trigger_objects’: [ 82%] Built target core /tmp/multi-bank_multi-output/src-gen/problem/problem.c:69:16: error: size of array ‘problem_b_self’ is negative [ 97%] Building C object CMakeFiles/problem.dir/_a.c.o [ 97%] Building C object CMakeFiles/problem.dir/problem.c.o [ 97%] Bui 69 | _b_self_t* problem_b_slding C object CMakeFiles/problem.dir/lib/schedule.c.o [ 97%] Building C object CMakeFiles/problem.dir/_b.c.o [ 97%] Building C object CMakeFiles/problem.dir/_problem_main.c.o elf[-1]; | ^~~~~~ gmake[2]: [CMakeFiles/problem.dir/build.make:132: CMakeFiles/problem.dir/problem.c.o] Error 1 gmake[2]: Waiting for unfinished jobs.... gmake[1]: [CMakeFiles/Makefile2:100: CMakeFiles/problem.dir/all] Error 2 gmake: [Makefile:136: all] Error 2 lfc: error: failed with error code 2

lfc: fatal error: Aborting due to 1 previous error.

FAILURE: Build failed with an exception.

BUILD FAILED in 2s 20 actionable tasks: 1 executed, 19 up-to-date


Although producing an error, it neither shows a java stacktrace nor indicating the `lfc: error: Error executing EValidator`. (the original problem is generated in Jetbrain's CLion IDE, the `problem.lf` compilation is from the cmdline).
Hope this helps; can always provide more information.
edwardalee commented 1 year ago

Ah, interesting. I've marked this as a bug and assigned it to myself. We obviously don't have any test cases for zero-width banks. These should either be prohibited in the validator or handled gracefully.

stustd commented 1 year ago

I'm honored to make my little contributions to LF technology this way.