blob: 5a413a615d37ecd9fe8a1a1a72a27f394e0dc57d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017-2020 Dortmund University of Applied Sciences and Arts and others.
*
* 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:
* Dortmund University of Applied Sciences and Arts - initial API and implementation
*******************************************************************************/
package org.eclipse.app4mc.multicore.partitioning.utils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.app4mc.amalthea.model.ASILType;
import org.eclipse.app4mc.amalthea.model.Activation;
import org.eclipse.app4mc.amalthea.model.AmaltheaFactory;
import org.eclipse.app4mc.amalthea.model.ProcessPrototype;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.RunnableCall;
import org.eclipse.app4mc.amalthea.model.SWModel;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.slf4j.LoggerFactory;
/**
* This class creates ProcessPrototypes if ASIL levels are assigned to runnables
* and adds runnable calls correspondingly
*/
public class AsilToPP {
public AsilToPP(final SWModel swmp) {
this.swm = swmp;
}
private final SWModel swm;
/**
* Creates ProcessPrototypes for each referenced ASIL level and assigns
* runnables correspondingly. May result in multiple RunnablesCalls for the
* same runnable if other ProcessPrototypes are already existing.
*/
public void createPPsFromASILs() {
for (final ASILType at : ASILType.values()) {
if (runnableRefsASIL(at)) {
final ProcessPrototype pp = AmaltheaFactory.eINSTANCE.createProcessPrototype();
pp.setName(at.getName());
for (final Runnable r : getAsilRunnables(at)) {
final RunnableCall trc = AmaltheaFactory.eINSTANCE.createRunnableCall();
trc.setRunnable(r);
pp.getRunnableCalls().add(trc);
}
if (!pp.getRunnableCalls().isEmpty()) {
this.swm.getProcessPrototypes().add(pp);
}
}
}
if (!new Helper().tRCsAreConsist(this.swm)) {
LoggerFactory.getLogger(AsilToPP.class).error("There are runnables called more than once");
}
}
/**
* Creates ProcessPrototypes (max 4) for each referenced ASIL level and
* assigns runnables correspondingly. Considers existing ProcessPrototypes,
* such that RunnableCalls are removed from existing ProcessPrototypes if
* corresponding runnables reference ASIL levels.
*/
public void createPPsFromASILsSplit() {
final EList<ProcessPrototype> newPPs = new BasicEList<>();
for (final ProcessPrototype pp : this.swm.getProcessPrototypes()) {
ASILType at = null;
final Iterator<RunnableCall> it = pp.getRunnableCalls().iterator();
while (it.hasNext()) {
final RunnableCall trc = it.next();
final Runnable r = trc.getRunnable();
if (null == at && null != r.getAsilLevel()) {
at = r.getAsilLevel();
}
else if (null != at && null != r.getAsilLevel() && !at.equals(r.getAsilLevel())) {
createASILPP(newPPs, it, trc, r);
}
}
}
this.swm.getProcessPrototypes().addAll(newPPs);
}
private void createASILPP(final EList<ProcessPrototype> newPPs, final Iterator<RunnableCall> it, final RunnableCall trc,
final Runnable r) {
final RunnableCall trcnew = AmaltheaFactory.eINSTANCE.createRunnableCall();
trcnew.setRunnable(trc.getRunnable());
if (!newPPsContains(newPPs, r.getAsilLevel(), r.getFirstActivation())) {
final ProcessPrototype ppNew = AmaltheaFactory.eINSTANCE.createProcessPrototype();
ppNew.setName("ASIL-" + r.getAsilLevel().toString());
if (null != r.getFirstActivation()) {
ppNew.setName(ppNew.getName() + "_" + r.getFirstActivation().getName());
}
ppNew.getRunnableCalls().add(trcnew);
newPPs.add(ppNew);
it.remove();
}
else {
addTrcToNewAsilPP(newPPs, trcnew);
it.remove();
}
}
/**
* Splits existing ProcessPrototypes for each referenced ASIL level and
* assigens runnables correspondingly. Potentially may result in max #PPs*5
*/
public void createPPsFromASILsSplitEach() {
final EList<ProcessPrototype> newPPs = new BasicEList<>();
final Iterator<ProcessPrototype> ppit = this.swm.getProcessPrototypes().iterator();
while (ppit.hasNext()) {
final ProcessPrototype pp = ppit.next();
final List<ASILType> asils = new ArrayList<>();
final List<RunnableCall> asiltrcs = pp.getRunnableCalls().stream().distinct().filter(
trc -> (null != trc.getRunnable().getAsilLevel() && !trc.getRunnable().getAsilLevel().toString().equals("_undefined_")))
.collect(Collectors.toList());
asiltrcs.stream().forEach(trc -> asils.add(trc.getRunnable().getAsilLevel()));
final List<ASILType> asilsd = asils.stream().distinct().collect(Collectors.toList());
for (final ASILType at : asilsd) {
final ProcessPrototype ppa = AmaltheaFactory.eINSTANCE.createProcessPrototype();
ppa.setName(pp.getName() + "_" + at.getName());
ppa.setActivation(pp.getActivation());
ppa.getRunnableCalls()
.addAll(asiltrcs.stream().filter(trc -> trc.getRunnable().getAsilLevel().equals(at)).collect(Collectors.toList()));
pp.getRunnableCalls().removeAll(ppa.getRunnableCalls());
if (pp.getRunnableCalls().isEmpty()) {
ppit.remove();
}
newPPs.add(ppa);
}
}
this.swm.getProcessPrototypes().addAll(newPPs);
}
private void addTrcToNewAsilPP(final EList<ProcessPrototype> newPPs, final RunnableCall trcnew) {
for (final ProcessPrototype pp : newPPs) {
if (null != pp.getRunnableCalls().get(0)) {
final Runnable r = pp.getRunnableCalls().get(0).getRunnable();
if (r.getAsilLevel().equals(trcnew.getRunnable().getAsilLevel())) {
pp.getRunnableCalls().add(trcnew);
break;
}
}
}
}
private boolean newPPsContains(final EList<ProcessPrototype> newPPs, final ASILType asilLevel, final Activation activation) {
for (final ProcessPrototype pp : newPPs) {
if (!pp.getRunnableCalls().isEmpty()) {
final RunnableCall trc = pp.getRunnableCalls().get(0);
if (trc.getRunnable().getAsilLevel().equals(asilLevel) && trc.getRunnable().getFirstActivation().equals(activation)) {
return true;
}
}
}
return false;
}
private EList<Runnable> getAsilRunnables(final ASILType at) {
final EList<Runnable> asilruns = new BasicEList<>();
for (final Runnable r : this.swm.getRunnables()) {
if (r.getAsilLevel().equals(at)) {
asilruns.add(r);
}
}
return asilruns;
}
private boolean runnableRefsASIL(final ASILType at) {
for (final Runnable r : this.swm.getRunnables()) {
if (null != r.getAsilLevel() && !r.getAsilLevel().getName().equals("_undefined_") && r.getAsilLevel().equals(at)) {
return true;
}
}
return false;
}
}