| /** |
| ******************************************************************************** |
| * Copyright (c) 2015-2019 Robert Bosch GmbH 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: |
| * Robert Bosch GmbH - initial API and implementation |
| ******************************************************************************** |
| */ |
| |
| package org.eclipse.app4mc.amalthea.model.util; |
| |
| import static org.eclipse.app4mc.amalthea.model.LabelAccessEnum.READ; |
| import static org.eclipse.app4mc.amalthea.model.LabelAccessEnum.WRITE; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Objects; |
| import java.util.Set; |
| import java.util.function.Function; |
| import java.util.stream.Collectors; |
| |
| import org.eclipse.app4mc.amalthea.model.ActivityGraphItem; |
| import org.eclipse.app4mc.amalthea.model.AmaltheaServices; |
| import org.eclipse.app4mc.amalthea.model.ClearEvent; |
| import org.eclipse.app4mc.amalthea.model.ExecutionNeed; |
| import org.eclipse.app4mc.amalthea.model.Group; |
| import org.eclipse.app4mc.amalthea.model.IActivityGraphItemContainer; |
| 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.LabelAccessStatistic; |
| import org.eclipse.app4mc.amalthea.model.MinAvgMaxStatistic; |
| import org.eclipse.app4mc.amalthea.model.ModeLabel; |
| import org.eclipse.app4mc.amalthea.model.ModeSwitch; |
| import org.eclipse.app4mc.amalthea.model.ModeSwitchEntry; |
| import org.eclipse.app4mc.amalthea.model.NumericStatistic; |
| import org.eclipse.app4mc.amalthea.model.ProbabilitySwitch; |
| import org.eclipse.app4mc.amalthea.model.ProbabilitySwitchEntry; |
| import org.eclipse.app4mc.amalthea.model.Process; |
| import org.eclipse.app4mc.amalthea.model.Runnable; |
| import org.eclipse.app4mc.amalthea.model.RunnableCall; |
| import org.eclipse.app4mc.amalthea.model.ServerCall; |
| import org.eclipse.app4mc.amalthea.model.SetEvent; |
| import org.eclipse.app4mc.amalthea.model.SingleValueStatistic; |
| import org.eclipse.app4mc.amalthea.model.Ticks; |
| import org.eclipse.app4mc.amalthea.model.WaitEvent; |
| import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType; |
| import org.eclipse.emf.common.util.BasicEList; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.EMap; |
| import org.eclipse.jdt.annotation.NonNull; |
| |
| public class SoftwareUtil { |
| |
| // Suppress default constructor |
| private SoftwareUtil() { |
| throw new IllegalStateException("Utility class"); |
| } |
| |
| /** |
| * Traverse the contained call graph items and collect all items. |
| * |
| * @param container call graph, group, ... |
| * @return |
| * List of ActivityGraphItems |
| */ |
| public static EList<ActivityGraphItem> collectActivityGraphItems(final IActivityGraphItemContainer container) { |
| return collectActivityGraphItems(container, null, ActivityGraphItem.class, null); |
| } |
| |
| /** |
| * Traverse the contained call graph items and collect all items. |
| * Collection can be restricted to specific modes. |
| * |
| * @param container call graph, group, ... |
| * @param modes (optional) - null works |
| * @return |
| * List of ActivityGraphItems |
| */ |
| public static EList<ActivityGraphItem> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(container, modes, ActivityGraphItem.class, null); |
| } |
| |
| /** |
| * Traverse the contained call graph items and collect all items. |
| * Collection can be restricted to specific modes and filtered by a lambda expression. |
| * |
| * @param container call graph, group, ... |
| * @param modes (optional) - null works |
| * @param filter lambda expression (e.g. "a -> a instanceof LabelAccess") |
| * @return |
| * List of ActivityGraphItems |
| */ |
| public static EList<ActivityGraphItem> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes, |
| final Function<ActivityGraphItem, Boolean> filter) { |
| return collectActivityGraphItems(container, modes, ActivityGraphItem.class, filter); |
| } |
| |
| /** |
| * Traverse the runnable items graph of a runnable and collect all items. |
| * Collection can be restricted to specific modes and filtered by class. |
| * |
| * @param container call graph, group, ... |
| * @param modes (optional) - null works |
| * @param targetClass subclass of ActivityGraphItem that restricts the result |
| * @return |
| * List of T extends ActivityGraphItems |
| */ |
| public static <T extends ActivityGraphItem> EList<T> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes, |
| final Class<T> targetClass) { |
| return collectActivityGraphItems(container, modes, targetClass, null); |
| } |
| |
| /** |
| * Traverse the runnable items graph of a runnable and collect all items. |
| * Collection can be restricted to specific modes and filtered by class and lambda expression. |
| * |
| * @param container call graph, group, ... |
| * @param modes (optional) - null works |
| * @param targetClass subclass of ActivityGraphItem that restricts the result |
| * @param filter lambda expression (e.g. "a -> a instanceof LabelAccess") |
| * @return |
| * List of T extends ActivityGraphItems |
| */ |
| public static <T extends ActivityGraphItem> EList<T> collectActivityGraphItems(final IActivityGraphItemContainer container, final EMap<ModeLabel, String> modes, |
| final Class<T> targetClass, final Function<T, Boolean> filter) { |
| EList<T> itemList = new BasicEList<>(); |
| if (container != null) { |
| collectActivityGraphItems(container.getItems(), modes, targetClass, filter, itemList); |
| } |
| return itemList; |
| } |
| |
| |
| private static <T extends ActivityGraphItem> void collectActivityGraphItems(final EList<ActivityGraphItem> input, final EMap<ModeLabel, String> modes, |
| final Class<T> targetClass, final Function<T, Boolean> filter, final List<T> itemList) { |
| for (ActivityGraphItem item : input) { |
| if (item instanceof Group) { |
| collectActivityGraphItems(((Group) item).getItems(), modes, targetClass, filter, itemList); |
| } else if (item instanceof ProbabilitySwitch) { |
| ProbabilitySwitch propSwitch = (ProbabilitySwitch) item; |
| for (ProbabilitySwitchEntry pse : propSwitch.getEntries()) { |
| collectActivityGraphItems(pse.getItems(), modes, targetClass, filter, itemList); |
| } |
| } else if (item instanceof ModeSwitch) { |
| ModeSwitch modeSwitch = (ModeSwitch) item; |
| boolean includeDefault = true; |
| for (ModeSwitchEntry mse : modeSwitch.getEntries()) { |
| if (modes == null) { |
| collectActivityGraphItems(mse.getItems(), modes, targetClass, filter, itemList); |
| } else if (mse.getCondition().isSatisfiedBy(modes)) { |
| collectActivityGraphItems(mse.getItems(), modes, targetClass, filter, itemList); |
| includeDefault = false; |
| break; |
| } |
| } |
| if (includeDefault && modeSwitch.getDefaultEntry() != null) { |
| collectActivityGraphItems(modeSwitch.getDefaultEntry().getItems(), modes, targetClass, filter, itemList); |
| } |
| } else if (targetClass.isInstance(item)) { |
| T castedItem = targetClass.cast(item); |
| if (filter == null || filter.apply(castedItem)) { |
| itemList.add(castedItem); |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| * Returns a set of labels accessed from the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Label> getAccessedLabelSet(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class) |
| .stream().map(LabelAccess::getData).filter(Objects::nonNull).collect(Collectors.toSet()); |
| } |
| |
| /** |
| * Returns a set of labels read by the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Label> getReadLabelSet(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == READ)) |
| .stream().map(LabelAccess::getData).filter(Objects::nonNull).collect(Collectors.toSet()); |
| } |
| |
| /** |
| * Returns a set of labels written by the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Label> getWriteLabelSet(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == WRITE)) |
| .stream().map(LabelAccess::getData).filter(Objects::nonNull).collect(Collectors.toSet()); |
| } |
| |
| /** |
| * Returns a list of all label accesses of the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of LabelAccesses |
| */ |
| public static List<LabelAccess> getLabelAccessList(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class); |
| } |
| |
| /** |
| * Returns a list of read label accesses of the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of LabelAccesses |
| */ |
| public static List<LabelAccess> getReadLabelAccessList(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == READ)); |
| } |
| |
| /** |
| * Returns a list of write label accesses of the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of LabelAccesses |
| */ |
| public static List<LabelAccess> getWriteLabelAccessList(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getAccess() == WRITE)); |
| } |
| |
| /** |
| * Returns a map: labels accessed from runnable -> the corresponding label accesses |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccesses |
| */ |
| public static Map<Label, List<LabelAccess>> getLabelToLabelAccessMap(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, (la -> la.getData() != null)) |
| .stream().collect(Collectors.groupingBy(LabelAccess::getData)); |
| } |
| |
| /** |
| * Returns a map: labels accessed by the runnable -> the corresponding LabelAccessStatistics |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return Map: |
| * Label -> List of LabelAccessStatistics |
| */ |
| public static Map<Label, List<LabelAccessStatistic>> getLabelAccessStatisticsMap(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, |
| (la -> la.getData() != null && la.getStatistic() != null)) |
| .stream().collect(Collectors.groupingBy( |
| LabelAccess::getData, |
| Collectors.mapping(LabelAccess::getStatistic, Collectors.toList()) )); |
| } |
| |
| /** |
| * Returns a map: labels read by the runnable -> the corresponding LabelAccessStatistics |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccessStatistics |
| */ |
| public static Map<Label, List<LabelAccessStatistic>> getReadLabelAccessStatisticsMap(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, |
| (la -> la.getData() != null && la.getStatistic() != null && la.getAccess() == READ)) |
| .stream().collect(Collectors.groupingBy( |
| LabelAccess::getData, |
| Collectors.mapping(LabelAccess::getStatistic, Collectors.toList()) )); |
| } |
| |
| /** |
| * Returns a map: labels written by the runnable -> the corresponding LabelAccessStatistics |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccessStatistics |
| */ |
| public static Map<Label, List<LabelAccessStatistic>> getWriteLabelAccessStatisticsMap(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, LabelAccess.class, |
| (la -> la.getData() != null && la.getStatistic() != null && la.getAccess() == WRITE)) |
| .stream().collect(Collectors.groupingBy( |
| LabelAccess::getData, |
| Collectors.mapping(LabelAccess::getStatistic, Collectors.toList()) )); |
| } |
| |
| /** |
| * Returns a set of labels accessed by the process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Label> getAccessedLabelSet(Process process, EMap<ModeLabel, String> modes) { |
| HashSet<Label> result = new HashSet<>(); |
| for (Runnable r : getRunnableList(process, modes)) |
| result.addAll(getAccessedLabelSet(r, modes)); |
| return result; |
| } |
| |
| /** |
| * Returns a set of labels read by the process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Label> getReadLabelSet(Process process, EMap<ModeLabel, String> modes) { |
| HashSet<Label> result = new HashSet<>(); |
| for (Runnable r : getRunnableList(process, modes)) |
| result.addAll(getReadLabelSet(r, modes)); |
| return result; |
| } |
| |
| /** |
| * Returns a set of labels written by the process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Label> getWriteLabelSet(Process process, EMap<ModeLabel, String> modes) { |
| HashSet<Label> result = new HashSet<>(); |
| for (Runnable r : getRunnableList(process, modes)) |
| result.addAll(getWriteLabelSet(r, modes)); |
| return result; |
| } |
| |
| /** |
| * Returns a list of all label accesses of the process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of LabelAccesses |
| */ |
| public static List<LabelAccess> getLabelAccessList(Process process, EMap<ModeLabel, String> modes) { |
| ArrayList<LabelAccess> result = new ArrayList<>(); |
| for (Runnable r : getRunnableList(process, modes)) |
| result.addAll(getLabelAccessList(r, modes)); |
| return result; |
| } |
| |
| /** |
| * Returns a map: accessed labels of the process -> the corresponding label accesses |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccess |
| */ |
| public static Map<Label, List<LabelAccess>> getLabelToLabelAccessMap(Process process, EMap<ModeLabel, String> modes) { |
| HashMap<Label, List<LabelAccess>> result = new HashMap<>(); |
| for (Runnable run : getRunnableList(process, modes)) { |
| Map<Label, List<LabelAccess>> labelToLabelAccessMap = SoftwareUtil.getLabelToLabelAccessMap(run, modes); |
| for(Entry<Label, List<LabelAccess>> entry : labelToLabelAccessMap.entrySet()) { |
| Label label = entry.getKey(); |
| List<LabelAccess> accessList = entry.getValue(); |
| if(!result.containsKey(label)) { |
| result.put(label, new ArrayList<>()); |
| } |
| result.get(label).addAll(accessList); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a map: labels accessed by the process -> the corresponding label access statistics |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccessStatistic |
| */ |
| public static Map<Label, List<LabelAccessStatistic>> getLabelAccessStatisticsMap(Process process, EMap<ModeLabel, String> modes) { |
| HashMap<Label, List<LabelAccessStatistic>> result = new HashMap<>(); |
| for (Runnable r : getRunnableList(process, modes)) { |
| Map<Label, List<LabelAccessStatistic>> labelToLabelAccessMap = SoftwareUtil.getLabelAccessStatisticsMap(r, modes); |
| for(Entry<Label, List<LabelAccessStatistic>> entry : labelToLabelAccessMap.entrySet()) { |
| Label label = entry.getKey(); |
| List<LabelAccessStatistic> statistics = entry.getValue(); |
| |
| if (!result.containsKey(label)) { |
| result.put(label, new ArrayList<>()); |
| } |
| result.get(label).addAll(statistics); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a map: labels read the process -> the corresponding label access statistics |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccessStatistic |
| */ |
| public static Map<Label, List<LabelAccessStatistic>> getReadLabelAccessStatisticsMap(Process process, EMap<ModeLabel, String> modes) { |
| HashMap<Label, List<LabelAccessStatistic>> result = new HashMap<>(); |
| for (Runnable run : getRunnableList(process, modes)) { |
| Map<Label, List<LabelAccessStatistic>> readLabelAccessStatisticsMap = SoftwareUtil.getReadLabelAccessStatisticsMap(run, modes); |
| for(Entry<Label, List<LabelAccessStatistic>> entry : readLabelAccessStatisticsMap.entrySet()) { |
| Label label = entry.getKey(); |
| List<LabelAccessStatistic> statistics = entry.getValue(); |
| |
| if (!result.containsKey(label)) { |
| result.put(label, new ArrayList<>()); |
| } |
| result.get(label).addAll(statistics); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a map: labels written by the process -> the corresponding label access statistics |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Map: Label -> List of LabelAccessStatistic |
| */ |
| public static Map<Label, List<LabelAccessStatistic>> getWriteLabelAccessStatisticsMap(Process process, EMap<ModeLabel, String> modes) { |
| HashMap<Label, List<LabelAccessStatistic>> result = new HashMap<>(); |
| for (Runnable run : getRunnableList(process, modes)) { |
| Map<Label, List<LabelAccessStatistic>> writeLabelAcessStatisticsMap = SoftwareUtil.getWriteLabelAccessStatisticsMap(run, modes); |
| for(Entry<Label, List<LabelAccessStatistic>> entry : writeLabelAcessStatisticsMap.entrySet()) { |
| Label label = entry.getKey(); |
| List<LabelAccessStatistic> statistics = entry.getValue(); |
| |
| if (!result.containsKey(label)) { |
| result.put(label, new ArrayList<>()); |
| } |
| result.get(label).addAll(statistics); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the reads from a process to a certain label. Evaluates the LabelAccessStatistic. |
| * Definition of TimeType is possible. Null value returns the average case. |
| */ |
| public static float getLabelReadCount(Label label, Process process, EMap<ModeLabel, String> modes, TimeType timeType) { |
| if (timeType == null) |
| timeType = TimeType.ACET; |
| |
| EList<@NonNull LabelAccess> accessList = collectActivityGraphItems( |
| process.getActivityGraph(), |
| modes, |
| LabelAccess.class, |
| (la -> la.getAccess() == READ && la.getData() == label)); |
| |
| return sumUpLabelAccesses(timeType, accessList); |
| } |
| |
| /** |
| * Returns the writes from a process to a certain label. Evaluates the LabelAccessStatistic. |
| * Definition of TimeType is possible. Null value returns the average case. |
| */ |
| public static float getLabelWriteCount(Label label, Process process, EMap<ModeLabel, String> modes, TimeType timeType) { |
| if (timeType == null) |
| timeType = TimeType.ACET; |
| |
| EList<@NonNull LabelAccess> accessList = collectActivityGraphItems( |
| process.getActivityGraph(), |
| modes, |
| LabelAccess.class, |
| (la -> la.getAccess() == WRITE && la.getData() == label)); |
| |
| return sumUpLabelAccesses(timeType, accessList); |
| } |
| |
| private static float sumUpLabelAccesses(TimeType timeType, EList<@NonNull LabelAccess> accessList) { |
| float accesses = 0f; |
| for (LabelAccess la : accessList) { |
| if (la.getStatistic() == null || la.getStatistic().getValue() == null) { |
| accesses += 1f; |
| continue; |
| } |
| |
| NumericStatistic statistic = la.getStatistic().getValue(); |
| if (statistic instanceof SingleValueStatistic) { |
| accesses += ((SingleValueStatistic) statistic).getValue(); |
| } else if (statistic instanceof MinAvgMaxStatistic) { |
| MinAvgMaxStatistic stat = (MinAvgMaxStatistic) statistic; |
| switch (timeType) { |
| case ACET: |
| accesses += stat.getAvg(); |
| break; |
| case BCET: |
| accesses += stat.getMin(); |
| break; |
| case WCET: |
| accesses += stat.getMax(); |
| break; |
| } |
| } |
| } |
| return accesses; |
| } |
| |
| /** |
| * Returns a list of runnables called by the process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of Runnables |
| */ |
| public static List<Runnable> getRunnableList(Process process, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(process.getActivityGraph(), modes, RunnableCall.class) |
| .stream().map(RunnableCall::getRunnable).filter(Objects::nonNull).collect(Collectors.toList()); |
| } |
| |
| /** |
| * Returns a set of runnables called by the process - no duplicates |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Set of runnables called by the process |
| */ |
| public static Set<Runnable> getRunnableSet(Process process, EMap<ModeLabel, String> modes) { |
| return new HashSet<>(getRunnableList(process, modes)); |
| } |
| |
| /** |
| * Returns the number of label accesses from a statistic. |
| * The accType defines if the minimum, maximum or average accesses are returned. |
| */ |
| public static float getLabelAccessCountFromStatistics(LabelAccess labelAcc, TimeType accType) { |
| if (labelAcc.getStatistic() == null) |
| return 1; |
| |
| float accesses = 1; |
| final NumericStatistic value = labelAcc.getStatistic().getValue(); |
| if (value instanceof SingleValueStatistic) { |
| accesses = ((SingleValueStatistic)value).getValue(); |
| } else if (value instanceof MinAvgMaxStatistic) { |
| switch(accType) { |
| case ACET: |
| accesses = ((MinAvgMaxStatistic)value).getAvg(); |
| break; |
| case BCET: |
| accesses = ((MinAvgMaxStatistic)value).getMin(); |
| break; |
| case WCET: |
| accesses = ((MinAvgMaxStatistic)value).getMax(); |
| break; |
| default: |
| accesses = ((MinAvgMaxStatistic)value).getAvg(); |
| } |
| } |
| return accesses; |
| } |
| |
| /** |
| * Returns a list of runnables reading the label |
| * @param label label |
| * @param modes (optional) - null works |
| * @return |
| * List of Runnables |
| */ |
| public static List<Runnable> getReaderListOfLabel(Label label, EMap<ModeLabel, String> modes) { |
| ArrayList<Runnable> result = new ArrayList<>(); |
| for (LabelAccess la : label.getLabelAccesses()) { |
| if (la.getAccess() == LabelAccessEnum.READ) { |
| Runnable run = AmaltheaServices.getContainerOfType(la, Runnable.class); |
| if (modes == null || modes.isEmpty() || (collectActivityGraphItems(run.getActivityGraph(), modes)).contains(la)) { |
| result.add(AmaltheaServices.getContainerOfType(la, Runnable.class)); |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a set of runnables reading the label |
| * @param label label |
| * @param modes (optional) - null works |
| * @return |
| * Set of Labels |
| */ |
| public static Set<Runnable> getReadersSetOfLabel(Label label, EMap<ModeLabel, String> modes) { |
| return new HashSet<>(getReaderListOfLabel(label, modes)); |
| } |
| |
| /** |
| * Returns a list of runnables writing the label |
| * @param label label |
| * @param modes (optional) - null works |
| * @return |
| * List of Runnables |
| */ |
| public static List<Runnable> getWriterListOfLabel(Label label, EMap<ModeLabel, String> modes) { |
| ArrayList<Runnable> result = new ArrayList<>(); |
| for (LabelAccess la : label.getLabelAccesses()) { |
| if (la.getAccess().equals(LabelAccessEnum.WRITE)) { |
| Runnable run = AmaltheaServices.getContainerOfType(la, Runnable.class); |
| if (modes == null || modes.isEmpty() || (collectActivityGraphItems(run.getActivityGraph(), modes)).contains(la)) { |
| result.add(AmaltheaServices.getContainerOfType(la, Runnable.class)); |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a set of runnables writing the label |
| * @param label label |
| * @param modes (optional) - null works |
| * @return |
| * Set of Runnables |
| */ |
| public static Set<Runnable> getWriterSetOfLabel(Label label, EMap<ModeLabel, String> modes) { |
| return new HashSet<>(getWriterListOfLabel(label, modes)); |
| } |
| |
| /** |
| * Collects a list of set events calls for a process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of SetEvents |
| */ |
| public static List<SetEvent> collectSetEvents(Process process, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(process.getActivityGraph(), modes, SetEvent.class); |
| } |
| |
| /** |
| * Collects a list of clear event calls for a process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of ClearEvents |
| */ |
| public static List<ClearEvent> collectClearEvents(Process process, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(process.getActivityGraph(), modes, ClearEvent.class); |
| } |
| |
| /** |
| * Collects a list of wait event calls for a process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of WaitEvents |
| */ |
| public static List<WaitEvent> collectWaitEvents(Process process, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(process.getActivityGraph(), modes, WaitEvent.class); |
| } |
| |
| /** |
| * Collects a list of event calls (clear, set or wait) of a process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of CallSequenceItems |
| */ |
| public static List<ActivityGraphItem> collectEventsOfProcess(Process process, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(process.getActivityGraph(), modes, |
| (call -> call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent)); |
| } |
| |
| /** |
| * Returns a list of all exchanged labels that are written by the sender process and read by the receiver process |
| * @param sender process (Task or ISR) |
| * @param receiver process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of Labels |
| */ |
| public static List<Label> getInterTaskCommunication(Process sender, Process receiver, EMap<ModeLabel, String> modes) { |
| ArrayList<Label> result = new ArrayList<>(); |
| result.addAll(getWriteLabelSet(sender, modes)); |
| result.retainAll(getReadLabelSet(receiver, modes)); |
| return result; |
| } |
| |
| /** |
| * Returns a list of processes calling the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of Processes |
| */ |
| public static List<Process> getCallingProcesses(Runnable runnable, EMap<ModeLabel, String> modes) { |
| ArrayList<Process> result = new ArrayList<>(); |
| for (RunnableCall callerRC : runnable.getRunnableCalls()) { |
| Process caller = callerRC.getContainingProcess(); // null if container is not of type Process |
| if (caller == null) continue; |
| |
| if (modes != null && !modes.isEmpty()) { |
| for (RunnableCall rc : collectActivityGraphItems(caller.getActivityGraph(), modes, RunnableCall.class)) { |
| if (rc.getRunnable() == runnable) { |
| result.add(caller); |
| break; |
| } |
| } |
| } else { |
| result.add(caller); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a list of runnables directly calling the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of Runnables |
| */ |
| public static List<Runnable> getCallingRunnables(Runnable runnable, EMap<ModeLabel, String> modes) { |
| ArrayList<Runnable> result = new ArrayList<>(); |
| for (RunnableCall callerRC : runnable.getRunnableCalls()) { |
| Runnable caller = callerRC.getContainingRunnable(); // null if container is not of type Runnable |
| if (caller == null) continue; |
| |
| if (modes != null && !modes.isEmpty()) { |
| for (RunnableCall rc : collectActivityGraphItems(caller.getActivityGraph(), modes, RunnableCall.class)) { |
| if (rc.getRunnable() == runnable) { |
| result.add(caller); |
| break; |
| } |
| } |
| } |
| else |
| result.add(caller); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a list of runnables directly called by the runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of Runnables |
| */ |
| public static List<Runnable> getCalledRunnables(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, RunnableCall.class) |
| .stream().map(RunnableCall::getRunnable).filter(Objects::nonNull).collect(Collectors.toList()); |
| } |
| |
| /** |
| * Returns a list of all execution needs for a given runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of ExecutionNeeds |
| */ |
| public static List<ExecutionNeed> getExecutionNeeds(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, ExecutionNeed.class); |
| |
| // Should nested runnable calls also be included ? (potential cycles) |
| } |
| |
| /** |
| * Returns a list of all execution needs for a given process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of ExecutionNeeds |
| */ |
| public static List<ExecutionNeed> getExecutionNeeds(Process process, EMap<ModeLabel, String> modes) { |
| List<ExecutionNeed> result = new ArrayList<>(); |
| // add needs on process level |
| result.addAll(collectActivityGraphItems(process.getActivityGraph(), modes, ExecutionNeed.class)); |
| // add needs of called runnables |
| for (Runnable run : getRunnableList(process, modes)) { |
| result.addAll(getExecutionNeeds(run, modes)); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a list of all ticks for a given runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * List of Ticks |
| */ |
| public static List<Ticks> getTicks(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, Ticks.class); |
| |
| // Should nested runnable calls also be included ? (potential cycles) |
| } |
| |
| /** |
| * Returns a list of all ticks for a given process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * List of Ticks |
| */ |
| public static List<Ticks> getTicks(Process process, EMap<ModeLabel, String> modes) { |
| List<Ticks> result = new ArrayList<>(); |
| // add ticks on process level |
| result.addAll(collectActivityGraphItems(process.getActivityGraph(), modes, Ticks.class)); |
| // add ticks of called runnables |
| for(Runnable run : getRunnableList(process, modes)) { |
| result.addAll(getTicks(run, modes)); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a set of server calls for a runnable |
| * @param runnable runnable |
| * @param modes (optional) - null works |
| * @return |
| * Set of ServerCall |
| */ |
| public static Set<ServerCall> getServerCallSet(Runnable runnable, EMap<ModeLabel, String> modes) { |
| return collectActivityGraphItems(runnable.getActivityGraph(), modes, ServerCall.class).stream().collect(Collectors.toSet()); |
| } |
| |
| /** |
| * Returns a set of server calls for a process |
| * @param process process (Task or ISR) |
| * @param modes (optional) - null works |
| * @return |
| * Set of ServerCall |
| */ |
| public static Set<ServerCall> getServerCallSet(Process process, EMap<ModeLabel, String> modes) { |
| HashSet<ServerCall> result = new HashSet<>(); |
| for (Runnable run : getRunnableList(process, modes)) { |
| result.addAll(getServerCallSet(run, modes)); |
| } |
| return result; |
| } |
| } |