blob: 48ef88fe752b0e2fa145fa2fd968d3a3379584c8 [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.customization;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
import org.eclipse.app4mc.amalthea.model.Process;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.Ticks;
import org.eclipse.app4mc.slg.commons.m2t.transformers.SLGTranslationUnit;
import org.eclipse.app4mc.slg.commons.m2t.transformers.sw.ActivityGraphItemTransformer;
import org.eclipse.app4mc.slg.commons.m2t.transformers.sw.RunnableTransformer;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class CustomRunnableTransformer extends RunnableTransformer {
@Inject private ActivityGraphItemTransformer activityGraphItemTransformer;
// ---------- generic part "def create new transform(...)" ----------
private final Map<List<Object>, SLGTranslationUnit> transformCache = new HashMap<>();
@Override
public Map<List<Object>, SLGTranslationUnit> getCache() {
return this.transformCache;
}
@Override
public SLGTranslationUnit transform(final Runnable runnable) {
final List<Object> key = new ArrayList<>(Arrays.asList(runnable));
final SLGTranslationUnit tu;
synchronized (transformCache) {
if (transformCache.containsKey(key)) {
return transformCache.get(key);
}
tu = createTranslationUnit(runnable);
transformCache.put(key, tu);
}
// if translation unit is newly created and valid -> create files
if (tu.isValid()) {
doTransform(tu, runnable);
}
return tu;
}
// ---------------------------------------------------
@Override
protected SLGTranslationUnit createTranslationUnit(final Runnable runnable) {
if ((runnable == null)) {
return new SLGTranslationUnit("UNSPECIFIED RUNNABLE");
} else {
String basePath = "synthetic_gen";
String moduleName = "runnables";
String call = "run_" + runnable.getName();
return new SLGTranslationUnit(basePath, moduleName, call);
}
}
@Override
protected void doTransform(final SLGTranslationUnit tu, final Runnable runnable) {
genFiles(tu, runnable);
}
@Override
protected void genFiles(final SLGTranslationUnit tu, final Runnable runnable) {
if (isSrcFileEmpty(tu)) {
srcAppend(tu, "#include \"" + getIncFile(tu) + "\"\n");
srcAppend(tu, "#include \"ticksUtils.h\"\n");
}
final HashSet<String> includes = new LinkedHashSet<>();
final List<String> calls = new ArrayList<>();
final List<Process> processedTasks = new ArrayList<>();
if (runnable != null && runnable.getActivityGraph() != null) {
for (final ActivityGraphItem item : runnable.getActivityGraph().getItems()) {
if (item instanceof Ticks) {
Ticks ticks = (Ticks) item;
final Map<String, SLGTranslationUnit> translationUnits = activityGraphItemTransformer.transformAllItems(ticks); // Mc: move method to TicksTransformer ?
SLGTranslationUnit defaultTicksTU = null;
boolean ticksAssociatedToPUs = false;
for (final Entry<String, SLGTranslationUnit> entry : translationUnits.entrySet()) {
String puName = entry.getKey();
SLGTranslationUnit tmpTU = entry.getValue();
if (puName.equals("default")) {
defaultTicksTU = tmpTU;
} else {
final String tmpIncFile = getIncFile(tmpTU);
if (tmpIncFile != null && !tmpIncFile.isEmpty() && !getIncFile(tu).equals(tmpIncFile)) {
includes.add(tmpIncFile);
}
final String call = tmpTU.getCall();
if (call != null && !call.isEmpty()) {
calls.add(ticksAssociatedToPUs ? "else if(strcmp(coreName,\"" + puName + "\")==0){" : " if(strcmp(coreName,\"" + puName + "\")==0){");
calls.add(call);
calls.add("}");
ticksAssociatedToPUs = true;
}
}
}
if ((defaultTicksTU != null)) {
if (ticksAssociatedToPUs) {
calls.add("else ");
calls.add("{");
}
if (defaultTicksTU.getCall() != null && !defaultTicksTU.getCall().isEmpty()) {
calls.add(defaultTicksTU.getCall());
}
if (ticksAssociatedToPUs) {
calls.add("}");
}
}
} else {
if ((item instanceof InterProcessTrigger)) {
InterProcessTrigger trigger = (InterProcessTrigger) item;
final String value = CustomRunnableGenerator.handleInterProcessTrigger(trigger.getStimulus(), processedTasks);
if (value != null && !value.trim().isEmpty()) {
calls.add(value);
}
} else {
final SLGTranslationUnit tmpTU = activityGraphItemTransformer.transform(item);
final String tmpIncFile = getIncFile(tmpTU);
if (tmpIncFile != null && !tmpIncFile.isEmpty() && !getIncFile(tu).equals(tmpIncFile)) {
includes.add(tmpIncFile);
}
final String call = tmpTU.getCall();
if (call != null && !call.isEmpty()) {
calls.add(call);
}
}
}
}
}
String runnableName = runnable.getName();
// write header
this.toH(tu, runnableName, includes);
// write body
srcAppend(tu, "\n//Runnable " + runnableName + "----\n");
toCpp(tu, calls);
}
protected void toH(final SLGTranslationUnit tu, final String runnableName, final HashSet<String> includes) {
if (isIncFileEmpty(tu)) {
incAppend(tu, "#include <string.h>\n");
}
for(String include : includes) {
incAppend(tu, "#include \"" + include + "\"\n");
}
incAppend(tu, "\n//Runnable " + runnableName + "----\n");
incAppend(tu, "void " + tu.getCall() + "(char* coreName);\n");
}
@Override
protected void toCpp(final SLGTranslationUnit tu, final List<String> calls) {
srcAppend(tu, "void " + tu.getCall() + "(char* coreName){\n");
for (String call : calls) {
srcAppend(tu, "\t" + call + (call.endsWith(")") ? ";" : "") + "\n");
}
srcAppend(tu, "}\n\n");
}
}