Skip to content

Commit

Permalink
Merge pull request #1011 from lf-lang/xtend-to-java-c-generator
Browse files Browse the repository at this point in the history
Partial refactoring and porting to Java of `CGenerator.xtend`
  • Loading branch information
lhstrh authored Mar 11, 2022
2 parents 9fb6267 + c230b1d commit e4567a4
Show file tree
Hide file tree
Showing 25 changed files with 1,963 additions and 1,366 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ protected String executeCommandForLocalFederate(FileConfig fileConfig,
*
*/
public void createLauncher(
ArrayList<String> coreFiles,
List<FederateInstance> federates,
LinkedHashMap<String, Object> federationRTIProperties
) throws IOException {
Expand Down
72 changes: 72 additions & 0 deletions org.lflang/src/org/lflang/generator/DockerComposeGenerator.java
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 org.lflang/src/org/lflang/generator/c/CActionGenerator.java
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 org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java
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 org.lflang/src/org/lflang/generator/c/CDockerGenerator.java
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"
);
}
}
Loading

0 comments on commit e4567a4

Please sign in to comment.