0.9.4 > 0.9.7 migration with other updates
1. E2ELatency.java
- single-core analysis implemented
- advanced multi-core analysis implemented
2. CPURta.java
- minor changes with constructors
3. IRTA.java interface is added to CPURta class.
Change-Id: Ib6e0de8cf8155adaa68b42b0ef89cb27f5da97f8
Signed-off-by: Junhyung Ki <kijoonh91@gmail.com>
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
index d5a0fa2..1375a74 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
@@ -8,12 +8,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*
- * Contributors: FH Dortmund - initial API and implementation
- *
+ * Contributors:
+ * FH Dortmund - initial API and implementation
*******************************************************************************/
package org.eclipse.app4mc.gsoc_rta;
import java.io.File;
+import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
@@ -24,8 +25,13 @@
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
+import org.eclipse.app4mc.gsoc_rta.IRTA;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts;
+import org.eclipse.app4mc.gsoc_rta.Contention;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.Amalthea;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
import org.eclipse.app4mc.amalthea.model.ClearEvent;
import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
@@ -36,9 +42,9 @@
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.RunnableCall;
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;
@@ -46,51 +52,53 @@
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;
+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;
+public class CPURta implements IRTA {
+ final Logger log = Logger.getLogger(CPURta.class);
+ private Amalthea model;
+
+ public static void main(final String[] args) {
+ org.apache.log4j.BasicConfigurator.configure();
+ // TODO set model and mapping int array
+ // COMMENT: this func (executable) should actually be removed and replaced by a unit test
+ final CPURta cpurta = new CPURta(false);
+ cpurta.run();
}
-
- private Amalthea model = null;
- /**
- * Constructor only for testing the class
- */
- public CPURta() {
- final Logger log = Logger.getLogger(CPURta.class);
- final Amalthea pModel = AmaltheaLoader.loadFromFile(this.inputFile);
- if (pModel == null) {
- log.error("Model is empty. Please check the model path.");
+ public void run() {
+ if (this.model == null) {
+ System.out.println("Error: No model loaded!");
return;
- } else {
- this.setModel(AmaltheaLoader.loadFromFile(this.inputFile));
}
- this.setTRT(this.getDefaultTRT(this.getModel()));
- this.setIA(this.getDefaultIAMapping());
- this.setPUl(CommonUtils.getPUs(this.getModel()));
+ log.setLevel(Level.ERROR);
+ log.debug("\n####################### The Test ########################\n");
+ log.debug("RT Time Sum: " + getRTSum(SharedConsts.timeType));
}
/**
* CPURta Constructor
+ * @param forFunctions
+ * true: to create an object to use functions
+ * false: to create a default object for CPURta measurement
+ */
+ public CPURta(final boolean forFunctions) {
+ if (!forFunctions) {
+ final Amalthea pModel = AmaltheaLoader.loadFromFile(this.inputFile);
+ if (pModel == null) {
+ log.error("Model is empty. Please check the model path.");
+ return;
+ } else {
+ this.setModel(pModel);
+ }
+ this.setTRT(getDefaultTRT(getModel()));
+ this.setIA(this.defaultIAMapping);
+ this.setPUl(CommonUtils.getPUs(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
@@ -104,49 +112,55 @@
this.setTRT(trt);
}
this.setIA(ia);
- this.setPUl(pul);
+ if (pul == null) {
+ this.setPUl(CommonUtils.getPUs(getModel()));
+ } else {
+ this.setPUl(pul);
+ }
+ this.setContention(this.getIA(), this.getModel());
}
-
+
/**
* Since this method is used by RTARuntimeUtil, the visibility should be 'public'
* @return
- * The Amalthea model object of the current CPURta class
+ * The Amalthea model object of the current CPURtaIA class
*/
public Amalthea getModel() {
return this.model;
}
-
+
/**
- * Set the Amalthea model object of the current CPURta class as the given Amalthea model parameter.
+ * Set the Amalthea model object of the current CPURtaIA 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.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
*/
+ @Override
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.
+ * @param trtp the HashMap variable parameter which would reinitialize the trt variable of the current CPURtaIA 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.
+ * Get the default trt(task with response time) value in case of running CPURtaIA 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
@@ -158,32 +172,33 @@
for (final Task t : allTaskList) {
if (this.gpuTaskList.contains(t)) {
trt.put(t, FactoryUtil.createTime(BigInteger.valueOf(val), TimeUnit.PS));
- } else {
+ }
+ 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'
+ * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
+ *
* @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.
+ * @param tpumap the parameter integer array which would reinitialize the tpuMapping array of the current CPURtaIA 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()) {
@@ -192,7 +207,7 @@
log.error("integer array size MUST match the number of tasks");
}
}
-
+
private List<ProcessingUnit> pul = new ArrayList<>();
/**
@@ -203,28 +218,27 @@
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
+ * @param pul the parameter pul list which would reinitialize the pul list variable of the current CPURtaIA 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() {
+ protected 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
@@ -235,7 +249,7 @@
public void setContention(final int[] ia, final Amalthea model) {
this.ct = new Contention(ia, model);
}
-
+
private List<Task> gpuTaskList = new ArrayList<Task>();
/**
@@ -256,12 +270,12 @@
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
@@ -271,7 +285,7 @@
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)
@@ -279,48 +293,48 @@
* @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();
- }
+ 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<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(t.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+ if (triggerList.size() != 0) {
+ this.triggeringTaskList.add(t);
+ if (RTARuntimeUtil.doesTaskHaveAsyncRunnable(t, this)) {
+ final List<ActivityGraphItem> cList = SoftwareUtil.collectActivityGraphItems(t.getActivityGraph(), null, (call -> call instanceof RunnableCall
+ || 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 RunnableCall) {
+ this.offloadingAsyncRunnable = ((RunnableCall) 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;
- }
+ }
+ 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
+ .collectActivityGraphItems(tt.getActivityGraph(), 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 List<Label> readLabelList = new ArrayList<Label>();
+ final List<Label> writeLabelList = new ArrayList<Label>();
+ if (null != triggeringTask) {
+ final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(triggeringTask.getActivityGraph(), null,
+ (call -> call instanceof RunnableCall || 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();
+ if ((i < indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+ thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
for (final LabelAccess la : thisLAList) {
if (la.getAccess().equals(LabelAccessEnum.READ)) {
@@ -329,8 +343,8 @@
}
}
/* Post-processing Runnable */
- else if ((i > indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
- thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
+ else if ((i > indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+ thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
for (final LabelAccess la : thisLAList) {
if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
@@ -339,22 +353,17 @@
}
}
}
- 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();
+ final List<List<Label>> aryofLabelList = new ArrayList<List<Label>>();
+ aryofLabelList.add(readLabelList);
+ aryofLabelList.add(writeLabelList);
+ this.gpuToCpuLabels.put(t, aryofLabelList);
}
}
-
+
/* 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
@@ -362,14 +371,14 @@
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);
@@ -388,24 +397,10 @@
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));
+ HashMap<Task, Time> accessCosts = new HashMap<>();
+
+ public HashMap<Task, Time> getAccessCosts() {
+ return this.accessCosts;
}
/**
@@ -414,8 +409,8 @@
* @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);
+ @Override
+ public Time getRTSum(final TimeType executionCase) {
if (this.model == null) {
log.error("No Model Loaded!");
return null;
@@ -431,8 +426,9 @@
}
this.setContention(this.getIA(), this.getModel());
Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ final EList<Task> allTaskList = this.model.getSwModel().getTasks();
for (int i = 0; i < this.tpuMapping.length; i++) {
- final Time rt = getTaskCPURT(this.model.getSwModel().getTasks().get(i), executionCase);
+ final Time rt = getTaskRTIA(allTaskList.get(i), executionCase);
if (rt.getValue().equals(BigInteger.valueOf(Long.MAX_VALUE)) && !SharedConsts.ignoreInfeasibility) {
return rt;
}
@@ -444,15 +440,15 @@
}
return time;
}
-
+
/**
- * Calculate response time of the given task of the given Amalthea model with the mapping model (tpuMapping)
+ * Calculate worst-case 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) {
+ protected Time getTaskRTIA(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];
@@ -469,9 +465,16 @@
}
}
final List<Task> sortedTaskList = taskSorting(puTaskList);
- return preciseTestCPURT(task, sortedTaskList, executionCase, pu);
+ if (executionCase.equals(TimeType.BCET)) {
+ return this.bestCaseCPURT(task, sortedTaskList, pu);
+ } else if (executionCase.equals(TimeType.WCET)) {
+ return SharedConsts.levelIBusyPeriod ? this.responseTimeLevelI(task, sortedTaskList, TimeType.WCET, pu)
+ : this.preciseTestCPURT(task, sortedTaskList, TimeType.WCET, pu);
+ }
+ return SharedConsts.levelIBusyPeriod ? this.responseTimeLevelI(task, sortedTaskList, TimeType.WCET, pu)
+ : this.preciseTestCPURT(task, sortedTaskList, TimeType.ACET, 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
@@ -498,19 +501,17 @@
}
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.
+ * Calculate response time of the observed task according to the worst-case RMS 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
+ * the worst-case 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) {
@@ -532,102 +533,363 @@
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;
+ period = CommonUtils.getStimInTime(taskList.get(index));
+ if (index == 0) {
+ thisRT = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(index), 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 {
+ /* In the case of a COOPERATIVE Preemption typed Task */
+ if (taskList.get(index).getPreemption().equals(Preemption.COOPERATIVE)) {
+ // TODO: Blocking
+ }
+ final Time thisExeTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(index), 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);
- } 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;
+ }
+ Time cumulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ /* 1. add all the execution time till the index - RT_0 */
+ for (int j = 0; j < index + 1; j++) {
+ final Time thisTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(j), pu, executionCase, this);
+ cumulativeRT = cumulativeRT.add(thisTime);
+ }
+ if (cumulativeRT.compareTo(period) <= 0) {
+ while (true) {
+ Time excepThisExeTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ for (int j = 0; j < index; j++) {
+ Time localPeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ localPeriod = CommonUtils.getStimInTime(taskList.get(j));
+ final Time preExeTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(j), pu, executionCase, this);
+ final double ri_period = Math.ceil(cumulativeRT.divide(localPeriod));
+ excepThisExeTime = excepThisExeTime.add(preExeTime.multiply(ri_period));
+ }
+ Time cumulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ cumulativeRT_x = thisExeTime.add(excepThisExeTime);
+ if (cumulativeRT_x.compareTo(period) <= 0) {
+ if (cumulativeRT_x.compareTo(cumulativeRT) == 0) {
+ thisRT = cumulativeRT_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));
}
- 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);
+ return thisRT;
}
+ cumulativeRT = cumulativeRT_x;
+ } else {
+ log.debug("!!! This is non schedulable...!!! Because of the period " + period
+ + " being less than the response time (cumulativeRT_x) of " + cumulativeRT_x + " for task " + task.getName());
+ if (SharedConsts.ignoreInfeasibility) {
+ return cumulativeRT_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);
}
+ log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + cumulativeRT
+ + " for task " + task.getName());
+ if (SharedConsts.ignoreInfeasibility) {
+ return cumulativeRT;
+ }
+ 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.
+ * Calculate response time of the observed task according to the best-case RMS response time analysis algorithm.
+ * (source: https://www.researchgate.net/publication/3958297_Exact_best-case_response_time_analysis_of_fixed_priority_scheduled_tasks (equ_16))
+ * @param task the observed task
+ * @param taskList list of tasks that is mapped to the same core
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @return
+ * the best-case response time of the observed task
+ */
+ public Time bestCaseCPURT(final Task task, final List<Task> taskList, final ProcessingUnit pu) {
+ Time bcrt = 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);
+ } else if (!taskList.contains(task)) {
+ 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();
+ Time bR_0 = this.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
+ for (int i = 0; i < index + 1; i++) {
+ if (index == 0) {
+ bcrt = bR_0;
+ break;
+ }
+ else if (i == index) {
+ final Time i_BCET = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, this);
+ final Time rt_0 = this.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
+ Time rt_n = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ boolean isItFirst = true;
+ while (true) {
+ Time sum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ for (int j = 0; j < i; j++) {
+ final Task curTask = taskList.get(j);
+ final Time curTask_period = CommonUtils.getStimInTime(curTask);
+ final Time curTask_BCET = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.BCET, this);
+ if (isItFirst) {
+ double ceil_value = Math.ceil((rt_0.subtract(curTask_period)).divide(curTask_period));
+ if (ceil_value < 0) {
+ ceil_value = 0;
+ }
+ final Time curIterTime = curTask_BCET.multiply(ceil_value);
+ sum = sum.add(curIterTime);
+ } else {
+ double ceil_value = Math.ceil((rt_n.subtract(curTask_period)).divide(curTask_period));
+ if (ceil_value < 0) {
+ ceil_value = 0;
+ }
+ final Time curIterTime = curTask_BCET.multiply(ceil_value);
+ sum = sum.add(curIterTime);
+ }
+ }
+ Time temp = i_BCET.add(sum);
+ if(isItFirst) {
+ if (temp.compareTo(rt_0) == 0) {
+ bcrt = temp;
+ break;
+ } else {
+ rt_n = temp;
+ }
+ } else {
+ if (temp.compareTo(rt_n) == 0) {
+ bcrt = temp;
+ break;
+ } else {
+ rt_n = temp;
+ }
+ }
+ isItFirst = false;
+ }
+ }
+ }
+ return bcrt;
+ }
+
+ /** New method implement from the news paper with Level_i
+ * @param thisTask
+ * @param thisTaskList
+ * @param executionCase
+ * @param pu
+ * @return
+ */
+ private Time responseTimeLevelI(final Task thisTask, final List<Task> thisTaskList, final TimeType executionCase, final ProcessingUnit pu) {
+ Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+
+ if (thisTaskList.size() == 0) {
+ log.debug("!!! This taskList is empty !!!");
+ // TODO: Catch Exception
+ return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+ }
+
+ /* to check if the given task is in the thisTaskList */
+ int flag = 0;
+ int index = 0;
+ for (int i = 0; i < thisTaskList.size(); i++) {
+ if (thisTask.equals(thisTaskList.get(i))) {
+ flag = 1;
+ index = i;
+ break;
+ }
+ }
+ /*
+ * the problem seems like once a gpu task (mapped to cpu) changes its stimulus it becomes completely new (or maybe not)
+ */
+ if (flag == 0) {
+ log.debug("!!! Nothing in the taskList matches the given Task !!!" + " --- thisTask: " + thisTask.getName());
+
+ // TODO: Catch Exception
+ return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+ }
+ final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+ final Time checkingTime = rtaut.getExecutionTimeforCPUTaskIA(thisTask, pu, executionCase, this);
+
+ if (checkingTime.getValue().longValue() == 0) {
+
+ return checkingTime;
+ }
+
+ /* Checking whether task list is schedulable or not */
+ double UtilizationValue = 0.0;
+ for (final Task task : thisTaskList) {
+ final Time exeTime = rtaut.getExecutionTimeforCPUTaskIA(task, pu, executionCase, this);
+ final Time periodTime = CommonUtils.getStimInTime(task);
+ final BigInteger exeTimePico = AmaltheaServices.convertToPicoSeconds(exeTime);
+ final BigInteger periodTimePico = AmaltheaServices.convertToPicoSeconds(periodTime);
+
+ UtilizationValue += (exeTimePico.doubleValue()) / (periodTimePico.doubleValue());
+ }
+
+ if (UtilizationValue > 1.0) {
+ final Time rpTime = FactoryUtil.createTime(Long.MAX_VALUE, TimeUnit.PS);
+ return rpTime;
+ }
+
+ /* ----------------------------------------------- */
+ /* Start applying level i approach from here */
+ for (int i = 0; i < index + 1; i++) {
+ period = CommonUtils.getStimInTime(thisTaskList.get(i));
+ if (index == 0) {
+ thisRT = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(i), pu, executionCase, this);
+ if (thisRT.compareTo(period) <= 0) {
+ if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
+ this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(thisTask, pu, executionCase));
+ }
+ return thisRT;
+ }
+ log.debug("!!! This is non schedulable...!!! Because of the period " + period + " is less than the execution time of " + thisRT + " for task "
+ + thisTask.getName());
+
+ // TODO: Catch Exception
+ return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+ }
+ else if (i == index) {
+ /* In the case of a COOPERATIVE Preemption typed Task */
+ if (thisTaskList.get(i).getPreemption().equals(Preemption.COOPERATIVE)) {
+ // TODO: Blocking
+ }
+ final Time thisExeTime = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.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 " + thisTask.getName());
+ // TODO: Catch Exception
+ return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+ }
+
+ BigDecimal l_value = BigDecimal.valueOf(1.0);
+ BigDecimal currentL_value = BigDecimal.valueOf(1.0);
+ BigDecimal temp = BigDecimal.valueOf(2.0);
+ BigDecimal localSum = BigDecimal.valueOf(0.0);
+ while (localSum.compareTo(temp) != 0) {
+ localSum = BigDecimal.valueOf(0);
+ for (int j = 0; j < i + 1; j++) {
+ temp = currentL_value;
+ Time thePeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time localExe = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ thePeriod = CommonUtils.getStimInTime(thisTaskList.get(j));
+
+ localExe = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(j), pu, executionCase, this);
+ final double periodInDouble = AmaltheaServices.convertToPicoSeconds(thePeriod).doubleValue();
+ final double exeInDouble = AmaltheaServices.convertToPicoSeconds(localExe).doubleValue();
+ final BigDecimal periodInDoubleBD = BigDecimal.valueOf(periodInDouble);
+ final BigDecimal exeInDoubleBD = BigDecimal.valueOf(exeInDouble);
+
+ /* l_value = Math.ceil(currentL_value / periodInDouble) * exeInDouble; */
+ l_value = currentL_value.divide(periodInDoubleBD, 0, BigDecimal.ROUND_UP).multiply(exeInDoubleBD);
+ localSum = localSum.add(l_value);
+ }
+ currentL_value = localSum;
+
+ }
+ final BigDecimal taskPeriodBD = BigDecimal.valueOf(AmaltheaServices.convertToPicoSeconds(period).doubleValue());
+
+ /*
+ * final int k_value = (int) Math.ceil(localSum /AmaltheaServices.convertToPicoSeconds(period).doubleValue());
+ */
+ final BigDecimal k_value = localSum.divide(taskPeriodBD, 0, BigDecimal.ROUND_UP);
+ // System.out.println("k value = " + k_value);
+ final List<Double> rtList = new ArrayList<Double>();
+
+ // double fl_value = 1.0;
+ BigDecimal fl_value = BigDecimal.valueOf(1.0);
+ // double ftemp = 3.0;
+ BigDecimal ftemp = BigDecimal.valueOf(3.0);
+
+ for (int j = 1; j <= k_value.intValue(); j++) {
+ ftemp = BigDecimal.valueOf(3.0);
+ while (fl_value.compareTo(ftemp) != 0) {
+ // double flocalSum = 0.0;
+ BigDecimal flocalSum = BigDecimal.valueOf(0.0);
+ // double fSum = 0.0;
+ BigDecimal fSum = BigDecimal.valueOf(0.0);
+ // Assign temp for comparation
+ ftemp = fl_value;
+ for (int m = 0; m < i; m++) {
+ Time thePeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time localExe = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ thePeriod = CommonUtils.getStimInTime(thisTaskList.get(j));
+ localExe = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(m), pu, executionCase, this);
+ final BigInteger periodInteger = AmaltheaServices.convertToPicoSeconds(thePeriod);
+ final BigInteger exeInteger = AmaltheaServices.convertToPicoSeconds(localExe);
+ // Value parsing
+ final double Tj = periodInteger.doubleValue();
+ final double Cj = exeInteger.doubleValue();
+ final BigDecimal TjBD = BigDecimal.valueOf(Tj);
+ final BigDecimal CjBD = BigDecimal.valueOf(Cj);
+
+ // flocalSum = Math.ceil(fl_value / Tj) * Cj;
+ flocalSum = fl_value.divide(TjBD, 0, BigDecimal.ROUND_UP).multiply(CjBD);
+
+ fSum = fSum.add(flocalSum);
+ }
+ final double Ci = AmaltheaServices.convertToPicoSeconds(thisExeTime).doubleValue();
+ // Fvalue of 1 iteration
+ // fl_value = fSum + j * Ci;
+ fl_value = BigDecimal.valueOf(fSum.doubleValue() + j * Ci);
+ }
+ // Final fl_value landed here
+ final double this_rt = fl_value.doubleValue() - (j - 1) * AmaltheaServices.convertToPicoSeconds(period).doubleValue();
+ rtList.add(this_rt);
+ }
+ final double rpt = Collections.max(rtList);
+ final Time responseTime = FactoryUtil.createTime(BigInteger.valueOf((long) rpt), TimeUnit.PS);
+ if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
+ this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(thisTask, pu, executionCase));
+ }
+ return responseTime;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Calculate the worst-case response time of the observed task according to the implicit 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)
- * @param cpurta the instance of CPURta class that contains model & mapping IA info
+ * @param cpurta the instance of CPURtaIA class that contains model & mapping IA info
* @return
- * response time of the observed task (implicit communication paradigm)
+ * the worst-case 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) {
@@ -652,7 +914,7 @@
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);
+ thisRT = rtaut.getExecutionTimeforCPUTaskIA(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]);
@@ -665,7 +927,7 @@
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);
+ Time thisExeTime = rtaut.getExecutionTimeforCPUTaskIA(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]);
@@ -677,72 +939,216 @@
+ " for task " + task.getName());
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
- Time culmulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time cumulativeRT = 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);
+ Time thisTime = rtaut.getExecutionTimeforCPUTaskIA(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);
+ cumulativeRT = cumulativeRT.add(thisTime);
}
- if (culmulativeRT.compareTo(period) <= 0) {
+ if (cumulativeRT.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);
+ Time preExeTime = rtaut.getExecutionTimeforCPUTaskIA(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));
+ final double ri_period = Math.ceil(cumulativeRT.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;
+ Time cumulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ cumulativeRT_x = thisExeTime.add(excepThisExeTime);
+ if (cumulativeRT_x.compareTo(period) <= 0) {
+ if (cumulativeRT_x.compareTo(cumulativeRT) == 0) {
+ thisRT = cumulativeRT_x;
return thisRT;
}
- culmulativeRT = culmulativeRT_x;
+ cumulativeRT = cumulativeRT_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());
+ + " being less than the response time (cumulativeRT_x) of " + cumulativeRT_x + " for task " + task.getName());
if (SharedConsts.ignoreInfeasibility) {
- return culmulativeRT_x;
+ return cumulativeRT_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
+ log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + cumulativeRT
+ " for task " + task.getName());
if (SharedConsts.ignoreInfeasibility) {
- return culmulativeRT;
+ return cumulativeRT;
}
return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
}
}
return thisRT;
}
+
+ /**
+ * Calculate response time of the observed task according to the best-case RMS response time analysis algorithm with Implicit Communication.
+ * (source: https://www.researchgate.net/publication/3958297_Exact_best-case_response_time_analysis_of_fixed_priority_scheduled_tasks (equ_16))
+ * @param task the observed task
+ * @param taskList list of tasks that is mapped to the same core
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @return
+ * the best-case response time of the observed task with Implicit Communication
+ */
+ public Time implicitBCCPURT(final Task task, final List<Task> taskList, final ProcessingUnit pu, final CPURta cpurta) {
+ Time bcrt = 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);
+ } else if (!taskList.contains(task)) {
+ 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();
+ Time bR_0 = this.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
+ for (int i = 0; i < index + 1; i++) {
+ if (index == 0) {
+ bcrt = bR_0;
+ break;
+ }
+ else if (i == index) {
+ Time i_BCET = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, this);
+ final Time[] ta = rtaut.getLocalCopyTimeArray(task, pu, TimeType.BCET, this);
+ for (int j = 0; j < ta.length; j++) {
+ i_BCET = i_BCET.add(ta[j]);
+ }
+ final Time rt_0 = this.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
+ Time rt_n = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ boolean isItFirst = true;
+ while (true) {
+ Time sum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ for (int j = 0; j < i; j++) {
+ final Task curTask = taskList.get(j);
+ final Time curTask_period = CommonUtils.getStimInTime(curTask);
+ Time curTask_BCET = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.BCET, this);
+ final Time[] ta_ = rtaut.getLocalCopyTimeArray(curTask, pu, TimeType.BCET, this);
+ for (int k = 0; k < ta_.length; k++) {
+ curTask_BCET = curTask_BCET.add(ta[k]);
+ }
+ if (isItFirst) {
+ double ceil_value = Math.ceil((rt_0.subtract(curTask_period)).divide(curTask_period));
+ if (ceil_value < 0) {
+ ceil_value = 0;
+ }
+ final Time curIterTime = curTask_BCET.multiply(ceil_value);
+ sum = sum.add(curIterTime);
+ } else {
+ double ceil_value = Math.ceil((rt_n.subtract(curTask_period)).divide(curTask_period));
+ if (ceil_value < 0) {
+ ceil_value = 0;
+ }
+ final Time curIterTime = curTask_BCET.multiply(ceil_value);
+ sum = sum.add(curIterTime);
+ }
+ }
+ Time temp = i_BCET.add(sum);
+ System.out.println("sum: " + sum + ", temp: " + temp);
+ if(isItFirst) {
+ if (temp.compareTo(rt_0) == 0) {
+ bcrt = temp;
+ break;
+ } else {
+ rt_n = temp;
+ }
+ } else {
+ if (temp.compareTo(rt_n) == 0) {
+ bcrt = temp;
+ break;
+ } else {
+ rt_n = temp;
+ }
+ }
+ isItFirst = false;
+ }
+ }
+ }
+ return bcrt;
+ }
+
+ /**
+ * get the processing unit that the observed task is mapped to
+ * @param task the observed task
+ * @param cpurta the instance of CPURta class
+ * @return
+ * pu
+ */
+ protected ProcessingUnit getPU(final Task task, final CPURta cpurta) {
+ final int tindex = cpurta.getModel().getSwModel().getTasks().indexOf(task);
+ final int puindex = cpurta.getIA()[tindex];
+ final ProcessingUnit pu = cpurta.getPUl().get(puindex);
+ return pu;
+ }
+
+ /**
+ * get the sorted task listed based on the given integer array mapping
+ * @param task the observed task
+ * @param pu ProcessingUnit that would compute the given method
+ * @param cpurta the instance of CPURta class
+ * @return
+ * sortedTaskList
+ */
+ protected List<Task> getSortedTaskList(final Task task, final ProcessingUnit pu, final CPURta cpurta) {
+ final int puIndex = cpurta.getPUl().indexOf(pu);
+ /* 2. get all tasks mapped to this CPU */
+ final List<Task> puTaskList = new ArrayList<Task>();
+ for (int i = 0; i < cpurta.getIA().length; i++) {
+ if (cpurta.getIA()[i] == puIndex) {
+ puTaskList.add(cpurta.getModel().getSwModel().getTasks().get(i));
+ }
+ }
+ final List<Task> sortedTaskList = taskSorting(puTaskList);
+ return sortedTaskList;
+ }
+
+ protected List<Task> getHigherPriorityTasks(final Task task, CPURta cpurta) {
+ final ProcessingUnit pu = getPU(task, cpurta);
+ final List<Task> hpList = getSortedTaskList(task, pu, cpurta);
+ final int index = hpList.indexOf(task);
+ final int count = hpList.size() - index;
+ for (int i = 0; i < count; i++) {
+ hpList.remove(hpList.size()-1);
+ }
+ return hpList;
+ }
/**
- * Visibility - public (This method is for the UI version code (ui package > RTApp.java))
+ * Visibility - public (This method is for EffectChainLatency)
* 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<>();
+ public HashMap<Integer, List<Task>> getPUTaskListHashMap(final Amalthea model) {
+ final HashMap<Integer, List<Task>> puListHashMap = new HashMap<>();
final EList<Task> allTaskList = model.getSwModel().getTasks();
- for(int i = 0; i < this.pul.size(); i++) {
+ 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++) {
+ for (int j = 0; j < this.tpuMapping.length; j++) {
final int puIndex = this.tpuMapping[j];
if (i == puIndex) {
puTaskList.add(allTaskList.get(j));
@@ -752,15 +1158,19 @@
}
return puListHashMap;
}
+
+ @Override
+ public Time getRT(final Task t, final TimeType timeType) {
+ if (null == getTRT().get(t)) {
+ getRTSum(timeType);
+ }
+ return getTRT().get(t);
+ }
}
/**
- * @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.
+ * this inner class is used for the method "taskSorting" to help compare between two tasks' periods (which is longer)
*/
class TimeCompIA implements Comparator<Time> {
@Override
@@ -770,4 +1180,4 @@
}
return 1;
}
-}
\ No newline at end of file
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java
index 6fb97c0..a49bd8b 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java
@@ -31,16 +31,15 @@
import java.util.stream.Collectors;
import org.apache.log4j.Logger;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.Amalthea;
import org.eclipse.app4mc.amalthea.model.AmaltheaFactory;
import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
-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.Frequency;
-import org.eclipse.app4mc.amalthea.model.GraphEntryBase;
+import org.eclipse.app4mc.amalthea.model.Group;
import org.eclipse.app4mc.amalthea.model.HwDefinition;
import org.eclipse.app4mc.amalthea.model.IDiscreteValueDeviation;
import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
@@ -53,12 +52,12 @@
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.RunnableCall;
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.TaskScheduler;
import org.eclipse.app4mc.amalthea.model.Ticks;
import org.eclipse.app4mc.amalthea.model.Time;
import org.eclipse.app4mc.amalthea.model.TimeUnit;
@@ -100,14 +99,14 @@
*/
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;
+ for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+ if (geb instanceof Group) {
+ final Group cs = (Group) geb;
+ for (final ActivityGraphItem csi : cs.getItems()) {
+ if (csi instanceof RunnableCall) {
+ final RunnableCall trc = (RunnableCall) csi;
final Runnable r = trc.getRunnable();
- for (final RunnableItem ri : r.getRunnableItems()) {
+ for (final ActivityGraphItem ri : r.getRunnableItems()) {
if (ri instanceof LabelAccess) {
final LabelAccess la = (LabelAccess) ri;
ls.add(la.getData());
@@ -159,11 +158,11 @@
tsl = tsl * (tl.size() - tl.indexOf(t));
break;
case TSxUtil:
- final double util = getET(t, gpu, SharedConsts.timeType).divide(getStimInTime(t));
+ final double util = RuntimeUtil.getExecutionTimeForProcess(t, gpu, null, SharedConsts.timeType).divide(getStimInTime(t));
tsl = (long) (util * SharedConsts.timeSliceLengthPS);
break;
case TSxUtilxNbTasks:
- final double util2 = getET(t, gpu, SharedConsts.timeType).divide(getStimInTime(t));
+ final double util2 = RuntimeUtil.getExecutionTimeForProcess(t, gpu, null, SharedConsts.timeType).divide(getStimInTime(t));
tsl = (long) (util2 * tl.size() * SharedConsts.timeSliceLengthPS);
break;
default:
@@ -224,8 +223,8 @@
final TaskAllocation tsa = tsal.get(0);
Time time = ta[0];
if (null != ta[1]) {
- /*TODO handle min max*/
- /*setting time to average*/
+ /* TODO handle min max */
+ /* setting time to average */
time = time.add(ta[1]);
time.setValue(time.getValue().divide(BigInteger.valueOf(2)));
}
@@ -312,35 +311,60 @@
* @return Time execution time based on DeploymentUtil.getAssignedCoreForProcess
*/
public static Time getSimpleET(final Task t, final Amalthea amalthea) {
- final Time time = CommonUtils.getET(t, DeploymentUtil.getAssignedCoreForProcess(t, amalthea).iterator().next(), SharedConsts.timeType);
+ final ProcessingUnit pu = DeploymentUtil.getAssignedCoreForProcess(t, amalthea).size() > 0
+ ? DeploymentUtil.getAssignedCoreForProcess(t, amalthea).iterator().next()
+ : getFirstMappedPuFromTask(amalthea, t);
+ final Time time = RuntimeUtil.getExecutionTimeForProcess(t, pu, null, SharedConsts.timeType);
return time;
}
+ private static ProcessingUnit getFirstMappedPuFromTask(final Amalthea amalthea, final Task t) {
+ for (final TaskAllocation ta : amalthea.getMappingModel().getTaskAllocation()) {
+ if (ta.getTask().equals(t) && ta.getAffinity().size() > 0) {
+ return ta.getAffinity().get(0);
+ }
+ }
+ return null;
+ }
+
/**
+ * Only returns execution time until the first InterProcessTrigger event
* @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, final TimeType tt) {
+ public static Time getETPre(final Amalthea ama, final Task t, final ProcessingUnit pu, final int[] tpumap, final TimeType tt) {
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));
+ if (taskTriggersGPUTask(ama, t, tpumap)) {
+ final List<ActivityGraphItem> csil = SoftwareUtil.collectActivityGraphItems(t.getActivityGraph());
+ for (final ActivityGraphItem csi : csil) {
+ if (csi instanceof InterProcessTrigger) {
+ break;
+ }
+ else if (csi instanceof RunnableCall) {
+ final RunnableCall trc = (RunnableCall) csi;
+ for (final ExecutionNeed en : SoftwareUtil.getExecutionNeeds(trc.getRunnable(), null)) {
+ for (final Entry<String, IDiscreteValueDeviation> needs : en.getNeeds().entrySet()) {
+ ct = ct.add(RuntimeUtil.getExecutionTimeForExecutionNeedEntry(needs.getValue(), null, pu, tt));
+ }
+ }
+ for (final Ticks ticks : SoftwareUtil.getTicks(trc.getRunnable(), null)) {
+ /* considers extended */
+ ct = ct.add(getExecutionTimeForTicks(ticks, pu, tt));
+ }
+ }
}
}
- for (final Ticks ticks : SoftwareUtil.getTicks(t, null)) {
- /* considers extended */
- ct = ct.add(getExecutionTimeForTicks(ticks, pu, tt));
- }
- if (ct.getValue().toString().endsWith("999")) {
- ct.setValue(ct.getValue().add(BigInteger.ONE));
+ else {
+ Logger.getLogger(CommonUtils.class).debug("Task " + t.getName() + " does not trigger a GPU task");
+ return RuntimeUtil.getExecutionTimeForProcess(t, pu, null, tt);
}
return ct;
}
/*--------------------------------------BEGIN COPY FROM RUNTIMEUTIL------------------------------------------------*/
/**
- * FIX for APP4MC0.9.4 only
+ * FIX for APP4MC<0.9.6
* @param ticks
* @param pu
* @param tt
@@ -360,7 +384,7 @@
}
/**
- * FIX for APP4MC0.9.4 only
+ * FIX for APP4MC<0.9.6
* @param deviation
* @param pu
* @param tt
@@ -384,7 +408,7 @@
}
/**
- * FIX for APP4MC0.9.4 only
+ * FIX for APP4MC<0.9.6
* @param ticks Double
* @param frequency
* @return Time execution time for a given double value derived from the frequency
@@ -399,6 +423,7 @@
}
/*--------------------------------------END COPY FROM RUNTIMEUTIL------------------------------------------------*/
+
/**
* @param amalthea Amalthea model
* @param onlyGPUStim optional boolean parameter whether only GPU Stimuli should be accounted
@@ -407,14 +432,17 @@
public static List<PeriodicStimulus> getSortedStim(final Amalthea amalthea, final boolean... onlyGPUStim) {
final List<PeriodicStimulus> stimListSorted = new ArrayList<PeriodicStimulus>();
List<Task> tl = null;
- if (null != onlyGPUStim && onlyGPUStim[0]) {
- tl = amalthea.getMappingModel().getTaskAllocation().stream().filter(ta -> ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU))
- .map(ta -> ta.getTask()).collect(Collectors.toList());
+ if (null != onlyGPUStim && onlyGPUStim.length > 0) {
+ if (onlyGPUStim[0]) {
+ 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] && null != tl) {
+ if (null != onlyGPUStim && onlyGPUStim.length > 0 && null != tl) {
for (final Task t : tl) {
if (t.getStimuli().contains(ps) && !stimListSorted.contains(ps)) {
stimListSorted.add(ps);
@@ -461,9 +489,8 @@
}
/**
- * Logs mutliple stimuli / stimuli != (Periodic,InterProcessTrigger)
* @param t Task
- * @return PeriodicStimulus of Task t
+ * @return PeriodicStimulus of Task t or if t is triggered by interProcessStimulus, the PeriodicStimulus of the triggering task is returned
*/
public static PeriodicStimulus getStim(final Task t) {
final Logger log = Logger.getLogger(CommonUtils.class);
@@ -478,8 +505,6 @@
}
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));
}
@@ -496,10 +521,10 @@
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()) {
+ for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+ if (geb instanceof Group) {
+ final Group cs = (Group) geb;
+ for (final ActivityGraphItem csi : cs.getItems()) {
if (csi instanceof InterProcessTrigger) {
final InterProcessTrigger ipt = (InterProcessTrigger) csi;
if (ipt.getStimulus().equals(ips)) {
@@ -543,11 +568,11 @@
il.add(gpus.indexOf(pu));
}
}
- /*il = only indexes of GPUs*/
+ /* 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*/
+ /* task i is mapped tp a GPU */
gpuTasks.add(am.getSwModel().getTasks().get(i));
}
}
@@ -556,13 +581,7 @@
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 (CommonUtils.getStimInTime(t1).compareTo(CommonUtils.getStimInTime(t2)));
}
});
return tl;
@@ -572,22 +591,34 @@
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, SharedConsts.timeType);
+ final Time et = RuntimeUtil.getExecutionTimeForProcess(t, pu, null, SharedConsts.timeType);
final Time per = getStimInTime(t);
sum += et.divide(per);
}
return sum > 1 ? false : true;
}
- /** Creates a Mapping Model from an integer array */
+ /** Creates a Mapping Model from an integer array*/
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++) {
- final TaskAllocation ta = AmaltheaFactory.eINSTANCE.createTaskAllocation();
- ta.setTask(amalthea.getSwModel().getTasks().get(i));
- ta.getAffinity().add(pul.get(ia[i]));
- mm.getTaskAllocation().add(ta);
+ for (final ProcessingUnit pu : pul) {
+ final TaskScheduler ts = AmaltheaFactory.eINSTANCE.createTaskScheduler();
+ final SchedulerAllocation sa = AmaltheaFactory.eINSTANCE.createSchedulerAllocation();
+ sa.setExecutingPU(pu);
+ sa.getResponsibility().add(pu);
+ ts.setName("TS_" + pu.getName());
+ sa.setScheduler(ts);
+ for (int i = 0; i < amalthea.getSwModel().getTasks().size(); i++) {
+ if (pul.get(ia[i]).equals(pu)) {
+ final TaskAllocation ta = AmaltheaFactory.eINSTANCE.createTaskAllocation();
+ ta.setTask(amalthea.getSwModel().getTasks().get(i));
+ ta.getAffinity().add(pul.get(ia[i]));
+ ta.setScheduler(ts);
+ mm.getTaskAllocation().add(ta);
+ }
+ }
+ mm.getSchedulerAllocation().add(sa);
}
return mm;
}
@@ -683,13 +714,13 @@
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*/
+ /* 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(CommonUtils.getET(task, pu, TimeType.WCET));
+ time = time.add(RuntimeUtil.getExecutionTimeForProcess(task, pu, null, SharedConsts.timeType));
}
}
return time;
@@ -703,7 +734,7 @@
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*/
+ /* 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()));
}
@@ -743,10 +774,10 @@
*/
public static List<InterProcessTrigger> getTriggered(final Task t) {
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()) {
+ for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+ if (geb instanceof Group) {
+ final Group cs = (Group) geb;
+ for (final ActivityGraphItem csi : cs.getItems()) {
if (csi instanceof InterProcessTrigger) {
final InterProcessTrigger ipt = (InterProcessTrigger) csi;
iptl.add(ipt);
@@ -764,10 +795,10 @@
*/
public static List<Task> getTriggered(final Amalthea ama, final Task t) {
final List<Task> tl = new ArrayList<>();
- for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
- if (geb instanceof CallSequence) {
- final CallSequence cs = (CallSequence) geb;
- for (final CallSequenceItem csi : cs.getCalls()) {
+ for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+ if (geb instanceof Group) {
+ final Group cs = (Group) geb;
+ for (final ActivityGraphItem csi : cs.getItems()) {
if (csi instanceof InterProcessTrigger) {
final InterProcessTrigger ipt = (InterProcessTrigger) csi;
for (final Task tmp : ama.getSwModel().getTasks()) {
@@ -793,10 +824,10 @@
*/
public static Task getTrigger(final Amalthea amalthea, final InterProcessStimulus ips) {
for (final Task t : amalthea.getSwModel().getTasks()) {
- for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
- if (geb instanceof CallSequence) {
- final CallSequence cs = (CallSequence) geb;
- for (final CallSequenceItem csi : cs.getCalls()) {
+ for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+ if (geb instanceof Group) {
+ final Group cs = (Group) geb;
+ for (final ActivityGraphItem csi : cs.getItems()) {
if (csi instanceof InterProcessTrigger) {
final InterProcessTrigger iptc = (InterProcessTrigger) csi;
if (iptc.getStimulus().getName().equals(ips.getName())) {
@@ -819,7 +850,7 @@
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*/
+ /* 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());
@@ -838,10 +869,10 @@
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");
+ "Configuration:\n Model,Mapping,SyncOffloading,UseModelTimeSlices,TimeSliceDerication,TimeSliceLengthInPSDefault,LevelI,TimeType,CEOnlyWrittenLabels,IgnoreInfeasibility,OffsetRTA\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");
+ + SharedConsts.onlyWrittenLabelsCE + "," + SharedConsts.ignoreInfeasibility + "," + SharedConsts.offsetCPURTA + "\n");
return sbl;
}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java
index b31da13..4767e1e 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java
@@ -20,8 +20,9 @@
import java.util.Set;
import java.util.stream.Collectors;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.Amalthea;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
import org.eclipse.app4mc.amalthea.model.Label;
@@ -31,9 +32,9 @@
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.RunnableCall;
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.util.FactoryUtil;
@@ -49,16 +50,16 @@
private final int[] ia;
private final Amalthea model;
private final int[] flagArray;
- private final HashMap<Task, List<Label>[]> gpuLabels = new HashMap<Task, List<Label>[]>();
+ private final HashMap<Task, List<List<Label>>> gpuLabels = new HashMap<Task, List<List<Label>>>();
public Contention(final int[] iap, final Amalthea modelp) {
this.ia = iap;
this.model = modelp;
- if (iap == null) {
- this.flagArray = null;
- } else {
+ if(iap != null) {
this.flagArray = new int[iap.length];
+ return ;
}
+ this.flagArray = null;
}
/**
@@ -83,8 +84,9 @@
/**
* Initiallize hashmap contain GPU tasks' labels hashmap <task, List<label>> (readList = hashmap.get(task)[0];)
- * and create flagarray that have the same length with our integerArray, then loop through all the PRE_POST tasks ( via looking for InterProcessStimulus) and check whether the triggered task (GPU task) are located on GPU or not, if it is, then I will give the value of that task in flagArray equal 1. It will look like this
-
+ * and create flagarray that have the same length with our integerArray, then loop through all the PRE_POST tasks
+ ( via looking for InterProcessStimulus) and check whether the triggered task (GPU task) are located on GPU or not, i
+ f it is, then I will give the value of that task in flagArray equal 1. It will look like this
ia = { 5, 1, 5, 0, 1, 0, 2, 1, 2, 1, 6, 3, 4, 6 } - our mapping array
fa = { 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,} - the flag array
*
@@ -99,6 +101,9 @@
for (final Task t : gpuTask) {
/* shotting task => t.getName */
final List<SetEvent> shottingTaskEvent = SoftwareUtil.collectSetEvents(t, null);
+ if (shottingTaskEvent.size() < 1) {
+ continue;
+ }
final Process shottingTask = shottingTaskEvent.get(0).getProcess();
final int shotIndex = this.model.getSwModel().getTasks().indexOf(shottingTask);
final int gpuIndex = this.model.getSwModel().getTasks().indexOf(t);
@@ -109,8 +114,8 @@
/* create HashMap for GPU task that mapped to CPU start here*/
final List<Label> readLabelList = new ArrayList<Label>();
final List<Label> writeLabelList = new ArrayList<Label>();
- final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(shottingTask);
- final CallSequenceItem ipt = callList.stream().filter(a -> a instanceof InterProcessTrigger).iterator().next();
+ final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(shottingTask.getActivityGraph());
+ final ActivityGraphItem ipt = callList.stream().filter(a -> a instanceof InterProcessTrigger).iterator().next();
/*
* get the position of InterProcessTrigger within task taking
* readLabel and write labels from pre and post processing (
@@ -121,8 +126,8 @@
for (int i = 0; i < callList.size(); i++) {
Runnable thisRunnable = null;
/* Pre-processing Runnable */
- if ((i < indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
- thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
+ if ((i < indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+ thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
for (final LabelAccess la : thisLAList) {
if (la.getAccess().equals(LabelAccessEnum.READ)) {
@@ -131,8 +136,8 @@
}
}
/* Post-processing Runnable */
- else if ((i > indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
- thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
+ else if ((i > indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+ thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
for (final LabelAccess la : thisLAList) {
if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
@@ -142,10 +147,9 @@
}
}
- @SuppressWarnings("unchecked")
- final List<Label>[] aryofLabelList = new ArrayList[2];
- aryofLabelList[0] = readLabelList;
- aryofLabelList[1] = writeLabelList;
+ final List<List<Label>> aryofLabelList = new ArrayList<List<Label>>();
+ aryofLabelList.add(readLabelList);
+ aryofLabelList.add(writeLabelList);
this.gpuLabels.put(t, aryofLabelList);
// HashMap created with <Task, ArrayofLabelList>
}
@@ -161,7 +165,6 @@
public Time contentionForTask(final Task task) {
/* Initialize hashmap */
setUpFlagArrayAndHashMap(this.ia);
-
final Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
/**
* Constant and variable init, change those constant for different model number
@@ -226,7 +229,7 @@
final Set<Runnable> wL = SoftwareUtil.getWriterSetOfLabel(l, null);
for (final Runnable r : wL) {
- final List<Process> lT = SoftwareUtil.getProcesses(r, null);
+ final List<Process> lT = SoftwareUtil.getCallingProcesses(r, null);
for (final Process lTT : lT) {
/* get related task through checking which runnable are accessing the same label
* put the task that contain those runnable into b2 and the core of that task in c2
@@ -255,7 +258,7 @@
final Set<Runnable> rL = SoftwareUtil.getReadersSetOfLabel(l, null);
for (final Runnable r : rL) {
- final List<Process> lT1 = SoftwareUtil.getProcesses(r, null);
+ final List<Process> lT1 = SoftwareUtil.getCallingProcesses(r, null);
for (final Process lTT1 : lT1) {
/* get related task through checking which runnable are accessing the same label
* put the task that contain those runnable into b2 and the core of that task in c2
@@ -365,8 +368,8 @@
final int shotIndex = this.model.getSwModel().getTasks().indexOf(shottingTask);
if (this.flagArray[shotIndex] == 1) {
- final List<Label> readList = this.gpuLabels.get(task)[0];
- final List<Label> writeList = this.gpuLabels.get(task)[1];
+ final List<Label> readList = this.gpuLabels.get(task).get(0);
+ final List<Label> writeList = this.gpuLabels.get(task).get(1);
for (final Label l : readList) {
sumCycle += (long) Math.ceil(l.getSize().getNumberBytes() / 64.0);
@@ -491,7 +494,7 @@
final Set<Runnable> wL = SoftwareUtil.getWriterSetOfLabel(l, null);
for (final Runnable r : wL) {
- final List<Process> lT = SoftwareUtil.getProcesses(r, null);
+ final List<Process> lT = SoftwareUtil.getCallingProcesses(r, null);
for (final Process lTT : lT) {
for (int taskIndex = 0; taskIndex < this.ia.length; taskIndex++) {
@@ -521,7 +524,7 @@
}
final Set<Runnable> rL = SoftwareUtil.getReadersSetOfLabel(l, null);
for (final Runnable r : rL) {
- final List<Process> lT1 = SoftwareUtil.getProcesses(r, null);
+ final List<Process> lT1 = SoftwareUtil.getCallingProcesses(r, null);
for (final Process lTT1 : lT1) {
for (int taskIndex = 0; taskIndex < this.ia.length; taskIndex++) {
final ProcessingUnit pup = pul.get(this.ia[taskIndex]);
@@ -645,4 +648,4 @@
return contentionTime;
}
-}
\ No newline at end of file
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
index 055ecd8..e693c30 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
@@ -1,686 +1,1172 @@
-/*******************************************************************************
- * 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.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
-import org.eclipse.app4mc.amalthea.model.Event;
-import org.eclipse.app4mc.amalthea.model.EventChain;
-import org.eclipse.app4mc.amalthea.model.EventChainContainer;
-import org.eclipse.app4mc.amalthea.model.EventChainItem;
-import org.eclipse.app4mc.amalthea.model.Label;
-import org.eclipse.app4mc.amalthea.model.ProcessEvent;
-import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
-import org.eclipse.app4mc.amalthea.model.Task;
-import org.eclipse.app4mc.amalthea.model.Time;
-import org.eclipse.app4mc.amalthea.model.TimeUnit;
-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.app4mc.gsoc_rta.SharedConsts.ComParadigm;
-import org.eclipse.emf.common.util.EList;
-
-/**
- * Date: August 21-2019
- * @author Junhyung Ki
- * @version 1.0
- * This class is to analyze End-to-End latency with the help of CPURta class.
- */
-public class E2ELatency {
- public final File inputFile = new File("model-input/WATERS19_release/ChallengeModel_release.amxmi");
- public CPURta cpurta = new CPURta();
- public static final int[] defaultIAMapping = new int[] { 4, 1, 1, 3, 4, 0, 3, 3, 3, 0, 6, 2, 5, 6 };
- public static void main(String[] args) {
- org.apache.log4j.BasicConfigurator.configure();
- Logger.getRootLogger().setLevel(Level.ERROR);
- final E2ELatency ecl = new E2ELatency();
- ecl.run();
- }
-
- public void run() {
- final Logger log = Logger.getLogger(E2ELatency.class);
- this.setCPURta(this.cpurta);
- if (this.cpurta.getModel() == null) {
- log.debug("Model is empty. Please check the model path.");
- return ;
- }
- final EList<EventChain> ecList = this.cpurta.getModel().getConstraintsModel().getEventChains();
- for (int i = 0; i < ecList.size(); i++) {
- log.debug(" ----- " + "Chain " + (i+1) + " ----- ");
- log.debug("Best-case Task-Chain Reaction(Direct): " + this.getTCReactionBC(ecList.get(i), ComParadigm.DIRECT, this.cpurta));
- log.debug("Worst-case Task-Chain Reaction(Direct): " + this.getTCReactionWC(ecList.get(i), ComParadigm.DIRECT, this.cpurta));
- log.debug("Best-case Task-Chain Reaction(Implicit): " + this.getTCReactionBC(ecList.get(i), ComParadigm.IMPLICIT, this.cpurta));
- log.debug("Worst-case Task-Chain Reaction(Implicit): " + this.getTCReactionWC(ecList.get(i), ComParadigm.IMPLICIT, this.cpurta));
- log.debug("Best-case Task-Chain Reaction(LET): " + this.getLetReactionBC(ecList.get(i), this.cpurta));
- log.debug("Worst-case Task-Chain Reaction(LET): " + this.getLetReactionWC(ecList.get(i), this.cpurta));
- log.debug("Worst-case Task-Chain Age(Direct): " + this.getTaskChainAge(ecList.get(i), TimeType.WCET, ComParadigm.DIRECT, this.cpurta));
- log.debug("Best-case Task-Chain Age(Direct): " + this.getTaskChainAge(ecList.get(i), TimeType.BCET, ComParadigm.DIRECT, this.cpurta));
- log.debug("Worst-case Task-Chain Age(Implicit): " + this.getTaskChainAge(ecList.get(i), TimeType.WCET, ComParadigm.IMPLICIT, this.cpurta));
- log.debug("Best-case Task-Chain Age(Implicit): " + this.getTaskChainAge(ecList.get(i), TimeType.BCET, ComParadigm.IMPLICIT, this.cpurta));
- log.debug("Worst-case Early Reaction(Direct): " + this.getEarlyReaction(ecList.get(i), TimeType.WCET, ComParadigm.DIRECT, this.cpurta));
- log.debug("Best-case Early Reaction(Direct): " + this.getEarlyReaction(ecList.get(i), TimeType.BCET, ComParadigm.DIRECT, this.cpurta));
- log.debug("Worst-case Early Reaction(Implicit): " + this.getEarlyReaction(ecList.get(i), TimeType.WCET, ComParadigm.IMPLICIT, this.cpurta));
- log.debug("Best-case Early Reaction(Implicit): " + this.getEarlyReaction(ecList.get(i), TimeType.BCET, ComParadigm.IMPLICIT, this.cpurta));
- log.debug("\n");
- }
- log.debug("\n################################################################################################################\n");
- for (int i = 0; i < ecList.size(); i++) {
- log.debug(" ----- " + "Chain " + (i+1) + " ----- ");
- for (int j = 0; j < this.cpurta.getModel().getSwModel().getLabels().size(); j++) {
- final Label label = this.cpurta.getModel().getSwModel().getLabels().get(j);
- log.debug("***** " + label.getName() + " *****");
- log.debug("Worst-case Data Age(Direct): " + this.getDataAge(label, ecList.get(i), TimeType.WCET, ComParadigm.DIRECT, this.cpurta));
- log.debug("Best-case Data Age(Direct): " + this.getDataAge(label, ecList.get(i), TimeType.BCET, ComParadigm.DIRECT, this.cpurta));
- log.debug("Worst-case Data Age(Implicit): " + this.getDataAge(label, ecList.get(i), TimeType.WCET, ComParadigm.IMPLICIT, this.cpurta));
- log.debug("Best-case Data Age(Implicit): " + this.getDataAge(label, ecList.get(i), TimeType.BCET, ComParadigm.IMPLICIT, this.cpurta) + "\n");
- }
- log.debug("\n");
- }
- }
-
- /**
- * Set CPURta class
- * @param cpurta the instance of CPURta class
- */
- public void setCPURta(final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- cpurta.setModel(AmaltheaLoader.loadFromFile(this.inputFile));
- if (cpurta.getModel() == null) {
- log.debug("Model is empty. Please check the model path.");
- return ;
- }
- cpurta.setTRT(cpurta.getDefaultTRT(cpurta.getModel()));
- cpurta.setIA(defaultIAMapping);
- cpurta.setPUl(CommonUtils.getPUs(cpurta.getModel()));
- cpurta.setContention(cpurta.getIA(), cpurta.getModel());
- }
-
- /**
- * Check the readiness of the observed class instance
- * @param cpurta the instance of CPURta class
- * @return
- * boolean value that indicates whether cpurta instance is ready
- */
- private boolean isTheRTAClassReady(final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- if (cpurta.getModel() == null) {
- log.debug("Model Setting needs to be done for cpurta!");
- return false;
- } else if (cpurta.getTRT() == null) {
- log.debug("TRT Setting needs to be done for cpurta!");
- return false;
- } else if (cpurta.getIA() == null) {
- log.debug("IA Setting needs to be done for cpurta!");
- return false;
- } else if (cpurta.getPUl().size() == 0) {
- log.debug("PUl Setting needs to be done for cpurta!");
- return false;
- } else if (cpurta.getCT() == null) {
- log.debug("CT Setting needs to be done for cpurta!");
- return false;
- }
- return true;
- }
-
- /**
- * Reaction: The time between one of the chain's first task instances to the earliest one of the chain's last task instances
- * which are propagated from the initial one. (which we can also call the best-case task-chain age latency)
- * the best-case E2E Chain Reaction(Direct or Implicit) = Sum of all entities' BCRT
- * @param ec the observed event chain
- * @param paradigm communication paradigm (DIRECT, IMPLICIT)
- * @param cpurta the instance of CPURta class
- * @return
- * the best-case E2E Chain Reaction(Direct or Implicit)
- */
- public Time getTCReactionBC(final EventChain ec, final ComParadigm paradigm, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- Time e2eRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isTheRTAClassReady(cpurta)) {
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- for (int i = 0; i < taskChain.size(); i++) {
- final Task task = taskChain.get(i);
- final ProcessingUnit pu = getPU(task, cpurta);
- final List<Task> taskList = getSortedTaskList(task, pu, cpurta);
- Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isMappedToCPU(task, cpurta)) {
- if (paradigm.equals(ComParadigm.DIRECT)) {
- bcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- bcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
- } else {
- log.error("'COM_PARADIGM == null' does not work.");
- return null;
- }
- } else {
- bcrt = cpurta.getTRT().get(task);
- }
- /* The task is not schedulable */
- final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));
- if (AmaltheaServices.convertToPicoSeconds(bcrt).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- e2eRctImplicit = e2eRctImplicit.add(bcrt);
- }
- return e2eRctImplicit;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * The worst case task chain reaction latency for Direct or Implicit Communication
- * @param ec the observed event chain
- * @param paradigm communication paradigm (DIRECT, IMPLICIT)
- * @param cpurta the instance of CPURta class
- * @return
- * the worst-case E2E Chain Reaction(Direct or Implicit)
- */
- public Time getTCReactionWC(final EventChain ec, final ComParadigm paradigm, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- Time e2eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isTheRTAClassReady(cpurta)) {
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- for (int i = 0; i < taskChain.size() - 1; i++) {
- final Task task = taskChain.get(i);
- final Time period = CommonUtils.getStimInTime(task);
- e2eRctWC = e2eRctWC.add(period.multiply(2));
- }
- final Task task = taskChain.get(taskChain.size() - 1);
- Time wcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isMappedToCPU(task, cpurta)) {
- final ProcessingUnit pu = getPU(task, cpurta);
- final List<Task> taskList = getSortedTaskList(task, pu, cpurta);
- if (paradigm.equals(ComParadigm.DIRECT)) {
- wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- wcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.WCET, pu, cpurta);
- } else {
- log.error("'COM_PARADIGM == null' does not work.");
- return null;
- }
- } else {
- wcrt = cpurta.getTRT().get(task);
- }
- /* The task is not schedulable */
- final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));
- if (AmaltheaServices.convertToPicoSeconds(wcrt).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- e2eRctWC = e2eRctWC.add(wcrt);
- return e2eRctWC;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * Reaction: The time between one of the chain's first task instances to the earliest one of the chain's last task instances
- * which are propagated from the initial one. (which we can also call the best-case task-chain age latency)
- * the best-case E2E Chain Reaction(LET) = Sum of all entities' periods
- * @param ec the observed event chain
- * @param cpurta the instance of CPURta class
- * @return
- * the best-case E2E Chain Reaction(LET)
- */
- public Time getLetReactionBC(final EventChain ec, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- Time e2eRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isTheRTAClassReady(cpurta)) {
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- for (int i = 0; i < taskChain.size(); i++) {
- final Task task = taskChain.get(i);
- e2eRctLET = e2eRctLET.add(CommonUtils.getStimInTime(task));
- }
- return e2eRctLET;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * The worst case task chain reaction latency for LET Communication
- * @param ec the observed event chain
- * @param cpurta the instance of CPURta class
- * @return
- * the worst-case E2E Chain Reaction(LET)
- */
- public Time getLetReactionWC(final EventChain ec, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- Time e2eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isTheRTAClassReady(cpurta)) {
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- final Task task0 = taskChain.get(0);
- final Time period0 = CommonUtils.getStimInTime(task0);
- e2eRctWC = e2eRctWC.add(period0);
- for (int i = 1; i < taskChain.size(); i++) {
- final Task task = taskChain.get(i);
- final Time period = CommonUtils.getStimInTime(task);
- e2eRctWC = e2eRctWC.add(period.multiply(2));
- }
- return e2eRctWC;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * A task chain age latency equals the chain's last (response) task age latency
- * worst-case: period - bcrt + wcrt
- * best-case: period - wcrt + bcrt
- * @param ec the observed event chain
- * @param executionCase WCET / BCET
- * @param paradigm communication paradigm (DIRECT, IMPLICIT)
- * @param cpurta the instance of CPURta class
- * @return
- * the worst-case E2E Task-Chain Age
- */
- public Time getTaskChainAge(final EventChain ec, final TimeType executionCase, final ComParadigm paradigm, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- Time e2eTCAgeWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isTheRTAClassReady(cpurta)) {
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- final Task task = taskChain.get(taskChain.size()-1);
- if (isMappedToCPU(task, cpurta)) {
- final Time period = CommonUtils.getStimInTime(task);
- final ProcessingUnit pu = getPU(task, cpurta);
- final List<Task> taskList = getSortedTaskList(task, pu, cpurta);
- Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time wcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (paradigm.equals(ComParadigm.DIRECT)) {
- bcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
- wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- bcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
- wcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.WCET, pu, cpurta);
- } else {
- log.error("'COM_PARADIGM == null' does not work.");
- return null;
- }
- /* The task is not schedulable */
- final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));
- if (AmaltheaServices.convertToPicoSeconds(bcrt).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- } else if (AmaltheaServices.convertToPicoSeconds(wcrt).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- if (executionCase.equals(TimeType.WCET)) {
- e2eTCAgeWC = period.subtract(bcrt).add(wcrt);
- } else if (executionCase.equals(TimeType.BCET)) {
- e2eTCAgeWC = period.subtract(wcrt).add(bcrt);
- } else {
- log.error("Only WCET or BCET is allowed!");
- return null;
- }
- } else {
- // TODO: if the observed task is mapped to GPU, then how should we calculate wcrt, bcrt?
- log.debug("GPU Task, how should we calculate wcrt, bcrt?");
- }
- return e2eTCAgeWC;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * The method is to be used for calculating 'reaction update'.
- * @param ec the observed event chain
- * @param executionCase WCET / BCET
- * @param paradigm communication paradigm (DIRECT, IMPLICIT)
- * @param cpurta the instance of CPURta class
- * @return
- * the reaction latency value of the observed event chain
- */
- public Time getEarlyReaction(final EventChain ec, final TimeType executionCase, final ComParadigm paradigm, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- Time e2eEarlyRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isTheRTAClassReady(cpurta)) {
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- final Task task0 = taskChain.get(0);
- Time rt0 = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isMappedToCPU(task0, cpurta)) {
- final ProcessingUnit pu = getPU(task0, cpurta);
- final List<Task> taskList = getSortedTaskList(task0, pu, cpurta);
- if (paradigm.equals(ComParadigm.DIRECT)) {
- rt0 = cpurta.preciseTestCPURT(task0, taskList, executionCase, pu);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- rt0 = cpurta.implicitPreciseTest(task0, taskList, executionCase, pu, cpurta);
- } else {
- log.error("'COM_PARADIGM == null' does not work.");
- return null;
- }
- } else {
- rt0 = cpurta.getTRT().get(task0);
- }
- /* The task is not schedulable */
- final BigInteger biPeriod0 = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task0));
- if (AmaltheaServices.convertToPicoSeconds(rt0).compareTo(biPeriod0) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- e2eEarlyRct = e2eEarlyRct.add(rt0);
- Time epsilon = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- for (int i = 0; i < taskChain.size() - 1; i++) {
- final Time nextPeriod = CommonUtils.getStimInTime(taskChain.get(i + 1));
- /* SUM (Sigma Starts) */
- final Time period = CommonUtils.getStimInTime(taskChain.get(i));
- final Task currentTask = taskChain.get(i);
- Time rtA = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isMappedToCPU(currentTask, cpurta)) {
- final ProcessingUnit puA = getPU(currentTask, cpurta);
- final List<Task> taskListA = getSortedTaskList(currentTask, puA, cpurta);
- /* NOTE: Sometimes rtA, rtB are BigInteger.valueOf(Long.MAX_VALUE) if it is executed with the implicit communication paradigm */
- /* In that case, the task is not schedulable, so the method should return 0 ps, otherwise the result is not correct and
- * would likely be negative (subtract the max BigIntegerValue would be obviously negative in most cases) */
- if (paradigm.equals(ComParadigm.DIRECT)) {
- rtA = cpurta.preciseTestCPURT(currentTask, taskListA, executionCase, puA);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- rtA = cpurta.implicitPreciseTest(currentTask, taskListA, executionCase, puA, cpurta);
- }
- } else {
- rtA = cpurta.getTRT().get(currentTask);
- }
- /* The task is not schedulable */
- final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(period);
- if (AmaltheaServices.convertToPicoSeconds(rtA).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- final Time currentEpsilon = (((period.multiply(2)).subtract(rtA)).subtract(nextPeriod)).subtract(epsilon);
- epsilon = currentEpsilon;
- final Task nextTask = taskChain.get(i + 1);
- Time rtB = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (isMappedToCPU(nextTask, cpurta)) {
- final ProcessingUnit puB = getPU(nextTask, cpurta);
- final List<Task> taskListB = getSortedTaskList(nextTask, puB, cpurta);
- if (paradigm.equals(ComParadigm.DIRECT)) {
- rtB = cpurta.preciseTestCPURT(nextTask, taskListB, executionCase, puB);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- rtB = cpurta.implicitPreciseTest(nextTask, taskListB, executionCase, puB, cpurta);
- }
- } else {
- rtB = cpurta.getTRT().get(nextTask);
- }
- /* The task is not schedulable */
- final BigInteger biPeriodB = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(nextTask));
- if (AmaltheaServices.convertToPicoSeconds(rtB).compareTo(biPeriodB) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- if (nextPeriod.compareTo(currentEpsilon.add(rtB)) < 0) {
- e2eEarlyRct = e2eEarlyRct.add(nextPeriod.multiply(2));
- } else {
- e2eEarlyRct = e2eEarlyRct.add(nextPeriod.add(currentEpsilon.add(rtB)));
- }
- if (e2eEarlyRct.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) < 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- }
- return e2eEarlyRct;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * the longest time some data version persists in memory.
- * worst-case: min (worst-case age latencies of the tasks that contain the observed label)
- * best-case: min (best-case age latencies of the tasks that contain the observed label)
- * @param label the observed label (data)
- * @param ec the observed event-chain
- * @param executionCase WCET / BCET
- * @param paradigm communication paradigm (DIRECT, IMPLICIT)
- * @param cpurta the instance of CPURta class
- * @return
- * the data age latency (wc or bc) of the given label
- * If any of tasks in the chain does not contain the observed label, the method shall return null.
- */
- public Time getDataAge(final Label label, final EventChain ec, final TimeType executionCase, final ComParadigm paradigm, final CPURta cpurta) {
- final Logger log = Logger.getLogger(E2ELatency.class);
- if (isTheRTAClassReady(cpurta)) {
- final List<Time> dataAgeList = new ArrayList<Time>();
- final List<Task> taskChain = getECTaskList(ec);
- if (taskChain.size() == 0) {
- log.error("This task chain is empty.");
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- for (int i = 0; i < taskChain.size(); i++) {
- if (isMappedToCPU(taskChain.get(i), cpurta)) {
- final Task task = taskChain.get(i);
- final Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
- if(labelSet.contains(label)) {
- Time dataAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- final ProcessingUnit pu = getPU(task, cpurta);
- final List<Task> taskList = getSortedTaskList(task, pu, cpurta);
- final Time period = CommonUtils.getStimInTime(task);
- Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time wcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (paradigm.equals(ComParadigm.DIRECT)) {
- bcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
- wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
- } else if (paradigm.equals(ComParadigm.IMPLICIT)) {
- bcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
- wcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.WCET, pu, cpurta);
- } else {
- log.error("'COM_PARADIGM == null' does not work.");
- return null;
- }
- /* The task is not schedulable */
- final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));
- if (AmaltheaServices.convertToPicoSeconds(bcrt).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- } else if (AmaltheaServices.convertToPicoSeconds(wcrt).compareTo(biPeriod) > 0) {
- return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- }
- if (executionCase.equals(TimeType.WCET)) {
- dataAge = period.subtract(bcrt).add(wcrt);
- } else if (executionCase.equals(TimeType.BCET)) {
- dataAge = period.subtract(wcrt).add(bcrt);
- } else {
- log.error("Only WCET or BCET is allowed!");
- }
- dataAgeList.add(dataAge);
- }
- }
- }
- if (dataAgeList.size() != 0) {
- Collections.sort(dataAgeList, new TimeComp());
- return dataAgeList.get(0);
- }
- return null;
- }
- log.error("cpurta instance is not ready!");
- return null;
- }
-
- /**
- * Get an Event-Chain Entity List (Task-based)
- * @param ec the observed event chain
- * @return
- * the corresponding EC task list
- */
- public List<Task> getECTaskList(final EventChain ec) {
- final List<Task> chain = new ArrayList<Task>();
- for (int i = 0; i < ec.getSegments().size(); i++) {
- final EventChainItem eci = ec.getSegments().get(i);
- if (eci instanceof EventChainContainer) {
- final EventChainContainer ecc = (EventChainContainer) eci;
- final Event stiEvent = ecc.getEventChain().getStimulus();
- if (stiEvent instanceof ProcessEvent) {
- final Task stiTask = (Task)((ProcessEvent) stiEvent).getEntity();
- chain.add(stiTask);
- }
- if (i == ec.getSegments().size() - 1) {
- final Event resEvent = ecc.getEventChain().getResponse();
- if (resEvent instanceof ProcessEvent) {
- final Task resTask = (Task)((ProcessEvent) resEvent).getEntity();
- chain.add(resTask);
- }
- break;
- }
- }
- }
- return chain;
- }
-
- /**
- * get the processing unit that the observed task is mapped to
- * @param task the observed task
- * @param cpurta the instance of CPURta class
- * @return
- * pu
- */
- private ProcessingUnit getPU(final Task task, final CPURta cpurta) {
- final int tindex = cpurta.getModel().getSwModel().getTasks().indexOf(task);
- final int puindex = cpurta.getIA()[tindex];
- final ProcessingUnit pu = cpurta.getPUl().get(puindex);
- return pu;
- }
-
- /**
- * get the sorted task listed based on the given integer array mapping
- * @param task the observed task
- * @param pu ProcessingUnit that would compute the given method
- * @param cpurta the instance of CPURta class
- * @return
- * sortedTaskList
- */
- private List<Task> getSortedTaskList(final Task task, final ProcessingUnit pu, final CPURta cpurta) {
- final int puIndex = cpurta.getPUl().indexOf(pu);
- /* 2. get all tasks mapped to this CPU */
- final List<Task> puTaskList = new ArrayList<Task>();
- for (int i = 0; i < cpurta.getIA().length; i++) {
- if (cpurta.getIA()[i] == puIndex) {
- puTaskList.add(cpurta.getModel().getSwModel().getTasks().get(i));
- }
- }
- final List<Task> sortedTaskList = taskSorting(puTaskList);
- return sortedTaskList;
- }
-
- /**
- * 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 TimeComp());
- /* 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;
- }
-
- /**
- * To check whether or not the observed task is mapped to CPU (according to the integer array)
- * @param task the observed task
- * @param cpurta the instance of CPURta class that contains model & mapping IA info
- * @return
- * boolean value that says whether or not it is mapped to CPU
- */
- private static boolean isMappedToCPU (final Task task, final CPURta cpurta) {
- /* The observed task is a GPU task */
- if (cpurta.getGpuTaskList().contains(task)) {
- final int index = cpurta.getModel().getSwModel().getTasks().indexOf(task);
- final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
- final int[] ia = cpurta.getIA();
- /* when the observed GPU task is mapped to GPU */
- if (ia[index] > cpuThreshold) {
- return false;
- }
- }
- /* when the observed task(CPU or GPU) is mapped to CPU */
- return true;
- }
-}
-
-/**
- * @Date: August 21-2019
- * @version 1.0
- * This inner class is used for sorting a Time type list.
- * If the Time of a is smaller than that of b, it returns -1.
- * If the Time of a is bigger than that of b, it returns 1.
- */
-class TimeComp implements Comparator<Time> {
- @Override
- public int compare(final Time a, final Time b) {
- if (a.compareTo(b) < 0) {
- return -1;
- }
- return 1;
- }
-}
-
-/**
- * @Date: August 21-2019
- * @version 1.0
- * This inner class is used for the method "letCom" to help compare between different values of propagation, age, reaction
- * in basicPaths (which is bigger)
- * If the BigDecimal of a is smaller than that of b, it returns -1.
- * If the BigDecimal of a is bigger than that of b, it returns 1.
- */
-class BigDecimalComp implements Comparator<BigDecimal> {
- @Override
- public int compare(final BigDecimal a, final BigDecimal b) {
- if (a.compareTo(b) < 0) {
- return -1;
- }
- return 1;
- }
+/*******************************************************************************
+ * 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.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts.SINGLE_CASE;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
+import org.eclipse.app4mc.amalthea.model.Amalthea;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
+import org.eclipse.app4mc.amalthea.model.Event;
+import org.eclipse.app4mc.amalthea.model.EventChain;
+import org.eclipse.app4mc.amalthea.model.EventChainContainer;
+import org.eclipse.app4mc.amalthea.model.EventChainItem;
+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.ProcessEvent;
+import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.TimeUnit;
+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;
+
+//TODO javadoc!
+public class E2ELatency {
+ final Logger log = Logger.getLogger(E2ELatency.class);
+ public CPURta cpurta = null;
+ public static StringBuffer sb = new StringBuffer();
+
+ public static void main(final String[] args) {
+ //TODO replace this eecutable function with unit test
+ org.apache.log4j.BasicConfigurator.configure();
+ Logger.getRootLogger().setLevel(Level.ERROR);
+ final E2ELatency ecl = new E2ELatency();
+ //ecl.runTest();
+ //ecl.runSingle();
+ ecl.runMulti();
+ }
+
+ //TODO implement a separate unit test
+ public void runTest() {
+ final boolean isSingle = false;
+ this.setCPURta(isSingle);
+ if (this.cpurta.getModel() == null) {
+ log.debug("Model is empty. Please check the model path.");
+ return ;
+ }
+ System.out.println("---TEST---");
+ final EList<Task> allTasks = this.cpurta.getModel().getSwModel().getTasks();
+ final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+ for (int i = 0; i < allTasks.size(); i++) {
+ final Task task = allTasks.get(i);
+ final ProcessingUnit pu = this.cpurta.getPU(allTasks.get(i), this.cpurta);
+ System.out.println(task.getName() + "(PU): " + pu.getName());
+ final Time adjustedP = CommonUtils.getStimInTime(task);
+ final BigInteger picoP = AmaltheaServices.convertToPicoSeconds(adjustedP);
+ final Time period = FactoryUtil.createTime(picoP, TimeUnit.PS);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time bcet = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, this.cpurta);
+ final Time wcet = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.WCET, this.cpurta);
+ final Time bcrt = this.cpurta.bestCaseCPURT(task, taskList, pu);
+ final Time wcrt = this.cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+ if (isSingle) {
+ System.out.println(task.getName() + "(BCET): " + bcet.adjustUnit());
+ System.out.println(task.getName() + "(WCET): " + wcet.adjustUnit());
+ System.out.println(task.getName() + "(Period): " + period.adjustUnit());
+ System.out.println(task.getName() + "(BCRT): " + bcrt.adjustUnit());
+ System.out.println(task.getName() + "(WCRT): " + wcrt.adjustUnit());
+ System.out.println();
+ } else {
+ System.out.println(task.getName() + "(BCET): " + bcet);
+ System.out.println(task.getName() + "(WCET): " + wcet);
+ System.out.println(task.getName() + "(Period): " + period);
+ System.out.println(task.getName() + "(BCRT): " + bcrt);
+ System.out.println(task.getName() + "(WCRT): " + wcrt);
+ System.out.println();
+ }
+ }
+ }
+
+ public void runSingle() {
+ this.setCPURta(true);
+ if (this.cpurta.getModel() == null) {
+ log.debug("Model is empty. Please check the model path.");
+ return ;
+ }
+ final EList<EventChain> ecList = this.cpurta.getModel().getConstraintsModel().getEventChains();
+ final List<Task> taskChain = getECTaskList(ecList.get(0));
+ final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+ .distinct().collect(Collectors.toList());
+ if (puList.size() > 1) {
+ log.error("SingleCore Reaction can not be calculated, "
+ + "The tasks are mapped to more than one processing unit.");
+ return ;
+ }
+ System.out.println("--- TEST ---");
+ for (int i = 0; i < ecList.size(); i++) {
+ this.testSingleCoreReaction(ecList.get(i), cpurta);
+ System.out.println();
+ }
+ }
+
+ public void runMulti() {
+ this.setCPURta(false);
+ if (this.cpurta.getModel() == null) {
+ log.debug("Model is empty. Please check the model path.");
+ return ;
+ }
+ final EList<EventChain> ecList = this.cpurta.getModel().getConstraintsModel().getEventChains();
+ for (int i = 0; i < ecList.size(); i++) {
+ final EventChain chain = ecList.get(i);
+ System.out.println();
+ System.out.println(" ----- " + chain.getName() + " ----- ");
+ System.out.println();
+ System.out.println("Best-case Task-Chain Reaction(Implicit): " + this.getBCReactionImplicit(chain, cpurta));
+ System.out.println("Best-case Task-Chain Reaction(LET): " + this.getBCReactionLET(chain, cpurta));
+ System.out.println();
+ System.out.println("Worst-case Task-Chain Reaction(Implicit): " + this.getWCReactionImplicit(chain, cpurta));
+ System.out.println("Worst-case Task-Chain Reaction(LET): " + this.getWCReactionLET(chain, cpurta));
+ System.out.println();
+ System.out.println("Best-case Initial Task-Chain Reaction(Implicit): " + this.getBCInitialRctImplicit(chain, cpurta));
+ System.out.println("Best-case Initial Task-Chain Reaction(LET): " + this.getBCInitialRctLET(chain, cpurta));
+ System.out.println();
+ System.out.println("Worst-case Initial Task-Chain Reaction(Implicit): " + this.getWCInitialRctImplicit(chain, cpurta));
+ System.out.println("Worst-case Initial Task-Chain Reaction(LET): " + this.getWCInitialRctLET(chain, cpurta));
+ System.out.println();
+ System.out.println("Best-case Task-Chain Age(Implicit): " + this.getBCAgeImplicit(chain, cpurta));
+ System.out.println("Best-case Task-Chain Age(LET): " + this.getBCAgeLET(chain, cpurta));
+ System.out.println();
+ System.out.println("Worst-case Task-Chain Age(Implicit): " + this.getWCAgeImplicit(chain, cpurta));
+ System.out.println("WC-BC Reaction Subtraction(Implicit): " + this.getWCBCSubAgeImplicit(chain, cpurta));
+ System.out.println("Worst-case Task-Chain Age(LET): " + this.getWCAgeLET(chain, cpurta));
+ System.out.println("WC-BC Reaction Subtraction(LET): " + this.getWCBCSubAgeLET(chain, cpurta));
+ System.out.println();
+ System.out.println("**************************************************************");
+ System.out.println();
+ }
+ }
+
+ /**
+ * Set CPURta class
+ * @param isSingle true - to analyze a single-core system
+ * false - to analyze a multi-core system
+ */
+ public void setCPURta(final boolean isSingle) {
+ if (isSingle) {
+ final Amalthea model = AmaltheaLoader.loadFromFile(new File(SharedConsts.ECRTS_SINGLE));
+ this.cpurta = new CPURta(model, (new CPURta(true)).getDefaultTRT(model), singleIAMapping, CommonUtils.getPUs(model));
+ } else {
+ final Amalthea model = AmaltheaLoader.loadFromFile(new File(SharedConsts.ECRTS_TCS));
+ this.cpurta = new CPURta(model, (new CPURta(true)).getDefaultTRT(model), defaultIAMapping, CommonUtils.getPUs(model));
+ }
+ if (this.cpurta.getModel() == null) {
+ log.debug("Model is empty. Please check the model path.");
+ return ;
+ }
+ this.cpurta.setContention(this.cpurta.getIA(), this.cpurta.getModel());
+ }
+
+ /**
+ * Check the readiness of the observed class instance
+ * @param cpurta the instance of CPURtaIA class
+ * @return
+ * boolean value that indicates whether cpurta instance is ready
+ */
+ protected boolean isTheRTAClassReady(final CPURta cpurta) {
+ if (cpurta.getModel() == null) {
+ log.debug("Model Setting needs to be done for cpurta!");
+ return false;
+ } else if (cpurta.getTRT() == null) {
+ log.debug("TRT Setting needs to be done for cpurta!");
+ return false;
+ } else if (cpurta.getIA() == null) {
+ log.debug("IA Setting needs to be done for cpurta!");
+ return false;
+ } else if (cpurta.getPUl().size() == 0) {
+ log.debug("PUl Setting needs to be done for cpurta!");
+ return false;
+ } else if (cpurta.getCT() == null) {
+ log.debug("CT Setting needs to be done for cpurta!");
+ return false;
+ }
+ return true;
+ }
+
+ /**************************************************************************************/
+
+ public void testSingleCoreReaction(final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ System.out.println("< " + ec.getName() + " >");
+ final List<Task> taskChain = getECTaskList(ec);
+ if (taskChain.size() == 0) {
+ log.error("This task chain is empty.");
+ return ;
+ }
+ final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+ .distinct().collect(Collectors.toList());
+ if (puList.size() > 1) {
+ log.error("SingleCore Reaction can not be calculated, "
+ + "The tasks are mapped to more than one processing unit.");
+ return ;
+ }
+ final ProcessingUnit pu = puList.get(0);
+ final Task task_0 = taskChain.get(0);
+ final List<Task> taskList = cpurta.getSortedTaskList(task_0, pu, cpurta);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ final Time hyper = this.getHyperPeriod(taskList);
+ final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
+ final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+ final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
+ for (int i = 0; i < chainsToCheck; i++) {
+ System.out.println("* " + i + "-th instance: ");
+ Time initRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time wcRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ initRct = this.getSingleCoreInitialRct_(i, ec, cpurta);
+ if (initRct.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+ System.out.println("ERROR: This is not a vaild chain!");
+ } else {
+ wcRct = this.getSingleCoreWCRct_(i, ec, cpurta);
+ if (initRct.compareTo(wcRct) == 0) {
+ System.out.println("---Initial Reaction(only): " + initRct.adjustUnit());
+ } else {
+ System.out.println("---Initial Reaction: " + initRct.adjustUnit());
+ System.out.println("---Worst-case Reaction: " + wcRct.adjustUnit());
+ }
+ }
+ }
+ }
+ }
+
+ public Time getSingleCoreInitialRct(final EventChain ec, final SINGLE_CASE latencyCase, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ if (taskChain.size() == 0) {
+ log.error("This task chain is empty.");
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+ .distinct().collect(Collectors.toList());
+ if (puList.size() > 1) {
+ log.error("SingleCore Reaction can not be calculated, "
+ + "The tasks are mapped to more than one processing unit.");
+ return null;
+ }
+ final ProcessingUnit pu = puList.get(0);
+ final Task task_0 = taskChain.get(0);
+ final List<Task> taskList = cpurta.getSortedTaskList(task_0, pu, cpurta);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ final Time hyper = this.getHyperPeriod(taskList);
+ final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
+ final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+ final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
+ /* Checking the first element's all instances in the hyper-period to see whether each can make a chain
+ * and to calculate latency if they can */
+ final ArrayList<Time> latencyList = new ArrayList<Time>();
+ for (int i = 0; i < chainsToCheck; i++) {
+ Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ lat = this.getSingleCoreInitialRct_(i, ec, cpurta);
+ /* Beginning-case */
+ if ((i == 0) && latencyCase.equals(SINGLE_CASE.CRITICAL)) {
+ return lat;
+ }
+ if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+ latencyList.add(lat);
+ }
+ }
+ Collections.sort(latencyList, new TimeComp());
+ /* Best-case */
+ if (latencyCase.equals(SINGLE_CASE.BCLAT)) {
+ return latencyList.get(0);
+ }
+ /* Worst-case */
+ return latencyList.get(latencyList.size()-1);
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ protected Time getSingleCoreInitialRct_(final int i, final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ final Task task_0 = taskChain.get(0);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ lat = this.getCRtoRT(i, task_0, cpurta);
+ for (int j = 1; j < taskChain.size(); j++) {
+ final Task task = taskChain.get(j);
+ final BigInteger latBI = AmaltheaServices.convertToPicoSeconds(lat);
+ final BigDecimal latBD = BigDecimal.valueOf(latBI.doubleValue());
+ final Time period = CommonUtils.getStimInTime(task);
+ final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+ final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
+ final Task preTask = taskChain.get(j-1);
+ final Time pre_period = CommonUtils.getStimInTime(preTask);
+ final BigInteger pre_periodBI = AmaltheaServices.convertToPicoSeconds(pre_period);
+ final BigDecimal pre_periodBD = BigDecimal.valueOf(pre_periodBI.doubleValue());
+ // TODO: check whether the next current task instance or the subsequent task instance comes first
+ // * compare the time difference between them - should be easy
+ // final Time compare = this.getCTR(cei, preTask, cpurta);
+ // * you should consider initial pending time! (offset + ip of pretask VS offset + ip of task)
+ final List<Task> preHPList = cpurta.getHigherPriorityTasks(preTask, cpurta);
+ long offset = 0;
+ /* To check whether the observed task is a higher priority than the previous chain element */
+ if (preHPList.contains(task)) {
+ final BigDecimal offsetBD = latBD.divide(periodBD, 0, BigDecimal.ROUND_CEILING);
+ offset = offsetBD.longValue();
+ } else {
+ final BigDecimal flo = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_FLOOR);
+ offset = (flo.multiply(pre_periodBD)).divide(periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+ }
+ final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+ final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, cpurta);
+ Time taskCRRT = this.getCRtoRT(offset, task, cpurta);
+ // TODO: the most important part (exceptions) write this part alone in the report. with the example situations written in your notebook.
+ /* The current task is a higher priority than the previous one */
+ if (preHPList.contains(task)) {
+ final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, cpurta);
+ if (preTaskCRRT.compareTo(taskCRRT) < 0) {
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ }
+ /* The current task is a lower priority than the previous one */
+ else {
+ Time taskCRIP = this.getCRtoIP(offset, task, cpurta);
+ if (preTaskCRIP.compareTo(taskCRIP) < 0) {
+ offset = offset-1;
+ taskCRIP = this.getCRtoIP(offset, task, cpurta);
+ /* it can not make a task chain */
+ if (lat.compareTo(taskCRIP) > 0 || preTaskCRIP.compareTo(taskCRIP) < 0) {
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ taskCRRT = this.getCRtoRT(offset, task, cpurta);
+ }
+ }
+ lat = taskCRRT;
+ }
+ /* delete the offset time */
+ if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+ lat = lat.subtract(period_0.multiply(i));
+ }
+ return lat;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getSingleCoreWCRct(final EventChain ec, final SINGLE_CASE latencyCase, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ if (taskChain.size() == 0) {
+ log.error("This task chain is empty.");
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+ .distinct().collect(Collectors.toList());
+ if (puList.size() > 1) {
+ log.error("SingleCore Reaction can not be calculated, "
+ + "The tasks are mapped to more than one processing unit.");
+ return null;
+ }
+ final ProcessingUnit pu = puList.get(0);
+ final Task task_0 = taskChain.get(0);
+ final List<Task> taskList = cpurta.getSortedTaskList(task_0, pu, cpurta);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ final Time hyper = this.getHyperPeriod(taskList);
+ final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
+ final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+ final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
+ /* Checking the first element's all instances in the hyper-period to see whether each can make a chain
+ * and to calculate latency if they can */
+ final ArrayList<Time> latencyList = new ArrayList<Time>();
+ for (int i = 0; i < chainsToCheck; i++) {
+ Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ lat = this.getSingleCoreWCRct_(i, ec, cpurta);
+ /* Beginning-case */
+ if ((i == 0) && latencyCase.equals(SINGLE_CASE.CRITICAL)) {
+ return lat;
+ }
+ if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+ latencyList.add(lat);
+ }
+ }
+ Collections.sort(latencyList, new TimeComp());
+ /* Best-case */
+ if (latencyCase.equals(SINGLE_CASE.BCLAT)) {
+ return latencyList.get(0);
+ }
+ /* Worst-case */
+ return latencyList.get(latencyList.size()-1);
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ protected Time getSingleCoreWCRct_(final int i, final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ final Task task_0 = taskChain.get(0);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ Time temp = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time pre_previousVal = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ lat = this.getCRtoRT(i, task_0, cpurta);
+ for (int j = 1; j < taskChain.size(); j++) {
+ final Task task = taskChain.get(j);
+ final BigInteger latBI = AmaltheaServices.convertToPicoSeconds(lat);
+ final BigDecimal latBD = BigDecimal.valueOf(latBI.doubleValue());
+ final Time period = CommonUtils.getStimInTime(task);
+ final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+ final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
+ final Task preTask = taskChain.get(j-1);
+ final Time pre_period = CommonUtils.getStimInTime(preTask);
+ final BigInteger pre_periodBI = AmaltheaServices.convertToPicoSeconds(pre_period);
+ final BigDecimal pre_periodBD = BigDecimal.valueOf(pre_periodBI.doubleValue());
+ // TODO: check whether the next current task instance or the subsequent task instance comes first
+ // * compare the time difference between them - should be easy
+ // final Time compare = this.getCTR(cei, preTask, cpurta);
+ // * you should consider initial pending time! (offset + ip of pretask VS offset + ip of task)
+ final List<Task> preHPList = cpurta.getHigherPriorityTasks(preTask, cpurta);
+ final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+ // TODO: the most important part (exceptions) write this part alone in the report. with the example situations written in your notebook.
+ /* The current task is a higher priority than the previous one */
+ Time taskCRRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (preHPList.contains(task)) {
+ final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, cpurta);
+ final BigInteger preTaskCrrtBI = AmaltheaServices.convertToPicoSeconds(preTaskCRRT);
+ final BigDecimal preTaskCrrtBD = BigDecimal.valueOf(preTaskCrrtBI.longValue());
+ final long offwhp = preTaskCrrtBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+ final Time crrt_cr = this.getCRtoRT(offwhp, task, cpurta);
+ final Time crrt_cr_ = this.getCRtoRT(offwhp-1, task, cpurta);
+ /* When there is an instance(s) of \tau_j between f(j-1)_x and the crrt time of the next instance of \tau_{j-1} */
+ if ((preTaskCrrtBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) &&
+ (lat.compareTo(crrt_cr) < 0) &&
+ (preTaskCRRT.compareTo(crrt_cr) > 0)) {
+ taskCRRT = crrt_cr;
+ }
+ /* In the worst-case, this part is only needed when the current task's priority is higher than the previous one's.
+ * Because the current task's crrt is calculated based on the crrt time of the next instance of the previous task.
+ * Due to the fact that there can be more than one instance of the higher priority task between the lower priority task's instances. */
+ else if ((preTaskCrrtBI.mod(periodBI).compareTo(BigInteger.ZERO) == 0) &&
+ (lat.compareTo(crrt_cr_) < 0) &&
+ (preTaskCRRT.compareTo(crrt_cr_) > 0)) {
+ taskCRRT = crrt_cr_;
+ }
+ }
+ /* The current task is a lower priority than the previous one */
+ else {
+ final Time previousValIP = this.getCRtoIP(preTask_offset-1, preTask, cpurta);
+ final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, cpurta);
+ final BigInteger preTaskCripBI = AmaltheaServices.convertToPicoSeconds(preTaskCRIP);
+ final BigDecimal preTaskCripBD = BigDecimal.valueOf(preTaskCripBI.longValue());
+ final long offlhp = preTaskCripBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+ final Time crip = this.getCRtoIP(offlhp, task, cpurta);
+ /* When there is an instance(s) of \tau_j between f(j-1)_x and the crip time of the next instance of \tau_{j-1} */
+ if ((preTaskCripBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) &&
+ (previousValIP.compareTo(crip) < 0) &&
+ (preTaskCRIP.compareTo(crip) > 0)) {
+ taskCRRT = this.getCRtoRT(offlhp, task, cpurta);
+ }
+ /* In the worst-case, this part is only needed when the current task's priority is lower than the previous one's
+ * Because the current task's crrt is calculated based on the crip time of the next instance of \tau_{j-1}.
+ * Due to the fact that there can be no instance of the lower priority task between the higher priority task's instances. */
+ else {
+ /* When \tau_j is the second element of the chain and there is no instance of \tau_j between f(j-1)_x and the crip time of the next instance of \tau_{j-1} */
+ if (pre_previousVal.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ taskCRRT = this.getCRWC(task, preTask, 1, lat, pre_previousVal, cpurta);
+ /* To consider a situation where there is another chain path that goes through the earlier instance of \tau_{j-1} */
+ if (taskCRRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ }
+ }
+ temp = lat;
+ lat = taskCRRT;
+ pre_previousVal = temp;
+ }
+ /* delete the offset time */
+ if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+ lat = lat.subtract(period_0.multiply(i));
+ }
+ return lat;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ private Time getCRWC(final Task task, final Task preTask, final long k,
+ final Time pre, final Time prepre, final CPURta cpurta) {
+ final BigInteger preBI = AmaltheaServices.convertToPicoSeconds(pre);
+ final BigDecimal preBD = BigDecimal.valueOf(preBI.longValue());
+ final Time period = CommonUtils.getStimInTime(task);
+ final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+ final BigDecimal periodBD = BigDecimal.valueOf(periodBI.longValue());
+ final Time prePeriod = CommonUtils.getStimInTime(preTask);
+ final BigInteger prePeriodBI = AmaltheaServices.convertToPicoSeconds(prePeriod);
+ final BigDecimal prePeriodBD = BigDecimal.valueOf(prePeriodBI.longValue());
+ final long preOffcr = preBD.divide(prePeriodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+ final long offcr = preBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+ final long offcr_ = offcr - 1;
+ final Time preCripCr = this.getCRtoIP(preOffcr - k, preTask, cpurta);
+ final Time crrtCr = this.getCRtoRT(offcr, task, cpurta);
+ final Time crrtCr_ = this.getCRtoRT(offcr_, task, cpurta);
+ final Time cripCr = this.getCRtoIP(offcr, task, cpurta);
+ final Time cripCr_ = this.getCRtoIP(offcr_, task, cpurta);
+ if (preCripCr.compareTo(prepre) < 0) {
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ } else if ((preBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) &&
+ (cripCr.compareTo(pre) < 0) &&
+ (cripCr.compareTo(preCripCr) > 0)){
+ return crrtCr;
+ } else if ((preBI.mod(periodBI).compareTo(BigInteger.ZERO) == 0) &&
+ (cripCr_.compareTo(pre) < 0) &&
+ (cripCr_.compareTo(preCripCr) > 0)){
+ return crrtCr_;
+ } else {
+ return this.getCRWC(task, preTask, k+1, pre, prepre, cpurta);
+ }
+ }
+
+ public Time getBCReactionImplicit(final EventChain ec, final CPURta cpurta) {
+ Time bcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+ bcRctImplicit = bcRctImplicit.add(bcrt);
+ if (i != 0) {
+ final Time bcip = this.getBCInitialPending(task, cpurta);
+ bcRctImplicit = bcRctImplicit.subtract(bcip);
+ }
+ }
+ return bcRctImplicit;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCReactionImplicit(final EventChain ec, final CPURta cpurta) {
+ Time wcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ final Task task_0 = taskChain.get(0);
+ final ProcessingUnit pu_0 = cpurta.getPU(task_0, cpurta);
+ final List<Task> taskList_0 = cpurta.getSortedTaskList(task_0, pu_0, cpurta);
+ final Time rt_0 = cpurta.preciseTestCPURT(task_0, taskList_0, TimeType.WCET, pu_0);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ wcRctImplicit = wcRctImplicit.add(rt_0);
+ wcRctImplicit = wcRctImplicit.add(period_0);
+ for (int i = 1; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time rt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+ wcRctImplicit = wcRctImplicit.add(rt);
+ if (i != taskChain.size() - 1) {
+ final Time period = CommonUtils.getStimInTime(task);
+ final Time bcip = this.getBCInitialPending(task, cpurta);
+ wcRctImplicit = wcRctImplicit.add(period.subtract(bcip));
+ } else {
+ final Time wcip = this.getWCInitialPending(task, cpurta);
+ wcRctImplicit = wcRctImplicit.subtract(wcip);
+ }
+ }
+ return wcRctImplicit;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
+ return getBCReactionImplicit(ec, cpurta);
+ }
+
+ public Time getWCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
+ Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time period = CommonUtils.getStimInTime(task);
+ final Time rt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+ wcInitialRct = wcInitialRct.add(rt);
+ if (i != 0) {
+ final Task preTask = taskChain.get(i-1);
+ final Time prePeriod = CommonUtils.getStimInTime(preTask);
+ if (period.compareTo(prePeriod) >= 0 && taskChain.size() - 1 < 3) {
+ final Time wcip = this.getWCInitialPending(task, cpurta);
+ wcInitialRct = wcInitialRct.add(prePeriod.subtract(wcip));
+ } else if (period.compareTo(prePeriod) >= 0 && i == taskChain.size() - 1) {
+ final Time wcip = this.getWCInitialPending(task, cpurta);
+ wcInitialRct = wcInitialRct.subtract(wcip);
+ } else if (period.compareTo(prePeriod) >= 0 && i == 1) {
+ final Time bcip = this.getBCInitialPending(task, cpurta);
+ wcInitialRct = wcInitialRct.add(prePeriod.add(period).subtract(bcip));
+ } else {
+ final Time bcip = this.getBCInitialPending(task, cpurta);
+ wcInitialRct = wcInitialRct.add(period.subtract(bcip));
+ }
+ }
+ }
+ return wcInitialRct;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCReactionLET(final EventChain ec, final CPURta cpurta) {
+ Time bcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final Time period = CommonUtils.getStimInTime(task);
+ bcRctLET = bcRctLET.add(period);
+ }
+ return bcRctLET;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCReactionLET(final EventChain ec, final CPURta cpurta) {
+ Time wcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final Time period = CommonUtils.getStimInTime(task);
+ if (i != taskChain.size() - 1) {
+ wcRctLET = wcRctLET.add(period.multiply(2));
+ } else {
+ wcRctLET = wcRctLET.add(period);
+ }
+ }
+ return wcRctLET;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCInitialRctLET(final EventChain ec, final CPURta cpurta) {
+ return getBCReactionLET(ec, cpurta);
+ }
+
+ public Time getWCInitialRctLET(final EventChain ec, final CPURta cpurta) {
+ Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final Time period = CommonUtils.getStimInTime(task);
+ wcInitialRct = wcInitialRct.add(period);
+ if (i != 0) {
+ final Task preTask = taskChain.get(i-1);
+ final Time prePeriod = CommonUtils.getStimInTime(preTask);
+ if (period.compareTo(prePeriod) > 0) {
+ wcInitialRct = wcInitialRct.add(prePeriod);
+ } else {
+ wcInitialRct = wcInitialRct.add(period);
+ }
+ }
+ }
+ return wcInitialRct;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCAgeImplicit(final EventChain ec, final CPURta cpurta) {
+ Time bcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ final Task task_0 = taskChain.get(0);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ final Time bcInitialRct = getBCInitialRctImplicit(ec, cpurta);
+ final Time wcReaction = getWCReactionImplicit(ec, cpurta);
+ if ((period_0.add(bcInitialRct)).compareTo(wcReaction) < 0) {
+ final Task lastTask = taskChain.get(taskChain.size() - 1);
+ final Time lastTaskAge = getBCTaskAgeImplicit(lastTask, cpurta);
+ bcAgeImplicit = bcAgeImplicit.add(lastTaskAge);
+ } else {
+ bcAgeImplicit = bcAgeImplicit.add(period_0.add(bcInitialRct).subtract(wcReaction));
+ }
+ return bcAgeImplicit;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCAgeImplicit(final EventChain ec, final CPURta cpurta) {
+ Time wcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ final Task task_0 = taskChain.get(0);
+ final Time period_0 = CommonUtils.getStimInTime(task_0);
+ final Time wcInitialRct = getWCInitialRctImplicit(ec, cpurta);
+ final Time bcInitialRct = getBCInitialRctImplicit(ec, cpurta);
+ wcAgeImplicit = wcAgeImplicit.add(period_0.add(wcInitialRct).subtract(bcInitialRct));
+ return wcAgeImplicit;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCBCSubAgeImplicit(final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final Time wcAgeRctImplicit = this.getWCReactionImplicit(ec, cpurta);
+ final Time bcAgeRctImplicit = this.getBCReactionImplicit(ec, cpurta);
+ return wcAgeRctImplicit.subtract(bcAgeRctImplicit);
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCAgeLET(final EventChain ec, final CPURta cpurta) {
+ Time bcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ final Task lastTask = taskChain.get(taskChain.size() - 1);
+ final Time lastTaskPeriod = CommonUtils.getStimInTime(lastTask);
+ bcAgeLET = bcAgeLET.add(lastTaskPeriod);
+ return bcAgeLET;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCAgeLET(final EventChain ec, final CPURta cpurta) {
+ Time wcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ final Time period = FactoryUtil.createTime(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task)), TimeUnit.PS);
+ if (i == 0) {
+ wcAgeLET = wcAgeLET.add(period);
+ } else {
+ if (period.compareTo(wcAgeLET) == 0) {
+ wcAgeLET = period.multiply(2);
+ } else if (period.compareTo(wcAgeLET) > 0) {
+ wcAgeLET = period;
+ } else {
+ final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+ final BigInteger wcAgeLETBI = AmaltheaServices.convertToPicoSeconds(wcAgeLET);
+ final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
+ final BigDecimal wcAgeLETBD = BigDecimal.valueOf(wcAgeLETBI.doubleValue());
+ if (wcAgeLETBI.mod(periodBI) != BigInteger.ZERO) {
+ final BigDecimal ceiledValueBD = wcAgeLETBD.divide(periodBD, 0, BigDecimal.ROUND_CEILING);
+ final BigInteger ceiledValueBI = BigInteger.valueOf(ceiledValueBD.longValue());
+ wcAgeLET = FactoryUtil.createTime(periodBI.multiply(ceiledValueBI), TimeUnit.PS);
+ } else {
+ wcAgeLET = FactoryUtil.createTime(periodBI.multiply(wcAgeLETBI.divide(periodBI)
+ .add(BigInteger.ONE)), TimeUnit.PS);
+ }
+ }
+ }
+ }
+ return wcAgeLET;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCBCSubAgeLET(final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final Time wcAgeRctLET = this.getWCReactionLET(ec, cpurta);
+ final Time bcAgeRctLET = this.getBCReactionLET(ec, cpurta);
+ return wcAgeRctLET.subtract(bcAgeRctLET);
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCTaskAgeImplicit(final Task task, final CPURta cpurta) {
+ Time bcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+ final Time wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+ final Time period = CommonUtils.getStimInTime(task);
+ bcTaskAge = bcTaskAge.add(period.subtract(wcrt).add(bcrt));
+ return bcTaskAge;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCTaskAgeImplicit(final Task task, final CPURta cpurta) {
+ Time wcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (isTheRTAClassReady(cpurta)) {
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+ final Time wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+ final Time period = CommonUtils.getStimInTime(task);
+ wcTaskAge = wcTaskAge.add(period.subtract(bcrt).add(wcrt));
+ return wcTaskAge;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getBCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Time> bcDataAgeList = new ArrayList<Time>();
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ if (isMappedToCPU(task, cpurta)) {
+ Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
+ if (cpurta.getTriggeringTaskList().contains(task)) {
+ final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+ final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
+ final InterProcessStimulus ips = ipt.getStimulus();
+ final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
+ final Set<Label> gpuLabelSet = SoftwareUtil.getAccessedLabelSet(gpuTask, null);
+ labelSet.addAll(gpuLabelSet);
+ labelSet = labelSet.stream().distinct().collect(Collectors.toSet());
+ }
+ if(labelSet.contains(label)) {
+ final Time bcDataAge = getBCTaskAgeImplicit(task, cpurta);
+ bcDataAgeList.add(bcDataAge);
+ }
+ } else {
+ /* GPU Task - there is no best case or worst case reponse time for GPU Task => Age Latency = Period */
+ bcDataAgeList.add(CommonUtils.getStimInTime(task));
+ }
+ }
+ if (bcDataAgeList.size() != 0) {
+ Collections.sort(bcDataAgeList, new TimeComp());
+ return bcDataAgeList.get(0);
+ }
+ log.error("This chain does not have the observed label.");
+ return null;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ public Time getWCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
+ if (isTheRTAClassReady(cpurta)) {
+ final List<Time> wcDataAgeList = new ArrayList<Time>();
+ final List<Task> taskChain = getECTaskList(ec);
+ for (int i = 0; i < taskChain.size(); i++) {
+ final Task task = taskChain.get(i);
+ if (isMappedToCPU(task, cpurta)) {
+ Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
+ if (cpurta.getTriggeringTaskList().contains(task)) {
+ final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+ final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
+ final InterProcessStimulus ips = ipt.getStimulus();
+ final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
+ final Set<Label> gpuLabelSet = SoftwareUtil.getAccessedLabelSet(gpuTask, null);
+ labelSet.addAll(gpuLabelSet);
+ labelSet = labelSet.stream().distinct().collect(Collectors.toSet());
+ }
+ if(labelSet.contains(label)) {
+ final Time wcDataAge = getWCTaskAgeImplicit(task, cpurta);
+ wcDataAgeList.add(wcDataAge);
+ }
+ } else {
+ /* GPU Task - there is no best case or worst case reponse time for GPU Task => Age Latency = Period */
+ wcDataAgeList.add(CommonUtils.getStimInTime(task));
+ }
+ }
+ if (wcDataAgeList.size() != 0) {
+ Collections.sort(wcDataAgeList, new TimeComp());
+ return wcDataAgeList.get(0);
+ }
+ log.error("This chain does not have the observed label.");
+ return null;
+ }
+ log.error("cpurta instance is not ready!");
+ return null;
+ }
+
+ /**************************************************************************************/
+
+ protected Time getBCInitialPending(final Task task, final CPURta cpurta) {
+ if (this.isTheRTAClassReady(cpurta)) {
+ /*
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+ final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+ final Time bcct = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, cpurta);
+ return bcrt.subtract(bcct);
+ */
+ // TODO: find the best-case initial pending in the given task's hyper-period
+ // (for E2E Latency with the worst-case sampling interval time.)
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ return null;
+ }
+
+ protected Time getWCInitialPending(final Task task, final CPURta cpurta) {
+ if (this.isTheRTAClassReady(cpurta)) {
+ final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
+ if (hpList.size() == 0) {
+ return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ }
+ final Task oneHigherTask = hpList.get(hpList.size()-1);
+ Time wcIPTime = cpurta.preciseTestCPURT(oneHigherTask, hpList, TimeType.WCET, pu);
+ BigInteger wcIPTimeBI = AmaltheaServices.convertToPicoSeconds(wcIPTime);
+ for (int i = 0; i < hpList.size(); i++) {
+ final Task curTask = hpList.get(i);
+ final Time curPeriod = CommonUtils.getStimInTime(curTask);
+ BigInteger curPeriodBI = AmaltheaServices.convertToPicoSeconds(curPeriod);
+ if (i == hpList.size()-1 || wcIPTimeBI.compareTo(curPeriodBI) < 0) {
+ break;
+ } else if (wcIPTimeBI.mod(curPeriodBI) == BigInteger.ZERO) {
+ final Time curExeTime = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.WCET, cpurta);
+ final BigInteger curExeTimeBI = AmaltheaServices.convertToPicoSeconds(curExeTime);
+ wcIPTimeBI = wcIPTimeBI.add(curExeTimeBI);
+ i = -1;
+ }
+ }
+ wcIPTime = FactoryUtil.createTime(wcIPTimeBI, TimeUnit.PS);
+ return wcIPTime;
+ }
+ return null;
+ }
+
+ protected Time getCRtoRT(final long offset, final Task task, final CPURta cpurta) {
+ Time crToRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (this.isTheRTAClassReady(cpurta)) {
+ final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time hyper = this.getHyperPeriod(taskList);
+ final Time period = CommonUtils.getStimInTime(task);
+ final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+ final BigInteger period_BI = AmaltheaServices.convertToPicoSeconds(period);
+ final long cycle = hyper_BI.divide(period_BI).longValue();
+ if (offset % cycle != 0) {
+ final Time wcct = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.WCET, cpurta);
+ final Time initialTime = period.multiply(offset).add(wcct);
+ crToRT = initialTime;
+ /* Incremental CRtoRT Part */
+ final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
+ for (int i = 0; i < hpList.size(); i++) {
+ final BigInteger time_BI = AmaltheaServices.convertToPicoSeconds(crToRT);
+ final BigDecimal time_BD = BigDecimal.valueOf(time_BI.doubleValue());
+ final Task hpTask = hpList.get(i);
+ final Time hpWcct = rtaut.getExecutionTimeforCPUTaskIA(hpTask, pu, TimeType.WCET, cpurta);
+ final Time hpPeriod = CommonUtils.getStimInTime(hpTask);
+ final BigInteger hpPeriod_BI = AmaltheaServices.convertToPicoSeconds(hpPeriod);
+ final BigDecimal hpPeriod_BD = BigDecimal.valueOf(hpPeriod_BI.doubleValue());
+ long hpOffset = time_BD.divide(hpPeriod_BD, 0, BigDecimal.ROUND_FLOOR).longValue();
+ if (hpPeriod.multiply(hpOffset).add(hpWcct).compareTo(crToRT.subtract(wcct)) > 0 && time_BI.mod(hpPeriod_BI).longValue() != 0) {
+ crToRT = hpPeriod.multiply(hpOffset).add(hpWcct).add(wcct);
+ i = -1;
+ }
+ }
+ } else {
+ crToRT = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu).add(period.multiply(offset));
+ }
+ return crToRT;
+ }
+ return null;
+ }
+
+ protected Time getCRtoIP(final long offset, final Task task, final CPURta cpurta) {
+ Time crToIP = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (this.isTheRTAClassReady(cpurta)) {
+ final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+ final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+ final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+ final Time hyper = this.getHyperPeriod(taskList);
+ final Time period = CommonUtils.getStimInTime(task);
+ final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+ final BigInteger period_BI = AmaltheaServices.convertToPicoSeconds(period);
+ final long cycle = hyper_BI.divide(period_BI).longValue();
+ if (offset % cycle != 0) {
+ final Time initialTime = period.multiply(offset);
+ crToIP = initialTime;
+ /* Incremental CRtoIP Part */
+ final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
+ for (int i = 0; i < hpList.size(); i++) {
+ final BigInteger time_BI = AmaltheaServices.convertToPicoSeconds(crToIP);
+ final BigDecimal time_BD = BigDecimal.valueOf(time_BI.doubleValue());
+ final Task hpTask = hpList.get(i);
+ final Time hpWcct = rtaut.getExecutionTimeforCPUTaskIA(hpTask, pu, TimeType.WCET, cpurta);
+ final Time hpPeriod = CommonUtils.getStimInTime(hpTask);
+ final BigInteger hpPeriod_BI = AmaltheaServices.convertToPicoSeconds(hpPeriod);
+ final BigDecimal hpPeriod_BD = BigDecimal.valueOf(hpPeriod_BI.doubleValue());
+ final long hpOffset = time_BD.divide(hpPeriod_BD, 0, BigDecimal.ROUND_FLOOR).longValue();
+ if (hpPeriod.multiply(hpOffset).add(hpWcct).compareTo(crToIP) > 0) {
+ crToIP = hpPeriod.multiply(hpOffset).add(hpWcct);
+ i = -1;
+ }
+ }
+ } else {
+ crToIP = this.getWCInitialPending(task, cpurta).add(period.multiply(offset));
+ }
+ return crToIP;
+ }
+ return null;
+ }
+
+ protected Time getHyperPeriod(List<Task> taskChain) {
+ final List<Time> periodList = taskChain.stream().map(s -> CommonUtils.getStimInTime(s))
+ .collect(Collectors.toList());
+ Time result = periodList.get(0);
+ BigInteger resultBI = AmaltheaServices.convertToPicoSeconds(result);
+ for (int i = 1; i < periodList.size(); i++) {
+ final BigInteger comTime = AmaltheaServices.convertToPicoSeconds(periodList.get(i));
+ resultBI = getLCM(resultBI, comTime);
+ }
+ result = FactoryUtil.createTime(resultBI, TimeUnit.PS);
+ return result;
+ }
+
+ private BigInteger getLCM(BigInteger time0, BigInteger time1) {
+ return time0.multiply(time1.divide(getGCD(time0, time1)));
+ }
+
+ private BigInteger getGCD(BigInteger time0, BigInteger time1) {
+ while (time1.compareTo(BigInteger.ZERO) == 1) {
+ BigInteger temp = time1;
+ time1 = time0.mod(time1);
+ time0 = temp;
+ }
+ return time0;
+ }
+
+ /**
+ * Get an Event-Chain Entity List (Task-based)
+ * @param ec the observed event chain
+ * @return
+ * the corresponding EC task list
+ */
+ public List<Task> getECTaskList(final EventChain ec) {
+ final List<Task> chain = new ArrayList<Task>();
+ for (int i = 0; i < ec.getItems().size(); i++) {
+ final EventChainItem eci = ec.getItems().get(i);
+ if (eci instanceof EventChainContainer) {
+ final EventChainContainer ecc = (EventChainContainer) eci;
+ final Event stiEvent = ecc.getEventChain().getStimulus();
+ if (stiEvent instanceof ProcessEvent) {
+ final Task stiTask = (Task)((ProcessEvent) stiEvent).getEntity();
+ chain.add(stiTask);
+ }
+ if (i == ec.getItems().size() - 1) {
+ final Event resEvent = ecc.getEventChain().getResponse();
+ if (resEvent instanceof ProcessEvent) {
+ final Task resTask = (Task)((ProcessEvent) resEvent).getEntity();
+ chain.add(resTask);
+ }
+ break;
+ }
+ }
+ }
+ return chain;
+ }
+
+ /**
+ * conver an event-chain to a list of Labels that belong to the chain
+ * @param ec the observed event-chain
+ * @return
+ * a list of the observed event-chain
+ */
+ public List<Label> convertECtoLabels(final EventChain ec, final CPURta cpurta) {
+ final List<Task> chain = getECTaskList(ec);
+ final List<Label> labels = new ArrayList<Label>();
+ for (int i = 0; i < chain.size(); i++) {
+ final Task task = chain.get(i);
+ final List<Runnable> runnables = SoftwareUtil.getRunnableList(task, null);
+ for (int j = 0; j < runnables.size(); j++) {
+ final Runnable runnable = runnables.get(j);
+ final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
+ final List<Label> temp = laList.stream().map(s -> s.getData()).distinct().collect(Collectors.toList());
+ labels.addAll(temp);
+ }
+ /* runnables from the triggered task (gpu task) */
+ if (cpurta.getTriggeringTaskList().contains(task)) {
+ final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+ final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
+ final InterProcessStimulus ips = ipt.getStimulus();
+ final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
+ final List<Runnable> gpuRunnables = SoftwareUtil.getRunnableList(gpuTask, null);
+ for (int j = 0; j < gpuRunnables.size(); j++) {
+ final Runnable runnable = gpuRunnables.get(j);
+ final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
+ final List<Label> temp = laList.stream().map(s -> s.getData()).distinct().collect(Collectors.toList());
+ labels.addAll(temp);
+ }
+ }
+ }
+ final List<Label> labelList = labels.stream().distinct().collect(Collectors.toList());
+ return labelList;
+ }
+
+ /**
+ * To check whether or not the observed task is mapped to CPU (according to the integer array)
+ * @param task the observed task
+ * @param cpurta the instance of CPURta class that contains model & mapping IA info
+ * @return
+ * boolean value that says whether or not it is mapped to CPU
+ */
+ private static boolean isMappedToCPU (final Task task, final CPURta cpurta) {
+ /* The observed task is a GPU task */
+ if (cpurta.getGpuTaskList().contains(task)) {
+ final int index = cpurta.getModel().getSwModel().getTasks().indexOf(task);
+ final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
+ final int[] ia = cpurta.getIA();
+ /* when the observed GPU task is mapped to GPU */
+ if (ia[index] > cpuThreshold) {
+ return false;
+ }
+ }
+ /* when the observed task(CPU or GPU) is mapped to CPU */
+ return true;
+ }
+}
+
+/**
+ * @Date: July 10-2019
+ * @version 1.0
+ * This inner class is used for sorting a Time type list.
+ * If the Time of a is smaller than that of b, it returns -1.
+ * If the Time of a is bigger than that of b, it returns 1.
+ */
+class TimeComp implements Comparator<Time> {
+ @Override
+ public int compare(final Time a, final Time b) {
+ if (a.compareTo(b) < 0) {
+ return -1;
+ }
+ return 1;
+ }
}
\ No newline at end of file
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/IRTA.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/IRTA.java
new file mode 100644
index 0000000..726d59e
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/IRTA.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2020 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.util.HashMap;
+
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
+
+public interface IRTA {
+
+ /**
+ * Get the sum of all response times contained in an AMALTHEA model
+ * @param timeType (BCET, WCET supported)
+ * @return Time response time sum across all tasks
+ */
+ public Time getRTSum(final TimeType timeType);
+
+ /**
+ * @return Hashmap<Task,Time> all tasks with corresponding response times
+ */
+ public HashMap<Task, Time> getTRT();
+
+ /**
+ * Get the response time of a task based on offsets for interProcessStimuli
+ * @param t Task
+ * @return Time reponse time
+ */
+ public Time getRT(final Task t, final TimeType timeType);
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
index 7d19a19..73bf841 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
@@ -1,573 +1,561 @@
-/*******************************************************************************
- * 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.math.BigInteger;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.log4j.Logger;
-import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
-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.ProcessingUnit;
-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.Ticks;
-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.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 support CPURta class. Response Time Analysis contains low level calculation
- * such as deriving execution time of a Task or Runnable. Execution time calculation varies depending on the analyzed model.
- * Therefore, it is necessary to separate from Response Time calculation to increase adaptability.
- * Only 'getExecutionTimeforCPUTask' method is accessible for CPURta and the rest are sub-methods of it.
- */
-public class RTARuntimeUtil {
- /**
- * Calculate execution time of the given task under one of the four cases with some configurations.
- * Since this method is used by CPURta, the visibility should be 'public'
- * 1. triggering task in the synchronous mode
- * 2. triggering task in the asynchronous mode
- * 3. GPU task on CPU
- * 4. task with only Ticks
- * @param task the observed task
- * @param pu ProcessingUnit that would compute the given task (A57 or Denver)
- * @param executionCase BCET, ACET, WCET
- * @param cpurta the instance of CPURta class that calls this method
- * (to access to the cumuAcTime Time variable that accumulate access latency)
- * @return
- * execution time of the observed task
- */
- public Time getExecutionTimeforCPUTask(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
- Logger.getLogger(RTARuntimeUtil.class);
- /* set the default result time variable as 0s */
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- /* check if the current task is a triggering task.
- * If so, check whether or not it triggers the target task which is newly mapped to CPU.
- * In that case, returns 0 ps */
- if (doesThisTaskTriggerCPUTask(task, cpurta)) {
- return result;
- }
- /* contention time */
- final Time contention = cpurta.getCT().contentionForTask(task);
- /* The list of runnables of the given task */
- final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
- /* To identify the index of the triggerEvent */
- final List<CallSequenceItem> callSequenceList = SoftwareUtil.collectCalls(task, null,
- (call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent
- || call instanceof SetEvent || call instanceof WaitEvent));
- int indexforTrigger = 0;
- for (int i = 0; i < callSequenceList.size(); i++) {
- if (callSequenceList.get(i) instanceof InterProcessTrigger) {
- indexforTrigger = i;
- }
- }
- /* To distinguish CPU Tasks between Sync & Async */
- if (isTriggeringTask(task)) {
- /* all should be synchronous (wait should not be ignored) - active wait */
- if (SharedConsts.synchronousOffloading == true) {
- result = syncTypeOperation(indexforTrigger, callSequenceList, runnableList, pu, executionCase, cpurta);
- /* if this task has the OffloadingAsync runnable, subtract the runnable part from the result */
- if (doesTaskHaveAsyncRunnable(task, cpurta)) {
- result = result.subtract(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));
- }
- }
- /* all should be asynchronous (wait should be ignored) - passive wait */
- else {
- result = asyncTypeOperation(runnableList, pu, executionCase);
- /* if this task is missing the OffloadingAsync runnable, add the runnable part to the result */
- if (!doesTaskHaveAsyncRunnable(task, cpurta)) {
- result = result.add(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));
- }
- }
- }
- else {
- /* GPU Origin Task on CPU & No Triggering Behavior (No InterProcessTrigger) */
- if (!(callSequenceList.get(indexforTrigger) instanceof InterProcessTrigger)) {
- /* GPU Origin task that is newly mapped to CPU */
- if (cpurta.getGpuTaskList().contains(task)) {
- result = result.add(getExecutionTimeForGPUTaskOnCPU(task, runnableList, pu, executionCase, cpurta));
- result = result.add(contention);
- return result;
- }
- /* No Triggering Behavior (No InterProcessTrigger) */
- for (final Runnable r : runnableList) {
- result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
- }
- }
- }
- result = result.add(contention);
- return result;
- }
-
- /**
- * Find out whether the given triggering task(that has an InterProcessTrigger) triggers a GPU task which is newly mapped to CPU.
- * If the ProcessingUnit index of the triggered task is bigger than the biggest CPU index, that means the triggered task is mapped to GPU
- * which would return false.
- * @param task the observed task
- * @param cpurta the instance of CPURta class that calls this method
- * (to get the task List & the integer array to identify the ProcessingUnit index of the triggered task)
- * @return
- * boolean value (true: the observed task triggers a task that is mapped to CPU /
- * false: the observed task triggers a task that is mapped to GPU)
- */
- private boolean doesThisTaskTriggerCPUTask(final Task task, final CPURta cpurta) {
- if (cpurta.getTriggeringTaskList().contains(task)) {
- final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(task, null,
- (call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent
- || call instanceof SetEvent || call instanceof WaitEvent));
- final InterProcessStimulus ips = ((InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next())
- .getStimulus();
- final EList<Task> allTaskList = cpurta.getModel().getSwModel().getTasks();
- final int[] ia = cpurta.getIA();
- final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
- for (int i = 0; i < ia.length; i++) {
- if (ia[i] > cpuThreshold) {
- final Task theTask = allTaskList.get(i);
- if (theTask.getStimuli().get(0) instanceof InterProcessStimulus) {
- final InterProcessStimulus thisIPS = (InterProcessStimulus) theTask.getStimuli().get(0);
- if (ips.equals(thisIPS)) {
- Logger.getLogger(RTARuntimeUtil.class).debug("Confirmation: The triggered task mapped to (GPU)");
- return false;
- }
- }
- }
- }
- Logger.getLogger(RTARuntimeUtil.class).debug("Confirmation: The triggered task mapped to (CPU)");
- return true;
- }
- return false;
- }
-
- /**
- * Calculate execution time of the given runnableList in a synchronous manner.
- * (execution time of pre-processing) + GPU task response time + (execution time of post-processing)
- * @param indexforTrigger Integer variable that is used to get InterProcessTrigger to identify the triggered GPU task
- * @param callSequenceList callSequenceList List variable that is used to get InterProcessTrigger to identify the triggered GPU task
- * @param runnableList the observed runnable List to calculate execution time in the synchronous mode
- * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
- * @param executionCase BCET, ACET, WCET
- * @param cpurta the instance of CPURta class that calls this method
- * (to get the identified triggered GPU task in the model)
- * (to access to the cumuAcTime Time variable that accumulate access latency)
- * @return
- * synchronous execution time of the observed set
- */
- private Time syncTypeOperation(final int indexforTrigger, final List<CallSequenceItem> callSequenceList, final List<Runnable> runnableList,
- final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
- Logger.getLogger(RTARuntimeUtil.class).debug("TYPE: SYNC");
- /* set the default result time variable as 0s */
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- /* Sum all the runnable ExecutionTime of the CPU Task */
- for (final Runnable r : runnableList) {
- result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
- }
- final InterProcessTrigger ipt = (InterProcessTrigger) callSequenceList.get(indexforTrigger);
- final Task triggeredGPUTask = cpurta.getModel().getSwModel().getTasks().stream().filter(t -> t.getStimuli().get(0).equals(ipt.getStimulus())).iterator()
- .next();
- result = result.add(cpurta.getTRT().get(triggeredGPUTask));
- return result;
- }
-
- /**
- * Calculate execution time of the given runnableList in an asynchronous manner.
- * (execution time of pre-processing) + (execution time of post-processing)
- * @param runnableList the observed runnable List to calculate execution time in the asynchronous mode
- * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
- * @param executionCase BCET, ACET, WCET
- * @return
- * asynchronous execution time of the observed runnable List
- */
- private Time asyncTypeOperation(final List<Runnable> runnableList, final ProcessingUnit pu, final TimeType executionCase) {
- Logger.getLogger(RTARuntimeUtil.class).debug("TYPE: ASYNC");
- /**
- * <Asynchronous Task> et_t=sum_{runnable calls before GPU trigger
- * event}et_r + et_{runnable calls after GPU trigger event};
- */
- /* set the default result time variable as 0s */
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- /* Sum all the runnable ExecutionTime */
- for (final Runnable r : runnableList) {
- /* In case of Pre_Detection_Post task, the AsyncOffloading runnable is already taken into account here. */
- result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
- }
- return result;
- }
-
- /**
- * Identify whether or not the given task has the OffloadingAsyncCosts Runnable (that takes costs into account in the Asynchronous mode)
- * which some triggering tasks do not have.
- * Since this method is used by CPURta, the visibility should be 'protected'
- * @param task the observed task
- * @param cpurta the instance of CPURta class that calls this method
- * (to access to the triggeringTaskList List<Task> variable that contains tasks with an InterProcessTrigger)
- * @return
- * boolean value of the result
- */
- protected static boolean doesTaskHaveAsyncRunnable (final Task task, final CPURta cpurta) {
- boolean result = false;
- if (cpurta.getTriggeringTaskList().contains(task)) {
- final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(task, null,
- (call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent
- || call instanceof SetEvent || call instanceof WaitEvent));
- final int waitIndex = callList.indexOf(callList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
- List<CallSequenceItem> clearEvent = callList.stream().filter(s -> s instanceof ClearEvent).collect(Collectors.toList());
- if (clearEvent.size() != 0) {
- final int clearIndex = callList.indexOf(callList.stream().filter(s -> s instanceof ClearEvent).iterator().next());
- if ((clearIndex - waitIndex) > 1) {
- result = true;
- }
- }
- } else {
- Logger.getLogger(RTARuntimeUtil.class).debug("ERROR: This task is not a triggering task!!");
- }
- return result;
- }
-
- /**
- * Calculate execution time of the given task which was originally designed for GPU but newly mapped to CPU by Generic Algorithm Mapping.
- * It should ignore offloading runnables and take the required labels(read from pre-processing, write from post-processing) into account.
- * The method follows Read / Compute(Ticks) / Write semantic.
- * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)
- * @param task the observed task
- * @param runnableList runnable list of the given task
- * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
- * @param executionCase BCET, ACET, WCET
- * @param cpurta the instance of CPURta class that calls this method
- * (to access to the gpuToCpuLabels HashMap variable that contains List<Label> of required read & write labels)
- * @return
- * execution time of the observed task
- */
- private Time getExecutionTimeForGPUTaskOnCPU(final Task task, final List<Runnable> runnableList, final ProcessingUnit pu,
- final TimeType executionCase, final CPURta cpurta) {
- Logger.getLogger(RTARuntimeUtil.class).debug("TYPE: GPUTaskOnCPU // " + "Task: " + task.getName());
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Runnable funcRunnable = null;
- for (final Runnable r : runnableList) {
- final List<Ticks> thisTicksList = SoftwareUtil.getTicks(r, null);
- if (thisTicksList.size() != 0) {
- funcRunnable = r;
- break;
- }
- }
- final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
- final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
- final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();
- final List<List<Label>> thisLabelList = gtcl.get(task);
- final List<Label> readLabelList = thisLabelList.get(0);
- final List<Label> writeLabelList = thisLabelList.get(1);
- for (final Label l : readLabelList) {
- Logger.getLogger(RTARuntimeUtil.class).debug("Label(Read): " + l.getName() + " // (" + task.getName() + ")");
- }
- for (final Label l : writeLabelList) {
- Logger.getLogger(RTARuntimeUtil.class).debug("Label(Write): " + l.getName() + " // (" + task.getName() + ")");
- }
- double readLatency = 0;
- double writeLatency = 0;
- if (executionCase.equals(TimeType.WCET)) {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
- } else if (executionCase.equals(TimeType.BCET)) {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
- } else {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
- }
- /* Read (LabelAccess): */
- double readAccessParameter = 0;
- double sizeofReadLabels = 0;
- for (final Label rl : readLabelList) {
- sizeofReadLabels += rl.getSize().getNumberBytes();
- }
- readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / freq));
- final Time readAccess = parameter.multiply(readAccessParameter);
- result = result.add(readAccess); // LabelAccess(Read) added
- /* Execution (Ticks): */
- final List<Ticks> ticksList = SoftwareUtil.getTicks(funcRunnable, null);
- for (final Ticks t : ticksList) {
- // TODO: This line Should be replaced into below in the version 0.9.5 */
- final Time tickExecution = CommonUtils.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.4
- // final Time tickExecution = RuntimeUtil.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.5
- result = result.add(tickExecution); // Execution(Ticks) added
- }
- /* Write (LabelAccess): */
- double writeAccessParameter = 0;
- double sizeofWriteLabels = 0;
- for (final Label wl : writeLabelList) {
- sizeofWriteLabels += wl.getSize().getNumberBytes();
- }
- writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / freq));
- final Time writeAccess = parameter.multiply(writeAccessParameter);
- result = result.add(writeAccess); // LabelAccess(Write) added
- return result;
- }
-
- /**
- * Calculate execution time of the given runnable.
- * The method consider Read / Compute(Ticks) / Write semantic.
- * @param runnable the observed runnable
- * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
- * @param executionCase BCET, ACET, WCET
- * @return
- * execution time of the observed runnable
- */
- private Time getExecutionTimeForRTARunnable(final Runnable runnable, final ProcessingUnit pu, final TimeType executionCase) {
- Logger.getLogger(RTARuntimeUtil.class).debug(executionCase.toString());
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
- double readLatency = 0;
- double writeLatency = 0;
- if (pu.getAccessElements().size() == 0) {
- readLatency = 30; // Default value will be assigned
- writeLatency = 30; // Default value of will be assigned
- } else {
- if (executionCase.equals(TimeType.WCET)) {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
- } else if (executionCase.equals(TimeType.BCET)) {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
- } else {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
- }
- }
- /* Read & Write Memory Access Time */
- result = result.add(getRunnableMemoryAccessTime(runnable, freq, readLatency, writeLatency));
- /* Execution (Ticks): */
- final List<Ticks> ticksList = SoftwareUtil.getTicks(runnable, null);
- for (final Ticks t : ticksList) {
- // TODO: This line Should be replaced into below in the version 0.9.5 */
- final Time tickExecution = CommonUtils.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.4
- // final Time tickExecution = RuntimeUtil.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.5
- result = result.add(tickExecution); // Execution(Ticks) added
- }
- return result;
- }
-
- /**
- * Calculate memory access time of the observed task.
- * Since this method is used by CPURta, the visibility should be 'public'
- * @param task the observed task
- * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
- * @param executionCase BCET, ACET, WCET
- * @return
- * memory access time of the observed task
- */
- public Time getTaskMemoryAccessTime (final Task task, final ProcessingUnit pu, final TimeType executionCase) {
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
- final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
- double readLatency = 0;
- double writeLatency = 0;
- if (pu.getAccessElements().size() == 0) {
- readLatency = 30; // Default value will be assigned
- writeLatency = 30; // Default value of will be assigned
- } else {
- if (executionCase.equals(TimeType.WCET)) {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
- } else if (executionCase.equals(TimeType.BCET)) {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
- } else {
- readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
- writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
- }
- }
- for(final Runnable r : runnableList ) {
- result = result.add(getRunnableMemoryAccessTime(r, freq, readLatency, writeLatency));
- }
- return result;
- }
-
- /**
- * Calculate memory access time of the observed runnable.
- * The method follows Read / Compute(Ticks) / Write semantic.
- * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)
- * @param runnable the observed runnable
- * @param frequency frequency value of the Processing Unit
- * @param readLatency readLatency value of the Processing Unit
- * @param writeLatency writeLatency value of the Processing Unit
- * @return
- * memory access time of the observed runnable
- */
- private Time getRunnableMemoryAccessTime (final Runnable runnable, final double frequency,
- final double readLatency, final double writeLatency) {
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
- final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(runnable, null);
- final List<LabelAccess> readList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.READ)).collect(Collectors.toList());
- final List<LabelAccess> writeList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.WRITE)).collect(Collectors.toList());
- /* Read (LabelAccess): */
- double readAccessParameter = 0;
- double sizeofReadLabels = 0;
- for (final LabelAccess rl : readList) {
- sizeofReadLabels += rl.getData().getSize().getNumberBytes();
- }
- readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / frequency));
- final Time readAccess = parameter.multiply(readAccessParameter);
- result = result.add(readAccess); // LabelAccess(Read) added
- /* Write (LabelAccess): */
- double writeAccessParameter = 0;
- double sizeofWriteLabels = 0;
- for (final LabelAccess wl : writeList) {
- sizeofWriteLabels += wl.getData().getSize().getNumberBytes();
- }
- writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / frequency));
- final Time writeAccess = parameter.multiply(writeAccessParameter);
- result = result.add(writeAccess); // LabelAccess(Write) added
- return result;
- }
-
- /**
- * Identify whether the given task has an InterProcessTrigger or not.
- * @param task the observed task
- * @return
- * boolean value of the result
- */
- private static boolean isTriggeringTask(final Task task) {
- /* true: Triggering Task, false: Non-Triggering Task */
- boolean result = false;
- final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(task, null,
- (call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent
- || call instanceof SetEvent || call instanceof WaitEvent));
- List<CallSequenceItem> iptList = callList.stream().filter(s -> s instanceof InterProcessTrigger).collect(Collectors.toList());
- if (iptList.size() != 0) {
- result = true;
- }
- return result;
- }
-
- /******************************************* Implicit Communication Paradigm *************************************************/
-
- /**
- * For the implicit communication paradigm
- * Time[0] = copy-in time for the observed task, Time[1] = copy-out time for the observed task
- * if a GPU task mapped to CPU is passed here, we also need to consider its required labels from Pre-Pro processing runnables
- * @param task the observed task
- * @param pu the processing unit that the observed task is mapped to
- * @param executionCase WCET, BCET, ACET
- * @return
- * Time array that contains copy-in, copy-out time of the observed task
- */
- public Time[] getLocalCopyTimeArray(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
- Time[] ta = new Time[2];
- Time readCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time writeCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- /* The observed task is a GPU task */
- if (cpurta.getGpuTaskList().contains(task)) {
- final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();
- final List<List<Label>> thisLabelList = gtcl.get(task);
- final List<Label> readLabels = thisLabelList.get(0);
- final List<Label> writeLabels = thisLabelList.get(1);
- for (final Label rl : readLabels) {
- readCopy = readCopy.add(getCopyEngineTime(rl, pu, executionCase, true));
- }
- ta[0] = readCopy;
- for (final Label wl : writeLabels) {
- writeCopy = writeCopy.add(getCopyEngineTime(wl, pu, executionCase, false));
- }
- ta[1] = writeCopy;
- return ta;
- }
- /* The observed task is a CPU task */
- final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
- final List<Label> readList = new ArrayList<Label>();
- final List<Label> writeList = new ArrayList<Label>();
- for (int i = 0; i < runnableList.size(); i++) {
- final Runnable runnable = runnableList.get(i);
- final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
- final List<Label> rList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.READ))
- .map(s->s.getData()).collect(Collectors.toList());
- rList.stream().forEach(s -> readList.add(s));
- final List<Label> wList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.WRITE))
- .map(s->s.getData()).collect(Collectors.toList());
- wList.stream().forEach(s -> writeList.add(s));
- }
- final List<Label> readLabels = readList.stream().distinct().collect(Collectors.toList());
- final List<Label> writeLabels = writeList.stream().distinct().collect(Collectors.toList());
- for (final Label rl : readLabels) {
- readCopy = readCopy.add(getCopyEngineTime(rl, pu, executionCase, true));
- }
- ta[0] = readCopy;
- for (final Label wl : writeLabels) {
- writeCopy = writeCopy.add(getCopyEngineTime(wl, pu, executionCase, false));
- }
- ta[1] = writeCopy;
- return ta;
- }
-
- /**
- * The method is used to calculate CopyEngine time for single label.
- * @param label the observed label
- * @param pu ProcessingUnit that would process the given label
- * @param executionCase BCET, ACET, WCET
- * @param readOrWrite when the given runnable is 'runnable_0'(the first callSquence of the task), it is read(true),
- * when the given runnable is 'runnable_Last'(the last callSquence of the task), it is write(false).
- * @return
- * the given label copy engine time
- */
- private Time getCopyEngineTime(final Label label, final ProcessingUnit pu, final TimeType executionCase, final boolean readOrWrite) {
- Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
- final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
- double latency = 0;
- /* Read */
- if(readOrWrite) {
- if (executionCase.equals(TimeType.BCET)) {
- latency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
- } else if (executionCase.equals(TimeType.ACET)) {
- latency = pu.getAccessElements().get(0).getReadLatency().getAverage();
- } else if (executionCase.equals(TimeType.WCET)) {
- latency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
- }
- }
- /* Write */
- else {
- if (executionCase.equals(TimeType.BCET)) {
- latency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
- } else if (executionCase.equals(TimeType.ACET)) {
- latency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
- } else if (executionCase.equals(TimeType.WCET)) {
- latency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
- }
- }
- double labelAccessParameter = 0;
- final double labelSize = label.getSize().getNumberBytes();
- labelAccessParameter = (Math.ceil(labelSize / 64.0) * (latency / freq));
- final Time labelAccess = parameter.multiply(labelAccessParameter);
- result = result.add(labelAccess); // LabelAccess(Read) added
- return result;
- }
+/*******************************************************************************
+ * 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.math.BigInteger;
+import java.util.ArrayList;
+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.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts;
+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.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.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.RunnableCall;
+import org.eclipse.app4mc.amalthea.model.SetEvent;
+import org.eclipse.app4mc.amalthea.model.Task;
+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.WaitEvent;
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
+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;
+import org.eclipse.emf.common.util.EList;
+
+public class RTARuntimeUtil {
+ final static Logger log = Logger.getLogger(RTARuntimeUtil.class);
+ /**
+ * Calculate execution time of the given task under one of the four cases with some configurations.
+ * Since this method is used by CPURta, the visibility should be 'public'
+ * 1. triggering task in the synchronous mode
+ * 2. triggering task in the asynchronous mode
+ * 3. GPU task on CPU
+ * 4. task with only Ticks
+ * @param task the observed task
+ * @param pu ProcessingUnit that would compute the given task (A57 or Denver)
+ * @param executionCase BCET, ACET, WCET
+ * @param cpurta the instance of CPURta class that calls this method
+ * (to access to the cumuAcTime Time variable that accumulate access latency)
+ * @return
+ * execution time of the observed task
+ */
+ public Time getExecutionTimeforCPUTaskIA(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
+ log.setLevel(Level.ERROR);
+ /* set the default result time variable as 0s */
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ /* check if the current task is a triggering task.
+ * If so, check whether or not it triggers the target task which is newly mapped to CPU.
+ * In that case, returns 0 ps */
+ if (doesThisTaskTriggerCPUTask(task, cpurta)) {
+ return result;
+ }
+ /* contention time */
+ final Time contention = cpurta.getCT().contentionForTask(task);
+ /* The list of runnables of the given task */
+ final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
+ /* To identify the index of the triggerEvent */
+ final List<ActivityGraphItem> callSequenceList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+ || call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+ int indexforTrigger = 0;
+ for (int i = 0; i < callSequenceList.size(); i++) {
+ if (callSequenceList.get(i) instanceof InterProcessTrigger) {
+ indexforTrigger = i;
+ }
+ }
+ /* To distinguish CPU Tasks between Sync & Async */
+ if (isTriggeringTask(task)) {
+ /* all should be synchronous (wait should not be ignored) - active wait */
+ if (SharedConsts.synchronousOffloading == true) {
+ result = syncTypeOperation(indexforTrigger, callSequenceList, runnableList, pu, executionCase, cpurta);
+ /* if this task has the OffloadingAsync runnable, subtract the runnable part from the result */
+ if (doesTaskHaveAsyncRunnable(task, cpurta)) {
+ result = result.subtract(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));
+ }
+ }
+ /* all should be asynchronous (wait should be ignored) - passive wait */
+ else {
+ result = asyncTypeOperation(runnableList, pu, executionCase);
+ /* if this task is missing the OffloadingAsync runnable, add the runnable part to the result */
+ if (!doesTaskHaveAsyncRunnable(task, cpurta)) {
+ result = result.add(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));
+ }
+ }
+ }
+ else {
+ /* GPU Origin Task on CPU & No Triggering Behavior (No InterProcessTrigger) */
+ if (!(callSequenceList.get(indexforTrigger) instanceof InterProcessTrigger)) {
+ /* GPU Origin task that is newly mapped to CPU */
+ if (cpurta.getGpuTaskList().contains(task)) {
+ result = result.add(getExecutionTimeForGPUTaskOnCPU(task, runnableList, pu, executionCase, cpurta));
+ result = result.add(contention);
+ return result;
+ }
+ /* No Triggering Behavior (No InterProcessTrigger) */
+ for (final Runnable r : runnableList) {
+ result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
+ }
+ }
+ }
+ result = result.add(contention);
+ return result;
+ }
+
+ /**
+ * Find out whether the given triggering task(that has an InterProcessTrigger) triggers a GPU task which is newly mapped to CPU.
+ * If the ProcessingUnit index of the triggered task is bigger than the biggest CPU index, that means the triggered task is mapped to GPU
+ * which would return false.
+ * @param task the observed task
+ * @param cpurta the instance of CPURtaIA class that calls this method
+ * (to get the task List & the integer array to identify the ProcessingUnit index of the triggered task)
+ * @return
+ * boolean value (true: the observed task triggers a task that is mapped to CPU /
+ * false: the observed task triggers a task that is mapped to GPU)
+ */
+ private boolean doesThisTaskTriggerCPUTask(final Task task, final CPURta cpurta) {
+ if (cpurta.getTriggeringTaskList().contains(task)) {
+ final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+ || call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+ final InterProcessStimulus ips = ((InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next())
+ .getStimulus();
+ final EList<Task> allTaskList = cpurta.getModel().getSwModel().getTasks();
+ final int[] ia = cpurta.getIA();
+ final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
+ for (int i = 0; i < ia.length; i++) {
+ if (ia[i] > cpuThreshold) {
+ final Task theTask = allTaskList.get(i);
+ if (theTask.getStimuli().get(0) instanceof InterProcessStimulus) {
+ final InterProcessStimulus thisIPS = (InterProcessStimulus) theTask.getStimuli().get(0);
+ if (ips.equals(thisIPS)) {
+ log.debug("Confirmation: The triggered task mapped to (GPU)");
+ return false;
+ }
+ }
+ }
+ }
+ log.debug("Confirmation: The triggered task mapped to (CPU)");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Calculate execution time of the given runnableList in a synchronous manner.
+ * (execution time of pre-processing) + GPU task response time + (execution time of post-processing)
+ * @param indexforTrigger Integer variable that is used to get InterProcessTrigger to identify the triggered GPU task
+ * @param callSequenceList callSequenceList List variable that is used to get InterProcessTrigger to identify the triggered GPU task
+ * @param runnableList the observed runnable List to calculate execution time in the synchronous mode
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @param executionCase BCET, ACET, WCET
+ * @param cpurta the instance of CPURtaIA class that calls this method
+ * (to get the identified triggered GPU task in the model)
+ * (to access to the cumuAcTime Time variable that accumulate access latency)
+ * @return
+ * synchronous execution time of the observed set
+ */
+ private Time syncTypeOperation(final int indexforTrigger, final List<ActivityGraphItem> callSequenceList, final List<Runnable> runnableList,
+ final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
+ log.debug("TYPE: SYNC");
+ /* set the default result time variable as 0s */
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ /* Sum all the runnable ExecutionTime of the CPU Task */
+ for (final Runnable r : runnableList) {
+ result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
+ }
+ final InterProcessTrigger ipt = (InterProcessTrigger) callSequenceList.get(indexforTrigger);
+ final Task triggeredGPUTask = cpurta.getModel().getSwModel().getTasks().stream().filter(t -> t.getStimuli().get(0).equals(ipt.getStimulus())).iterator()
+ .next();
+ result = result.add(cpurta.getTRT().get(triggeredGPUTask));
+ return result;
+ }
+
+ /**
+ * Calculate execution time of the given runnableList in an asynchronous manner.
+ * (execution time of pre-processing) + (execution time of post-processing)
+ * @param runnableList the observed runnable List to calculate execution time in the asynchronous mode
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @param executionCase BCET, ACET, WCET
+ * @return
+ * asynchronous execution time of the observed runnable List
+ */
+ private Time asyncTypeOperation(final List<Runnable> runnableList, final ProcessingUnit pu, final TimeType executionCase) {
+ log.debug("TYPE: ASYNC");
+ /**
+ * <Asynchronous Task> et_t=sum_{runnable calls before GPU trigger
+ * event}et_r + et_{runnable calls after GPU trigger event};
+ */
+ /* set the default result time variable as 0s */
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ /* Sum all the runnable ExecutionTime */
+ for (final Runnable r : runnableList) {
+ /* In case of Pre_Detection_Post task, the AsyncOffloading runnable is already taken into account here. */
+ result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
+ }
+ return result;
+ }
+
+ /**
+ * Identify whether or not the given task has the OffloadingAsyncCosts Runnable (that takes costs into account in the Asynchronous mode)
+ * which some triggering tasks do not have.
+ * Since this method is used by CPURtaIA, the visibility should be 'protected'
+ * @param task the observed task
+ * @param cpurta the instance of CPURtaIA class that calls this method
+ * (to access to the triggeringTaskList List<Task> variable that contains tasks with an InterProcessTrigger)
+ * @return
+ * boolean value of the result
+ */
+ protected static boolean doesTaskHaveAsyncRunnable(final Task task, final CPURta cpurta) {
+ boolean result = false;
+ if (cpurta.getTriggeringTaskList().contains(task)) {
+ final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+ || call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+ final int waitIndex = callList.indexOf(callList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
+ final List<ActivityGraphItem> clearEvent = callList.stream().filter(s -> s instanceof ClearEvent).collect(Collectors.toList());
+ if (clearEvent.size() != 0) {
+ final int clearIndex = callList.indexOf(callList.stream().filter(s -> s instanceof ClearEvent).iterator().next());
+ if ((clearIndex - waitIndex) > 1) {
+ result = true;
+ }
+ }
+ } else {
+ log.debug("ERROR: This task is not a triggering task!!");
+ }
+ return result;
+ }
+
+ /**
+ * Calculate execution time of the given task which was originally designed for GPU but newly mapped to CPU by Generic Algorithm Mapping.
+ * It should ignore offloading runnables and take the required labels(read from pre-processing, write from post-processing) into account.
+ * The method follows Read / Compute(Ticks) / Write semantic.
+ * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)
+ * @param task the observed task
+ * @param runnableList runnable list of the given task
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @param executionCase BCET, ACET, WCET
+ * @param cpurta the instance of CPURtaIA class that calls this method
+ * (to access to the gpuToCpuLabels HashMap variable that contains List<Label> of required read & write labels)
+ * @return
+ * execution time of the observed task
+ */
+ private Time getExecutionTimeForGPUTaskOnCPU(final Task task, final List<Runnable> runnableList, final ProcessingUnit pu,
+ final TimeType executionCase, final CPURta cpurta) {
+ log.debug("TYPE: GPUTaskOnCPU // " + "Task: " + task.getName());
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Runnable funcRunnable = null;
+ for (final Runnable r : runnableList) {
+ final List<Ticks> thisTicksList = SoftwareUtil.getTicks(r, null);
+ if (thisTicksList.size() != 0) {
+ funcRunnable = r;
+ break;
+ }
+ }
+ final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
+ final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+ final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();
+ final List<List<Label>> thisLabelList = gtcl.get(task);
+ final List<Label> readLabelList = thisLabelList.get(0);
+ final List<Label> writeLabelList = thisLabelList.get(1);
+ for (final Label l : readLabelList) {
+ log.debug("Label(Read): " + l.getName() + " // (" + task.getName() + ")");
+ }
+ for (final Label l : writeLabelList) {
+ log.debug("Label(Write): " + l.getName() + " // (" + task.getName() + ")");
+ }
+ double readLatency = 0;
+ double writeLatency = 0;
+ if (executionCase.equals(TimeType.WCET)) {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+ } else if (executionCase.equals(TimeType.BCET)) {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+ } else {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+ }
+ /* Read (LabelAccess): */
+ double readAccessParameter = 0;
+ double sizeofReadLabels = 0;
+ for (final Label rl : readLabelList) {
+ sizeofReadLabels += rl.getSize().getNumberBytes();
+ }
+ readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / freq));
+ final Time readAccess = parameter.multiply(readAccessParameter);
+ result = result.add(readAccess); // LabelAccess(Read) added
+ /* Execution (Ticks): */
+ final List<Ticks> ticksList = SoftwareUtil.getTicks(funcRunnable, null);
+ for (final Ticks t : ticksList) {
+ final Time tickExecution = CommonUtils.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.4
+ result = result.add(tickExecution); // Execution(Ticks) added
+ }
+ /* Write (LabelAccess): */
+ double writeAccessParameter = 0;
+ double sizeofWriteLabels = 0;
+ for (final Label wl : writeLabelList) {
+ sizeofWriteLabels += wl.getSize().getNumberBytes();
+ }
+ writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / freq));
+ final Time writeAccess = parameter.multiply(writeAccessParameter);
+ result = result.add(writeAccess); // LabelAccess(Write) added
+ return result;
+ }
+
+ /**
+ * Calculate execution time of the given runnable.
+ * The method consider Read / Compute(Ticks) / Write semantic.
+ * @param runnable the observed runnable
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @param executionCase BCET, ACET, WCET
+ * @return
+ * execution time of the observed runnable
+ */
+ private Time getExecutionTimeForRTARunnable(final Runnable runnable, final ProcessingUnit pu, final TimeType executionCase) {
+ log.debug(executionCase.toString());
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+ double readLatency = 0;
+ double writeLatency = 0;
+ if (pu.getAccessElements().size() == 0) {
+ readLatency = 30; // Default value will be assigned
+ writeLatency = 30; // Default value of will be assigned
+ } else {
+ if (executionCase.equals(TimeType.WCET)) {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+ } else if (executionCase.equals(TimeType.BCET)) {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+ } else {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+ }
+ }
+ /* Read & Write Memory Access Time */
+ result = result.add(getRunnableMemoryAccessTime(runnable, freq, readLatency, writeLatency));
+ /* Execution (Ticks): */
+ final List<Ticks> ticksList = SoftwareUtil.getTicks(runnable, null);
+ for (final Ticks t : ticksList) {
+ final Time tickExecution = RuntimeUtil.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.5
+ result = result.add(tickExecution); // Execution(Ticks) added
+ }
+ return result;
+ }
+
+ /**
+ * Calculate memory access time of the observed task.
+ * Since this method is used by CPURta, the visibility should be 'public'
+ * @param task the observed task
+ * @param pu ProcessingUnit that would compute the given runnable (A57 or Denver)
+ * @param executionCase BCET, ACET, WCET
+ * @return
+ * memory access time of the observed task
+ */
+ public Time getTaskMemoryAccessTime(final Task task, final ProcessingUnit pu, final TimeType executionCase) {
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+ final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
+ double readLatency = 0;
+ double writeLatency = 0;
+ if (pu.getAccessElements().size() == 0) {
+ readLatency = 30; // Default value will be assigned
+ writeLatency = 30; // Default value of will be assigned
+ } else {
+ if (executionCase.equals(TimeType.WCET)) {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+ } else if (executionCase.equals(TimeType.BCET)) {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+ } else {
+ readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+ writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+ }
+ }
+ for (final Runnable r : runnableList) {
+ result = result.add(getRunnableMemoryAccessTime(r, freq, readLatency, writeLatency));
+ }
+ return result;
+ }
+
+ /**
+ * Calculate memory access time of the observed runnable.
+ * The method follows Read / Compute(Ticks) / Write semantic.
+ * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)
+ * @param runnable the observed runnable
+ * @param frequency frequency value of the Processing Unit
+ * @param readLatency readLatency value of the Processing Unit
+ * @param writeLatency writeLatency value of the Processing Unit
+ * @return
+ * memory access time of the observed runnable
+ */
+ public Time getRunnableMemoryAccessTime(final Runnable runnable, final double frequency, final double readLatency, final double writeLatency) {
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
+ final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(runnable, null);
+ final List<LabelAccess> readList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.READ)).collect(Collectors.toList());
+ final List<LabelAccess> writeList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.WRITE)).collect(Collectors.toList());
+ /* Read (LabelAccess): */
+ double readAccessParameter = 0;
+ double sizeofReadLabels = 0;
+ for (final LabelAccess rl : readList) {
+ sizeofReadLabels += rl.getData().getSize().getNumberBytes();
+ }
+ readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / frequency));
+ final Time readAccess = parameter.multiply(readAccessParameter);
+ result = result.add(readAccess); // LabelAccess(Read) added
+ /* Write (LabelAccess): */
+ double writeAccessParameter = 0;
+ double sizeofWriteLabels = 0;
+ for (final LabelAccess wl : writeList) {
+ sizeofWriteLabels += wl.getData().getSize().getNumberBytes();
+ }
+ writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / frequency));
+ final Time writeAccess = parameter.multiply(writeAccessParameter);
+ result = result.add(writeAccess); // LabelAccess(Write) added
+ return result;
+ }
+
+ /**
+ * Identify whether the given task has an InterProcessTrigger or not.
+ * @param task the observed task
+ * @return
+ * boolean value of the result
+ */
+ protected static boolean isTriggeringTask(final Task task) {
+ /* true: Triggering Task, false: Non-Triggering Task */
+ boolean result = false;
+ final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+ || call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+ final List<ActivityGraphItem> iptList = callList.stream().filter(s -> s instanceof InterProcessTrigger).collect(Collectors.toList());
+ if (iptList.size() != 0) {
+ result = true;
+ }
+ return result;
+ }
+
+ /******************************************* Implicit Communication Paradigm *************************************************/
+
+ /**
+ * For the implicit communication paradigm
+ * Time[0] = copy-in time for the observed task, Time[1] = copy-out time for the observed task
+ * if a GPU task mapped to CPU is passed here, we also need to consider its required labels from Pre-Pro processing runnables
+ * @param task the observed task
+ * @param pu the processing unit that the observed task is mapped to
+ * @param executionCase WCET, BCET, ACET
+ * @param cpurta the instance of CPURtaIA class that calls this method
+ * @return
+ * Time array that contains copy-in, copy-out time of the observed task
+ */
+ protected Time[] getLocalCopyTimeArray(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
+ final Time[] ta = new Time[2];
+ Time readCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time writeCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ /* The observed task is a GPU task */
+ if (cpurta.getGpuTaskList().contains(task)) {
+ final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();
+ final List<List<Label>> thisLabelList = gtcl.get(task);
+ final List<Label> readLabels = thisLabelList.get(0);
+ final List<Label> writeLabels = thisLabelList.get(1);
+ for (final Label rl : readLabels) {
+ readCopy = readCopy.add(this.getLocalCopyTime(rl, pu, executionCase, true));
+ }
+ ta[0] = readCopy;
+ for (final Label wl : writeLabels) {
+ writeCopy = writeCopy.add(this.getLocalCopyTime(wl, pu, executionCase, false));
+ }
+ ta[1] = writeCopy;
+ return ta;
+ }
+ /* The observed task is a CPU task */
+ final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
+ final List<Label> readList = new ArrayList<Label>();
+ final List<Label> writeList = new ArrayList<Label>();
+ for (int i = 0; i < runnableList.size(); i++) {
+ final Runnable runnable = runnableList.get(i);
+ final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
+ final List<Label> rList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.READ))
+ .map(s -> s.getData()).collect(Collectors.toList());
+ rList.stream().forEach(s -> readList.add(s));
+ final List<Label> wList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.WRITE))
+ .map(s -> s.getData()).collect(Collectors.toList());
+ wList.stream().forEach(s -> writeList.add(s));
+ }
+ final List<Label> readLabels = readList.stream().distinct().collect(Collectors.toList());
+ final List<Label> writeLabels = writeList.stream().distinct().collect(Collectors.toList());
+ for (final Label rl : readLabels) {
+ readCopy = readCopy.add(this.getLocalCopyTime(rl, pu, executionCase, true));
+ }
+ ta[0] = readCopy;
+ for (final Label wl : writeLabels) {
+ writeCopy = writeCopy.add(this.getLocalCopyTime(wl, pu, executionCase, false));
+ }
+ ta[1] = writeCopy;
+ return ta;
+ }
+
+ /**
+ * The method is used to calculate LocalCopy time for single label.
+ * @param label the observed label
+ * @param pu ProcessingUnit that would process the given label
+ * @param executionCase BCET, ACET, WCET
+ * @param readOrWrite when the given runnable is 'runnable_0'(the first callSquence of the task), it is read(true),
+ * when the given runnable is 'runnable_Last'(the last callSquence of the task), it is write(false).
+ * @return
+ * the given LocalCopy time
+ */
+ private Time getLocalCopyTime(final Label label, final ProcessingUnit pu, final TimeType executionCase, final boolean readOrWrite) {
+ Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
+ final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+ double latency = 0;
+ /* Read */
+ if (readOrWrite) {
+ if (executionCase.equals(TimeType.BCET)) {
+ latency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+ } else if (executionCase.equals(TimeType.ACET)) {
+ latency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+ } else if (executionCase.equals(TimeType.WCET)) {
+ latency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+ }
+ }
+ /* Write */
+ else {
+ if (executionCase.equals(TimeType.BCET)) {
+ latency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+ } else if (executionCase.equals(TimeType.ACET)) {
+ latency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+ } else if (executionCase.equals(TimeType.WCET)) {
+ latency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+ }
+ }
+ double labelAccessParameter = 0;
+ final double labelSize = label.getSize().getNumberBytes();
+ labelAccessParameter = (Math.ceil(labelSize / 64.0) * (latency / freq));
+ final Time labelAccess = parameter.multiply(labelAccessParameter);
+ result = result.add(labelAccess); // LabelAccess(Read) added
+ return result;
+ }
}
\ No newline at end of file
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java
index 8e8a72e..e763bd8 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java
@@ -16,21 +16,26 @@
import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
public class SharedConsts {
+
+ public static int RUNTIMESEC = 2 * 60 * 60;
+
/*-----------Measurement Configuration--------------–*/
public static TimeType timeType = TimeType.WCET;
public static boolean onlyWrittenLabelsCE = true;
public static boolean synchronousOffloading = false;
public static boolean useModelTimeSlices = false;
- public static boolean ignoreInfeasibility = true;
+ public static boolean ignoreInfeasibility = false;
public static int[] timeSlices;
public static long timeSliceLengthPS = 1000000000l;
- public static final boolean levelIBusyPeriod = false;
+ public static boolean levelIBusyPeriod = false;
public static TS_DERIV tsDeriv = TS_DERIV.TSxPrio;
public static OPT_TYPE optimize = OPT_TYPE.RESPONSETIMESUM;
+ public static final boolean considerGlobalBlocking = false;
+ public static final boolean considerLocalBlocking = false;
+ public static boolean offsetCPURTA = true;
+ public static final boolean zeroHigh = true;
/*-----------End Measur. Configuration--------------–*/
- /* Arbitrary Integer Array (GA scenario) */
- public static final int[] defaultIAMapping = new int[] { 4, 1, 1, 3, 4, 0, 3, 3, 3, 0, 6, 2, 5, 6 };
public enum OPT_TYPE {
TASKCHAINS, RESPONSETIMESUM, LOADBALANCING
@@ -47,4 +52,8 @@
public enum ComParadigm {
DIRECT, IMPLICIT
}
-}
\ No newline at end of file
+
+ public enum SINGLE_CASE {
+ BCLAT, WCLAT, CRITICAL
+ }
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
index f71f927..19d822d 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
@@ -1,1057 +1,1057 @@
-/*******************************************************************************
- * 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: Junhyung Ki - initial API and implementation
- *
- *******************************************************************************/
-package org.eclipse.app4mc.gsoc_rta.ui;
-
-import java.awt.Color;
-import java.awt.EventQueue;
-import java.awt.Font;
-import java.awt.List;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.math.BigInteger;
-import java.util.HashMap;
-import java.util.stream.Collectors;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JFrame;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JRadioButton;
-import javax.swing.JTextField;
-
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.eclipse.app4mc.amalthea.model.Amalthea;
-import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
-import org.eclipse.app4mc.amalthea.model.EventChain;
-import org.eclipse.app4mc.amalthea.model.Label;
-import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
-import org.eclipse.app4mc.amalthea.model.PuType;
-import org.eclipse.app4mc.amalthea.model.Task;
-import org.eclipse.app4mc.amalthea.model.Time;
-import org.eclipse.app4mc.amalthea.model.TimeUnit;
-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.gsoc_rta.*;
-import org.eclipse.app4mc.gsoc_rta.SharedConsts.ComParadigm;
-import org.eclipse.emf.common.util.EList;
-import javax.swing.SwingConstants;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.JSeparator;
-
-/**
- * Date: August 21-2019
- * @author Junhyung Ki
- * @version 1.0
- * The purpose of this class is to provide users a better visual and increase usability of Response Time Analysis.
- */
-@SuppressWarnings("serial")
-public class APP4RTA extends JFrame {
- private static JComboBox<String> ecComboBox = new JComboBox<String>();
-
- private CPURta cpurta = new CPURta();
- private E2ELatency e2e = new E2ELatency();
- private Amalthea currentModel = null;
- private java.util.List<ProcessingUnit> currentPUList = null;
- private int[] currentIA = null;
- private EList<Task> allTaskList = null;
- private EList<EventChain> currentECList = null;
- private EventChain currentEC = null;
- private java.util.List<Task> currentTaskChain = null;
- private File currentFile = null;
-
- private HashMap<Integer, java.util.List<Task>> puTaskListHM;
- private JFrame frame;
- private int selectedECIndex = -1;
- private boolean schedulability_flag = false;
- private ComParadigm currentParadigm = null;
- JFileChooser fileChooser;
- JTextField selectedModelLbl;
-
- private JLabel jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10,
- jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19;
- private JTextField tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9,
- tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19;
- private JLabel[] jLabelArray = {
- jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10,
- jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19
- };
- private JTextField[] jTextFieldArray= {
- tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9,
- tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19
- };
-
- private JLabel jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7;
- private JLabel jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h;
- private List l0, l1, l2, l3, l4, l5, l6, l7;
- private List rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7;
- private JLabel[] puLabelArray = {
- jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7
- };
- private JLabel[] rtListLabelArray = {
- jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h
- };
- private List[] puListArray = {
- l0, l1, l2, l3, l4, l5, l6, l7
- };
- private List[] rtListArray = {
- rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7
- };
-
- private JLabel ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6,
- ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13;
- private JTextField jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,
- jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13;
- private JLabel[] ecLabelArray = {
- ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6,
- ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13
- };
- private JTextField[] ecJTPArray = {
- jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,
- jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13
- };
-
- private List list, list_1, list_2;
-
- public static void main(String[] args) {
- EventQueue.invokeLater(new Runnable() {
- public void run() {
- org.apache.log4j.BasicConfigurator.configure();
- Logger.getRootLogger().setLevel(Level.ERROR);
- final APP4RTA window = new APP4RTA();
- window.frame.setVisible(true);
- window.frame.setTitle("APP4RTA");
- }
- });
- }
-
- public APP4RTA() {
- initialize();
- }
-
- private void initialize() {
- frame = new JFrame();
- frame.getContentPane().setFont(new Font("Sitka Small", Font.PLAIN, 13));
- frame.setBounds(0, 31, 1200, 1027);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.getContentPane().setLayout(null);
-
- JLabel lblSelectTheModel = new JLabel("Amalthea Model");
- lblSelectTheModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));
- lblSelectTheModel.setBounds(10, 13, 120, 22);
- frame.getContentPane().add(lblSelectTheModel);
-
- JLabel lblTaskName = new JLabel("Task Name");
- lblTaskName.setForeground(new Color(139, 0, 0));
- lblTaskName.setFont(new Font("Sitka Heading", Font.BOLD, 12));
- lblTaskName.setHorizontalAlignment(SwingConstants.CENTER);
- lblTaskName.setBounds(15, 43, 70, 16);
- frame.getContentPane().add(lblTaskName);
-
- JLabel lblPuNum = new JLabel("PU Num");
- lblPuNum.setForeground(new Color(0, 0, 255));
- lblPuNum.setHorizontalAlignment(SwingConstants.CENTER);
- lblPuNum.setFont(new Font("Sitka Heading", Font.BOLD, 12));
- lblPuNum.setBounds(92, 43, 70, 16);
- frame.getContentPane().add(lblPuNum);
-
- JButton btnDefualtIa = new JButton("Defualt IA");
- btnDefualtIa.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- if (cpurta.getModel() == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: A model is not loaded.");
- return ;
- } else if (cpurta.getTRT() == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: TRT HashMap is not loaded.");
- return ;
- } else if (cpurta.getPUl().size() == 0) {
- JOptionPane.showMessageDialog(frame, "ERROR: Processing Unit List is not loaded.");
- return ;
- }
- final int[] defaultIA = SharedConsts.defaultIAMapping;
- if (cpurta.getModel().getSwModel().getTasks().size() == defaultIA.length) {
- for (int i = 0; i < defaultIA.length; i++) {
- jTextFieldArray[i].setText("" + defaultIA[i]);
- }
- return ;
- } else if (currentPUList.size() == 1) {
- final int numOfTasks = cpurta.getModel().getSwModel().getTasks().size();
- for (int i = 0; i < numOfTasks; i++) {
- jTextFieldArray[i].setText("0");
- }
- return ;
- }
- String str = "";
- for (int i = 0; i < currentPUList.size(); i++) {
- if (i == currentPUList.size() - 1) {
- str = str + i;
- break;
- }
- str = str + i + ", ";
- }
- JOptionPane.showMessageDialog(frame, "ERROR: The length of the default integer array does not match with\n"
- + "the number of tasks in the target model.\n\n" + "Please assign the number(s) manually.\n"
- + "Available PU number(s): " + str);
- }
- });
-
- JButton btnEnterIA = new JButton("Enter IA");
- btnEnterIA.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- currentIA = new int[cpurta.getModel().getSwModel().getTasks().size()];
- for (int i = 0; i < allTaskList.size(); i++) {
- if (jTextFieldArray[i].getText().length() == 0) {
- JOptionPane.showMessageDialog(frame, "ERROR: Fill the rest of the array!");
- return ;
- } else if (jTextFieldArray[i].getText().charAt(0) < 48 || jTextFieldArray[i].getText().charAt(0) > 54) {
- JOptionPane.showMessageDialog(frame, "ERROR: Wrong array value!");
- return ;
- } else if (i >= 0 && i <= 9 && Integer.parseInt(jTextFieldArray[i].getText()) == 6) {
- JOptionPane.showMessageDialog(frame, "ERROR: CPU Tasks should not be mapped to GPU! \n\n"
- + "Please assign different IA value for " + "(" + allTaskList.get(i).getName() + ")");
- return ;
- } else if (i == jTextFieldArray.length-1 && Integer.parseInt(jTextFieldArray[i].getText()) != 6) {
- JOptionPane.showMessageDialog(frame, "ERROR: 'Detection' task can not be mapped to CPU!");
- return ;
- }
- currentIA[i] = Integer.parseInt(jTextFieldArray[i].getText());
- }
- cpurta.setIA(currentIA);
- cpurta.setContention(currentIA, currentModel);
- puTaskListHM = cpurta.be_getPUTaskListHashMap(currentModel);
- for (int i = 0; i < puTaskListHM.size(); i++) {
- if (puListArray[i].getItemCount() == 0) {
- for (int j = 0; j < puTaskListHM.get(i).size(); j++) {
- puListArray[i].add((puTaskListHM.get(i).get(j)).getName());
- }
- }
- }
- }
- });
-
- JRadioButton rdbtnSynchronous = new JRadioButton("Synchronous");
- rdbtnSynchronous.setForeground(new Color(139, 0, 0));
- rdbtnSynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));
-
- JRadioButton rdbtnAsynchronous = new JRadioButton("Asynchronous");
- rdbtnAsynchronous.setForeground(new Color(0, 0, 255));
- rdbtnAsynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));
-
- ButtonGroup offloadingMode = new ButtonGroup();
- offloadingMode.add(rdbtnSynchronous);
- offloadingMode.add(rdbtnAsynchronous);
-
- JRadioButton rdbtnWorstCase = new JRadioButton("Worst-Case");
- rdbtnWorstCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
- rdbtnWorstCase.setForeground(Color.DARK_GRAY);
-
- JRadioButton rdbtnAverageCase = new JRadioButton("Average-Case");
- rdbtnAverageCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
- rdbtnAverageCase.setForeground(Color.DARK_GRAY);
-
- JRadioButton rdbtnBestCase = new JRadioButton("Best-Case");
- rdbtnBestCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
- rdbtnBestCase.setForeground(Color.DARK_GRAY);
-
- ButtonGroup executionMode = new ButtonGroup();
- executionMode.add(rdbtnWorstCase);
- executionMode.add(rdbtnAverageCase);
- executionMode.add(rdbtnBestCase);
-
- JLabel lblSchedulability = new JLabel("Schedulability");
- JTextField schedulability = new JTextField();
- schedulability.setHorizontalAlignment(SwingConstants.RIGHT);
- schedulability.setEditable(false);
-
- JLabel lblMemAccCost = new JLabel("Cumulated Memory-Access Cost");
- JTextField memAccCost = new JTextField();
- memAccCost.setHorizontalAlignment(SwingConstants.RIGHT);
- memAccCost.setEditable(false);
-
- JLabel lblCumulContention = new JLabel("Cumulated Contention");
- JTextField cumulContention = new JTextField();
- cumulContention.setHorizontalAlignment(SwingConstants.RIGHT);
- cumulContention.setEditable(false);
-
- JLabel lblComputation = new JLabel("Computation");
- JTextField computation = new JTextField();
- computation.setHorizontalAlignment(SwingConstants.RIGHT);
- computation.setEditable(false);
-
- JLabel lblResponseTimeSum = new JLabel("Response Time Sum");
- JTextField rtSum = new JTextField();
- rtSum.setHorizontalAlignment(SwingConstants.RIGHT);
- rtSum.setEditable(false);
-
- JButton btnCalculate = new JButton("Calculate");
- btnCalculate.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- for (int i = 0; i < allTaskList.size(); i++) {
- if (jTextFieldArray[i].getText().length() == 0) {
- JOptionPane.showMessageDialog(frame, "ERROR: Fill the array first!");
- return ;
- }
- }
- if (rdbtnSynchronous.isSelected()) {
- SharedConsts.synchronousOffloading = true;
- } else if (rdbtnAsynchronous.isSelected()) {
- SharedConsts.synchronousOffloading = false;
- } else {
- JOptionPane.showMessageDialog(frame, "ERROR: You should choose an offloading mode! (Sync / Async)");
- return ;
- }
- if (rdbtnWorstCase.isSelected()) {
- SharedConsts.timeType = TimeType.WCET;
- } else if (rdbtnAverageCase.isSelected()) {
- SharedConsts.timeType = TimeType.ACET;
- } else if (rdbtnBestCase.isSelected()) {
- SharedConsts.timeType = TimeType.BCET;
- } else {
- JOptionPane.showMessageDialog(frame, "ERROR: You should choose an execution case! (Worst Case / Average Case / Best Case)");
- return ;
- }
- if (currentIA == null || puTaskListHM.size() == 0) {
- JOptionPane.showMessageDialog(frame, "ERROR: Click the 'Enter IA' button.");
- return ;
- }
- schedulability_flag = true;
- Time pRtSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- for (int i = 0; i < puTaskListHM.size(); i++) {
- final ProcessingUnit pu = cpurta.getPUl().get(i);
- final java.util.List<Task> thisPUTaskList = puTaskListHM.get(i);
- Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- if (rtListArray[i].getItemCount() == 0) {
- if (pu.getDefinition().getPuType().equals(PuType.CPU)) {
- for (Task t : thisPUTaskList) {
- thisRT = cpurta.preciseTestCPURT(t, thisPUTaskList, SharedConsts.timeType, pu);
- final Time thisPeriod = CommonUtils.getStimInTime(t);
- final BigInteger period = AmaltheaServices.convertToPicoSeconds(thisPeriod);
- if (AmaltheaServices.convertToPicoSeconds(thisRT).compareTo(period) > 0) {
- rtListArray[i].add("Non Scheduleable! => MAX Value");
- schedulability_flag = false;
- } else if (AmaltheaServices.convertToPicoSeconds(thisRT).equals(BigInteger.ZERO)) {
- rtListArray[i].add("0 ps (GPU Task on CPU)");
- } else {
- rtListArray[i].add(thisRT.toString());
- }
- pRtSum = pRtSum.add(thisRT);
- }
- } else {
- for (Task t : thisPUTaskList) {
- thisRT = cpurta.getTRT().get(t);
- rtListArray[i].add(thisRT.toString());
- pRtSum = pRtSum.add(thisRT);
- }
- }
- }
- }
- if (schedulability_flag) {
- schedulability.setText("Scheduleable! :)");
- memAccCost.setText("" + cpurta.getCumulatedMemAccCosts());
- cumulContention.setText("" + cpurta.getCumulatedContention());
- computation.setText("" + (pRtSum.subtract(cpurta.getCumulatedMemAccCosts())).subtract(cpurta.getCumulatedContention()));
- rtSum.setText(pRtSum.toString());
- } else {
- schedulability.setText("Non Scheduleable! :(");
- memAccCost.setText("Not Available.");
- cumulContention.setText("Not Available.");
- computation.setText("Not Available.");
- rtSum.setText("Not Available.");
- }
- }
- });
-
- JButton btnReset = new JButton("Reset");
- btnReset.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- currentIA = null;
- cpurta.setIA(currentIA);
- cpurta.setContention(currentIA, currentModel);
- /* latency time initializing */
- cpurta.initCumulatedMemAccCosts();
- cpurta.initCumulatedContention();
- for (int i = 0; i < allTaskList.size(); i++) {
- jTextFieldArray[i].setText("");
- }
- for (int i = 0; i < currentPUList.size(); i++) {
- puListArray[i].removeAll();
- }
- for (int i = 0; i < currentPUList.size(); i++) {
- rtListArray[i].removeAll();
- }
- offloadingMode.setSelected(null, false);
- executionMode.setSelected(null, false);
- schedulability.setText(null);
- memAccCost.setText(null);
- cumulContention.setText(null);
- computation.setText(null);
- rtSum.setText(null);
- currentIA = null;
- puTaskListHM = null;
- frame.revalidate();
- frame.repaint();
- }
- });
-
- selectedModelLbl = new JTextField();
- selectedModelLbl.setEditable(false);
- selectedModelLbl.setBounds(142, 13, 206, 22);
- frame.getContentPane().add(selectedModelLbl);
- selectedModelLbl.setColumns(10);
-
- JButton amaltheaSchBtn = new JButton("Search Amalthea");
- amaltheaSchBtn.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- final String userDirLocation = System.getProperty("user.dir");
- File userDir = new File(userDirLocation);
- fileChooser = new JFileChooser(userDir);
- fileChooser.setAcceptAllFileFilterUsed(false);
- FileNameExtensionFilter filter = new FileNameExtensionFilter("Amalthea models", "amxmi");
- fileChooser.addChoosableFileFilter(filter);
- fileChooser.setDialogTitle("Open File");
- int result = fileChooser.showOpenDialog(null);
- if (result == JFileChooser.APPROVE_OPTION) {
- final Amalthea loadedModel = AmaltheaLoader.loadFromFile(fileChooser.getSelectedFile());
- if (loadedModel.getVersion().compareTo("0.9.4") != 0) {
- JOptionPane.showMessageDialog(frame, "Error: This model should be migrated to the version 0.9.4");
- return ;
- }
- /* Something was selected before */
- if (currentFile != null) {
- /* The selected file is equal to the previous file => Do nothing */
- if (fileChooser.getSelectedFile().equals(currentFile)) {
- JOptionPane.showMessageDialog(frame, "Same Model");
- return ;
- }
- /* If the selected file is different to the previous one => Remove and Do Normal. */
- else {
- schedulability.setText(null);
- memAccCost.setText(null);
- cumulContention.setText(null);
- computation.setText(null);
- rtSum.setText(null);
- for (int i = 0; i < allTaskList.size(); i++) {
- frame.remove(jLabelArray[i]);
- frame.remove(jTextFieldArray[i]);
- }
- frame.remove(btnDefualtIa);
- frame.remove(btnEnterIA);
- frame.remove(rdbtnSynchronous);
- frame.remove(rdbtnAsynchronous);
- frame.remove(rdbtnWorstCase);
- frame.remove(rdbtnAverageCase);
- frame.remove(rdbtnBestCase);
- frame.remove(btnCalculate);
- frame.remove(btnReset);
- frame.remove(lblSchedulability);
- frame.remove(schedulability);
- frame.remove(lblMemAccCost);
- frame.remove(memAccCost);
- frame.remove(lblCumulContention);
- frame.remove(cumulContention);
- frame.remove(lblComputation);
- frame.remove(computation);
- frame.remove(lblResponseTimeSum);
- frame.remove(rtSum);
- for (int i = 0; i < currentPUList.size(); i++) {
- frame.remove(puLabelArray[i]);
- frame.remove(rtListLabelArray[i]);
- frame.remove(puListArray[i]);
- frame.remove(rtListArray[i]);
- }
- frame.remove(ecComboBox);
- }
- }
- /* Something was not selected before => Do normal */
- currentFile = fileChooser.getSelectedFile();
- selectedModelLbl.setText(currentFile.getName());
- currentModel = loadedModel;
- currentPUList = CommonUtils.getPUs(currentModel);
- if (currentPUList.get(0).getAccessElements().size() == 0) {
- JOptionPane.showMessageDialog(frame, "The selected model's processing unit(s) does(do) not have 'read & write Latency' values.\n\n"
- + "Therefore, the default value of 30 will be assigned for them.\n"
- + "This will affect the response time results.");
- }
- cpurta.setModel(currentModel);
- cpurta.setTRT(cpurta.getDefaultTRT(currentModel));
- cpurta.setPUl(currentPUList);
- allTaskList = currentModel.getSwModel().getTasks();
- if (allTaskList.size() > 20) {
- JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + allTaskList.size() + " Tasks. (Limit: 20)\n"
- + "Please choose a different model.");
- return ;
- } else if (currentPUList.size() > 8) {
- JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + currentPUList.size() + " Processing Units. (Limit: 8)\n"
- + "Please choose a different model.");
- return ;
- }
- /* Task Indices */
- for (int i = 0; i < allTaskList.size(); i++) {
- jLabelArray[i] = new JLabel(allTaskList.get(i).getName());
- jLabelArray[i].setBounds(12, (60+(i*24)), 97, 16);
- frame.getContentPane().add(jLabelArray[i]);
- jTextFieldArray[i] = new JTextField();
- jTextFieldArray[i].setColumns(10);
- jTextFieldArray[i].setBounds(118, (60+(i*24)), 22, 22);
- frame.getContentPane().add(jTextFieldArray[i]);
- }
- /* DefaultIA Button */
- btnDefualtIa.setBounds(155, 60, 97, 25);
- frame.getContentPane().add(btnDefualtIa);
- /* EnterIA Button */
- btnEnterIA.setBounds(155, 90, 97, 25);
- frame.getContentPane().add(btnEnterIA);
- /* Sync Radio Button */
- rdbtnSynchronous.setBounds(152, 125, 126, 25);
- frame.getContentPane().add(rdbtnSynchronous);
- /* Async Radio Button */
- rdbtnAsynchronous.setBounds(152, 145, 126, 25);
- frame.getContentPane().add(rdbtnAsynchronous);
- /* WorstCase Radio Button */
- rdbtnWorstCase.setBounds(152, 175, 107, 25);
- frame.getContentPane().add(rdbtnWorstCase);
- /* AverageCase Radio Button */
- rdbtnAverageCase.setBounds(152, 195, 107, 25);
- frame.getContentPane().add(rdbtnAverageCase);
- /* BestCase Radio Button */
- rdbtnBestCase.setBounds(152, 215, 107, 25);
- frame.getContentPane().add(rdbtnBestCase);
- /* Calculate Button */
- btnCalculate.setBounds(155, 252, 97, 25);
- frame.getContentPane().add(btnCalculate);
- /* Reset Button */
- btnReset.setBounds(155, 282, 97, 25);
- frame.getContentPane().add(btnReset);
- /* Schedulability Label & TextField */
- lblSchedulability.setBounds(157, 323, 200, 16);
- frame.getContentPane().add(lblSchedulability);
- schedulability.setBounds(155, 343, 200, 22);
- frame.getContentPane().add(schedulability);
- /* MemAccCost Label & TextField */
- lblMemAccCost.setBounds(157, 368, 200, 16);
- frame.getContentPane().add(lblMemAccCost);
- memAccCost.setBounds(155, 388, 200, 22);
- frame.getContentPane().add(memAccCost);
- /* CumulContention Label & TextField */
- lblCumulContention.setBounds(157, 413, 200, 16);
- frame.getContentPane().add(lblCumulContention);
- cumulContention.setBounds(155, 433, 200, 22);
- frame.getContentPane().add(cumulContention);
- /* Computation */
- lblComputation.setBounds(157, 458, 200, 16);
- frame.getContentPane().add(lblComputation);
- computation.setBounds(155, 478, 200, 22);
- frame.getContentPane().add(computation);
- /* ResponseTime Sum Label & TextField */
- lblResponseTimeSum.setBounds(157, 503, 200, 16);
- frame.getContentPane().add(lblResponseTimeSum);
- rtSum.setBounds(155, 523, 200, 22);
- frame.getContentPane().add(rtSum);
- /* PU & RT Lists */
- for (int i = 0; i < currentPUList.size(); i++) {
- puLabelArray[i] = new JLabel(i +": " + currentPUList.get(i).getDefinition().getName());
- rtListLabelArray[i] = new JLabel("Response Time");
- puListArray[i] = new List();
- rtListArray[i] = new List();
- if (i >= 0 && i < 4) {
- puLabelArray[i].setBounds((387+(i*200)), 50, 87, 22);
- rtListLabelArray[i].setBounds((474+(i*200)), 50, 88, 22);
- puListArray[i].setBounds((385+(i*200)), 75, 87, 145);
- rtListArray[i].setBounds((475+(i*200)), 75, 87, 145);
- } else if (i >= 4) {
- puLabelArray[i].setBounds((387+((i-4)*200)), 225, 87, 22);
- rtListLabelArray[i].setBounds((474+((i-4)*200)), 225, 88, 22);
- puListArray[i].setBounds((385+((i-4)*200)), 250, 87, 145);
- rtListArray[i].setBounds((475+((i-4)*200)), 250, 87, 145);
- }
- frame.getContentPane().add(puLabelArray[i]);
- frame.getContentPane().add(rtListLabelArray[i]);
- frame.getContentPane().add(puListArray[i]);
- frame.getContentPane().add(rtListArray[i]);
- }
- /* E2ELatency Part */
- currentECList = currentModel.getConstraintsModel().getEventChains();
- if (currentECList.size() != 0) {
- final String[] ecComboArray = new String[currentECList.size()];
- for (int i = 0; i < currentECList.size(); i++) {
- ecComboArray[i] = currentECList.get(i).getName();
- }
- ecComboBox = new JComboBox<String>(ecComboArray);
- ecComboBox.setBounds(150, 570, 206, 22);
- frame.getContentPane().add(ecComboBox);
- ecComboBox.setSelectedItem(null);
- } else {
- JOptionPane.showMessageDialog(frame, "WARNING: The selected model has no Event-Chain.\n"
- + "End-to-End Event-Chain Latency Calculation is impossible with this model.");
- // TODO: Something needs to be done here to prevent E2ELatency calculation.
- }
- frame.revalidate();
- frame.repaint();
- }
- }
- });
- amaltheaSchBtn.setBounds(348, 12, 133, 24);
- frame.getContentPane().add(amaltheaSchBtn);
-
- JLabel lblEventChainModel = new JLabel("EVENT CHAIN MODEL");
- lblEventChainModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));
- lblEventChainModel.setBounds(10, 570, 136, 22);
- frame.getContentPane().add(lblEventChainModel);
-
- JRadioButton rdbtnDirect = new JRadioButton("Direct");
- rdbtnDirect.setForeground(new Color(139, 0, 0));
- rdbtnDirect.setFont(new Font("Sitka Heading", Font.BOLD, 13));
- rdbtnDirect.setBounds(530, 569, 70, 25);
- frame.getContentPane().add(rdbtnDirect);
-
- JRadioButton rdbtnImplicit = new JRadioButton("Implicit");
- rdbtnImplicit.setForeground(new Color(0, 0, 255));
- rdbtnImplicit.setFont(new Font("Sitka Heading", Font.BOLD, 13));
- rdbtnImplicit.setBounds(596, 569, 79, 25);
- frame.getContentPane().add(rdbtnImplicit);
-
- ButtonGroup paradigmMode = new ButtonGroup();
- paradigmMode.add(rdbtnDirect);
- paradigmMode.add(rdbtnImplicit);
-
- JLabel lblNewLabel = new JLabel("Direct & Implicit Communication Paradigm");
- lblNewLabel.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
- lblNewLabel.setBounds(10, 605, 293, 16);
- frame.getContentPane().add(lblNewLabel);
-
- JLabel lblWorstcaseReaction = new JLabel("WC Reaction");
- lblWorstcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);
- lblWorstcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblWorstcaseReaction.setBounds(10, 627, 90, 16);
- frame.getContentPane().add(lblWorstcaseReaction);
-
- JTextField txtField0 = new JTextField();
- txtField0.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField0.setBounds(103, 625, 200, 22);
- txtField0.setEditable(false);
- frame.getContentPane().add(txtField0);
-
- JLabel lblBestcaseReaction = new JLabel("BC Reaction");
- lblBestcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblBestcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);
- lblBestcaseReaction.setBounds(10, 656, 90, 16);
- frame.getContentPane().add(lblBestcaseReaction);
-
- JTextField txtField1 = new JTextField();
- txtField1.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField1.setBounds(103, 654, 200, 22);
- txtField1.setEditable(false);
- frame.getContentPane().add(txtField1);
-
- JLabel lblLetCommunicationParadigm = new JLabel("LET Communication Paradigm");
- lblLetCommunicationParadigm.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
- lblLetCommunicationParadigm.setBounds(10, 688, 193, 16);
- frame.getContentPane().add(lblLetCommunicationParadigm);
-
- JLabel lblWcReaction = new JLabel("WC Reaction");
- lblWcReaction.setHorizontalAlignment(SwingConstants.CENTER);
- lblWcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblWcReaction.setBounds(10, 710, 90, 16);
- frame.getContentPane().add(lblWcReaction);
-
- JTextField txtField2 = new JTextField();
- txtField2.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField2.setBounds(103, 708, 200, 22);
- txtField2.setEditable(false);
- frame.getContentPane().add(txtField2);
-
- JLabel lblBcReaction = new JLabel("BC Reaction");
- lblBcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblBcReaction.setHorizontalAlignment(SwingConstants.CENTER);
- lblBcReaction.setBounds(10, 739, 90, 16);
- frame.getContentPane().add(lblBcReaction);
-
- JTextField txtField3 = new JTextField();
- txtField3.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField3.setBounds(103, 737, 200, 22);
- txtField3.setEditable(false);
- frame.getContentPane().add(txtField3);
-
- JLabel lblTaskChain = new JLabel("Task Chain Age (Direct & Implicit)");
- lblTaskChain.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
- lblTaskChain.setBounds(338, 605, 222, 16);
- frame.getContentPane().add(lblTaskChain);
-
- JLabel lblWcAge = new JLabel("WC Age");
- lblWcAge.setHorizontalAlignment(SwingConstants.CENTER);
- lblWcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblWcAge.setBounds(350, 627, 58, 16);
- frame.getContentPane().add(lblWcAge);
-
- JTextField txtField4 = new JTextField();
- txtField4.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField4.setBounds(413, 625, 200, 22);
- txtField4.setEditable(false);
- frame.getContentPane().add(txtField4);
-
- JLabel lblBcAge = new JLabel("BC Age");
- lblBcAge.setHorizontalAlignment(SwingConstants.CENTER);
- lblBcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblBcAge.setBounds(350, 656, 58, 16);
- frame.getContentPane().add(lblBcAge);
-
- JTextField txtField5 = new JTextField();
- txtField5.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField5.setBounds(413, 654, 200, 22);
- txtField5.setEditable(false);
- frame.getContentPane().add(txtField5);
-
- JLabel lblEarlyReaction = new JLabel("Early Reaction (Direct & Implicit)");
- lblEarlyReaction.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
- lblEarlyReaction.setBounds(338, 688, 232, 16);
- frame.getContentPane().add(lblEarlyReaction);
-
- JLabel lblWcErct = new JLabel("WC E-Rct");
- lblWcErct.setHorizontalAlignment(SwingConstants.CENTER);
- lblWcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblWcErct.setBounds(338, 710, 70, 16);
- frame.getContentPane().add(lblWcErct);
-
- JTextField txtField6 = new JTextField();
- txtField6.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField6.setBounds(413, 708, 200, 22);
- txtField6.setEditable(false);
- frame.getContentPane().add(txtField6);
-
- JLabel lblBcErct = new JLabel("BC E-Rct");
- lblBcErct.setHorizontalAlignment(SwingConstants.CENTER);
- lblBcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblBcErct.setBounds(338, 739, 70, 16);
- frame.getContentPane().add(lblBcErct);
-
- JTextField txtField7 = new JTextField();
- txtField7.setHorizontalAlignment(SwingConstants.RIGHT);
- txtField7.setBounds(413, 737, 200, 22);
- txtField7.setEditable(false);
- frame.getContentPane().add(txtField7);
-
- JLabel lblDataAge = new JLabel("Data Age");
- lblDataAge.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
- lblDataAge.setBounds(10, 771, 58, 16);
- frame.getContentPane().add(lblDataAge);
-
- JLabel lblContainedLabels = new JLabel("Contained Labels");
- lblContainedLabels.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblContainedLabels.setBounds(10, 791, 136, 16);
- frame.getContentPane().add(lblContainedLabels);
-
- list = new List();
- list.setBounds(10, 810, 155, 160);
- frame.getContentPane().add(list);
-
- JLabel lblWorstcaseAge = new JLabel("Worst-case Age");
- lblWorstcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblWorstcaseAge.setBounds(177, 791, 136, 16);
- frame.getContentPane().add(lblWorstcaseAge);
-
- list_1 = new List();
- list_1.setBounds(177, 810, 155, 160);
- frame.getContentPane().add(list_1);
-
- JLabel lblBestcaseAge = new JLabel("Best-case Age");
- lblBestcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
- lblBestcaseAge.setBounds(344, 791, 136, 16);
- frame.getContentPane().add(lblBestcaseAge);
-
- list_2 = new List();
- list_2.setBounds(344, 810, 155, 160);
- frame.getContentPane().add(list_2);
-
- JButton ecSelect = new JButton("Calculate");
- ecSelect.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- if (currentModel == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");
- return ;
- } else if (currentECList == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Event-Chain List is empty somehow.");
- return ;
- } else if (currentECList.size() == 0) {
- JOptionPane.showMessageDialog(frame, "ERROR: There is no Event-Chain in this model.");
- return ;
- } else if (ecComboBox.getSelectedItem() == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");
- return ;
- } else if (puTaskListHM == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been assigned.");
- return ;
- } else if (offloadingMode.getSelection() == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Choose an offloading mode. (Sync / Async)");
- return ;
- } else if (schedulability_flag == false) {
- String offMode = null;
- if (SharedConsts.synchronousOffloading == true) {
- offMode = "Sync";
- } else if (SharedConsts.synchronousOffloading == false) {
- offMode = "Aync";
- }
- String tType = null;
- if (SharedConsts.timeType.equals(TimeType.WCET)) {
- tType = "WC";
- } else if (SharedConsts.timeType.equals(TimeType.ACET)) {
- tType = "AC";
- } else if (SharedConsts.timeType.equals(TimeType.BCET)) {
- tType = "BC";
- }
- String iaFeedback = "";
- for (int i = 0; i < currentIA.length; i++) {
- if (i == currentIA.length - 1) {
- iaFeedback = iaFeedback + currentIA[i];
- } else {
- iaFeedback = iaFeedback + currentIA[i] + ", ";
- }
- }
- JOptionPane.showMessageDialog(frame, "ERROR: The entered IA value is not schedulable with the current configuration.\n\n"
- + "Current Integer Arrary: { " + iaFeedback + " }\n\n"
- + "Current Configuration: Offloading Mode(" + offMode + "), ExecutionCase(" + tType + ")");
- return ;
- } else if (paradigmMode.getSelection() == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Choose a communication paradigm. (Direct / Implicit)");
- return ;
- }
- final int thisIndex = ecComboBox.getSelectedIndex();
- /* Something was selected before */
- if (selectedECIndex != -1) {
- /* If the selected Event-Chain is the same as before => Do Nothing */
- if (selectedECIndex == thisIndex) {
- if (currentParadigm != null) {
- ComParadigm changedParadigm = null;
- if (rdbtnDirect.isSelected()) {
- changedParadigm = ComParadigm.DIRECT;
- } else if (rdbtnImplicit.isSelected()) {
- changedParadigm = ComParadigm.IMPLICIT;
- }
- if (currentParadigm.equals(changedParadigm)) {
- JOptionPane.showMessageDialog(frame, "Same Paradigm & Same Event-Chain.");
- return ;
- }
- for (int i = 0; i < currentTaskChain.size(); i++) {
- frame.remove(ecLabelArray[i]);
- frame.remove(ecJTPArray[i]);
- }
- }
- }
- /* If the selected Event-Chain is different to the previous one => Remove and Do Normal. */
- else if (selectedECIndex != thisIndex) {
- for (int i = 0; i < currentTaskChain.size(); i++) {
- frame.remove(ecLabelArray[i]);
- frame.remove(ecJTPArray[i]);
- }
- selectedECIndex = thisIndex;
- }
- }
- selectedECIndex = thisIndex;
- currentEC = currentECList.get(thisIndex);
- currentTaskChain = e2e.getECTaskList(currentEC);
- if (currentTaskChain.size() == 0 ) {
- JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has no chain-element.");
- txtField0.setText("Not Available.");
- txtField1.setText("Not Available.");
- txtField2.setText("Not Available.");
- txtField3.setText("Not Available.");
- txtField4.setText("Not Available.");
- txtField5.setText("Not Available.");
- txtField6.setText("Not Available.");
- txtField7.setText("Not Available.");
- list.removeAll();
- list.add("Not Available.");
- list_1.removeAll();
- list_1.add("Not Available.");
- list_2.removeAll();
- list_2.add("Not Available.");
- return ;
- }
- else if (currentTaskChain.size() > 14) {
- JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has more than " + currentTaskChain.size() + " elements. (Limit: 14)\n");
- txtField0.setText("Not Available.");
- txtField1.setText("Not Available.");
- txtField2.setText("Not Available.");
- txtField3.setText("Not Available.");
- txtField4.setText("Not Available.");
- txtField5.setText("Not Available.");
- txtField6.setText("Not Available.");
- txtField7.setText("Not Available.");
- list.removeAll();
- list.add("Not Available.");
- list_1.removeAll();
- list_1.add("Not Available.");
- list_2.removeAll();
- list_2.add("Not Available.");
- return ;
- }
- for (int i = 0; i < currentTaskChain.size(); i++) {
- final Task task = currentTaskChain.get(i);
- for (int j = 0; j < puTaskListHM.size(); j++) {
- java.util.List<Task> puTaskList = puTaskListHM.get(j);
- if (puTaskList.stream().filter(s -> s.equals(task)).collect(Collectors.toList()).size() != 0) {
- final ProcessingUnit pu = currentPUList.get(j);
- ecLabelArray[i] = new JLabel((i+1) + ": " + pu.getName() + " (" + pu.getDefinition().getName() + ")");
- ecJTPArray[i] = new JTextField();
- ecJTPArray[i].setText(task.getName());
- ecJTPArray[i].setEditable(false);
- if (i < 7) {
- ecLabelArray[i].setBounds(750, (604+(50*i)), 187, 16);
- ecJTPArray[i].setBounds(750, (624+(50*i)), 187, 22);
- } else {
- ecLabelArray[i].setBounds(950, (604+(50*(i-7))), 187, 16);
- ecJTPArray[i].setBounds(950, (624+(50*(i-7))), 187, 22);
- }
- frame.getContentPane().add(ecLabelArray[i]);
- frame.getContentPane().add(ecJTPArray[i]);
- break;
- }
- }
- }
-
- /* Calculation Part */
- if (currentModel == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");
- return ;
- } else if (ecComboBox.getSelectedItem() == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");
- return ;
- } else if (currentIA == null) {
- JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been entered.");
- return ;
- }
- if (list.getItemCount() > 0) {
- list.removeAll();
- list_1.removeAll();
- list_2.removeAll();
- }
- /* Sometimes the same task can not be schedulable in the implicit communication due to the LocalCopy cost time */
- Time rctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time rctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time ageWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time ageBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time eRctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-
- /* PARADIGM */
- if (rdbtnDirect.isSelected()) {
- currentParadigm = ComParadigm.DIRECT;
- rctWC = e2e.getTCReactionWC(currentEC, currentParadigm, cpurta);
- rctBC = e2e.getTCReactionBC(currentEC, currentParadigm, cpurta);
- ageWC = e2e.getTaskChainAge(currentEC, TimeType.WCET, currentParadigm, cpurta);
- ageBC = e2e.getTaskChainAge(currentEC, TimeType.BCET, currentParadigm, cpurta);
- eRctWC = e2e.getEarlyReaction(currentEC, TimeType.WCET, currentParadigm, cpurta);
- eRctBC = e2e.getEarlyReaction(currentEC, TimeType.BCET, currentParadigm, cpurta);
- } else if (rdbtnImplicit.isSelected()) {
- currentParadigm = ComParadigm.IMPLICIT;
- rctWC = e2e.getTCReactionWC(currentEC, currentParadigm, cpurta);
- rctBC = e2e.getTCReactionBC(currentEC, currentParadigm, cpurta);
- ageWC = e2e.getTaskChainAge(currentEC, TimeType.WCET, currentParadigm, cpurta);
- ageBC = e2e.getTaskChainAge(currentEC, TimeType.BCET, currentParadigm, cpurta);
- eRctWC = e2e.getEarlyReaction(currentEC, TimeType.WCET, currentParadigm, cpurta);
- eRctBC = e2e.getEarlyReaction(currentEC, TimeType.BCET, currentParadigm, cpurta);
- }
- if (rctWC.getValue().equals(BigInteger.ZERO)) {
- txtField0.setText("Not Schedulable (LocalCopy Cost)");
- } else {
- txtField0.setText("" + rctWC);
- }
- if (rctBC.getValue().equals(BigInteger.ZERO)) {
- txtField1.setText("Not Schedulable (LocalCopy Cost)");
- } else {
- txtField1.setText("" + rctBC);
- }
- txtField2.setText("" + e2e.getLetReactionWC(currentEC, cpurta));
- txtField3.setText("" + e2e.getLetReactionBC(currentEC, cpurta));
- txtField4.setText("" + ageWC);
- txtField5.setText("" + ageBC);
- if (eRctWC.getValue().equals(BigInteger.ZERO)) {
- txtField6.setText("Not Schedulable (LocalCopy Cost)");
- } else {
- txtField6.setText("" + eRctWC);
- }
- if (eRctBC.getValue().equals(BigInteger.ZERO)) {
- txtField7.setText("Not Schedulable (LocalCopy Cost)");
- } else {
- txtField7.setText("" + eRctBC);
- }
- final EList<Label> labelList = currentModel.getSwModel().getLabels();
- for (int i = 0; i < labelList.size(); i++) {
- Time datAgeLatWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- Time datAgeLatBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
- datAgeLatWC = e2e.getDataAge(labelList.get(i), currentEC, TimeType.WCET, currentParadigm, cpurta);
- datAgeLatBC = e2e.getDataAge(labelList.get(i), currentEC, TimeType.BCET, currentParadigm, cpurta);
- if (datAgeLatWC != null && datAgeLatBC != null) {
- list.add(labelList.get(i).getName());
- list_1.add(datAgeLatWC + "");
- list_2.add(datAgeLatBC + "");
- }
- }
- frame.revalidate();
- frame.repaint();
- }
- });
- ecSelect.setBounds(356, 569, 90, 25);
- frame.getContentPane().add(ecSelect);
-
- JButton btnNewButton_1 = new JButton("Reset");
- btnNewButton_1.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- for (int i = 0; i < currentTaskChain.size(); i++) {
- ecLabelArray[i].setText(null);
- frame.remove(ecLabelArray[i]);
- ecJTPArray[i].setText(null);
- frame.remove(ecJTPArray[i]);
- }
- selectedECIndex = -1;
- currentParadigm = null;
- txtField0.setText("");
- txtField1.setText("");
- txtField2.setText("");
- txtField3.setText("");
- txtField4.setText("");
- txtField5.setText("");
- txtField6.setText("");
- txtField7.setText("");
- paradigmMode.setSelected(null, false);
- list.removeAll();
- list_1.removeAll();
- list_2.removeAll();
- frame.revalidate();
- frame.repaint();
- }
- });
- btnNewButton_1.setBounds(445, 569, 70, 25);
- frame.getContentPane().add(btnNewButton_1);
-
- JLabel lblTaskChain_1 = new JLabel("Task Chain >");
- lblTaskChain_1.setFont(new Font("Segoe UI Emoji", Font.BOLD, 13));
- lblTaskChain_1.setBounds(646, 605, 90, 16);
- frame.getContentPane().add(lblTaskChain_1);
-
- JLabel lblApprta = new JLabel("APP4RTA");
- lblApprta.setForeground(Color.DARK_GRAY);
- lblApprta.setFont(new Font("Snap ITC", Font.ITALIC, 20));
- lblApprta.setBounds(1050, 1, 120, 34);
- frame.getContentPane().add(lblApprta);
-
- JSeparator separator = new JSeparator();
- separator.setBounds(10, 557, 1160, 2);
- frame.getContentPane().add(separator);
- }
+/*******************************************************************************
+ * 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: Junhyung Ki - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.app4mc.gsoc_rta.ui;
+
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.List;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.stream.Collectors;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.eclipse.app4mc.amalthea.model.Amalthea;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
+import org.eclipse.app4mc.amalthea.model.EventChain;
+import org.eclipse.app4mc.amalthea.model.Label;
+import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.PuType;
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.TimeUnit;
+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.gsoc_rta.*;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts.ComParadigm;
+import org.eclipse.emf.common.util.EList;
+import javax.swing.SwingConstants;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.JSeparator;
+
+/**
+ * Date: August 21-2019
+ * @author Junhyung Ki
+ * @version 1.0
+ * The purpose of this class is to provide users a better visual and increase usability of Response Time Analysis.
+ */
+@SuppressWarnings("serial")
+public class APP4RTA extends JFrame {
+ private static JComboBox<String> ecComboBox = new JComboBox<String>();
+
+ private CPURta cpurta = new CPURta(false);
+ private E2ELatency e2e = new E2ELatency();
+ private Amalthea currentModel = null;
+ private java.util.List<ProcessingUnit> currentPUList = null;
+ private int[] currentIA = null;
+ private EList<Task> allTaskList = null;
+ private EList<EventChain> currentECList = null;
+ private EventChain currentEC = null;
+ private java.util.List<Task> currentTaskChain = null;
+ private File currentFile = null;
+
+ private HashMap<Integer, java.util.List<Task>> puTaskListHM;
+ private JFrame frame;
+ private int selectedECIndex = -1;
+ private boolean schedulability_flag = false;
+ private ComParadigm currentParadigm = null;
+ JFileChooser fileChooser;
+ JTextField selectedModelLbl;
+
+ private JLabel jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10,
+ jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19;
+ private JTextField tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9,
+ tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19;
+ private JLabel[] jLabelArray = {
+ jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10,
+ jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19
+ };
+ private JTextField[] jTextFieldArray= {
+ tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9,
+ tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19
+ };
+
+ private JLabel jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7;
+ private JLabel jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h;
+ private List l0, l1, l2, l3, l4, l5, l6, l7;
+ private List rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7;
+ private JLabel[] puLabelArray = {
+ jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7
+ };
+ private JLabel[] rtListLabelArray = {
+ jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h
+ };
+ private List[] puListArray = {
+ l0, l1, l2, l3, l4, l5, l6, l7
+ };
+ private List[] rtListArray = {
+ rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7
+ };
+
+ private JLabel ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6,
+ ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13;
+ private JTextField jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,
+ jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13;
+ private JLabel[] ecLabelArray = {
+ ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6,
+ ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13
+ };
+ private JTextField[] ecJTPArray = {
+ jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,
+ jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13
+ };
+
+ private List list, list_1, list_2;
+
+ public static void main(String[] args) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ org.apache.log4j.BasicConfigurator.configure();
+ Logger.getRootLogger().setLevel(Level.ERROR);
+ final APP4RTA window = new APP4RTA();
+ window.frame.setVisible(true);
+ window.frame.setTitle("APP4RTA");
+ }
+ });
+ }
+
+ public APP4RTA() {
+ initialize();
+ }
+
+ private void initialize() {
+ frame = new JFrame();
+ frame.getContentPane().setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ frame.setBounds(0, 31, 1200, 1027);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.getContentPane().setLayout(null);
+
+ JLabel lblSelectTheModel = new JLabel("Amalthea Model");
+ lblSelectTheModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));
+ lblSelectTheModel.setBounds(10, 13, 120, 22);
+ frame.getContentPane().add(lblSelectTheModel);
+
+ JLabel lblTaskName = new JLabel("Task Name");
+ lblTaskName.setForeground(new Color(139, 0, 0));
+ lblTaskName.setFont(new Font("Sitka Heading", Font.BOLD, 12));
+ lblTaskName.setHorizontalAlignment(SwingConstants.CENTER);
+ lblTaskName.setBounds(15, 43, 70, 16);
+ frame.getContentPane().add(lblTaskName);
+
+ JLabel lblPuNum = new JLabel("PU Num");
+ lblPuNum.setForeground(new Color(0, 0, 255));
+ lblPuNum.setHorizontalAlignment(SwingConstants.CENTER);
+ lblPuNum.setFont(new Font("Sitka Heading", Font.BOLD, 12));
+ lblPuNum.setBounds(92, 43, 70, 16);
+ frame.getContentPane().add(lblPuNum);
+
+ JButton btnDefualtIa = new JButton("Defualt IA");
+ btnDefualtIa.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ if (cpurta.getModel() == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: A model is not loaded.");
+ return ;
+ } else if (cpurta.getTRT() == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: TRT HashMap is not loaded.");
+ return ;
+ } else if (cpurta.getPUl().size() == 0) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Processing Unit List is not loaded.");
+ return ;
+ }
+ final int[] defaultIA = SharedConsts.defaultIAMapping;
+ if (cpurta.getModel().getSwModel().getTasks().size() == defaultIA.length) {
+ for (int i = 0; i < defaultIA.length; i++) {
+ jTextFieldArray[i].setText("" + defaultIA[i]);
+ }
+ return ;
+ } else if (currentPUList.size() == 1) {
+ final int numOfTasks = cpurta.getModel().getSwModel().getTasks().size();
+ for (int i = 0; i < numOfTasks; i++) {
+ jTextFieldArray[i].setText("0");
+ }
+ return ;
+ }
+ String str = "";
+ for (int i = 0; i < currentPUList.size(); i++) {
+ if (i == currentPUList.size() - 1) {
+ str = str + i;
+ break;
+ }
+ str = str + i + ", ";
+ }
+ JOptionPane.showMessageDialog(frame, "ERROR: The length of the default integer array does not match with\n"
+ + "the number of tasks in the target model.\n\n" + "Please assign the number(s) manually.\n"
+ + "Available PU number(s): " + str);
+ }
+ });
+
+ JButton btnEnterIA = new JButton("Enter IA");
+ btnEnterIA.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ currentIA = new int[cpurta.getModel().getSwModel().getTasks().size()];
+ for (int i = 0; i < allTaskList.size(); i++) {
+ if (jTextFieldArray[i].getText().length() == 0) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Fill the rest of the array!");
+ return ;
+ } else if (jTextFieldArray[i].getText().charAt(0) < 48 || jTextFieldArray[i].getText().charAt(0) > 54) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Wrong array value!");
+ return ;
+ } else if (i >= 0 && i <= 9 && Integer.parseInt(jTextFieldArray[i].getText()) == 6) {
+ JOptionPane.showMessageDialog(frame, "ERROR: CPU Tasks should not be mapped to GPU! \n\n"
+ + "Please assign different IA value for " + "(" + allTaskList.get(i).getName() + ")");
+ return ;
+ } else if (i == jTextFieldArray.length-1 && Integer.parseInt(jTextFieldArray[i].getText()) != 6) {
+ JOptionPane.showMessageDialog(frame, "ERROR: 'Detection' task can not be mapped to CPU!");
+ return ;
+ }
+ currentIA[i] = Integer.parseInt(jTextFieldArray[i].getText());
+ }
+ cpurta.setIA(currentIA);
+ cpurta.setContention(currentIA, currentModel);
+ puTaskListHM = cpurta.getPUTaskListHashMap(currentModel);
+ for (int i = 0; i < puTaskListHM.size(); i++) {
+ if (puListArray[i].getItemCount() == 0) {
+ for (int j = 0; j < puTaskListHM.get(i).size(); j++) {
+ puListArray[i].add((puTaskListHM.get(i).get(j)).getName());
+ }
+ }
+ }
+ }
+ });
+
+ JRadioButton rdbtnSynchronous = new JRadioButton("Synchronous");
+ rdbtnSynchronous.setForeground(new Color(139, 0, 0));
+ rdbtnSynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+
+ JRadioButton rdbtnAsynchronous = new JRadioButton("Asynchronous");
+ rdbtnAsynchronous.setForeground(new Color(0, 0, 255));
+ rdbtnAsynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+
+ ButtonGroup offloadingMode = new ButtonGroup();
+ offloadingMode.add(rdbtnSynchronous);
+ offloadingMode.add(rdbtnAsynchronous);
+
+ JRadioButton rdbtnWorstCase = new JRadioButton("Worst-Case");
+ rdbtnWorstCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+ rdbtnWorstCase.setForeground(Color.DARK_GRAY);
+
+ JRadioButton rdbtnAverageCase = new JRadioButton("Average-Case");
+ rdbtnAverageCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+ rdbtnAverageCase.setForeground(Color.DARK_GRAY);
+
+ JRadioButton rdbtnBestCase = new JRadioButton("Best-Case");
+ rdbtnBestCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+ rdbtnBestCase.setForeground(Color.DARK_GRAY);
+
+ ButtonGroup executionMode = new ButtonGroup();
+ executionMode.add(rdbtnWorstCase);
+ executionMode.add(rdbtnAverageCase);
+ executionMode.add(rdbtnBestCase);
+
+ JLabel lblSchedulability = new JLabel("Schedulability");
+ JTextField schedulability = new JTextField();
+ schedulability.setHorizontalAlignment(SwingConstants.RIGHT);
+ schedulability.setEditable(false);
+
+ JLabel lblMemAccCost = new JLabel("Cumulated Memory-Access Cost");
+ JTextField memAccCost = new JTextField();
+ memAccCost.setHorizontalAlignment(SwingConstants.RIGHT);
+ memAccCost.setEditable(false);
+
+ JLabel lblCumulContention = new JLabel("Cumulated Contention");
+ JTextField cumulContention = new JTextField();
+ cumulContention.setHorizontalAlignment(SwingConstants.RIGHT);
+ cumulContention.setEditable(false);
+
+ JLabel lblComputation = new JLabel("Computation");
+ JTextField computation = new JTextField();
+ computation.setHorizontalAlignment(SwingConstants.RIGHT);
+ computation.setEditable(false);
+
+ JLabel lblResponseTimeSum = new JLabel("Response Time Sum");
+ JTextField rtSum = new JTextField();
+ rtSum.setHorizontalAlignment(SwingConstants.RIGHT);
+ rtSum.setEditable(false);
+
+ JButton btnCalculate = new JButton("Calculate");
+ btnCalculate.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent arg0) {
+ for (int i = 0; i < allTaskList.size(); i++) {
+ if (jTextFieldArray[i].getText().length() == 0) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Fill the array first!");
+ return ;
+ }
+ }
+ if (rdbtnSynchronous.isSelected()) {
+ SharedConsts.synchronousOffloading = true;
+ } else if (rdbtnAsynchronous.isSelected()) {
+ SharedConsts.synchronousOffloading = false;
+ } else {
+ JOptionPane.showMessageDialog(frame, "ERROR: You should choose an offloading mode! (Sync / Async)");
+ return ;
+ }
+ if (rdbtnWorstCase.isSelected()) {
+ SharedConsts.timeType = TimeType.WCET;
+ } else if (rdbtnAverageCase.isSelected()) {
+ SharedConsts.timeType = TimeType.ACET;
+ } else if (rdbtnBestCase.isSelected()) {
+ SharedConsts.timeType = TimeType.BCET;
+ } else {
+ JOptionPane.showMessageDialog(frame, "ERROR: You should choose an execution case! (Worst Case / Average Case / Best Case)");
+ return ;
+ }
+ if (currentIA == null || puTaskListHM.size() == 0) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Click the 'Enter IA' button.");
+ return ;
+ }
+ schedulability_flag = true;
+ Time pRtSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ for (int i = 0; i < puTaskListHM.size(); i++) {
+ final ProcessingUnit pu = cpurta.getPUl().get(i);
+ final java.util.List<Task> thisPUTaskList = puTaskListHM.get(i);
+ Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ if (rtListArray[i].getItemCount() == 0) {
+ if (pu.getDefinition().getPuType().equals(PuType.CPU)) {
+ for (Task t : thisPUTaskList) {
+ thisRT = cpurta.preciseTestCPURT(t, thisPUTaskList, SharedConsts.timeType, pu);
+ final Time thisPeriod = CommonUtils.getStimInTime(t);
+ final BigInteger period = AmaltheaServices.convertToPicoSeconds(thisPeriod);
+ if (AmaltheaServices.convertToPicoSeconds(thisRT).compareTo(period) > 0) {
+ rtListArray[i].add("Non Scheduleable! => MAX Value");
+ schedulability_flag = false;
+ } else if (AmaltheaServices.convertToPicoSeconds(thisRT).equals(BigInteger.ZERO)) {
+ rtListArray[i].add("0 ps (GPU Task on CPU)");
+ } else {
+ rtListArray[i].add(thisRT.toString());
+ }
+ pRtSum = pRtSum.add(thisRT);
+ }
+ } else {
+ for (Task t : thisPUTaskList) {
+ thisRT = cpurta.getTRT().get(t);
+ rtListArray[i].add(thisRT.toString());
+ pRtSum = pRtSum.add(thisRT);
+ }
+ }
+ }
+ }
+ if (schedulability_flag) {
+ schedulability.setText("Scheduleable! :)");
+ memAccCost.setText("" + cpurta.getCumulatedMemAccCosts());
+ cumulContention.setText("" + cpurta.getCumulatedContention());
+ computation.setText("" + (pRtSum.subtract(cpurta.getCumulatedMemAccCosts())).subtract(cpurta.getCumulatedContention()));
+ rtSum.setText(pRtSum.toString());
+ } else {
+ schedulability.setText("Non Scheduleable! :(");
+ memAccCost.setText("Not Available.");
+ cumulContention.setText("Not Available.");
+ computation.setText("Not Available.");
+ rtSum.setText("Not Available.");
+ }
+ }
+ });
+
+ JButton btnReset = new JButton("Reset");
+ btnReset.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ currentIA = null;
+ cpurta.setIA(currentIA);
+ cpurta.setContention(currentIA, currentModel);
+ /* latency time initializing */
+ cpurta.initCumulatedMemAccCosts();
+ cpurta.initCumulatedContention();
+ for (int i = 0; i < allTaskList.size(); i++) {
+ jTextFieldArray[i].setText("");
+ }
+ for (int i = 0; i < currentPUList.size(); i++) {
+ puListArray[i].removeAll();
+ }
+ for (int i = 0; i < currentPUList.size(); i++) {
+ rtListArray[i].removeAll();
+ }
+ offloadingMode.setSelected(null, false);
+ executionMode.setSelected(null, false);
+ schedulability.setText(null);
+ memAccCost.setText(null);
+ cumulContention.setText(null);
+ computation.setText(null);
+ rtSum.setText(null);
+ currentIA = null;
+ puTaskListHM = null;
+ frame.revalidate();
+ frame.repaint();
+ }
+ });
+
+ selectedModelLbl = new JTextField();
+ selectedModelLbl.setEditable(false);
+ selectedModelLbl.setBounds(142, 13, 206, 22);
+ frame.getContentPane().add(selectedModelLbl);
+ selectedModelLbl.setColumns(10);
+
+ JButton amaltheaSchBtn = new JButton("Search Amalthea");
+ amaltheaSchBtn.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ final String userDirLocation = System.getProperty("user.dir");
+ File userDir = new File(userDirLocation);
+ fileChooser = new JFileChooser(userDir);
+ fileChooser.setAcceptAllFileFilterUsed(false);
+ FileNameExtensionFilter filter = new FileNameExtensionFilter("Amalthea models", "amxmi");
+ fileChooser.addChoosableFileFilter(filter);
+ fileChooser.setDialogTitle("Open File");
+ int result = fileChooser.showOpenDialog(null);
+ if (result == JFileChooser.APPROVE_OPTION) {
+ final Amalthea loadedModel = AmaltheaLoader.loadFromFile(fileChooser.getSelectedFile());
+ if (loadedModel.getVersion().compareTo("0.9.5") != 0) {
+ JOptionPane.showMessageDialog(frame, "Error: This model should be migrated to the version 0.9.4");
+ return ;
+ }
+ /* Something was selected before */
+ if (currentFile != null) {
+ /* The selected file is equal to the previous file => Do nothing */
+ if (fileChooser.getSelectedFile().equals(currentFile)) {
+ JOptionPane.showMessageDialog(frame, "Same Model");
+ return ;
+ }
+ /* If the selected file is different to the previous one => Remove and Do Normal. */
+ else {
+ schedulability.setText(null);
+ memAccCost.setText(null);
+ cumulContention.setText(null);
+ computation.setText(null);
+ rtSum.setText(null);
+ for (int i = 0; i < allTaskList.size(); i++) {
+ frame.remove(jLabelArray[i]);
+ frame.remove(jTextFieldArray[i]);
+ }
+ frame.remove(btnDefualtIa);
+ frame.remove(btnEnterIA);
+ frame.remove(rdbtnSynchronous);
+ frame.remove(rdbtnAsynchronous);
+ frame.remove(rdbtnWorstCase);
+ frame.remove(rdbtnAverageCase);
+ frame.remove(rdbtnBestCase);
+ frame.remove(btnCalculate);
+ frame.remove(btnReset);
+ frame.remove(lblSchedulability);
+ frame.remove(schedulability);
+ frame.remove(lblMemAccCost);
+ frame.remove(memAccCost);
+ frame.remove(lblCumulContention);
+ frame.remove(cumulContention);
+ frame.remove(lblComputation);
+ frame.remove(computation);
+ frame.remove(lblResponseTimeSum);
+ frame.remove(rtSum);
+ for (int i = 0; i < currentPUList.size(); i++) {
+ frame.remove(puLabelArray[i]);
+ frame.remove(rtListLabelArray[i]);
+ frame.remove(puListArray[i]);
+ frame.remove(rtListArray[i]);
+ }
+ frame.remove(ecComboBox);
+ }
+ }
+ /* Something was not selected before => Do normal */
+ currentFile = fileChooser.getSelectedFile();
+ selectedModelLbl.setText(currentFile.getName());
+ currentModel = loadedModel;
+ currentPUList = CommonUtils.getPUs(currentModel);
+ if (currentPUList.get(0).getAccessElements().size() == 0) {
+ JOptionPane.showMessageDialog(frame, "The selected model's processing unit(s) does(do) not have 'read & write Latency' values.\n\n"
+ + "Therefore, the default value of 30 will be assigned for them.\n"
+ + "This will affect the response time results.");
+ }
+ cpurta.setModel(currentModel);
+ cpurta.setTRT(cpurta.getDefaultTRT(currentModel));
+ cpurta.setPUl(currentPUList);
+ allTaskList = currentModel.getSwModel().getTasks();
+ if (allTaskList.size() > 20) {
+ JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + allTaskList.size() + " Tasks. (Limit: 20)\n"
+ + "Please choose a different model.");
+ return ;
+ } else if (currentPUList.size() > 8) {
+ JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + currentPUList.size() + " Processing Units. (Limit: 8)\n"
+ + "Please choose a different model.");
+ return ;
+ }
+ /* Task Indices */
+ for (int i = 0; i < allTaskList.size(); i++) {
+ jLabelArray[i] = new JLabel(allTaskList.get(i).getName());
+ jLabelArray[i].setBounds(12, (60+(i*24)), 97, 16);
+ frame.getContentPane().add(jLabelArray[i]);
+ jTextFieldArray[i] = new JTextField();
+ jTextFieldArray[i].setColumns(10);
+ jTextFieldArray[i].setBounds(118, (60+(i*24)), 22, 22);
+ frame.getContentPane().add(jTextFieldArray[i]);
+ }
+ /* DefaultIA Button */
+ btnDefualtIa.setBounds(155, 60, 97, 25);
+ frame.getContentPane().add(btnDefualtIa);
+ /* EnterIA Button */
+ btnEnterIA.setBounds(155, 90, 97, 25);
+ frame.getContentPane().add(btnEnterIA);
+ /* Sync Radio Button */
+ rdbtnSynchronous.setBounds(152, 125, 126, 25);
+ frame.getContentPane().add(rdbtnSynchronous);
+ /* Async Radio Button */
+ rdbtnAsynchronous.setBounds(152, 145, 126, 25);
+ frame.getContentPane().add(rdbtnAsynchronous);
+ /* WorstCase Radio Button */
+ rdbtnWorstCase.setBounds(152, 175, 107, 25);
+ frame.getContentPane().add(rdbtnWorstCase);
+ /* AverageCase Radio Button */
+ rdbtnAverageCase.setBounds(152, 195, 107, 25);
+ frame.getContentPane().add(rdbtnAverageCase);
+ /* BestCase Radio Button */
+ rdbtnBestCase.setBounds(152, 215, 107, 25);
+ frame.getContentPane().add(rdbtnBestCase);
+ /* Calculate Button */
+ btnCalculate.setBounds(155, 252, 97, 25);
+ frame.getContentPane().add(btnCalculate);
+ /* Reset Button */
+ btnReset.setBounds(155, 282, 97, 25);
+ frame.getContentPane().add(btnReset);
+ /* Schedulability Label & TextField */
+ lblSchedulability.setBounds(157, 323, 200, 16);
+ frame.getContentPane().add(lblSchedulability);
+ schedulability.setBounds(155, 343, 200, 22);
+ frame.getContentPane().add(schedulability);
+ /* MemAccCost Label & TextField */
+ lblMemAccCost.setBounds(157, 368, 200, 16);
+ frame.getContentPane().add(lblMemAccCost);
+ memAccCost.setBounds(155, 388, 200, 22);
+ frame.getContentPane().add(memAccCost);
+ /* CumulContention Label & TextField */
+ lblCumulContention.setBounds(157, 413, 200, 16);
+ frame.getContentPane().add(lblCumulContention);
+ cumulContention.setBounds(155, 433, 200, 22);
+ frame.getContentPane().add(cumulContention);
+ /* Computation */
+ lblComputation.setBounds(157, 458, 200, 16);
+ frame.getContentPane().add(lblComputation);
+ computation.setBounds(155, 478, 200, 22);
+ frame.getContentPane().add(computation);
+ /* ResponseTime Sum Label & TextField */
+ lblResponseTimeSum.setBounds(157, 503, 200, 16);
+ frame.getContentPane().add(lblResponseTimeSum);
+ rtSum.setBounds(155, 523, 200, 22);
+ frame.getContentPane().add(rtSum);
+ /* PU & RT Lists */
+ for (int i = 0; i < currentPUList.size(); i++) {
+ puLabelArray[i] = new JLabel(i +": " + currentPUList.get(i).getDefinition().getName());
+ rtListLabelArray[i] = new JLabel("Response Time");
+ puListArray[i] = new List();
+ rtListArray[i] = new List();
+ if (i >= 0 && i < 4) {
+ puLabelArray[i].setBounds((387+(i*200)), 50, 87, 22);
+ rtListLabelArray[i].setBounds((474+(i*200)), 50, 88, 22);
+ puListArray[i].setBounds((385+(i*200)), 75, 87, 145);
+ rtListArray[i].setBounds((475+(i*200)), 75, 87, 145);
+ } else if (i >= 4) {
+ puLabelArray[i].setBounds((387+((i-4)*200)), 225, 87, 22);
+ rtListLabelArray[i].setBounds((474+((i-4)*200)), 225, 88, 22);
+ puListArray[i].setBounds((385+((i-4)*200)), 250, 87, 145);
+ rtListArray[i].setBounds((475+((i-4)*200)), 250, 87, 145);
+ }
+ frame.getContentPane().add(puLabelArray[i]);
+ frame.getContentPane().add(rtListLabelArray[i]);
+ frame.getContentPane().add(puListArray[i]);
+ frame.getContentPane().add(rtListArray[i]);
+ }
+ /* E2ELatency Part */
+ currentECList = currentModel.getConstraintsModel().getEventChains();
+ if (currentECList.size() != 0) {
+ final String[] ecComboArray = new String[currentECList.size()];
+ for (int i = 0; i < currentECList.size(); i++) {
+ ecComboArray[i] = currentECList.get(i).getName();
+ }
+ ecComboBox = new JComboBox<String>(ecComboArray);
+ ecComboBox.setBounds(150, 570, 206, 22);
+ frame.getContentPane().add(ecComboBox);
+ ecComboBox.setSelectedItem(null);
+ } else {
+ JOptionPane.showMessageDialog(frame, "WARNING: The selected model has no Event-Chain.\n"
+ + "End-to-End Event-Chain Latency Calculation is impossible with this model.");
+ // TODO: Something needs to be done here to prevent E2ELatency calculation.
+ }
+ frame.revalidate();
+ frame.repaint();
+ }
+ }
+ });
+ amaltheaSchBtn.setBounds(348, 12, 133, 24);
+ frame.getContentPane().add(amaltheaSchBtn);
+
+ JLabel lblEventChainModel = new JLabel("EVENT CHAIN MODEL");
+ lblEventChainModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));
+ lblEventChainModel.setBounds(10, 570, 136, 22);
+ frame.getContentPane().add(lblEventChainModel);
+
+ JRadioButton rdbtnDirect = new JRadioButton("Direct");
+ rdbtnDirect.setForeground(new Color(139, 0, 0));
+ rdbtnDirect.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+ rdbtnDirect.setBounds(530, 569, 70, 25);
+ frame.getContentPane().add(rdbtnDirect);
+
+ JRadioButton rdbtnImplicit = new JRadioButton("Implicit");
+ rdbtnImplicit.setForeground(new Color(0, 0, 255));
+ rdbtnImplicit.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+ rdbtnImplicit.setBounds(596, 569, 79, 25);
+ frame.getContentPane().add(rdbtnImplicit);
+
+ ButtonGroup paradigmMode = new ButtonGroup();
+ paradigmMode.add(rdbtnDirect);
+ paradigmMode.add(rdbtnImplicit);
+
+ JLabel lblNewLabel = new JLabel("Direct & Implicit Communication Paradigm");
+ lblNewLabel.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+ lblNewLabel.setBounds(10, 605, 293, 16);
+ frame.getContentPane().add(lblNewLabel);
+
+ JLabel lblWorstcaseReaction = new JLabel("WC Reaction");
+ lblWorstcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);
+ lblWorstcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblWorstcaseReaction.setBounds(10, 627, 90, 16);
+ frame.getContentPane().add(lblWorstcaseReaction);
+
+ JTextField txtField0 = new JTextField();
+ txtField0.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField0.setBounds(103, 625, 200, 22);
+ txtField0.setEditable(false);
+ frame.getContentPane().add(txtField0);
+
+ JLabel lblBestcaseReaction = new JLabel("BC Reaction");
+ lblBestcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblBestcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);
+ lblBestcaseReaction.setBounds(10, 656, 90, 16);
+ frame.getContentPane().add(lblBestcaseReaction);
+
+ JTextField txtField1 = new JTextField();
+ txtField1.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField1.setBounds(103, 654, 200, 22);
+ txtField1.setEditable(false);
+ frame.getContentPane().add(txtField1);
+
+ JLabel lblLetCommunicationParadigm = new JLabel("LET Communication Paradigm");
+ lblLetCommunicationParadigm.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+ lblLetCommunicationParadigm.setBounds(10, 688, 193, 16);
+ frame.getContentPane().add(lblLetCommunicationParadigm);
+
+ JLabel lblWcReaction = new JLabel("WC Reaction");
+ lblWcReaction.setHorizontalAlignment(SwingConstants.CENTER);
+ lblWcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblWcReaction.setBounds(10, 710, 90, 16);
+ frame.getContentPane().add(lblWcReaction);
+
+ JTextField txtField2 = new JTextField();
+ txtField2.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField2.setBounds(103, 708, 200, 22);
+ txtField2.setEditable(false);
+ frame.getContentPane().add(txtField2);
+
+ JLabel lblBcReaction = new JLabel("BC Reaction");
+ lblBcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblBcReaction.setHorizontalAlignment(SwingConstants.CENTER);
+ lblBcReaction.setBounds(10, 739, 90, 16);
+ frame.getContentPane().add(lblBcReaction);
+
+ JTextField txtField3 = new JTextField();
+ txtField3.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField3.setBounds(103, 737, 200, 22);
+ txtField3.setEditable(false);
+ frame.getContentPane().add(txtField3);
+
+ JLabel lblTaskChain = new JLabel("Task Chain Age (Direct & Implicit)");
+ lblTaskChain.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+ lblTaskChain.setBounds(338, 605, 222, 16);
+ frame.getContentPane().add(lblTaskChain);
+
+ JLabel lblWcAge = new JLabel("WC Age");
+ lblWcAge.setHorizontalAlignment(SwingConstants.CENTER);
+ lblWcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblWcAge.setBounds(350, 627, 58, 16);
+ frame.getContentPane().add(lblWcAge);
+
+ JTextField txtField4 = new JTextField();
+ txtField4.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField4.setBounds(413, 625, 200, 22);
+ txtField4.setEditable(false);
+ frame.getContentPane().add(txtField4);
+
+ JLabel lblBcAge = new JLabel("BC Age");
+ lblBcAge.setHorizontalAlignment(SwingConstants.CENTER);
+ lblBcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblBcAge.setBounds(350, 656, 58, 16);
+ frame.getContentPane().add(lblBcAge);
+
+ JTextField txtField5 = new JTextField();
+ txtField5.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField5.setBounds(413, 654, 200, 22);
+ txtField5.setEditable(false);
+ frame.getContentPane().add(txtField5);
+
+ JLabel lblEarlyReaction = new JLabel("Early Reaction (Direct & Implicit)");
+ lblEarlyReaction.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+ lblEarlyReaction.setBounds(338, 688, 232, 16);
+ frame.getContentPane().add(lblEarlyReaction);
+
+ JLabel lblWcErct = new JLabel("WC E-Rct");
+ lblWcErct.setHorizontalAlignment(SwingConstants.CENTER);
+ lblWcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblWcErct.setBounds(338, 710, 70, 16);
+ frame.getContentPane().add(lblWcErct);
+
+ JTextField txtField6 = new JTextField();
+ txtField6.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField6.setBounds(413, 708, 200, 22);
+ txtField6.setEditable(false);
+ frame.getContentPane().add(txtField6);
+
+ JLabel lblBcErct = new JLabel("BC E-Rct");
+ lblBcErct.setHorizontalAlignment(SwingConstants.CENTER);
+ lblBcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblBcErct.setBounds(338, 739, 70, 16);
+ frame.getContentPane().add(lblBcErct);
+
+ JTextField txtField7 = new JTextField();
+ txtField7.setHorizontalAlignment(SwingConstants.RIGHT);
+ txtField7.setBounds(413, 737, 200, 22);
+ txtField7.setEditable(false);
+ frame.getContentPane().add(txtField7);
+
+ JLabel lblDataAge = new JLabel("Data Age");
+ lblDataAge.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+ lblDataAge.setBounds(10, 771, 58, 16);
+ frame.getContentPane().add(lblDataAge);
+
+ JLabel lblContainedLabels = new JLabel("Contained Labels");
+ lblContainedLabels.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblContainedLabels.setBounds(10, 791, 136, 16);
+ frame.getContentPane().add(lblContainedLabels);
+
+ list = new List();
+ list.setBounds(10, 810, 155, 160);
+ frame.getContentPane().add(list);
+
+ JLabel lblWorstcaseAge = new JLabel("Worst-case Age");
+ lblWorstcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblWorstcaseAge.setBounds(177, 791, 136, 16);
+ frame.getContentPane().add(lblWorstcaseAge);
+
+ list_1 = new List();
+ list_1.setBounds(177, 810, 155, 160);
+ frame.getContentPane().add(list_1);
+
+ JLabel lblBestcaseAge = new JLabel("Best-case Age");
+ lblBestcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+ lblBestcaseAge.setBounds(344, 791, 136, 16);
+ frame.getContentPane().add(lblBestcaseAge);
+
+ list_2 = new List();
+ list_2.setBounds(344, 810, 155, 160);
+ frame.getContentPane().add(list_2);
+
+ JButton ecSelect = new JButton("Calculate");
+ ecSelect.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ if (currentModel == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");
+ return ;
+ } else if (currentECList == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Event-Chain List is empty somehow.");
+ return ;
+ } else if (currentECList.size() == 0) {
+ JOptionPane.showMessageDialog(frame, "ERROR: There is no Event-Chain in this model.");
+ return ;
+ } else if (ecComboBox.getSelectedItem() == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");
+ return ;
+ } else if (puTaskListHM == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been assigned.");
+ return ;
+ } else if (offloadingMode.getSelection() == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Choose an offloading mode. (Sync / Async)");
+ return ;
+ } else if (schedulability_flag == false) {
+ String offMode = null;
+ if (SharedConsts.synchronousOffloading == true) {
+ offMode = "Sync";
+ } else if (SharedConsts.synchronousOffloading == false) {
+ offMode = "Aync";
+ }
+ String tType = null;
+ if (SharedConsts.timeType.equals(TimeType.WCET)) {
+ tType = "WC";
+ } else if (SharedConsts.timeType.equals(TimeType.ACET)) {
+ tType = "AC";
+ } else if (SharedConsts.timeType.equals(TimeType.BCET)) {
+ tType = "BC";
+ }
+ String iaFeedback = "";
+ for (int i = 0; i < currentIA.length; i++) {
+ if (i == currentIA.length - 1) {
+ iaFeedback = iaFeedback + currentIA[i];
+ } else {
+ iaFeedback = iaFeedback + currentIA[i] + ", ";
+ }
+ }
+ JOptionPane.showMessageDialog(frame, "ERROR: The entered IA value is not schedulable with the current configuration.\n\n"
+ + "Current Integer Arrary: { " + iaFeedback + " }\n\n"
+ + "Current Configuration: Offloading Mode(" + offMode + "), ExecutionCase(" + tType + ")");
+ return ;
+ } else if (paradigmMode.getSelection() == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Choose a communication paradigm. (Direct / Implicit)");
+ return ;
+ }
+ final int thisIndex = ecComboBox.getSelectedIndex();
+ /* Something was selected before */
+ if (selectedECIndex != -1) {
+ /* If the selected Event-Chain is the same as before => Do Nothing */
+ if (selectedECIndex == thisIndex) {
+ if (currentParadigm != null) {
+ ComParadigm changedParadigm = null;
+ if (rdbtnDirect.isSelected()) {
+ changedParadigm = ComParadigm.DIRECT;
+ } else if (rdbtnImplicit.isSelected()) {
+ changedParadigm = ComParadigm.IMPLICIT;
+ }
+ if (currentParadigm.equals(changedParadigm)) {
+ JOptionPane.showMessageDialog(frame, "Same Paradigm & Same Event-Chain.");
+ return ;
+ }
+ for (int i = 0; i < currentTaskChain.size(); i++) {
+ frame.remove(ecLabelArray[i]);
+ frame.remove(ecJTPArray[i]);
+ }
+ }
+ }
+ /* If the selected Event-Chain is different to the previous one => Remove and Do Normal. */
+ else if (selectedECIndex != thisIndex) {
+ for (int i = 0; i < currentTaskChain.size(); i++) {
+ frame.remove(ecLabelArray[i]);
+ frame.remove(ecJTPArray[i]);
+ }
+ selectedECIndex = thisIndex;
+ }
+ }
+ selectedECIndex = thisIndex;
+ currentEC = currentECList.get(thisIndex);
+ currentTaskChain = e2e.getECTaskList(currentEC);
+ if (currentTaskChain.size() == 0 ) {
+ JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has no chain-element.");
+ txtField0.setText("Not Available.");
+ txtField1.setText("Not Available.");
+ txtField2.setText("Not Available.");
+ txtField3.setText("Not Available.");
+ txtField4.setText("Not Available.");
+ txtField5.setText("Not Available.");
+ txtField6.setText("Not Available.");
+ txtField7.setText("Not Available.");
+ list.removeAll();
+ list.add("Not Available.");
+ list_1.removeAll();
+ list_1.add("Not Available.");
+ list_2.removeAll();
+ list_2.add("Not Available.");
+ return ;
+ }
+ else if (currentTaskChain.size() > 14) {
+ JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has more than " + currentTaskChain.size() + " elements. (Limit: 14)\n");
+ txtField0.setText("Not Available.");
+ txtField1.setText("Not Available.");
+ txtField2.setText("Not Available.");
+ txtField3.setText("Not Available.");
+ txtField4.setText("Not Available.");
+ txtField5.setText("Not Available.");
+ txtField6.setText("Not Available.");
+ txtField7.setText("Not Available.");
+ list.removeAll();
+ list.add("Not Available.");
+ list_1.removeAll();
+ list_1.add("Not Available.");
+ list_2.removeAll();
+ list_2.add("Not Available.");
+ return ;
+ }
+ for (int i = 0; i < currentTaskChain.size(); i++) {
+ final Task task = currentTaskChain.get(i);
+ for (int j = 0; j < puTaskListHM.size(); j++) {
+ java.util.List<Task> puTaskList = puTaskListHM.get(j);
+ if (puTaskList.stream().filter(s -> s.equals(task)).collect(Collectors.toList()).size() != 0) {
+ final ProcessingUnit pu = currentPUList.get(j);
+ ecLabelArray[i] = new JLabel((i+1) + ": " + pu.getName() + " (" + pu.getDefinition().getName() + ")");
+ ecJTPArray[i] = new JTextField();
+ ecJTPArray[i].setText(task.getName());
+ ecJTPArray[i].setEditable(false);
+ if (i < 7) {
+ ecLabelArray[i].setBounds(750, (604+(50*i)), 187, 16);
+ ecJTPArray[i].setBounds(750, (624+(50*i)), 187, 22);
+ } else {
+ ecLabelArray[i].setBounds(950, (604+(50*(i-7))), 187, 16);
+ ecJTPArray[i].setBounds(950, (624+(50*(i-7))), 187, 22);
+ }
+ frame.getContentPane().add(ecLabelArray[i]);
+ frame.getContentPane().add(ecJTPArray[i]);
+ break;
+ }
+ }
+ }
+
+ /* Calculation Part */
+ if (currentModel == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");
+ return ;
+ } else if (ecComboBox.getSelectedItem() == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");
+ return ;
+ } else if (currentIA == null) {
+ JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been entered.");
+ return ;
+ }
+ if (list.getItemCount() > 0) {
+ list.removeAll();
+ list_1.removeAll();
+ list_2.removeAll();
+ }
+ /* Sometimes the same task can not be schedulable in the implicit communication due to the LocalCopy cost time */
+ Time rctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time rctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time ageWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time ageBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time eRctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+
+ /* PARADIGM */
+ if (rdbtnDirect.isSelected()) {
+ currentParadigm = ComParadigm.DIRECT;
+ rctWC = e2e.getWCReactionImplicit(currentEC, cpurta);
+ rctBC = e2e.getBCReactionImplicit(currentEC, cpurta);
+ ageWC = e2e.getWCAgeImplicit(currentEC, cpurta);
+ ageBC = e2e.getBCAgeImplicit(currentEC, cpurta);
+ eRctWC = e2e.getWCInitialRctImplicit(currentEC, cpurta);
+ eRctBC = e2e.getBCInitialRctImplicit(currentEC, cpurta);
+ } else if (rdbtnImplicit.isSelected()) {
+ currentParadigm = ComParadigm.IMPLICIT;
+ rctWC = e2e.getWCReactionImplicit(currentEC, cpurta);
+ rctBC = e2e.getBCReactionImplicit(currentEC, cpurta);
+ ageWC = e2e.getWCAgeImplicit(currentEC, cpurta);
+ ageBC = e2e.getBCAgeImplicit(currentEC, cpurta);
+ eRctWC = e2e.getWCInitialRctImplicit(currentEC, cpurta);
+ eRctBC = e2e.getBCInitialRctImplicit(currentEC, cpurta);
+ }
+ if (rctWC.getValue().equals(BigInteger.ZERO)) {
+ txtField0.setText("Not Schedulable (LocalCopy Cost)");
+ } else {
+ txtField0.setText("" + rctWC);
+ }
+ if (rctBC.getValue().equals(BigInteger.ZERO)) {
+ txtField1.setText("Not Schedulable (LocalCopy Cost)");
+ } else {
+ txtField1.setText("" + rctBC);
+ }
+ txtField2.setText("" + e2e.getWCReactionLET(currentEC, cpurta).adjustUnit());
+ txtField3.setText("" + e2e.getBCReactionLET(currentEC, cpurta).adjustUnit());
+ txtField4.setText("" + ageWC);
+ txtField5.setText("" + ageBC);
+ if (eRctWC.getValue().equals(BigInteger.ZERO)) {
+ txtField6.setText("Not Schedulable (LocalCopy Cost)");
+ } else {
+ txtField6.setText("" + eRctWC);
+ }
+ if (eRctBC.getValue().equals(BigInteger.ZERO)) {
+ txtField7.setText("Not Schedulable (LocalCopy Cost)");
+ } else {
+ txtField7.setText("" + eRctBC);
+ }
+ final EList<Label> labelList = currentModel.getSwModel().getLabels();
+ for (int i = 0; i < labelList.size(); i++) {
+ Time datAgeLatWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ Time datAgeLatBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+ datAgeLatWC = e2e.getWCDataAge(labelList.get(i), currentEC, cpurta);
+ datAgeLatBC = e2e.getBCDataAge(labelList.get(i), currentEC, cpurta);
+ if (datAgeLatWC != null && datAgeLatBC != null) {
+ list.add(labelList.get(i).getName());
+ list_1.add(datAgeLatWC + "");
+ list_2.add(datAgeLatBC + "");
+ }
+ }
+ frame.revalidate();
+ frame.repaint();
+ }
+ });
+ ecSelect.setBounds(356, 569, 90, 25);
+ frame.getContentPane().add(ecSelect);
+
+ JButton btnNewButton_1 = new JButton("Reset");
+ btnNewButton_1.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ for (int i = 0; i < currentTaskChain.size(); i++) {
+ ecLabelArray[i].setText(null);
+ frame.remove(ecLabelArray[i]);
+ ecJTPArray[i].setText(null);
+ frame.remove(ecJTPArray[i]);
+ }
+ selectedECIndex = -1;
+ currentParadigm = null;
+ txtField0.setText("");
+ txtField1.setText("");
+ txtField2.setText("");
+ txtField3.setText("");
+ txtField4.setText("");
+ txtField5.setText("");
+ txtField6.setText("");
+ txtField7.setText("");
+ paradigmMode.setSelected(null, false);
+ list.removeAll();
+ list_1.removeAll();
+ list_2.removeAll();
+ frame.revalidate();
+ frame.repaint();
+ }
+ });
+ btnNewButton_1.setBounds(445, 569, 70, 25);
+ frame.getContentPane().add(btnNewButton_1);
+
+ JLabel lblTaskChain_1 = new JLabel("Task Chain >");
+ lblTaskChain_1.setFont(new Font("Segoe UI Emoji", Font.BOLD, 13));
+ lblTaskChain_1.setBounds(646, 605, 90, 16);
+ frame.getContentPane().add(lblTaskChain_1);
+
+ JLabel lblApprta = new JLabel("APP4RTA");
+ lblApprta.setForeground(Color.DARK_GRAY);
+ lblApprta.setFont(new Font("Snap ITC", Font.ITALIC, 20));
+ lblApprta.setBounds(1050, 1, 120, 34);
+ frame.getContentPane().add(lblApprta);
+
+ JSeparator separator = new JSeparator();
+ separator.setBounds(10, 557, 1160, 2);
+ frame.getContentPane().add(separator);
+ }
}
\ No newline at end of file