Merge branch 'app4mc0.9.7/rttca' into master
Compliant to Amalthea 0.9.8
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.classpath b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.classpath
index eca7bdb..0d8f9cd 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.classpath
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.classpath
@@ -3,5 +3,7 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
 	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="xtend-gen"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
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..b33f6af
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/xtend-gen/
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.project b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.project
index dd2a679..cfe32e5 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.project
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.project
@@ -6,6 +6,11 @@
 	</projects>
 	<buildSpec>
 		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
 			</arguments>
@@ -24,5 +29,6 @@
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
 	</natures>
 </projectDescription>
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/doc/APP4RTA_1.0_Description.pdf b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/doc/APP4RTA_1.0_Description.pdf
deleted file mode 100644
index ad1c41c..0000000
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/doc/APP4RTA_1.0_Description.pdf
+++ /dev/null
Binary files differ
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/doc/Class_Diagram.png b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/doc/Class_Diagram.png
deleted file mode 100644
index 96608a1..0000000
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/doc/Class_Diagram.png
+++ /dev/null
Binary files differ
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/model-input/SingleTCs/SingleTCs.amxmi b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/model-input/SingleTCs/SingleTCs.amxmi
new file mode 100644
index 0000000..c714b75
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/model-input/SingleTCs/SingleTCs.amxmi
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<am:Amalthea xmlns:am="http://app4mc.eclipse.org/amalthea/0.9.8" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmi:version="2.0">
+  <swModel>
+    <tasks xmi:id="Task0?type=Task" name="Task0" stimuli="periodic_03s?type=PeriodicStimulus" multipleTaskActivationLimit="0">
+      <activityGraph>
+        <items xsi:type="am:RunnableCall" runnable="Run0?type=Runnable" />
+      </activityGraph>
+    </tasks>
+    <tasks xmi:id="Task1?type=Task" name="Task1" stimuli="periodic_05s?type=PeriodicStimulus" multipleTaskActivationLimit="0">
+      <activityGraph>
+        <items xsi:type="am:RunnableCall" runnable="Run1?type=Runnable" />
+      </activityGraph>
+    </tasks>
+    <tasks xmi:id="Task2?type=Task" name="Task2" stimuli="periodic_06s?type=PeriodicStimulus" multipleTaskActivationLimit="0">
+      <activityGraph>
+        <items xsi:type="am:RunnableCall" runnable="Run2?type=Runnable" />
+      </activityGraph>
+    </tasks>
+    <tasks xmi:id="Task3?type=Task" name="Task3" stimuli="periodic_10s?type=PeriodicStimulus" multipleTaskActivationLimit="0">
+      <activityGraph>
+        <items xsi:type="am:RunnableCall" runnable="Run3?type=Runnable" />
+      </activityGraph>
+    </tasks>
+    <runnables xmi:id="Run0?type=Runnable" name="Run0" callback="false" service="false">
+      <activityGraph>
+        <items xsi:type="am:Ticks">
+          <default xsi:type="am:DiscreteValueConstant" value="1" />
+        </items>
+      </activityGraph>
+    </runnables>
+    <runnables xmi:id="Run1?type=Runnable" name="Run1" callback="false" service="false">
+      <activityGraph>
+        <items xsi:type="am:Ticks">
+          <default xsi:type="am:DiscreteValueConstant" value="1" />
+        </items>
+      </activityGraph>
+    </runnables>
+    <runnables xmi:id="Run2?type=Runnable" name="Run2" callback="false" service="false">
+      <activityGraph>
+        <items xsi:type="am:Ticks">
+          <default xsi:type="am:DiscreteValueConstant" value="1" />
+        </items>
+      </activityGraph>
+    </runnables>
+    <runnables xmi:id="Run3?type=Runnable" name="Run3" callback="false" service="false">
+      <activityGraph>
+        <items xsi:type="am:Ticks">
+          <default xsi:type="am:DiscreteValueConstant" value="2" />
+        </items>
+      </activityGraph>
+    </runnables>
+  </swModel>
+  <hwModel>
+    <definitions xsi:type="am:ProcessingUnitDefinition" xmi:id="A57?type=ProcessingUnitDefinition" name="A57" puType="CPU">
+      <customProperties key="baseline">
+        <value xsi:type="am:Time" value="20" unit="ns" />
+      </customProperties>
+      <customProperties key="k">
+        <value xsi:type="am:Time" value="20" unit="ns" />
+      </customProperties>
+      <customProperties key="sGPU">
+        <value xsi:type="am:Time" value="100" unit="ns" />
+      </customProperties>
+    </definitions>
+    <definitions xsi:type="am:ProcessingUnitDefinition" xmi:id="Denver?type=ProcessingUnitDefinition" name="Denver" puType="CPU">
+      <customProperties key="baseline">
+        <value xsi:type="am:Time" value="8" unit="ns" />
+      </customProperties>
+      <customProperties key="k">
+        <value xsi:type="am:Time" value="2" unit="ns" />
+      </customProperties>
+      <customProperties key="sGPU">
+        <value xsi:type="am:Time" value="20" unit="ns" />
+      </customProperties>
+    </definitions>
+    <definitions xsi:type="am:ProcessingUnitDefinition" xmi:id="GPU_def?type=ProcessingUnitDefinition" name="GPU_def" puType="GPU">
+      <customProperties key="baseline">
+        <value xsi:type="am:Time" value="3" unit="ns" />
+      </customProperties>
+    </definitions>
+    <definitions xsi:type="am:MemoryDefinition" xmi:id="LPDDR4?type=MemoryDefinition" name="LPDDR4" memoryType="DRAM">
+      <size value="8" unit="GB" />
+      <accessLatency xsi:type="am:DiscreteValueConstant" value="0" />
+    </definitions>
+    <definitions xsi:type="am:ConnectionHandlerDefinition" xmi:id="Interconnect?type=ConnectionHandlerDefinition" name="Interconnect" policy="RoundRobin" maxBurstSize="4" maxConcurrentTransfers="1" />
+    <definitions xsi:type="am:CacheDefinition" xmi:id="CPU_L2?type=CacheDefinition" name="CPU_L2" cacheType="unified" writeStrategy="writeback" nWays="4" coherency="false" exclusive="false" hitRate="0.0">
+      <size value="2" unit="MB" />
+      <lineSize value="64" unit="B" />
+    </definitions>
+    <definitions xsi:type="am:CacheDefinition" xmi:id="GPU_L2?type=CacheDefinition" name="GPU_L2" cacheType="data" writeStrategy="writeback" nWays="4" coherency="false" exclusive="false" hitRate="0.0">
+      <size value="512" unit="kB" />
+      <lineSize value="64" unit="B" />
+    </definitions>
+    <structures xmi:id="JetsonTX2?type=HwStructure" name="JetsonTX2" structureType="System">
+      <structures xmi:id="ARM+island?type=HwStructure" name="ARM island" structureType="Cluster">
+        <modules xsi:type="am:ProcessingUnit" xmi:id="Core0?type=ProcessingUnit" name="Core0" frequencyDomain="A57_Domain?type=FrequencyDomain" definition="A57?type=ProcessingUnitDefinition">
+          <accessElements name="C2toDRAM">
+            <readLatency xsi:type="am:DiscreteValueConstant" value="40" />
+            <writeLatency xsi:type="am:DiscreteValueConstant" value="40" />
+            <dataRate value="4500" unit="MBPerSecond" />
+          </accessElements>
+        </modules>
+      </structures>
+    </structures>
+    <domains xsi:type="am:FrequencyDomain" xmi:id="A57_Domain?type=FrequencyDomain" name="A57_Domain" clockGating="false">
+      <defaultValue value="1.0" unit="Hz" />
+    </domains>
+  </hwModel>
+  <stimuliModel>
+    <stimuli xsi:type="am:PeriodicStimulus" xmi:id="periodic_03s?type=PeriodicStimulus" name="periodic_03s">
+      <recurrence value="3" unit="s" />
+    </stimuli>
+    <stimuli xsi:type="am:PeriodicStimulus" xmi:id="periodic_05s?type=PeriodicStimulus" name="periodic_05s">
+      <recurrence value="5" unit="s" />
+    </stimuli>
+    <stimuli xsi:type="am:PeriodicStimulus" xmi:id="periodic_06s?type=PeriodicStimulus" name="periodic_06s">
+      <recurrence value="6" unit="s" />
+    </stimuli>
+    <stimuli xsi:type="am:PeriodicStimulus" xmi:id="periodic_10s?type=PeriodicStimulus" name="periodic_10s">
+      <recurrence value="10" unit="s" />
+    </stimuli>
+  </stimuliModel>
+  <eventModel>
+    <events xsi:type="am:ProcessEvent" xmi:id="Task0+event?type=ProcessEvent" name="Task0 event" description="" entity="Task0?type=Task" />
+    <events xsi:type="am:ProcessEvent" xmi:id="Task1+event?type=ProcessEvent" name="Task1 event" entity="Task1?type=Task" />
+    <events xsi:type="am:ProcessEvent" xmi:id="Task2+event?type=ProcessEvent" name="Task2 event" entity="Task2?type=Task" />
+    <events xsi:type="am:ProcessEvent" xmi:id="Task3+event?type=ProcessEvent" name="Task3 event" description="" entity="Task3?type=Task" />
+  </eventModel>
+  <constraintsModel>
+    <eventChains xmi:id="EC_3-5-6-10?type=EventChain" name="EC_3-5-6-10" itemType="sequence" minItemsCompleted="1">
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task0+event?type=ProcessEvent" response="Task1+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task1+event?type=ProcessEvent" response="Task2+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task2+event?type=ProcessEvent" response="Task3+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+    </eventChains>
+    <eventChains xmi:id="EC_3-6-5-10?type=EventChain" name="EC_3-6-5-10" itemType="sequence" minItemsCompleted="1">
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task0+event?type=ProcessEvent" response="Task2+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task2+event?type=ProcessEvent" response="Task1+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task1+event?type=ProcessEvent" response="Task3+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+    </eventChains>
+    <eventChains xmi:id="EC_10-5-6-3?type=EventChain" name="EC_10-5-6-3" itemType="sequence" minItemsCompleted="1">
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task3+event?type=ProcessEvent" response="Task1+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task1+event?type=ProcessEvent" response="Task2+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task2+event?type=ProcessEvent" response="Task0+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+    </eventChains>
+    <eventChains xmi:id="EC_10-6-5-3?type=EventChain" name="EC_10-6-5-3" itemType="sequence" minItemsCompleted="1">
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task3+event?type=ProcessEvent" response="Task2+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task2+event?type=ProcessEvent" response="Task1+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+      <items xsi:type="am:EventChainContainer">
+        <eventChain name="" stimulus="Task1+event?type=ProcessEvent" response="Task0+event?type=ProcessEvent" minItemsCompleted="1" />
+      </items>
+    </eventChains>
+  </constraintsModel>
+</am:Amalthea>
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
new file mode 100644
index 0000000..629c65b
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
@@ -0,0 +1,1234 @@
+/*******************************************************************************
+ * 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.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.log4j.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.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.Preemption;
+import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.PuType;
+import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.RunnableCall;
+import org.eclipse.app4mc.amalthea.model.SetEvent;
+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.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;
+
+public class CPURta implements IRTA {
+	final Logger log = Logger.getLogger(CPURta.class);
+	private Amalthea model;
+	
+	/**
+	 * CPURta Constructor
+	 * @param forFunctions
+	 * 					true: when creating a class instance just to use functions
+	 * 					false: when creating a default class instance for CPURta simulation
+	 * @param file		target Amalthea file
+	 * @param ia		interger array mapping model
+	 */
+	public CPURta(final boolean forFunctions, final Amalthea model, final int[] ia) {
+		if (!forFunctions) {
+			if (model == null) {
+				log.error("The file is empty. Please check the model path.");
+				return;
+			}
+			this.setModel(model);
+			this.setTRT(getDefaultTRT(model));
+			this.setIA(ia);
+			this.setPUl(CommonUtils.getPUs(model));
+			this.setContention(ia, model);
+		}
+	}
+
+	/**
+	 * CPURta Constructor -	when manually creating a class instance for CPURta simulation
+	 * @param model			the observed Amalthea Model
+	 * @param trt			the observed HashMap Task with Response Time (null works => the default testing trt will be assigned)
+	 * @param ia			the observed IntegerArray Mapping Model
+	 * @param pul			the observed List of ProcessingUnits
+	 */
+	public CPURta(final Amalthea model, final HashMap<Task, Time> trt, final int[] ia, final List<ProcessingUnit> pul) {
+		if (model == null) {
+			log.error("Model is empty. Please check the model path.");
+			return;
+		}
+		this.setModel(model);
+		if (trt == null) {
+			this.setTRT(this.getDefaultTRT(model));
+		} else {
+			this.setTRT(trt);
+		}
+		this.setIA(ia);
+		if (pul == null) {
+			this.setPUl(CommonUtils.getPUs(model));
+		} else {
+			this.setPUl(pul);
+		}
+		this.setContention(ia, model);
+	}
+
+	/**
+	 * CPURta Constructor - when there is only one processing unit inside the model. (Therefore, IA mapping is not required.)
+	 * @param model
+	 */
+	public CPURta(final Amalthea model) {
+		if (model == null) {
+			log.error("Model is empty. Please check the model path.");
+		}
+		this.setModel(model);
+		final int numOfTasks = model.getSwModel().getTasks().size();
+		final int[] ia = new int[numOfTasks];
+		for (int i = 0; i < numOfTasks; i++) {
+			ia[i] = 0;
+		}
+		this.setTRT(getDefaultTRT(model));
+		this.setIA(ia);
+		this.setPUl(CommonUtils.getPUs(model));
+		this.setContention(ia, model);
+	}
+	
+	/**
+	 * Since this method is used by RTARuntimeUtil, the visibility should be 'public'
+	 * @return
+	 * 			The Amalthea model instance of the current CPURta class
+	 */
+	public Amalthea getModel() {
+		return this.model;
+	}
+
+	/**
+	 * Set the Amalthea model object of the current CPURta class as the given Amalthea model parameter.
+	 * @param pAmalthea			the parameter Amalthea model which would reinitialize the Amalthea model
+	 */
+	public void setModel(final Amalthea pAmalthea) {
+		this.model = pAmalthea;
+		this.setGTCL(this.model);
+	}
+
+	private HashMap<Task, Time> trt = null;
+
+	/**
+	 * Since this method is used by GAMapping, the visibility should be 'public'
+	 * @return
+	 * 			trt(task with response time) HashMap variable
+	 */
+	@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.
+	 */
+	public void setTRT(final HashMap<Task, Time> trtp) {
+		this.trt = trtp;
+	}
+
+	/**
+	 * Get the default trt(task with response time) value in case of running CPURta class itself.
+	 * @param model				the current class's Amalthea model which is used to get the trt value out of it
+	 * @return
+	 * 			the trt value which is derived out of the given parameter Amalthea model
+	 */
+	public HashMap<Task, Time> getDefaultTRT(final Amalthea model) {
+		final HashMap<Task, Time> trt = new HashMap<Task, Time>();
+		final EList<Task> allTaskList = model.getSwModel().getTasks();
+		final long val = 2000000000;
+		for (final Task t : allTaskList) {
+			if (this.gpuTaskList.contains(t)) {
+				trt.put(t, FactoryUtil.createTime(BigInteger.valueOf(val), TimeUnit.PS));
+			}
+			else {
+				trt.put(t, FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS));
+			}
+		}
+		return trt;
+	}
+
+	private int[] tpuMapping = null;
+
+	/**
+	 * Since this method is used by RTARuntimeUtil, the visibility should be '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.
+	 */
+	public void setIA(final int[] tpumap) {
+		if (tpumap == null) {
+			this.tpuMapping = null;
+		} else if (tpumap.length == this.model.getSwModel().getTasks().size()) {
+			this.tpuMapping = tpumap;
+		} else {
+			log.error("integer array size MUST match the number of tasks");
+		}
+	}
+
+	private List<ProcessingUnit> pul = new ArrayList<>();
+
+	/**
+	 * Get a list of ProcessingUnits
+	 * @return
+	 * 			this.pul
+	 */
+	public List<ProcessingUnit> getPUl() {
+		return this.pul;
+	}
+
+	/**
+	 * Set the pul, the list of Processing Units variable (which would be used to map tasks along with tpuMapping array)
+	 * as the given pul parameter variable.
+	 * @param pul 				the parameter pul list which would reinitialize the pul list variable of the current CPURta class
+	 */
+	public void setPUl(final List<ProcessingUnit> pul) {
+		this.pul = pul;
+	}
+
+	private Contention ct = null;
+
+	/**
+	 * Get the contention instance
+	 * @return
+	 * 			this.ct
+	 */
+	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
+	 * and Amalthea model parameters.
+	 * @param ia				Integer Array which is referred to map tasks of the given model
+	 * @param model				Amalthea model
+	 */
+	public void setContention(final int[] ia, final Amalthea model) {
+		this.ct = new Contention(ia, model);
+	}
+
+	private List<Task> gpuTaskList = new ArrayList<Task>();
+
+	/**
+	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
+	 * @return
+	 * 			gpuTaskList which contains tasks (which are originally designed for GPU) of the Amalthea model
+	 */
+	protected List<Task> getGpuTaskList() {
+		return this.gpuTaskList;
+	}
+
+	private final List<Task> triggeringTaskList = new ArrayList<Task>();
+	/**
+	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
+	 * @return
+	 * 			triggeringTaskList which contains tasks (which contain InterProcessTrigger) of the Amalthea model
+	 */
+	protected List<Task> getTriggeringTaskList() {
+		return this.triggeringTaskList;
+	}
+
+	/* this runnable is used to calculate execution time in RTARuntimeUtil class */
+	protected Runnable offloadingAsyncRunnable = null;
+
+	private final HashMap<Task, List<List<Label>>> gpuToCpuLabels = new HashMap<Task, List<List<Label>>>();
+
+	/**
+	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
+	 * @return
+	 * 			gpuToCpuLabels HashMap which contains required labels (of the corresponding task)
+	 * 			that need to be taken into account when GPU tasks are mapped to CPU
+	 */
+	protected HashMap<Task, List<List<Label>>> getGTCL() {
+		return this.gpuToCpuLabels;
+	}
+
+	/**
+	 * Not only set gpuToCpuLabels HashMap, this also set gpuTaskList (only contains GPU tasks),
+	 * triggeringTaskList (only contains tasks with InterProcessTrigger)
+	 * and offloadingAsyncRunnable (the Runnable that is taken into account for triggering tasks when the mode is asynchronous)
+	 * @param model				the parameter Amalthea model which is used to derived required labels of the corresponding GPU task
+	 */
+	private void setGTCL(final Amalthea model) {
+		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
+						.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>();
+			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 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)) {
+								readLabelList.add(la.getData());
+							}
+						}
+					}
+					/* Post-processing Runnable */
+					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)) {
+								writeLabelList.add(la.getData());
+							}
+						}
+					}
+				}
+			}
+			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
+	 */
+	public Time getCumulatedMemAccCosts() {
+		return this.cumuAcTime;
+	}
+	
+	/**
+	 * Initializing cumuAcTime to 0 ps
+	 */
+	public void initCumulatedMemAccCosts() {
+		this.cumuAcTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+	}
+
+	/* To calculate pure latency cost (without memory access latency & pure computation(Ticks)) */
+	protected Time cumuConTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+	
+	/**
+	 * @return
+	 * 			cumulatedCon, the total time of latency (Contention of the task)
+	 */
+	public Time getCumulatedContention() {
+		return this.cumuConTime;
+	}
+	
+	/**
+	 * Initializing cumulatedCon to 0 ps
+	 */
+	public void initCumulatedContention() {
+		this.cumuConTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+	}
+	
+	HashMap<Task, Time> accessCosts = new HashMap<>();
+
+	public HashMap<Task, Time> getAccessCosts() {
+		return this.accessCosts;
+	}
+
+	/**
+	 * Calculate the total sum of response times of the tasks of the given Amalthea model with the mapping model (tpuMapping)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @return
+	 * 			total sum of all tasks' response times of the given mapped model (tpuMapping)
+	 */
+	@Override
+	public Time getRTSum(final TimeType executionCase) {
+		if (this.model == null) {
+			log.error("No Model Loaded!");
+			return null;
+		} else if (this.trt == null) {
+			log.error("No HashMap Loaded!");
+			return null;
+		} else if (this.tpuMapping == null) {
+			log.error("No IntegerArray Loaded!");
+			return null;
+		} else if (this.pul == null) {
+			log.error("No PUList Loaded!");
+			return null;
+		}
+		this.setContention(this.getIA(), this.getModel());
+		Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final EList<Task> allTaskList = this.model.getSwModel().getTasks();
+		for (int i = 0; i < this.tpuMapping.length; i++) {
+			final Time rt = getTaskRTIA(allTaskList.get(i), executionCase);
+			if (rt.getValue().equals(BigInteger.valueOf(Long.MAX_VALUE)) && !SharedConsts.ignoreInfeasibility) {
+				return rt;
+			}
+			time = time.add(rt);
+			if (!rt.getValue().equals(BigInteger.ZERO)) {
+				/* only put CPU tasks */
+				this.trt.put(this.model.getSwModel().getTasks().get(i), rt);
+			}
+		}
+		return time;
+	}
+
+	/**
+	 * Calculate 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 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];
+		final ProcessingUnit pu = this.pul.get(puindex);
+		if (!pu.getDefinition().getPuType().equals(PuType.CPU)) {
+			Logger.getLogger(CPURta.class).debug(task.getName() + " is not mapped to a CPU");
+			return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		}
+		/* 2. get all tasks mapped to this CPU */
+		final List<Task> puTaskList = new ArrayList<Task>();
+		for (int i = 0; i < this.tpuMapping.length; i++) {
+			if (this.tpuMapping[i] == puindex) {
+				puTaskList.add(this.model.getSwModel().getTasks().get(i));
+			}
+		}
+		final List<Task> sortedTaskList = taskSorting(puTaskList);
+		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
+	 * @return
+	 * 			the sorted list of tasks
+	 */
+	protected List<Task> taskSorting(final List<Task> taskList) {
+		/* Getting stimuliList out of the given taskList (because it is RMS) */
+		final List<Time> stimuliList = new ArrayList<>();
+		for (final Task t : taskList) {
+			stimuliList.add(CommonUtils.getStimInTime(t));
+		}
+		/* Sorting (Shortest Period(Time) first) */
+		Collections.sort(stimuliList, new TimeCompIA());
+		/* Sort tasks to the newTaskList in order of Period length (shortest first
+		 * longest last)-(according to the stimuliList) */
+		final List<Task> newTaskList = new ArrayList<>();
+		for (int i = 0; i < stimuliList.size(); i++) {
+			for (final Task t : taskList) {
+				if ((!newTaskList.contains(t)) && (stimuliList.get(i).compareTo(CommonUtils.getStimInTime(t)) == 0)) {
+					newTaskList.add(t);
+				}
+			}
+		}
+		return newTaskList;
+	}
+
+	/**
+	 * 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
+	 * 			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) {
+		Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (taskList.size() == 0) {
+			log.debug("!!! This taskList is empty so I am returning MAX !!!");
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		/* to check if the given task is in the taskList */
+		int flag = 0;
+		int index = 0;
+		for (int i = 0; i < taskList.size(); i++) {
+			if (task.equals(taskList.get(i))) {
+				flag = 1;
+				index = i;
+				break;
+			}
+		}
+		if (flag == 0) {
+			log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+		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));
+					if (this.getIA() != null) {
+						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);
+			}
+			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));
+								if (this.getIA() != null) {
+									this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
+								}
+							}
+							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 " + cumulativeRT
+				+ " for task " + task.getName());
+			if (SharedConsts.ignoreInfeasibility) {
+				return cumulativeRT;
+			}
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+	}
+	
+	/**
+	 * 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
+	 * @return
+	 * 				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) {
+		Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (taskList.size() == 0) {
+			log.debug("!!! This taskList is empty so I am returning MAX !!!");
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		/* to check if the given task is in the taskList */
+		int flag = 0;
+		int index = 0;
+		for (int i = 0; i < taskList.size(); i++) {
+			if (task.equals(taskList.get(i))) {
+				flag = 1;
+				index = i;
+				break;
+			}
+		}
+		if (flag == 0) {
+			log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+		for (int i = 0; i < index + 1; i++) {
+			period = CommonUtils.getStimInTime(taskList.get(i));
+			if (index == 0) {
+				thisRT = rtaut.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]);
+				}
+				if (thisRT.compareTo(period) <= 0) {
+					return thisRT;
+				}
+				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+						+ " for task " + task.getName());
+				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+			} else if (i == index) {
+				/* In the case of a COOPERATIVE Preemption typed Task */
+				Time thisExeTime = rtaut.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]);
+				}
+				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 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.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]);
+					}
+					cumulativeRT = cumulativeRT.add(thisTime);
+				}
+				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.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(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;
+								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 " + cumulativeRT
+						+ " for task " + task.getName());
+				if (SharedConsts.ignoreInfeasibility) {
+					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;
+	}
+	
+	/**
+	 * get a list of tasks that are mapped to the same core and have a higher priority than the observed task has
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 				hpList
+	 */
+	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;
+	}
+	
+	/**
+	 * get a list of tasks that are mapped to the same core and have a higher priority than the observed task has
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 				hpList
+	 */
+	protected List<Task> getHigherPriorityTasksInChain(final Task task, final List<Task> chain) {
+		if (!chain.contains(task)) {
+			System.out.println("ERROR: The observed task chain does not contain the observed task.");
+			return null;
+		}
+		List<Time> periodList = chain.stream().map(s -> CommonUtils.getStimInTime(s)).collect(Collectors.toList());
+		/* Sorting (Shortest Period(Time) first) */
+		Collections.sort(periodList, new TimeCompIA());
+		final List<Task> sortedChain = new ArrayList<Task>();
+		for (int i = 0; i < periodList.size(); i++) {
+			final Time thisPeriod = periodList.get(i);
+			for (int j = 0; j < chain.size(); j++) {
+				final Task thisTask = chain.get(j);
+				if (thisPeriod.compareTo(CommonUtils.getStimInTime(thisTask)) == 0) {
+					if (!sortedChain.contains(thisTask)) {
+						sortedChain.add(thisTask);
+						break;
+					}
+				}
+			}
+		}
+		final int index = sortedChain.indexOf(task);
+		final List<Task> hpList = new ArrayList<Task>();
+		for (int i = 0; i < index; i++) {
+			hpList.add(sortedChain.get(i));
+		}
+		return hpList;
+	}
+	
+	/**
+	 * 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>> 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++) {
+			final List<Task> puTaskList = new ArrayList<Task>();
+			for (int j = 0; j < this.tpuMapping.length; j++) {
+				final int puIndex = this.tpuMapping[j];
+				if (i == puIndex) {
+					puTaskList.add(allTaskList.get(j));
+				}
+			}
+			puListHashMap.put(i, taskSorting(puTaskList));
+		}
+		return puListHashMap;
+	}
+
+	@Override
+	public Time getRT(final Task t, final TimeType timeType) {
+		if (null == getTRT().get(t)) {
+			getRTSum(timeType);
+		}
+		return getTRT().get(t);
+	}
+}
+
+/**
+ * @author Junhyung Ki
+ *			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
+	public int compare(final Time arg0, final Time arg1) {
+		if (arg0.compareTo(arg1) < 0) {
+			return -1;
+		}
+		return 1;
+	}
+}
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 5097077..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
@@ -13,7 +13,6 @@
  *******************************************************************************/
 package org.eclipse.app4mc.gsoc_rta;
 
-import org.apache.log4j.Logger;
 import java.io.BufferedWriter;
 import java.io.FileOutputStream;
 import java.io.OutputStreamWriter;
@@ -31,39 +30,39 @@
 import java.util.Set;
 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.CallSequence;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
 import org.eclipse.app4mc.amalthea.model.DiscreteValueConstant;
 import org.eclipse.app4mc.amalthea.model.DiscreteValueStatistics;
 import org.eclipse.app4mc.amalthea.model.ExecutionNeed;
-import org.eclipse.app4mc.amalthea.model.GraphEntryBase;
+import org.eclipse.app4mc.amalthea.model.Frequency;
+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;
 import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
 import org.eclipse.app4mc.amalthea.model.Label;
 import org.eclipse.app4mc.amalthea.model.LabelAccess;
-import org.eclipse.app4mc.amalthea.model.LabelAccessEnum;
 import org.eclipse.app4mc.amalthea.model.MappingModel;
 import org.eclipse.app4mc.amalthea.model.PeriodicStimulus;
-import org.eclipse.app4mc.amalthea.model.Process;
 import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
 import org.eclipse.app4mc.amalthea.model.ProcessingUnitDefinition;
 import org.eclipse.app4mc.amalthea.model.PuType;
 import org.eclipse.app4mc.amalthea.model.Runnable;
-import org.eclipse.app4mc.amalthea.model.RunnableItem;
-import org.eclipse.app4mc.amalthea.model.SWModel;
+import org.eclipse.app4mc.amalthea.model.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;
 import org.eclipse.app4mc.amalthea.model.UserSpecificSchedulingAlgorithm;
+import org.eclipse.app4mc.amalthea.model.util.DeploymentUtil;
 import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
 import org.eclipse.app4mc.amalthea.model.util.HardwareUtil;
 import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil;
@@ -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());
@@ -121,71 +120,6 @@
 	}
 
 	/**
-	 * @param l Label
-	 * @param swm Amalthea software model
-	 * @return Set of runnables which write label l
-	 */
-	public static Set<Runnable> getWriterSetOfLabel(final Label l, final SWModel swm) {
-		final Set<Runnable> rs = new HashSet<>();
-		for (final Runnable r : swm.getRunnables()) {
-			for (final RunnableItem ri : r.getRunnableItems()) {
-				if (ri instanceof LabelAccess) {
-					final LabelAccess la = (LabelAccess) ri;
-					if (la.getData().equals(l) && la.getAccess().equals(LabelAccessEnum.WRITE)) {
-						rs.add(r);
-					}
-				}
-			}
-		}
-		return rs;
-	}
-
-	/**
-	 * @param l Label
-	 * @param swm Amalthea software model
-	 * @return Set of runnables which read label l
-	 */
-	public static Set<Runnable> getReadersSetOfLabel(final Label l, final SWModel swm) {
-		final Set<Runnable> rs = new HashSet<>();
-		for (final Runnable r : swm.getRunnables()) {
-			for (final RunnableItem ri : r.getRunnableItems()) {
-				if (ri instanceof LabelAccess) {
-					final LabelAccess la = (LabelAccess) ri;
-					if (la.getData().equals(l) && la.getAccess().equals(LabelAccessEnum.READ)) {
-						rs.add(r);
-					}
-				}
-			}
-		}
-		return rs;
-	}
-
-	/**
-	 * @param r Runnable
-	 * @param swm Amalthea Software model
-	 * @return List of Processes that call runnable r (via taskRunnableCall)
-	 */
-	public static List<Process> getProcesses(final Runnable r, final SWModel swm) {
-		final List<Process> pl = new ArrayList<Process>();
-		for (final Task t : swm.getTasks()) {
-			for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-				if (geb instanceof CallSequence) {
-					final CallSequence cs = (CallSequence) geb;
-					for (final CallSequenceItem csi : cs.getCalls()) {
-						if (csi instanceof TaskRunnableCall) {
-							final TaskRunnableCall trc = (TaskRunnableCall) csi;
-							if (trc.getRunnable().equals(r)) {
-								pl.add(t);
-							}
-						}
-					}
-				}
-			}
-		}
-		return pl;
-	}
-
-	/**
 	 * @param model Amalthea
 	 * @return integer array size of tasks, that contains processing unit indexes
 	 * for each task for the processing unit the tasks are mapped to according to
@@ -224,11 +158,11 @@
 						tsl = tsl * (tl.size() - tl.indexOf(t));
 						break;
 					case TSxUtil:
-						final double util = getET(t, gpu).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).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:
@@ -289,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)));
 					}
@@ -373,51 +307,122 @@
 
 	/**
 	 * @param t Task
-	 * @param pu Processing Unit
-	 * @return Time execution time of t at pu
+	 * @param amalthea Model
+	 * @return Time execution time based on DeploymentUtil.getAssignedCoreForProcess
 	 */
-	public static Time getET(final Task t, final ProcessingUnit pu) {
-		Time ct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-		for (final ExecutionNeed en : SoftwareUtil.getExecutionNeeds(t, null)) {
-			for (final Entry<String, IDiscreteValueDeviation> needs : en.getNeeds().entrySet()) {
-				ct = ct.add(RuntimeUtil.getExecutionTimeForExecutionNeedEntry(needs.getValue(), null, pu, SharedConsts.timeType));
+	public static Time getSimpleET(final Task t, final Amalthea amalthea) {
+		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);
 			}
 		}
-		for (final Ticks ticks : getTicks(t)) {
-			/* considers extended */
-			ct = ct.add(RuntimeUtil.getExecutionTimeForTicks(ticks, pu, SharedConsts.timeType));
-		}
-		if (ct.getValue().toString().endsWith("999")) {
-			ct.setValue(ct.getValue().add(BigInteger.ONE));
-		}
-		return ct;
+		return null;
 	}
 
 	/**
+	 * Only returns execution time until the first InterProcessTrigger event
 	 * @param t Task
-	 * @return set of Task t's ticks
+	 * @param pu Processing Unit
+	 * @return Time execution time of t at pu
 	 */
-	public static Set<Ticks> getTicks(final Task t) {
-		final Set<Ticks> tickss = new HashSet<>();
-		for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-			if (geb instanceof CallSequence) {
-				final CallSequence cs = (CallSequence) geb;
-				for (final CallSequenceItem csi : cs.getCalls()) {
-					if (csi instanceof TaskRunnableCall) {
-						final TaskRunnableCall trc = (TaskRunnableCall) csi;
-						for (final RunnableItem ri : trc.getRunnable().getRunnableItems()) {
-							if (ri instanceof Ticks) {
-								final Ticks ticks = (Ticks) ri;
-								tickss.add(ticks);
-							}
+	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);
+		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));
+					}
 				}
 			}
 		}
-		return tickss;
+		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 APP4MC<0.9.6
+	 * @param ticks
+	 * @param pu
+	 * @param tt
+	 * @return Time execution time for a given Ticks value derived from given ProcessingUnit and TimeType
+	 */
+	public static Time getExecutionTimeForTicks(final Ticks ticks, final ProcessingUnit pu, final TimeType tt) {
+		Time result = FactoryUtil.createTime();
+
+		if (ticks.getExtended().get(pu.getDefinition()) != null) {
+			final IDiscreteValueDeviation deviation = ticks.getExtended().get(pu.getDefinition());
+			result = getExecutionTimeForTicksDeviation(deviation, pu, tt);
+		}
+		else {
+			result = getExecutionTimeForTicksDeviation(ticks.getDefault(), pu, tt);
+		}
+		return result;
+	}
+
+	/**
+	 * FIX for APP4MC<0.9.6
+	 * @param deviation
+	 * @param pu
+	 * @param tt
+	 * @return Time execution time for a given IDiscreteValueDeviation value derived from given ProcessingUnit and TimeType
+	 */
+	private static Time getExecutionTimeForTicksDeviation(final IDiscreteValueDeviation deviation, final ProcessingUnit pu, final TimeType tt) {
+		double ticks = 0d;
+		switch (tt) {
+			case BCET:
+				ticks = deviation.getLowerBound().doubleValue();
+				break;
+			case ACET:
+				ticks = deviation.getAverage();
+				break;
+			case WCET:
+				ticks = deviation.getUpperBound().doubleValue();
+				break;
+		}
+		final Time result = getExecutionTimeForCycles(ticks, pu.getFrequencyDomain().getDefaultValue());
+		return result;
+	}
+
+	/**
+	 * FIX for APP4MC<0.9.6
+	 * @param ticks Double
+	 * @param frequency
+	 * @return Time execution time for a given double value derived from the frequency
+	 */
+	public static Time getExecutionTimeForCycles(final double ticks, final Frequency frequency) {
+		final double cyclesPerSecond = AmaltheaServices.convertToHertz(frequency).doubleValue();
+		final double factor = 1.0d / cyclesPerSecond;
+		final Time oneSecond = FactoryUtil.createTime(1, TimeUnit.S);
+		final Time t1 = oneSecond.multiply(ticks);
+		final Time result = t1.multiply(factor);
+		return result.adjustUnit();
+	}
+	/*--------------------------------------END COPY FROM RUNTIMEUTIL------------------------------------------------*/
+
 
 	/**
 	 * @param amalthea Amalthea model
@@ -426,12 +431,18 @@
 	 */
 	public static List<PeriodicStimulus> getSortedStim(final Amalthea amalthea, final boolean... onlyGPUStim) {
 		final List<PeriodicStimulus> stimListSorted = new ArrayList<PeriodicStimulus>();
-		final List<Task> tl = amalthea.getMappingModel().getTaskAllocation().stream()
-				.filter(ta -> ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU)).map(ta -> ta.getTask()).collect(Collectors.toList());
+		List<Task> tl = null;
+		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]) {
+				if (null != onlyGPUStim && onlyGPUStim.length > 0 && null != tl) {
 					for (final Task t : tl) {
 						if (t.getStimuli().contains(ps) && !stimListSorted.contains(ps)) {
 							stimListSorted.add(ps);
@@ -478,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);
@@ -495,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));
 			}
@@ -513,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)) {
@@ -532,7 +540,10 @@
 		return null;
 	}
 
-	/** requires mapping model*/
+	/**
+	 * requires mapping model within the given AMALTHEA model. Prints all task acllocations into log.
+	 * @param amalthea Model
+	 */
 	public void printTaskAllocs(final Amalthea amalthea) {
 		final Logger log = Logger.getLogger(this.getClass().getName().substring(this.getClass().getName().lastIndexOf("." + 1)));
 		for (final TaskAllocation ta : amalthea.getMappingModel().getTaskAllocation()) {
@@ -557,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));
 				}
 			}
@@ -570,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;
@@ -586,24 +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);
+			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 a Chromosome; Decreases efficiency */
+	/** 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++) {
-			// for (final IntegerGene ig : chromosome) {
-			final TaskAllocation ta = AmaltheaFactory.eINSTANCE.createTaskAllocation();
-			ta.setTask(amalthea.getSwModel().getTasks().get(i));
-			ta.getAffinity().add(pul.get(ia[i]));
-			ta.getParameterExtensions().put("Timeslice", "7200us");
-			mm.getTaskAllocation().add(ta);
+		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;
 	}
@@ -664,6 +679,8 @@
 		return pus;
 	}
 
+	@SuppressWarnings("resource")
+	/** writes a stringbuffer into either measurements.csv or optional @param filename */
 	public static void writeCSV(final StringBuffer sbp, final String... filenamep) {
 		if (null == sbp) {
 			Logger.getLogger(CommonUtils.class).error("Nothing to write. Probably, the system is not schedulable.");
@@ -697,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(RuntimeUtil.getExecutionTimeForProcess(task, pu, null, TimeType.WCET));
+				time = time.add(RuntimeUtil.getExecutionTimeForProcess(task, pu, null, SharedConsts.timeType));
 			}
 		}
 		return time;
@@ -717,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()));
 		}
@@ -731,7 +748,7 @@
 	 */
 	public static long getTicksLongForPU(final ProcessingUnit pu, final Task t) {
 		long sum = 0;
-		for (final Ticks ticks : CommonUtils.getTicks(t)) {
+		for (final Ticks ticks : SoftwareUtil.getTicks(t, null)) {
 			if (null != ticks && null != ticks.getExtended() && null != ticks.getExtended().get(pu.getDefinition())) {
 
 				if (null != ticks.getExtended().get(pu.getDefinition())) {
@@ -753,18 +770,14 @@
 
 	/**
 	 * @param t
-	 * @return List of tasks triggered by Task t via interProcessTrigger CallSequenceItem
+	 * @return List of interProcessTriggers of Task t
 	 */
 	public static List<InterProcessTrigger> getTriggered(final Task t) {
-		/*DOES NOT WORK*/
-		//		 t.getCallGraph().getGraphEntries().stream().filter(geb -> geb instanceof CallSequence)
-		//			.map(cs -> ((CallSequence) cs).getCalls()).filter(csi -> csi instanceof InterProcessTrigger).map(csi -> ((InterProcessTrigger) csi))
-		//			.collect(Collectors.toList());
 		final List<InterProcessTrigger> iptl = new ArrayList<>();
-		for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-			if (geb instanceof CallSequence) {
-				final CallSequence cs = (CallSequence) geb;
-				for (final CallSequenceItem csi : cs.getCalls()) {
+		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);
@@ -776,6 +789,59 @@
 	}
 
 	/**
+	 * @param Amalthea model ama
+	 * @param Task t
+	 * @return List of Tasks triggered by Task t
+	 */
+	public static List<Task> getTriggered(final Amalthea ama, final Task t) {
+		final List<Task> tl = new ArrayList<>();
+		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()) {
+							if (tmp.getStimuli().get(0) instanceof InterProcessStimulus) {
+								final InterProcessStimulus ips = (InterProcessStimulus) tmp.getStimuli().get(0);
+								if (ips.equals(ipt.getStimulus())) {
+									tl.add(tmp);
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return tl;
+	}
+
+	/**
+	 * Returns the first task within the given AMALTHEA model, which has the given InterProcessStimulus as a stimulus.
+	 * @param amalthea model to search tasks
+	 * @param ips interProcessStimulus to check
+	 * @return the task, that is activated by the IPS
+	 */
+	public static Task getTrigger(final Amalthea amalthea, final InterProcessStimulus ips) {
+		for (final Task t : amalthea.getSwModel().getTasks()) {
+			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())) {
+								return t;
+							}
+						}
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	/**
 	 * @param model Amalthea
 	 * @param ia task to processing unit mapping int array
 	 * @param t Task under consideration
@@ -784,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());
@@ -803,10 +869,38 @@
 	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;
 	}
+
+	/**
+	 * Determines whether given processing unit as index is a GPU or CPU
+	 * @param pul list of PUs, of which GPUs are at the list's tail (end)
+	 * @param index of the PU within given list to be chaecked
+	 * @return true if pu index is a GPU
+	 */
+	public static boolean isGPUTask(final List<ProcessingUnit> pul, final int index) {
+		if (pul.get(index).getDefinition().getPuType().equals(PuType.CPU)) {
+			return false;
+		}
+		return true;
+	}
+
+	/**
+	 * @param ama Amalthea model
+	 * @param t Task
+	 * @param tpumap Task to PU mapping
+	 * @return true, if triggered task is mapped to GPU
+	 */
+	public static boolean taskTriggersGPUTask(final Amalthea ama, final Task t, final int[] tpumap) {
+		for (final Task trigger : getTriggered(ama, t)) {
+			if (tpumap[ama.getSwModel().getTasks().indexOf(trigger)] >= getNumberofCPUs(ama)) {
+				return true;
+			}
+		}
+		return false;
+	}
 }
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 c68bf5d..ed5127e 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
@@ -21,8 +21,8 @@
 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;
@@ -32,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;
@@ -50,12 +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;
-		this.flagArray = new int[iap.length];
+		if(iap != null) {
+			this.flagArray = new int[iap.length];
+			return ;
+		}
+		this.flagArray = null;
 	}
 
 	/**
@@ -79,12 +83,10 @@
 	}
 
 	/**
-	 * 	Initiallize hashmap contain GPU tasks' labels hashmap <task, List<label>> (readList = hashmap.get(task)[0];)
+	 * 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
-
-		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
-	 *
+	 * 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
 	 * @param tpumapping (or ia)
 	 */
 	private void setUpFlagArrayAndHashMap(final int[] iap) {
@@ -96,6 +98,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);
@@ -106,8 +111,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 (
@@ -118,8 +123,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)) {
@@ -128,8 +133,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)) {
@@ -139,9 +144,9 @@
 				}
 			}
 
-			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>
 		}
@@ -157,7 +162,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
@@ -222,7 +226,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
@@ -251,7 +255,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
@@ -361,8 +365,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);
@@ -487,7 +491,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++) {
@@ -517,7 +521,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]);
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
deleted file mode 100644
index 4febdc0..0000000
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CpuRTA.java
+++ /dev/null
@@ -1,587 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.
- *
- * This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors: FH Dortmund - initial API and implementation
- * 
- *******************************************************************************/
-package org.eclipse.app4mc.gsoc_rta;
-
-import java.io.File;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.log4j.Logger;
-import org.eclipse.app4mc.amalthea.model.Amalthea;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
-import org.eclipse.app4mc.amalthea.model.ClearEvent;
-import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
-import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
-import org.eclipse.app4mc.amalthea.model.Label;
-import org.eclipse.app4mc.amalthea.model.LabelAccess;
-import org.eclipse.app4mc.amalthea.model.LabelAccessEnum;
-import org.eclipse.app4mc.amalthea.model.Preemption;
-import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
-import org.eclipse.app4mc.amalthea.model.PuType;
-import org.eclipse.app4mc.amalthea.model.Runnable;
-import org.eclipse.app4mc.amalthea.model.SetEvent;
-import org.eclipse.app4mc.amalthea.model.Task;
-import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;
-import org.eclipse.app4mc.amalthea.model.Time;
-import org.eclipse.app4mc.amalthea.model.TimeUnit;
-import org.eclipse.app4mc.amalthea.model.WaitEvent;
-import org.eclipse.app4mc.amalthea.model.io.AmaltheaLoader;
-import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
-import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
-import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
-import org.eclipse.emf.common.util.EList; 
-
-/**
- * Date: June 21-2019 
- * @author Junhyung Ki
- * @version 1.0
- *				This class is to analyze Response Times of CPU(e.g., ARM, Denver cores) Tasks in a CPU-GPU Heterogeneous System
- *				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.
- */
-public class CpuRTA {
-	public final File inputFile = new File("model-input/WATERS19_release/ChallengeModel_release.amxmi");
-	
-	/**
-	 * Get Default IA Map
-	 * @return
-	 * 			this.defaultIAMapping
-	 */
-	public int[] getDefaultIAMapping() {
-		return SharedConsts.defaultIAMapping;
-	}
-	
-	private Amalthea model;
-
-	/**
-	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
-	 *
-	 * @return
-	 * 			The Amalthea model object of the current CPURtaIA class
-	 */
-	public Amalthea getModel() {
-		return this.model;
-	}
-	
-	/**
-	 * 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.setGTCL(this.model);
-	}
-	
-	private HashMap<Task, Time> trt = null;
-	
-	/**
-	 * Since this method is used by GAMapping, the visibility should be 'public'
-	 *
-	 * @return
-	 * 			trt(task with response time) HashMap variable
-	 */
-	public HashMap<Task, Time> getTRT() {
-		return this.trt;
-	}
-	
-	/**
-	 * Set the trt(task with response time) HashMap variable as the given trtp parameter variable.
-	 * Which would contains GPU tasks' response times from the beginning
-	 *
-	 * @param trtp				the HashMap variable parameter which would reinitialize the trt variable of the current 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 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
-	 */
-	public HashMap<Task, Time> getDefaultTRT(final Amalthea model) {
-		final HashMap<Task, Time> trt = new HashMap<Task, Time>();
-		final EList<Task> allTaskList = model.getSwModel().getTasks();
-		final long val = 2000000000;
-		for (final Task t : allTaskList) {
-			if (this.gpuTaskList.contains(t)) {
-				trt.put(t, FactoryUtil.createTime(BigInteger.valueOf(val), TimeUnit.PS));
-			}
-			else {
-				trt.put(t, FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS));
-			}
-		}
-		return trt;
-	}
-	
-	private int[] tpuMapping = null;
-
-	/**
-	 * Since this method is used by RTARuntimeUtil, the visibility should be '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 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()) {
-			this.tpuMapping = tpumap;
-		}
-		else {
-			log.error("integer array size MUST match the number of tasks");
-		}
-	}
-	
-	private List<ProcessingUnit> pul = new ArrayList<>();
-
-	/**
-	 * Get a list of ProcessingUnits
-	 * 
-	 * @return
-	 * 			this.pul
-	 */
-	public List<ProcessingUnit> getPUl() {
-		return this.pul;
-	}
-	
-	/**
-	 * Set the pul, the list of Processing Units variable (which would be used to map tasks along with tpuMapping array)
-	 * as the given pul parameter variable.
-	 *
-	 * @param pul 				the parameter pul list which would reinitialize the pul list variable of the current CPURtaIA class
-	 */
-	public void setPUl(final List<ProcessingUnit> pul) {
-		this.pul = pul;
-	}
-	
-	//TODO: Contention not considered
-	
-	private List<Task> gpuTaskList = new ArrayList<Task>();
-
-	/**
-	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
-	 *
-	 * @return
-	 * 			gpuTaskList which contains tasks (which are originally designed for GPU) of the Amalthea model
-	 */
-	protected List<Task> getGpuTaskList() {
-		return this.gpuTaskList;
-	}
-
-	private final List<Task> triggeringTaskList = new ArrayList<Task>();
-	/**
-	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
-	 *
-	 * @return
-	 * 			triggeringTaskList which contains tasks (which contain InterProcessTrigger) of the Amalthea model
-	 */
-	protected List<Task> getTriggeringTaskList() {
-		return this.triggeringTaskList;
-	}
-	
-	/* this runnable is used to calculate execution time in RTARuntimeUtil class */
-	protected Runnable offloadingAsyncRunnable = null;
-	
-	private final HashMap<Task, List<Label>[]> gpuToCpuLabels = new HashMap<Task, List<Label>[]>();
-	
-	/**
-	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
-	 *
-	 * @return
-	 * 			gpuToCpuLabels HashMap which contains required labels (of the corresponding task)
-	 * 			that need to be taken into account when GPU tasks are mapped to CPU
-	 */
-	protected HashMap<Task, List<Label>[]> getGTCL() {
-		return this.gpuToCpuLabels;
-	}
-	
-	/**
-	 * Not only set gpuToCpuLabels HashMap, this also set gpuTaskList (only contains GPU tasks),
-	 * triggeringTaskList (only contains tasks with InterProcessTrigger)
-	 * and offloadingAsyncRunnable (the Runnable that is taken into account for triggering tasks when the mode is asynchronous)
-	 *
-	 * @param model				the parameter Amalthea model which is used to derived required labels of the corresponding GPU task
-	 */
-	@SuppressWarnings("unchecked")
-	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 (RuntimeUtilRTA.doesTaskHaveAsyncRunnable(t, this)) {
-						final List<CallSequenceItem> cList = SoftwareUtil.collectCalls(t, null, (call -> call instanceof TaskRunnableCall || 
-								call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
-						final int waitIndex = cList.indexOf(cList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
-						final int asyncOffloadingIndex = waitIndex + 1;
-						if (cList.get(asyncOffloadingIndex) instanceof TaskRunnableCall) {
-							this.offloadingAsyncRunnable = ((TaskRunnableCall) cList.get(asyncOffloadingIndex)).getRunnable();
-						}
-					}
-				}
-			}
-			for (final Task t : this.gpuTaskList) {
-				final InterProcessStimulus ips = (InterProcessStimulus) (t.getStimuli().get(0));
-				Task triggeringTask = null;
-				for (final Task tt : this.triggeringTaskList) {
-					final InterProcessTrigger ipt = (InterProcessTrigger) SoftwareUtil.collectCalls(tt, null, 
-							(call -> call instanceof InterProcessTrigger)).stream().iterator().next();
-					if (ips.equals(ipt.getStimulus())) {
-						triggeringTask = tt;
-						break;
-					}
-				}
-				final List<Label> readLabelList = new ArrayList<Label>();
-				final List<Label> writeLabelList = new ArrayList<Label>();
-				final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(triggeringTask, null, (call -> call instanceof TaskRunnableCall || 
-						call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
-				final InterProcessTrigger ipt = (InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next();
-				final int indexforTrigger = callList.indexOf(ipt);
-				for (int i = 0; i < callList.size(); i++) {
-					Runnable thisRunnable = null;
-					/* Pre-processing Runnable */
-					if ((i < indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
-						thisRunnable = (Runnable) ((TaskRunnableCall) callList.get(i)).getRunnable();
-						final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
-						for (final LabelAccess la : thisLAList) {
-							if (la.getAccess().equals(LabelAccessEnum.READ)) {
-								readLabelList.add(la.getData());
-							}
-						}
-					}
-					/* Post-processing Runnable */
-					else if ((i > indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
-						thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
-						final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
-						for (final LabelAccess la : thisLAList) {
-							if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
-								writeLabelList.add(la.getData());
-							}
-						}
-					}
-				}
-				final List<Label>[] aryofLabelList = new ArrayList[2];
-				aryofLabelList[0] = readLabelList;
-				aryofLabelList[1] = writeLabelList;
-				this.gpuToCpuLabels.put(t, aryofLabelList);
-			}
-		}
-		else {
-			this.gpuTaskList.clear();
-			this.triggeringTaskList.clear();
-			this.offloadingAsyncRunnable = null;
-			this.gpuToCpuLabels.clear();
-		}
-	}
-	
-	// TODO: Consider Offloading Runnable
-	// TODO: Cumulative Latency Time
-	public static void main(String[] args) {
-		org.apache.log4j.BasicConfigurator.configure();
-		final CpuRTA cpurta = new CpuRTA();
-		cpurta.setModel(AmaltheaLoader.loadFromFile(cpurta.inputFile));
-		cpurta.setTRT(cpurta.getDefaultTRT(cpurta.getModel()));
-		cpurta.setIA(SharedConsts.defaultIAMapping);
-		cpurta.setPUl(CommonUtils.getPUs(cpurta.getModel()));
-		cpurta.run();
-	}
-	
-	/**
-	 * Executable method
-	 */
-	public void run() {
-		final Logger log = Logger.getLogger(CpuRTA.class);
-		if (this.model == null) {
-			log.error("No model loaded!");
-			return;
-		}
-		log.debug("\n####################### The Test ########################\n");
-		log.debug("RT Time Sum: " + getCPUResponseTimeSum(SharedConsts.timeType));
-	}
-
-	/**
-	 * Calculate the total sum of response times of the tasks of the given Amalthea model with the mapping model (tpuMapping)
-	 *
-	 * @param executionCase		BCET, ACET, WCET
-	 * @return
-	 * 			total sum of all tasks' response times of the given mapped model (tpuMapping)
-	 */
-	public Time getCPUResponseTimeSum(final TimeType executionCase) {
-		final Logger log = Logger.getLogger(CpuRTA.class);
-		if (this.model == null) {
-			log.error("No Model Loaded!");
-			return null;
-		}
-		else if (this.trt == null) {
-			log.error("No HashMap Loaded!");
-			return null;
-		}
-		else if (this.tpuMapping == null) {
-			log.error("No IntegerArray Loaded!");
-			return null;
-		}
-		else if (this.pul == null) {
-			log.error("No PUList Loaded!");
-			return null;
-		}
-		// TODO: Contention
-		Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-		for (int i = 0; i < this.tpuMapping.length; i++) {
-			final Time rt = getTaskCPURT(this.model.getSwModel().getTasks().get(i), executionCase);
-			if (rt.getValue().equals(BigInteger.valueOf(Long.MAX_VALUE)) && !SharedConsts.ignoreInfeasibility) {
-				return rt;
-			}
-			time = time.add(rt);
-			if (!rt.getValue().equals(BigInteger.ZERO)) {
-				/* only put CPU tasks */
-				this.trt.put(this.model.getSwModel().getTasks().get(i), rt);
-			}
-		}
-		return time;
-	}
-	
-	/**
-	 * Calculate response time of the given task of the given Amalthea model with the mapping model (tpuMapping)
-	 *
-	 * @param task				the observed task
-	 * @param executionCase		BCET, ACET, WCET
-	 * @return
-	 * 			response time of the observed task
-	 */
-	protected Time getTaskCPURT(final Task task, final TimeType executionCase) {
-		/* 1. validate thisTask is mapped to CPU */
-		final int tindex = this.model.getSwModel().getTasks().indexOf(task);
-		final int puindex = this.tpuMapping[tindex];
-		final ProcessingUnit pu = this.pul.get(puindex);
-		if (!pu.getDefinition().getPuType().equals(PuType.CPU)) {
-			Logger.getLogger(CpuRTA.class).debug(task.getName() + " is not mapped to a CPU");
-			return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-		}
-		/* 2. get all tasks mapped to this CPU */
-		final List<Task> puTaskList = new ArrayList<Task>();
-		for (int i = 0; i < this.tpuMapping.length; i++) {
-			if (this.tpuMapping[i] == puindex) {
-				puTaskList.add(this.model.getSwModel().getTasks().get(i));
-			}
-		}
-		final List<Task> sortedTaskList = taskSorting(puTaskList);
-		return preciseTestCPURT(task, sortedTaskList, executionCase, pu);
-	}
-	
-	/**
-	 * Sort out the given list of tasks (in order of shorter period first - Rate Monotonic Scheduling)
-	 *
-	 * @param taskList			list of tasks that is mapped to the same core
-	 * @return
-	 * 			the sorted list of tasks
-	 */
-	private List<Task> taskSorting(final List<Task> taskList) {
-		/* Getting stimuliList out of the given taskList (because it is RMS) */
-		final List<Time> stimuliList = new ArrayList<>();
-		for (final Task t : taskList) {
-			stimuliList.add(CommonUtils.getStimInTime(t));
-		}
-		/* Sorting (Shortest Period(Time) first) */
-		Collections.sort(stimuliList, new TimeCompIA());
-		/* Sort tasks to the newTaskList in order of Period length (shortest first
-		 * longest last)-(according to the stimuliList) */
-		final List<Task> newTaskList = new ArrayList<>();
-		for (int i = 0; i < stimuliList.size(); i++) {
-			for (final Task t : taskList) {
-				if ((!newTaskList.contains(t)) && (stimuliList.get(i).compareTo(CommonUtils.getStimInTime(t)) == 0)) {
-					newTaskList.add(t);
-				}
-			}
-		}
-		return newTaskList;
-	}
-	
-	/**
-	 * Visibility - public (This method is for the UI version code (ui package > RTApp.java))
-	 * Calculate response time of the observed task according to the periodic tasks response time analysis algorithm.
-	 *
-	 * @param task				the observed task
-	 * @param taskList			list of tasks that is mapped to the same core
-	 * @param executionCase		BCET, ACET, WCET
-	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
-	 * @return
-	 * 			response time of the observed task
-	 */
-	public Time preciseTestCPURT(final Task task, final List<Task> taskList, final TimeType executionCase, final ProcessingUnit pu) {
-		final Logger log = Logger.getLogger(CpuRTA.class);
-		Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-		Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-		if (taskList.size() == 0) {
-			log.debug("!!! This taskList is empty so I am returning MAX !!!");
-			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-		}
-		/* to check if the given task is in the taskList */
-		int flag = 0;
-		int index = 0;
-		for (int i = 0; i < taskList.size(); i++) {
-			if (task.equals(taskList.get(i))) {
-				flag = 1;
-				index = i;
-				break;
-			}
-		}
-		if (flag == 0) {
-			log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
-			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-		}
-		final RuntimeUtilRTA rtaut = new RuntimeUtilRTA();
-		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) {
-					// TODO: cumulative if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0)
-					return thisRT;
-				}
-				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
-						+ " for task " + task.getName());
-				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-			}
-			else if (i == index) {
-				/* In the case of a COOPERATIVE Preemption typed Task */
-				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;
-								// TODO: cumulative if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0)
-								return thisRT;
-							}
-							culmulativeRT = culmulativeRT_x;
-						}
-						else {
-							log.debug("!!! This is non schedulable...!!! Because of the period " + period
-									+ " being less than the response time (culmulativeRT_x) of " + culmulativeRT_x + " for task " + task.getName());
-							if (SharedConsts.ignoreInfeasibility) {
-								return culmulativeRT_x;
-							}
-							return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-						}
-					}
-				}
-				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + culmulativeRT
-						+ " for task " + task.getName());
-				if (SharedConsts.ignoreInfeasibility) {
-					return culmulativeRT;
-				}
-				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-			}
-		}
-		// TODO: cumulative if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0)
-		return thisRT;
-	}
-	
-	/**
-	 * Visibility - public (This method is for the UI version code (ui package > RTApp.java))
-	 * It returns HashMap<Integer, List<Task>> Type reference that contains an Integer(number of Processing Unit index) and the corresponding List of Tasks
-	 * This is to visualize which task is mapped to which processing unit.
-	 * 
-	 * @return
-	 * 			HashMap<Integer, List<Task>> puListHashMap
-	 */
-	public HashMap<Integer, List<Task>> be_getPUTaskListHashMap(final Amalthea model) {
-		HashMap<Integer, List<Task>> puListHashMap = new HashMap<>();
-		final EList<Task> allTaskList = model.getSwModel().getTasks();
-		for(int i = 0; i < this.pul.size(); i++) {
-			final List<Task> puTaskList = new ArrayList<Task>();
-			for(int j = 0; j < this.tpuMapping.length; j++) {
-				final int puIndex = this.tpuMapping[j];
-				if (i == puIndex) {
-					puTaskList.add(allTaskList.get(j));
-				}
-			}
-			puListHashMap.put(i, taskSorting(puTaskList));
-		}
-		return puListHashMap;
-	}
-}
-
-/**
- * @Date: June 21-2019 
- * @author Junhyung Ki
- * @version 1.0
- *			This inner class is used for the method "taskSorting" to help compare between two tasks' periods (which is longer)
- *			If the time of arg0 is shorter than that of arg1, it returns -1.
- *			If the time of arg0 is longer than that of arg1, it returns 1.
- */
-class TimeCompIA implements Comparator<Time> {
-	@Override
-	public int compare(final Time arg0, final Time arg1) {
-		if (arg0.compareTo(arg1) < 0) {
-			return -1;
-		}
-		return 1;
-	}
-}
\ 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
new file mode 100644
index 0000000..3840d3d
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
@@ -0,0 +1,1389 @@
+/*******************************************************************************
+ * 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.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.Logger;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
+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.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;
+
+public class E2ELatency {
+	final Logger log = Logger.getLogger(E2ELatency.class);
+	public static StringBuffer sb = new StringBuffer();
+	
+	public enum SinglecoreLatCase {
+		CriInitRct, BCInitRct, WCInitRct, 
+		CriWCRct, BCWCRct, WCWCRct
+	}
+	
+	public enum MulticoreLatCase {
+		BCRctIm, BCRctLET, 
+		WCRctIm, WCRctLET, 
+		BCInitRctIm, BCInitRctLET, 
+		WCInitRctIm, WCInitRctLET, 
+		BCAgeIm, BCAgeLET, 
+		WCAgeIm, WCAgeLET
+	}
+
+	/**
+	 * To derive the total sum of all task chains' latency values
+	 * @param cpurta		the instance of CPURta class
+	 * @param pu			processing unit that computes task chains' latency
+	 * @param latCase		the target single-core latency case
+	 * @return
+	 * 						the total sum of all task chains' latency values
+	 */
+	public Time getSingleTCLsum(final CPURta cpurta, final ProcessingUnit pu, final SinglecoreLatCase latCase) {
+		if (cpurta == null) {
+			log.debug("The cpurta instance is empty. Please check the instance.");
+			return null;
+		} else if (cpurta.getModel() == null) {
+			log.debug("Model is empty. Please check the model path.");
+			return null;
+		}
+		Time tclSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final EList<EventChain> ecList = cpurta.getModel().getConstraintsModel().getEventChains();
+		for (int i = 0; i < ecList.size(); i++) {
+			final EventChain chain = ecList.get(i);
+			log.debug("\n");
+			log.debug(" ----- " + chain.getName() + " ----- ");
+			Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			if (latCase.equals(SinglecoreLatCase.CriInitRct) || latCase.equals(SinglecoreLatCase.BCInitRct) 
+					|| latCase.equals(SinglecoreLatCase.WCInitRct)) {
+				lat = this.getSingleCoreInitialRct(ecList.get(i), pu, latCase, cpurta);
+			} else if (latCase.equals(SinglecoreLatCase.CriWCRct) || latCase.equals(SinglecoreLatCase.BCWCRct) 
+					|| latCase.equals(SinglecoreLatCase.WCWCRct)) {
+				lat = this.getSingleCoreWCRct(chain, pu, latCase, cpurta);
+			} 
+			tclSum = tclSum.add(lat);
+		}
+		return tclSum;
+	}
+	
+	/**
+	 * To derive the total sum of all task chains' multi-core latency values
+	 * @param cpurta		the instance of CPURta class
+	 * @param latCase		the target multi-core latency case
+	 * @return
+	 * 						the total sum of all task chains' multi-core latency values
+	 */
+	public Time getMultiTCLsum(final CPURta cpurta, final MulticoreLatCase latCase) {
+		if (cpurta == null) {
+			log.debug("The cpurta instance is empty. Please check the instance.");
+			return null;
+		} else if (cpurta.getModel() == null) {
+			log.debug("Model is empty. Please check the model path.");
+			return null;
+		}
+		Time tclSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final EList<EventChain> ecList = cpurta.getModel().getConstraintsModel().getEventChains();
+		for (int i = 0; i < ecList.size(); i++) {
+			final EventChain chain = ecList.get(i);
+			log.debug("");
+			log.debug(" ----- " + chain.getName() + " ----- ");
+			Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			if (latCase.equals(MulticoreLatCase.BCRctIm)) {
+				lat = this.getBCReactionImplicit(chain, cpurta);
+				log.debug("Best-case Task-Chain Reaction(Implicit): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.BCRctLET)) {
+				lat = this.getBCReactionLET(chain, cpurta);
+				log.debug("Best-case Task-Chain Reaction(LET): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.WCRctIm)) {
+				lat = this.getWCReactionImplicit(chain, cpurta);
+				log.debug("Worst-case Task-Chain Reaction(Implicit): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.WCRctLET)) {
+				lat = this.getWCReactionLET(chain, cpurta);
+				log.debug("Worst-case Task-Chain Reaction(LET): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.BCInitRctIm)) {
+				lat = this.getBCInitialRctImplicit(chain, cpurta);
+				log.debug("Best-case Initial Task-Chain Reaction(Implicit): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.BCInitRctLET)) {
+				lat = this.getBCInitialRctLET(chain, cpurta);
+				log.debug("Best-case Initial Task-Chain Reaction(LET): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.WCInitRctIm)) {
+				lat = this.getWCInitialRctImplicit(chain, cpurta);
+				log.debug("Worst-case Initial Task-Chain Reaction(Implicit): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.WCInitRctLET)) {
+				lat = this.getWCInitialRctLET(chain, cpurta);
+				log.debug("Worst-case Initial Task-Chain Reaction(LET): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.BCAgeIm)) {
+				lat = this.getBCAgeImplicit(chain, cpurta);
+				log.debug("Best-case Task-Chain Age(Implicit): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.BCAgeLET)) {
+				lat = this.getBCAgeLET(chain, cpurta);
+				log.debug("Best-case Task-Chain Age(LET): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.WCAgeIm)) {
+				lat = this.getWCAgeImplicit(chain, cpurta);
+				log.debug("Worst-case Task-Chain Age(Implicit): " + lat);
+			} else if (latCase.equals(MulticoreLatCase.WCAgeLET)) {
+				lat = this.getWCAgeLET(chain, cpurta);
+				log.debug("Worst-case Task-Chain Age(LET): " + lat);
+			}
+			if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) < 0) {
+				log.error("Error: Latency is smaller than 0!");
+				return null;
+			}
+			tclSum = tclSum.add(lat);
+		}
+		log.debug("");
+		return tclSum;
+	}
+	
+	/**
+	 * 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
+	 */
+	protected boolean isTheRTAClassReadySingle(final CPURta cpurta) {
+		if (cpurta.getModel() == null) {
+			log.debug("Model 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;
+	}
+	
+	/**
+	 * 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
+	 */
+	protected boolean isTheRTAClassReadyMulti(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;
+	}
+
+	/**
+	 * To derive the observed event chain's initial single-core reaction according to the target latency case
+	 * @param ec			the observed event chain
+	 * @param pu			processing unit that computes the observed event chain
+	 * @param latCase		the target single-core latency case (critical-case, best-case, worst-case)
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the initial single-core reaction time of the observed event chain with the given latCase
+	 */
+	public Time getSingleCoreInitialRct(final EventChain ec, final ProcessingUnit pu, final SinglecoreLatCase latCase, final CPURta cpurta) {
+		if (isTheRTAClassReadySingle(cpurta)) {
+			if (latCase.equals(SinglecoreLatCase.CriWCRct) || latCase.equals(SinglecoreLatCase.BCWCRct) 
+					|| latCase.equals(SinglecoreLatCase.WCWCRct)) {
+				log.error("latCase needs to be changed into one of three: CriInitRct, BCInitRct, WCInitRct");
+				return null;
+			}
+			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_0 = taskChain.get(0);
+			final List<Task> sortedChain = cpurta.taskSorting(taskChain);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time hyper = this.getHyperPeriod(sortedChain);
+			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 List<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, pu, cpurta);
+				/* Critical-case */
+				if ((i == 0) && latCase.equals(SinglecoreLatCase.CriInitRct)) {
+					return lat;
+				}
+				if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+					latencyList.add(lat);
+				}
+				log.debug(i + "-th instance: " + lat);
+			}
+			Collections.sort(latencyList, new TimeComp());
+			/* Best-case */
+			if (latCase.equals(SinglecoreLatCase.BCInitRct)) {
+				return latencyList.get(0);
+			}
+			/* Worst-case */
+			return latencyList.get(latencyList.size()-1);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+
+	/**
+	 * To derive the initial single-core reaction that starts with (i+1)_th instance of the first task
+	 * in the observed event chain (in the hyper-period with the critical instant)
+	 * @param i				the number(i+1) of the observed instance of the first of the event chain in the hyper-period
+	 * @param ec			the observed event chain
+	 * @param pu			processing unit that computes the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the initial single-core reaction of the observed task chain starting with (i+1)_th instance of the first task
+	 */
+	protected Time getSingleCoreInitialRct_(final int i, final EventChain ec, final ProcessingUnit pu, final CPURta cpurta) {
+		if (isTheRTAClassReadySingle(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, taskChain, pu, 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());
+				final List<Task> preHPList = cpurta.getHigherPriorityTasksInChain(preTask, taskChain);
+				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, taskChain, pu, cpurta);
+				Time taskCRRT = this.getCRtoRT(offset, task, taskChain, pu, cpurta);
+				/* The current task is a higher priority than the previous one */
+				if (preHPList.contains(task)) {
+					final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, taskChain, pu, 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, taskChain, pu, cpurta);
+					if (preTaskCRIP.compareTo(taskCRIP) < 0) {
+						offset = offset-1;
+						taskCRIP = this.getCRtoIP(offset, task, taskChain, pu, 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, taskChain, pu, 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;
+	}
+	
+	/**
+	 * To derive the observed event chain's worst-case single-core reaction according to the target latency case
+	 * @param ec			the observed event chain
+	 * @param pu			processing unit that computes the observed event chain
+	 * @param latCase		the target single-core latency case (critical-case, best-case, worst-case)
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case single-core reaction time of the observed event chain with the given latCase
+	 */
+	public Time getSingleCoreWCRct(final EventChain ec, final ProcessingUnit pu, final SinglecoreLatCase latCase, final CPURta cpurta) {
+		if (isTheRTAClassReadySingle(cpurta)) {
+			if (latCase.equals(SinglecoreLatCase.CriInitRct) || latCase.equals(SinglecoreLatCase.BCInitRct) 
+					|| latCase.equals(SinglecoreLatCase.WCInitRct)) {
+				log.error("latCase needs to be changed into one of three: CriWCRct, BCWCRct, WCWCRct");
+				return null;
+			}
+			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_0 = taskChain.get(0);
+			final List<Task> sortedChain = cpurta.taskSorting(taskChain);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time hyper = this.getHyperPeriod(sortedChain);
+			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 List<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, pu, cpurta);
+				/* Critical-case */
+				if ((i == 0) && latCase.equals(SinglecoreLatCase.CriWCRct)) {
+					return lat;
+				}
+				if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+					latencyList.add(lat);
+				}
+				log.debug(i + "-th instance: " + lat);
+			}
+			Collections.sort(latencyList, new TimeComp());
+			/* Best-case */
+			if (latCase.equals(SinglecoreLatCase.BCWCRct)) {
+				return latencyList.get(0);
+			}
+			/* Worst-case */
+			return latencyList.get(latencyList.size()-1);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	/**
+	 * To derive the worst-case single-core reaction that starts with (i+1)_th instance of the first task
+	 * in the observed event chain (in the hyper-period with the critical instant)
+	 * @param i				the number(i+1) of the observed instance of the first of the event chain in the hyper-period
+	 * @param ec			the observed event chain
+	 * @param pu			processing unit that computes the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case single-core reaction of the observed task chain starting with (i+1)_th instance of the first task
+	 */
+	protected Time getSingleCoreWCRct_(final int i, final EventChain ec, final ProcessingUnit pu, final CPURta cpurta) {
+		if (isTheRTAClassReadySingle(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, taskChain, pu, 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());
+				final List<Task> preHPList = cpurta.getHigherPriorityTasksInChain(preTask, taskChain);
+				final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+				/* 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, taskChain, pu, 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, taskChain, pu, cpurta);
+					final Time crrt_cr_ = this.getCRtoRT(offwhp-1, task, taskChain, pu, 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, taskChain, pu, cpurta);
+					final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, taskChain, pu, 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, taskChain, pu, 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, taskChain, pu, 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, taskChain, pu, 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;
+	}
+	
+	/**
+	 * this method is used by getSingleCoreWCRct_() when getSingleCoreWCRct_() fails to identify a valid task's instance.
+	 * the method is intended to find an alternative chain path from the time point of prepre: 
+	 * : the finishing point of the worst-case reaction of the successor of preTask.
+	 * @param task			the observed task
+	 * @param preTask		the successor of the observed task
+	 * @param k				constant to subtract to calculate the initial point to identify the alternative chain path
+	 * @param pre			the finishing point of the worst-case reaction of preTask
+	 * @param prepre		the finishing point of the worst-case reaction of the successor of preTask
+	 * @param chain			the observed task chain
+	 * @param pu			processing unit that computes the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the alternative getSingleCoreWCRct_() result (the crwc time value of the observed task)
+	 */
+	private Time getCRWC(final Task task, final Task preTask, final long k, 
+			final Time pre, final Time prepre, final List<Task> chain, final ProcessingUnit pu, 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, chain, pu, cpurta);
+		final Time crrtCr = this.getCRtoRT(offcr, task, chain, pu, cpurta);
+		final Time crrtCr_ = this.getCRtoRT(offcr_, task, chain, pu, cpurta);
+		final Time cripCr = this.getCRtoIP(offcr, task, chain, pu, cpurta);
+		final Time cripCr_ = this.getCRtoIP(offcr_, task, chain, pu, 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, chain, pu, cpurta);
+		}
+	}
+	
+	/**
+	 * to derive the best-case reaction of the observed event chain with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case reaction of the observed event chain with Implicit communication
+	 */
+	public Time getBCReactionImplicit(final EventChain ec, final CPURta cpurta) {
+		Time bcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case reaction of the observed event chain with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case reaction of the observed event chain with Implicit communication
+	 */
+	public Time getWCReactionImplicit(final EventChain ec, final CPURta cpurta) {
+		Time wcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case initial reaction of the observed event chain with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case initial reaction of the observed event chain with Implicit communication
+	 */
+	public Time getBCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
+		return getBCReactionImplicit(ec, cpurta);
+	}
+	
+	/**
+	 * to derive the worst-case initial reaction of the observed event chain with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case initial reaction of the observed event chain with Implicit communication
+	 */
+	public Time getWCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
+		Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case reaction of the observed event chain with LET communication
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case reaction of the observed event chain with LET communication
+	 */
+	public Time getBCReactionLET(final EventChain ec, final CPURta cpurta) {
+		Time bcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case reaction of the observed event chain with LET communication
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case reaction of the observed event chain with LET communication
+	 */
+	public Time getWCReactionLET(final EventChain ec, final CPURta cpurta) {
+		Time wcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case initial reaction of the observed event chain with LET communication
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case initial reaction of the observed event chain with LET communication
+	 */
+	public Time getBCInitialRctLET(final EventChain ec, final CPURta cpurta) {
+		return getBCReactionLET(ec, cpurta);
+	}
+	
+	/**
+	 * to derive the worst-case initial reaction of the observed event chain with LET communication
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case initial reaction of the observed event chain with LET communication
+	 */
+	public Time getWCInitialRctLET(final EventChain ec, final CPURta cpurta) {
+		Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case age of the observed event chain with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case age of the observed event chain with Implicit communication
+	 */
+	public Time getBCAgeImplicit(final EventChain ec, final CPURta cpurta) {
+		Time bcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case age of the observed event chain with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case age of the observed event chain with Implicit communication
+	 */
+	public Time getWCAgeImplicit(final EventChain ec, final CPURta cpurta) {
+		Time wcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the subtraction between the worst- and best-case reaction times of the observed event chain with Implicit communication
+	 * (to compare to the worst-case age of the observed event chain with Implicit communication)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the subtraction between the worst- and best-case reaction times with Implicit communication
+	 */
+	public Time getWCBCSubAgeImplicit(final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case age of the observed event chain with LET communication
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case age of the observed event chain with LET communication
+	 */
+	public Time getBCAgeLET(final EventChain ec, final CPURta cpurta) {
+		Time bcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case age of the observed event chain with LET communication
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case age of the observed event chain with LET communication
+	 */
+	public Time getWCAgeLET(final EventChain ec, final CPURta cpurta) {
+		Time wcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the subtraction between the worst- and best-case reaction times of the observed event chain with LET communication
+	 * (to compare to the worst-case age of the observed event chain with LET communication)
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the subtraction between the worst- and best-case reaction times with LET communication
+	 */
+	public Time getWCBCSubAgeLET(final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReadyMulti(cpurta)) {
+			final Time wcRctLET = this.getWCReactionLET(ec, cpurta);
+			final Time bcRctLET = this.getBCReactionLET(ec, cpurta);
+			return wcRctLET.subtract(bcRctLET);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	/**
+	 * to derive the best-case task age latency of the observed task with Implicit communication 
+	 * (for now calculation is done with direct response time functions)
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case task age latency of the observed task with Implicit communication
+	 */
+	public Time getBCTaskAgeImplicit(final Task task, final CPURta cpurta) {
+		Time bcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case task age latency of the observed task with Implicit communication
+	 * (for now calculation is done with direct response time functions)
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case task age latency of the observed task with Implicit communication
+	 */
+	public Time getWCTaskAgeImplicit(final Task task, final CPURta cpurta) {
+		Time wcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case data age regarding the observed label in the given event chain
+	 * @param label			the observed label
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case data age regarding the observed label in the given event chain
+	 */
+	public Time getBCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case data age regarding the observed label in the given event chain
+	 * @param label			the observed label
+	 * @param ec			the observed event chain
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case data age regarding the observed label in the given event chain
+	 */
+	public Time getWCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the best-case intial pending time of the observed task
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the best-case intial pending time of the observed task
+	 */
+	protected Time getBCInitialPending(final Task task, final CPURta cpurta) {
+		if (this.isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the worst-case initial pending time of the observed task with the observed task chain
+	 * @param task			the observed task
+	 * @param chain			the observed task chain
+	 * @param pu			processing unit that computes to derive the wc initial pending time
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case initial pending time of the observed task in the observed task chain
+	 */
+	protected Time getWCInitialPending(final Task task, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
+		if (this.isTheRTAClassReadySingle(cpurta)) {
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final List<Task> hpList = cpurta.getHigherPriorityTasksInChain(task, chain);
+			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;
+	}
+	
+	/**
+	 * to derive the worst-case initial pending time of the observed task 
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the worst-case initial pending time of the observed task
+	 */
+	protected Time getWCInitialPending(final Task task, final CPURta cpurta) {
+		if (this.isTheRTAClassReadyMulti(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;
+	}
+	
+	/**
+	 * to derive the time between the critical instant and the given offset's task instance's finishing point 
+	 * @param offset		the offset constant number (to set the initial point to analyze, initial point: offset * period of task)
+	 * @param task			the target task to derive the time between the critical instant and its current instance's finishing point
+	 * @param chain			the observed task chain
+	 * @param pu			processing unit that computes to derive the crrt time
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the time between the critical instant and the given offset's task instance's finishing point 
+	 */
+	protected Time getCRtoRT(final long offset, final Task task, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
+		Time crToRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (this.isTheRTAClassReadySingle(cpurta)) {
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final List<Task> sortedChain = cpurta.taskSorting(chain);
+			final Time hyper = this.getHyperPeriod(sortedChain);
+			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.getHigherPriorityTasksInChain(task, chain);
+				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, sortedChain, TimeType.WCET, pu).add(period.multiply(offset));
+			}
+			return crToRT;
+		}
+		return null;
+	}
+	
+	/**
+	 * to derive the time between the critical instant and the given offset's task instance's starting point 
+	 * @param offset		the offset constant number (to set the initial point to analyze, initial point: offset * period of task)
+	 * @param task			the target task to derive the time between the critical instant and its current instance's starting point
+	 * @param chain			the observed task chain
+	 * @param pu			processing unit that computes to derive the crip time
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 						the time between the critical instant and the given offset's task instance's starting point 
+	 */
+	protected Time getCRtoIP(final long offset, final Task task, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
+		Time crToIP = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (this.isTheRTAClassReadySingle(cpurta)) {
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final List<Task> sortedChain = cpurta.taskSorting(chain);
+			final Time hyper = this.getHyperPeriod(sortedChain);
+			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.getHigherPriorityTasksInChain(task, chain);
+				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, chain, pu, cpurta).add(period.multiply(offset));
+			}
+			return crToIP;
+		}
+		return null;
+	}
+	
+	/**
+	 * to derive the hyper-period of the observed task chain
+	 * @param taskChain		the observed task chain
+	 * @return
+	 * 						the hyper-period of the observed task chain
+	 */
+	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;
+	}
+	
+	/**
+	 * to derive the least common multiple of two different BigInteger values
+	 * @param time0			BigInteger A
+	 * @param time1			BigInteger B
+	 * @return
+	 * 						the least common multiple of BigInteger A and BigInteger B
+	 */
+	private BigInteger getLCM(BigInteger time0, BigInteger time1) {
+		return time0.multiply(time1.divide(getGCD(time0, time1)));
+	}
+	
+	/**
+	 * to derive the greatest common divisor of two different BigInteger values
+	 * @param time0			BigInteger A
+	 * @param time1			BigInteger B
+	 * @return
+	 * 						the greatest common divisor of BigInteger A and BigInteger B
+	 */
+	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;
+	}
+}
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/RuntimeUtilRTA.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
similarity index 61%
rename from eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RuntimeUtilRTA.java
rename to eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
index 4713894..71a96a7 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RuntimeUtilRTA.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
@@ -1,477 +1,564 @@
-/*******************************************************************************

- * 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.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;

-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: June 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 RuntimeUtilRTA {

-	/**

-	 * Calculate execution time of the given task under one of the several configurations.

-	 * Since this method is used by CPURtaIA, the visibility should be 'protected'

-	 * 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 trt				HashMap that would contain the corresponding GPU task's response time

-	 * @param cpurta			the instance of CPURtaIA class that calls this method

-	 * 							(to access to the cumuAcTime Time variable that accumulate access latency)

-	 * @return

-	 * 			execution time of the observed task

-	 */

-	protected Time getExecutionTimeforCPUTask(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CpuRTA cpurta) {

-		Logger.getLogger(RuntimeUtilRTA.class);

-		// TODO: Contention Parameter

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

-		}

-		// TODO: Contention

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

-					// TODO: result = result.add(contention);

-					return result;

-				}

-				/* No Triggering Behavior (No InterProcessTrigger) */

-				for (final Runnable r : runnableList) {

-					result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));

-				}

-				// TODO: result = result.add(contention);

-				return result;

-			}

-		}

-		// TODO: 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<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(RuntimeUtilRTA.class).debug("Confirmation: The triggered task mapped to (GPU)");

-							return false;

-						}

-					}

-				}

-			}

-			Logger.getLogger(RuntimeUtilRTA.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 trt				HashMap that would contain the corresponding GPU task's response time

-	 * @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<CallSequenceItem> callSequenceList, final List<Runnable> runnableList,

-			final ProcessingUnit pu, final TimeType executionCase, final CpuRTA cpurta) {

-		Logger.getLogger(RuntimeUtilRTA.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(RuntimeUtilRTA.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 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<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());

-			final int clearIndex = callList.indexOf(callList.stream().filter(s -> s instanceof ClearEvent).iterator().next());

-			if ((clearIndex - waitIndex) > 1) {

-				result = true;

-			}

-		}

-		else {

-			Logger.getLogger(RuntimeUtilRTA.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 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) {

-		Logger.getLogger(RuntimeUtilRTA.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<Label>[]> gtcl = cpurta.getGTCL();

-		final List<Label>[] thisLabelList = gtcl.get(task);

-		final List<Label> readLabelList = thisLabelList[0];

-		final List<Label> writeLabelList = thisLabelList[1];

-		for (final Label l : readLabelList) {

-			Logger.getLogger(RuntimeUtilRTA.class).debug("Label(Read): " + l.getName() + " // (" + task.getName() + ")");

-		}

-		for (final Label l : writeLabelList) {

-			Logger.getLogger(RuntimeUtilRTA.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) {

-			final Time tickExecution = RuntimeUtil.getExecutionTimeForTicks(t, pu, executionCase);

-			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

-	 */

-	protected Time getExecutionTimeForRTARunnable(final Runnable runnable, final ProcessingUnit pu, final TimeType executionCase) {

-		Logger.getLogger(RuntimeUtilRTA.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 (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);

-			result = result.add(tickExecution); // Execution(Ticks) added

-		}

-		return result;

-	}

-

-	/**

-	 * Calculate memory access time of the observed task.

-	 * Since this method is used by CPURtaIA, the visibility should be 'protected'

-	 * 

-	 * @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

-	 */

-	protected 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 (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

-	 */

-	protected 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;

-	}

-}
\ No newline at end of file
+/*******************************************************************************
+ * 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 */
+		Time contention = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (cpurta.getIA() != null) {
+			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;
+	}
+}
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 2ab3f29..ed04559 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,23 +16,27 @@
 import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
 
 public class SharedConsts {
+
+	public static int RUNTIMESEC = 2 * 60 * 60;
+	public static final String SINGLE_CORE_MODEL = "model-input/SingleTCs/SingleTCs.amxmi";
+	
 	/*-----------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 int comParadigm = 0;
+	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, 1, 3, 3, 0, 6, 2, 5, 6 };
-
 	public enum OPT_TYPE {
 		TASKCHAINS, RESPONSETIMESUM, LOADBALANCING
 	}
@@ -41,7 +45,7 @@
 		TS, TSxPrio, TSxUtil, TSxUtilxNbTasks
 	}
 
-	public enum MAPPINGS {
-		EV, RTS, TCS, LB, RND
+	public enum ComParadigm {
+		DIRECT, IMPLICIT
 	}
-}
\ 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/test/AllTests.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/AllTests.java
new file mode 100644
index 0000000..19509f3
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/AllTests.java
@@ -0,0 +1,12 @@
+package org.eclipse.app4mc.gsoc_rta.test;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({ CPURtaTest.class, E2ELatencyTest_Single.class, E2ELatencyTest_Multi.class })
+
+public class AllTests {
+	// empty class to start test suite
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/CPURtaTest.xtend b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/CPURtaTest.xtend
new file mode 100644
index 0000000..a73226d
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/CPURtaTest.xtend
@@ -0,0 +1,146 @@
+package org.eclipse.app4mc.gsoc_rta.test
+
+import java.math.BigInteger
+import org.eclipse.app4mc.amalthea.model.AmaltheaFactory
+import org.eclipse.app4mc.amalthea.model.DiscreteValueConstant
+import org.eclipse.app4mc.amalthea.model.FrequencyDomain
+import org.eclipse.app4mc.amalthea.model.FrequencyUnit
+import org.eclipse.app4mc.amalthea.model.ProcessingUnitDefinition
+import org.eclipse.app4mc.amalthea.model.Runnable
+import org.eclipse.app4mc.amalthea.model.TimeUnit
+import org.eclipse.app4mc.amalthea.model.builder.AmaltheaBuilder
+import org.eclipse.app4mc.amalthea.model.builder.HardwareBuilder
+import org.eclipse.app4mc.amalthea.model.builder.SoftwareBuilder
+import org.eclipse.app4mc.amalthea.model.builder.StimuliBuilder
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType
+import org.eclipse.app4mc.amalthea.model.PeriodicStimulus
+import org.eclipse.app4mc.gsoc_rta.CPURta
+import org.junit.Assert
+import org.junit.Test
+import org.eclipse.app4mc.amalthea.model.PuType
+
+class CPURtaTest {
+	extension AmaltheaBuilder b1 = new AmaltheaBuilder
+	extension SoftwareBuilder b2 = new SoftwareBuilder
+	extension HardwareBuilder b3 = new HardwareBuilder
+	extension StimuliBuilder b4 = new StimuliBuilder
+	
+	@Test
+	def void CPURtaTest(){
+		org.apache.log4j.BasicConfigurator.configure();
+		val model = amalthea [
+			stimuliModel [
+				periodicStimulus [
+					name="periodic_03s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(3), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_05s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(5), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_06s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(6), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_10s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(10), TimeUnit.S)
+				]
+			]
+			softwareModel [
+				runnable [
+					name="r0"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r1"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r2"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r3"
+					activityGraph [
+						ticks [^default = createDVC(2l)]
+					]
+				]
+				task [
+					name="t0"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r0")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_03s"))
+				]
+				task [
+					name="t1"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r1")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_05s"))
+				]
+				task [
+					name="t2"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r2")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_06s"))
+				]
+				task [
+					name="t3"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r3")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_10s"))
+				]
+			]
+			hardwareModel [
+				// ***** Definitions *****
+				definition_ProcessingUnit [
+					name = "ARM"
+					puType = PuType.CPU
+				]
+				
+				// ***** Domains *****
+				domain_Frequency [
+					name = "ARM_Domain"
+					defaultValue = FactoryUtil.createFrequency(1, FrequencyUnit::HZ)
+				]
+				
+				// ***** Structures *****
+				structure [
+					module_ProcessingUnit [
+						name = "ARM0"
+						definition = _find(ProcessingUnitDefinition, "ARM")
+						frequencyDomain = _find(FrequencyDomain, "ARM_Domain")
+					]
+				]
+			]
+		]
+		var CPURta cpurta = new CPURta(model)
+		var wcrtSum = cpurta.getRTSum(TimeType.WCET).adjustUnit().toString()
+		Assert.assertTrue(wcrtSum == "15 s")
+	}
+	
+	private def DiscreteValueConstant createDVC(long upper) {
+		val ret = AmaltheaFactory.eINSTANCE.createDiscreteValueConstant
+		ret.value=upper
+		ret
+	}
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/E2ELatencyTest_Multi.xtend b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/E2ELatencyTest_Multi.xtend
new file mode 100644
index 0000000..d635baa
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/E2ELatencyTest_Multi.xtend
@@ -0,0 +1,389 @@
+package org.eclipse.app4mc.gsoc_rta.test
+
+import java.math.BigInteger
+import org.eclipse.app4mc.amalthea.model.AmaltheaFactory
+import org.eclipse.app4mc.amalthea.model.DiscreteValueConstant
+import org.eclipse.app4mc.amalthea.model.Runnable
+import org.eclipse.app4mc.amalthea.model.TimeUnit
+import org.eclipse.app4mc.amalthea.model.builder.AmaltheaBuilder
+import org.eclipse.app4mc.amalthea.model.builder.SoftwareBuilder
+import org.eclipse.app4mc.amalthea.model.builder.StimuliBuilder
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil
+import org.junit.Test
+import org.eclipse.app4mc.amalthea.model.PeriodicStimulus
+import org.eclipse.app4mc.amalthea.model.Task
+import org.eclipse.app4mc.amalthea.model.ProcessEvent
+import org.eclipse.app4mc.amalthea.model.EventChainItemType
+import org.eclipse.app4mc.amalthea.model.builder.ConstraintsBuilder
+import org.eclipse.app4mc.amalthea.model.builder.HardwareBuilder
+import org.eclipse.app4mc.amalthea.model.PuType
+import org.eclipse.app4mc.amalthea.model.FrequencyUnit
+import org.eclipse.app4mc.amalthea.model.ProcessingUnitDefinition
+import org.eclipse.app4mc.amalthea.model.FrequencyDomain
+import org.eclipse.app4mc.gsoc_rta.CPURta
+import org.eclipse.app4mc.gsoc_rta.E2ELatency
+import org.eclipse.app4mc.gsoc_rta.E2ELatency.MulticoreLatCase
+import org.junit.Assert
+
+class E2ELatencyTest_Multi {
+	extension AmaltheaBuilder b1 = new AmaltheaBuilder
+	extension HardwareBuilder b2 = new HardwareBuilder
+	extension StimuliBuilder b3 = new StimuliBuilder
+	extension SoftwareBuilder b4 = new SoftwareBuilder
+	extension ConstraintsBuilder b5 = new ConstraintsBuilder
+	
+	@Test
+	def void E2ELatencyTest_Multi(){
+		org.apache.log4j.BasicConfigurator.configure();
+		val model = amalthea [
+			hardwareModel [
+				// ***** Definitions *****
+				definition_ProcessingUnit [
+					name = "ARM"
+					puType = PuType.CPU
+				]
+				
+				// ***** Domains *****
+				domain_Frequency [
+					name = "ARM_Domain"
+					defaultValue = FactoryUtil.createFrequency(1, FrequencyUnit::HZ)
+				]
+				
+				// ***** Structures *****
+				structure [
+					module_ProcessingUnit [
+						name = "ARM0"
+						definition = _find(ProcessingUnitDefinition, "ARM")
+						frequencyDomain = _find(FrequencyDomain, "ARM_Domain")
+					]
+					module_ProcessingUnit [
+						name = "ARM1"
+						definition = _find(ProcessingUnitDefinition, "ARM")
+						frequencyDomain = _find(FrequencyDomain, "ARM_Domain")
+					]
+					module_ProcessingUnit [
+						name = "ARM2"
+						definition = _find(ProcessingUnitDefinition, "ARM")
+						frequencyDomain = _find(FrequencyDomain, "ARM_Domain")
+					]
+				]
+			]
+			stimuliModel [
+				periodicStimulus [
+					name="periodic_03s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(3), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_05s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(5), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_06s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(6), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_10s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(10), TimeUnit.S)
+				]
+			]
+			softwareModel [
+				runnable [
+					name="r0"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r1"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r2"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r3"
+					activityGraph [
+						ticks [^default = createDVC(2l)]
+					]
+				]
+				task [
+					name="t0"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r0")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_03s"))
+				]
+				task [
+					name="t1"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r0")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_03s"))
+				]
+				task [
+					name="t2"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r0")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_03s"))
+				]
+				task [
+					name="t3"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r1")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_05s"))
+				]
+				task [
+					name="t4"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r1")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_05s"))
+				]
+				task [
+					name="t5"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r1")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_05s"))
+				]
+				task [
+					name="t6"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r2")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_06s"))
+				]
+				task [
+					name="t7"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r2")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_06s"))
+				]
+				task [
+					name="t8"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r2")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_06s"))
+				]
+				task [
+					name="t9"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r3")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_10s"))
+				]
+				task [
+					name="t10"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r3")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_10s"))
+				]
+				task [
+					name="t11"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r3")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_10s"))
+				]
+			]
+			eventModel [
+				val pe0 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe0.entity= _find(Task,"t0")
+				pe0.name = "pe0"
+				val pe1 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe1.entity= _find(Task,"t1")
+				pe1.name = "pe1"
+				val pe2 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe2.entity= _find(Task,"t2")
+				pe2.name = "pe2"
+				val pe3 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe3.entity= _find(Task,"t3")
+				pe3.name = "pe3"
+				val pe4 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe4.entity= _find(Task,"t4")
+				pe4.name = "pe4"
+				val pe5 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe5.entity= _find(Task,"t5")
+				pe5.name = "pe5"
+				val pe6 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe6.entity= _find(Task,"t6")
+				pe6.name = "pe6"
+				val pe7 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe7.entity= _find(Task,"t7")
+				pe7.name = "pe7"
+				val pe8 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe8.entity= _find(Task,"t8")
+				pe8.name = "pe8"
+				val pe9 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe9.entity= _find(Task,"t9")
+				pe9.name = "pe9"
+				val pe10 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe10.entity= _find(Task,"t10")
+				pe10.name = "pe10"
+				val pe11 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe11.entity= _find(Task,"t11")
+				pe11.name = "pe11"
+				events.add(pe0)
+				events.add(pe1)
+				events.add(pe2)
+				events.add(pe3)
+				events.add(pe4)
+				events.add(pe5)
+				events.add(pe6)
+				events.add(pe7)
+				events.add(pe8)
+				events.add(pe9)
+				events.add(pe10)
+				events.add(pe11)
+			]
+			constraintsModel [
+				eventChain[
+					name = "ec0"
+					stimulus = _find(ProcessEvent,"pe0")
+					response = _find(ProcessEvent,"pe9")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe0")
+						response = _find(ProcessEvent,"pe4")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe4")
+						response = _find(ProcessEvent,"pe8")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe8")
+						response = _find(ProcessEvent,"pe9")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+				eventChain[
+					name = "ec1"
+					stimulus = _find(ProcessEvent,"pe9")
+					response = _find(ProcessEvent,"pe0")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe9")
+						response = _find(ProcessEvent,"pe7")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe7")
+						response = _find(ProcessEvent,"pe5")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe5")
+						response = _find(ProcessEvent,"pe0")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+				eventChain[
+					name = "ec2"
+					stimulus = _find(ProcessEvent,"pe0")
+					response = _find(ProcessEvent,"pe9")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe0")
+						response = _find(ProcessEvent,"pe7")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe7")
+						response = _find(ProcessEvent,"pe5")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe5")
+						response = _find(ProcessEvent,"pe9")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+				eventChain[
+					name = "ec3"
+					stimulus = _find(ProcessEvent,"pe9")
+					response = _find(ProcessEvent,"pe0")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe9")
+						response = _find(ProcessEvent,"pe4")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe4")
+						response = _find(ProcessEvent,"pe8")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe8")
+						response = _find(ProcessEvent,"pe0")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+			]
+		]
+		val ia = #[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
+		var cpurta = new CPURta(false, model, ia);
+		var ecl = new E2ELatency();
+		var bcRctIm = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.BCRctIm).adjustUnit().toString();
+		var bcRctLET = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.BCRctLET).adjustUnit().toString();
+		var wcRctIm = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.WCRctIm).adjustUnit().toString();
+		var wcRctLET = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.WCRctLET).adjustUnit().toString();
+		var bcInitRctIm = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.BCInitRctIm).adjustUnit().toString();
+		var bcInitRctLET = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.BCInitRctLET).adjustUnit().toString();
+		var wcInitRctIm = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.WCInitRctIm).adjustUnit().toString();
+		var wcInitRctLET = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.WCInitRctLET).adjustUnit().toString();
+		var bcAgeIm = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.BCAgeIm).adjustUnit().toString();
+		var bcAgeLET = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.BCAgeLET).adjustUnit().toString();
+		var wcAgeIm = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.WCAgeIm).adjustUnit().toString();
+		var wcAgeLET = ecl.getMultiTCLsum(cpurta, MulticoreLatCase.WCAgeLET).adjustUnit().toString();
+		Assert.assertTrue(bcRctIm == "20 s")
+		Assert.assertTrue(bcRctLET == "96 s")
+		Assert.assertTrue(wcRctIm == "122 s")
+		Assert.assertTrue(wcRctLET == "166 s")
+		Assert.assertTrue(bcInitRctIm == "20 s")
+		Assert.assertTrue(bcInitRctLET == "96 s")
+		Assert.assertTrue(wcInitRctIm == "108 s")
+		Assert.assertTrue(wcInitRctLET == "150 s")
+		Assert.assertTrue(bcAgeIm == "12 s")
+		Assert.assertTrue(bcAgeLET == "26 s")
+		Assert.assertTrue(wcAgeIm == "114 s")
+		Assert.assertTrue(wcAgeLET == "69 s")
+	}
+	private def DiscreteValueConstant createDVC(long upper) {
+		val ret = AmaltheaFactory.eINSTANCE.createDiscreteValueConstant
+		ret.value=upper
+		ret
+	}
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/E2ELatencyTest_Single.xtend b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/E2ELatencyTest_Single.xtend
new file mode 100644
index 0000000..4f130e4
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/test/E2ELatencyTest_Single.xtend
@@ -0,0 +1,265 @@
+package org.eclipse.app4mc.gsoc_rta.test
+
+import org.eclipse.app4mc.amalthea.model.builder.AmaltheaBuilder
+import org.eclipse.app4mc.amalthea.model.builder.HardwareBuilder
+import org.eclipse.app4mc.amalthea.model.builder.StimuliBuilder
+import org.eclipse.app4mc.amalthea.model.builder.SoftwareBuilder
+import org.eclipse.app4mc.amalthea.model.builder.ConstraintsBuilder
+import org.junit.Test
+import org.eclipse.app4mc.amalthea.model.PuType
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil
+import org.eclipse.app4mc.amalthea.model.FrequencyUnit
+import org.eclipse.app4mc.amalthea.model.ProcessingUnitDefinition
+import org.eclipse.app4mc.amalthea.model.FrequencyDomain
+import java.math.BigInteger
+import org.eclipse.app4mc.amalthea.model.TimeUnit
+import org.eclipse.app4mc.amalthea.model.Runnable
+import org.eclipse.app4mc.amalthea.model.DiscreteValueConstant
+import org.eclipse.app4mc.amalthea.model.AmaltheaFactory
+import org.junit.Assert
+import org.eclipse.app4mc.gsoc_rta.CPURta
+import org.eclipse.app4mc.gsoc_rta.E2ELatency
+import org.eclipse.app4mc.amalthea.model.PeriodicStimulus
+import org.eclipse.app4mc.amalthea.model.Task
+import org.eclipse.app4mc.amalthea.model.ProcessEvent
+import org.eclipse.app4mc.amalthea.model.EventChainItemType
+import org.eclipse.app4mc.gsoc_rta.CommonUtils
+import org.eclipse.app4mc.gsoc_rta.E2ELatency.SinglecoreLatCase
+
+class E2ELatencyTest_Single {
+	extension AmaltheaBuilder b1 = new AmaltheaBuilder
+	extension HardwareBuilder b2 = new HardwareBuilder
+	extension StimuliBuilder b3 = new StimuliBuilder
+	extension SoftwareBuilder b4 = new SoftwareBuilder
+	extension ConstraintsBuilder b5 = new ConstraintsBuilder
+	
+	@Test
+	def void E2ELatencyTest_Single(){
+		org.apache.log4j.BasicConfigurator.configure();
+		val model = amalthea [
+			hardwareModel [
+				// ***** Definitions *****
+				definition_ProcessingUnit [
+					name = "ARM"
+					puType = PuType.CPU
+				]
+				
+				// ***** Domains *****
+				domain_Frequency [
+					name = "ARM_Domain"
+					defaultValue = FactoryUtil.createFrequency(1, FrequencyUnit::HZ)
+				]
+				
+				// ***** Structures *****
+				structure [
+					module_ProcessingUnit [
+						name = "ARM0"
+						definition = _find(ProcessingUnitDefinition, "ARM")
+						frequencyDomain = _find(FrequencyDomain, "ARM_Domain")
+					]
+				]
+			]
+			stimuliModel [
+				periodicStimulus [
+					name="periodic_03s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(3), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_05s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(5), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_06s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(6), TimeUnit.S)
+				]
+				periodicStimulus [
+					name="periodic_10s"
+					recurrence=FactoryUtil.createTime(BigInteger.valueOf(10), TimeUnit.S)
+				]
+			]
+			softwareModel [
+				runnable [
+					name="r0"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r1"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r2"
+					activityGraph [
+						ticks [^default = createDVC(1l)]
+					]
+				]
+				runnable [
+					name="r3"
+					activityGraph [
+						ticks [^default = createDVC(2l)]
+					]
+				]
+				task [
+					name="t0"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r0")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_03s"))
+				]
+				task [
+					name="t1"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r1")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_05s"))
+				]
+				task [
+					name="t2"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r2")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_06s"))
+				]
+				task [
+					name="t3"
+					activityGraph [
+						runnableCall [
+							runnable = _find(Runnable, "r3")
+						]
+					]
+					stimuli.add(_find(PeriodicStimulus, "periodic_10s"))
+				]
+			]
+			eventModel [
+				val pe0 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe0.entity= _find(Task,"t0")
+				pe0.name = "pe0"
+				val pe1 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe1.entity= _find(Task,"t1")
+				pe1.name = "pe1"
+				val pe2 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe2.entity= _find(Task,"t2")
+				pe2.name = "pe2"
+				val pe3 = AmaltheaFactory.eINSTANCE.createProcessEvent
+				pe3.entity= _find(Task,"t3")
+				pe3.name = "pe3"
+				events.add(pe0)
+				events.add(pe1)
+				events.add(pe2)
+				events.add(pe3)
+			]
+			constraintsModel [
+				eventChain[
+					name = "ec0"
+					stimulus = _find(ProcessEvent,"pe0")
+					response = _find(ProcessEvent,"pe3")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe0")
+						response = _find(ProcessEvent,"pe1")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe1")
+						response = _find(ProcessEvent,"pe2")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe2")
+						response = _find(ProcessEvent,"pe3")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+				eventChain[
+					name = "ec1"
+					stimulus = _find(ProcessEvent,"pe3")
+					response = _find(ProcessEvent,"pe0")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe3")
+						response = _find(ProcessEvent,"pe2")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe2")
+						response = _find(ProcessEvent,"pe1")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe1")
+						response = _find(ProcessEvent,"pe0")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+				eventChain[
+					name = "ec2"
+					stimulus = _find(ProcessEvent,"pe0")
+					response = _find(ProcessEvent,"pe3")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe0")
+						response = _find(ProcessEvent,"pe2")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe2")
+						response = _find(ProcessEvent,"pe1")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe1")
+						response = _find(ProcessEvent,"pe3")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+				eventChain[
+					name = "ec3"
+					stimulus = _find(ProcessEvent,"pe3")
+					response = _find(ProcessEvent,"pe0")
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe3")
+						response = _find(ProcessEvent,"pe1")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe1")
+						response = _find(ProcessEvent,"pe2")
+						itemType = EventChainItemType.SEQUENCE
+					]
+					subchain	[
+						stimulus = _find(ProcessEvent,"pe2")
+						response = _find(ProcessEvent,"pe0")
+						itemType = EventChainItemType.SEQUENCE
+					]
+				]
+			]
+		]
+		var cpurta = new CPURta(model);
+		var ama = cpurta.getModel();
+		var pu = CommonUtils.getPUs(ama).get(0)
+		var ecl = new E2ELatency();
+		var criInitRct = ecl.getSingleTCLsum(cpurta, pu, SinglecoreLatCase.CriInitRct).adjustUnit().toString();
+		var bcInitRct = ecl.getSingleTCLsum(cpurta, pu, SinglecoreLatCase.BCInitRct).adjustUnit().toString();
+		var wcInitRct = ecl.getSingleTCLsum(cpurta, pu, SinglecoreLatCase.WCInitRct).adjustUnit().toString();
+		var criWCRct = ecl.getSingleTCLsum(cpurta, pu, SinglecoreLatCase.CriWCRct).adjustUnit().toString();
+		var bcWCRct = ecl.getSingleTCLsum(cpurta, pu, SinglecoreLatCase.BCWCRct).adjustUnit().toString();
+		var wcWCRct = ecl.getSingleTCLsum(cpurta, pu, SinglecoreLatCase.WCWCRct).adjustUnit().toString();
+		Assert.assertTrue(criInitRct == "44 s")
+		Assert.assertTrue(bcInitRct == "35 s")
+		Assert.assertTrue(wcInitRct == "62 s")
+		Assert.assertTrue(criWCRct == "47 s")
+		Assert.assertTrue(bcWCRct == "49 s")
+		Assert.assertTrue(wcWCRct == "76 s")
+	}
+	private def DiscreteValueConstant createDVC(long upper) {
+		val ret = AmaltheaFactory.eINSTANCE.createDiscreteValueConstant
+		ret.value=upper
+		ret
+	}
+}
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
new file mode 100644
index 0000000..8704d73
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
@@ -0,0 +1,1151 @@
+/*******************************************************************************
+ * 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.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.E2ELatency.SinglecoreLatCase;
+import org.eclipse.emf.common.util.EList;
+import javax.swing.SwingConstants;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.JSeparator;
+
+/**
+ * Date: May 04, 2020
+ * @version 2.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, AmaltheaLoader.loadFromFile(new File(SharedConsts.SINGLE_CORE_MODEL)), new int[] { 4, 1, 1, 3, 4, 0, 1, 3, 3, 0, 6, 2, 5, 6 });
+	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;
+	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
+	};
+
+	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("Default 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 ;
+				}
+				/* This is only for 'ChallengeModel_TCs.amxmi' */
+				/*
+				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 ;
+				}
+				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); 
+				*/
+				if (currentPUList.size() < 1) {
+					JOptionPane.showMessageDialog(frame, "ERROR: There is no processing unit in this model.\n"
+							+ "Please choose another model."); 
+				} 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 ;
+				} else {
+					final int numOfTasks = cpurta.getModel().getSwModel().getTasks().size();
+					final int numOfPUs = currentPUList.size();
+					int x = 0;
+					for (int i = 0; i < numOfTasks; i++) {
+						if (x < numOfPUs) {
+							jTextFieldArray[i].setText("" + x);
+						} else {
+							x = 0;
+							jTextFieldArray[i].setText("" + x);
+						}
+						x++;
+					}
+				}
+			}
+		});
+		
+		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("Not 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.");
+					JOptionPane.showMessageDialog(frame, "ERROR: This mapping is not schedulable.\n"
+							+ "Please change the mapping.");
+				}
+			}
+		});
+		
+		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.8") != 0) {
+		        		JOptionPane.showMessageDialog(frame, "Error: This model should be migrated to the version 0.9.8");
+		        		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);
+		
+		JLabel lblRI = new JLabel("Reaction (Implicit)");
+		lblRI.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblRI.setBounds(105, 605, 293, 16);
+		frame.getContentPane().add(lblRI);
+		
+		JLabel lblBCRI = new JLabel("Best-Case");
+		lblBCRI.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCRI.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCRI.setBounds(10, 627, 90, 16);
+		frame.getContentPane().add(lblBCRI);
+		
+		JTextField txtField0 = new JTextField();
+		txtField0.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField0.setBounds(103, 625, 200, 22);
+		txtField0.setEditable(false);
+		frame.getContentPane().add(txtField0);
+		
+		JLabel lblWCRI = new JLabel("Worst-Case");
+		lblWCRI.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCRI.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCRI.setBounds(10, 656, 90, 16);
+		frame.getContentPane().add(lblWCRI);
+		
+		JTextField txtField1 = new JTextField();
+		txtField1.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField1.setBounds(103, 654, 200, 22);
+		txtField1.setEditable(false);
+		frame.getContentPane().add(txtField1);
+		
+		JLabel lblIRI = new JLabel("Initial Reaction (Implicit)");
+		lblIRI.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblIRI.setBounds(105, 688, 193, 16);
+		frame.getContentPane().add(lblIRI);
+		
+		JLabel lblBCIRI = new JLabel("Best-Case");
+		lblBCIRI.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCIRI.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCIRI.setBounds(10, 710, 90, 16);
+		frame.getContentPane().add(lblBCIRI);
+		
+		JTextField txtField2 = new JTextField();
+		txtField2.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField2.setBounds(103, 708, 200, 22);
+		txtField2.setEditable(false);
+		frame.getContentPane().add(txtField2);
+		
+		JLabel lblWCIRI = new JLabel("Worst-Case");
+		lblWCIRI.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCIRI.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCIRI.setBounds(10, 739, 90, 16);
+		frame.getContentPane().add(lblWCIRI);
+		
+		JTextField txtField3 = new JTextField();
+		txtField3.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField3.setBounds(103, 737, 200, 22);
+		txtField3.setEditable(false);
+		frame.getContentPane().add(txtField3);
+		
+		JLabel lblRL = new JLabel("Reaction (LET)");
+		lblRL.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblRL.setBounds(415, 605, 222, 16);
+		frame.getContentPane().add(lblRL);
+		
+		JLabel lblBCRL = new JLabel("Best-Case");
+		lblBCRL.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCRL.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCRL.setBounds(320, 627, 90, 16);
+		frame.getContentPane().add(lblBCRL);
+		
+		JTextField txtField4 = new JTextField();
+		txtField4.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField4.setBounds(413, 625, 200, 22);
+		txtField4.setEditable(false);
+		frame.getContentPane().add(txtField4);
+		
+		JLabel lblWCRL = new JLabel("Worst-Case");
+		lblWCRL.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCRL.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCRL.setBounds(320, 656, 90, 16);
+		frame.getContentPane().add(lblWCRL);
+		
+		JTextField txtField5 = new JTextField();
+		txtField5.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField5.setBounds(413, 654, 200, 22);
+		txtField5.setEditable(false);
+		frame.getContentPane().add(txtField5);
+		
+		JLabel lblIRL = new JLabel("Initial Reaction (LET)");
+		lblIRL.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblIRL.setBounds(415, 688, 232, 16);
+		frame.getContentPane().add(lblIRL);
+		
+		JLabel lblBCIRL = new JLabel("Best-Case");
+		lblBCIRL.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCIRL.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCIRL.setBounds(320, 710, 90, 16);
+		frame.getContentPane().add(lblBCIRL);
+		
+		JTextField txtField6 = new JTextField();
+		txtField6.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField6.setBounds(413, 708, 200, 22);
+		txtField6.setEditable(false);
+		frame.getContentPane().add(txtField6);
+		
+		JLabel lblWCIRL = new JLabel("Worst-Case");
+		lblWCIRL.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCIRL.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCIRL.setBounds(320, 739, 90, 16);
+		frame.getContentPane().add(lblWCIRL);
+		
+		JTextField txtField7 = new JTextField();
+		txtField7.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField7.setBounds(413, 737, 200, 22);
+		txtField7.setEditable(false);
+		frame.getContentPane().add(txtField7);
+		
+		JLabel lblAI = new JLabel("Age (Implicit)");
+		lblAI.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblAI.setBounds(105, 771, 293, 16);
+		frame.getContentPane().add(lblAI);
+		
+		JLabel lblBCAI = new JLabel("Best-Case");
+		lblBCAI.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCAI.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCAI.setBounds(10, 793, 90, 16);
+		frame.getContentPane().add(lblBCAI);
+		
+		JTextField txtField8 = new JTextField();
+		txtField8.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField8.setBounds(103, 791, 200, 22);
+		txtField8.setEditable(false);
+		frame.getContentPane().add(txtField8);
+		
+		JLabel lblWCAI = new JLabel("Worst-Case");
+		lblWCAI.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCAI.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCAI.setBounds(10, 822, 90, 16);
+		frame.getContentPane().add(lblWCAI);
+		
+		JTextField txtField9 = new JTextField();
+		txtField9.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField9.setBounds(103, 820, 200, 22);
+		txtField9.setEditable(false);
+		frame.getContentPane().add(txtField9);
+		
+		JLabel lblAL = new JLabel("Age (LET)");
+		lblAL.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblAL.setBounds(415, 771, 232, 16);
+		frame.getContentPane().add(lblAL);
+		
+		JLabel lblBCAL = new JLabel("Best-Case");
+		lblBCAL.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCAL.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCAL.setBounds(320, 793, 90, 16);
+		frame.getContentPane().add(lblBCAL);
+		
+		JTextField txtField10 = new JTextField();
+		txtField10.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField10.setBounds(413, 791, 200, 22);
+		txtField10.setEditable(false);
+		frame.getContentPane().add(txtField10);
+		
+		JLabel lblWCAL = new JLabel("Worst-Case");
+		lblWCAL.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCAL.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCAL.setBounds(320, 822, 90, 16);
+		frame.getContentPane().add(lblWCAL);
+		
+		JTextField txtField11 = new JTextField();
+		txtField11.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField11.setBounds(413, 820, 200, 22);
+		txtField11.setEditable(false);
+		frame.getContentPane().add(txtField11);
+		
+		JLabel lblSIR = new JLabel("Single-core Initial Reaction");
+		lblSIR.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblSIR.setBounds(105, 865, 293, 16);
+		frame.getContentPane().add(lblSIR);
+		
+		JLabel lblCRSIR = new JLabel("Critical-Case");
+		lblCRSIR.setHorizontalAlignment(SwingConstants.CENTER);
+		lblCRSIR.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblCRSIR.setBounds(10, 887, 90, 16);
+		frame.getContentPane().add(lblCRSIR);
+		
+		JTextField txtField12 = new JTextField();
+		txtField12.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField12.setBounds(103, 885, 200, 22);
+		txtField12.setEditable(false);
+		frame.getContentPane().add(txtField12);
+		
+		JLabel lblBCSIR = new JLabel("Best-Case");
+		lblBCSIR.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCSIR.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCSIR.setBounds(10, 916, 90, 16);
+		frame.getContentPane().add(lblBCSIR);
+		
+		JTextField txtField13 = new JTextField();
+		txtField13.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField13.setBounds(103, 914, 200, 22);
+		txtField13.setEditable(false);
+		frame.getContentPane().add(txtField13);
+		
+		JLabel lblWCSIR = new JLabel("Worst-Case");
+		lblWCSIR.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCSIR.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCSIR.setBounds(10, 945, 90, 16);
+		frame.getContentPane().add(lblWCSIR);
+		
+		JTextField txtField14 = new JTextField();
+		txtField14.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField14.setBounds(103, 943, 200, 22);
+		txtField14.setEditable(false);
+		frame.getContentPane().add(txtField14);
+
+		JLabel lblSWCR = new JLabel("Single-core Worst-case Reaction");
+		lblSWCR.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblSWCR.setBounds(415, 865, 293, 16);
+		frame.getContentPane().add(lblSWCR);
+		
+		JLabel lblCRSWCR = new JLabel("Critical-Case");
+		lblCRSWCR.setHorizontalAlignment(SwingConstants.CENTER);
+		lblCRSWCR.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblCRSWCR.setBounds(320, 887, 90, 16);
+		frame.getContentPane().add(lblCRSWCR);
+		
+		JTextField txtField15 = new JTextField();
+		txtField15.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField15.setBounds(413, 885, 200, 22);
+		txtField15.setEditable(false);
+		frame.getContentPane().add(txtField15);
+		
+		JLabel lblBCSWCR = new JLabel("Best-Case");
+		lblBCSWCR.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBCSWCR.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBCSWCR.setBounds(320, 916, 90, 16);
+		frame.getContentPane().add(lblBCSWCR);
+		
+		JTextField txtField16 = new JTextField();
+		txtField16.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField16.setBounds(413, 914, 200, 22);
+		txtField16.setEditable(false);
+		frame.getContentPane().add(txtField16);
+		
+		JLabel lblWCSWCR = new JLabel("Worst-Case");
+		lblWCSWCR.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWCSWCR.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWCSWCR.setBounds(320, 945, 90, 16);
+		frame.getContentPane().add(lblWCSWCR);
+		
+		JTextField txtField17 = new JTextField();
+		txtField17.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField17.setBounds(413, 943, 200, 22);
+		txtField17.setEditable(false);
+		frame.getContentPane().add(txtField17);
+		
+		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 ;
+				}
+				
+				/* If cpurta has only one core > single core mode, else > multicore mode (01/05/2020) */
+				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) {
+						return ;
+					}
+					/* If the selected Event-Chain is different to the previous one => Remove and Do Normal. */
+					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.");
+					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.");
+					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 ;
+				}
+				
+				/* To find out how many processing units are used by tasks */
+				ProcessingUnit pu = null;
+				int puCount = 0;
+				for (int i = 0; i < puTaskListHM.size(); i++) {
+					final java.util.List<Task> tasks = puTaskListHM.get(i);
+					if (tasks.size() > 0) {
+						pu = currentPUList.get(i);
+						puCount++;
+					}
+				}
+				
+				if (puCount > 1) {
+					final Time bcRctIm = e2e.getBCReactionImplicit(currentEC, cpurta);
+					final Time wcRctIm = e2e.getWCReactionImplicit(currentEC, cpurta);
+					final Time bcInitRctIm = e2e.getBCInitialRctImplicit(currentEC, cpurta);
+					final Time wcInitRctIm = e2e.getWCInitialRctImplicit(currentEC, cpurta);
+					final Time bcRctLET = e2e.getBCReactionLET(currentEC, cpurta);
+					final Time wcRctLET = e2e.getWCReactionLET(currentEC, cpurta);
+					final Time bcInitRctLET = e2e.getBCInitialRctLET(currentEC, cpurta);
+					final Time wcInitRctLET = e2e.getWCInitialRctLET(currentEC, cpurta);
+					final Time bcAgeIm = e2e.getBCAgeImplicit(currentEC, cpurta);
+					final Time wcAgeIm = e2e.getWCAgeImplicit(currentEC, cpurta);
+					final Time bcAgeLET = e2e.getBCAgeLET(currentEC, cpurta);
+					final Time wcAgeLET = e2e.getWCAgeLET(currentEC, cpurta);
+					
+					txtField0.setText("" + bcRctIm);
+					txtField1.setText("" + wcRctIm);
+					txtField2.setText("" + bcInitRctIm);
+					txtField3.setText("" + wcInitRctIm);
+					txtField4.setText("" + bcRctLET);
+					txtField5.setText("" + wcRctLET);
+					txtField6.setText("" + bcInitRctLET);
+					txtField7.setText("" + wcInitRctLET);
+					txtField8.setText("" + bcAgeIm);
+					txtField9.setText("" + wcAgeIm);
+					txtField10.setText("" + bcAgeLET);
+					txtField11.setText("" + wcAgeLET);
+					
+					txtField12.setText("Not Single-Core.");
+					txtField13.setText("Not Single-Core.");
+					txtField14.setText("Not Single-Core.");
+					txtField15.setText("Not Single-Core.");
+					txtField16.setText("Not Single-Core.");
+					txtField17.setText("Not Single-Core.");
+				} else {
+					final Time crSingleInitRct = e2e.getSingleCoreInitialRct(currentEC, pu, SinglecoreLatCase.CriInitRct, cpurta);
+					final Time bcSingleInitRct = e2e.getSingleCoreInitialRct(currentEC, pu, SinglecoreLatCase.BCInitRct, cpurta);;
+					final Time wcSingleInitRct = e2e.getSingleCoreInitialRct(currentEC, pu, SinglecoreLatCase.WCInitRct, cpurta);;
+					final Time crSingleWCRct = e2e.getSingleCoreWCRct(currentEC, pu, SinglecoreLatCase.CriWCRct, cpurta);;
+					final Time bcSingleWCRct = e2e.getSingleCoreWCRct(currentEC, pu, SinglecoreLatCase.BCWCRct, cpurta);;
+					final Time wcSingleWCRct = e2e.getSingleCoreWCRct(currentEC, pu, SinglecoreLatCase.WCWCRct, cpurta);;
+					
+					txtField0.setText("Not Multi-Core.");
+					txtField1.setText("Not Multi-Core.");
+					txtField2.setText("Not Multi-Core.");
+					txtField3.setText("Not Multi-Core.");
+					txtField4.setText("Not Multi-Core.");
+					txtField5.setText("Not Multi-Core.");
+					txtField6.setText("Not Multi-Core.");
+					txtField7.setText("Not Multi-Core.");
+					txtField8.setText("Not Multi-Core.");
+					txtField9.setText("Not Multi-Core.");
+					txtField10.setText("Not Multi-Core.");
+					txtField11.setText("Not Multi-Core.");
+					
+					txtField12.setText("" + crSingleInitRct);
+					txtField13.setText("" + bcSingleInitRct);
+					txtField14.setText("" + wcSingleInitRct);
+					txtField15.setText("" + crSingleWCRct);
+					txtField16.setText("" + bcSingleWCRct);
+					txtField17.setText("" + wcSingleWCRct);
+				}
+				
+				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;
+				txtField0.setText("");
+				txtField1.setText("");
+				txtField2.setText("");
+				txtField3.setText("");
+				txtField4.setText("");
+				txtField5.setText("");
+				txtField6.setText("");
+				txtField7.setText("");
+				txtField8.setText("");
+				txtField9.setText("");
+				txtField10.setText("");
+				txtField11.setText("");
+				txtField12.setText("");
+				txtField13.setText("");
+				txtField14.setText("");
+				txtField15.setText("");
+				txtField16.setText("");
+				txtField17.setText("");
+				
+				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);
+	}
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/RTApp_WATERS19.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/RTApp_WATERS19.java
deleted file mode 100644
index 4df858e..0000000
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/RTApp_WATERS19.java
+++ /dev/null
@@ -1,561 +0,0 @@
-/*******************************************************************************

- * 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.TextArea;

-import java.awt.event.ActionEvent;

-import java.awt.event.ActionListener;

-import java.math.BigInteger;

-import java.util.ArrayList;

-import java.util.HashMap;

-import javax.swing.ButtonGroup;

-import javax.swing.JButton;

-import javax.swing.JFrame;

-import javax.swing.JLabel;

-import javax.swing.JOptionPane;

-import javax.swing.JRadioButton;

-import javax.swing.JTextField;

-

-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.*;

-

-/**

- * Date: Jun 20-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 RTApp_WATERS19 extends JFrame {

-	private HashMap<Integer, java.util.List<Task>> puTaskListHM;

-	private JFrame frame;

-	private boolean iaEntered = false;

-	

-	/**

-	 * Launch the application.

-	 */

-	public static void main(String[] args) {

-		EventQueue.invokeLater(new Runnable() {

-			public void run() {

-				org.apache.log4j.BasicConfigurator.configure();

-				final RTApp_WATERS19 window = new RTApp_WATERS19();

-				window.frame.setVisible(true);

-				window.frame.setTitle("APP4RTA");

-			}

-		});

-	}

-

-	/**

-	 * Create the frame.

-	 */

-	public RTApp_WATERS19() {

-		initialize();

-	}

-	

-	private void initialize() {

-		final CpuRTA cpurta = new CpuRTA();

-		final ArrayList<JTextField> jTextFieldList = new ArrayList<JTextField>();

-		final ArrayList<List> tListList = new ArrayList<List>();

-		final ArrayList<List> rtListList = new ArrayList<List>();

-		

-		frame = new JFrame();

-		frame.setBounds(100, 100, 864, 690);

-		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

-		frame.getContentPane().setLayout(null);

-		

-		JLabel lblEnterIa = new JLabel("Enter IA");

-		lblEnterIa.setBounds(32, 13, 56, 16);

-		frame.getContentPane().add(lblEnterIa);

-		

-		JButton btnDefualtIa = new JButton("Defualt IA");

-		btnDefualtIa.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent arg0) {

-				cpurta.setModel(AmaltheaLoader.loadFromFile(cpurta.inputFile));

-				cpurta.setTRT(cpurta.getDefaultTRT(cpurta.getModel()));

-				cpurta.setIA(cpurta.getDefaultIAMapping());

-				cpurta.setPUl(CommonUtils.getPUs(cpurta.getModel()));

-				final int[] defaultIA = cpurta.getIA();

-				for (int i = 0; i < defaultIA.length; i++) {

-					jTextFieldList.get(i).setText(""+defaultIA[i]);

-				}

-			}

-		});

-		btnDefualtIa.setBounds(12, 28, 97, 25);

-		frame.getContentPane().add(btnDefualtIa);

-		

-		JRadioButton rdbtnSynchronous = new JRadioButton("Synchronous");

-		rdbtnSynchronous.setBounds(157, 58, 107, 25);

-		frame.getContentPane().add(rdbtnSynchronous);

-		

-		JRadioButton rdbtnAsynchronous = new JRadioButton("Asynchronous");

-		rdbtnAsynchronous.setBounds(157, 79, 107, 25);

-		frame.getContentPane().add(rdbtnAsynchronous);

-		

-		ButtonGroup group_0 = new ButtonGroup();

-		group_0.add(rdbtnSynchronous);

-		group_0.add(rdbtnAsynchronous);

-		

-		JRadioButton rdbtnWorstCase = new JRadioButton("Worst Case");

-		rdbtnWorstCase.setBounds(268, 58, 107, 25);

-		frame.getContentPane().add(rdbtnWorstCase);

-		

-		JRadioButton rdbtnAverageCase = new JRadioButton("Average Case");

-		rdbtnAverageCase.setBounds(268, 79, 107, 25);

-		frame.getContentPane().add(rdbtnAverageCase);

-		

-		JRadioButton rdbtnBestCase = new JRadioButton("Best Case");

-		rdbtnBestCase.setBounds(268, 100, 107, 25);

-		frame.getContentPane().add(rdbtnBestCase);

-		

-		ButtonGroup group_1 = new ButtonGroup();

-		group_1.add(rdbtnWorstCase);

-		group_1.add(rdbtnAverageCase);

-		group_1.add(rdbtnBestCase);

-		

-		JButton btnEnterIA = new JButton("Enter IA");

-		btnEnterIA.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

-				cpurta.setModel(AmaltheaLoader.loadFromFile(cpurta.inputFile));

-				cpurta.setTRT(cpurta.getDefaultTRT(cpurta.getModel()));

-				int[] tpumap = new int[cpurta.getModel().getSwModel().getTasks().size()];

-				for (int i = 0; i < jTextFieldList.size(); i++) {

-					if ((jTextFieldList.get(i)).getText().length() == 0) {

-						JOptionPane.showMessageDialog(frame, "ERROR: Fill the rest of the array!");

-						return ;

-					}

-					else if ((jTextFieldList.get(i)).getText().charAt(0) < 48 || (jTextFieldList.get(i)).getText().charAt(0) > 54) {

-						JOptionPane.showMessageDialog(frame, "ERROR: Wrong array value!");

-						return ;

-					}

-					// TODO: should be more generic

-					else if (i >= 0 && i <= 9 && Integer.parseInt(((jTextFieldList.get(i)).getText())) == 6) {

-						JOptionPane.showMessageDialog(frame, "ERROR: CPU Tasks should not be mapped to GPU!");

-						return ;

-					}

-					// TODO: should be more generic

-					else if (i == jTextFieldList.size()-1 && Integer.parseInt(((jTextFieldList.get(i)).getText())) != 6) {

-						JOptionPane.showMessageDialog(frame, "ERROR: 'Detection' task can not be mapped to CPU!");

-						return ;

-					}

-					tpumap[i] = Integer.parseInt(((jTextFieldList.get(i)).getText()));

-				}

-				cpurta.setIA(tpumap);

-				cpurta.setPUl(CommonUtils.getPUs(cpurta.getModel()));

-				puTaskListHM = cpurta.be_getPUTaskListHashMap(cpurta.getModel());

-				for (int i = 0; i < puTaskListHM.size(); i++) {

-					if (tListList.get(i).getItemCount() == 0) {

-						for (int j = 0; j < puTaskListHM.get(i).size(); j++) {	

-							tListList.get(i).add((puTaskListHM.get(i).get(j)).getName());

-						}

-					}

-				}

-				iaEntered = true;

-			}

-		});

-		btnEnterIA.setBounds(616, 28, 97, 25);

-		frame.getContentPane().add(btnEnterIA);

-		

-		JLabel lblResponseTimeSum = new JLabel("Response Time Sum");

-		lblResponseTimeSum.setBounds(616, 359, 145, 16);

-		frame.getContentPane().add(lblResponseTimeSum);

-		

-		TextArea rtSum = new TextArea();

-		rtSum.setBounds(616, 381, 218, 50);

-		frame.getContentPane().add(rtSum);

-		

-		JButton btnCalculate = new JButton("Calculate");

-		btnCalculate.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent arg0) {

-				for (int i = 0; i < jTextFieldList.size(); i++) {

-					if ((jTextFieldList.get(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 (iaEntered == false) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Click the 'Enter IA' button!");

-					return ;

-				}				

-				boolean flag = false;

-				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 (rtListList.get(i).getItemCount() == 0) {

-						if (pu.getDefinition().getPuType().equals(PuType.CPU)) {

-							for (Task t : thisPUTaskList) {

-								thisRT = cpurta.preciseTestCPURT(t, thisPUTaskList, SharedConsts.timeType, pu);

-								if (thisRT.getValue().equals(BigInteger.valueOf(Long.MAX_VALUE))) {

-									rtListList.get(i).add("Non Scheduleable! => MAX Value");

-									flag = true;

-								}

-								else {

-									rtListList.get(i).add(thisRT.toString());

-								}

-								pRtSum = pRtSum.add(thisRT);

-							}

-						}

-						else {

-							// TODO: TRT 0s!

-							for (Task t : thisPUTaskList) {

-								thisRT = cpurta.getTRT().get(t);

-								rtListList.get(i).add(thisRT.toString());

-								pRtSum = pRtSum.add(thisRT);

-							}

-						}

-					}

-				}

-				if (flag) {

-					rtSum.setText("Non Scheduleable!: " + pRtSum.toString());

-				}

-				else {

-					rtSum.setText(pRtSum.toString());

-				}

-			}

-		});

-		btnCalculate.setBounds(616, 58, 97, 25);

-		frame.getContentPane().add(btnCalculate);

-		

-		JButton btnReset = new JButton("Reset");

-		btnReset.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

-				cpurta.setModel(null);

-				cpurta.setTRT(null);

-				cpurta.setIA(null);

-				cpurta.setPUl(null);

-				puTaskListHM = null;

-				for (int i = 0; i < jTextFieldList.size(); i++) {

-					jTextFieldList.get(i).setText("");

-				}

-				for (List tList : tListList) {

-					tList.removeAll();

-				}

-				for (List rtList : rtListList) {

-					rtList.removeAll();

-				}

-				rtSum.setText(null);

-				iaEntered = false;

-			}

-		});

-		btnReset.setBounds(616, 86, 97, 25);

-		frame.getContentPane().add(btnReset);

-		

-		JLabel lblT0 = new JLabel("T0");

-		lblT0.setBounds(124, 13, 15, 16);

-		frame.getContentPane().add(lblT0);

-		

-		JTextField txtInput0 = new JTextField();

-		txtInput0.setBounds(124, 29, 23, 22);

-		txtInput0.setColumns(10);

-		frame.getContentPane().add(txtInput0);

-		jTextFieldList.add(txtInput0);

-		

-		JLabel lblT1 = new JLabel("T1");

-		lblT1.setBounds(159, 13, 15, 16);

-		frame.getContentPane().add(lblT1);

-		

-		JTextField txtInput1 = new JTextField();

-		txtInput1.setColumns(10);

-		txtInput1.setBounds(159, 29, 23, 22);

-		frame.getContentPane().add(txtInput1);

-		jTextFieldList.add(txtInput1);

-		

-		JLabel lblT2 = new JLabel("T2");

-		lblT2.setBounds(194, 13, 15, 16);

-		frame.getContentPane().add(lblT2);

-		

-		JTextField txtInput2 = new JTextField();

-		txtInput2.setColumns(10);

-		txtInput2.setBounds(194, 29, 23, 22);

-		frame.getContentPane().add(txtInput2);

-		jTextFieldList.add(txtInput2);

-		

-		JLabel lblT3 = new JLabel("T3");

-		lblT3.setBounds(229, 13, 15, 16);

-		frame.getContentPane().add(lblT3);

-		

-		JTextField txtInput3 = new JTextField();

-		txtInput3.setColumns(10);

-		txtInput3.setBounds(229, 29, 23, 22);

-		frame.getContentPane().add(txtInput3);

-		jTextFieldList.add(txtInput3);

-		

-		JLabel lblT4 = new JLabel("T4");

-		lblT4.setBounds(264, 13, 15, 16);

-		frame.getContentPane().add(lblT4);

-		

-		JTextField txtInput4 = new JTextField();

-		txtInput4.setColumns(10);

-		txtInput4.setBounds(264, 29, 23, 22);

-		frame.getContentPane().add(txtInput4);

-		jTextFieldList.add(txtInput4);

-		

-		JLabel lblT5 = new JLabel("T5");

-		lblT5.setBounds(299, 13, 15, 16);

-		frame.getContentPane().add(lblT5);

-		

-		JTextField txtInput5 = new JTextField();

-		txtInput5.setColumns(10);

-		txtInput5.setBounds(299, 29, 23, 22);

-		frame.getContentPane().add(txtInput5);

-		jTextFieldList.add(txtInput5);

-		

-		JLabel lblT6 = new JLabel("T6");

-		lblT6.setBounds(334, 13, 15, 16);

-		frame.getContentPane().add(lblT6);

-		

-		JTextField txtInput6 = new JTextField();

-		txtInput6.setColumns(10);

-		txtInput6.setBounds(334, 29, 23, 22);

-		frame.getContentPane().add(txtInput6);

-		jTextFieldList.add(txtInput6);

-		

-		JLabel lblT7 = new JLabel("T7");

-		lblT7.setBounds(369, 13, 15, 16);

-		frame.getContentPane().add(lblT7);

-		

-		JTextField txtInput7 = new JTextField();

-		txtInput7.setColumns(10);

-		txtInput7.setBounds(369, 29, 23, 22);

-		frame.getContentPane().add(txtInput7);

-		jTextFieldList.add(txtInput7);

-		

-		JLabel lblT8 = new JLabel("T8");

-		lblT8.setBounds(404, 13, 15, 16);

-		frame.getContentPane().add(lblT8);

-		

-		JTextField txtInput8 = new JTextField();

-		txtInput8.setColumns(10);

-		txtInput8.setBounds(404, 29, 23, 22);

-		frame.getContentPane().add(txtInput8);

-		jTextFieldList.add(txtInput8);

-		

-		JLabel lblT9 = new JLabel("T9");

-		lblT9.setBounds(439, 13, 15, 16);

-		frame.getContentPane().add(lblT9);

-		

-		JTextField txtInput9 = new JTextField();

-		txtInput9.setColumns(10);

-		txtInput9.setBounds(439, 29, 23, 22);

-		frame.getContentPane().add(txtInput9);

-		jTextFieldList.add(txtInput9);

-		

-		JLabel lblT10 = new JLabel("T10");

-		lblT10.setBounds(474, 13, 23, 16);

-		frame.getContentPane().add(lblT10);

-		

-		JTextField txtInput10 = new JTextField();

-		txtInput10.setColumns(10);

-		txtInput10.setBounds(474, 29, 23, 22);

-		frame.getContentPane().add(txtInput10);

-		jTextFieldList.add(txtInput10);

-		

-		JLabel lblT11 = new JLabel("T11");

-		lblT11.setBounds(509, 13, 23, 16);

-		frame.getContentPane().add(lblT11);

-		

-		JTextField txtInput11 = new JTextField();

-		txtInput11.setColumns(10);

-		txtInput11.setBounds(509, 29, 23, 22);

-		frame.getContentPane().add(txtInput11);

-		jTextFieldList.add(txtInput11);

-		

-		JLabel lblT12 = new JLabel("T12");

-		lblT12.setBounds(544, 13, 23, 16);

-		frame.getContentPane().add(lblT12);

-		

-		JTextField txtInput12 = new JTextField();

-		txtInput12.setColumns(10);

-		txtInput12.setBounds(544, 29, 23, 22);

-		frame.getContentPane().add(txtInput12);

-		jTextFieldList.add(txtInput12);

-		

-		JLabel lblT13 = new JLabel("T13");

-		lblT13.setBounds(579, 13, 23, 16);

-		frame.getContentPane().add(lblT13);

-		

-		JTextField txtInput13 = new JTextField();

-		txtInput13.setColumns(10);

-		txtInput13.setBounds(579, 29, 23, 22);

-		frame.getContentPane().add(txtInput13);

-		jTextFieldList.add(txtInput13);

-		

-		JLabel txtArm_0 = new JLabel("ARM0");

-		txtArm_0.setBounds(86, 154, 42, 22);

-		frame.getContentPane().add(txtArm_0);

-		

-		List arm0_list = new List();

-		arm0_list.setBounds(10, 180, 87, 145);

-		frame.getContentPane().add(arm0_list);

-		tListList.add(arm0_list);

-		

-		List arm0_rtList = new List();

-		arm0_rtList.setBounds(108, 180, 87, 145);

-		frame.getContentPane().add(arm0_rtList);

-		rtListList.add(arm0_rtList);

-		

-		JLabel txtArm_1 = new JLabel("ARM1");

-		txtArm_1.setBounds(288, 154, 42, 22);

-		frame.getContentPane().add(txtArm_1);

-		

-		List arm1_list = new List();

-		arm1_list.setBounds(212, 180, 87, 145);

-		frame.getContentPane().add(arm1_list);

-		tListList.add(arm1_list);

-		

-		List arm1_rtList = new List();

-		arm1_rtList.setBounds(309, 180, 87, 145);

-		frame.getContentPane().add(arm1_rtList);

-		rtListList.add(arm1_rtList);

-		

-		JLabel txtArm_2 = new JLabel("ARM2");

-		txtArm_2.setBounds(489, 154, 42, 22);

-		frame.getContentPane().add(txtArm_2);

-		

-		List arm2_list = new List();

-		arm2_list.setBounds(414, 180, 87, 145);

-		frame.getContentPane().add(arm2_list);

-		tListList.add(arm2_list);

-		

-		List arm2_rtList = new List();

-		arm2_rtList.setBounds(510, 180, 87, 145);

-		frame.getContentPane().add(arm2_rtList);

-		rtListList.add(arm2_rtList);

-		

-		JLabel txtArm_3 = new JLabel("ARM3");

-		txtArm_3.setBounds(691, 154, 42, 22);

-		frame.getContentPane().add(txtArm_3);

-		

-		List arm3_list = new List();

-		arm3_list.setBounds(616, 180, 87, 145);

-		frame.getContentPane().add(arm3_list);

-		tListList.add(arm3_list);

-		

-		List arm3_rtList = new List();

-		arm3_rtList.setBounds(711, 180, 87, 145);

-		frame.getContentPane().add(arm3_rtList);

-		rtListList.add(arm3_rtList);

-		

-		JLabel txtDenver_0 = new JLabel("Denver0");

-		txtDenver_0.setBounds(82, 335, 56, 22);

-		frame.getContentPane().add(txtDenver_0);

-		

-		List denver0_list = new List();

-		denver0_list.setBounds(10, 359, 87, 145);

-		frame.getContentPane().add(denver0_list);

-		tListList.add(denver0_list);

-		

-		List denver0_rtList = new List();

-		denver0_rtList.setBounds(108, 359, 87, 145);

-		frame.getContentPane().add(denver0_rtList);

-		rtListList.add(denver0_rtList);

-		

-		JLabel txtDenver_1 = new JLabel("Denver1");

-		txtDenver_1.setBounds(284, 335, 56, 22);

-		frame.getContentPane().add(txtDenver_1);

-		

-		List denver1_list = new List();

-		denver1_list.setBounds(212, 359, 87, 145);

-		frame.getContentPane().add(denver1_list);

-		tListList.add(denver1_list);

-		

-		List denver1_rtList = new List();

-		denver1_rtList.setBounds(309, 359, 87, 145);

-		frame.getContentPane().add(denver1_rtList);

-		rtListList.add(denver1_rtList);

-		

-		JLabel txtGpu = new JLabel("GPU");

-		txtGpu.setBounds(489, 335, 42, 22);

-		frame.getContentPane().add(txtGpu);

-		

-		List gpu_list = new List();

-		gpu_list.setBounds(414, 359, 87, 145);

-		frame.getContentPane().add(gpu_list);

-		tListList.add(gpu_list);

-		

-		List gpu_rtList = new List();

-		gpu_rtList.setBounds(510, 359, 87, 145);

-		frame.getContentPane().add(gpu_rtList);

-		rtListList.add(gpu_rtList);

-		

-		JLabel lblArm = new JLabel("0: ARM0");

-		lblArm.setBounds(12, 62, 56, 16);

-		frame.getContentPane().add(lblArm);

-		

-		JLabel lblArm_1 = new JLabel("1: ARM1");

-		lblArm_1.setBounds(12, 79, 56, 16);

-		frame.getContentPane().add(lblArm_1);

-		

-		JLabel lblArm_2 = new JLabel("2: ARM2");

-		lblArm_2.setBounds(12, 98, 56, 16);

-		frame.getContentPane().add(lblArm_2);

-		

-		JLabel lblArm_3 = new JLabel("3: ARM3");

-		lblArm_3.setBounds(12, 117, 56, 16);

-		frame.getContentPane().add(lblArm_3);

-		

-		JLabel lblDenver = new JLabel("4: Denver0");

-		lblDenver.setBounds(77, 62, 72, 16);

-		frame.getContentPane().add(lblDenver);

-		

-		JLabel lblDenver_1 = new JLabel("5: Denver1");

-		lblDenver_1.setBounds(77, 79, 72, 16);

-		frame.getContentPane().add(lblDenver_1);

-		

-		JLabel lblGpu = new JLabel("6: GPU");

-		lblGpu.setBounds(77, 96, 56, 16);

-		frame.getContentPane().add(lblGpu);

-		

-		JLabel lblApprta = new JLabel("APP4RTA");

-		lblApprta.setForeground(Color.BLUE);

-		lblApprta.setFont(new Font("Tahoma", Font.ITALIC, 20));

-		lblApprta.setBounds(747, 1, 87, 34);

-		frame.getContentPane().add(lblApprta);

-	}

-}
\ No newline at end of file