diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 33c447673d..83c704c4f6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -42,6 +42,7 @@ jobs: repo_token: "${{ secrets.envPAT }}" automatic_release_tag: 'nightly' prerelease: true + title: "Lingua Franca Nightly" files: | org.lflang.rca/target/products/*.tar.gz org.lflang.rca/target/products/*.zip diff --git a/CHANGELOG.md b/CHANGELOG.md index 77cc7f7001..d9ac0fa00e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,105 @@ # Changelog +## [v0.3.0](https://github.com/lingua-franca/lingua-franca/tree/v0.3.0) (2022-07-22) + +**Highlights**\n\nThis release adds broader support for methods (C and Python), syntax for annotations similar those in [Java](https://en.wikipedia.org/wiki/Java_annotation), an adaptive scheduler in the C runtime, and a new `platform` target property to furnish support for specialized execution platforms. + +[Full Changelog](https://github.com/lingua-franca/lingua-franca/compare/v0.2.1...v0.3.0) + +**🚀 New Features** + +- Support for C methods [\#1215](https://github.com/lf-lang/lingua-franca/pull/1215) ([edwardalee](https://github.com/edwardalee)) +- Support for Python methods [\#1230](https://github.com/lf-lang/lingua-franca/pull/1230) ([Soroosh129](https://github.com/Soroosh129)) +- Adaptive scheduler for C target [\#1207](https://github.com/lf-lang/lingua-franca/pull/1207) ([petervdonovan](https://github.com/petervdonovan)) +- Platform target property [\#1246](https://github.com/lf-lang/lingua-franca/pull/1246) ([Soroosh129](https://github.com/Soroosh129)) +- Annotations [\#977](https://github.com/lf-lang/lingua-franca/pull/977) ([lsk567](https://github.com/lsk567)) + +**✨ Enhancements** + +- New handling of startup/shutdown/reset reactions in modes [\#1169](https://github.com/lf-lang/lingua-franca/pull/1169) ([a-sr](https://github.com/a-sr)) +- Diagram layout improvements [\#1206](https://github.com/lf-lang/lingua-franca/pull/1206) ([a-sr](https://github.com/a-sr)) +- History transitions are now indicated using the `history` keyword [\#1247](https://github.com/lf-lang/lingua-franca/pull/1247) ([a-sr](https://github.com/a-sr)) +- Compile warnings are fixed and clang-tidy is ran when compiling C++ tests in CI [\#1259](https://github.com/lf-lang/lingua-franca/pull/1259) ([cmnrd](https://github.com/cmnrd)) +- New design for reset symbols in diagrams [\#1241](https://github.com/lf-lang/lingua-franca/pull/1241) ([a-sr](https://github.com/a-sr)) +- Improvements of mode diagram layout [\#1282](https://github.com/lf-lang/lingua-franca/pull/1282) ([a-sr](https://github.com/a-sr)) +- [cpp] Additional checks to determine whether a subdirectory should be included in compilation [\#1283](https://github.com/lf-lang/lingua-franca/pull/1283) ([cmnrd](https://github.com/cmnrd)) +- [cpp] CLI parser errors are caught and a print help message is printed [\#1288](https://github.com/lf-lang/lingua-franca/pull/1288) ([cmnrd](https://github.com/cmnrd)) +- [ts] Handling of physical action-triggered outputs in federated execution (previously handled by TAN - Time Advance Notice) [\#1275](https://github.com/lf-lang/lingua-franca/pull/1275) ([hokeun](https://github.com/hokeun)) + +**🔧 Fixes** + +- TAN messages no longer used and in-transit messages recorded in the RTI [\#1074](https://github.com/lf-lang/lingua-franca/pull/1074) ([Soroosh129](https://github.com/Soroosh129)) +- [c] A deadline of `0` is no longer interpreted as an _absent_ deadline but one that can never be met [\#1217](https://github.com/lf-lang/lingua-franca/pull/1217) ([billy-bao](https://github.com/billy-bao)) +- Fix for deadlock in federated execution [\#1189](https://github.com/lf-lang/lingua-franca/pull/1189) ([Soroosh129](https://github.com/Soroosh129)) +- [c] Removal of STP violation inheritance mechanism [\#1251](https://github.com/lf-lang/lingua-franca/pull/1251) ([Soroosh129](https://github.com/Soroosh129)) +- Fix for properly handling paths with spaces in lfc launch script [\#1257](https://github.com/lf-lang/lingua-franca/pull/1257) ([cmnrd](https://github.com/cmnrd)) +- Fix that repairs the ability to execute commands with Bash in case command is not found on path [\#1265](https://github.com/lf-lang/lingua-franca/pull/1265) ([petervdonovan](https://github.com/petervdonovan)) +- Fix to not include downstream reactions in highlighted cycles [\#1270](https://github.com/lf-lang/lingua-franca/pull/1270) ([edwardalee](https://github.com/edwardalee)) +- Correction of misplacement of self loops in diagrams [\#1274](https://github.com/lf-lang/lingua-franca/pull/1274) ([a-sr](https://github.com/a-sr)) +- Fix that silences spurious error messages from Pylint [\#1280](https://github.com/lf-lang/lingua-franca/pull/1280) ([petervdonovan](https://github.com/petervdonovan)) +- Patch that avoids NullPointerException in `CompileActionHandler` [\#1267](https://github.com/lf-lang/lingua-franca/pull/1267) ([lhstrh](https://github.com/lhstrh)) +- Do not minimize the shadow jar [\#1285](https://github.com/lf-lang/lingua-franca/pull/1285) ([cmnrd](https://github.com/cmnrd)) +- Fix for `ASTUtils.width()` returnning `-1` even when the width can be inferred from connections [\#1287](https://github.com/lf-lang/lingua-franca/pull/1287) ([hokeun](https://github.com/hokeun)) +- Fix banks of modal reactors [\#1279](https://github.com/lf-lang/lingua-franca/pull/1279) ([a-sr](https://github.com/a-sr)) +- Ensure that reactions consistently trigger banks [\#1289](https://github.com/lf-lang/lingua-franca/pull/1289) ([edwardalee](https://github.com/edwardalee)) +- Cpp: fix triggering of reactions in multiple nested reactors [\#1286](https://github.com/lf-lang/lingua-franca/pull/1286) ([cmnrd](https://github.com/cmnrd)) +- Fix to ensure the ordering of reactions relative to modes is correct [\#1303](https://github.com/lf-lang/lingua-franca/pull/1303) ([a-sr](https://github.com/a-sr)) + +**🚧 Maintenance and Refactoring** + +- Machine-applicable refactorings [\#1224](https://github.com/lf-lang/lingua-franca/pull/1224) ([petervdonovan](https://github.com/petervdonovan)) +- Inclusion of reactor-rs as a submodule [\#1296](https://github.com/lf-lang/lingua-franca/pull/1296) ([cmnrd](https://github.com/cmnrd)) + +**⬆️ Updated Dependencies** + +- Upgrade to Xtext 2.27.0 and Lsp4j 0.14.0 [\#1234](https://github.com/lf-lang/lingua-franca/pull/1234) ([lhstrh](https://github.com/lhstrh)) +- Bump Klighd version to 2.2 [\#1297](https://github.com/lf-lang/lingua-franca/pull/1297) ([a-sr](https://github.com/a-sr)) + + +### Submodule [lf-lang/reactor-c](http://github.com/lf-lang/reactor-c) + +**✨ Enhancements** + +- New handling of startup/shutdown/reset reactions in modes [\#79](https://github.com/lf-lang/reactor-c/pull/79) ([a-sr](https://github.com/a-sr)) +- STP violations now result in error messages [\#82](https://github.com/lf-lang/reactor-c/pull/82) ([edwardalee](https://github.com/edwardalee)) +- Removal of TAN messages and new capability to record in-transit messages in the RTI [\#61](https://github.com/lf-lang/reactor-c/pull/61) ([Soroosh129](https://github.com/Soroosh129)) + +**🔧 Fixes** + +- Patch to ensure that deadlines with zero delay are never met [\#86](https://github.com/lf-lang/reactor-c/pull/86) ([billy-bao](https://github.com/billy-bao)) + + +### Submodule [lf-lang/reactor-cpp](http://github.com/lf-lang/reactor-cpp) + +**✨ Enhancements** + +- Nix tooling expanded with cachegrind, callgrind, and memtest [\#13](https://github.com/lf-lang/reactor-cpp/pull/13) ([revol-xut](https://github.com/revol-xut)) +- Relocation of `unistd.h` and `execinfo.h` includes to void namespace pollution [\#14](https://github.com/lf-lang/reactor-cpp/pull/14) ([erlingrj](https://github.com/erlingrj)) +- Fixes that addresses warnings reported by clang-tidy [\#15](https://github.com/lf-lang/reactor-cpp/pull/15) ([cmnrd](https://github.com/cmnrd)) +- Optimized port communication for scalar types [\#17](https://github.com/lf-lang/reactor-cpp/pull/17) ([cmnrd](https://github.com/cmnrd)) + +**🔧 Fixes** + +- Fix to allow ports to have both triggers and further bindings [\#16](https://github.com/lf-lang/reactor-cpp/pull/16) ([cmnrd](https://github.com/cmnrd)) + + +### Submodule [lf-lang/reactor-rs](http://github.com/lf-lang/reactor-rs) + +- No Changes + + +### Submodule [lf-lang/reactor-ts](http://github.com/lf-lang/reactor-ts) + +**🚀 New Features** + +- JSON serialization [\#99](https://github.com/lf-lang/reactor-ts/pull/99) ([CloverCho](https://github.com/CloverCho)) + +**🧪 Tests** + +- Increased coverage of unit tests in bank.ts, multiport.ts and port.ts [\#100](https://github.com/lf-lang/reactor-ts/pull/100) ([goekberk](https://github.com/goekberk)) + + + ## [v0.2.1](https://github.com/lf-lang/lingua-franca/tree/v0.2.1) (2022-06-01) **Highlights:** diff --git a/gradle.properties b/gradle.properties index 380874839b..0bb26e7808 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ [header] group=org.lflang -version=0.2.2-SNAPSHOT +version=0.3.1-SNAPSHOT [versions] commonsCliVersion=1.4 diff --git a/oomph/LinguaFranca.setup b/oomph/LinguaFranca.setup index 5a3c22d492..ef668b3277 100644 --- a/oomph/LinguaFranca.setup +++ b/oomph/LinguaFranca.setup @@ -357,7 +357,7 @@ + url="https://kieler.github.io/KLighD/v2.2.0/"/> ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.diagram diff --git a/org.lflang.diagram/src/org/lflang/diagram/synthesis/SynthesisRegistration.java b/org.lflang.diagram/src/org/lflang/diagram/synthesis/SynthesisRegistration.java index 480c2b27b9..50b42aeaaf 100644 --- a/org.lflang.diagram/src/org/lflang/diagram/synthesis/SynthesisRegistration.java +++ b/org.lflang.diagram/src/org/lflang/diagram/synthesis/SynthesisRegistration.java @@ -1,13 +1,17 @@ package org.lflang.diagram.synthesis; -import de.cau.cs.kieler.klighd.IKlighdStartupHook; -import de.cau.cs.kieler.klighd.KlighdDataManager; import org.lflang.diagram.synthesis.action.CollapseAllReactorsAction; import org.lflang.diagram.synthesis.action.ExpandAllReactorsAction; import org.lflang.diagram.synthesis.action.FilterCycleAction; import org.lflang.diagram.synthesis.action.MemorizingExpandCollapseAction; import org.lflang.diagram.synthesis.action.ShowCycleAction; import org.lflang.diagram.synthesis.postprocessor.ReactionPortAdjustment; +import org.lflang.diagram.synthesis.styles.LinguaFrancaShapeExtensions; +import org.lflang.diagram.synthesis.styles.LinguaFrancaStyleExtensions; +import org.lflang.diagram.synthesis.util.NamedInstanceUtil; + +import de.cau.cs.kieler.klighd.IKlighdStartupHook; +import de.cau.cs.kieler.klighd.KlighdDataManager; /** * Registration of all diagram synthesis related classes in Klighd. @@ -32,6 +36,17 @@ public void execute() { // Style Mod reg.registerStyleModifier(ReactionPortAdjustment.ID, new ReactionPortAdjustment()); + + // Blacklist LF-specific properties that should be removed when a diagram is sent from the diagram server to a client. + reg.registerBlacklistedProperty(FilterCycleAction.FILTER_BUTTON); + reg.registerBlacklistedProperty(LinguaFrancaSynthesis.REACTOR_HAS_BANK_PORT_OFFSET); + reg.registerBlacklistedProperty(LinguaFrancaSynthesis.REACTOR_INPUT); + reg.registerBlacklistedProperty(LinguaFrancaSynthesis.REACTOR_OUTPUT); + reg.registerBlacklistedProperty(LinguaFrancaSynthesis.REACTION_SPECIAL_TRIGGER); + reg.registerBlacklistedProperty(ReactionPortAdjustment.PROCESSED); + reg.registerBlacklistedProperty(LinguaFrancaShapeExtensions.REACTOR_CONTENT_CONTAINER); + reg.registerBlacklistedProperty(LinguaFrancaStyleExtensions.LABEL_PARENT_BACKGROUND); + reg.registerBlacklistedProperty(NamedInstanceUtil.LINKED_INSTANCE); // Very important since its values can not be synthesized easily! } } diff --git a/org.lflang.diagram/src/org/lflang/diagram/synthesis/action/FilterCycleAction.java b/org.lflang.diagram/src/org/lflang/diagram/synthesis/action/FilterCycleAction.java index 3e58f74cf0..d5c2735181 100644 --- a/org.lflang.diagram/src/org/lflang/diagram/synthesis/action/FilterCycleAction.java +++ b/org.lflang.diagram/src/org/lflang/diagram/synthesis/action/FilterCycleAction.java @@ -59,9 +59,9 @@ public class FilterCycleAction extends AbstractAction { private static final WeakHashMap FILTERING_STATES = new WeakHashMap<>(); /** - * Property to mark filter button + * INTERNAL property to mark filter button. */ - private static final Property FILTER_BUTTON = new Property<>("org.lflang.diagram.synthesis.action.cyclefilter.button", false); + public static final Property FILTER_BUTTON = new Property<>("org.lflang.diagram.synthesis.action.cyclefilter.button", false); @Override public IAction.ActionResult execute(final IAction.ActionContext context) { diff --git a/org.lflang.diagram/src/org/lflang/diagram/synthesis/postprocessor/ReactionPortAdjustment.java b/org.lflang.diagram/src/org/lflang/diagram/synthesis/postprocessor/ReactionPortAdjustment.java index e605493cc6..fdf5d57468 100644 --- a/org.lflang.diagram/src/org/lflang/diagram/synthesis/postprocessor/ReactionPortAdjustment.java +++ b/org.lflang.diagram/src/org/lflang/diagram/synthesis/postprocessor/ReactionPortAdjustment.java @@ -55,7 +55,10 @@ public class ReactionPortAdjustment implements IStyleModifier { public static final String ID = "org.lflang.diagram.synthesis.postprocessor.ReactionPortAdjustment"; - private static final Property PROCESSED = new Property<>("org.lflang.diagram.synthesis.postprocessor.reaction.ports.processed", false); + /** + * INTERNAL property to mark node as processed. + */ + public static final Property PROCESSED = new Property<>("org.lflang.diagram.synthesis.postprocessor.reaction.ports.processed", false); @Extension private KGraphFactory _kGraphFactory = KGraphFactory.eINSTANCE; diff --git a/org.lflang.diagram/src/org/lflang/diagram/synthesis/styles/LinguaFrancaStyleExtensions.java b/org.lflang.diagram/src/org/lflang/diagram/synthesis/styles/LinguaFrancaStyleExtensions.java index e1e10049c7..4659251299 100644 --- a/org.lflang.diagram/src/org/lflang/diagram/synthesis/styles/LinguaFrancaStyleExtensions.java +++ b/org.lflang.diagram/src/org/lflang/diagram/synthesis/styles/LinguaFrancaStyleExtensions.java @@ -67,7 +67,10 @@ @ViewSynthesisShared public class LinguaFrancaStyleExtensions extends AbstractSynthesisExtensions { - private static final Property LABEL_PARENT_BACKGROUND = new Property<>( + /** + * INTERNAL property to communicate a node's background color. + */ + public static final Property LABEL_PARENT_BACKGROUND = new Property<>( "org.lflang.linguafranca.diagram.synthesis.styles.label.parent.background", Colors.WHITE); @Inject diff --git a/org.lflang.ide/META-INF/MANIFEST.MF b/org.lflang.ide/META-INF/MANIFEST.MF index 8805747276..d31a90e3d8 100644 --- a/org.lflang.ide/META-INF/MANIFEST.MF +++ b/org.lflang.ide/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: org.lflang.ide Bundle-ManifestVersion: 2 Bundle-Name: Lingua Franca IDE Bundle-Vendor: University of California, Berkeley -Bundle-Version: 0.2.2.qualifier +Bundle-Version: 0.3.1.qualifier Bundle-SymbolicName: org.lflang.ide; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.lflang, diff --git a/org.lflang.ide/pom.xml b/org.lflang.ide/pom.xml index 5a5559fc0d..9ba35c93e1 100644 --- a/org.lflang.ide/pom.xml +++ b/org.lflang.ide/pom.xml @@ -7,7 +7,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.ide diff --git a/org.lflang.lds/pom.xml b/org.lflang.lds/pom.xml index a0112169f7..b23e4d43ac 100644 --- a/org.lflang.lds/pom.xml +++ b/org.lflang.lds/pom.xml @@ -7,7 +7,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.lds diff --git a/org.lflang.lfc/src/org/lflang/lfc/Main.java b/org.lflang.lfc/src/org/lflang/lfc/Main.java index e7e44ac747..179f6e1fa7 100644 --- a/org.lflang.lfc/src/org/lflang/lfc/Main.java +++ b/org.lflang.lfc/src/org/lflang/lfc/Main.java @@ -52,7 +52,7 @@ public class Main { /// current lfc version as printed by --version - private static final String VERSION = "0.2.2-SNAPSHOT"; + private static final String VERSION = "0.3.1-SNAPSHOT"; /** * Object for interpreting command line arguments. diff --git a/org.lflang.product/META-INF/MANIFEST.MF b/org.lflang.product/META-INF/MANIFEST.MF index e5cb24a684..80749becbd 100644 --- a/org.lflang.product/META-INF/MANIFEST.MF +++ b/org.lflang.product/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Lingua Franca Product Bundle-SymbolicName: org.lflang.product;singleton:=true -Bundle-Version: 0.2.2.qualifier +Bundle-Version: 0.3.1.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Automatic-Module-Name: org.lflang.product Bundle-Vendor: University of California, Berkeley diff --git a/org.lflang.product/plugin.xml b/org.lflang.product/plugin.xml index b6cae59341..bae5ff15cd 100644 --- a/org.lflang.product/plugin.xml +++ b/org.lflang.product/plugin.xml @@ -34,7 +34,7 @@ + value="Version: 0.3.1-SNAPSHOT. Epoch is an IDE for Lingua Franca, a polyglot coordination language for building concurrent and distributed software that delivers predictable and reproducible reactive behavior. Visit our GitHub: https://repo.lf-lang.org/. This software is licensed under the BSD 2-Clause License. Copyright © 2019-2022, the Lingua Franca contributors. All rights reserved."> ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.product diff --git a/org.lflang.product/splash.bmp b/org.lflang.product/splash.bmp index 0e27b6e8fb..7f77dadb29 100644 Binary files a/org.lflang.product/splash.bmp and b/org.lflang.product/splash.bmp differ diff --git a/org.lflang.rca/lflang.product b/org.lflang.rca/lflang.product index 41a1616878..b2ffa65e7b 100644 --- a/org.lflang.rca/lflang.product +++ b/org.lflang.rca/lflang.product @@ -1,7 +1,7 @@ - + diff --git a/org.lflang.rca/pom.xml b/org.lflang.rca/pom.xml index 608df40740..28c22582bc 100644 --- a/org.lflang.rca/pom.xml +++ b/org.lflang.rca/pom.xml @@ -8,10 +8,10 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.rca eclipse-repository Lingua Franca Epoch IDE diff --git a/org.lflang.sdk/feature.xml b/org.lflang.sdk/feature.xml index a54cd764d3..5aaccb7b0d 100644 --- a/org.lflang.sdk/feature.xml +++ b/org.lflang.sdk/feature.xml @@ -2,7 +2,7 @@ + version="0.3.1.qualifier"> diff --git a/org.lflang.sdk/pom.xml b/org.lflang.sdk/pom.xml index 9e9c342ebf..d4766b03f3 100644 --- a/org.lflang.sdk/pom.xml +++ b/org.lflang.sdk/pom.xml @@ -7,7 +7,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.sdk diff --git a/org.lflang.targetplatform/org.lflang.targetplatform.target b/org.lflang.targetplatform/org.lflang.targetplatform.target index 3e18cdeb1b..9e9cbcb290 100644 --- a/org.lflang.targetplatform/org.lflang.targetplatform.target +++ b/org.lflang.targetplatform/org.lflang.targetplatform.target @@ -68,7 +68,7 @@ - + diff --git a/org.lflang.targetplatform/pom.xml b/org.lflang.targetplatform/pom.xml index dc439fcc21..d736f7f607 100644 --- a/org.lflang.targetplatform/pom.xml +++ b/org.lflang.targetplatform/pom.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.targetplatform eclipse-target-definition Lingua Franca Target Platform @@ -12,7 +12,7 @@ org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT ../pom.xml diff --git a/org.lflang.tests/META-INF/MANIFEST.MF b/org.lflang.tests/META-INF/MANIFEST.MF index 6955f40ff5..1e0539c0f5 100644 --- a/org.lflang.tests/META-INF/MANIFEST.MF +++ b/org.lflang.tests/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: org.lflang.tests Bundle-ManifestVersion: 2 Bundle-Name: Lingua Franca Tests Bundle-Vendor: University of California, Berkeley -Bundle-Version: 0.2.2.qualifier +Bundle-Version: 0.3.1.qualifier Bundle-SymbolicName: org.lflang.tests; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.lflang, diff --git a/org.lflang.tests/pom.xml b/org.lflang.tests/pom.xml index e5082ae5f3..66854d4996 100644 --- a/org.lflang.tests/pom.xml +++ b/org.lflang.tests/pom.xml @@ -6,7 +6,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.tests diff --git a/org.lflang.ui.tests/META-INF/MANIFEST.MF b/org.lflang.ui.tests/META-INF/MANIFEST.MF index 715a4b88c7..d65c33ed96 100644 --- a/org.lflang.ui.tests/META-INF/MANIFEST.MF +++ b/org.lflang.ui.tests/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: org.lflang.ui.tests Bundle-ManifestVersion: 2 Bundle-Name: Lingua Franca UI Tests Bundle-Vendor: University of California, Berkeley -Bundle-Version: 0.2.2.qualifier +Bundle-Version: 0.3.1.qualifier Bundle-SymbolicName: org.lflang.ui.tests; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.lflang.ui, diff --git a/org.lflang.ui.tests/pom.xml b/org.lflang.ui.tests/pom.xml index f0e9399e53..b2ee9d321c 100644 --- a/org.lflang.ui.tests/pom.xml +++ b/org.lflang.ui.tests/pom.xml @@ -6,7 +6,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.ui.tests diff --git a/org.lflang.ui/META-INF/MANIFEST.MF b/org.lflang.ui/META-INF/MANIFEST.MF index cfa1aa2256..08371cdbf4 100644 --- a/org.lflang.ui/META-INF/MANIFEST.MF +++ b/org.lflang.ui/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: org.lflang.ui Bundle-ManifestVersion: 2 Bundle-Name: Lingua Franca UI Bundle-Vendor: University of California, Berkeley -Bundle-Version: 0.2.2.qualifier +Bundle-Version: 0.3.1.qualifier Bundle-SymbolicName: org.lflang.ui; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.lflang, diff --git a/org.lflang.ui/pom.xml b/org.lflang.ui/pom.xml index 1aef29124e..f9fb56e16b 100644 --- a/org.lflang.ui/pom.xml +++ b/org.lflang.ui/pom.xml @@ -7,7 +7,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.ui diff --git a/org.lflang.updatesite/pom.xml b/org.lflang.updatesite/pom.xml index 98e6928719..cc0103f430 100644 --- a/org.lflang.updatesite/pom.xml +++ b/org.lflang.updatesite/pom.xml @@ -7,7 +7,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang.updatesite diff --git a/org.lflang/META-INF/MANIFEST.MF b/org.lflang/META-INF/MANIFEST.MF index a368d1e992..dc9b84caf5 100644 --- a/org.lflang/META-INF/MANIFEST.MF +++ b/org.lflang/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: org.lflang Bundle-ManifestVersion: 2 Bundle-Name: Lingua Franca Language Implementation Bundle-Vendor: University of California, Berkeley -Bundle-Version: 0.2.2.qualifier +Bundle-Version: 0.3.1.qualifier Bundle-SymbolicName: org.lflang; singleton:=true Bundle-ActivationPolicy: lazy Require-Bundle: org.eclipse.xtext, diff --git a/org.lflang/pom.xml b/org.lflang/pom.xml index 4ead38db21..c57a8a57bd 100644 --- a/org.lflang/pom.xml +++ b/org.lflang/pom.xml @@ -7,7 +7,7 @@ ../pom.xml org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT org.lflang diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 4d300d934e..0a197940fa 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 4d300d934e3e52b79592633cc9bbffac74376f33 +Subproject commit 0a197940fae3194145eae136e1726d6a26c27b57 diff --git a/org.lflang/src/lib/py/reactor-c-py b/org.lflang/src/lib/py/reactor-c-py index 64292fa820..61433a39c9 160000 --- a/org.lflang/src/lib/py/reactor-c-py +++ b/org.lflang/src/lib/py/reactor-c-py @@ -1 +1 @@ -Subproject commit 64292fa820f6fdd86226cd3016c4afa802b87541 +Subproject commit 61433a39c98d6cdec3e317ce3692e98abadcc5fc diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index 6f8ca4dbfa..ec9f8328a1 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -62,7 +62,6 @@ import org.lflang.lf.Action; import org.lflang.lf.ActionOrigin; import org.lflang.lf.Assignment; -import org.lflang.lf.Attribute; import org.lflang.lf.Code; import org.lflang.lf.Connection; import org.lflang.lf.Element; @@ -726,7 +725,7 @@ public static LinkedHashSet superClasses(Reactor reactor) { * @param The type of elements to collect (e.g., Port, Timer, etc.) * @return A list of all elements of type T found */ - public static List collectElements(Reactor definition, EStructuralFeature feature) { + public static List collectElements(Reactor definition, EStructuralFeature feature) { return ASTUtils.collectElements(definition, feature, true, true); } @@ -741,7 +740,7 @@ public static List collectElements(Reactor definition, EStructuralFeature * @return A list of all elements of type T found */ @SuppressWarnings("unchecked") - public static List collectElements(Reactor definition, EStructuralFeature feature, boolean includeSuperClasses, boolean includeModes) { + public static List collectElements(Reactor definition, EStructuralFeature feature, boolean includeSuperClasses, boolean includeModes) { List result = new ArrayList<>(); if (includeSuperClasses) { @@ -761,12 +760,64 @@ public static List collectElements(Reactor definition, EStructuralFeature var modeFeature = reactorModeFeatureMap.get(feature); // Add elements of elements defined in modes. for (Mode mode : includeSuperClasses ? allModes(definition) : definition.getModes()) { - result.addAll((EList) mode.eGet(modeFeature)); + insertModeElementsAtTextualPosition(result, (EList) mode.eGet(modeFeature), mode); } } return result; } + + /** + * Adds the elements into the given list at a location matching to their textual position. + * + * When creating a flat view onto reactor elements including modes, the final list must be ordered according + * to the textual positions. + * + * Example: + * reactor R { + * reaction // -> is R.reactions[0] + * mode M { + * reaction // -> is R.mode[0].reactions[0] + * reaction // -> is R.mode[0].reactions[1] + * } + * reaction // -> is R.reactions[1] + * } + * In this example, it is important that the reactions in the mode are inserted between the top-level + * reactions to retain the correct global reaction ordering, which will be derived from this flattened view. + * + * @param list The list to add the elements into. + * @param elements The elements to add. + * @param mode The mode containing the elements. + * @param The type of elements to add (e.g., Port, Timer, etc.) + */ + private static void insertModeElementsAtTextualPosition(List list, List elements, Mode mode) { + if (elements.isEmpty()) { + return; // Nothing to add + } + + var idx = list.size(); + if (idx > 0) { + // If there are elements in the list, first check if the last element has the same container as the mode. + // I.e. we don't want to compare textual positions of different reactors (super classes) + if (mode.eContainer() == list.get(list.size() - 1).eContainer()) { + var modeAstNode = NodeModelUtils.getNode(mode); + if (modeAstNode != null) { + var modePos = modeAstNode.getOffset(); + // Now move the insertion index from the last element forward as long as this element has a textual + // position after the mode. + do { + var astNode = NodeModelUtils.getNode(list.get(idx - 1)); + if (astNode != null && astNode.getOffset() > modePos) { + idx--; + } else { + break; // Insertion index is ok. + } + } while (idx > 0); + } + } + } + list.addAll(idx, elements); + } //////////////////////////////// //// Utility functions for translating AST nodes into text diff --git a/org.lflang/src/org/lflang/AttributeUtils.java b/org.lflang/src/org/lflang/AttributeUtils.java index 9c67b06754..79d2baf80b 100644 --- a/org.lflang/src/org/lflang/AttributeUtils.java +++ b/org.lflang/src/org/lflang/AttributeUtils.java @@ -86,7 +86,20 @@ public static String findLabelAttribute(EObject node) { .map(it -> it.getAttrParms().get(0).getValue().getStr()) .findFirst() .orElse(null); - + } + + /** + * Return true if the specified node is an Input and has an {@code @sparse} + * attribute. + * @param node An AST node. + */ + public static boolean isSparse(EObject node) { + if (node instanceof Input) { + for (var attribute : getAttributes(node)) { + if (attribute.getAttrName().equalsIgnoreCase("sparse")) return true; + } + } + return false; } /** diff --git a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java index 2126a8a985..0c51ad8b55 100644 --- a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java +++ b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java @@ -61,6 +61,8 @@ private static List getBaseCoreFiles() { "tag.c", "trace.h", "trace.c", + "port.h", + "port.c", "utils/pqueue.c", "utils/pqueue.h", "utils/pqueue_support.h", diff --git a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java index 13571015db..e77e272eed 100644 --- a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java @@ -1,6 +1,7 @@ package org.lflang.generator.c; import org.lflang.ASTUtils; +import org.lflang.AttributeUtils; import org.lflang.ErrorReporter; import org.lflang.Target; import org.lflang.generator.CodeBuilder; @@ -62,9 +63,16 @@ public static String generateAuxiliaryStruct( var code = new CodeBuilder(); code.pr("typedef struct {"); code.indent(); + // NOTE: The following fields are required to be the first ones so that + // pointer to this struct can be cast to a (lf_port_base_t*) to access + // these fields for any port. + code.pr(String.join("\n", + "bool is_present;", + "lf_sparse_io_record_t* sparse_record;", + "int destination_channel;" + )); code.pr(valueDeclaration(port, target, errorReporter, types)); code.pr(String.join("\n", - "bool is_present;", "int num_destinations;", "lf_token_t* token;", "int length;", @@ -88,22 +96,39 @@ public static String initializeInputMultiport( ) { var portRefName = CUtil.portRefName(input); // If the port is a multiport, create an array. - return input.isMultiport() ? - String.join("\n", - portRefName+"_width = "+input.getWidth()+";", - "// Allocate memory for multiport inputs.", - portRefName+" = ("+variableStructType(input)+"**)_lf_allocate(", - " "+input.getWidth()+", sizeof("+variableStructType(input)+"*),", - " &"+reactorSelfStruct+"->base.allocations); ", - "// Set inputs by default to an always absent default input.", - "for (int i = 0; i < "+input.getWidth()+"; i++) {", - " "+portRefName+"[i] = &"+reactorSelfStruct+"->_lf_default__"+input.getName()+";", + if (input.isMultiport()) { + String result = String.join("\n", + portRefName+"_width = "+input.getWidth()+";", + "// Allocate memory for multiport inputs.", + portRefName+" = ("+variableStructType(input)+"**)_lf_allocate(", + " "+input.getWidth()+", sizeof("+variableStructType(input)+"*),", + " &"+reactorSelfStruct+"->base.allocations); ", + "// Set inputs by default to an always absent default input.", + "for (int i = 0; i < "+input.getWidth()+"; i++) {", + " "+portRefName+"[i] = &"+reactorSelfStruct+"->_lf_default__"+input.getName()+";", + "}" + ); + if (AttributeUtils.isSparse(input.getDefinition())) { + return String.join("\n", result, + "if ("+input.getWidth()+" >= LF_SPARSE_WIDTH_THRESHOLD) {", + " "+portRefName+"__sparse = _lf_allocate(1,", + " sizeof(lf_sparse_io_record_t) + sizeof(size_t) * "+input.getWidth()+"/LF_SPARSE_CAPACITY_DIVIDER,", + " &"+reactorSelfStruct+"->base.allocations);", + " "+portRefName+"__sparse->capacity = "+input.getWidth()+"/LF_SPARSE_CAPACITY_DIVIDER;", + " if (_lf_sparse_io_record_sizes.start == NULL) {", + " _lf_sparse_io_record_sizes = vector_new(1);", + " }", + " vector_push(&_lf_sparse_io_record_sizes, (void*)&"+portRefName+"__sparse->size);", "}" - ) : - String.join("\n", - "// width of -2 indicates that it is not a multiport.", - portRefName+"_width = -2;" ); + } + return result; + } else { + return String.join("\n", + "// width of -2 indicates that it is not a multiport.", + portRefName+"_width = -2;" + ); + } } /** @@ -220,7 +245,9 @@ private static void generateInputDeclarations( variableStructType(input, decl)+"** _lf_"+inputName+";", "int _lf_"+inputName+"_width;", "// Default input (in case it does not get connected)", - variableStructType(input, decl)+" _lf_default__"+inputName+";" + variableStructType(input, decl)+" _lf_default__"+inputName+";", + "// Struct to support efficiently reading sparse inputs.", + "lf_sparse_io_record_t* _lf_"+inputName+"__sparse;" )); } else { // input is not a multiport. diff --git a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java index a254a234e0..7adc5bdcf8 100644 --- a/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPreambleGenerator.java @@ -52,6 +52,7 @@ public static String generateIncludeStatements( code.pr("#include \"core/trace.c\""); } code.pr("#include \"core/mixed_radix.h\""); + code.pr("#include \"core/port.h\""); return code.toString(); } diff --git a/org.lflang/src/org/lflang/generator/c/CTriggerObjectsGenerator.java b/org.lflang/src/org/lflang/generator/c/CTriggerObjectsGenerator.java index 1d45fd01b0..e8192be795 100644 --- a/org.lflang/src/org/lflang/generator/c/CTriggerObjectsGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CTriggerObjectsGenerator.java @@ -15,6 +15,7 @@ import java.util.stream.Collectors; import org.lflang.ASTUtils; +import org.lflang.AttributeUtils; import org.lflang.TargetConfig; import org.lflang.TargetProperty.CoordinationType; import org.lflang.TargetProperty.LogLevel; @@ -483,8 +484,12 @@ private static String connectPortToEventualDestinations( // An output port of a contained reactor is triggering a reaction. code.pr(CUtil.portRefNested(dst, dr, db, dc)+" = ("+destStructType+"*)&"+CUtil.portRef(src, sr, sb, sc)+";"); } else { - // An output port is triggering + // An output port is triggering an input port. code.pr(CUtil.portRef(dst, dr, db, dc)+" = ("+destStructType+"*)&"+CUtil.portRef(src, sr, sb, sc)+";"); + if (AttributeUtils.isSparse(dst.getDefinition())) { + code.pr(CUtil.portRef(dst, dr, db, dc)+"->sparse_record = "+CUtil.portRefName(dst, dr, db, dc)+"__sparse;"); + code.pr(CUtil.portRef(dst, dr, db, dc)+"->destination_channel = "+dc+";"); + } } code.endScopedRangeBlock(srcRange, dstRange, isFederated); } diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index 2974d48f9b..e283d8bc4e 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -124,10 +124,16 @@ private PythonGenerator(FileConfig fileConfig, ErrorReporter errorReporter, Pyth * statically allocated arrays in Lingua Franca. * This template is defined as * typedef struct { - * PyObject* value; * bool is_present; + * lf_sparse_io_record_t* sparse_record; // NULL if there is no sparse record. + * int destination_channel; // -1 if there is no destination. + * PyObject* value; * int num_destinations; - * FEDERATED_CAPSULE_EXTENSION + * lf_token_t* token; + * int length; + * void (*destructor) (void* value); + * void* (*copy_constructor) (void* value); + * FEDERATED_GENERIC_EXTENSION * } generic_port_instance_struct; * * @see reactor-c-py/lib/pythontarget.h diff --git a/org.lflang/src/org/lflang/validation/AttributeSpec.java b/org.lflang/src/org/lflang/validation/AttributeSpec.java index 07c70af72a..35d29da6f6 100644 --- a/org.lflang/src/org/lflang/validation/AttributeSpec.java +++ b/org.lflang/src/org/lflang/validation/AttributeSpec.java @@ -1,5 +1,5 @@ /************* - * Copyright (c) 2019-2020, The University of California at Berkeley. + * Copyright (c) 2019-2022, The University of California at Berkeley. * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -37,7 +37,7 @@ import org.lflang.lf.LfPackage.Literals; /** - * Specification of the structure of an annotation. + * Specification of the structure of an attribute annotation. * * @author{Clément Fournier, TU Dresden, INSA Rennes} * @author{Shaokai Lin } @@ -52,7 +52,11 @@ class AttributeSpec { public static final Map ATTRIBUTE_SPECS_BY_NAME = new HashMap<>(); public AttributeSpec(List params) { - paramSpecByName = params.stream().collect(Collectors.toMap(it -> it.name, it -> it)); + if (params != null) { + paramSpecByName = params.stream().collect(Collectors.toMap(it -> it.name, it -> it)); + } else { + paramSpecByName = null; + } } /** @@ -61,11 +65,17 @@ public AttributeSpec(List params) { */ public void check(LFValidator validator, Attribute attr) { Set seen; - // Check to see if there is one or multiple parameters. - if (attr.getAttrParms().size() == 1 && attr.getAttrParms().get(0).getName() == null) { + // If there is just one parameter, it is required to be named "value". + if (attr.getAttrParms() != null + && attr.getAttrParms().size() == 1 + && attr.getAttrParms().get(0).getName() == null) { // If we are in this branch, // then the user has provided @attr("value"), // which is a shorthand for @attr(value="value"). + if (paramSpecByName == null) { + validator.error("Attribute doesn't take a parameter.", Literals.ATTRIBUTE__ATTR_NAME); + return; + } AttrParamSpec valueSpec = paramSpecByName.get(VALUE_ATTR); if (valueSpec == null) { validator.error("Attribute doesn't have a 'value' parameter.", Literals.ATTR_PARM__NAME); @@ -75,47 +85,55 @@ public void check(LFValidator validator, Attribute attr) { valueSpec.check(validator, attr.getAttrParms().get(0)); seen = Set.of(VALUE_ATTR); } else { - // Process multiple attributes, each of which has to be named. + // Process multiple parameters, each of which has to be named. seen = processNamedAttrParms(validator, attr); } // Check if there are any missing parameters required by this attribute. - Map missingParams = new HashMap<>(paramSpecByName); - missingParams.keySet().removeAll(seen); - missingParams.forEach((name, paramSpec) -> { - if (!paramSpec.isOptional()) { - validator.error("Missing required attribute parameter '" + name + "'.", Literals.ATTRIBUTE__ATTR_PARMS); - } - }); + if (paramSpecByName != null) { + Map missingParams = new HashMap<>(paramSpecByName); + missingParams.keySet().removeAll(seen); + missingParams.forEach((name, paramSpec) -> { + if (!paramSpec.isOptional()) { + validator.error("Missing required attribute parameter '" + name + "'.", Literals.ATTRIBUTE__ATTR_PARMS); + } + }); + } } /** - * Check if the attribute parameters are named, whether + * Check whether the attribute parameters are named, whether * these names are known, and whether the named parameters * conform to the param spec (whether the param has the * right type, etc.). * - * @param validator The current validator in use - * @param attr The attribute being checked - * @return A set of named attribute parameters the user provides + * @param validator The current validator in use. + * @param attr The attribute being checked. + * @return A set of named attribute parameters the user provides. */ private Set processNamedAttrParms(LFValidator validator, Attribute attr) { Set seen = new HashSet<>(); - for (AttrParm parm : attr.getAttrParms()) { - if (parm.getName() == null) { - validator.error("Missing name for attribute parameter.", Literals.ATTRIBUTE__ATTR_NAME); - continue; - } - - AttrParamSpec parmSpec = paramSpecByName.get(parm.getName()); - if (parmSpec == null) { - validator.error("\"" + parm.getName() + "\"" + " is an unknown attribute parameter.", - Literals.ATTRIBUTE__ATTR_NAME); - continue; + if (attr.getAttrParms() != null) { + for (AttrParm parm : attr.getAttrParms()) { + if (paramSpecByName == null) { + validator.error("Attribute does not take parameters.", Literals.ATTRIBUTE__ATTR_NAME); + break; + } + if (parm.getName() == null) { + validator.error("Missing name for attribute parameter.", Literals.ATTRIBUTE__ATTR_NAME); + continue; + } + + AttrParamSpec parmSpec = paramSpecByName.get(parm.getName()); + if (parmSpec == null) { + validator.error("\"" + parm.getName() + "\"" + " is an unknown attribute parameter.", + Literals.ATTRIBUTE__ATTR_NAME); + continue; + } + // Check whether a parameter conforms to its spec. + parmSpec.check(validator, parm); + seen.add(parm.getName()); } - // Check whether a parameter conforms to its spec. - parmSpec.check(validator, parm); - seen.add(parm.getName()); } return seen; } @@ -162,7 +180,6 @@ public void check(LFValidator validator, AttrParm parm) { } break; } - } } @@ -185,5 +202,7 @@ enum AttrParamType { ATTRIBUTE_SPECS_BY_NAME.put("label", new AttributeSpec( List.of(new AttrParamSpec(AttributeSpec.VALUE_ATTR, AttrParamType.STRING, null)) )); + // @sparse + ATTRIBUTE_SPECS_BY_NAME.put("sparse", new AttributeSpec(null)); } } diff --git a/org.lflang/src/org/lflang/validation/LFValidator.java b/org.lflang/src/org/lflang/validation/LFValidator.java index c2ca25211f..d14b792ce1 100644 --- a/org.lflang/src/org/lflang/validation/LFValidator.java +++ b/org.lflang/src/org/lflang/validation/LFValidator.java @@ -37,12 +37,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -58,7 +56,6 @@ import org.eclipse.xtext.validation.Check; import org.eclipse.xtext.validation.CheckType; import org.eclipse.xtext.validation.ValidationMessageAcceptor; - import org.lflang.ASTUtils; import org.lflang.ModelInfo; import org.lflang.Target; @@ -69,7 +66,6 @@ import org.lflang.lf.Action; import org.lflang.lf.ActionOrigin; import org.lflang.lf.Assignment; -import org.lflang.lf.AttrParm; import org.lflang.lf.Attribute; import org.lflang.lf.BuiltinTrigger; import org.lflang.lf.BuiltinTriggerRef; @@ -114,8 +110,6 @@ import org.lflang.lf.WidthSpec; import org.lflang.lf.WidthTerm; import org.lflang.util.FileUtil; -import org.lflang.validation.AttributeSpec.AttrParamSpec; -import org.lflang.validation.AttributeSpec.AttrParamType; import com.google.inject.Inject; diff --git a/pom.xml b/pom.xml index 59d927143d..c889b736db 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.lflang lf - 0.2.2-SNAPSHOT + 0.3.1-SNAPSHOT pom Lingua Franca diff --git a/test/C/src/modal_models/MixedReactions.lf b/test/C/src/modal_models/MixedReactions.lf new file mode 100644 index 0000000000..eb07bd9e8d --- /dev/null +++ b/test/C/src/modal_models/MixedReactions.lf @@ -0,0 +1,54 @@ +/* + * Modal Reactor Test. + * Tests reactions that are defined between and after modes and should be ordered accordingly. + */ +target C { + fast: true, + timeout: 110 msec +}; + +main reactor { + state x:int(0); + state first:bool(true); + + timer t(0, 100msec) + + reaction(t) {= + self->x = self->x * 10 + 1; + =} + + reaction(t) {= + self->x = self->x * 10 + 2; + =} + + initial mode A { + reaction(t) -> B {= + self->x = self->x * 10 + 3; + lf_set_mode(B); + =} + } + + reaction(t) {= + self->x = self->x * 10 + 4; + =} + + mode B { + reaction(t) {= + self->x = self->x * 10 + 5; + =} + } + + reaction(t) {= + printf("%d\n", self->x); + if (self->first) { + if (self->x != 1234) { + printf("ERROR: Wrong reaction order.\n"); + exit(1); + } + self->first = false; + } else if (self->x != 12341245) { + printf("ERROR: Wrong reaction order.\n"); + exit(2); + } + =} +} diff --git a/test/C/src/multiport/Sparse.lf b/test/C/src/multiport/Sparse.lf new file mode 100644 index 0000000000..667b3cb576 --- /dev/null +++ b/test/C/src/multiport/Sparse.lf @@ -0,0 +1,47 @@ +/** + * Test reading of sparse inputs on a multiport. + */ +target C { + timeout: 20ms +} +reactor SparseSource(width:int(20)) { + output[width] out:int; + state count:int(0); + timer t(0, 1ms); + reaction(t) -> out {= + int next_count = self->count + 1; + if (next_count >= self->width) { + next_count = 0; + } + lf_set(out[next_count], next_count); + lf_set(out[self->count], self->count); + self->count = next_count; + =} +} +reactor SparseSink(width:int(20)) { + input[width] in:int; + reaction(in) {= + struct lf_multiport_iterator_t i = lf_multiport_iterator(in); + lf_print("--------"); + // Ensure inputs are seen in order. + int previous = -1; + int channel = lf_multiport_next(&i); + while(channel >= 0) { + lf_print("Received %d on channel %d", in[channel]->value, channel); + // The value of the input should equal the channel number. + if (in[channel]->value != channel) { + lf_print_error_and_exit("Expected %d", channel); + } + if (channel <= previous) { + lf_print_error_and_exit("Input channels not read in order."); + } + previous = channel; + channel = lf_multiport_next(&i); + } + =} +} +main reactor(width:int(20)) { + s = new SparseSource(width = width); + d = new SparseSink(width = width); + s.out -> d.in; +} diff --git a/test/C/src/multiport/SparseFallback.lf b/test/C/src/multiport/SparseFallback.lf new file mode 100644 index 0000000000..84b1ef2bfb --- /dev/null +++ b/test/C/src/multiport/SparseFallback.lf @@ -0,0 +1,49 @@ +/** + * Test reading of sparse inputs on a multiport where + * the density of writes to the multiport is high enough to + * force the fallback policy to kick in. + */ +target C { + timeout: 20ms +} +reactor SparseSource(width:int(20)) { + output[width] out:int; + state count:int(0); + timer t(0, 1ms); + reaction(t) -> out {= + int next_count = self->count + 1; + if (next_count >= self->width) { + next_count = 0; + } + lf_set(out[self->count], self->count); + lf_set(out[next_count], next_count); + self->count = next_count; + =} +} +reactor SparseSink(width:int(20)) { + input[width] in:int; + reaction(in) {= + struct lf_multiport_iterator_t i = lf_multiport_iterator(in); + lf_print("--------"); + // Ensure inputs are seen in order. + int previous = -1; + int channel = lf_multiport_next(&i); + while(channel >= 0) { + lf_print("Received %d on channel %d", in[channel]->value, channel); + // The value of the input should equal the channel number. + if (in[channel]->value != channel) { + lf_print_error_and_exit("Expected %d", channel); + } + if (channel <= previous) { + lf_print_error_and_exit("Input channels not read in order."); + } + previous = channel; + channel = lf_multiport_next(&i); + } + =} +} +main reactor(width:int(10)) { + s = new SparseSource(width = width); + d = new SparseSink(width = width); + s.out -> d.in; +}