Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Python federated #675

Merged
merged 33 commits into from
Nov 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b2472a9
Moved the python generator and serialization support into separate pa…
Soroosh129 Oct 26, 2021
0c7a54e
Updated submodule
Soroosh129 Oct 26, 2021
ff85005
Made a simple HelloDistributed compilable
Soroosh129 Oct 26, 2021
a2492ee
Updated submodule
Soroosh129 Oct 26, 2021
838a57f
First step to add support for Python's pickle module for native seria…
Soroosh129 Oct 26, 2021
755b656
Updated submodule
Soroosh129 Oct 28, 2021
f2ddc43
First working version of native Python pickling. Fed test will fail b…
Soroosh129 Oct 28, 2021
ef58af1
Added a launcher for Python target programs
Soroosh129 Oct 28, 2021
4e13432
First working version of federated Python
Soroosh129 Oct 28, 2021
f4eee5d
Added Python main generator
Soroosh129 Oct 29, 2021
6f77275
Comments only
Soroosh129 Oct 29, 2021
9b58b17
Merge remote-tracking branch 'origin/master' into python-federated
Soroosh129 Oct 29, 2021
c232ed1
First attempt at making TestBase compatible with federated Python pro…
Soroosh129 Oct 29, 2021
9cd4e2a
Added run info when the program is federated
Soroosh129 Oct 29, 2021
86dde1f
Updated reactor-c-py
Soroosh129 Oct 29, 2021
9492865
Removing the tabs that snuck in FedLauncher.xtend during the refactoring
Soroosh129 Oct 29, 2021
48d262f
add tests
housengw Oct 31, 2021
16578fc
Merge remote-tracking branch 'origin/master' into python-federated
Soroosh129 Oct 31, 2021
758fcd3
port test/C/src/lib code over to test/Python/src/lib
housengw Nov 1, 2021
ca9530f
port more tests and fix syntax errors
housengw Nov 1, 2021
eef4f96
Merge remote-tracking branch 'origin/master' into python-federated
Soroosh129 Nov 1, 2021
d40d8ce
Only generate a dockerfile for the RTI if docker is set to true
Soroosh129 Nov 1, 2021
fd2650d
Fixes #703 I hope
Soroosh129 Nov 2, 2021
53ca5b5
port more test
housengw Nov 2, 2021
a90d40e
port tests and fix errors
housengw Nov 2, 2021
3c0da37
port more tests
housengw Nov 2, 2021
520bcaf
port more tests
housengw Nov 2, 2021
9b3f19d
port more tests
housengw Nov 3, 2021
02da970
Pointing submodule to a ref that actually exists
lhstrh Nov 4, 2021
2b4112c
Merge remote-tracking branch 'origin/master' into python-federated
Soroosh129 Nov 4, 2021
cda059c
Merge branch master
Soroosh129 Nov 7, 2021
65519d2
Revert "Merge branch master"
Soroosh129 Nov 7, 2021
9c033d0
Merge remote-tracking branch 'origin/master' into python-federated
Soroosh129 Nov 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion org.lflang.tests/src/org/lflang/tests/TestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,15 @@ private ProcessBuilder getExecCommand(LFTest test) {
}
}
case Python: {
var binPath = test.fileConfig.binPath;
var binaryName = nameOnly;
var fullPath = binPath.resolve(binaryName);
if (Files.exists(fullPath)) {
// If execution script exists, run it.
return new ProcessBuilder(fullPath.toString()).directory(binPath.toFile());
}
var srcGen = test.fileConfig.getSrcGenPath();
var fullPath = srcGen.resolve(nameOnly + ".py");
fullPath = srcGen.resolve(nameOnly + ".py");
if (Files.exists(fullPath)) {
return new ProcessBuilder("python3", fullPath.getFileName().toString())
.directory(srcGen.toFile());
Expand Down
2 changes: 1 addition & 1 deletion org.lflang/src/lib/py/reactor-c-py
7 changes: 5 additions & 2 deletions org.lflang/src/org/lflang/federated/FedASTUtils.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*************
* Copyright (c) 2021, The University of California at Berkeley.
* Copyright (c) 2021, The University of Texas at Dallas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -38,6 +39,7 @@
import org.lflang.InferredType;
import org.lflang.JavaAstUtils;
import org.lflang.TargetProperty.CoordinationType;
import org.lflang.federated.serialization.SupportedSerializers;
import org.lflang.TimeValue;
import org.lflang.generator.GeneratorBase;
import org.lflang.generator.PortInstance;
Expand All @@ -62,6 +64,7 @@
* execution.
*
* @author Soroush Bateni {soroush@utdallas.edu}
* @author Edward A. Lee {eal@berkeley.edu}
*
*/
public class FedASTUtils {
Expand Down Expand Up @@ -698,9 +701,9 @@ public static void makeCommunication(
serializer = SupportedSerializers.valueOf(
connection.getSerializer().getType().toUpperCase()
);
// Add it to the list of enabled serializers
generator.enabledSerializers.add(serializer);
}
// Add it to the list of enabled serializers
generator.enabledSerializers.add(serializer);

// Add the sender reaction.
addNetworkSenderReaction(
Expand Down
209 changes: 209 additions & 0 deletions org.lflang/src/org/lflang/federated/PythonGeneratorExtension.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*************
* Copyright (c) 2021, The University of Texas at Dallas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
***************/

package org.lflang.federated;

import org.lflang.InferredType;
import org.lflang.TargetProperty.CoordinationType;
import org.lflang.federated.serialization.FedNativePythonSerialization;
import org.lflang.federated.serialization.FedSerialization;
import org.lflang.federated.serialization.SupportedSerializers;
import org.lflang.generator.python.PythonGenerator;
import org.lflang.lf.Action;
import org.lflang.lf.Delay;
import org.lflang.lf.VarRef;

/**
* An extension class to the PythonGenerator that enables certain federated
* functionalities.
*
* @author Soroush Bateni {soroush@utdallas.edu}
*
*/
public class PythonGeneratorExtension {
/**
* Generate code for the body of a reaction that handles an output
* that is to be sent over the network.
* @param sendingPort The output port providing the data to send.
* @param receivingPort The variable reference to the destination port.
* @param receivingPortID The ID of the destination port.
* @param sendingFed The sending federate.
* @param sendingBankIndex The bank index of the sending federate, if it is a bank.
* @param sendingChannelIndex The channel index of the sending port, if it is a multiport.
* @param receivingFed The destination federate.
* @param type The type.
* @param isPhysical Indicates whether the connection is physical or not
* @param delay The delay value imposed on the connection using after
* @param serializer The serializer used on the connection.
* @param generator The instance of the PythonGenerator.
*/
public static String generateNetworkSenderBody(
VarRef sendingPort,
VarRef receivingPort,
int receivingPortID,
FederateInstance sendingFed,
int sendingBankIndex,
int sendingChannelIndex,
FederateInstance receivingFed,
InferredType type,
boolean isPhysical,
Delay delay,
SupportedSerializers serializer,
PythonGenerator generator
) {
String sendRef = generator.generatePortRef(sendingPort, sendingBankIndex, sendingChannelIndex);
String receiveRef = generator.generateVarRef(receivingPort); // Used for comments only, so no need for bank/multiport index.
StringBuilder result = new StringBuilder();
result.append("// Sending from " + sendRef +
" in federate " + sendingFed.name + " to " + receiveRef + " in federate " + receivingFed.name + "\n");
// If the connection is physical and the receiving federate is remote, send it directly on a socket.
// If the connection is logical and the coordination mode is centralized, send via RTI.
// If the connection is logical and the coordination mode is decentralized, send directly
String messageType;
// Name of the next immediate destination of this message
String next_destination_name = "\"federate " + receivingFed.id + "\"";

// Get the delay literal
String additionalDelayString =
CGeneratorExtension.getNetworkDelayLiteral(
delay,
generator
);

if (isPhysical) {
messageType = "MSG_TYPE_P2P_MESSAGE";
} else if (generator.getTargetConfig().coordination == CoordinationType.DECENTRALIZED) {
messageType = "MSG_TYPE_P2P_TAGGED_MESSAGE";
} else {
// Logical connection
// Send the message via rti
messageType = "MSG_TYPE_TAGGED_MESSAGE";
next_destination_name = "\"federate " + receivingFed.id + " via the RTI\"";
}


String sendingFunction = "send_timed_message";
String commonArgs = additionalDelayString + ", "
+ messageType + ", "
+ receivingPortID + ", "
+ receivingFed.id + ", "
+ next_destination_name + ", "
+ "message_length";
if (isPhysical) {
// Messages going on a physical connection do not
// carry a timestamp or require the delay;
sendingFunction = "send_message";
commonArgs = messageType + ", " + receivingPortID + ", " + receivingFed.id + ", "
+ next_destination_name + ", message_length";
}

var lengthExpression = "";
var pointerExpression = "";
switch (serializer) {
case NATIVE: {
var variableToSerialize = sendRef+"->value";
FedNativePythonSerialization pickler = new FedNativePythonSerialization();
lengthExpression = pickler.serializedBufferLength();
pointerExpression = pickler.seializedBufferVar();
result.append(
pickler.generateNetworkSerializerCode(variableToSerialize, null)
);
result.append("size_t message_length = "+lengthExpression+";\n");
result.append("info_print(\"Message length is %d\", message_length);\n");
result.append(sendingFunction+"("+commonArgs+", "+pointerExpression+");\n");
break;
}
case PROTO: {
throw new UnsupportedOperationException("Protbuf serialization is not supported yet.");
}
case ROS2: {
throw new UnsupportedOperationException("ROS2 serialization is not supported yet.");
}

}
return result.toString();
}

/**
* Generate code for the body of a reaction that handles the
* action that is triggered by receiving a message from a remote
* federate.
* @param action The action.
* @param sendingPort The output port providing the data to send.
* @param receivingPort The ID of the destination port.
* @param receivingPortID The ID of the destination port.
* @param sendingFed The sending federate.
* @param receivingFed The destination federate.
* @param receivingBankIndex The receiving federate's bank index, if it is in a bank.
* @param receivingChannelIndex The receiving federate's channel index, if it is a multiport.
* @param type The type.
* @param isPhysical Indicates whether or not the connection is physical
* @param serializer The serializer used on the connection.
* @param generator The instance of the PythonGenerator.
*/
public static String generateNetworkReceiverBody(
Action action,
VarRef sendingPort,
VarRef receivingPort,
int receivingPortID,
FederateInstance sendingFed,
FederateInstance receivingFed,
int receivingBankIndex,
int receivingChannelIndex,
InferredType type,
boolean isPhysical,
SupportedSerializers serializer,
PythonGenerator generator
) {

String receiveRef = generator.generatePortRef(receivingPort, receivingBankIndex, receivingChannelIndex);
StringBuilder result = new StringBuilder();

// Transfer the physical time of arrival from the action to the port
result.append(receiveRef+"->physical_time_of_arrival = self->_lf__"+action.getName()+".physical_time_of_arrival;\n");


String value = "";
switch (serializer) {
case NATIVE: {
value = action.getName();
FedNativePythonSerialization pickler = new FedNativePythonSerialization();
result.append(pickler.generateNetworkDeserializerCode(value, null));
result.append("SET("+receiveRef+", "+FedSerialization.deserializedVarName+");\n");
break;
}
case PROTO: {
throw new UnsupportedOperationException("Protbuf serialization is not supported yet.");
}
case ROS2: {
throw new UnsupportedOperationException("ROS2 serialization is not supported yet.");
}

}

return result.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***************/

package org.lflang.federated;
package org.lflang.federated.launcher;

import java.io.File;
import java.io.IOException;

import org.lflang.ErrorReporter;
import org.lflang.FileConfig;
import org.lflang.TargetConfig;
import org.lflang.federated.FedFileConfig;
import org.lflang.federated.FederateInstance;
import org.lflang.generator.c.CCompiler;

/**
Expand Down
Loading