blob: 2c0a1a7a32415e7d86184d8168c15675e71eb306 [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.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.app4mc.amalthea.model.Amalthea;
import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
import org.eclipse.app4mc.amalthea.model.ClearEvent;
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.Preemption;
import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
import org.eclipse.app4mc.amalthea.model.PuType;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.SetEvent;
import org.eclipse.app4mc.amalthea.model.Task;
import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;
import org.eclipse.app4mc.amalthea.model.Time;
import org.eclipse.app4mc.amalthea.model.TimeUnit;
import org.eclipse.app4mc.amalthea.model.WaitEvent;
import org.eclipse.app4mc.amalthea.model.io.AmaltheaLoader;
import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
import org.eclipse.emf.common.util.EList;
/**
* Date: August 21-2019
* @author Junhyung Ki
* @version 1.0
* This class is to analyze response time of CPU(e.g., ARM, Denver cores) Tasks in CPU-GPU Heterogeneous Systems
* The entire class is designed for Generic Algorithm Mapping to find the most optimized task mapping solution.
* Therefore, setting the integer array variable, 'tpuMapping' (which is considered as a mapping solution) along with
* others ( Amalthea Model, 'model' setting, Task Response Time HashMap, 'trt' setting (for GPU Tasks), Processing Unit List, 'pul' setting
* should be the first step before executing any response time method. (Which is done by the constructor)
*/
public class CPURta {
public final File inputFile = new File("model-input/WATERS19_release/ChallengeModel_release.amxmi");
/**
* Get Default IA Map
* @return
* this.defaultIAMapping
*/
public int[] getDefaultIAMapping() {
return SharedConsts.defaultIAMapping;
}
private Amalthea model = null;
/**
* Constructor only for testing the class
*/
public CPURta() {
this.setModel(AmaltheaLoader.loadFromFile(this.inputFile));
this.setTRT(this.getDefaultTRT(this.getModel()));
this.setIA(this.getDefaultIAMapping());
this.setPUl(CommonUtils.getPUs(this.getModel()));
}
/**
* CPURta Constructor
* @param model the observed Amalthea Model
* @param trt the observed HashMap Task with Response Time (null works => the default testing trt will be assigned)
* @param ia the observed IntegerArray Mapping Model
* @param pul the observed List of ProcessingUnits
*/
public CPURta(final Amalthea model, final HashMap<Task, Time> trt, final int[] ia, final List<ProcessingUnit> pul) {
this.setModel(model);
if (trt == null) {
this.setTRT(this.getDefaultTRT(this.getModel()));
} else {
this.setTRT(trt);
}
this.setIA(ia);
this.setPUl(pul);
}
/**
* Since this method is used by RTARuntimeUtil, the visibility should be 'public'
* @return
* The Amalthea model object of the current CPURta class
*/
public Amalthea getModel() {
return this.model;
}
/**
* Set the Amalthea model object of the current CPURta class as the given Amalthea model parameter.
* @param pAmalthea the parameter Amalthea model which would reinitialize the Amalthea model
*/
public void setModel(final Amalthea pAmalthea) {
this.model = pAmalthea;
this.setGTCL(this.model);
}
private HashMap<Task, Time> trt = null;
/**
* Since this method is used by GAMapping, the visibility should be 'public'
* @return
* trt(task with response time) HashMap variable
*/
public HashMap<Task, Time> getTRT() {
return this.trt;
}
/**
* Set the trt(task with response time) HashMap variable as the given trtp parameter variable.
* Which would contains GPU tasks' response times from the beginning
* @param trtp the HashMap variable parameter which would reinitialize the trt variable of the current CPURta class.
*/
public void setTRT(final HashMap<Task, Time> trtp) {
this.trt = trtp;
}
/**
* Get the default trt(task with response time) value in case of running CPURta class itself.
* @param model the current class's Amalthea model which is used to get the trt value out of it
* @return
* the trt value which is derived out of the given parameter Amalthea model
*/
public HashMap<Task, Time> getDefaultTRT(final Amalthea model) {
final HashMap<Task, Time> trt = new HashMap<Task, Time>();
final EList<Task> allTaskList = model.getSwModel().getTasks();
final long val = 2000000000;
for (final Task t : allTaskList) {
if (this.gpuTaskList.contains(t)) {
trt.put(t, FactoryUtil.createTime(BigInteger.valueOf(val), TimeUnit.PS));
} else {
trt.put(t, FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS));
}
}
return trt;
}
private int[] tpuMapping = null;
/**
* Since this method is used by RTARuntimeUtil, the visibility should be 'public'
* @return
* The tpuMapping integer array
*/
public int[] getIA() {
return this.tpuMapping;
}
/**
* Set the tpuMapping integer array (which would be used to modify the current task mapping to different Processing Units)
* as the given tpumap parameter variable.
* (The integer array would be used to modify the current task mapping to different Processing Units)
* @param tpumap the parameter integer array which would reinitialize the tpuMapping array of the current CPURta class.
*/
public void setIA(final int[] tpumap) {
final Logger log = Logger.getLogger(CPURta.class);
if (tpumap == null) {
this.tpuMapping = null;
} else if (tpumap.length == this.model.getSwModel().getTasks().size()) {
this.tpuMapping = tpumap;
} else {
log.error("integer array size MUST match the number of tasks");
}
}
private List<ProcessingUnit> pul = new ArrayList<>();
/**
* Get a list of ProcessingUnits
* @return
* this.pul
*/
public List<ProcessingUnit> getPUl() {
return this.pul;
}
/**
* Set the pul, the list of Processing Units variable (which would be used to map tasks along with tpuMapping array)
* as the given pul parameter variable.
* @param pul the parameter pul list which would reinitialize the pul list variable of the current CPURta class
*/
public void setPUl(final List<ProcessingUnit> pul) {
this.pul = pul;
}
private Contention ct = null;
/**
* Get the contention instance
*
* @return
* this.ct
*/
public Contention getCT() {
return this.ct;
}
/**
* Set the ct (Contention) variable which would be used to calculate memory contention of the given task that will be added up to the response time result
* as the newly generated contention instance with the given integer array
* and Amalthea model parameters.
* @param ia Integer Array which is referred to map tasks of the given model
* @param model Amalthea model
*/
public void setContention(final int[] ia, final Amalthea model) {
this.ct = new Contention(ia, model);
}
private List<Task> gpuTaskList = new ArrayList<Task>();
/**
* Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
* @return
* gpuTaskList which contains tasks (which are originally designed for GPU) of the Amalthea model
*/
protected List<Task> getGpuTaskList() {
return this.gpuTaskList;
}
private final List<Task> triggeringTaskList = new ArrayList<Task>();
/**
* Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
* @return
* triggeringTaskList which contains tasks (which contain InterProcessTrigger) of the Amalthea model
*/
protected List<Task> getTriggeringTaskList() {
return this.triggeringTaskList;
}
/* this runnable is used to calculate execution time in RTARuntimeUtil class */
protected Runnable offloadingAsyncRunnable = null;
private final HashMap<Task, List<List<Label>>> gpuToCpuLabels = new HashMap<Task, List<List<Label>>>();
/**
* Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
* @return
* gpuToCpuLabels HashMap which contains required labels (of the corresponding task)
* that need to be taken into account when GPU tasks are mapped to CPU
*/
protected HashMap<Task, List<List<Label>>> getGTCL() {
return this.gpuToCpuLabels;
}
/**
* Not only set gpuToCpuLabels HashMap, this also set gpuTaskList (only contains GPU tasks),
* triggeringTaskList (only contains tasks with InterProcessTrigger)
* and offloadingAsyncRunnable (the Runnable that is taken into account for triggering tasks when the mode is asynchronous)
* @param model the parameter Amalthea model which is used to derived required labels of the corresponding GPU task
*/
private void setGTCL(final Amalthea model) {
if (model != null) {
final EList<Task> allTaskList = model.getSwModel().getTasks();
this.gpuTaskList = allTaskList.stream().filter(s -> s.getStimuli().get(0) instanceof InterProcessStimulus).collect(Collectors.toList());
/* find the triggering tasks */
for (final Task t : allTaskList) {
final List<CallSequenceItem> triggerList = SoftwareUtil.collectCalls(t, null,
(call -> call instanceof InterProcessTrigger));
if (triggerList.size() != 0) {
this.triggeringTaskList.add(t);
if (RTARuntimeUtil.doesTaskHaveAsyncRunnable(t, this)) {
final List<CallSequenceItem> cList = SoftwareUtil.collectCalls(t, null, (call -> call instanceof TaskRunnableCall ||
call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
final int waitIndex = cList.indexOf(cList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
final int asyncOffloadingIndex = waitIndex + 1;
if (cList.get(asyncOffloadingIndex) instanceof TaskRunnableCall) {
this.offloadingAsyncRunnable = ((TaskRunnableCall) cList.get(asyncOffloadingIndex)).getRunnable();
}
}
}
}
for (final Task t : this.gpuTaskList) {
final InterProcessStimulus ips = (InterProcessStimulus) (t.getStimuli().get(0));
Task triggeringTask = null;
for (final Task tt : this.triggeringTaskList) {
final InterProcessTrigger ipt = (InterProcessTrigger) SoftwareUtil.collectCalls(tt, null,
(call -> call instanceof InterProcessTrigger)).stream().iterator().next();
if (ips.equals(ipt.getStimulus())) {
triggeringTask = tt;
break;
}
}
final List<Label> readLabelList = new ArrayList<Label>();
final List<Label> writeLabelList = new ArrayList<Label>();
final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(triggeringTask, null, (call -> call instanceof TaskRunnableCall ||
call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
final InterProcessTrigger ipt = (InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next();
final int indexforTrigger = callList.indexOf(ipt);
for (int i = 0; i < callList.size(); i++) {
Runnable thisRunnable = null;
/* Pre-processing Runnable */
if ((i < indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
thisRunnable = (Runnable) ((TaskRunnableCall) callList.get(i)).getRunnable();
final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
for (final LabelAccess la : thisLAList) {
if (la.getAccess().equals(LabelAccessEnum.READ)) {
readLabelList.add(la.getData());
}
}
}
/* Post-processing Runnable */
else if ((i > indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
for (final LabelAccess la : thisLAList) {
if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
writeLabelList.add(la.getData());
}
}
}
}
final List<List<Label>> listOfLabelList = new ArrayList<List<Label>>();
listOfLabelList.add(readLabelList);
listOfLabelList.add(writeLabelList);
this.gpuToCpuLabels.put(t, listOfLabelList);
}
} else {
this.gpuTaskList.clear();
this.triggeringTaskList.clear();
this.offloadingAsyncRunnable = null;
this.gpuToCpuLabels.clear();
}
}
/* To calculate pure memory access latency cost (without contention & pure computation(Ticks)) */
protected Time cumuAcTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
/**
* @return
* cumuAcTime, the total time of latency (Read & Write memory access) from CPUs
*/
public Time getCumulatedMemAccCosts() {
return this.cumuAcTime;
}
/**
* Initializing cumuAcTime to 0 ps
*/
public void initCumulatedMemAccCosts() {
this.cumuAcTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
/* To calculate pure latency cost (without memory access latency & pure computation(Ticks)) */
protected Time cumuConTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
/**
* @return
* cumulatedCon, the total time of latency (Contention of the task)
*/
public Time getCumulatedContention() {
return this.cumuConTime;
}
/**
* Initializing cumulatedCon to 0 ps
*/
public void initCumulatedContention() {
this.cumuConTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
public static void main(String[] args) {
org.apache.log4j.BasicConfigurator.configure();
Logger.getRootLogger().setLevel(Level.ERROR);
final CPURta cpurta = new CPURta();
cpurta.run();
}
/**
* Executable method
*/
public void run() {
final Logger log = Logger.getLogger(CPURta.class);
if (this.model == null) {
log.error("No model loaded!");
return;
}
log.debug("\n####################### The Test ########################\n");
log.debug("RT Time Sum: " + getCPUResponseTimeSum(SharedConsts.timeType));
}
/**
* Calculate the total sum of response times of the tasks of the given Amalthea model with the mapping model (tpuMapping)
* @param executionCase BCET, ACET, WCET
* @return
* total sum of all tasks' response times of the given mapped model (tpuMapping)
*/
public Time getCPUResponseTimeSum(final TimeType executionCase) {
final Logger log = Logger.getLogger(CPURta.class);
if (this.model == null) {
log.error("No Model Loaded!");
return null;
} else if (this.trt == null) {
log.error("No HashMap Loaded!");
return null;
} else if (this.tpuMapping == null) {
log.error("No IntegerArray Loaded!");
return null;
} else if (this.pul == null) {
log.error("No PUList Loaded!");
return null;
}
this.setContention(this.getIA(), this.getModel());
Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
for (int i = 0; i < this.tpuMapping.length; i++) {
final Time rt = getTaskCPURT(this.model.getSwModel().getTasks().get(i), executionCase);
if (rt.getValue().equals(BigInteger.valueOf(Long.MAX_VALUE)) && !SharedConsts.ignoreInfeasibility) {
return rt;
}
time = time.add(rt);
if (!rt.getValue().equals(BigInteger.ZERO)) {
/* only put CPU tasks */
this.trt.put(this.model.getSwModel().getTasks().get(i), rt);
}
}
return time;
}
/**
* Calculate response time of the given task of the given Amalthea model with the mapping model (tpuMapping)
* @param task the observed task
* @param executionCase BCET, ACET, WCET
* @return
* response time of the observed task
*/
protected Time getTaskCPURT(final Task task, final TimeType executionCase) {
/* 1. validate thisTask is mapped to CPU */
final int tindex = this.model.getSwModel().getTasks().indexOf(task);
final int puindex = this.tpuMapping[tindex];
final ProcessingUnit pu = this.pul.get(puindex);
if (!pu.getDefinition().getPuType().equals(PuType.CPU)) {
Logger.getLogger(CPURta.class).debug(task.getName() + " is not mapped to a CPU");
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
/* 2. get all tasks mapped to this CPU */
final List<Task> puTaskList = new ArrayList<Task>();
for (int i = 0; i < this.tpuMapping.length; i++) {
if (this.tpuMapping[i] == puindex) {
puTaskList.add(this.model.getSwModel().getTasks().get(i));
}
}
final List<Task> sortedTaskList = taskSorting(puTaskList);
return preciseTestCPURT(task, sortedTaskList, executionCase, pu);
}
/**
* Sort out the given list of tasks (in order of shorter period first - Rate Monotonic Scheduling)
* @param taskList list of tasks that is mapped to the same core
* @return
* the sorted list of tasks
*/
private List<Task> taskSorting(final List<Task> taskList) {
/* Getting stimuliList out of the given taskList (because it is RMS) */
final List<Time> stimuliList = new ArrayList<>();
for (final Task t : taskList) {
stimuliList.add(CommonUtils.getStimInTime(t));
}
/* Sorting (Shortest Period(Time) first) */
Collections.sort(stimuliList, new TimeCompIA());
/* Sort tasks to the newTaskList in order of Period length (shortest first
* longest last)-(according to the stimuliList) */
final List<Task> newTaskList = new ArrayList<>();
for (int i = 0; i < stimuliList.size(); i++) {
for (final Task t : taskList) {
if ((!newTaskList.contains(t)) && (stimuliList.get(i).compareTo(CommonUtils.getStimInTime(t)) == 0)) {
newTaskList.add(t);
}
}
}
return newTaskList;
}
/**
* Visibility - public (This method is for the UI version code (ui package > RTApp.java))
* Calculate response time of the observed task according to the periodic tasks response time analysis algorithm.
* @param task the observed task
* @param taskList list of tasks that is mapped to the same core
* @param executionCase BCET, ACET, WCET
* @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
* @return
* response time of the observed task
*/
public Time preciseTestCPURT(final Task task, final List<Task> taskList, final TimeType executionCase, final ProcessingUnit pu) {
final Logger log = Logger.getLogger(CPURta.class);
Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (taskList.size() == 0) {
log.debug("!!! This taskList is empty so I am returning MAX !!!");
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
/* to check if the given task is in the taskList */
int flag = 0;
int index = 0;
for (int i = 0; i < taskList.size(); i++) {
if (task.equals(taskList.get(i))) {
flag = 1;
index = i;
break;
}
}
if (flag == 0) {
log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
for (int i = 0; i < index + 1; i++) {
period = CommonUtils.getStimInTime(taskList.get(i));
if (index == 0) {
thisRT = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, this);
if (thisRT.compareTo(period) <= 0) {
/* To analyze the pure latency time */
if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
}
return thisRT;
}
log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+ " for task " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
} else if (i == index) {
/* In the case of a COOPERATIVE Preemption typed Task */
if (taskList.get(i).getPreemption().equals(Preemption.COOPERATIVE)) {
// TODO: Blocking
}
final Time thisExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, this);
if (thisExeTime.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
return thisExeTime;
} else if (thisExeTime.compareTo(period) > 0) {
log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+ " for task " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
Time culmulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
/* 1. add all the execution time till the index */
for (int j = 0; j < i + 1; j++) {
final Time thisTime = rtaut.getExecutionTimeforCPUTask(taskList.get(j), pu, executionCase, this);
culmulativeRT = culmulativeRT.add(thisTime);
}
if (culmulativeRT.compareTo(period) <= 0) {
while (true) {
Time excepThisExeTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
for (int k = 0; k < i; k++) {
Time localPeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
localPeriod = CommonUtils.getStimInTime(taskList.get(k));
final Time preExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(k), pu, executionCase, this);
final double ri_period = Math.ceil(culmulativeRT.divide(localPeriod));
excepThisExeTime = excepThisExeTime.add(preExeTime.multiply(ri_period));
}
Time culmulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
culmulativeRT_x = thisExeTime.add(excepThisExeTime);
if (culmulativeRT_x.compareTo(period) <= 0) {
if (culmulativeRT_x.compareTo(culmulativeRT) == 0) {
thisRT = culmulativeRT_x;
/* To analyze the pure latency time */
if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
}
return thisRT;
}
culmulativeRT = culmulativeRT_x;
} else {
log.debug("!!! This is non schedulable...!!! Because of the period " + period
+ " being less than the response time (culmulativeRT_x) of " + culmulativeRT_x + " for task " + task.getName());
if (SharedConsts.ignoreInfeasibility) {
return culmulativeRT_x;
}
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
}
}
log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + culmulativeRT
+ " for task " + task.getName());
if (SharedConsts.ignoreInfeasibility) {
return culmulativeRT;
}
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
}
/* To analyze the pure latency time */
if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
}
return thisRT;
}
/**
* Calculate response time of the observed task according to the implicit communication paradigm.
* @param task the observed task
* @param taskList list of tasks that is mapped to the same core
* @param executionCase BCET, ACET, WCET
* @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
* @param cpurta the instance of CPURta class that contains model & mapping IA info
* @return
* response time of the observed task (implicit communication paradigm)
*/
public Time implicitPreciseTest(final Task task, final List<Task> taskList, final TimeType executionCase,
final ProcessingUnit pu, final CPURta cpurta) {
final Logger log = Logger.getLogger(CPURta.class);
Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (taskList.size() == 0) {
log.debug("!!! This taskList is empty so I am returning MAX !!!");
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
/* to check if the given task is in the taskList */
int flag = 0;
int index = 0;
for (int i = 0; i < taskList.size(); i++) {
if (task.equals(taskList.get(i))) {
flag = 1;
index = i;
break;
}
}
if (flag == 0) {
log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
for (int i = 0; i < index + 1; i++) {
period = CommonUtils.getStimInTime(taskList.get(i));
if (index == 0) {
thisRT = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, cpurta);
final Time[] ta = rtaut.getLocalCopyTimeArray(taskList.get(i), pu, executionCase, cpurta);
for (int j = 0; j < ta.length; j++) {
thisRT = thisRT.add(ta[j]);
}
if (thisRT.compareTo(period) <= 0) {
return thisRT;
}
log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+ " for task " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
} else if (i == index) {
/* In the case of a COOPERATIVE Preemption typed Task */
Time thisExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, cpurta);
final Time[] ta = rtaut.getLocalCopyTimeArray(taskList.get(i), pu, executionCase, cpurta);
for (int j = 0; j < ta.length; j++) {
thisExeTime = thisExeTime.add(ta[j]);
}
if (thisExeTime.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
return thisExeTime;
} else if (thisExeTime.compareTo(period) > 0) {
log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+ " for task " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
Time culmulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
/* 1. add all the execution time till the index */
for (int j = 0; j < i + 1; j++) {
Time thisTime = rtaut.getExecutionTimeforCPUTask(taskList.get(j), pu, executionCase, cpurta);
final Time[] ta_ = rtaut.getLocalCopyTimeArray(taskList.get(j), pu, executionCase, cpurta);
for (int k = 0; k < ta_.length; k++) {
thisTime = thisTime.add(ta[k]);
}
culmulativeRT = culmulativeRT.add(thisTime);
}
if (culmulativeRT.compareTo(period) <= 0) {
while (true) {
Time excepThisExeTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
for (int j = 0; j < i; j++) {
Time localPeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
localPeriod = CommonUtils.getStimInTime(taskList.get(j));
Time preExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(j), pu, executionCase, cpurta);
final Time[] ta_ = rtaut.getLocalCopyTimeArray(taskList.get(j), pu, executionCase, cpurta);
for (int k = 0; k < ta_.length; k++) {
preExeTime = preExeTime.add(ta_[k]);
}
final double ri_period = Math.ceil(culmulativeRT.divide(localPeriod));
excepThisExeTime = excepThisExeTime.add(preExeTime.multiply(ri_period));
}
Time culmulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
culmulativeRT_x = thisExeTime.add(excepThisExeTime);
if (culmulativeRT_x.compareTo(period) <= 0) {
if (culmulativeRT_x.compareTo(culmulativeRT) == 0) {
thisRT = culmulativeRT_x;
return thisRT;
}
culmulativeRT = culmulativeRT_x;
} else {
log.debug("!!! This is non schedulable...!!! Because of the period " + period
+ " being less than the response time (culmulativeRT_x) of " + culmulativeRT_x + " for task " + task.getName());
if (SharedConsts.ignoreInfeasibility) {
return culmulativeRT_x;
}
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
}
}
log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + culmulativeRT
+ " for task " + task.getName());
if (SharedConsts.ignoreInfeasibility) {
return culmulativeRT;
}
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
}
return thisRT;
}
/**
* Visibility - public (This method is for the UI version code (ui package > RTApp.java))
* It returns HashMap<Integer, List<Task>> Type reference that contains an Integer(number of Processing Unit index) and the corresponding List of Tasks
* This is to visualize which task is mapped to which processing unit.
* @return
* HashMap<Integer, List<Task>> puListHashMap
*/
public HashMap<Integer, List<Task>> be_getPUTaskListHashMap(final Amalthea model) {
HashMap<Integer, List<Task>> puListHashMap = new HashMap<>();
final EList<Task> allTaskList = model.getSwModel().getTasks();
for(int i = 0; i < this.pul.size(); i++) {
final List<Task> puTaskList = new ArrayList<Task>();
for(int j = 0; j < this.tpuMapping.length; j++) {
final int puIndex = this.tpuMapping[j];
if (i == puIndex) {
puTaskList.add(allTaskList.get(j));
}
}
puListHashMap.put(i, taskSorting(puTaskList));
}
return puListHashMap;
}
}
/**
* @Date: August 21-2019
* @author Junhyung Ki
* @version 1.0
* This inner class is used for the method "taskSorting" to help compare between two tasks' periods (which is longer)
* If the time of arg0 is shorter than that of arg1, it returns -1.
* If the time of arg0 is longer than that of arg1, it returns 1.
*/
class TimeCompIA implements Comparator<Time> {
@Override
public int compare(final Time arg0, final Time arg1) {
if (arg0.compareTo(arg1) < 0) {
return -1;
}
return 1;
}
}