blob: 92d5e22625164c4a17b6ffc2f27c55df04f90cd0 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2015, 2017 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.execution.logic.openmapping;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.app4mc.amalthea.model.ActivityGraph;
import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.Group;
import org.eclipse.app4mc.amalthea.model.ITimeDeviation;
import org.eclipse.app4mc.amalthea.model.PeriodicStimulus;
import org.eclipse.app4mc.amalthea.model.RelativePeriodicStimulus;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.RunnableCall;
import org.eclipse.app4mc.amalthea.model.Stimulus;
import org.eclipse.app4mc.amalthea.model.Task;
import org.eclipse.app4mc.amalthea.model.Time;
import org.eclipse.app4mc.amalthea.model.Value;
import org.eclipse.emf.ecore.EAttribute;
/**
*
*/
public class OMTask {
private final Task taskRef;
private OMTask predecessor = null;
private long iInstructionCount = -1;
private final List<OMEdge> post = new LinkedList<>();
private List<OMRunnable> runnableSequence;
private long period = -1;
public OMTask(final Task taskRef) {
this.taskRef = taskRef;
}
public OMTask(final Task taskRef, final OMTask predecessor) {
this.taskRef = taskRef;
this.predecessor = predecessor;
}
public Task getTaskRef() {
return this.taskRef;
}
public OMTask getPredecessor() {
return this.predecessor;
}
/**
*
* @return
*/
public long getInstructionCount() {
if (0 > this.iInstructionCount) {
// try to get instructioncount from property
// first
getPropertyInstructionCount();
}
if (0 > this.iInstructionCount) {
this.iInstructionCount = 0;
for (final OMRunnable r : getRunnableCallSequence()) {
this.iInstructionCount += r.getInstructionCount();
}
}
return this.iInstructionCount;
}
private boolean getPropertyInstructionCount() {
final Value x = getTaskRef().getCustomProperties().get("instructionCount");
if (x != null) {
final List<EAttribute> a = x.eClass().getEAttributes();
if (!a.isEmpty()) {
final Object o = x.eGet(a.get(0));
final long val = Long.parseLong(o.toString());
if (val > 0) {
this.iInstructionCount = val;
return true;
}
}
}
return false;
}
public long getRunnableCount() {
return getRunnableCallSequence().size();
}
@Override
public String toString() {
return this.taskRef.getUniqueName();
}
/**
* Get the period period of the task activation.
*
* @param t
* @return Period of the task in pico seconds or 0 if the task has no period
*/
public long getPeriod() {
if (this.period < 0) {
for (final Stimulus s : getTaskRef().getStimuli()) {
if (s instanceof PeriodicStimulus) {
final PeriodicStimulus ps = (PeriodicStimulus) s;
final Time x = ps.getRecurrence();
if (x == null) {
this.period = 0;
return this.period;
}
long val = x.getValue().longValue();
if (val == 0 || x.getUnit() == null) {
this.period = 0;
return this.period;
}
switch (x.getUnit()) {
case PS:
val *= 1; //
break;
case NS:
val *= 1000; //
break;
case US:
val *= 1000000L; //
break;
case MS:
val *= 1000000000L; //
break;
case S:
val *= 1000000000000L; //
break;
default:
this.period = 0;
return this.period;
}
this.period = val;
return this.period;
}
// Support fot FMTV
if (s instanceof RelativePeriodicStimulus) {
final RelativePeriodicStimulus spst = (RelativePeriodicStimulus) s;
final ITimeDeviation dev = spst.getNextOccurrence();
final Time x = dev.getLowerBound();
if (x == null) {
this.period = 0;
return this.period;
}
long val = x.getValue().longValue();
if (val == 0 || x.getUnit() == null) {
this.period = 0;
return this.period;
}
switch (x.getUnit()) {
case PS:
val *= 1; //
break;
case NS:
val *= 1000; //
break;
case US:
val *= 1000000L; //
break;
case MS:
val *= 1000000000L; //
break;
case S:
val *= 1000000000000L; //
break;
default:
this.period = 0;
return this.period;
}
this.period = val;
return this.period;
}
}
this.period = 0;// not periodic
}
return this.period;
}
public List<OMRunnable> getRunnableCallSequence() {
if (this.runnableSequence == null) {
try {
this.runnableSequence = createCallSequenceList().stream().map(OMRunnable::new)
.collect(Collectors.toList());
}
catch (final MalformedModelException e) {
this.runnableSequence = new LinkedList<>();
}
}
return this.runnableSequence;
}
private List<Runnable> createCallSequenceList() throws MalformedModelException {
final List<Runnable> list = new LinkedList<>();
final Task t = getTaskRef();
if (t == null) {
throw new MalformedModelException("No Task defined!");
}
final ActivityGraph graph = t.getActivityGraph();
if (graph == null) {
throw new MalformedModelException("No callgraph at task " + t.getName());
}
for (final ActivityGraphItem entry : graph.getItems()) {
if (entry instanceof Group) {
final Group seq = (Group) entry;
for (final ActivityGraphItem item : seq.getItems()) {
if (item instanceof RunnableCall) {
final RunnableCall call = (RunnableCall) item;
final Runnable r = call.getRunnable();
if (r == null) {
throw new MalformedModelException("Empty Runnable call at task " + t.getName());
}
list.add(r);
}
}
if (list.isEmpty()) {
throw new MalformedModelException("Empty CallSequence at task " + t.getName());
}
return list;
}
}
throw new MalformedModelException("No CallSequence defined!");
}
public List<OMEdge> getPosts() {
return this.post;
}
}