blob: 6cf53b76c10d7ea876a5ee10da4c4428a224d1ba [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2020-2021 Robert Bosch GmbH.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Robert Bosch GmbH - initial API and implementation
* *******************************************************************************
*/
package org.eclipse.app4mc.slg.ros2.transformers.sw;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.BooleanObject;
import org.eclipse.app4mc.amalthea.model.Channel;
import org.eclipse.app4mc.amalthea.model.ChannelSend;
import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.slg.commons.m2t.transformers.SLGTranslationUnit;
import org.eclipse.app4mc.slg.commons.m2t.transformers.sw.RunnableTransformer;
import org.eclipse.app4mc.slg.ros2.generators.RosRunnableGenerator;
import org.eclipse.app4mc.slg.ros2.transformers.utils.Utils;
import org.eclipse.app4mc.transformation.util.OutputBuffer;
import com.google.inject.Inject;
public class RosRunnableTransformer extends RunnableTransformer {
public static final String LIB_NAME = "RUNNABLES_LIB";
public static final String BASE_PATH = "synthetic_gen";
public static final String MODULE_NAME = "runnables";
public static final String MODULE_PATH = BASE_PATH + "/" + MODULE_NAME;
public static final String MAKEFILE_PATH = MODULE_PATH + "/CMakeLists.txt";
@Inject private OutputBuffer outputBuffer;
@Inject private RosActivityGraphItemTransformer activityGraphItemTransformer;
@Inject private RosRunnableCache rosRunnableCache;
@Override
public void genFiles(SLGTranslationUnit tu, Runnable runnable) {
if (isSrcFileEmpty(tu)) { // all stuff only required once regardless of runnable instance
srcAppend(tu, "#include \"" + getIncFile(tu) + "\"\n");
}
final HashSet<String> includes = new LinkedHashSet<>();
final List<String> calls = new ArrayList<>();
boolean measurePerformance = false;
if (runnable != null && runnable.getCustomProperties().get("measure_performance") instanceof BooleanObject) {
measurePerformance = ((BooleanObject) runnable.getCustomProperties().get("measure_performance")).isValue();
}
if (measurePerformance) {
includes.add("aml.h");
}
// Compute characteristic values of runnable
String param = "";
String nodeParam = "";
final List<String> publishers = new ArrayList<>();
final List<String> clientDeclarations = new ArrayList<>();
final List<String> clientInits = new ArrayList<>();
if (runnable != null && runnable.getActivityGraph() != null) {
for (ActivityGraphItem item : runnable.getActivityGraph().getItems()) {
final SLGTranslationUnit graphItemTU = activityGraphItemTransformer.transform(item);
String graphItemIncFile = getIncFile(graphItemTU);
if (graphItemIncFile != null && !graphItemIncFile.isEmpty() && !getIncFile(tu).equals(graphItemIncFile)) {
includes.add(graphItemIncFile);
}
// check if item is publisher
if (item instanceof ChannelSend) {
ChannelSend cs = (ChannelSend) item;
Channel data = cs.getData();
publishers.add(data.getName() + "_publisher");
nodeParam = nodeParam + ((nodeParam.equals("")) ? "" : ";") + data.getName() + "_publisher";
param = ((param.equals("")) ? "" : ";") + "rclcpp::Publisher<std_msgs::msg::String>::SharedPtr& "
+ data.getName() + "_publisher";
}
if (item instanceof InterProcessTrigger) {
InterProcessTrigger trigger = (InterProcessTrigger) item;
InterProcessStimulus stimulus = trigger.getStimulus();
includes.add(stimulus.getName() + "_service/srv/" + stimulus.getName() + "_service" + ".hpp");
clientDeclarations.add(
"rclcpp::Client<" + stimulus.getName() + "_service::srv::"
+ Utils.toIdlCompliantName(stimulus.getName() + "_service")
+ ">::SharedPtr " + stimulus.getName() + "_client");
clientInits.add(
stimulus.getName() + "_client = this->create_client<" + stimulus.getName() + "_service::srv::"
+ Utils.toIdlCompliantName(stimulus.getName() + "_service") + ">"
+ "(\"" + stimulus.getName() + "_service\")");
nodeParam = nodeParam + (nodeParam.equals("") ? "" : ";") + stimulus.getName() + "_client";
param = (param.equals("") ? "" : ";") + "rclcpp::Client<"
+ stimulus.getName() + "_service::srv::" + Utils.toIdlCompliantName(stimulus.getName() + "_service")
+ ">::SharedPtr& " + stimulus.getName() + "_client";
}
final String call = graphItemTU.getCall();
if (call != null && !call.isEmpty()) {
calls.add(call);
}
}
}
// store characteristic values in runnable cache
rosRunnableCache.storeValues(tu, runnable, param, nodeParam, publishers, clientDeclarations, clientInits);
String fullCall = "run_" + runnable.getName() + "(" + param + ")";
// write header
incAppend(tu, "\n//Runnable " + runnable.getName() + "----\n");
toH(tu, includes, fullCall);
// write body
srcAppend(tu, "\n//Runnable " + runnable.getName() + "----\n");
toCpp(tu, runnable.getName(), fullCall, calls, measurePerformance);
}
private void toH(SLGTranslationUnit tu, final HashSet<String> includes, final String fullCall) {
for (String include : includes) {
incAppend(tu, "#include \"" + include + "\"\n");
}
incAppend(tu, "void " + fullCall + ";\n");
}
private void toCpp(SLGTranslationUnit tu, final String runnableName, final String fullCall, final List<String> calls, boolean measurePerformance) {
srcAppend(tu, "void " + fullCall + "{\n");
if (measurePerformance) {
srcAppend(tu,
"uint64_t event_list[] = {0x11, 0x13, 0x17}; //CPU CYCLES, MEM ACCESS, L2 Cache Refill\n"
+ "int total_events = sizeof(event_list)/sizeof(event_list[0]);\n"
+ "int fd = instrument_start(0,event_list, total_events);\n");
}
for (String call : calls) {
srcAppend(tu, "\t" + call + ";\n");
}
if (measurePerformance) {
srcAppend(tu, "instrument_stop(fd, \"" + runnableName + ".log\");\n");
}
srcAppend(tu, "}\n\n");
}
@Override
public boolean createCMake() {
return outputBuffer.appendTo(
"OTHER", MAKEFILE_PATH, RosRunnableGenerator.toCMake(LIB_NAME, getSrcFiles()));
}
}