blob: 895b4b88c04093d36267b169b86474c67f908530 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* FH Dortmund - initial API and implementation
*******************************************************************************/
package org.eclipse.app4mc.gsoc_rta;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.log4j.Logger;
import org.eclipse.app4mc.amalthea.model.Amalthea;
import org.eclipse.app4mc.amalthea.model.AmaltheaFactory;
import org.eclipse.app4mc.amalthea.model.CallSequence;
import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
import org.eclipse.app4mc.amalthea.model.DiscreteValueConstant;
import org.eclipse.app4mc.amalthea.model.DiscreteValueStatistics;
import org.eclipse.app4mc.amalthea.model.ExecutionNeed;
import org.eclipse.app4mc.amalthea.model.GraphEntryBase;
import org.eclipse.app4mc.amalthea.model.HwDefinition;
import org.eclipse.app4mc.amalthea.model.IDiscreteValueDeviation;
import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
import org.eclipse.app4mc.amalthea.model.Label;
import org.eclipse.app4mc.amalthea.model.LabelAccess;
import org.eclipse.app4mc.amalthea.model.LabelAccessEnum;
import org.eclipse.app4mc.amalthea.model.MappingModel;
import org.eclipse.app4mc.amalthea.model.PeriodicStimulus;
import org.eclipse.app4mc.amalthea.model.Process;
import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
import org.eclipse.app4mc.amalthea.model.ProcessingUnitDefinition;
import org.eclipse.app4mc.amalthea.model.PuType;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.RunnableItem;
import org.eclipse.app4mc.amalthea.model.SWModel;
import org.eclipse.app4mc.amalthea.model.SchedulerAllocation;
import org.eclipse.app4mc.amalthea.model.Stimulus;
import org.eclipse.app4mc.amalthea.model.Task;
import org.eclipse.app4mc.amalthea.model.TaskAllocation;
import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;
import org.eclipse.app4mc.amalthea.model.Ticks;
import org.eclipse.app4mc.amalthea.model.Time;
import org.eclipse.app4mc.amalthea.model.TimeUnit;
import org.eclipse.app4mc.amalthea.model.UserSpecificSchedulingAlgorithm;
import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
import org.eclipse.app4mc.amalthea.model.util.HardwareUtil;
import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil;
import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
public class CommonUtils {
/**
* @param amalthea Amalthea model
* @return List of processing units which CPUs at the beginning (GPUs at the end)
*/
public static List<ProcessingUnit> getPUs(final Amalthea amalthea) {
final List<ProcessingUnit> pul = new ArrayList<ProcessingUnit>();
for (final HwDefinition hwd : amalthea.getHwModel().getDefinitions()) {
if (hwd instanceof ProcessingUnitDefinition) {
final ProcessingUnitDefinition pud = (ProcessingUnitDefinition) hwd;
if (pud.getPuType().equals(PuType.CPU)) {
/* insert at the beginning */
pul.addAll(0, HardwareUtil.getAllProcessingUnitsForProcessingUnitDefinition(amalthea, pud));
}
else {
pul.addAll(HardwareUtil.getAllProcessingUnitsForProcessingUnitDefinition(amalthea, pud));
}
}
}
return pul;
}
/* UTIL Classes SoftwareUtil.getAccessedLabelSet(t, null) not Wokring => this method works */
/**
* @param t Task
* @return Labels accessed by Task t
*/
public static Set<Label> getAccessedLabelSet(final Task t) {
final Set<Label> ls = new HashSet<Label>();
for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
if (geb instanceof CallSequence) {
final CallSequence cs = (CallSequence) geb;
for (final CallSequenceItem csi : cs.getCalls()) {
if (csi instanceof TaskRunnableCall) {
final TaskRunnableCall trc = (TaskRunnableCall) csi;
final Runnable r = trc.getRunnable();
for (final RunnableItem ri : r.getRunnableItems()) {
if (ri instanceof LabelAccess) {
final LabelAccess la = (LabelAccess) ri;
ls.add(la.getData());
}
}
}
}
}
}
return ls;
}
/**
* @param l Label
* @param swm Amalthea software model
* @return Set of runnables which write label l
*/
public static Set<Runnable> getWriterSetOfLabel(final Label l, final SWModel swm) {
final Set<Runnable> rs = new HashSet<>();
for (final Runnable r : swm.getRunnables()) {
for (final RunnableItem ri : r.getRunnableItems()) {
if (ri instanceof LabelAccess) {
final LabelAccess la = (LabelAccess) ri;
if (la.getData().equals(l) && la.getAccess().equals(LabelAccessEnum.WRITE)) {
rs.add(r);
}
}
}
}
return rs;
}
/**
* @param l Label
* @param swm Amalthea software model
* @return Set of runnables which read label l
*/
public static Set<Runnable> getReadersSetOfLabel(final Label l, final SWModel swm) {
final Set<Runnable> rs = new HashSet<>();
for (final Runnable r : swm.getRunnables()) {
for (final RunnableItem ri : r.getRunnableItems()) {
if (ri instanceof LabelAccess) {
final LabelAccess la = (LabelAccess) ri;
if (la.getData().equals(l) && la.getAccess().equals(LabelAccessEnum.READ)) {
rs.add(r);
}
}
}
}
return rs;
}
/**
* @param r Runnable
* @param swm Amalthea Software model
* @return List of Processes that call runnable r (via taskRunnableCall)
*/
public static List<Process> getProcesses(final Runnable r, final SWModel swm) {
final List<Process> pl = new ArrayList<Process>();
for (final Task t : swm.getTasks()) {
for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
if (geb instanceof CallSequence) {
final CallSequence cs = (CallSequence) geb;
for (final CallSequenceItem csi : cs.getCalls()) {
if (csi instanceof TaskRunnableCall) {
final TaskRunnableCall trc = (TaskRunnableCall) csi;
if (trc.getRunnable().equals(r)) {
pl.add(t);
}
}
}
}
}
}
return pl;
}
/**
* @param model Amalthea
* @return integer array size of tasks, that contains processing unit indexes
* for each task for the processing unit the tasks are mapped to according to
* the task allocation entries in the mapping model
*/
public static int[] getIAFromMappingModel(final Amalthea model) {
final int[] ia = new int[model.getSwModel().getTasks().size()];
final List<ProcessingUnit> pul = CommonUtils.getPUs(model);
for (final TaskAllocation ta : model.getMappingModel().getTaskAllocation()) {
final Task t = ta.getTask();
final ProcessingUnit pu = ta.getAffinity().get(0);
ia[model.getSwModel().getTasks().indexOf(t)] = pul.indexOf(pu);
}
return ia;
}
/**
* @param model Amalthea model
* @return HashMap<Task,Time> which contains a timeslice for each task if there exists task
* allocation entities within the mapping model with "timeslice" parameter extensions for each task
*/
public static HashMap<Task, Time> getTimeSlices(final Amalthea model) {
final HashMap<Task, Time> ret = new HashMap<>();
final Logger log = Logger.getLogger(CommonUtils.class);
if (!SharedConsts.useModelTimeSlices) {
final List<ProcessingUnit> pul = getPUs(model);
final ProcessingUnit gpu = pul.get(pul.size() - 1);
final List<Task> tl = getGPUTasksOrderedByRecurrence(model);
//model.getMappingModel().getTaskAllocation().stream().filter(ta->ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU)).map(ta->ta.getTask()).collect(Collectors.toList());
for (final Task t : tl) {
long tsl = SharedConsts.timeSliceLengthPS;
switch (SharedConsts.tsDeriv) {
case TS:
break;
case TSxPrio:
tsl = tsl * (tl.size() - tl.indexOf(t));
break;
case TSxUtil:
final double util = getET(t, gpu).divide(getStimInTime(t));
tsl = (long) (util * SharedConsts.timeSliceLengthPS);
break;
case TSxUtilxNbTasks:
final double util2 = getET(t, gpu).divide(getStimInTime(t));
tsl = (long) (util2 * tl.size() * SharedConsts.timeSliceLengthPS);
break;
default:
break;
}
final Time time = FactoryUtil.createTime(tsl, TimeUnit.PS).adjustUnit();
ret.put(t, time);
}
ret.entrySet().stream().forEach(es -> log.debug("TimeSlices: " + es.getKey().getName() + " " + es.getValue().toString() + "; "));
return ret;
}
if (null == model.getOsModel()) {
log.error("No OS Model");
return null;
}
if (model.getOsModel().getOperatingSystems().size() < 1) {
log.error("No Operating System");
return null;
}
if (model.getOsModel().getOperatingSystems().get(0).getTaskSchedulers().size() < 1) {
log.error("No Task Scheduler in Operating System");
return null;
}
if (null == model.getMappingModel()) {
log.error("No Mapping Model");
return null;
}
if (null == model.getMappingModel().getSchedulerAllocation()) {
log.error("No Scheduler Allocations");
return null;
}
if (null == model.getMappingModel().getTaskAllocation()) {
log.error("No Task Allocations");
return null;
}
for (final SchedulerAllocation sa : model.getMappingModel().getSchedulerAllocation()) {
if (sa.getScheduler().getSchedulingAlgorithm() instanceof UserSpecificSchedulingAlgorithm) {
final UserSpecificSchedulingAlgorithm ussa = (UserSpecificSchedulingAlgorithm) sa.getScheduler().getSchedulingAlgorithm();
final List<Entry<String, String>> pel = ussa.getParameterExtensions().stream().collect(Collectors.toList());
final Time[] ta = new Time[2];
for (final Entry<String, String> e : pel) {
if (e.getKey().toString().contains("minimumTimeslice")) {
final Time mints = parseTimeString(e.getValue().toString());
ta[0] = mints;
}
else if (e.getKey().toString().contains("maximumTimeslice")) {
final Time maxts = parseTimeString(e.getValue().toString());
ta[1] = maxts;
}
else if (e.getKey().toString().contains("Timeslice")) {
final Time constts = parseTimeString(e.getValue().toString());
ta[0] = constts;
}
}
final List<TaskAllocation> tsal = model.getMappingModel().getTaskAllocation().stream()
.filter(tal -> tal.getScheduler() != null && tal.getScheduler().equals(sa.getScheduler())).collect(Collectors.toList());
if (tsal.size() > 0) {
final TaskAllocation tsa = tsal.get(0);
Time time = ta[0];
if (null != ta[1]) {
/*TODO handle min max*/
/*setting time to average*/
time = time.add(ta[1]);
time.setValue(time.getValue().divide(BigInteger.valueOf(2)));
}
ret.put(tsa.getTask(), time);
}
}
}
for (final TaskAllocation ta : model.getMappingModel().getTaskAllocation()) {
for (final Entry<String, String> e : ta.getParameterExtensions()) {
if (e.getKey().contains("timeslice") || e.getKey().contains("TimeSlice") || e.getKey().contains("Timeslice")) {
if (!ret.containsKey(ta.getTask())) {
ret.put(ta.getTask(), parseTimeString(e.getValue()));
}
}
}
}
final StringBuffer sb = new StringBuffer();
ret.entrySet().stream().forEach(es -> sb.append("TimeSlices: " + es.getKey().getName() + " " + es.getValue().toString() + "; "));
log.debug(sb);
return ret;
}
/**
* @param task
* @param model
* @return Time of timeslice, if there exists a taskAllocation for the task, which a parameterExtension with key "timeslice"
*/
public static Time getTimeSlice(final Task task, final Amalthea model) {
Entry<String, String> pex = null;
for (final TaskAllocation ta : model.getMappingModel().getTaskAllocation()) {
if (ta.getTask().equals(task)) {
for (final Entry<String, String> e : ta.getParameterExtensions()) {
if (e.getKey().contains("timeslice") || e.getKey().contains("TimeSlice") || e.getKey().contains("Timeslice")) {
pex = e;
}
}
}
}
if (null == pex) {
// final Time sum = getTimeSlices(model).get(task)[0].add(getTimeSlices(model).get(task)[1]);
// final Time two = FactoryUtil.createTime(2, sum.getUnit());
// return FactoryUtil.createTime(BigInteger.valueOf((long) sum.divide(two)), sum.getUnit());
return getTimeSlices(model).get(task);
}
return parseTimeString(pex.getValue());
}
/**
* @param string should contain a number and a unit
* @return String as Time, e.g. "12ms" => Time.value=12; Time.unit=TimeUnit.MS;
*/
private static Time parseTimeString(final String string) {
final Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
@SuppressWarnings("resource")
final Scanner sc = new Scanner(string);
time.setValue(BigInteger.valueOf(sc.useDelimiter("[^0-9]+").nextInt()));
switch (string.substring(string.length() - 2, string.length())) {
case " s":
time.setUnit(TimeUnit.S);
break;
case "ms":
time.setUnit(TimeUnit.MS);
break;
case "us":
time.setUnit(TimeUnit.US);
break;
case "ns":
time.setUnit(TimeUnit.NS);
break;
case "ps":
time.setUnit(TimeUnit.PS);
break;
default:
time.setUnit(TimeUnit._UNDEFINED_);
}
return time;
}
/**
* @param t Task
* @param pu Processing Unit
* @return Time execution time of t at pu
*/
public static Time getET(final Task t, final ProcessingUnit pu) {
Time ct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
for (final ExecutionNeed en : SoftwareUtil.getExecutionNeeds(t, null)) {
for (final Entry<String, IDiscreteValueDeviation> needs : en.getNeeds().entrySet()) {
ct = ct.add(RuntimeUtil.getExecutionTimeForExecutionNeedEntry(needs.getValue(), null, pu, SharedConsts.timeType));
}
}
for (final Ticks ticks : getTicks(t)) {
/* considers extended */
ct = ct.add(RuntimeUtil.getExecutionTimeForTicks(ticks, pu, SharedConsts.timeType));
}
if (ct.getValue().toString().endsWith("999")) {
ct.setValue(ct.getValue().add(BigInteger.ONE));
}
return ct;
}
/**
* @param t Task
* @return set of Task t's ticks
*/
public static Set<Ticks> getTicks(final Task t) {
final Set<Ticks> tickss = new HashSet<>();
for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
if (geb instanceof CallSequence) {
final CallSequence cs = (CallSequence) geb;
for (final CallSequenceItem csi : cs.getCalls()) {
if (csi instanceof TaskRunnableCall) {
final TaskRunnableCall trc = (TaskRunnableCall) csi;
for (final RunnableItem ri : trc.getRunnable().getRunnableItems()) {
if (ri instanceof Ticks) {
final Ticks ticks = (Ticks) ri;
tickss.add(ticks);
}
}
}
}
}
}
return tickss;
}
/**
* @param amalthea Amalthea model
* @param onlyGPUStim optional boolean parameter whether only GPU Stimuli should be accounted
* @return ordered list of stimuli; index 0 = lowest recurrence value
*/
public static List<PeriodicStimulus> getSortedStim(final Amalthea amalthea, final boolean... onlyGPUStim) {
final List<PeriodicStimulus> stimListSorted = new ArrayList<PeriodicStimulus>();
final List<Task> tl = amalthea.getMappingModel().getTaskAllocation().stream()
.filter(ta -> ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU)).map(ta -> ta.getTask()).collect(Collectors.toList());
for (final Stimulus s : amalthea.getStimuliModel().getStimuli()) {
if (s instanceof PeriodicStimulus) {
final PeriodicStimulus ps = (PeriodicStimulus) s;
if (null != onlyGPUStim && onlyGPUStim[0]) {
for (final Task t : tl) {
if (t.getStimuli().contains(ps) && !stimListSorted.contains(ps)) {
stimListSorted.add(ps);
break;
}
}
}
else {
stimListSorted.add(ps);
}
}
}
Collections.sort(stimListSorted, (a, b) -> a.getRecurrence().compareTo(b.getRecurrence()));
return stimListSorted;
}
/**
* @param t Task
* @return time recurrence if task @param t is periodically called or interProcess triggered,
* i.e., the recurrence of the triggering task is returned;
* Otherwise time 0 is returned
*/
public static Time getStimInTime(final Task t) {
final Logger log = Logger.getLogger(CommonUtils.class);
if (t.getStimuli().size() > 1) {
// TODO
log.warn("Multiple Simuli not supported.");
}
for (final Stimulus s : t.getStimuli()) {
if (s instanceof PeriodicStimulus) {
final PeriodicStimulus ps = (PeriodicStimulus) s;
return ps.getRecurrence();
}
if (s instanceof InterProcessStimulus) {
final InterProcessStimulus ips = (InterProcessStimulus) s;
// final List<Process> triggers = ips.getExplicitTriggers().stream().map(ipt -> ipt.getContainingProcess()).collect(Collectors.toList());
// final Time rec = ((PeriodicStimulus) triggers.get(0).getStimuli().get(0)).getRecurrence();
final Task trigger = getFirstTrigger(ips);
return ((PeriodicStimulus) trigger.getStimuli().get(0)).getRecurrence();
}
log.warn("Stimuli other than periodic / interprocesstrigger not supported.");
}
return FactoryUtil.createTime(0, TimeUnit._UNDEFINED_);
}
/**
* Logs mutliple stimuli / stimuli != (Periodic,InterProcessTrigger)
* @param t Task
* @return PeriodicStimulus of Task t
*/
public static PeriodicStimulus getStim(final Task t) {
final Logger log = Logger.getLogger(CommonUtils.class);
if (t.getStimuli().size() > 1) {
// TODO
log.warn("Multiple Simuli not supported.");
}
for (final Stimulus s : t.getStimuli()) {
if (s instanceof PeriodicStimulus) {
final PeriodicStimulus ps = (PeriodicStimulus) s;
return ps;
}
if (s instanceof InterProcessStimulus) {
final InterProcessStimulus ips = (InterProcessStimulus) s;
// final List<Process> triggers = ips.getExplicitTriggers().stream().map(ipt -> ipt.getContainingProcess()).collect(Collectors.toList());
// final Time rec = ((PeriodicStimulus) triggers.get(0).getStimuli().get(0)).getRecurrence();
final Task trigger = getFirstTrigger(ips);
return ((PeriodicStimulus) trigger.getStimuli().get(0));
}
log.warn("Stimuli other than periodic / interprocesstrigger not supported.");
}
log.error("NO SUPPORTED STIMULUS");
return null;
}
/**
* @param ips InterProcessStimulus
* @return Task t that contains ips as activation
*/
private static Task getFirstTrigger(final InterProcessStimulus ips) {
final Amalthea model = (Amalthea) ips.eContainer().eContainer();
for (final Task t : model.getSwModel().getTasks()) {
for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
if (geb instanceof CallSequence) {
final CallSequence cs = (CallSequence) geb;
for (final CallSequenceItem csi : cs.getCalls()) {
if (csi instanceof InterProcessTrigger) {
final InterProcessTrigger ipt = (InterProcessTrigger) csi;
if (ipt.getStimulus().equals(ips)) {
return t;
}
}
}
}
}
}
final Logger log = Logger.getLogger("CommonUtils");
log.error("No triggering task found for " + ips.getName());
return null;
}
/** requires mapping model*/
public void printTaskAllocs(final Amalthea amalthea) {
final Logger log = Logger.getLogger(this.getClass().getName().substring(this.getClass().getName().lastIndexOf("." + 1)));
for (final TaskAllocation ta : amalthea.getMappingModel().getTaskAllocation()) {
log.debug(" " + Thread.currentThread().getId() + " " + ta.getTask().getName() + " ==> " + ta.getAffinity().get(0).getName());
}
}
/**
* @param am Amalthea model
* @param ia Task to processing unit mapping int array
* @return ordered List of tasks mapped to GPUs, lowest recurrence (period) at beginning
*/
public static List<Task> getGPUTasksOrderedByRecurrence(final Amalthea am, final int[]... ia) {
List<Task> tl = am.getMappingModel().getTaskAllocation().stream().filter(ta -> ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU))
.map(ta -> ta.getTask()).collect(Collectors.toList());
if (ia.length > 0) {
final int[] mapping = ia[0];
final List<Integer> il = new ArrayList<Integer>();
final List<ProcessingUnit> gpus = getPUs(am);
for (final ProcessingUnit pu : gpus) {
if (pu.getDefinition().getPuType().equals(PuType.GPU)) {
il.add(gpus.indexOf(pu));
}
}
/*il = only indexes of GPUs*/
final List<Task> gpuTasks = new ArrayList<Task>();
for (int i = 0; i < mapping.length; i++) {
if (il.contains(mapping[i])) {
/*task i is mapped tp a GPU*/
gpuTasks.add(am.getSwModel().getTasks().get(i));
}
}
tl = gpuTasks;
}
tl.sort(new Comparator<Task>() {
@Override
public int compare(final Task t1, final Task t2) {
final List<Stimulus> psl1 = t1.getStimuli().stream().filter(s -> s instanceof PeriodicStimulus).collect(Collectors.toList());
final List<Stimulus> psl2 = t2.getStimuli().stream().filter(s -> s instanceof PeriodicStimulus).collect(Collectors.toList());
if (psl1.size() != 1 || psl2.size() != 1) {
Logger.getLogger("CommonUtils").debug("Task " + t1.getName() + " has no periodic stimulus.");
return 0;
}
return ((PeriodicStimulus) psl1.get(0)).getRecurrence().compareTo(((PeriodicStimulus) psl2.get(0)).getRecurrence());
}
});
return tl;
}
/** single core schedulability => utilization must be <= 1*/
public static boolean isSchedulable(final List<Task> tl, final ProcessingUnit pu) {
Double sum = 0d;
for (final Task t : tl) {
final Time et = CommonUtils.getET(t, pu);
final Time per = getStimInTime(t);
sum += et.divide(per);
}
return sum > 1 ? false : true;
}
/** Creates a Mapping Model from a Chromosome; Decreases efficiency */
public static MappingModel createMMFromIA(final Amalthea amalthea, final int[] ia) {
final List<ProcessingUnit> pul = getPUs(amalthea);
final MappingModel mm = AmaltheaFactory.eINSTANCE.createMappingModel();
for (int i = 0; i < amalthea.getSwModel().getTasks().size(); i++) {
// for (final IntegerGene ig : chromosome) {
final TaskAllocation ta = AmaltheaFactory.eINSTANCE.createTaskAllocation();
ta.setTask(amalthea.getSwModel().getTasks().get(i));
ta.getAffinity().add(pul.get(ia[i]));
ta.getParameterExtensions().put("Timeslice", "7200us");
mm.getTaskAllocation().add(ta);
}
return mm;
}
/**
* @param model
* @return int number of GPUs
*/
public static int getNumberofGPUs(final Amalthea model) {
int gpus = 0;
for (final HwDefinition hwd : model.getHwModel().getDefinitions()) {
if (hwd instanceof ProcessingUnitDefinition) {
final ProcessingUnitDefinition pud = (ProcessingUnitDefinition) hwd;
if (pud.getPuType().equals(PuType.GPU)) {
gpus += HardwareUtil.getAllProcessingUnitsForProcessingUnitDefinition(model, pud).size();
}
}
}
return gpus;
}
/**
* @param amalthea
* @return int number of CPUs
*/
public static int getNumberofCPUs(final Amalthea amalthea) {
int cpus = 0;
for (final HwDefinition hwd : amalthea.getHwModel().getDefinitions()) {
if (hwd instanceof ProcessingUnitDefinition) {
final ProcessingUnitDefinition pud = (ProcessingUnitDefinition) hwd;
if (pud.getPuType().equals(PuType.CPU)) {
cpus += HardwareUtil.getAllProcessingUnitsForProcessingUnitDefinition(amalthea, pud).size();
}
}
}
return cpus;
}
/**
* @param amalthea Model
* @return int number of processing units
*/
public static int getNumberofPUs(final Amalthea amalthea) {
int pus = 0;
for (final HwDefinition hwd : amalthea.getHwModel().getDefinitions()) {
if (hwd instanceof ProcessingUnitDefinition) {
final ProcessingUnitDefinition pud = (ProcessingUnitDefinition) hwd;
if (pud.getPuType().equals(PuType.CPU)) {
/* insert at the beginning */
pus += HardwareUtil.getAllProcessingUnitsForProcessingUnitDefinition(amalthea, pud).size();
}
else {
pus += HardwareUtil.getAllProcessingUnitsForProcessingUnitDefinition(amalthea, pud).size();
}
}
}
return pus;
}
@SuppressWarnings("resource")
/** writes a stringbuffer into either measurements.csv or optional @param filename */
public static void writeCSV(final StringBuffer sbp, final String... filenamep) {
if (null == sbp) {
Logger.getLogger(CommonUtils.class).error("Nothing to write. Probably, the system is not schedulable.");
return;
}
String fileName;
if (null != filenamep && filenamep.length > 0 && null != filenamep[0]) {
fileName = filenamep[0];
}
else {
fileName = "measurements.csv";
}
try {
final Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), "utf-8"));
writer.write(sbp.toString());
writer.close();
System.out.println("Wrote results to " + System.getProperty("user.dir") + "/" + fileName);
}
catch (final Exception e) {
e.printStackTrace();
}
}
/**
* @param model Amalthea model
* @param ia Task to Processingunit integer array
* @param t Task to be checked
* @return Time sum of execution times of all triggered tasks of t
*/
public static Time getETofTriggeredTask(final Amalthea model, final int[] ia, final Task t) {
Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
final List<InterProcessTrigger> ipts = getTriggered(t);
final List<ProcessingUnit> pul = CommonUtils.getPUs(model);
/*task triggers other task*/
for (final InterProcessTrigger ipt : ipts) {
final List<Task> triggered = model.getSwModel().getTasks().stream().filter(task -> task.getStimuli().get(0).equals(ipt.getStimulus()))
.collect(Collectors.toList());
for (final Task task : triggered) {
final ProcessingUnit pu = pul.get(ia[model.getSwModel().getTasks().indexOf(task)]);
time = time.add(RuntimeUtil.getExecutionTimeForProcess(task, pu, null, TimeType.WCET));
}
}
return time;
}
/**
* @param ama Amalthea model
* @param t Task to be checked
* @return List of tasks triggered by t via interProcessTrigger event contained in t
*/
public static List<Task> getTriggeredTasks(final Amalthea ama, final Task t) {
final List<Task> tl = new ArrayList<>();
final List<InterProcessTrigger> ipts = getTriggered(t);
/*task triggers other task*/
for (final InterProcessTrigger ipt : ipts) {
tl.addAll(ama.getSwModel().getTasks().stream().filter(task -> task.getStimuli().get(0).equals(ipt.getStimulus())).collect(Collectors.toList()));
}
return tl;
}
/**
* @param pu Processing Unit
* @param t Task
* @return Ticks of t at pu
*/
public static long getTicksLongForPU(final ProcessingUnit pu, final Task t) {
long sum = 0;
for (final Ticks ticks : CommonUtils.getTicks(t)) {
if (null != ticks && null != ticks.getExtended() && null != ticks.getExtended().get(pu.getDefinition())) {
if (null != ticks.getExtended().get(pu.getDefinition())) {
if (ticks.getExtended().get(pu.getDefinition()) instanceof DiscreteValueConstant) {
sum += ((DiscreteValueConstant) ticks.getExtended().get(pu.getDefinition())).getValue();
}
else if (ticks.getExtended().get(pu.getDefinition()) instanceof DiscreteValueStatistics) {
final DiscreteValueStatistics dvs = (DiscreteValueStatistics) ticks.getExtended().get(pu.getDefinition());
sum += (dvs.getLowerBound() + dvs.getUpperBound()) / 2;
}
}
else {
sum += ((DiscreteValueConstant) ticks.getDefault()).getValue();
}
}
}
return sum;
}
/**
* @param t
* @return List of tasks triggered by Task t via interProcessTrigger CallSequenceItem
*/
public static List<InterProcessTrigger> getTriggered(final Task t) {
/*DOES NOT WORK*/
// t.getCallGraph().getGraphEntries().stream().filter(geb -> geb instanceof CallSequence)
// .map(cs -> ((CallSequence) cs).getCalls()).filter(csi -> csi instanceof InterProcessTrigger).map(csi -> ((InterProcessTrigger) csi))
// .collect(Collectors.toList());
final List<InterProcessTrigger> iptl = new ArrayList<>();
for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
if (geb instanceof CallSequence) {
final CallSequence cs = (CallSequence) geb;
for (final CallSequenceItem csi : cs.getCalls()) {
if (csi instanceof InterProcessTrigger) {
final InterProcessTrigger ipt = (InterProcessTrigger) csi;
iptl.add(ipt);
}
}
}
}
return iptl;
}
/**
* @param model Amalthea
* @param ia task to processing unit mapping int array
* @param t Task under consideration
* @return long sum of WC ticks of triggered tasks by t
*/
public static long getTicksLongOfTriggeredTask(final Amalthea model, final int[] ia, final Task t) {
final List<InterProcessTrigger> ipts = getTriggered(t);
long ticks = 0;
/*task triggers other task*/
for (final InterProcessTrigger ipt : ipts) {
final List<Task> triggered = model.getSwModel().getTasks().stream().filter(task -> task.getStimuli().get(0).equals(ipt.getStimulus()))
.collect(Collectors.toList());
for (final Task task : triggered) {
ticks += getTicksLongForPU(CommonUtils.getPUs(model).get(ia[model.getSwModel().getTasks().indexOf(task)]), task);
}
}
return ticks;
}
/**
* @param model Amalthea model
* @param mapping task to processing unit mapping int array
* @return StringBuffer containing SharedConsts class configurations
*/
public static StringBuffer appendConfig(final String model, final int[] mapping) {
final StringBuffer sbl = new StringBuffer();
sbl.append(
"Configuration:\n Model,Mapping,SyncOffloading,UseModelTimeSlices,TimeSliceDerication,TimeSliceLengthInPSDefault,LevelI,TimeType,CEOnlyWrittenLabels,IgnoreInfeasibility\n");
sbl.append(model + "," + Arrays.toString(mapping).replace(",", ";") + "," + SharedConsts.synchronousOffloading + "," + SharedConsts.useModelTimeSlices
+ "," + SharedConsts.tsDeriv + "," + SharedConsts.timeSliceLengthPS + "," + SharedConsts.levelIBusyPeriod + "," + SharedConsts.timeType + ","
+ SharedConsts.onlyWrittenLabelsCE + "," + SharedConsts.ignoreInfeasibility + "\n");
return sbl;
}
}