| /** |
| ******************************************************************************** |
| * 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; |
| } |
| |
| } |