-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1011 from lf-lang/xtend-to-java-c-generator
Partial refactoring and porting to Java of `CGenerator.xtend`
- Loading branch information
Showing
25 changed files
with
1,963 additions
and
1,366 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
org.lflang/src/org/lflang/generator/DockerComposeGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package org.lflang.generator; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import org.eclipse.xtext.xbase.lib.Exceptions; | ||
|
||
/** | ||
* Generates the content of the docker-compose.yml file | ||
* used to deploy containerized LF programs. | ||
* | ||
* @author{Hou Seng Wong <[email protected]>} | ||
*/ | ||
public class DockerComposeGenerator { | ||
/** | ||
* Write the docker-compose.yml for orchestrating the federates. | ||
* @param the directory to write the docker-compose.yml | ||
* @param content of the "services" section of the docker-compose.yml | ||
* @param the name of the network hosting the federation | ||
*/ | ||
public static void writeFederatesDockerComposeFile( | ||
File dir, | ||
StringBuilder dockerComposeServices, | ||
String networkName | ||
) { | ||
var dockerComposeFileName = "docker-compose.yml"; | ||
var dockerComposeFile = dir + File.separator + dockerComposeFileName; | ||
var contents = new CodeBuilder(); | ||
contents.pr(String.join("\n", | ||
"version: \"3.9\"", | ||
"services:", | ||
dockerComposeServices.toString(), | ||
"networks:", | ||
" lingua-franca:", | ||
" name: "+networkName | ||
)); | ||
try { | ||
contents.writeToFile(dockerComposeFile); | ||
} catch (IOException e) { | ||
throw Exceptions.sneakyThrow(e); | ||
} | ||
} | ||
|
||
/** | ||
* Append a service to the "services" section of the docker-compose.yml file. | ||
* @param the content of the "services" section of the docker-compose.yml file. | ||
* @param the name of the federate to be added to "services". | ||
* @param the name of the federate's Dockerfile. | ||
*/ | ||
public static void appendFederateToDockerComposeServices(StringBuilder dockerComposeServices, String federateName, String context, String dockerFileName) { | ||
var tab = " ".repeat(4); | ||
dockerComposeServices.append(tab+federateName+":\n"); | ||
dockerComposeServices.append(tab+tab+"build:\n"); | ||
dockerComposeServices.append(tab+tab+tab+"context: "+context+"\n"); | ||
dockerComposeServices.append(tab+tab+tab+"dockerfile: "+dockerFileName+"\n"); | ||
dockerComposeServices.append(tab+tab+"command: -i 1\n"); | ||
} | ||
|
||
/** | ||
* Append the RTI to the "services" section of the docker-compose.yml file. | ||
* @param the content of the "services" section of the docker-compose.yml file. | ||
* @param the name given to the RTI in the "services" section. | ||
* @param the tag of the RTI's image. | ||
* @param the number of federates. | ||
*/ | ||
public static void appendRtiToDockerComposeServices(StringBuilder dockerComposeServices, String dockerImageName, String hostName, int n) { | ||
var tab = " ".repeat(4); | ||
dockerComposeServices.append(tab+"rti:\n"); | ||
dockerComposeServices.append(tab+tab+"image: "+dockerImageName+"\n"); | ||
dockerComposeServices.append(tab+tab+"hostname: "+hostName+"\n"); | ||
dockerComposeServices.append(tab+tab+"command: -i 1 -n "+n+"\n"); | ||
} | ||
} |
112 changes: 112 additions & 0 deletions
112
org.lflang/src/org/lflang/generator/c/CActionGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package org.lflang.generator.c; | ||
|
||
import java.util.List; | ||
import java.util.ArrayList; | ||
|
||
import org.lflang.ASTUtils; | ||
import org.lflang.federated.FederateInstance; | ||
import org.lflang.generator.ActionInstance; | ||
import org.lflang.generator.CodeBuilder; | ||
import org.lflang.generator.GeneratorBase; | ||
import org.lflang.generator.ReactorInstance; | ||
import org.lflang.lf.Action; | ||
import org.lflang.lf.Reactor; | ||
import org.lflang.lf.ReactorDecl; | ||
|
||
/** | ||
* Generates code for actions (logical or physical) for the C and CCpp target. | ||
* | ||
* @author{Edward A. Lee <[email protected]>} | ||
* @author{Marten Lohstroh <[email protected]>} | ||
* @author{Mehrdad Niknami <[email protected]>} | ||
* @author{Christian Menard <[email protected]>} | ||
* @author{Matt Weber <[email protected]>} | ||
* @author{Soroush Bateni <[email protected]> | ||
* @author{Alexander Schulz-Rosengarten <[email protected]>} | ||
* @author{Hou Seng Wong <[email protected]>} | ||
*/ | ||
public class CActionGenerator { | ||
/** | ||
* For each action of the specified reactor instance, generate initialization code | ||
* for the offset and period fields. | ||
* @param instance The reactor. | ||
* @param currentFederate The federate we are | ||
*/ | ||
public static String generateInitializers( | ||
ReactorInstance instance, | ||
FederateInstance currentFederate | ||
) { | ||
List<String> code = new ArrayList<>(); | ||
for (ActionInstance action : instance.actions) { | ||
if (currentFederate.contains(action.getDefinition()) && | ||
!action.isShutdown() | ||
) { | ||
var triggerStructName = CUtil.reactorRef(action.getParent()) + "->_lf__" + action.getName(); | ||
var minDelay = action.getMinDelay(); | ||
var minSpacing = action.getMinSpacing(); | ||
var offsetInitializer = triggerStructName+".offset = " + GeneratorBase.timeInTargetLanguage(minDelay) + ";"; | ||
var periodInitializer = triggerStructName+".period = " + (minSpacing != null ? | ||
GeneratorBase.timeInTargetLanguage(minSpacing) : | ||
CGenerator.UNDEFINED_MIN_SPACING) + ";"; | ||
code.addAll(List.of( | ||
"// Initializing action "+action.getFullName(), | ||
offsetInitializer, | ||
periodInitializer | ||
)); | ||
|
||
var mode = action.getMode(false); | ||
if (mode != null) { | ||
var modeParent = mode.getParent(); | ||
var modeRef = "&"+CUtil.reactorRef(modeParent)+"->_lf__modes["+modeParent.modes.indexOf(mode)+"];"; | ||
code.add(triggerStructName+".mode = "+modeRef+";"); | ||
} else { | ||
code.add(triggerStructName+".mode = NULL;"); | ||
} | ||
} | ||
} | ||
return String.join("\n", code); | ||
} | ||
|
||
/** | ||
* Create a reference token initialized to the payload size. | ||
* This token is marked to not be freed so that the trigger_t struct | ||
* always has a reference token. | ||
* At the start of each time step, we need to initialize the is_present field | ||
* of each action's trigger object to false and free a previously | ||
* allocated token if appropriate. This code sets up the table that does that. | ||
* | ||
* @param selfStruct The variable name of the self struct | ||
* @param actionName The action name | ||
* @param payloadSize The code that returns the size of the action's payload in C. | ||
*/ | ||
public static String generateTokenInitializer( | ||
String selfStruct, | ||
String actionName, | ||
String payloadSize | ||
) { | ||
return String.join("\n", | ||
selfStruct+"->_lf__"+actionName+".token = _lf_create_token("+payloadSize+");", | ||
selfStruct+"->_lf__"+actionName+".status = absent;", | ||
"_lf_tokens_with_ref_count[_lf_tokens_with_ref_count_count].token = &"+selfStruct+"->_lf__"+actionName+".token;", | ||
"_lf_tokens_with_ref_count[_lf_tokens_with_ref_count_count].status = &"+selfStruct+"->_lf__"+actionName+".status;", | ||
"_lf_tokens_with_ref_count[_lf_tokens_with_ref_count_count++].reset_is_present = true;" | ||
); | ||
} | ||
|
||
public static void generateDeclarations( | ||
Reactor reactor, | ||
ReactorDecl decl, | ||
FederateInstance currentFederate, | ||
CodeBuilder body, | ||
CodeBuilder constructorCode | ||
) { | ||
for (Action action : ASTUtils.allActions(reactor)) { | ||
if (currentFederate.contains(action)) { | ||
var actionName = action.getName(); | ||
body.pr(action, CGenerator.variableStructType(action, decl)+" _lf_"+actionName+";"); | ||
// Initialize the trigger pointer in the action. | ||
constructorCode.pr(action, "self->_lf_"+actionName+".trigger = &self->_lf__"+actionName+";"); | ||
} | ||
} | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package org.lflang.generator.c; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.lflang.TargetProperty.SchedulerOption; | ||
|
||
/** | ||
* Generates the list of files to be included in the | ||
* core library for each reactor given conditions listed | ||
* as arguments of each function. | ||
* | ||
* @author{Hou Seng Wong <[email protected]>} | ||
*/ | ||
public class CCoreFilesUtils { | ||
public static List<String> getCoreFiles( | ||
boolean isFederated, | ||
boolean threading, | ||
SchedulerOption scheduler | ||
) { | ||
List<String> coreFiles = new ArrayList<>(); | ||
coreFiles.addAll(getBaseCoreFiles()); | ||
coreFiles.addAll(getPlatformFiles()); | ||
if (isFederated) { | ||
coreFiles.addAll(getFederatedFiles()); | ||
} | ||
coreFiles.addAll(getThreadSupportFiles(threading, scheduler)); | ||
return coreFiles; | ||
} | ||
|
||
private static List<String> getBaseCoreFiles() { | ||
return List.of( | ||
"reactor_common.c", | ||
"reactor.h", | ||
"tag.h", | ||
"tag.c", | ||
"trace.h", | ||
"trace.c", | ||
"utils/pqueue.c", | ||
"utils/pqueue.h", | ||
"utils/pqueue_support.h", | ||
"utils/vector.c", | ||
"utils/vector.h", | ||
"utils/semaphore.h", | ||
"utils/semaphore.c", | ||
"utils/util.h", | ||
"utils/util.c", | ||
"platform.h", | ||
"platform/Platform.cmake", | ||
"mixed_radix.c", | ||
"mixed_radix.h" | ||
); | ||
} | ||
|
||
private static List<String> getPlatformFiles() { | ||
return List.of( | ||
"platform/lf_tag_64_32.h", | ||
"platform/lf_POSIX_threads_support.c", | ||
"platform/lf_C11_threads_support.c", | ||
"platform/lf_C11_threads_support.h", | ||
"platform/lf_POSIX_threads_support.h", | ||
"platform/lf_POSIX_threads_support.c", | ||
"platform/lf_unix_clock_support.c", | ||
"platform/lf_unix_syscall_support.c", | ||
"platform/lf_macos_support.c", | ||
"platform/lf_macos_support.h", | ||
"platform/lf_windows_support.c", | ||
"platform/lf_windows_support.h", | ||
"platform/lf_linux_support.c", | ||
"platform/lf_linux_support.h" | ||
); | ||
} | ||
|
||
private static List<String> getFederatedFiles() { | ||
return List.of( | ||
"federated/net_util.c", | ||
"federated/net_util.h", | ||
"federated/net_common.h", | ||
"federated/federate.c", | ||
"federated/federate.h", | ||
"federated/clock-sync.h", | ||
"federated/clock-sync.c" | ||
); | ||
} | ||
|
||
private static List<String> getThreadSupportFiles( | ||
boolean threading, | ||
SchedulerOption scheduler | ||
) { | ||
return threading ? | ||
List.of( | ||
"threaded/scheduler.h", | ||
"threaded/scheduler_instance.h", | ||
"threaded/scheduler_sync_tag_advance.c", | ||
"threaded/scheduler_" + scheduler + ".c", | ||
"threaded/reactor_threaded.c" | ||
) : | ||
List.of("reactor.c"); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
org.lflang/src/org/lflang/generator/c/CDockerGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package org.lflang.generator.c; | ||
|
||
import java.nio.file.Path; | ||
|
||
/** | ||
* Generates the docker file related code for the C and CCpp target. | ||
* | ||
* @author{Edward A. Lee <[email protected]>} | ||
* @author{Hou Seng Wong <[email protected]>} | ||
*/ | ||
public class CDockerGenerator { | ||
public static String generateDockerFileContent( | ||
String topLevelName, | ||
String baseImage, | ||
String compiler, | ||
String compileCommand, | ||
Path srcGenPath | ||
) { | ||
return String.join("\n", | ||
"# Generated docker file for "+topLevelName+" in "+srcGenPath+".", | ||
"# For instructions, see: https://github.com/icyphy/lingua-franca/wiki/Containerized-Execution", | ||
"FROM "+baseImage+" AS builder", | ||
"WORKDIR /lingua-franca/"+topLevelName, | ||
"RUN set -ex && apk add --no-cache "+compiler+" musl-dev cmake make", | ||
"COPY . src-gen", | ||
compileCommand, | ||
"", | ||
"FROM "+baseImage, | ||
"WORKDIR /lingua-franca", | ||
"RUN mkdir bin", | ||
"COPY --from=builder /lingua-franca/"+topLevelName+"/bin/"+topLevelName+" ./bin/"+topLevelName, | ||
"", | ||
"# Use ENTRYPOINT not CMD so that command-line arguments go through", | ||
"ENTRYPOINT [\"./bin/"+topLevelName+"\"]" | ||
); | ||
} | ||
|
||
public static String generateDefaultCompileCommand() { | ||
return String.join("\n", | ||
"RUN set -ex && \\", | ||
"mkdir bin && \\", | ||
"cmake -S src-gen -B bin && \\", | ||
"cd bin && \\", | ||
"make all" | ||
); | ||
} | ||
} |
Oops, something went wrong.