From af6f2b35d4aa2dbf78d92c44c0ea7719ba7b86f7 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 09:50:48 -0700 Subject: [PATCH 01/12] Start towards fixing multiports in modes --- .../org/lflang/generator/GeneratorBase.java | 18 +---- .../org/lflang/generator/c/CGenerator.java | 53 ++++++++++----- .../generator/python/PythonGenerator.java | 9 ++- core/src/main/resources/lib/c/reactor-c | 2 +- test/C/src/modal_models/ModalMultiport.lf | 67 +++++++++++++++++++ 5 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 test/C/src/modal_models/ModalMultiport.lf diff --git a/core/src/main/java/org/lflang/generator/GeneratorBase.java b/core/src/main/java/org/lflang/generator/GeneratorBase.java index 0713b863be..b3ef1a6491 100644 --- a/core/src/main/java/org/lflang/generator/GeneratorBase.java +++ b/core/src/main/java/org/lflang/generator/GeneratorBase.java @@ -53,13 +53,7 @@ import org.lflang.generator.docker.DockerComposeGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.graph.InstantiationGraph; -import org.lflang.lf.Attribute; -import org.lflang.lf.Connection; -import org.lflang.lf.Instantiation; -import org.lflang.lf.LfFactory; -import org.lflang.lf.Mode; -import org.lflang.lf.Reaction; -import org.lflang.lf.Reactor; +import org.lflang.lf.*; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.FilesProperty; @@ -441,13 +435,7 @@ private void transformConflictingConnectionsInModalReactors(Set resour reaction.getEffects().add(destRef); var code = factory.createCode(); - var source = - (sourceRef.getContainer() != null ? sourceRef.getContainer().getName() + "." : "") - + sourceRef.getVariable().getName(); - var dest = - (destRef.getContainer() != null ? destRef.getContainer().getName() + "." : "") - + destRef.getVariable().getName(); - code.setBody(getConflictingConnectionsInModalReactorsBody(source, dest)); + code.setBody(getConflictingConnectionsInModalReactorsBody(sourceRef, destRef)); reaction.setCode(code); EcoreUtil.remove(connection); @@ -464,7 +452,7 @@ private void transformConflictingConnectionsInModalReactors(Set resour *

This method needs to be overridden in target specific code generators that support modal * reactors. */ - protected String getConflictingConnectionsInModalReactorsBody(String source, String dest) { + protected String getConflictingConnectionsInModalReactorsBody(VarRef source, VarRef dest) { messageReporter .nowhere() .error( diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index f6ee943085..d9436371e4 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -70,18 +70,7 @@ import org.lflang.generator.docker.CDockerGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.generator.python.PythonGenerator; -import org.lflang.lf.Action; -import org.lflang.lf.ActionOrigin; -import org.lflang.lf.Input; -import org.lflang.lf.Instantiation; -import org.lflang.lf.Mode; -import org.lflang.lf.Port; -import org.lflang.lf.Preamble; -import org.lflang.lf.Reaction; -import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; -import org.lflang.lf.StateVar; -import org.lflang.lf.Variable; +import org.lflang.lf.*; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.BuildCommandsProperty; @@ -659,12 +648,40 @@ public void checkModalReactorSupport(boolean __) { } @Override - protected String getConflictingConnectionsInModalReactorsBody(String source, String dest) { - return String.join( - "\n", - "// Generated forwarding reaction for connections with the same destination", - "// but located in mutually exclusive modes.", - "lf_set(" + dest + ", " + source + "->value);"); + protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, VarRef destRef) { + Instantiation sourceContainer = sourceRef.getContainer(); + Instantiation destContainer = destRef.getContainer(); + Port sourceAsPort = (Port) sourceRef.getVariable(); + Port destAsPort = (Port) destRef.getVariable(); + WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); + WidthSpec destWidth = destAsPort.getWidthSpec(); + + // FIXME: Support banks (containers) + var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + + sourceAsPort.getName() + + ((sourceWidth != null)? "[i]" : ""); + var dest = (destContainer != null ? destContainer.getName() + "." : "") + + destAsPort.getName() + + ((destWidth != null)? "[i]" : ""); + // If either side is a multiport, iterate. + // Note that one side could be a multiport of width 1 and the other an ordinary port. + var result = new StringBuilder(); + if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + if (sourceAsPort.getWidthSpec() != null) { + var width = (sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName(); + result.append("for(int i = 0; i < " + width + "_width; i++) { "); + } else { + var width = (destContainer != null)? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName(); + result.append("for(int i = 0; i < " + width + "_width; i++) { "); + } + } + result.append("lf_set(" + dest + ", " + source + "->value);"); + if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + result.append(" }"); + } + return result.toString(); } /** Set the scheduler type in the target config as needed. */ diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 854c8f108a..5f76ab7184 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -59,6 +59,7 @@ import org.lflang.lf.Port; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; +import org.lflang.lf.VarRef; import org.lflang.target.Target; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ProtobufsProperty; @@ -539,7 +540,13 @@ protected void generateSelfStructExtension( } @Override - protected String getConflictingConnectionsInModalReactorsBody(String source, String dest) { + protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, VarRef destRef) { + var source = + (sourceRef.getContainer() != null ? sourceRef.getContainer().getName() + "." : "") + + sourceRef.getVariable().getName(); + var dest = + (destRef.getContainer() != null ? destRef.getContainer().getName() + "." : "") + + destRef.getVariable().getName(); // NOTE: Strangely, a newline is needed at the beginning or indentation // gets swallowed. return String.join( diff --git a/core/src/main/resources/lib/c/reactor-c b/core/src/main/resources/lib/c/reactor-c index 693c5f5bdb..184567d3bd 160000 --- a/core/src/main/resources/lib/c/reactor-c +++ b/core/src/main/resources/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 693c5f5bdbc6918cebc619c3ae46a22af719b741 +Subproject commit 184567d3bd06ae5c5f8a75a0b51093115e7fbe52 diff --git a/test/C/src/modal_models/ModalMultiport.lf b/test/C/src/modal_models/ModalMultiport.lf new file mode 100644 index 0000000000..e6714ec024 --- /dev/null +++ b/test/C/src/modal_models/ModalMultiport.lf @@ -0,0 +1,67 @@ +target C { + timeout: 1 ms +} + +reactor Destination(n_inputs: int = 2) { + input[n_inputs] req: int + output[n_inputs] rsp: int + + reaction(req) -> rsp {= + for (int i = 0; i < self->n_inputs; ++i) { + if (req[i]->is_present) { + lf_set (rsp[i], req[i]->value); + } + } + =} +} + +reactor Source(n_ports: int = 2) { + output[n_ports] req: int + input[n_ports] rsp: int + timer t(0, 1 ms) + + reaction(t) -> req {= + for (int i = 0; i < self->n_ports; ++i) { + lf_set (req[i], i); + } + =} + + reaction(rsp) {= + for (int i = 0; i < self->n_ports; ++i) { + lf_print("Received response:%d", rsp[i]->value); + if (rsp[i]->value != i) { + lf_print_error_and_exit("Expected %d", i); + } + } + =} +} + +reactor Selector(n_ports: int = 2) { + input[n_ports] in_req: int + output[n_ports] out_rsp: int + + initial mode DST_1 { + dst1 = new Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + lf_set_mode(DST_2); + =} + } + + mode DST_2 { + dst2 = new Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} From d6da2b66e211c649401b0dd286de1fd1008f091f Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 11:42:03 -0700 Subject: [PATCH 02/12] Added Python support --- .../org/lflang/generator/c/CGenerator.java | 14 ++---- .../generator/python/PythonGenerator.java | 50 +++++++++++-------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index d9436371e4..34e61691f7 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -656,7 +656,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); - // FIXME: Support banks (containers) + // FIXME: Support banks (for the containers) var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceAsPort.getName() + ((sourceWidth != null)? "[i]" : ""); @@ -667,15 +667,11 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { - if (sourceAsPort.getWidthSpec() != null) { - var width = (sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName(); + var width = (sourceAsPort.getWidthSpec() != null)? + ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() : sourceAsPort.getName()) + : + ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() : destAsPort.getName()); result.append("for(int i = 0; i < " + width + "_width; i++) { "); - } else { - var width = (destContainer != null)? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName(); - result.append("for(int i = 0; i < " + width + "_width; i++) { "); - } } result.append("lf_set(" + dest + ", " + source + "->value);"); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 5f76ab7184..214b0f6d41 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -52,14 +52,7 @@ import org.lflang.generator.c.CUtil; import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.generator.docker.PythonDockerGenerator; -import org.lflang.lf.Action; -import org.lflang.lf.Input; -import org.lflang.lf.Model; -import org.lflang.lf.Output; -import org.lflang.lf.Port; -import org.lflang.lf.Reaction; -import org.lflang.lf.Reactor; -import org.lflang.lf.VarRef; +import org.lflang.lf.*; import org.lflang.target.Target; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ProtobufsProperty; @@ -541,19 +534,34 @@ protected void generateSelfStructExtension( @Override protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, VarRef destRef) { - var source = - (sourceRef.getContainer() != null ? sourceRef.getContainer().getName() + "." : "") - + sourceRef.getVariable().getName(); - var dest = - (destRef.getContainer() != null ? destRef.getContainer().getName() + "." : "") - + destRef.getVariable().getName(); - // NOTE: Strangely, a newline is needed at the beginning or indentation - // gets swallowed. - return String.join( - "\n", - "\n# Generated forwarding reaction for connections with the same destination", - "# but located in mutually exclusive modes.", - dest + ".set(" + source + ".value)\n"); + Instantiation sourceContainer = sourceRef.getContainer(); + Instantiation destContainer = destRef.getContainer(); + Port sourceAsPort = (Port) sourceRef.getVariable(); + Port destAsPort = (Port) destRef.getVariable(); + WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); + WidthSpec destWidth = destAsPort.getWidthSpec(); + + // FIXME: Support banks (for the containers) + var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + + sourceAsPort.getName() + + ((sourceWidth != null)? "[i]" : ""); + var dest = (destContainer != null ? destContainer.getName() + "." : "") + + destAsPort.getName() + + ((destWidth != null)? "[i]" : ""); + // If either side is a multiport, iterate. + // Note that one side could be a multiport of width 1 and the other an ordinary port. + var result = new StringBuilder(); + if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + var width = (sourceAsPort.getWidthSpec() != null)? + ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName()) + : + ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName()); + result.append("for i in range(" + width + ".width): "); + } + result.append(dest + ".set(" + source + ".value)"); + return result.toString(); } @Override From ae8c1ab86a0ada06d9234503fa0e0e32d1a21b20 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 11:50:00 -0700 Subject: [PATCH 03/12] Spotless --- .../org/lflang/generator/c/CGenerator.java | 24 ++++++++++------- .../generator/python/PythonGenerator.java | 26 +++++++++++-------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 34e61691f7..f9c89ac1d4 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -657,21 +657,27 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec destWidth = destAsPort.getWidthSpec(); // FIXME: Support banks (for the containers) - var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + var source = + (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceAsPort.getName() - + ((sourceWidth != null)? "[i]" : ""); - var dest = (destContainer != null ? destContainer.getName() + "." : "") + + ((sourceWidth != null) ? "[i]" : ""); + var dest = + (destContainer != null ? destContainer.getName() + "." : "") + destAsPort.getName() - + ((destWidth != null)? "[i]" : ""); + + ((destWidth != null) ? "[i]" : ""); // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { - var width = (sourceAsPort.getWidthSpec() != null)? - ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() : sourceAsPort.getName()) - : - ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() : destAsPort.getName()); - result.append("for(int i = 0; i < " + width + "_width; i++) { "); + var width = + (sourceAsPort.getWidthSpec() != null) + ? ((sourceContainer != null) + ? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName()) + : ((destContainer != null) + ? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName()); + result.append("for(int i = 0; i < " + width + "_width; i++) { "); } result.append("lf_set(" + dest + ", " + source + "->value);"); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 214b0f6d41..64839bc347 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -542,23 +542,27 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec destWidth = destAsPort.getWidthSpec(); // FIXME: Support banks (for the containers) - var source = (sourceContainer != null ? sourceContainer.getName() + "." : "") + var source = + (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceAsPort.getName() - + ((sourceWidth != null)? "[i]" : ""); - var dest = (destContainer != null ? destContainer.getName() + "." : "") + + ((sourceWidth != null) ? "[i]" : ""); + var dest = + (destContainer != null ? destContainer.getName() + "." : "") + destAsPort.getName() - + ((destWidth != null)? "[i]" : ""); + + ((destWidth != null) ? "[i]" : ""); // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { - var width = (sourceAsPort.getWidthSpec() != null)? - ((sourceContainer != null)? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName()) - : - ((destContainer != null)? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName()); - result.append("for i in range(" + width + ".width): "); + var width = + (sourceAsPort.getWidthSpec() != null) + ? ((sourceContainer != null) + ? sourceContainer.getName() + "." + sourceAsPort.getName() + : sourceAsPort.getName()) + : ((destContainer != null) + ? destContainer.getName() + "." + destAsPort.getName() + : destAsPort.getName()); + result.append("for i in range(" + width + ".width): "); } result.append(dest + ".set(" + source + ".value)"); return result.toString(); From 9614b9dccf4765aa3d62eede5ca15c4a08dbb17e Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 17:38:41 -0700 Subject: [PATCH 04/12] Compile error with banks/modes/multiports --- core/src/main/java/org/lflang/generator/c/CGenerator.java | 2 +- .../main/java/org/lflang/generator/c/CReactionGenerator.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index f9c89ac1d4..d3150a982a 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -668,7 +668,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. var result = new StringBuilder(); - if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + if (sourceWidth != null || destWidth != null) { var width = (sourceAsPort.getWidthSpec() != null) ? ((sourceContainer != null) diff --git a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java index 151d2a47fb..ffc36848fe 100644 --- a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java @@ -279,7 +279,9 @@ public static int maxContainedReactorBankWidth( nestedBreadcrumbs.add(mainDef); } int result = max; - Reactor parent = (Reactor) containedReactor.eContainer(); + Reactor parent = containedReactor.eContainer() instanceof Mode? + (Reactor) containedReactor.eContainer().eContainer() + : (Reactor) containedReactor.eContainer(); if (parent == ASTUtils.toDefinition(mainDef.getReactorClass())) { // The parent is main, so there can't be any other instantiations of it. return ASTUtils.width(containedReactor.getWidthSpec(), null); From 11b4ff5ac54bd9f1a032de75df49cc51769e5ffe Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 6 Oct 2024 19:07:40 -0700 Subject: [PATCH 05/12] Support banks with multiports in modes --- .../org/lflang/generator/c/CGenerator.java | 61 +++++++++++++---- .../generator/c/CReactionGenerator.java | 5 +- test/C/src/modal_models/ModalMultiportBank.lf | 67 +++++++++++++++++++ 3 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 test/C/src/modal_models/ModalMultiportBank.lf diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index d3150a982a..8ff50ca999 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -656,33 +656,68 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); - // FIXME: Support banks (for the containers) + // If the source or dest is a port of a bank, we need to iterate over it. + var isBank = false; + Instantiation bank = null; + var sourceContainerRef = ""; + if (sourceContainer != null) { + sourceContainerRef = sourceContainer.getName() + "."; + bank = sourceContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + sourceContainerRef = sourceContainer.getName() + "[j]."; + } + } + var sourceIndex = isBank ? "i" : "count"; var source = - (sourceContainer != null ? sourceContainer.getName() + "." : "") + sourceContainerRef + sourceAsPort.getName() - + ((sourceWidth != null) ? "[i]" : ""); + + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); + var destContainerRef = ""; + var destIndex = "count"; + if (destContainer != null) { + destIndex = "i"; + destContainerRef = destContainer.getName() + "."; + if (bank == null) { + bank = destContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + destContainerRef = destContainer.getName() + "[j]."; + } + } + } var dest = - (destContainer != null ? destContainer.getName() + "." : "") + destContainerRef + destAsPort.getName() - + ((destWidth != null) ? "[i]" : ""); + + ((destWidth != null) ? "[" + destIndex + "]" : ""); + var result = new StringBuilder(); + result.append("{ int count = 0; SUPPRESS_UNUSED_WARNING(count); "); + // If either side is a bank (only one side should be), iterate over it. + if (isBank) { + var width = new StringBuilder(); + for (var term : bank.getWidthSpec().getTerms()) { + if (!width.isEmpty()) width.append(" + "); + if (term.getCode() != null) width.append(term.getCode().getBody()); + else if (term.getParameter() != null) width.append("self->" + term.getParameter()); + else width.append(term.getWidth()); + } + result.append("for(int j = 0; j < " + width.toString() + "; j++) { "); + } // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. - var result = new StringBuilder(); if (sourceWidth != null || destWidth != null) { var width = (sourceAsPort.getWidthSpec() != null) - ? ((sourceContainer != null) - ? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName()) - : ((destContainer != null) - ? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName()); + ? sourceContainerRef + sourceAsPort.getName() + : destContainerRef + destAsPort.getName(); result.append("for(int i = 0; i < " + width + "_width; i++) { "); } - result.append("lf_set(" + dest + ", " + source + "->value);"); + result.append("lf_set(" + dest + ", " + source + "->value); count++; "); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { result.append(" }"); } + if (isBank) result.append(" }"); + result.append(" }"); return result.toString(); } diff --git a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java index ffc36848fe..a2f2a93f7d 100644 --- a/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CReactionGenerator.java @@ -279,8 +279,9 @@ public static int maxContainedReactorBankWidth( nestedBreadcrumbs.add(mainDef); } int result = max; - Reactor parent = containedReactor.eContainer() instanceof Mode? - (Reactor) containedReactor.eContainer().eContainer() + Reactor parent = + containedReactor.eContainer() instanceof Mode + ? (Reactor) containedReactor.eContainer().eContainer() : (Reactor) containedReactor.eContainer(); if (parent == ASTUtils.toDefinition(mainDef.getReactorClass())) { // The parent is main, so there can't be any other instantiations of it. diff --git a/test/C/src/modal_models/ModalMultiportBank.lf b/test/C/src/modal_models/ModalMultiportBank.lf new file mode 100644 index 0000000000..9ab4213fd5 --- /dev/null +++ b/test/C/src/modal_models/ModalMultiportBank.lf @@ -0,0 +1,67 @@ +target C { + timeout: 1 ms +} + +reactor Destination(n_inputs: int = 2) { + input[n_inputs] req: int + output[n_inputs] rsp: int + + reaction(req) -> rsp {= + for (int i = 0; i < self->n_inputs; ++i) { + if (req[i]->is_present) { + lf_set (rsp[i], req[i]->value); + } + } + =} +} + +reactor Source(n_ports: int = 4) { + output[n_ports] req: int + input[n_ports] rsp: int + timer t(0, 1 ms) + + reaction(t) -> req {= + for (int i = 0; i < self->n_ports; ++i) { + lf_set (req[i], i); + } + =} + + reaction(rsp) {= + for (int i = 0; i < self->n_ports; ++i) { + lf_print("Received response:%d", rsp[i]->value); + if (rsp[i]->value != i) { + lf_print_error_and_exit("Expected %d", i); + } + } + =} +} + +reactor Selector(n_ports: int = 4) { + input[n_ports] in_req: int + output[n_ports] out_rsp: int + + initial mode DST_1 { + dst1 = new[2] Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + lf_set_mode(DST_2); + =} + } + + mode DST_2 { + dst2 = new[2] Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} From 2d5abf8e81b4b27ed959a1ed4d7ac4f8aae4d8d7 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 7 Oct 2024 08:20:18 -0700 Subject: [PATCH 06/12] Rename local vars to prevent collision with port names --- .../org/lflang/generator/c/CGenerator.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 8ff50ca999..e9327c52f3 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -656,6 +656,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); + // NOTE: Have to be careful with naming count variables because if the name matches + // that of a port, the program will fail to compile. + // If the source or dest is a port of a bank, we need to iterate over it. var isBank = false; Instantiation bank = null; @@ -665,24 +668,24 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, bank = sourceContainer; if (bank.getWidthSpec() != null) { isBank = true; - sourceContainerRef = sourceContainer.getName() + "[j]."; + sourceContainerRef = sourceContainer.getName() + "[_lf_j]."; } } - var sourceIndex = isBank ? "i" : "count"; + var sourceIndex = isBank ? "_lf_i" : "_lf_c"; var source = sourceContainerRef + sourceAsPort.getName() + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); var destContainerRef = ""; - var destIndex = "count"; + var destIndex = "_lf_c"; if (destContainer != null) { - destIndex = "i"; + destIndex = "_lf_i"; destContainerRef = destContainer.getName() + "."; if (bank == null) { bank = destContainer; if (bank.getWidthSpec() != null) { isBank = true; - destContainerRef = destContainer.getName() + "[j]."; + destContainerRef = destContainer.getName() + "[_lf_j]."; } } } @@ -691,7 +694,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, + destAsPort.getName() + ((destWidth != null) ? "[" + destIndex + "]" : ""); var result = new StringBuilder(); - result.append("{ int count = 0; SUPPRESS_UNUSED_WARNING(count); "); + result.append("{ int _lf_c = 0; SUPPRESS_UNUSED_WARNING(_lf_c); "); // If either side is a bank (only one side should be), iterate over it. if (isBank) { var width = new StringBuilder(); @@ -701,7 +704,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, else if (term.getParameter() != null) width.append("self->" + term.getParameter()); else width.append(term.getWidth()); } - result.append("for(int j = 0; j < " + width.toString() + "; j++) { "); + result.append("for(int _lf_j = 0; _lf_j < " + width.toString() + "; _lf_j++) { "); } // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. @@ -710,9 +713,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, (sourceAsPort.getWidthSpec() != null) ? sourceContainerRef + sourceAsPort.getName() : destContainerRef + destAsPort.getName(); - result.append("for(int i = 0; i < " + width + "_width; i++) { "); + result.append("for(int _lf_i = 0; _lf_i < " + width + "_width; _lf_i++) { "); } - result.append("lf_set(" + dest + ", " + source + "->value); count++; "); + result.append("lf_set(" + dest + ", " + source + "->value); _lf_c++; "); if (sourceWidth != null || destAsPort.getWidthSpec() != null) { result.append(" }"); } From 1249f1445fceb460d8c40f8a15278cfb54debb42 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 14:19:43 -0700 Subject: [PATCH 07/12] Fixed imports to not use * --- .../org/lflang/generator/GeneratorBase.java | 9 +++++++- .../org/lflang/generator/c/CGenerator.java | 15 +++++++++++- .../generator/python/PythonGenerator.java | 23 ++++++++----------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/GeneratorBase.java b/core/src/main/java/org/lflang/generator/GeneratorBase.java index b3ef1a6491..83eb540775 100644 --- a/core/src/main/java/org/lflang/generator/GeneratorBase.java +++ b/core/src/main/java/org/lflang/generator/GeneratorBase.java @@ -53,7 +53,14 @@ import org.lflang.generator.docker.DockerComposeGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.graph.InstantiationGraph; -import org.lflang.lf.*; +import org.lflang.lf.Attribute; +import org.lflang.lf.Connection; +import org.lflang.lf.Instantiation; +import org.lflang.lf.LfFactory; +import org.lflang.lf.Mode; +import org.lflang.lf.Reaction; +import org.lflang.lf.Reactor; +import org.lflang.lf.VarRef; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.FilesProperty; diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index e9327c52f3..c8fc99d2c5 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -70,7 +70,20 @@ import org.lflang.generator.docker.CDockerGenerator; import org.lflang.generator.docker.DockerGenerator; import org.lflang.generator.python.PythonGenerator; -import org.lflang.lf.*; +import org.lflang.lf.Action; +import org.lflang.lf.ActionOrigin; +import org.lflang.lf.Input; +import org.lflang.lf.Instantiation; +import org.lflang.lf.Mode; +import org.lflang.lf.Port; +import org.lflang.lf.Preamble; +import org.lflang.lf.Reaction; +import org.lflang.lf.Reactor; +import org.lflang.lf.ReactorDecl; +import org.lflang.lf.StateVar; +import org.lflang.lf.Variable; +import org.lflang.lf.VarRef; +import org.lflang.lf.WidthSpec; import org.lflang.target.Target; import org.lflang.target.TargetConfig; import org.lflang.target.property.BuildCommandsProperty; diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 64839bc347..52620e2b2b 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -52,7 +52,16 @@ import org.lflang.generator.c.CUtil; import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.generator.docker.PythonDockerGenerator; -import org.lflang.lf.*; +import org.lflang.lf.Action; +import org.lflang.lf.Input; +import org.lflang.lf.Instantiation; +import org.lflang.lf.Model; +import org.lflang.lf.Output; +import org.lflang.lf.Port; +import org.lflang.lf.Reaction; +import org.lflang.lf.Reactor; +import org.lflang.lf.VarRef; +import org.lflang.lf.WidthSpec; import org.lflang.target.Target; import org.lflang.target.property.DockerProperty; import org.lflang.target.property.ProtobufsProperty; @@ -641,18 +650,6 @@ private static String generateCmakeInstall(FileConfig fileConfig) { .replace("", pyMainName); } - /** - * Generate a ({@code key}, {@code val}) tuple pair for the {@code define_macros} field of the - * Extension class constructor from setuptools. - * - * @param key The key of the macro entry - * @param val The value of the macro entry - * @return A ({@code key}, {@code val}) tuple pair as String - */ - private static String generateMacroEntry(String key, String val) { - return "(" + StringUtil.addDoubleQuotes(key) + ", " + StringUtil.addDoubleQuotes(val) + ")"; - } - /** * Generate the name of the python module. * From f85f400a4828eec8847c8ef9d8a2f5abe599c39f Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 15:59:09 -0700 Subject: [PATCH 08/12] Support in Python plus tests --- .../org/lflang/generator/c/CGenerator.java | 2 +- .../generator/python/PythonGenerator.java | 79 ++++++++++++++----- .../Python/src/modal_models/ModalMultiport.lf | 63 +++++++++++++++ .../src/modal_models/ModalMultiportBank.lf | 63 +++++++++++++++ 4 files changed, 188 insertions(+), 19 deletions(-) create mode 100644 test/Python/src/modal_models/ModalMultiport.lf create mode 100644 test/Python/src/modal_models/ModalMultiportBank.lf diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index c8fc99d2c5..44eaad8c68 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -714,7 +714,7 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, for (var term : bank.getWidthSpec().getTerms()) { if (!width.isEmpty()) width.append(" + "); if (term.getCode() != null) width.append(term.getCode().getBody()); - else if (term.getParameter() != null) width.append("self->" + term.getParameter()); + else if (term.getParameter() != null) width.append("self->" + term.getParameter().getName()); else width.append(term.getWidth()); } result.append("for(int _lf_j = 0; _lf_j < " + width.toString() + "; _lf_j++) { "); diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 52620e2b2b..658c8e4955 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -550,30 +550,73 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, WidthSpec sourceWidth = sourceAsPort.getWidthSpec(); WidthSpec destWidth = destAsPort.getWidthSpec(); - // FIXME: Support banks (for the containers) + // NOTE: Have to be careful with naming count variables because if the name matches + // that of a port, the program will fail to compile. + + // If the source or dest is a port of a bank, we need to iterate over it. + var isBank = false; + Instantiation bank = null; + var sourceContainerRef = ""; + if (sourceContainer != null) { + sourceContainerRef = sourceContainer.getName() + "."; + bank = sourceContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + sourceContainerRef = sourceContainer.getName() + "[_lf_j]."; + } + } + var sourceIndex = isBank ? "_lf_i" : "_lf_c"; var source = - (sourceContainer != null ? sourceContainer.getName() + "." : "") - + sourceAsPort.getName() - + ((sourceWidth != null) ? "[i]" : ""); + sourceContainerRef + + sourceAsPort.getName() + + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); + var destContainerRef = ""; + var destIndex = "_lf_c"; + if (destContainer != null) { + destIndex = "_lf_i"; + destContainerRef = destContainer.getName() + "."; + if (bank == null) { + bank = destContainer; + if (bank.getWidthSpec() != null) { + isBank = true; + destContainerRef = destContainer.getName() + "[_lf_j]."; + } + } + } var dest = - (destContainer != null ? destContainer.getName() + "." : "") - + destAsPort.getName() - + ((destWidth != null) ? "[i]" : ""); + destContainerRef + + destAsPort.getName() + + ((destWidth != null) ? "[" + destIndex + "]" : ""); + var result = new CodeBuilder(); + // If either side is a bank (only one side should be), iterate over it. + if (isBank) { + result.pr("_lf_c = 0"); // Counter variable over nested loop if there is a bank and multiport. + var width = new StringBuilder(); + for (var term : bank.getWidthSpec().getTerms()) { + if (!width.isEmpty()) width.append(" + "); + if (term.getCode() != null) width.append(term.getCode().getBody()); + else if (term.getParameter() != null) width.append("self." + term.getParameter().getName()); + else width.append(term.getWidth()); + } + result.pr("for _lf_j in range(" + width + "):"); + result.indent(); + } // If either side is a multiport, iterate. // Note that one side could be a multiport of width 1 and the other an ordinary port. - var result = new StringBuilder(); - if (sourceWidth != null || destAsPort.getWidthSpec() != null) { + if (sourceWidth != null || destWidth != null) { var width = - (sourceAsPort.getWidthSpec() != null) - ? ((sourceContainer != null) - ? sourceContainer.getName() + "." + sourceAsPort.getName() - : sourceAsPort.getName()) - : ((destContainer != null) - ? destContainer.getName() + "." + destAsPort.getName() - : destAsPort.getName()); - result.append("for i in range(" + width + ".width): "); + (sourceAsPort.getWidthSpec() != null) + ? sourceContainerRef + sourceAsPort.getName() + : destContainerRef + destAsPort.getName(); + result.pr("for _lf_i in range(" + width + ".width):"); + result.indent(); + } + result.pr(dest + ".set(" + source + ".value)"); + if (isBank) { + result.pr("_lf_c += 1"); // Increment the count. + result.unindent(); } - result.append(dest + ".set(" + source + ".value)"); + result.unindent(); return result.toString(); } diff --git a/test/Python/src/modal_models/ModalMultiport.lf b/test/Python/src/modal_models/ModalMultiport.lf new file mode 100644 index 0000000000..38790a7e80 --- /dev/null +++ b/test/Python/src/modal_models/ModalMultiport.lf @@ -0,0 +1,63 @@ +target Python { + timeout: 1 ms +} + +reactor Destination(n_inputs=2) { + input[n_inputs] req + output[n_inputs] rsp + + reaction(req) -> rsp {= + for n in range(self.n_inputs): + if req[n].is_present: + rsp[n].set(req[n].value) + =} +} + +reactor Source(n_ports=2) { + output[n_ports] req + input[n_ports] rsp + timer t(0, 1 ms) + + reaction(t) -> req {= + for n in range(self.n_ports): + req[n].set(n) + =} + + reaction(rsp) {= + for n in range(self.n_ports): + print("Received response: ", rsp[n].value); + if rsp[n].value != n: + sys.stderr.write("ERROR: Expected {:d}\n".format(n)) + exit(1) + =} +} + +reactor Selector(n_ports=2) { + input[n_ports] in_req + output[n_ports] out_rsp + + initial mode DST_1 { + dst1 = new Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + DST_2.set() + =} + } + + mode DST_2 { + dst2 = new Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} diff --git a/test/Python/src/modal_models/ModalMultiportBank.lf b/test/Python/src/modal_models/ModalMultiportBank.lf new file mode 100644 index 0000000000..5521a8d2e3 --- /dev/null +++ b/test/Python/src/modal_models/ModalMultiportBank.lf @@ -0,0 +1,63 @@ +target Python { + timeout: 1 ms +} + +reactor Destination(n_inputs=2) { + input[n_inputs] req + output[n_inputs] rsp + + reaction(req) -> rsp {= + for n in range(self.n_inputs): + if req[n].is_present: + rsp[n].set(req[n].value) + =} +} + +reactor Source(n_ports=4) { + output[n_ports] req + input[n_ports] rsp + timer t(0, 1 ms) + + reaction(t) -> req {= + for n in range(self.n_ports): + req[n].set(n) + =} + + reaction(rsp) {= + for n in range(self.n_ports): + print("Received {:d} response: {:d}".format(n, rsp[n].value)) + if rsp[n].value != n: + sys.stderr.write("ERROR: Expected {:d}\n".format(n)) + exit(1) + =} +} + +reactor Selector(n_ports=4, n_dest=2) { + input[n_ports] in_req + output[n_ports] out_rsp + + initial mode DST_1 { + dst1 = new[n_dest] Destination() + + in_req -> dst1.req + dst1.rsp -> out_rsp + reaction(startup) -> reset(DST_2) {= + DST_2.set() + =} + } + + mode DST_2 { + dst2 = new[n_dest] Destination() + + in_req -> dst2.req + dst2.rsp -> out_rsp + } +} + +main reactor { + src = new Source() + sel = new Selector() + + src.req -> sel.in_req + sel.out_rsp -> src.rsp +} From f319a5170931515b916e8f3ef0f7ad840084dcec Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 16:40:38 -0700 Subject: [PATCH 09/12] Better reaction to odd cycle detection error --- .../org/lflang/generator/c/CGenerator.java | 19 +++++++++--- .../generator/python/PythonGenerator.java | 31 ++++++++++--------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 44eaad8c68..dda5c06d89 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -81,8 +81,8 @@ import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.StateVar; -import org.lflang.lf.Variable; import org.lflang.lf.VarRef; +import org.lflang.lf.Variable; import org.lflang.lf.WidthSpec; import org.lflang.target.Target; import org.lflang.target.TargetConfig; @@ -410,7 +410,10 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { if (!isOSCompatible()) return; // Incompatible OS and configuration // Perform set up that does not generate code - setUpGeneralParameters(); + if (!setUpGeneralParameters()) { + // Failure. + return; + } FileUtil.createDirectoryIfDoesNotExist(fileConfig.getSrcGenPath().toFile()); FileUtil.createDirectoryIfDoesNotExist(fileConfig.binPath.toFile()); @@ -714,7 +717,8 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, for (var term : bank.getWidthSpec().getTerms()) { if (!width.isEmpty()) width.append(" + "); if (term.getCode() != null) width.append(term.getCode().getBody()); - else if (term.getParameter() != null) width.append("self->" + term.getParameter().getName()); + else if (term.getParameter() != null) + width.append("self->" + term.getParameter().getName()); else width.append(term.getWidth()); } result.append("for(int _lf_j = 0; _lf_j < " + width.toString() + "; _lf_j++) { "); @@ -2009,8 +2013,8 @@ protected DockerGenerator getDockerGenerator(LFGeneratorContext context) { // ////////////////////////////////////////// // // Protected methods. - // Perform set up that does not generate code - protected void setUpGeneralParameters() { + // Perform set up that does not generate code. Return false on failure. + protected boolean setUpGeneralParameters() { accommodatePhysicalActionsIfPresent(); CompileDefinitionsProperty.INSTANCE.update( targetConfig, @@ -2020,6 +2024,10 @@ protected void setUpGeneralParameters() { // Create the main reactor instance if there is a main reactor. this.main = ASTUtils.createMainReactorInstance(mainDef, reactors, messageReporter, targetConfig); + if (this.main == null) { + // Something went wrong (causality cycle?). Stop. + return false; + } if (hasModalReactors) { // So that each separate compile knows about modal reactors, do this: CompileDefinitionsProperty.INSTANCE.update(targetConfig, Map.of("MODAL_REACTORS", "TRUE")); @@ -2072,6 +2080,7 @@ protected void setUpGeneralParameters() { } pickCompilePlatform(); } + return true; } protected void handleProtoFiles() { diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 658c8e4955..667207f267 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -67,7 +67,6 @@ import org.lflang.target.property.ProtobufsProperty; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; -import org.lflang.util.StringUtil; /** * Generator for Python target. This class generates Python code defining each reactor class given @@ -567,9 +566,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, } var sourceIndex = isBank ? "_lf_i" : "_lf_c"; var source = - sourceContainerRef - + sourceAsPort.getName() - + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); + sourceContainerRef + + sourceAsPort.getName() + + ((sourceWidth != null) ? "[" + sourceIndex + "]" : ""); var destContainerRef = ""; var destIndex = "_lf_c"; if (destContainer != null) { @@ -584,9 +583,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, } } var dest = - destContainerRef - + destAsPort.getName() - + ((destWidth != null) ? "[" + destIndex + "]" : ""); + destContainerRef + + destAsPort.getName() + + ((destWidth != null) ? "[" + destIndex + "]" : ""); var result = new CodeBuilder(); // If either side is a bank (only one side should be), iterate over it. if (isBank) { @@ -605,9 +604,9 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, // Note that one side could be a multiport of width 1 and the other an ordinary port. if (sourceWidth != null || destWidth != null) { var width = - (sourceAsPort.getWidthSpec() != null) - ? sourceContainerRef + sourceAsPort.getName() - : destContainerRef + destAsPort.getName(); + (sourceAsPort.getWidthSpec() != null) + ? sourceContainerRef + sourceAsPort.getName() + : destContainerRef + destAsPort.getName(); result.pr("for _lf_i in range(" + width + ".width):"); result.indent(); } @@ -621,11 +620,15 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, } @Override - protected void setUpGeneralParameters() { - super.setUpGeneralParameters(); - if (hasModalReactors) { - targetConfig.compileAdditionalSources.add("lib/modal_models/impl.c"); + protected boolean setUpGeneralParameters() { + boolean result = super.setUpGeneralParameters(); + if (result) { + if (hasModalReactors) { + targetConfig.compileAdditionalSources.add("lib/modal_models/impl.c"); + } + return true; } + return false; } @Override From af38cba0ef6dfec79dce8f01a7943126c3f8b63e Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 10 Oct 2024 16:52:04 -0700 Subject: [PATCH 10/12] unconditionally define variable --- .../java/org/lflang/generator/python/PythonGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java index 667207f267..f486c64a47 100644 --- a/core/src/main/java/org/lflang/generator/python/PythonGenerator.java +++ b/core/src/main/java/org/lflang/generator/python/PythonGenerator.java @@ -588,8 +588,8 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, + ((destWidth != null) ? "[" + destIndex + "]" : ""); var result = new CodeBuilder(); // If either side is a bank (only one side should be), iterate over it. + result.pr("_lf_c = 0"); // Counter variable over nested loop if there is a bank and multiport. if (isBank) { - result.pr("_lf_c = 0"); // Counter variable over nested loop if there is a bank and multiport. var width = new StringBuilder(); for (var term : bank.getWidthSpec().getTerms()) { if (!width.isEmpty()) width.append(" + "); @@ -611,11 +611,11 @@ protected String getConflictingConnectionsInModalReactorsBody(VarRef sourceRef, result.indent(); } result.pr(dest + ".set(" + source + ".value)"); + result.pr("_lf_c += 1"); // Increment the count. + result.unindent(); if (isBank) { - result.pr("_lf_c += 1"); // Increment the count. result.unindent(); } - result.unindent(); return result.toString(); } From dfa39901682c9e9684d6f250d50e10bc1a116447 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 13 Oct 2024 17:42:55 -0700 Subject: [PATCH 11/12] Avoid NPE --- core/src/main/java/org/lflang/ast/ASTUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 7e55e3cabc..ef66d24cd1 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -623,7 +623,7 @@ public static ReactorInstance createMainReactorInstance( messageReporter .nowhere() .error("Main reactor has causality cycles. Skipping code generation."); - return null; + return main; // Avoid NPE. } // Inform the run-time of the breadth/parallelism of the reaction graph var breadth = reactionInstanceGraph.getBreadth(); From 9aea6792941b97f510af6b9da24a43a2e840f057 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Wed, 16 Oct 2024 15:15:23 -0700 Subject: [PATCH 12/12] Temporarily move test to failing since failure is unrelated to this PR --- test/Python/src/concurrent/{ => failing}/ConcurrentAction.lf | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/Python/src/concurrent/{ => failing}/ConcurrentAction.lf (100%) diff --git a/test/Python/src/concurrent/ConcurrentAction.lf b/test/Python/src/concurrent/failing/ConcurrentAction.lf similarity index 100% rename from test/Python/src/concurrent/ConcurrentAction.lf rename to test/Python/src/concurrent/failing/ConcurrentAction.lf