0.9.4 > 0.9.7 migration with other updates

1. E2ELatency.java
	- single-core analysis implemented
	- advanced multi-core analysis implemented

2. CPURta.java
	- minor changes with constructors

3. IRTA.java interface is added to CPURta class.

Change-Id: Ib6e0de8cf8155adaa68b42b0ef89cb27f5da97f8
Signed-off-by: Junhyung Ki <kijoonh91@gmail.com>
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore
new file mode 100644
index 0000000..ae3c172
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
index d5a0fa2..1375a74 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CPURta.java
@@ -8,12 +8,13 @@
  *
  * SPDX-License-Identifier: EPL-2.0
  *
- * Contributors: FH Dortmund - initial API and implementation
- * 
+ * Contributors:
+ *     FH Dortmund - initial API and implementation
  *******************************************************************************/
 package org.eclipse.app4mc.gsoc_rta;
 
 import java.io.File;
+import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -24,8 +25,13 @@
 
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
+import org.eclipse.app4mc.gsoc_rta.IRTA;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts;
+import org.eclipse.app4mc.gsoc_rta.Contention;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
 import org.eclipse.app4mc.amalthea.model.Amalthea;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
 import org.eclipse.app4mc.amalthea.model.ClearEvent;
 import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
 import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
@@ -36,9 +42,9 @@
 import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
 import org.eclipse.app4mc.amalthea.model.PuType;
 import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.RunnableCall;
 import org.eclipse.app4mc.amalthea.model.SetEvent;
 import org.eclipse.app4mc.amalthea.model.Task;
-import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;
 import org.eclipse.app4mc.amalthea.model.Time;
 import org.eclipse.app4mc.amalthea.model.TimeUnit;
 import org.eclipse.app4mc.amalthea.model.WaitEvent;
@@ -46,51 +52,53 @@
 import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
 import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
 import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
-import org.eclipse.emf.common.util.EList; 
+import org.eclipse.emf.common.util.EList;
 
-/**
- * Date: August 21-2019 
- * @author Junhyung Ki
- * @version 1.0
- *				This class is to analyze response time of CPU(e.g., ARM, Denver cores) Tasks in CPU-GPU Heterogeneous Systems
- *				The entire class is designed for Generic Algorithm Mapping to find the most optimized task mapping solution.
- *				Therefore, setting the integer array variable, 'tpuMapping' (which is considered as a mapping solution) along with 
- *				others ( Amalthea Model, 'model' setting, Task Response Time HashMap, 'trt' setting (for GPU Tasks), Processing Unit List, 'pul' setting
- *				should be the first step before executing any response time method. (Which is done by the constructor)
- */
-public class CPURta {
-	public final File inputFile = new File("model-input/WATERS19_release/ChallengeModel_release.amxmi");
-	
-	/**
-	 * Get Default IA Map
-	 * @return
-	 * 			this.defaultIAMapping
-	 */
-	public int[] getDefaultIAMapping() {
-		return SharedConsts.defaultIAMapping;
+public class CPURta implements IRTA {
+	final Logger log = Logger.getLogger(CPURta.class);
+	private Amalthea model;
+
+	public static void main(final String[] args) {
+		org.apache.log4j.BasicConfigurator.configure();
+          	// TODO set model and mapping int array
+          	// COMMENT: this func (executable) should actually be removed and replaced by a unit test
+		final CPURta cpurta = new CPURta(false);
+		cpurta.run();
 	}
-	
-	private Amalthea model = null;
 
-	/**
-	 * Constructor only for testing the class
-	 */
-	public CPURta() {
-		final Logger log = Logger.getLogger(CPURta.class);
-		final Amalthea pModel = AmaltheaLoader.loadFromFile(this.inputFile);
-		if (pModel == null) {
-			log.error("Model is empty. Please check the model path.");
+	public void run() {
+		if (this.model == null) {
+			System.out.println("Error: No model loaded!");
 			return;
-		} else {
-			this.setModel(AmaltheaLoader.loadFromFile(this.inputFile));
 		}
-		this.setTRT(this.getDefaultTRT(this.getModel()));
-		this.setIA(this.getDefaultIAMapping());
-		this.setPUl(CommonUtils.getPUs(this.getModel()));
+		log.setLevel(Level.ERROR);
+		log.debug("\n####################### The Test ########################\n");
+		log.debug("RT Time Sum: " + getRTSum(SharedConsts.timeType));
 	}
 	
 	/**
 	 * CPURta Constructor
+	 * @param forFunctions
+	 * 					true: to create an object to use functions
+	 * 					false: to create a default object for CPURta measurement
+	 */
+	public CPURta(final boolean forFunctions) {
+		if (!forFunctions) {
+			final Amalthea pModel = AmaltheaLoader.loadFromFile(this.inputFile);
+			if (pModel == null) {
+				log.error("Model is empty. Please check the model path.");
+				return;
+			} else {
+				this.setModel(pModel);
+			}
+			this.setTRT(getDefaultTRT(getModel()));
+			this.setIA(this.defaultIAMapping);
+			this.setPUl(CommonUtils.getPUs(getModel()));
+		}
+	}
+
+	/**
+	 * CPURta Constructor
 	 * @param model			the observed Amalthea Model
 	 * @param trt			the observed HashMap Task with Response Time (null works => the default testing trt will be assigned)
 	 * @param ia			the observed IntegerArray Mapping Model
@@ -104,49 +112,55 @@
 			this.setTRT(trt);
 		}
 		this.setIA(ia);
-		this.setPUl(pul);
+		if (pul == null) {
+			this.setPUl(CommonUtils.getPUs(getModel()));
+		} else {
+			this.setPUl(pul);
+		}
+		this.setContention(this.getIA(), this.getModel());
 	}
-	
+
 	/**
 	 * Since this method is used by RTARuntimeUtil, the visibility should be 'public'
 	 * @return
-	 * 			The Amalthea model object of the current CPURta class
+	 * 			The Amalthea model object of the current CPURtaIA class
 	 */
 	public Amalthea getModel() {
 		return this.model;
 	}
-	
+
 	/**
-	 * Set the Amalthea model object of the current CPURta class as the given Amalthea model parameter.
+	 * Set the Amalthea model object of the current CPURtaIA class as the given Amalthea model parameter.
 	 * @param pAmalthea			the parameter Amalthea model which would reinitialize the Amalthea model
 	 */
 	public void setModel(final Amalthea pAmalthea) {
-		this.model = pAmalthea; 
+		this.model = pAmalthea;
 		this.setGTCL(this.model);
 	}
-	
+
 	private HashMap<Task, Time> trt = null;
-	
+
 	/**
 	 * Since this method is used by GAMapping, the visibility should be 'public'
 	 * @return
 	 * 			trt(task with response time) HashMap variable
 	 */
+	@Override
 	public HashMap<Task, Time> getTRT() {
 		return this.trt;
 	}
-	
+
 	/**
 	 * Set the trt(task with response time) HashMap variable as the given trtp parameter variable.
 	 * Which would contains GPU tasks' response times from the beginning
-	 * @param trtp				the HashMap variable parameter which would reinitialize the trt variable of the current CPURta class.
+	 * @param trtp				the HashMap variable parameter which would reinitialize the trt variable of the current CPURtaIA class.
 	 */
 	public void setTRT(final HashMap<Task, Time> trtp) {
 		this.trt = trtp;
 	}
-	
+
 	/**
-	 * Get the default trt(task with response time) value in case of running CPURta class itself.
+	 * Get the default trt(task with response time) value in case of running CPURtaIA class itself.
 	 * @param model				the current class's Amalthea model which is used to get the trt value out of it
 	 * @return
 	 * 			the trt value which is derived out of the given parameter Amalthea model
@@ -158,32 +172,33 @@
 		for (final Task t : allTaskList) {
 			if (this.gpuTaskList.contains(t)) {
 				trt.put(t, FactoryUtil.createTime(BigInteger.valueOf(val), TimeUnit.PS));
-			} else {
+			}
+			else {
 				trt.put(t, FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS));
 			}
 		}
 		return trt;
 	}
-	
+
 	private int[] tpuMapping = null;
 
 	/**
-	 * Since this method is used by RTARuntimeUtil, the visibility should be 'public'
+	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
+	 *
 	 * @return
 	 * 			The tpuMapping integer array
 	 */
 	public int[] getIA() {
 		return this.tpuMapping;
 	}
-	
+
 	/**
 	 * Set the tpuMapping integer array (which would be used to modify the current task mapping to different Processing Units)
 	 * as the given tpumap parameter variable.
 	 * (The integer array would be used to modify the current task mapping to different Processing Units)
-	 * @param tpumap			the parameter integer array which would reinitialize the tpuMapping array of the current CPURta class.
+	 * @param tpumap			the parameter integer array which would reinitialize the tpuMapping array of the current CPURtaIA class.
 	 */
 	public void setIA(final int[] tpumap) {
-		final Logger log = Logger.getLogger(CPURta.class);
 		if (tpumap == null) {
 			this.tpuMapping = null;
 		} else if (tpumap.length == this.model.getSwModel().getTasks().size()) {
@@ -192,7 +207,7 @@
 			log.error("integer array size MUST match the number of tasks");
 		}
 	}
-	
+
 	private List<ProcessingUnit> pul = new ArrayList<>();
 
 	/**
@@ -203,28 +218,27 @@
 	public List<ProcessingUnit> getPUl() {
 		return this.pul;
 	}
-	
+
 	/**
 	 * Set the pul, the list of Processing Units variable (which would be used to map tasks along with tpuMapping array)
 	 * as the given pul parameter variable.
-	 * @param pul 				the parameter pul list which would reinitialize the pul list variable of the current CPURta class
+	 * @param pul 				the parameter pul list which would reinitialize the pul list variable of the current CPURtaIA class
 	 */
 	public void setPUl(final List<ProcessingUnit> pul) {
 		this.pul = pul;
 	}
-	
+
 	private Contention ct = null;
-	
+
 	/**
 	 * Get the contention instance
-	 *
 	 * @return
 	 * 			this.ct
 	 */
-	public Contention getCT() {
+	protected Contention getCT() {
 		return this.ct;
 	}
-	
+
 	/**
 	 * Set the ct (Contention) variable which would be used to calculate memory contention of the given task that will be added up to the response time result
 	 * as the newly generated contention instance with the given integer array
@@ -235,7 +249,7 @@
 	public void setContention(final int[] ia, final Amalthea model) {
 		this.ct = new Contention(ia, model);
 	}
-	
+
 	private List<Task> gpuTaskList = new ArrayList<Task>();
 
 	/**
@@ -256,12 +270,12 @@
 	protected List<Task> getTriggeringTaskList() {
 		return this.triggeringTaskList;
 	}
-	
+
 	/* this runnable is used to calculate execution time in RTARuntimeUtil class */
 	protected Runnable offloadingAsyncRunnable = null;
-	
+
 	private final HashMap<Task, List<List<Label>>> gpuToCpuLabels = new HashMap<Task, List<List<Label>>>();
-	
+
 	/**
 	 * Since this method is used by RTARuntimeUtil, the visibility should be 'protected'
 	 * @return
@@ -271,7 +285,7 @@
 	protected HashMap<Task, List<List<Label>>> getGTCL() {
 		return this.gpuToCpuLabels;
 	}
-	
+
 	/**
 	 * Not only set gpuToCpuLabels HashMap, this also set gpuTaskList (only contains GPU tasks),
 	 * triggeringTaskList (only contains tasks with InterProcessTrigger)
@@ -279,48 +293,48 @@
 	 * @param model				the parameter Amalthea model which is used to derived required labels of the corresponding GPU task
 	 */
 	private void setGTCL(final Amalthea model) {
-		if (model != null) {
-			final EList<Task> allTaskList = model.getSwModel().getTasks();
-			this.gpuTaskList = allTaskList.stream().filter(s -> s.getStimuli().get(0) instanceof InterProcessStimulus).collect(Collectors.toList());
-			/* find the triggering tasks */
-			for (final Task t : allTaskList) {
-				final List<CallSequenceItem> triggerList = SoftwareUtil.collectCalls(t, null, 
-						(call -> call instanceof InterProcessTrigger));
-				if (triggerList.size() != 0) {
-					this.triggeringTaskList.add(t);
-					if (RTARuntimeUtil.doesTaskHaveAsyncRunnable(t, this)) {
-						final List<CallSequenceItem> cList = SoftwareUtil.collectCalls(t, null, (call -> call instanceof TaskRunnableCall || 
-								call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
-						final int waitIndex = cList.indexOf(cList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
-						final int asyncOffloadingIndex = waitIndex + 1;
-						if (cList.get(asyncOffloadingIndex) instanceof TaskRunnableCall) {
-							this.offloadingAsyncRunnable = ((TaskRunnableCall) cList.get(asyncOffloadingIndex)).getRunnable();
-						}
+		final EList<Task> allTaskList = model.getSwModel().getTasks();
+		this.gpuTaskList = allTaskList.stream().filter(s -> s.getStimuli().get(0) instanceof InterProcessStimulus).collect(Collectors.toList());
+		/* find the triggering tasks */
+		for (final Task t : allTaskList) {
+			final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(t.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+			if (triggerList.size() != 0) {
+				this.triggeringTaskList.add(t);
+				if (RTARuntimeUtil.doesTaskHaveAsyncRunnable(t, this)) {
+					final List<ActivityGraphItem> cList = SoftwareUtil.collectActivityGraphItems(t.getActivityGraph(), null, (call -> call instanceof RunnableCall
+							|| call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+					final int waitIndex = cList.indexOf(cList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
+					final int asyncOffloadingIndex = waitIndex + 1;
+					if (cList.get(asyncOffloadingIndex) instanceof RunnableCall) {
+						this.offloadingAsyncRunnable = ((RunnableCall) cList.get(asyncOffloadingIndex)).getRunnable();
 					}
 				}
 			}
-			for (final Task t : this.gpuTaskList) {
-				final InterProcessStimulus ips = (InterProcessStimulus) (t.getStimuli().get(0));
-				Task triggeringTask = null;
-				for (final Task tt : this.triggeringTaskList) {
-					final InterProcessTrigger ipt = (InterProcessTrigger) SoftwareUtil.collectCalls(tt, null, 
-							(call -> call instanceof InterProcessTrigger)).stream().iterator().next();
-					if (ips.equals(ipt.getStimulus())) {
-						triggeringTask = tt;
-						break;
-					}
+		}
+		for (final Task t : this.gpuTaskList) {
+			final InterProcessStimulus ips = (InterProcessStimulus) (t.getStimuli().get(0));
+			Task triggeringTask = null;
+			for (final Task tt : this.triggeringTaskList) {
+				final InterProcessTrigger ipt = (InterProcessTrigger) SoftwareUtil
+						.collectActivityGraphItems(tt.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger)).stream().iterator().next();
+				if (ips.equals(ipt.getStimulus())) {
+					triggeringTask = tt;
+					break;
 				}
-				final List<Label> readLabelList = new ArrayList<Label>();
-				final List<Label> writeLabelList = new ArrayList<Label>();
-				final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(triggeringTask, null, (call -> call instanceof TaskRunnableCall || 
-						call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+			}
+			final List<Label> readLabelList = new ArrayList<Label>();
+			final List<Label> writeLabelList = new ArrayList<Label>();
+			if (null != triggeringTask) {
+				final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(triggeringTask.getActivityGraph(), null,
+						(call -> call instanceof RunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent
+								|| call instanceof WaitEvent));
 				final InterProcessTrigger ipt = (InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next();
 				final int indexforTrigger = callList.indexOf(ipt);
 				for (int i = 0; i < callList.size(); i++) {
 					Runnable thisRunnable = null;
 					/* Pre-processing Runnable */
-					if ((i < indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
-						thisRunnable = (Runnable) ((TaskRunnableCall) callList.get(i)).getRunnable();
+					if ((i < indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+						thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
 						final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
 						for (final LabelAccess la : thisLAList) {
 							if (la.getAccess().equals(LabelAccessEnum.READ)) {
@@ -329,8 +343,8 @@
 						}
 					}
 					/* Post-processing Runnable */
-					else if ((i > indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
-						thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
+					else if ((i > indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+						thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
 						final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
 						for (final LabelAccess la : thisLAList) {
 							if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
@@ -339,22 +353,17 @@
 						}
 					}
 				}
-				final List<List<Label>> listOfLabelList = new ArrayList<List<Label>>();
-				listOfLabelList.add(readLabelList);
-				listOfLabelList.add(writeLabelList);
-				this.gpuToCpuLabels.put(t, listOfLabelList);
 			}
-		} else {
-			this.gpuTaskList.clear();
-			this.triggeringTaskList.clear();
-			this.offloadingAsyncRunnable = null;
-			this.gpuToCpuLabels.clear();
+			final List<List<Label>> aryofLabelList = new ArrayList<List<Label>>();
+			aryofLabelList.add(readLabelList);
+			aryofLabelList.add(writeLabelList);
+			this.gpuToCpuLabels.put(t, aryofLabelList);
 		}
 	}
-	
+
 	/* To calculate pure memory access latency cost (without contention & pure computation(Ticks)) */
 	protected Time cumuAcTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-	
+
 	/**
 	 * @return
 	 * 			cumuAcTime, the total time of latency (Read & Write memory access) from CPUs
@@ -362,14 +371,14 @@
 	public Time getCumulatedMemAccCosts() {
 		return this.cumuAcTime;
 	}
-
+	
 	/**
 	 * Initializing cumuAcTime to 0 ps
 	 */
 	public void initCumulatedMemAccCosts() {
 		this.cumuAcTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 	}
-	
+
 	/* To calculate pure latency cost (without memory access latency & pure computation(Ticks)) */
 	protected Time cumuConTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 	
@@ -388,24 +397,10 @@
 		this.cumuConTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 	}
 	
-	public static void main(String[] args) {
-		org.apache.log4j.BasicConfigurator.configure();
-		Logger.getRootLogger().setLevel(Level.ERROR);
-		final CPURta cpurta = new CPURta();
-		cpurta.run();
-	}
-	
-	/**
-	 * Executable method
-	 */
-	public void run() {
-		final Logger log = Logger.getLogger(CPURta.class);
-		if (this.model == null) {
-			log.error("No model loaded!");
-			return;
-		}
-		log.debug("\n####################### The Test ########################\n");
-		log.debug("RT Time Sum: " + getCPUResponseTimeSum(SharedConsts.timeType));
+	HashMap<Task, Time> accessCosts = new HashMap<>();
+
+	public HashMap<Task, Time> getAccessCosts() {
+		return this.accessCosts;
 	}
 
 	/**
@@ -414,8 +409,8 @@
 	 * @return
 	 * 			total sum of all tasks' response times of the given mapped model (tpuMapping)
 	 */
-	public Time getCPUResponseTimeSum(final TimeType executionCase) {
-		final Logger log = Logger.getLogger(CPURta.class);
+	@Override
+	public Time getRTSum(final TimeType executionCase) {
 		if (this.model == null) {
 			log.error("No Model Loaded!");
 			return null;
@@ -431,8 +426,9 @@
 		}
 		this.setContention(this.getIA(), this.getModel());
 		Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final EList<Task> allTaskList = this.model.getSwModel().getTasks();
 		for (int i = 0; i < this.tpuMapping.length; i++) {
-			final Time rt = getTaskCPURT(this.model.getSwModel().getTasks().get(i), executionCase);
+			final Time rt = getTaskRTIA(allTaskList.get(i), executionCase);
 			if (rt.getValue().equals(BigInteger.valueOf(Long.MAX_VALUE)) && !SharedConsts.ignoreInfeasibility) {
 				return rt;
 			}
@@ -444,15 +440,15 @@
 		}
 		return time;
 	}
-	
+
 	/**
-	 * Calculate response time of the given task of the given Amalthea model with the mapping model (tpuMapping)
+	 * Calculate worst-case response time of the given task of the given Amalthea model with the mapping model (tpuMapping)
 	 * @param task				the observed task
 	 * @param executionCase		BCET, ACET, WCET
 	 * @return
 	 * 			response time of the observed task
 	 */
-	protected Time getTaskCPURT(final Task task, final TimeType executionCase) {
+	protected Time getTaskRTIA(final Task task, final TimeType executionCase) {
 		/* 1. validate thisTask is mapped to CPU */
 		final int tindex = this.model.getSwModel().getTasks().indexOf(task);
 		final int puindex = this.tpuMapping[tindex];
@@ -469,9 +465,16 @@
 			}
 		}
 		final List<Task> sortedTaskList = taskSorting(puTaskList);
-		return preciseTestCPURT(task, sortedTaskList, executionCase, pu);
+		if (executionCase.equals(TimeType.BCET)) {
+			return this.bestCaseCPURT(task, sortedTaskList, pu);
+		} else if (executionCase.equals(TimeType.WCET)) {
+			return SharedConsts.levelIBusyPeriod ? this.responseTimeLevelI(task, sortedTaskList, TimeType.WCET, pu)
+					: this.preciseTestCPURT(task, sortedTaskList, TimeType.WCET, pu);
+		}
+		return SharedConsts.levelIBusyPeriod ? this.responseTimeLevelI(task, sortedTaskList, TimeType.WCET, pu)
+				: this.preciseTestCPURT(task, sortedTaskList, TimeType.ACET, pu);
 	}
-	
+
 	/**
 	 * Sort out the given list of tasks (in order of shorter period first - Rate Monotonic Scheduling)
 	 * @param taskList			list of tasks that is mapped to the same core
@@ -498,19 +501,17 @@
 		}
 		return newTaskList;
 	}
-	
+
 	/**
-	 * Visibility - public (This method is for the UI version code (ui package > RTApp.java))
-	 * Calculate response time of the observed task according to the periodic tasks response time analysis algorithm.
+	 * Calculate response time of the observed task according to the worst-case RMS response time analysis algorithm.
 	 * @param task				the observed task
 	 * @param taskList			list of tasks that is mapped to the same core
 	 * @param executionCase		BCET, ACET, WCET
 	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
 	 * @return
-	 * 			response time of the observed task
+	 * 			the worst-case response time of the observed task
 	 */
 	public Time preciseTestCPURT(final Task task, final List<Task> taskList, final TimeType executionCase, final ProcessingUnit pu) {
-		final Logger log = Logger.getLogger(CPURta.class);
 		Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 		Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 		if (taskList.size() == 0) {
@@ -532,102 +533,363 @@
 			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 		}
 		final RTARuntimeUtil rtaut = new RTARuntimeUtil();
-		for (int i = 0; i < index + 1; i++) {
-			period = CommonUtils.getStimInTime(taskList.get(i));
-			if (index == 0) {
-				thisRT = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, this);
-				if (thisRT.compareTo(period) <= 0) {
-					/* To analyze the pure latency time */
-					if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
-						this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
-						this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
-					}
-					return thisRT;
+		period = CommonUtils.getStimInTime(taskList.get(index));
+		if (index == 0) {
+			thisRT = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(index), pu, executionCase, this);
+			if (thisRT.compareTo(period) <= 0) {
+				/* To analyze the pure latency time */
+				if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
+					this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
+					this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
 				}
+				return thisRT;
+			}
+			log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+					+ " for task " + task.getName());
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		else {
+			/* In the case of a COOPERATIVE Preemption typed Task */
+			if (taskList.get(index).getPreemption().equals(Preemption.COOPERATIVE)) {
+				// TODO: Blocking
+			}
+			final Time thisExeTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(index), pu, executionCase, this);
+			if (thisExeTime.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+				return thisExeTime;
+			} else if (thisExeTime.compareTo(period) > 0) {
 				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
 						+ " for task " + task.getName());
 				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-			} else if (i == index) {
-				/* In the case of a COOPERATIVE Preemption typed Task */
-				if (taskList.get(i).getPreemption().equals(Preemption.COOPERATIVE)) {
-					// TODO: Blocking
-				}
-				final Time thisExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, this);
-				if (thisExeTime.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
-					return thisExeTime;
-				} else if (thisExeTime.compareTo(period) > 0) {
-					log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
-							+ " for task " + task.getName());
-					return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
-				}
-				Time culmulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-				/* 1. add all the execution time till the index */
-				for (int j = 0; j < i + 1; j++) {
-					final Time thisTime = rtaut.getExecutionTimeforCPUTask(taskList.get(j), pu, executionCase, this);
-					culmulativeRT = culmulativeRT.add(thisTime);
-				}
-				if (culmulativeRT.compareTo(period) <= 0) {
-					while (true) {
-						Time excepThisExeTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-						for (int k = 0; k < i; k++) {
-							Time localPeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-							localPeriod = CommonUtils.getStimInTime(taskList.get(k));
-							final Time preExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(k), pu, executionCase, this);
-							final double ri_period = Math.ceil(culmulativeRT.divide(localPeriod));
-							excepThisExeTime = excepThisExeTime.add(preExeTime.multiply(ri_period));
-						}
-						Time culmulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-						culmulativeRT_x = thisExeTime.add(excepThisExeTime);
-						if (culmulativeRT_x.compareTo(period) <= 0) {
-							if (culmulativeRT_x.compareTo(culmulativeRT) == 0) {
-								thisRT = culmulativeRT_x;
-								/* To analyze the pure latency time */
-								if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
-									this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
-									this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
-								}
-								return thisRT;
+			}
+			Time cumulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			/* 1. add all the execution time till the index - RT_0 */
+			for (int j = 0; j < index + 1; j++) {
+				final Time thisTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(j), pu, executionCase, this);
+				cumulativeRT = cumulativeRT.add(thisTime);
+			}
+			if (cumulativeRT.compareTo(period) <= 0) {
+				while (true) {
+					Time excepThisExeTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					for (int j = 0; j < index; j++) {
+						Time localPeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						localPeriod = CommonUtils.getStimInTime(taskList.get(j));
+						final Time preExeTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(j), pu, executionCase, this);
+						final double ri_period = Math.ceil(cumulativeRT.divide(localPeriod));
+						excepThisExeTime = excepThisExeTime.add(preExeTime.multiply(ri_period));
+					}
+					Time cumulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					cumulativeRT_x = thisExeTime.add(excepThisExeTime);
+					if (cumulativeRT_x.compareTo(period) <= 0) {
+						if (cumulativeRT_x.compareTo(cumulativeRT) == 0) {
+							thisRT = cumulativeRT_x;
+							/* To analyze the pure latency time */
+							if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
+								this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
+								this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
 							}
-							culmulativeRT = culmulativeRT_x;
-						} else {
-							log.debug("!!! This is non schedulable...!!! Because of the period " + period
-									+ " being less than the response time (culmulativeRT_x) of " + culmulativeRT_x + " for task " + task.getName());
-							if (SharedConsts.ignoreInfeasibility) {
-								return culmulativeRT_x;
-							}
-							return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+							return thisRT;
 						}
+						cumulativeRT = cumulativeRT_x;
+					} else {
+						log.debug("!!! This is non schedulable...!!! Because of the period " + period
+							+ " being less than the response time (cumulativeRT_x) of " + cumulativeRT_x + " for task " + task.getName());
+						if (SharedConsts.ignoreInfeasibility) {
+							return cumulativeRT_x;
+						}
+						return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 					}
 				}
-				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + culmulativeRT
-						+ " for task " + task.getName());
-				if (SharedConsts.ignoreInfeasibility) {
-					return culmulativeRT;
-				}
-				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 			}
+			log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + cumulativeRT
+				+ " for task " + task.getName());
+			if (SharedConsts.ignoreInfeasibility) {
+				return cumulativeRT;
+			}
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 		}
-		/* To analyze the pure latency time */
-		if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
-			this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(task, pu, executionCase));
-			this.cumuConTime = this.cumuConTime.add(this.getCT().contentionForTask(task));
-		}
-		return thisRT;
 	}
 	
 	/**
-	 * Calculate response time of the observed task according to the implicit communication paradigm.
+	 * Calculate response time of the observed task according to the best-case RMS response time analysis algorithm.
+	 * (source: https://www.researchgate.net/publication/3958297_Exact_best-case_response_time_analysis_of_fixed_priority_scheduled_tasks (equ_16))
+	 * @param task				the observed task
+	 * @param taskList			list of tasks that is mapped to the same core
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @return
+	 * 			the best-case response time of the observed task
+	 */
+	public Time bestCaseCPURT(final Task task, final List<Task> taskList, final ProcessingUnit pu) {
+		Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (taskList.size() == 0) {
+			log.debug("!!! This taskList is empty so I am returning MAX !!!");
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		} else if (!taskList.contains(task)) {
+			log.debug("!!! This taskList is empty so I am returning MAX !!!");
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		/* to check if the given task is in the taskList */
+		int flag = 0;
+		int index = 0;
+		for (int i = 0; i < taskList.size(); i++) {
+			if (task.equals(taskList.get(i))) {
+				flag = 1;
+				index = i;
+				break;
+			}
+		}
+		if (flag == 0) {
+			log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+		Time bR_0 = this.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
+		for (int i = 0; i < index + 1; i++) {
+			if (index == 0) {
+				bcrt = bR_0;
+				break;
+			}
+			else if (i == index) {
+				final Time i_BCET = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, this);
+				final Time rt_0 = this.preciseTestCPURT(task, taskList, TimeType.BCET, pu);
+				Time rt_n = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				boolean isItFirst = true;
+				while (true) {
+					Time sum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					for (int j = 0; j < i; j++) {
+						final Task curTask = taskList.get(j);
+						final Time curTask_period = CommonUtils.getStimInTime(curTask);
+						final Time curTask_BCET = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.BCET, this);
+						if (isItFirst) {
+							double ceil_value = Math.ceil((rt_0.subtract(curTask_period)).divide(curTask_period));
+							if (ceil_value < 0) {
+								ceil_value = 0;
+							}
+							final Time curIterTime = curTask_BCET.multiply(ceil_value);
+							sum = sum.add(curIterTime);
+						} else {
+							double ceil_value = Math.ceil((rt_n.subtract(curTask_period)).divide(curTask_period));
+							if (ceil_value < 0) {
+								ceil_value = 0;
+							}
+							final Time curIterTime = curTask_BCET.multiply(ceil_value);
+							sum = sum.add(curIterTime);
+						}
+					}
+					Time temp = i_BCET.add(sum);
+					if(isItFirst) {
+						if (temp.compareTo(rt_0) == 0) {
+							bcrt = temp;
+							break;
+						} else {
+							rt_n = temp;
+						}
+					} else {
+						if (temp.compareTo(rt_n) == 0) {
+							bcrt = temp;
+							break;
+						} else {
+							rt_n = temp;
+						}
+					}
+					isItFirst = false;
+				}
+			}
+		}
+		return bcrt;
+	}
+
+	/** New method implement from the news paper with Level_i
+	 * @param thisTask
+	 * @param thisTaskList
+	 * @param executionCase
+	 * @param pu
+	 * @return
+	 */
+	private Time responseTimeLevelI(final Task thisTask, final List<Task> thisTaskList, final TimeType executionCase, final ProcessingUnit pu) {
+		Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+
+		if (thisTaskList.size() == 0) {
+			log.debug("!!! This taskList is empty !!!");
+			// TODO: Catch Exception
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+
+		/* to check if the given task is in the thisTaskList */
+		int flag = 0;
+		int index = 0;
+		for (int i = 0; i < thisTaskList.size(); i++) {
+			if (thisTask.equals(thisTaskList.get(i))) {
+				flag = 1;
+				index = i;
+				break;
+			}
+		}
+		/*
+		 * the problem seems like once a gpu task (mapped to cpu) changes its stimulus it becomes completely new (or maybe not)
+		 */
+		if (flag == 0) {
+			log.debug("!!! Nothing in the taskList matches the given Task !!!" + " --- thisTask: " + thisTask.getName());
+
+			// TODO: Catch Exception
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+		final Time checkingTime = rtaut.getExecutionTimeforCPUTaskIA(thisTask, pu, executionCase, this);
+
+		if (checkingTime.getValue().longValue() == 0) {
+
+			return checkingTime;
+		}
+
+		/* Checking whether task list is schedulable or not */
+		double UtilizationValue = 0.0;
+		for (final Task task : thisTaskList) {
+			final Time exeTime = rtaut.getExecutionTimeforCPUTaskIA(task, pu, executionCase, this);
+			final Time periodTime = CommonUtils.getStimInTime(task);
+			final BigInteger exeTimePico = AmaltheaServices.convertToPicoSeconds(exeTime);
+			final BigInteger periodTimePico = AmaltheaServices.convertToPicoSeconds(periodTime);
+
+			UtilizationValue += (exeTimePico.doubleValue()) / (periodTimePico.doubleValue());
+		}
+
+		if (UtilizationValue > 1.0) {
+			final Time rpTime = FactoryUtil.createTime(Long.MAX_VALUE, TimeUnit.PS);
+			return rpTime;
+		}
+
+		/* ----------------------------------------------- */
+		/* Start applying level i approach from here */
+		for (int i = 0; i < index + 1; i++) {
+			period = CommonUtils.getStimInTime(thisTaskList.get(i));
+			if (index == 0) {
+				thisRT = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(i), pu, executionCase, this);
+				if (thisRT.compareTo(period) <= 0) {
+					if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
+						this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(thisTask, pu, executionCase));
+					}
+					return thisRT;
+				}
+				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " is less than the execution time of " + thisRT + " for task "
+						+ thisTask.getName());
+
+				// TODO: Catch Exception
+				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+			}
+			else if (i == index) {
+				/* In the case of a COOPERATIVE Preemption typed Task */
+				if (thisTaskList.get(i).getPreemption().equals(Preemption.COOPERATIVE)) {
+					// TODO: Blocking
+				}
+				final Time thisExeTime = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(i), pu, executionCase, this);
+				if (thisExeTime.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+					return thisExeTime;
+				}
+				else if (thisExeTime.compareTo(period) > 0) {
+					log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the execution time of " + thisRT
+							+ " for task " + thisTask.getName());
+					// TODO: Catch Exception
+					return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+				}
+
+				BigDecimal l_value = BigDecimal.valueOf(1.0);
+				BigDecimal currentL_value = BigDecimal.valueOf(1.0);
+				BigDecimal temp = BigDecimal.valueOf(2.0);
+				BigDecimal localSum = BigDecimal.valueOf(0.0);
+				while (localSum.compareTo(temp) != 0) {
+					localSum = BigDecimal.valueOf(0);
+					for (int j = 0; j < i + 1; j++) {
+						temp = currentL_value;
+						Time thePeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						Time localExe = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						thePeriod = CommonUtils.getStimInTime(thisTaskList.get(j));
+
+						localExe = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(j), pu, executionCase, this);
+						final double periodInDouble = AmaltheaServices.convertToPicoSeconds(thePeriod).doubleValue();
+						final double exeInDouble = AmaltheaServices.convertToPicoSeconds(localExe).doubleValue();
+						final BigDecimal periodInDoubleBD = BigDecimal.valueOf(periodInDouble);
+						final BigDecimal exeInDoubleBD = BigDecimal.valueOf(exeInDouble);
+
+						/* l_value = Math.ceil(currentL_value / periodInDouble) * exeInDouble; */
+						l_value = currentL_value.divide(periodInDoubleBD, 0, BigDecimal.ROUND_UP).multiply(exeInDoubleBD);
+						localSum = localSum.add(l_value);
+					}
+					currentL_value = localSum;
+
+				}
+				final BigDecimal taskPeriodBD = BigDecimal.valueOf(AmaltheaServices.convertToPicoSeconds(period).doubleValue());
+
+				/*
+				 * final int k_value = (int) Math.ceil(localSum /AmaltheaServices.convertToPicoSeconds(period).doubleValue());
+				 */
+				final BigDecimal k_value = localSum.divide(taskPeriodBD, 0, BigDecimal.ROUND_UP);
+				// System.out.println("k value = " + k_value);
+				final List<Double> rtList = new ArrayList<Double>();
+
+				// double fl_value = 1.0;
+				BigDecimal fl_value = BigDecimal.valueOf(1.0);
+				// double ftemp = 3.0;
+				BigDecimal ftemp = BigDecimal.valueOf(3.0);
+
+				for (int j = 1; j <= k_value.intValue(); j++) {
+					ftemp = BigDecimal.valueOf(3.0);
+					while (fl_value.compareTo(ftemp) != 0) {
+						// double flocalSum = 0.0;
+						BigDecimal flocalSum = BigDecimal.valueOf(0.0);
+						// double fSum = 0.0;
+						BigDecimal fSum = BigDecimal.valueOf(0.0);
+						// Assign temp for comparation
+						ftemp = fl_value;
+						for (int m = 0; m < i; m++) {
+							Time thePeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+							Time localExe = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+							thePeriod = CommonUtils.getStimInTime(thisTaskList.get(j));
+							localExe = rtaut.getExecutionTimeforCPUTaskIA(thisTaskList.get(m), pu, executionCase, this);
+							final BigInteger periodInteger = AmaltheaServices.convertToPicoSeconds(thePeriod);
+							final BigInteger exeInteger = AmaltheaServices.convertToPicoSeconds(localExe);
+							// Value parsing
+							final double Tj = periodInteger.doubleValue();
+							final double Cj = exeInteger.doubleValue();
+							final BigDecimal TjBD = BigDecimal.valueOf(Tj);
+							final BigDecimal CjBD = BigDecimal.valueOf(Cj);
+
+							// flocalSum = Math.ceil(fl_value / Tj) * Cj;
+							flocalSum = fl_value.divide(TjBD, 0, BigDecimal.ROUND_UP).multiply(CjBD);
+
+							fSum = fSum.add(flocalSum);
+						}
+						final double Ci = AmaltheaServices.convertToPicoSeconds(thisExeTime).doubleValue();
+						// Fvalue of 1 iteration
+						// fl_value = fSum + j * Ci;
+						fl_value = BigDecimal.valueOf(fSum.doubleValue() + j * Ci);
+					}
+					// Final fl_value landed here
+					final double this_rt = fl_value.doubleValue() - (j - 1) * AmaltheaServices.convertToPicoSeconds(period).doubleValue();
+					rtList.add(this_rt);
+				}
+				final double rpt = Collections.max(rtList);
+				final Time responseTime = FactoryUtil.createTime(BigInteger.valueOf((long) rpt), TimeUnit.PS);
+				if (thisRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) > 0) {
+					this.cumuAcTime = this.cumuAcTime.add(rtaut.getTaskMemoryAccessTime(thisTask, pu, executionCase));
+				}
+				return responseTime;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Calculate the worst-case response time of the observed task according to the implicit periodic tasks response time analysis algorithm.
 	 * @param task				the observed task
 	 * @param taskList			list of tasks that is mapped to the same core
 	 * @param executionCase		BCET, ACET, WCET
 	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
-	 * @param cpurta			the instance of CPURta class that contains model & mapping IA info
+	 * @param cpurta			the instance of CPURtaIA class that contains model & mapping IA info
 	 * @return
-	 * 				response time of the observed task (implicit communication paradigm)
+	 * 				the worst-case response time of the observed task (implicit communication paradigm)
 	 */
 	public Time implicitPreciseTest(final Task task, final List<Task> taskList, final TimeType executionCase, 
 			final ProcessingUnit pu, final CPURta cpurta) {
-		final Logger log = Logger.getLogger(CPURta.class);
 		Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 		Time period = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 		if (taskList.size() == 0) {
@@ -652,7 +914,7 @@
 		for (int i = 0; i < index + 1; i++) {
 			period = CommonUtils.getStimInTime(taskList.get(i));
 			if (index == 0) {
-				thisRT = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, cpurta);
+				thisRT = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(i), pu, executionCase, cpurta);
 				final Time[] ta = rtaut.getLocalCopyTimeArray(taskList.get(i), pu, executionCase, cpurta);
 				for (int j = 0; j < ta.length; j++) {
 					thisRT = thisRT.add(ta[j]);
@@ -665,7 +927,7 @@
 				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 			} else if (i == index) {
 				/* In the case of a COOPERATIVE Preemption typed Task */
-				Time thisExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(i), pu, executionCase, cpurta);
+				Time thisExeTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(i), pu, executionCase, cpurta);
 				final Time[] ta = rtaut.getLocalCopyTimeArray(taskList.get(i), pu, executionCase, cpurta);
 				for (int j = 0; j < ta.length; j++) {
 					thisExeTime = thisExeTime.add(ta[j]);
@@ -677,72 +939,216 @@
 							+ " for task " + task.getName());
 					return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 				}
-				Time culmulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time cumulativeRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 				/* 1. add all the execution time till the index */
 				for (int j = 0; j < i + 1; j++) {
-					Time thisTime = rtaut.getExecutionTimeforCPUTask(taskList.get(j), pu, executionCase, cpurta);
+					Time thisTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(j), pu, executionCase, cpurta);
 					final Time[] ta_ = rtaut.getLocalCopyTimeArray(taskList.get(j), pu, executionCase, cpurta);
 					for (int k = 0; k < ta_.length; k++) {
 						thisTime = thisTime.add(ta[k]);
 					}
-					culmulativeRT = culmulativeRT.add(thisTime);
+					cumulativeRT = cumulativeRT.add(thisTime);
 				}
-				if (culmulativeRT.compareTo(period) <= 0) {
+				if (cumulativeRT.compareTo(period) <= 0) {
 					while (true) {
 						Time excepThisExeTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 						for (int j = 0; j < i; j++) {
 							Time localPeriod = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 							localPeriod = CommonUtils.getStimInTime(taskList.get(j));
-							Time preExeTime = rtaut.getExecutionTimeforCPUTask(taskList.get(j), pu, executionCase, cpurta);
+							Time preExeTime = rtaut.getExecutionTimeforCPUTaskIA(taskList.get(j), pu, executionCase, cpurta);
 							final Time[] ta_ = rtaut.getLocalCopyTimeArray(taskList.get(j), pu, executionCase, cpurta);
 							for (int k = 0; k < ta_.length; k++) {
 								preExeTime = preExeTime.add(ta_[k]);
 							}
-							final double ri_period = Math.ceil(culmulativeRT.divide(localPeriod));
+							final double ri_period = Math.ceil(cumulativeRT.divide(localPeriod));
 							excepThisExeTime = excepThisExeTime.add(preExeTime.multiply(ri_period));
 						}
-						Time culmulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-						culmulativeRT_x = thisExeTime.add(excepThisExeTime);
-						if (culmulativeRT_x.compareTo(period) <= 0) {
-							if (culmulativeRT_x.compareTo(culmulativeRT) == 0) {
-								thisRT = culmulativeRT_x;
+						Time cumulativeRT_x = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						cumulativeRT_x = thisExeTime.add(excepThisExeTime);
+						if (cumulativeRT_x.compareTo(period) <= 0) {
+							if (cumulativeRT_x.compareTo(cumulativeRT) == 0) {
+								thisRT = cumulativeRT_x;
 								return thisRT;
 							}
-							culmulativeRT = culmulativeRT_x;
+							cumulativeRT = cumulativeRT_x;
 						} else {
 							log.debug("!!! This is non schedulable...!!! Because of the period " + period
-									+ " being less than the response time (culmulativeRT_x) of " + culmulativeRT_x + " for task " + task.getName());
+									+ " being less than the response time (cumulativeRT_x) of " + cumulativeRT_x + " for task " + task.getName());
 							if (SharedConsts.ignoreInfeasibility) {
-								return culmulativeRT_x;
+								return cumulativeRT_x;
 							}
 							return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 						}
 					}
 				}
-				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + culmulativeRT
+				log.debug("!!! This is non schedulable...!!! Because of the period " + period + " being less than the response time of " + cumulativeRT
 						+ " for task " + task.getName());
 				if (SharedConsts.ignoreInfeasibility) {
-					return culmulativeRT;
+					return cumulativeRT;
 				}
 				return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
 			}
 		}
 		return thisRT;
 	}
+
+	/**
+	 * Calculate response time of the observed task according to the best-case RMS response time analysis algorithm with Implicit Communication.
+	 * (source: https://www.researchgate.net/publication/3958297_Exact_best-case_response_time_analysis_of_fixed_priority_scheduled_tasks (equ_16))
+	 * @param task				the observed task
+	 * @param taskList			list of tasks that is mapped to the same core
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @return
+	 * 			the best-case response time of the observed task with Implicit Communication
+	 */
+	public Time implicitBCCPURT(final Task task, final List<Task> taskList, final ProcessingUnit pu, final CPURta cpurta) {
+		Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (taskList.size() == 0) {
+			log.debug("!!! This taskList is empty so I am returning MAX !!!");
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		} else if (!taskList.contains(task)) {
+			log.debug("!!! This taskList is empty so I am returning MAX !!!");
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		/* to check if the given task is in the taskList */
+		int flag = 0;
+		int index = 0;
+		for (int i = 0; i < taskList.size(); i++) {
+			if (task.equals(taskList.get(i))) {
+				flag = 1;
+				index = i;
+				break;
+			}
+		}
+		if (flag == 0) {
+			log.debug("!!! Nothing in the taskList matches the given Task !!! So I am returning 0s" + " --- thisTask: " + task.getName());
+			return FactoryUtil.createTime(BigInteger.valueOf(Long.MAX_VALUE), TimeUnit.PS);
+		}
+		final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+		Time bR_0 = this.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
+		for (int i = 0; i < index + 1; i++) {
+			if (index == 0) {
+				bcrt = bR_0;
+				break;
+			}
+			else if (i == index) {
+				Time i_BCET = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, this);
+				final Time[] ta = rtaut.getLocalCopyTimeArray(task, pu, TimeType.BCET, this);
+				for (int j = 0; j < ta.length; j++) {
+					i_BCET = i_BCET.add(ta[j]);
+				}
+				final Time rt_0 = this.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);
+				Time rt_n = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				boolean isItFirst = true;
+				while (true) {
+					Time sum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					for (int j = 0; j < i; j++) {
+						final Task curTask = taskList.get(j);
+						final Time curTask_period = CommonUtils.getStimInTime(curTask);
+						Time curTask_BCET = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.BCET, this);
+						final Time[] ta_ = rtaut.getLocalCopyTimeArray(curTask, pu, TimeType.BCET, this);
+						for (int k = 0; k < ta_.length; k++) {
+							curTask_BCET = curTask_BCET.add(ta[k]);
+						}
+						if (isItFirst) {
+							double ceil_value = Math.ceil((rt_0.subtract(curTask_period)).divide(curTask_period));
+							if (ceil_value < 0) {
+								ceil_value = 0;
+							}
+							final Time curIterTime = curTask_BCET.multiply(ceil_value);
+							sum = sum.add(curIterTime);
+						} else {
+							double ceil_value = Math.ceil((rt_n.subtract(curTask_period)).divide(curTask_period));
+							if (ceil_value < 0) {
+								ceil_value = 0;
+							}
+							final Time curIterTime = curTask_BCET.multiply(ceil_value);
+							sum = sum.add(curIterTime);
+						}
+					}
+					Time temp = i_BCET.add(sum);
+					System.out.println("sum: " + sum + ", temp: " + temp);
+					if(isItFirst) {
+						if (temp.compareTo(rt_0) == 0) {
+							bcrt = temp;
+							break;
+						} else {
+							rt_n = temp;
+						}
+					} else {
+						if (temp.compareTo(rt_n) == 0) {
+							bcrt = temp;
+							break;
+						} else {
+							rt_n = temp;
+						}
+					}
+					isItFirst = false;
+				}
+			}
+		}
+		return bcrt;
+	}
+
+	/**
+	 * get the processing unit that the observed task is mapped to
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 				pu
+	 */
+	protected ProcessingUnit getPU(final Task task, final CPURta cpurta) {
+		final int tindex = cpurta.getModel().getSwModel().getTasks().indexOf(task);
+		final int puindex = cpurta.getIA()[tindex];
+		final ProcessingUnit pu = cpurta.getPUl().get(puindex);
+		return pu;
+	}
+
+	/**
+	 * get the sorted task listed based on the given integer array mapping
+	 * @param task			the observed task
+	 * @param pu			ProcessingUnit that would compute the given method
+	 * @param cpurta		the instance of CPURta class
+	 * @return
+	 * 				sortedTaskList
+	 */
+	protected List<Task> getSortedTaskList(final Task task, final ProcessingUnit pu, final CPURta cpurta) {
+		final int puIndex = cpurta.getPUl().indexOf(pu);
+		/* 2. get all tasks mapped to this CPU */
+		final List<Task> puTaskList = new ArrayList<Task>();
+		for (int i = 0; i < cpurta.getIA().length; i++) {
+			if (cpurta.getIA()[i] == puIndex) {
+				puTaskList.add(cpurta.getModel().getSwModel().getTasks().get(i));
+			}
+		}
+		final List<Task> sortedTaskList = taskSorting(puTaskList);
+		return sortedTaskList;
+	}
+	
+	protected List<Task> getHigherPriorityTasks(final Task task, CPURta cpurta) {
+		final ProcessingUnit pu = getPU(task, cpurta);
+		final List<Task> hpList = getSortedTaskList(task, pu, cpurta);
+		final int index = hpList.indexOf(task);
+		final int count = hpList.size() - index;
+		for (int i = 0; i < count; i++) {
+			hpList.remove(hpList.size()-1);
+		}
+		return hpList;
+	}
 	
 	/**
-	 * Visibility - public (This method is for the UI version code (ui package > RTApp.java))
+	 * Visibility - public (This method is for EffectChainLatency)
 	 * It returns HashMap<Integer, List<Task>> Type reference that contains an Integer(number of Processing Unit index) and the corresponding List of Tasks
 	 * This is to visualize which task is mapped to which processing unit.
 	 * @return
 	 * 			HashMap<Integer, List<Task>> puListHashMap
 	 */
-	public HashMap<Integer, List<Task>> be_getPUTaskListHashMap(final Amalthea model) {
-		HashMap<Integer, List<Task>> puListHashMap = new HashMap<>();
+	public HashMap<Integer, List<Task>> getPUTaskListHashMap(final Amalthea model) {
+		final HashMap<Integer, List<Task>> puListHashMap = new HashMap<>();
 		final EList<Task> allTaskList = model.getSwModel().getTasks();
-		for(int i = 0; i < this.pul.size(); i++) {
+		for (int i = 0; i < this.pul.size(); i++) {
 			final List<Task> puTaskList = new ArrayList<Task>();
-			for(int j = 0; j < this.tpuMapping.length; j++) {
+			for (int j = 0; j < this.tpuMapping.length; j++) {
 				final int puIndex = this.tpuMapping[j];
 				if (i == puIndex) {
 					puTaskList.add(allTaskList.get(j));
@@ -752,15 +1158,19 @@
 		}
 		return puListHashMap;
 	}
+
+	@Override
+	public Time getRT(final Task t, final TimeType timeType) {
+		if (null == getTRT().get(t)) {
+			getRTSum(timeType);
+		}
+		return getTRT().get(t);
+	}
 }
 
 /**
- * @Date: August 21-2019
  * @author Junhyung Ki
- * @version 1.0
- *			This inner class is used for the method "taskSorting" to help compare between two tasks' periods (which is longer)
- *			If the time of arg0 is shorter than that of arg1, it returns -1.
- *			If the time of arg0 is longer than that of arg1, it returns 1.
+ *			this inner class is used for the method "taskSorting" to help compare between two tasks' periods (which is longer)
  */
 class TimeCompIA implements Comparator<Time> {
 	@Override
@@ -770,4 +1180,4 @@
 		}
 		return 1;
 	}
-}
\ No newline at end of file
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java
index 6fb97c0..a49bd8b 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/CommonUtils.java
@@ -31,16 +31,15 @@
 import java.util.stream.Collectors;
 
 import org.apache.log4j.Logger;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
 import org.eclipse.app4mc.amalthea.model.Amalthea;
 import org.eclipse.app4mc.amalthea.model.AmaltheaFactory;
 import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
-import org.eclipse.app4mc.amalthea.model.CallSequence;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
 import org.eclipse.app4mc.amalthea.model.DiscreteValueConstant;
 import org.eclipse.app4mc.amalthea.model.DiscreteValueStatistics;
 import org.eclipse.app4mc.amalthea.model.ExecutionNeed;
 import org.eclipse.app4mc.amalthea.model.Frequency;
-import org.eclipse.app4mc.amalthea.model.GraphEntryBase;
+import org.eclipse.app4mc.amalthea.model.Group;
 import org.eclipse.app4mc.amalthea.model.HwDefinition;
 import org.eclipse.app4mc.amalthea.model.IDiscreteValueDeviation;
 import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
@@ -53,12 +52,12 @@
 import org.eclipse.app4mc.amalthea.model.ProcessingUnitDefinition;
 import org.eclipse.app4mc.amalthea.model.PuType;
 import org.eclipse.app4mc.amalthea.model.Runnable;
-import org.eclipse.app4mc.amalthea.model.RunnableItem;
+import org.eclipse.app4mc.amalthea.model.RunnableCall;
 import org.eclipse.app4mc.amalthea.model.SchedulerAllocation;
 import org.eclipse.app4mc.amalthea.model.Stimulus;
 import org.eclipse.app4mc.amalthea.model.Task;
 import org.eclipse.app4mc.amalthea.model.TaskAllocation;
-import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;
+import org.eclipse.app4mc.amalthea.model.TaskScheduler;
 import org.eclipse.app4mc.amalthea.model.Ticks;
 import org.eclipse.app4mc.amalthea.model.Time;
 import org.eclipse.app4mc.amalthea.model.TimeUnit;
@@ -100,14 +99,14 @@
 	 */
 	public static Set<Label> getAccessedLabelSet(final Task t) {
 		final Set<Label> ls = new HashSet<Label>();
-		for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-			if (geb instanceof CallSequence) {
-				final CallSequence cs = (CallSequence) geb;
-				for (final CallSequenceItem csi : cs.getCalls()) {
-					if (csi instanceof TaskRunnableCall) {
-						final TaskRunnableCall trc = (TaskRunnableCall) csi;
+		for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+			if (geb instanceof Group) {
+				final Group cs = (Group) geb;
+				for (final ActivityGraphItem csi : cs.getItems()) {
+					if (csi instanceof RunnableCall) {
+						final RunnableCall trc = (RunnableCall) csi;
 						final Runnable r = trc.getRunnable();
-						for (final RunnableItem ri : r.getRunnableItems()) {
+						for (final ActivityGraphItem ri : r.getRunnableItems()) {
 							if (ri instanceof LabelAccess) {
 								final LabelAccess la = (LabelAccess) ri;
 								ls.add(la.getData());
@@ -159,11 +158,11 @@
 						tsl = tsl * (tl.size() - tl.indexOf(t));
 						break;
 					case TSxUtil:
-						final double util = getET(t, gpu, SharedConsts.timeType).divide(getStimInTime(t));
+						final double util = RuntimeUtil.getExecutionTimeForProcess(t, gpu, null, SharedConsts.timeType).divide(getStimInTime(t));
 						tsl = (long) (util * SharedConsts.timeSliceLengthPS);
 						break;
 					case TSxUtilxNbTasks:
-						final double util2 = getET(t, gpu, SharedConsts.timeType).divide(getStimInTime(t));
+						final double util2 = RuntimeUtil.getExecutionTimeForProcess(t, gpu, null, SharedConsts.timeType).divide(getStimInTime(t));
 						tsl = (long) (util2 * tl.size() * SharedConsts.timeSliceLengthPS);
 						break;
 					default:
@@ -224,8 +223,8 @@
 					final TaskAllocation tsa = tsal.get(0);
 					Time time = ta[0];
 					if (null != ta[1]) {
-						/*TODO handle min max*/
-						/*setting time to average*/
+						/* TODO handle min max */
+						/* setting time to average */
 						time = time.add(ta[1]);
 						time.setValue(time.getValue().divide(BigInteger.valueOf(2)));
 					}
@@ -312,35 +311,60 @@
 	 * @return Time execution time based on DeploymentUtil.getAssignedCoreForProcess
 	 */
 	public static Time getSimpleET(final Task t, final Amalthea amalthea) {
-		final Time time = CommonUtils.getET(t, DeploymentUtil.getAssignedCoreForProcess(t, amalthea).iterator().next(), SharedConsts.timeType);
+		final ProcessingUnit pu = DeploymentUtil.getAssignedCoreForProcess(t, amalthea).size() > 0
+				? DeploymentUtil.getAssignedCoreForProcess(t, amalthea).iterator().next()
+				: getFirstMappedPuFromTask(amalthea, t);
+		final Time time = RuntimeUtil.getExecutionTimeForProcess(t, pu, null, SharedConsts.timeType);
 		return time;
 	}
 
+	private static ProcessingUnit getFirstMappedPuFromTask(final Amalthea amalthea, final Task t) {
+		for (final TaskAllocation ta : amalthea.getMappingModel().getTaskAllocation()) {
+			if (ta.getTask().equals(t) && ta.getAffinity().size() > 0) {
+				return ta.getAffinity().get(0);
+			}
+		}
+		return null;
+	}
+
 	/**
+	 * Only returns execution time until the first InterProcessTrigger event
 	 * @param t Task
 	 * @param pu Processing Unit
 	 * @return Time execution time of t at pu
 	 */
-	public static Time getET(final Task t, final ProcessingUnit pu, final TimeType tt) {
+	public static Time getETPre(final Amalthea ama, final Task t, final ProcessingUnit pu, final int[] tpumap, final TimeType tt) {
 		Time ct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
-		for (final ExecutionNeed en : SoftwareUtil.getExecutionNeeds(t, null)) {
-			for (final Entry<String, IDiscreteValueDeviation> needs : en.getNeeds().entrySet()) {
-				ct = ct.add(RuntimeUtil.getExecutionTimeForExecutionNeedEntry(needs.getValue(), null, pu, SharedConsts.timeType));
+		if (taskTriggersGPUTask(ama, t, tpumap)) {
+			final List<ActivityGraphItem> csil = SoftwareUtil.collectActivityGraphItems(t.getActivityGraph());
+			for (final ActivityGraphItem csi : csil) {
+				if (csi instanceof InterProcessTrigger) {
+					break;
+				}
+				else if (csi instanceof RunnableCall) {
+					final RunnableCall trc = (RunnableCall) csi;
+					for (final ExecutionNeed en : SoftwareUtil.getExecutionNeeds(trc.getRunnable(), null)) {
+						for (final Entry<String, IDiscreteValueDeviation> needs : en.getNeeds().entrySet()) {
+							ct = ct.add(RuntimeUtil.getExecutionTimeForExecutionNeedEntry(needs.getValue(), null, pu, tt));
+						}
+					}
+					for (final Ticks ticks : SoftwareUtil.getTicks(trc.getRunnable(), null)) {
+						/* considers extended */
+						ct = ct.add(getExecutionTimeForTicks(ticks, pu, tt));
+					}
+				}
 			}
 		}
-		for (final Ticks ticks : SoftwareUtil.getTicks(t, null)) {
-			/* considers extended */
-			ct = ct.add(getExecutionTimeForTicks(ticks, pu, tt));
-		}
-		if (ct.getValue().toString().endsWith("999")) {
-			ct.setValue(ct.getValue().add(BigInteger.ONE));
+		else {
+			Logger.getLogger(CommonUtils.class).debug("Task " + t.getName() + " does not trigger a GPU task");
+			return RuntimeUtil.getExecutionTimeForProcess(t, pu, null, tt);
 		}
 		return ct;
 	}
 
 	/*--------------------------------------BEGIN COPY FROM RUNTIMEUTIL------------------------------------------------*/
 	/**
-	 * FIX for APP4MC0.9.4 only
+	 * FIX for APP4MC<0.9.6
 	 * @param ticks
 	 * @param pu
 	 * @param tt
@@ -360,7 +384,7 @@
 	}
 
 	/**
-	 * FIX for APP4MC0.9.4 only
+	 * FIX for APP4MC<0.9.6
 	 * @param deviation
 	 * @param pu
 	 * @param tt
@@ -384,7 +408,7 @@
 	}
 
 	/**
-	 * FIX for APP4MC0.9.4 only
+	 * FIX for APP4MC<0.9.6
 	 * @param ticks Double
 	 * @param frequency
 	 * @return Time execution time for a given double value derived from the frequency
@@ -399,6 +423,7 @@
 	}
 	/*--------------------------------------END COPY FROM RUNTIMEUTIL------------------------------------------------*/
 
+
 	/**
 	 * @param amalthea Amalthea model
 	 * @param onlyGPUStim optional boolean parameter whether only GPU Stimuli should be accounted
@@ -407,14 +432,17 @@
 	public static List<PeriodicStimulus> getSortedStim(final Amalthea amalthea, final boolean... onlyGPUStim) {
 		final List<PeriodicStimulus> stimListSorted = new ArrayList<PeriodicStimulus>();
 		List<Task> tl = null;
-		if (null != onlyGPUStim && onlyGPUStim[0]) {
-			tl = amalthea.getMappingModel().getTaskAllocation().stream().filter(ta -> ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU))
-					.map(ta -> ta.getTask()).collect(Collectors.toList());
+		if (null != onlyGPUStim && onlyGPUStim.length > 0) {
+			if (onlyGPUStim[0]) {
+				tl = amalthea.getMappingModel().getTaskAllocation().stream()
+						.filter(ta -> ta.getAffinity().get(0).getDefinition().getPuType().equals(PuType.GPU)).map(ta -> ta.getTask())
+						.collect(Collectors.toList());
+			}
 		}
 		for (final Stimulus s : amalthea.getStimuliModel().getStimuli()) {
 			if (s instanceof PeriodicStimulus) {
 				final PeriodicStimulus ps = (PeriodicStimulus) s;
-				if (null != onlyGPUStim && onlyGPUStim[0] && null != tl) {
+				if (null != onlyGPUStim && onlyGPUStim.length > 0 && null != tl) {
 					for (final Task t : tl) {
 						if (t.getStimuli().contains(ps) && !stimListSorted.contains(ps)) {
 							stimListSorted.add(ps);
@@ -461,9 +489,8 @@
 	}
 
 	/**
-	 * Logs mutliple stimuli / stimuli != (Periodic,InterProcessTrigger)
 	 * @param t Task
-	 * @return PeriodicStimulus of Task t
+	 * @return PeriodicStimulus of Task t or if t is triggered by interProcessStimulus, the PeriodicStimulus of the triggering task is returned
 	 */
 	public static PeriodicStimulus getStim(final Task t) {
 		final Logger log = Logger.getLogger(CommonUtils.class);
@@ -478,8 +505,6 @@
 			}
 			if (s instanceof InterProcessStimulus) {
 				final InterProcessStimulus ips = (InterProcessStimulus) s;
-				//				final List<Process> triggers = ips.getExplicitTriggers().stream().map(ipt -> ipt.getContainingProcess()).collect(Collectors.toList());
-				//				final Time rec = ((PeriodicStimulus) triggers.get(0).getStimuli().get(0)).getRecurrence();
 				final Task trigger = getFirstTrigger(ips);
 				return ((PeriodicStimulus) trigger.getStimuli().get(0));
 			}
@@ -496,10 +521,10 @@
 	private static Task getFirstTrigger(final InterProcessStimulus ips) {
 		final Amalthea model = (Amalthea) ips.eContainer().eContainer();
 		for (final Task t : model.getSwModel().getTasks()) {
-			for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-				if (geb instanceof CallSequence) {
-					final CallSequence cs = (CallSequence) geb;
-					for (final CallSequenceItem csi : cs.getCalls()) {
+			for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+				if (geb instanceof Group) {
+					final Group cs = (Group) geb;
+					for (final ActivityGraphItem csi : cs.getItems()) {
 						if (csi instanceof InterProcessTrigger) {
 							final InterProcessTrigger ipt = (InterProcessTrigger) csi;
 							if (ipt.getStimulus().equals(ips)) {
@@ -543,11 +568,11 @@
 					il.add(gpus.indexOf(pu));
 				}
 			}
-			/*il = only indexes of GPUs*/
+			/* il = only indexes of GPUs */
 			final List<Task> gpuTasks = new ArrayList<Task>();
 			for (int i = 0; i < mapping.length; i++) {
 				if (il.contains(mapping[i])) {
-					/*task i is mapped tp a GPU*/
+					/* task i is mapped tp a GPU */
 					gpuTasks.add(am.getSwModel().getTasks().get(i));
 				}
 			}
@@ -556,13 +581,7 @@
 		tl.sort(new Comparator<Task>() {
 			@Override
 			public int compare(final Task t1, final Task t2) {
-				final List<Stimulus> psl1 = t1.getStimuli().stream().filter(s -> s instanceof PeriodicStimulus).collect(Collectors.toList());
-				final List<Stimulus> psl2 = t2.getStimuli().stream().filter(s -> s instanceof PeriodicStimulus).collect(Collectors.toList());
-				if (psl1.size() != 1 || psl2.size() != 1) {
-					Logger.getLogger("CommonUtils").debug("Task " + t1.getName() + " has no periodic stimulus.");
-					return 0;
-				}
-				return ((PeriodicStimulus) psl1.get(0)).getRecurrence().compareTo(((PeriodicStimulus) psl2.get(0)).getRecurrence());
+				return (CommonUtils.getStimInTime(t1).compareTo(CommonUtils.getStimInTime(t2)));
 			}
 		});
 		return tl;
@@ -572,22 +591,34 @@
 	public static boolean isSchedulable(final List<Task> tl, final ProcessingUnit pu) {
 		Double sum = 0d;
 		for (final Task t : tl) {
-			final Time et = CommonUtils.getET(t, pu, SharedConsts.timeType);
+			final Time et = RuntimeUtil.getExecutionTimeForProcess(t, pu, null, SharedConsts.timeType);
 			final Time per = getStimInTime(t);
 			sum += et.divide(per);
 		}
 		return sum > 1 ? false : true;
 	}
 
-	/** Creates a Mapping Model from an integer array */
+	/** Creates a Mapping Model from an integer array*/
 	public static MappingModel createMMFromIA(final Amalthea amalthea, final int[] ia) {
 		final List<ProcessingUnit> pul = getPUs(amalthea);
 		final MappingModel mm = AmaltheaFactory.eINSTANCE.createMappingModel();
-		for (int i = 0; i < amalthea.getSwModel().getTasks().size(); i++) {
-			final TaskAllocation ta = AmaltheaFactory.eINSTANCE.createTaskAllocation();
-			ta.setTask(amalthea.getSwModel().getTasks().get(i));
-			ta.getAffinity().add(pul.get(ia[i]));
-			mm.getTaskAllocation().add(ta);
+		for (final ProcessingUnit pu : pul) {
+			final TaskScheduler ts = AmaltheaFactory.eINSTANCE.createTaskScheduler();
+			final SchedulerAllocation sa = AmaltheaFactory.eINSTANCE.createSchedulerAllocation();
+			sa.setExecutingPU(pu);
+			sa.getResponsibility().add(pu);
+			ts.setName("TS_" + pu.getName());
+			sa.setScheduler(ts);
+			for (int i = 0; i < amalthea.getSwModel().getTasks().size(); i++) {
+				if (pul.get(ia[i]).equals(pu)) {
+					final TaskAllocation ta = AmaltheaFactory.eINSTANCE.createTaskAllocation();
+					ta.setTask(amalthea.getSwModel().getTasks().get(i));
+					ta.getAffinity().add(pul.get(ia[i]));
+					ta.setScheduler(ts);
+					mm.getTaskAllocation().add(ta);
+				}
+			}
+			mm.getSchedulerAllocation().add(sa);
 		}
 		return mm;
 	}
@@ -683,13 +714,13 @@
 		Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 		final List<InterProcessTrigger> ipts = getTriggered(t);
 		final List<ProcessingUnit> pul = CommonUtils.getPUs(model);
-		/*task triggers other task*/
+		/* task triggers other task */
 		for (final InterProcessTrigger ipt : ipts) {
 			final List<Task> triggered = model.getSwModel().getTasks().stream().filter(task -> task.getStimuli().get(0).equals(ipt.getStimulus()))
 					.collect(Collectors.toList());
 			for (final Task task : triggered) {
 				final ProcessingUnit pu = pul.get(ia[model.getSwModel().getTasks().indexOf(task)]);
-				time = time.add(CommonUtils.getET(task, pu, TimeType.WCET));
+				time = time.add(RuntimeUtil.getExecutionTimeForProcess(task, pu, null, SharedConsts.timeType));
 			}
 		}
 		return time;
@@ -703,7 +734,7 @@
 	public static List<Task> getTriggeredTasks(final Amalthea ama, final Task t) {
 		final List<Task> tl = new ArrayList<>();
 		final List<InterProcessTrigger> ipts = getTriggered(t);
-		/*task triggers other task*/
+		/* task triggers other task */
 		for (final InterProcessTrigger ipt : ipts) {
 			tl.addAll(ama.getSwModel().getTasks().stream().filter(task -> task.getStimuli().get(0).equals(ipt.getStimulus())).collect(Collectors.toList()));
 		}
@@ -743,10 +774,10 @@
 	 */
 	public static List<InterProcessTrigger> getTriggered(final Task t) {
 		final List<InterProcessTrigger> iptl = new ArrayList<>();
-		for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-			if (geb instanceof CallSequence) {
-				final CallSequence cs = (CallSequence) geb;
-				for (final CallSequenceItem csi : cs.getCalls()) {
+		for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+			if (geb instanceof Group) {
+				final Group cs = (Group) geb;
+				for (final ActivityGraphItem csi : cs.getItems()) {
 					if (csi instanceof InterProcessTrigger) {
 						final InterProcessTrigger ipt = (InterProcessTrigger) csi;
 						iptl.add(ipt);
@@ -764,10 +795,10 @@
 	 */
 	public static List<Task> getTriggered(final Amalthea ama, final Task t) {
 		final List<Task> tl = new ArrayList<>();
-		for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-			if (geb instanceof CallSequence) {
-				final CallSequence cs = (CallSequence) geb;
-				for (final CallSequenceItem csi : cs.getCalls()) {
+		for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+			if (geb instanceof Group) {
+				final Group cs = (Group) geb;
+				for (final ActivityGraphItem csi : cs.getItems()) {
 					if (csi instanceof InterProcessTrigger) {
 						final InterProcessTrigger ipt = (InterProcessTrigger) csi;
 						for (final Task tmp : ama.getSwModel().getTasks()) {
@@ -793,10 +824,10 @@
 	 */
 	public static Task getTrigger(final Amalthea amalthea, final InterProcessStimulus ips) {
 		for (final Task t : amalthea.getSwModel().getTasks()) {
-			for (final GraphEntryBase geb : t.getCallGraph().getGraphEntries()) {
-				if (geb instanceof CallSequence) {
-					final CallSequence cs = (CallSequence) geb;
-					for (final CallSequenceItem csi : cs.getCalls()) {
+			for (final ActivityGraphItem geb : t.getActivityGraph().getItems()) {
+				if (geb instanceof Group) {
+					final Group cs = (Group) geb;
+					for (final ActivityGraphItem csi : cs.getItems()) {
 						if (csi instanceof InterProcessTrigger) {
 							final InterProcessTrigger iptc = (InterProcessTrigger) csi;
 							if (iptc.getStimulus().getName().equals(ips.getName())) {
@@ -819,7 +850,7 @@
 	public static long getTicksLongOfTriggeredTask(final Amalthea model, final int[] ia, final Task t) {
 		final List<InterProcessTrigger> ipts = getTriggered(t);
 		long ticks = 0;
-		/*task triggers other task*/
+		/* task triggers other task */
 		for (final InterProcessTrigger ipt : ipts) {
 			final List<Task> triggered = model.getSwModel().getTasks().stream().filter(task -> task.getStimuli().get(0).equals(ipt.getStimulus()))
 					.collect(Collectors.toList());
@@ -838,10 +869,10 @@
 	public static StringBuffer appendConfig(final String model, final int[] mapping) {
 		final StringBuffer sbl = new StringBuffer();
 		sbl.append(
-				"Configuration:\n Model,Mapping,SyncOffloading,UseModelTimeSlices,TimeSliceDerication,TimeSliceLengthInPSDefault,LevelI,TimeType,CEOnlyWrittenLabels,IgnoreInfeasibility\n");
+				"Configuration:\n Model,Mapping,SyncOffloading,UseModelTimeSlices,TimeSliceDerication,TimeSliceLengthInPSDefault,LevelI,TimeType,CEOnlyWrittenLabels,IgnoreInfeasibility,OffsetRTA\n");
 		sbl.append(model + "," + Arrays.toString(mapping).replace(",", ";") + "," + SharedConsts.synchronousOffloading + "," + SharedConsts.useModelTimeSlices
 				+ "," + SharedConsts.tsDeriv + "," + SharedConsts.timeSliceLengthPS + "," + SharedConsts.levelIBusyPeriod + "," + SharedConsts.timeType + ","
-				+ SharedConsts.onlyWrittenLabelsCE + "," + SharedConsts.ignoreInfeasibility + "\n");
+				+ SharedConsts.onlyWrittenLabelsCE + "," + SharedConsts.ignoreInfeasibility + "," + SharedConsts.offsetCPURTA + "\n");
 		return sbl;
 	}
 
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java
index b31da13..4767e1e 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/Contention.java
@@ -20,8 +20,9 @@
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
 import org.eclipse.app4mc.amalthea.model.Amalthea;
-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;
 import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
 import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
 import org.eclipse.app4mc.amalthea.model.Label;
@@ -31,9 +32,9 @@
 import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
 import org.eclipse.app4mc.amalthea.model.PuType;
 import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.RunnableCall;
 import org.eclipse.app4mc.amalthea.model.SetEvent;
 import org.eclipse.app4mc.amalthea.model.Task;
-import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;
 import org.eclipse.app4mc.amalthea.model.Time;
 import org.eclipse.app4mc.amalthea.model.TimeUnit;
 import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
@@ -49,16 +50,16 @@
 	private final int[] ia;
 	private final Amalthea model;
 	private final int[] flagArray;
-	private final HashMap<Task, List<Label>[]> gpuLabels = new HashMap<Task, List<Label>[]>();
+	private final HashMap<Task, List<List<Label>>> gpuLabels = new HashMap<Task, List<List<Label>>>();
 
 	public Contention(final int[] iap, final Amalthea modelp) {
 		this.ia = iap;
 		this.model = modelp;
-		if (iap == null) {
-			this.flagArray = null;
-		} else {
+		if(iap != null) {
 			this.flagArray = new int[iap.length];
+			return ;
 		}
+		this.flagArray = null;
 	}
 
 	/**
@@ -83,8 +84,9 @@
 
 	/**
 	 * 	Initiallize hashmap contain GPU tasks' labels hashmap <task, List<label>> (readList = hashmap.get(task)[0];)
-	 * and create flagarray that have the same length with our integerArray, then loop through all the PRE_POST tasks ( via looking for InterProcessStimulus) and check whether the triggered task (GPU task) are located on GPU or not, if it is, then I will give the value of that task in flagArray equal 1. It will look like this
-
+	 * and create flagarray that have the same length with our integerArray, then loop through all the PRE_POST tasks 
+         ( via looking for InterProcessStimulus) and check whether the triggered task (GPU task) are located on GPU or not, i
+         f it is, then I will give the value of that task in flagArray equal 1. It will look like this
 		ia = { 5, 1, 5, 0, 1, 0, 2, 1, 2, 1, 6, 3, 4, 6 } - our mapping array
 		fa = { 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,} - the flag array
 	 *
@@ -99,6 +101,9 @@
 		for (final Task t : gpuTask) {
 			/* shotting task => t.getName */
 			final List<SetEvent> shottingTaskEvent = SoftwareUtil.collectSetEvents(t, null);
+			if (shottingTaskEvent.size() < 1) {
+				continue;
+			}
 			final Process shottingTask = shottingTaskEvent.get(0).getProcess();
 			final int shotIndex = this.model.getSwModel().getTasks().indexOf(shottingTask);
 			final int gpuIndex = this.model.getSwModel().getTasks().indexOf(t);
@@ -109,8 +114,8 @@
 			/* create HashMap for GPU task that mapped to CPU start here*/
 			final List<Label> readLabelList = new ArrayList<Label>();
 			final List<Label> writeLabelList = new ArrayList<Label>();
-			final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(shottingTask);
-			final CallSequenceItem ipt = callList.stream().filter(a -> a instanceof InterProcessTrigger).iterator().next();
+			final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(shottingTask.getActivityGraph());
+			final ActivityGraphItem ipt = callList.stream().filter(a -> a instanceof InterProcessTrigger).iterator().next();
 			/*
 			 * get the position of InterProcessTrigger within task taking
 			 * readLabel and write labels from pre and post processing (
@@ -121,8 +126,8 @@
 			for (int i = 0; i < callList.size(); i++) {
 				Runnable thisRunnable = null;
 				/* Pre-processing Runnable */
-				if ((i < indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
-					thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
+				if ((i < indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+					thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
 					final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
 					for (final LabelAccess la : thisLAList) {
 						if (la.getAccess().equals(LabelAccessEnum.READ)) {
@@ -131,8 +136,8 @@
 					}
 				}
 				/* Post-processing Runnable */
-				else if ((i > indexforTrigger) && (callList.get(i) instanceof TaskRunnableCall)) {
-					thisRunnable = ((TaskRunnableCall) callList.get(i)).getRunnable();
+				else if ((i > indexforTrigger) && (callList.get(i) instanceof RunnableCall)) {
+					thisRunnable = ((RunnableCall) callList.get(i)).getRunnable();
 					final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(thisRunnable, null);
 					for (final LabelAccess la : thisLAList) {
 						if (la.getAccess().equals(LabelAccessEnum.WRITE)) {
@@ -142,10 +147,9 @@
 				}
 			}
 
-			@SuppressWarnings("unchecked")
-			final List<Label>[] aryofLabelList = new ArrayList[2];
-			aryofLabelList[0] = readLabelList;
-			aryofLabelList[1] = writeLabelList;
+			final List<List<Label>> aryofLabelList = new ArrayList<List<Label>>();
+			aryofLabelList.add(readLabelList);
+			aryofLabelList.add(writeLabelList);
 			this.gpuLabels.put(t, aryofLabelList);
 			// HashMap created with <Task, ArrayofLabelList>
 		}
@@ -161,7 +165,6 @@
 	public Time contentionForTask(final Task task) {
 		/* Initialize hashmap */
 		setUpFlagArrayAndHashMap(this.ia);
-
 		final Time time = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
 		/**
 		 * Constant and variable init, change those constant for different model number
@@ -226,7 +229,7 @@
 
 					final Set<Runnable> wL = SoftwareUtil.getWriterSetOfLabel(l, null);
 					for (final Runnable r : wL) {
-						final List<Process> lT = SoftwareUtil.getProcesses(r, null);
+						final List<Process> lT = SoftwareUtil.getCallingProcesses(r, null);
 						for (final Process lTT : lT) {
 							/* get related task through checking which runnable are accessing the same label
 							 * put the task that contain those runnable into b2 and the core of that task in c2
@@ -255,7 +258,7 @@
 
 					final Set<Runnable> rL = SoftwareUtil.getReadersSetOfLabel(l, null);
 					for (final Runnable r : rL) {
-						final List<Process> lT1 = SoftwareUtil.getProcesses(r, null);
+						final List<Process> lT1 = SoftwareUtil.getCallingProcesses(r, null);
 						for (final Process lTT1 : lT1) {
 							/* get related task through checking which runnable are accessing the same label
 							 * put the task that contain those runnable into b2 and the core of that task in c2
@@ -365,8 +368,8 @@
 					final int shotIndex = this.model.getSwModel().getTasks().indexOf(shottingTask);
 
 					if (this.flagArray[shotIndex] == 1) {
-						final List<Label> readList = this.gpuLabels.get(task)[0];
-						final List<Label> writeList = this.gpuLabels.get(task)[1];
+						final List<Label> readList = this.gpuLabels.get(task).get(0);
+						final List<Label> writeList = this.gpuLabels.get(task).get(1);
 						for (final Label l : readList) {
 
 							sumCycle += (long) Math.ceil(l.getSize().getNumberBytes() / 64.0);
@@ -491,7 +494,7 @@
 
 					final Set<Runnable> wL = SoftwareUtil.getWriterSetOfLabel(l, null);
 					for (final Runnable r : wL) {
-						final List<Process> lT = SoftwareUtil.getProcesses(r, null);
+						final List<Process> lT = SoftwareUtil.getCallingProcesses(r, null);
 						for (final Process lTT : lT) {
 
 							for (int taskIndex = 0; taskIndex < this.ia.length; taskIndex++) {
@@ -521,7 +524,7 @@
 					}
 					final Set<Runnable> rL = SoftwareUtil.getReadersSetOfLabel(l, null);
 					for (final Runnable r : rL) {
-						final List<Process> lT1 = SoftwareUtil.getProcesses(r, null);
+						final List<Process> lT1 = SoftwareUtil.getCallingProcesses(r, null);
 						for (final Process lTT1 : lT1) {
 							for (int taskIndex = 0; taskIndex < this.ia.length; taskIndex++) {
 								final ProcessingUnit pup = pul.get(this.ia[taskIndex]);
@@ -645,4 +648,4 @@
 
 		return contentionTime;
 	}
-}
\ No newline at end of file
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
index 055ecd8..e693c30 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/E2ELatency.java
@@ -1,686 +1,1172 @@
-/*******************************************************************************

- * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.

- *

- * This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License 2.0

- * which accompanies this distribution, and is available at

- * https://www.eclipse.org/legal/epl-2.0/

- *

- * SPDX-License-Identifier: EPL-2.0

- *

- * Contributors:

- *     FH Dortmund - initial API and implementation

- *******************************************************************************/

-package org.eclipse.app4mc.gsoc_rta;

-

-import java.io.File;

-import java.math.BigDecimal;

-import java.math.BigInteger;

-import java.util.ArrayList;

-import java.util.Collections;

-import java.util.Comparator;

-import java.util.List;

-import java.util.Set;

-

-import org.apache.log4j.Level;

-import org.apache.log4j.Logger;

-import org.eclipse.app4mc.amalthea.model.AmaltheaServices;

-import org.eclipse.app4mc.amalthea.model.Event;

-import org.eclipse.app4mc.amalthea.model.EventChain;

-import org.eclipse.app4mc.amalthea.model.EventChainContainer;

-import org.eclipse.app4mc.amalthea.model.EventChainItem;

-import org.eclipse.app4mc.amalthea.model.Label;

-import org.eclipse.app4mc.amalthea.model.ProcessEvent;

-import org.eclipse.app4mc.amalthea.model.ProcessingUnit;

-import org.eclipse.app4mc.amalthea.model.Task;

-import org.eclipse.app4mc.amalthea.model.Time;

-import org.eclipse.app4mc.amalthea.model.TimeUnit;

-import org.eclipse.app4mc.amalthea.model.io.AmaltheaLoader;

-import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;

-import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;

-import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;

-import org.eclipse.app4mc.gsoc_rta.SharedConsts.ComParadigm;

-import org.eclipse.emf.common.util.EList;

-

-/**

- * Date: August 21-2019

- * @author Junhyung Ki

- * @version 1.0

- * 				This class is to analyze End-to-End latency with the help of CPURta class.

- */

-public class E2ELatency {

-	public final File inputFile = new File("model-input/WATERS19_release/ChallengeModel_release.amxmi");

-	public CPURta cpurta = new CPURta();

-	public static final int[] defaultIAMapping = new int[] { 4, 1, 1, 3, 4, 0, 3, 3, 3, 0, 6, 2, 5, 6 };

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

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

-		Logger.getRootLogger().setLevel(Level.ERROR);

-		final E2ELatency ecl = new E2ELatency();

-		ecl.run();

-	}

-	

-	public void run() {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		this.setCPURta(this.cpurta);

-		if (this.cpurta.getModel() == null) {

-			log.debug("Model is empty. Please check the model path.");

-			return ;

-		}

-		final EList<EventChain> ecList = this.cpurta.getModel().getConstraintsModel().getEventChains();

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

-			log.debug(" ----- " + "Chain " + (i+1) + " ----- ");

-			log.debug("Best-case Task-Chain Reaction(Direct): " + this.getTCReactionBC(ecList.get(i), ComParadigm.DIRECT, this.cpurta));

-			log.debug("Worst-case Task-Chain Reaction(Direct): " + this.getTCReactionWC(ecList.get(i), ComParadigm.DIRECT, this.cpurta));

-			log.debug("Best-case Task-Chain Reaction(Implicit): " + this.getTCReactionBC(ecList.get(i), ComParadigm.IMPLICIT, this.cpurta));

-			log.debug("Worst-case Task-Chain Reaction(Implicit): " + this.getTCReactionWC(ecList.get(i), ComParadigm.IMPLICIT, this.cpurta));

-			log.debug("Best-case Task-Chain Reaction(LET): " + this.getLetReactionBC(ecList.get(i), this.cpurta));

-			log.debug("Worst-case Task-Chain Reaction(LET): " + this.getLetReactionWC(ecList.get(i), this.cpurta));

-			log.debug("Worst-case Task-Chain Age(Direct): " + this.getTaskChainAge(ecList.get(i), TimeType.WCET, ComParadigm.DIRECT, this.cpurta));

-			log.debug("Best-case Task-Chain Age(Direct): " + this.getTaskChainAge(ecList.get(i), TimeType.BCET, ComParadigm.DIRECT, this.cpurta));

-			log.debug("Worst-case Task-Chain Age(Implicit): " + this.getTaskChainAge(ecList.get(i), TimeType.WCET, ComParadigm.IMPLICIT, this.cpurta));

-			log.debug("Best-case Task-Chain Age(Implicit): " + this.getTaskChainAge(ecList.get(i), TimeType.BCET, ComParadigm.IMPLICIT, this.cpurta));

-			log.debug("Worst-case Early Reaction(Direct): " + this.getEarlyReaction(ecList.get(i), TimeType.WCET, ComParadigm.DIRECT, this.cpurta));

-			log.debug("Best-case Early Reaction(Direct): " + this.getEarlyReaction(ecList.get(i), TimeType.BCET, ComParadigm.DIRECT, this.cpurta));

-			log.debug("Worst-case Early Reaction(Implicit): " + this.getEarlyReaction(ecList.get(i), TimeType.WCET, ComParadigm.IMPLICIT, this.cpurta));

-			log.debug("Best-case Early Reaction(Implicit): " + this.getEarlyReaction(ecList.get(i), TimeType.BCET, ComParadigm.IMPLICIT, this.cpurta));

-			log.debug("\n");

-		}

-		log.debug("\n################################################################################################################\n");

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

-			log.debug(" ----- " + "Chain " + (i+1) + " ----- ");

-			for (int j = 0; j < this.cpurta.getModel().getSwModel().getLabels().size(); j++) {

-				final Label label = this.cpurta.getModel().getSwModel().getLabels().get(j);

-				log.debug("***** " + label.getName() + " *****");

-				log.debug("Worst-case Data Age(Direct): " + this.getDataAge(label, ecList.get(i), TimeType.WCET, ComParadigm.DIRECT, this.cpurta));

-				log.debug("Best-case Data Age(Direct): " + this.getDataAge(label, ecList.get(i), TimeType.BCET, ComParadigm.DIRECT, this.cpurta));

-				log.debug("Worst-case Data Age(Implicit): " + this.getDataAge(label, ecList.get(i), TimeType.WCET, ComParadigm.IMPLICIT, this.cpurta));

-				log.debug("Best-case Data Age(Implicit): " + this.getDataAge(label, ecList.get(i), TimeType.BCET, ComParadigm.IMPLICIT, this.cpurta) + "\n");

-			}

-			log.debug("\n");

-		}

-	}

-	

-	/**

-	 * Set CPURta class

-	 * @param cpurta		the instance of CPURta class

-	 */

-	public void setCPURta(final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

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

-		if (cpurta.getModel() == null) {

-			log.debug("Model is empty. Please check the model path.");

-			return ;

-		}

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

-		cpurta.setIA(defaultIAMapping);

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

-		cpurta.setContention(cpurta.getIA(), cpurta.getModel());

-	}

-	

-	/**

-	 * Check the readiness of the observed class instance

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				boolean value that indicates whether cpurta instance is ready

-	 */

-	private boolean isTheRTAClassReady(final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		if (cpurta.getModel() == null) {

-			log.debug("Model Setting needs to be done for cpurta!");

-			return false;

-		} else if (cpurta.getTRT() == null) {

-			log.debug("TRT Setting needs to be done for cpurta!");

-			return false;

-		} else if (cpurta.getIA() == null) {

-			log.debug("IA Setting needs to be done for cpurta!");

-			return false;

-		} else if (cpurta.getPUl().size() == 0) {

-			log.debug("PUl Setting needs to be done for cpurta!");

-			return false;

-		} else if (cpurta.getCT() == null) {

-			log.debug("CT Setting needs to be done for cpurta!");

-			return false;

-		}

-		return true;

-	}

-	

-	/**

-	 * Reaction: The time between one of the chain's first task instances to the earliest one of the chain's last task instances 

-	 * which are propagated from the initial one. (which we can also call the best-case task-chain age latency) 

-	 * the best-case E2E Chain Reaction(Direct or Implicit) = Sum of all entities' BCRT

-	 * @param ec			the observed event chain

-	 * @param paradigm		communication paradigm (DIRECT, IMPLICIT)

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				the best-case E2E Chain Reaction(Direct or Implicit)

-	 */

-	public Time getTCReactionBC(final EventChain ec, final ComParadigm paradigm, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		Time e2eRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

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

-				final Task task = taskChain.get(i);

-				final ProcessingUnit pu = getPU(task, cpurta);

-				final List<Task> taskList = getSortedTaskList(task, pu, cpurta);

-				Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				if (isMappedToCPU(task, cpurta)) {

-					if (paradigm.equals(ComParadigm.DIRECT)) {

-						bcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.BCET, pu);

-					} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-						bcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);

-					} else {

-						log.error("'COM_PARADIGM == null' does not work.");

-						return null;

-					}

-				} else {

-					bcrt = cpurta.getTRT().get(task);

-				}

-				/* The task is not schedulable */

-				final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));

-				if (AmaltheaServices.convertToPicoSeconds(bcrt).compareTo(biPeriod) > 0) {

-					return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				}

-				e2eRctImplicit = e2eRctImplicit.add(bcrt);

-			}

-			return e2eRctImplicit;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-

-	/**

-	 * The worst case task chain reaction latency for Direct or Implicit Communication

-	 * @param ec			the observed event chain

-	 * @param paradigm		communication paradigm (DIRECT, IMPLICIT)

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				the worst-case E2E Chain Reaction(Direct or Implicit)

-	 */

-	public Time getTCReactionWC(final EventChain ec, final ComParadigm paradigm, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		Time e2eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

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

-				final Task task = taskChain.get(i);

-				final Time period = CommonUtils.getStimInTime(task);

-				e2eRctWC = e2eRctWC.add(period.multiply(2));

-			}

-			final Task task = taskChain.get(taskChain.size() - 1);

-			Time wcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			if (isMappedToCPU(task, cpurta)) {

-				final ProcessingUnit pu = getPU(task, cpurta);

-				final List<Task> taskList = getSortedTaskList(task, pu, cpurta);

-				if (paradigm.equals(ComParadigm.DIRECT)) {

-					wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);

-				} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-					wcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.WCET, pu, cpurta);

-				} else {

-					log.error("'COM_PARADIGM == null' does not work.");

-					return null;

-				}

-			} else {

-				wcrt = cpurta.getTRT().get(task);

-			}

-			/* The task is not schedulable */

-			final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));

-			if (AmaltheaServices.convertToPicoSeconds(wcrt).compareTo(biPeriod) > 0) {

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

-			e2eRctWC = e2eRctWC.add(wcrt);

-			return e2eRctWC;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-	

-	/**

-	 * Reaction: The time between one of the chain's first task instances to the earliest one of the chain's last task instances 

-	 * which are propagated from the initial one. (which we can also call the best-case task-chain age latency)

-	 * the best-case E2E Chain Reaction(LET) = Sum of all entities' periods

-	 * @param ec			the observed event chain

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				the best-case E2E Chain Reaction(LET)

-	 */

-	public Time getLetReactionBC(final EventChain ec, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		Time e2eRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

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

-				final Task task = taskChain.get(i);

-				e2eRctLET = e2eRctLET.add(CommonUtils.getStimInTime(task));

-			}

-			return e2eRctLET;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-	

-	/**

-	 * The worst case task chain reaction latency for LET Communication

-	 * @param ec			the observed event chain

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				the worst-case E2E Chain Reaction(LET)

-	 */

-	public Time getLetReactionWC(final EventChain ec, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		Time e2eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

-			final Task task0 = taskChain.get(0);

-			final Time period0 = CommonUtils.getStimInTime(task0);

-			e2eRctWC = e2eRctWC.add(period0);

-			for (int i = 1; i < taskChain.size(); i++) {

-				final Task task = taskChain.get(i);

-				final Time period = CommonUtils.getStimInTime(task);

-				e2eRctWC = e2eRctWC.add(period.multiply(2));

-			}

-			return e2eRctWC;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-	

-	/**

-	 * A task chain age latency equals the chain's last (response) task age latency

-	 * worst-case: period - bcrt + wcrt

-	 * best-case: period - wcrt + bcrt

-	 * @param ec				the observed event chain

-	 * @param executionCase		WCET / BCET

-	 * @param paradigm			communication paradigm (DIRECT, IMPLICIT)

-	 * @param cpurta			the instance of CPURta class

-	 * @return

-	 * 				the worst-case E2E Task-Chain Age

-	 */

-	public Time getTaskChainAge(final EventChain ec, final TimeType executionCase, final ComParadigm paradigm, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		Time e2eTCAgeWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

-			final Task task = taskChain.get(taskChain.size()-1);

-			if (isMappedToCPU(task, cpurta)) {

-				final Time period = CommonUtils.getStimInTime(task);

-				final ProcessingUnit pu = getPU(task, cpurta);

-				final List<Task> taskList = getSortedTaskList(task, pu, cpurta);

-				Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				Time wcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				if (paradigm.equals(ComParadigm.DIRECT)) {

-					bcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.BCET, pu);

-					wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);

-				} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-					bcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);

-					wcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.WCET, pu, cpurta);

-				} else {

-					log.error("'COM_PARADIGM == null' does not work.");

-					return null;

-				}

-				/* The task is not schedulable */

-				final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));

-				if (AmaltheaServices.convertToPicoSeconds(bcrt).compareTo(biPeriod) > 0) {

-					return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				} else if (AmaltheaServices.convertToPicoSeconds(wcrt).compareTo(biPeriod) > 0) {

-					return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				}

-				if (executionCase.equals(TimeType.WCET)) {

-					e2eTCAgeWC = period.subtract(bcrt).add(wcrt);

-				} else if (executionCase.equals(TimeType.BCET)) {

-					e2eTCAgeWC = period.subtract(wcrt).add(bcrt);

-				} else {

-					log.error("Only WCET or BCET is allowed!");

-					return null;

-				}

-			} else {

-				// TODO: if the observed task is mapped to GPU, then how should we calculate wcrt, bcrt?

-				log.debug("GPU Task, how should we calculate wcrt, bcrt?");

-			}

-			return e2eTCAgeWC;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-

-	/**

-	 * The method is to be used for calculating 'reaction update'.

-	 * @param ec				the observed event chain

-	 * @param executionCase		WCET / BCET

-	 * @param paradigm			communication paradigm (DIRECT, IMPLICIT)

-	 * @param cpurta			the instance of CPURta class

-	 * @return

-	 * 				the reaction latency value of the observed event chain

-	 */

-	public Time getEarlyReaction(final EventChain ec, final TimeType executionCase, final ComParadigm paradigm, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		Time e2eEarlyRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

-			final Task task0 = taskChain.get(0);

-			Time rt0 = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			if (isMappedToCPU(task0, cpurta)) {

-				final ProcessingUnit pu = getPU(task0, cpurta);

-				final List<Task> taskList = getSortedTaskList(task0, pu, cpurta);

-				if (paradigm.equals(ComParadigm.DIRECT)) {

-					rt0 = cpurta.preciseTestCPURT(task0, taskList, executionCase, pu);

-				} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-					rt0 = cpurta.implicitPreciseTest(task0, taskList, executionCase, pu, cpurta);

-				} else {

-					log.error("'COM_PARADIGM == null' does not work.");

-					return null;

-				}

-			} else {

-				rt0 = cpurta.getTRT().get(task0);

-			}

-			/* The task is not schedulable */

-			final BigInteger biPeriod0 = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task0));

-			if (AmaltheaServices.convertToPicoSeconds(rt0).compareTo(biPeriod0) > 0) {

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

-			e2eEarlyRct = e2eEarlyRct.add(rt0);

-			Time epsilon = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

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

-				final Time nextPeriod = CommonUtils.getStimInTime(taskChain.get(i + 1));

-				/* SUM (Sigma Starts) */

-				final Time period = CommonUtils.getStimInTime(taskChain.get(i));

-				final Task currentTask = taskChain.get(i);

-				Time rtA = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				if (isMappedToCPU(currentTask, cpurta)) {

-					final ProcessingUnit puA = getPU(currentTask, cpurta);

-					final List<Task> taskListA = getSortedTaskList(currentTask, puA, cpurta);

-					/* NOTE: Sometimes rtA, rtB are BigInteger.valueOf(Long.MAX_VALUE) if it is executed with the implicit communication paradigm */

-					/* In that case, the task is not schedulable, so the method should return 0 ps, otherwise the result is not correct and

-					 * would likely be negative (subtract the max BigIntegerValue would be obviously negative in most cases) */

-					if (paradigm.equals(ComParadigm.DIRECT)) {

-						rtA = cpurta.preciseTestCPURT(currentTask, taskListA, executionCase, puA);

-					} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-						rtA = cpurta.implicitPreciseTest(currentTask, taskListA, executionCase, puA, cpurta);

-					}

-				} else {

-					rtA = cpurta.getTRT().get(currentTask);

-				}

-				/* The task is not schedulable */

-				final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(period);

-				if (AmaltheaServices.convertToPicoSeconds(rtA).compareTo(biPeriod) > 0) {

-					return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				}

-				final Time currentEpsilon = (((period.multiply(2)).subtract(rtA)).subtract(nextPeriod)).subtract(epsilon);

-				epsilon = currentEpsilon;

-				final Task nextTask = taskChain.get(i + 1);

-				Time rtB = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				if (isMappedToCPU(nextTask, cpurta)) {

-					final ProcessingUnit puB = getPU(nextTask, cpurta);

-					final List<Task> taskListB = getSortedTaskList(nextTask, puB, cpurta);

-					if (paradigm.equals(ComParadigm.DIRECT)) {

-						rtB = cpurta.preciseTestCPURT(nextTask, taskListB, executionCase, puB);

-					} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-						rtB = cpurta.implicitPreciseTest(nextTask, taskListB, executionCase, puB, cpurta);

-					}

-				} else {

-					rtB = cpurta.getTRT().get(nextTask);

-				}

-				/* The task is not schedulable */

-				final BigInteger biPeriodB = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(nextTask));

-				if (AmaltheaServices.convertToPicoSeconds(rtB).compareTo(biPeriodB) > 0) {

-					return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				}

-				if (nextPeriod.compareTo(currentEpsilon.add(rtB)) < 0) {

-					e2eEarlyRct = e2eEarlyRct.add(nextPeriod.multiply(2));

-				} else {

-					e2eEarlyRct = e2eEarlyRct.add(nextPeriod.add(currentEpsilon.add(rtB)));

-				}

-				if (e2eEarlyRct.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) < 0) {

-					return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				}

-			}

-			return e2eEarlyRct;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-	

-	/**

-	 * the longest time some data version persists in memory.

-	 * worst-case: min (worst-case age latencies of the tasks that contain the observed label)

-	 * best-case: min (best-case age latencies of the tasks that contain the observed label)

-	 * @param label				the observed label (data)

-	 * @param ec				the observed event-chain

-	 * @param executionCase		WCET / BCET

-	 * @param paradigm			communication paradigm (DIRECT, IMPLICIT)

-	 * @param cpurta			the instance of CPURta class

-	 * @return

-	 * 				the data age latency (wc or bc) of the given label

-	 * 				If any of tasks in the chain does not contain the observed label, the method shall return null.

-	 */

-	public Time getDataAge(final Label label, final EventChain ec, final TimeType executionCase, final ComParadigm paradigm, final CPURta cpurta) {

-		final Logger log = Logger.getLogger(E2ELatency.class);

-		if (isTheRTAClassReady(cpurta)) {

-			final List<Time> dataAgeList = new ArrayList<Time>();

-			final List<Task> taskChain = getECTaskList(ec);

-			if (taskChain.size() == 0) {

-				log.error("This task chain is empty.");

-				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-			}

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

-				if (isMappedToCPU(taskChain.get(i), cpurta)) {

-					final Task task = taskChain.get(i);

-					final Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);

-					if(labelSet.contains(label)) {

-						Time dataAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-						final ProcessingUnit pu = getPU(task, cpurta);

-						final List<Task> taskList = getSortedTaskList(task, pu, cpurta);

-						final Time period = CommonUtils.getStimInTime(task);

-						Time bcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-						Time wcrt = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-						if (paradigm.equals(ComParadigm.DIRECT)) {

-							bcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.BCET, pu);

-							wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);

-						} else if (paradigm.equals(ComParadigm.IMPLICIT)) {

-							bcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.BCET, pu, cpurta);

-							wcrt = cpurta.implicitPreciseTest(task, taskList, TimeType.WCET, pu, cpurta);

-						} else {

-							log.error("'COM_PARADIGM == null' does not work.");

-							return null;

-						}

-						/* The task is not schedulable */

-						final BigInteger biPeriod = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task));

-						if (AmaltheaServices.convertToPicoSeconds(bcrt).compareTo(biPeriod) > 0) {

-							return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-						} else if (AmaltheaServices.convertToPicoSeconds(wcrt).compareTo(biPeriod) > 0) {

-							return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-						}

-						if (executionCase.equals(TimeType.WCET)) {

-							dataAge = period.subtract(bcrt).add(wcrt);

-						} else if (executionCase.equals(TimeType.BCET)) {

-							dataAge = period.subtract(wcrt).add(bcrt);

-						} else {

-							log.error("Only WCET or BCET is allowed!");

-						}

-						dataAgeList.add(dataAge);

-					}

-				}

-			}

-			if (dataAgeList.size() != 0) {

-				Collections.sort(dataAgeList, new TimeComp());

-				return dataAgeList.get(0);

-			}

-			return null;

-		}

-		log.error("cpurta instance is not ready!");

-		return null;

-	}

-	

-	/**

-	 * Get an Event-Chain Entity List (Task-based)

-	 * @param ec			the observed event chain

-	 * @return			

-	 * 				the corresponding EC task list

-	 */

-	public List<Task> getECTaskList(final EventChain ec) {

-		final List<Task> chain = new ArrayList<Task>();

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

-			final EventChainItem eci = ec.getSegments().get(i);

-			if (eci instanceof EventChainContainer) {

-				final EventChainContainer ecc = (EventChainContainer) eci;

-				final Event stiEvent = ecc.getEventChain().getStimulus();

-				if (stiEvent instanceof ProcessEvent) {

-					final Task stiTask = (Task)((ProcessEvent) stiEvent).getEntity();

-					chain.add(stiTask);

-				}

-				if (i == ec.getSegments().size() - 1) {

-					final Event resEvent = ecc.getEventChain().getResponse();

-					if (resEvent instanceof ProcessEvent) {

-						final Task resTask = (Task)((ProcessEvent) resEvent).getEntity();

-						chain.add(resTask);

-					}

-					break;

-				}

-			}

-		}

-		return chain;

-	}

-	

-	/**

-	 * get the processing unit that the observed task is mapped to

-	 * @param task			the observed task

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				pu

-	 */

-	private ProcessingUnit getPU(final Task task, final CPURta cpurta) {

-		final int tindex = cpurta.getModel().getSwModel().getTasks().indexOf(task);

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

-		final ProcessingUnit pu = cpurta.getPUl().get(puindex);

-		return pu;

-	}

-	

-	/**

-	 * get the sorted task listed based on the given integer array mapping

-	 * @param task			the observed task

-	 * @param pu			ProcessingUnit that would compute the given method

-	 * @param cpurta		the instance of CPURta class

-	 * @return

-	 * 				sortedTaskList

-	 */

-	private List<Task> getSortedTaskList(final Task task, final ProcessingUnit pu, final CPURta cpurta) {

-		final int puIndex = cpurta.getPUl().indexOf(pu);

-		/* 2. get all tasks mapped to this CPU */

-		final List<Task> puTaskList = new ArrayList<Task>();

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

-			if (cpurta.getIA()[i] == puIndex) {

-				puTaskList.add(cpurta.getModel().getSwModel().getTasks().get(i));

-			}

-		}

-		final List<Task> sortedTaskList = taskSorting(puTaskList);

-		return sortedTaskList;

-	}

-	

-	/**

-	 * Sort out the given list of tasks (in order of shorter period first - Rate Monotonic Scheduling)

-	 * @param taskList		list of tasks that is mapped to the same core	

-	 * @return

-	 * 				the sorted list of tasks

-	 */

-	private List<Task> taskSorting(final List<Task> taskList) {

-		/* Getting stimuliList out of the given taskList (because it is RMS) */

-		final List<Time> stimuliList = new ArrayList<>();

-		for (final Task t : taskList) {

-			stimuliList.add(CommonUtils.getStimInTime(t));

-		}

-		/* Sorting (Shortest Period(Time) first) */

-		Collections.sort(stimuliList, new TimeComp());

-		/* Sort tasks to the newTaskList in order of Period length (shortest first

-		 * longest last)-(according to the stimuliList) */

-		final List<Task> newTaskList = new ArrayList<>();

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

-			for (final Task t : taskList) {

-				if ((!newTaskList.contains(t)) && (stimuliList.get(i).compareTo(CommonUtils.getStimInTime(t)) == 0)) {

-					newTaskList.add(t);

-				}

-			}

-		}

-		return newTaskList;

-	}

-	

-	/**

-	 * To check whether or not the observed task is mapped to CPU (according to the integer array)

-	 * @param task				the observed task

-	 * @param cpurta			the instance of CPURta class that contains model & mapping IA info

-	 * @return

-	 * 				boolean value that says whether or not it is mapped to CPU

-	 */

-	private static boolean isMappedToCPU (final Task task, final CPURta cpurta) {

-		/* The observed task is a GPU task */

-		if (cpurta.getGpuTaskList().contains(task)) {

-			final int index = cpurta.getModel().getSwModel().getTasks().indexOf(task);

-			final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;

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

-			/* when the observed GPU task is mapped to GPU */

-			if (ia[index] > cpuThreshold) {

-				return false;

-			}

-		}

-		/* when the observed task(CPU or GPU) is mapped to CPU */

-		return true;

-	}

-}

-

-/**

- * @Date: August 21-2019

- * @version 1.0

- *			This inner class is used for sorting a Time type list.

- *			If the Time of a is smaller than that of b, it returns -1.

- *			If the Time of a is bigger than that of b, it returns 1.

- */

-class TimeComp implements Comparator<Time> {

-	@Override

-	public int compare(final Time a, final Time b) {

-		if (a.compareTo(b) < 0) {

-			return -1;

-		}

-		return 1;

-	}

-}

-

-/**

- * @Date: August 21-2019

- * @version 1.0

- *			This inner class is used for the method "letCom" to help compare between different values of propagation, age, reaction

- *			in basicPaths (which is bigger)

- *			If the BigDecimal of a is smaller than that of b, it returns -1.

- *			If the BigDecimal of a is bigger than that of b, it returns 1.

- */

-class BigDecimalComp implements Comparator<BigDecimal> {

-	@Override

-	public int compare(final BigDecimal a, final BigDecimal b) {

-		if (a.compareTo(b) < 0) {

-			return -1;

-		}

-		return 1;

-	}

+/*******************************************************************************
+ * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     FH Dortmund - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.app4mc.gsoc_rta;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts.SINGLE_CASE;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
+import org.eclipse.app4mc.amalthea.model.Amalthea;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
+import org.eclipse.app4mc.amalthea.model.Event;
+import org.eclipse.app4mc.amalthea.model.EventChain;
+import org.eclipse.app4mc.amalthea.model.EventChainContainer;
+import org.eclipse.app4mc.amalthea.model.EventChainItem;
+import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
+import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
+import org.eclipse.app4mc.amalthea.model.Label;
+import org.eclipse.app4mc.amalthea.model.LabelAccess;
+import org.eclipse.app4mc.amalthea.model.ProcessEvent;
+import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.TimeUnit;
+import org.eclipse.app4mc.amalthea.model.io.AmaltheaLoader;
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
+import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
+import org.eclipse.emf.common.util.EList;
+
+//TODO javadoc!
+public class E2ELatency {
+	final Logger log = Logger.getLogger(E2ELatency.class);
+	public CPURta cpurta = null;
+	public static StringBuffer sb = new StringBuffer();
+  
+	public static void main(final String[] args) {
+		//TODO replace this eecutable function with unit test
+		org.apache.log4j.BasicConfigurator.configure();
+		Logger.getRootLogger().setLevel(Level.ERROR);
+		final E2ELatency ecl = new E2ELatency();
+		//ecl.runTest();
+		//ecl.runSingle();
+		ecl.runMulti();
+	}
+	
+  	//TODO implement a separate unit test
+	public void runTest() {
+		final boolean isSingle = false;
+		this.setCPURta(isSingle);
+		if (this.cpurta.getModel() == null) {
+			log.debug("Model is empty. Please check the model path.");
+			return ;
+		}
+		System.out.println("---TEST---");
+		final EList<Task> allTasks = this.cpurta.getModel().getSwModel().getTasks();
+		final RTARuntimeUtil rtaut = new RTARuntimeUtil(); 
+		for (int i = 0; i < allTasks.size(); i++) {
+			final Task task = allTasks.get(i);
+			final ProcessingUnit pu = this.cpurta.getPU(allTasks.get(i), this.cpurta);
+			System.out.println(task.getName() + "(PU): " + pu.getName());
+			final Time adjustedP = CommonUtils.getStimInTime(task);
+			final BigInteger picoP = AmaltheaServices.convertToPicoSeconds(adjustedP);
+			final Time period = FactoryUtil.createTime(picoP, TimeUnit.PS);
+			final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+			final Time bcet = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, this.cpurta);
+			final Time wcet = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.WCET, this.cpurta);
+			final Time bcrt = this.cpurta.bestCaseCPURT(task, taskList, pu);
+			final Time wcrt = this.cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+			if (isSingle) {
+				System.out.println(task.getName() + "(BCET): " + bcet.adjustUnit());
+				System.out.println(task.getName() + "(WCET): " + wcet.adjustUnit());
+				System.out.println(task.getName() + "(Period): " + period.adjustUnit());
+				System.out.println(task.getName() + "(BCRT): " + bcrt.adjustUnit());
+				System.out.println(task.getName() + "(WCRT): " + wcrt.adjustUnit());
+				System.out.println();
+			} else {
+				System.out.println(task.getName() + "(BCET): " + bcet);
+				System.out.println(task.getName() + "(WCET): " + wcet);
+				System.out.println(task.getName() + "(Period): " + period);
+				System.out.println(task.getName() + "(BCRT): " + bcrt);
+				System.out.println(task.getName() + "(WCRT): " + wcrt);
+				System.out.println();
+			}
+		}
+	}
+	
+	public void runSingle() {
+		this.setCPURta(true);
+		if (this.cpurta.getModel() == null) {
+			log.debug("Model is empty. Please check the model path.");
+			return ;
+		}
+		final EList<EventChain> ecList = this.cpurta.getModel().getConstraintsModel().getEventChains();
+		final List<Task> taskChain = getECTaskList(ecList.get(0));
+		final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+				.distinct().collect(Collectors.toList());
+		if (puList.size() > 1) {
+			log.error("SingleCore Reaction can not be calculated, "
+					+ "The tasks are mapped to more than one processing unit.");
+			return ;
+		}
+		System.out.println("--- TEST ---");
+		for (int i = 0; i < ecList.size(); i++) {
+			this.testSingleCoreReaction(ecList.get(i), cpurta);
+			System.out.println();
+		}
+	}
+	
+	public void runMulti() {
+		this.setCPURta(false);
+		if (this.cpurta.getModel() == null) {
+			log.debug("Model is empty. Please check the model path.");
+			return ;
+		}
+		final EList<EventChain> ecList = this.cpurta.getModel().getConstraintsModel().getEventChains();
+		for (int i = 0; i < ecList.size(); i++) {
+			final EventChain chain = ecList.get(i);
+			System.out.println();
+			System.out.println(" ----- " + chain.getName() + " ----- ");
+			System.out.println();
+			System.out.println("Best-case Task-Chain Reaction(Implicit): " + this.getBCReactionImplicit(chain, cpurta));
+			System.out.println("Best-case Task-Chain Reaction(LET): " + this.getBCReactionLET(chain, cpurta));
+			System.out.println();
+			System.out.println("Worst-case Task-Chain Reaction(Implicit): " + this.getWCReactionImplicit(chain, cpurta));
+			System.out.println("Worst-case Task-Chain Reaction(LET): " + this.getWCReactionLET(chain, cpurta));
+			System.out.println();
+			System.out.println("Best-case Initial Task-Chain Reaction(Implicit): " + this.getBCInitialRctImplicit(chain, cpurta));
+			System.out.println("Best-case Initial Task-Chain Reaction(LET): " + this.getBCInitialRctLET(chain, cpurta));
+			System.out.println();
+			System.out.println("Worst-case Initial Task-Chain Reaction(Implicit): " + this.getWCInitialRctImplicit(chain, cpurta));
+			System.out.println("Worst-case Initial Task-Chain Reaction(LET): " + this.getWCInitialRctLET(chain, cpurta));
+			System.out.println();
+			System.out.println("Best-case Task-Chain Age(Implicit): " + this.getBCAgeImplicit(chain, cpurta));
+			System.out.println("Best-case Task-Chain Age(LET): " + this.getBCAgeLET(chain, cpurta));
+			System.out.println();
+			System.out.println("Worst-case Task-Chain Age(Implicit): " + this.getWCAgeImplicit(chain, cpurta));
+			System.out.println("WC-BC Reaction Subtraction(Implicit): " + this.getWCBCSubAgeImplicit(chain, cpurta));
+			System.out.println("Worst-case Task-Chain Age(LET): " + this.getWCAgeLET(chain, cpurta));
+			System.out.println("WC-BC Reaction Subtraction(LET): " + this.getWCBCSubAgeLET(chain, cpurta));
+			System.out.println();
+			System.out.println("**************************************************************");
+			System.out.println();
+		}
+	}
+	
+	/**
+	 * Set CPURta class
+	 * @param isSingle		true - to analyze a single-core system
+	 * 						false - to analyze a multi-core system
+	 */
+	public void setCPURta(final boolean isSingle) {
+		if (isSingle) {
+			final Amalthea model = AmaltheaLoader.loadFromFile(new File(SharedConsts.ECRTS_SINGLE));
+			this.cpurta = new CPURta(model, (new CPURta(true)).getDefaultTRT(model), singleIAMapping, CommonUtils.getPUs(model));
+		} else {
+			final Amalthea model = AmaltheaLoader.loadFromFile(new File(SharedConsts.ECRTS_TCS));
+			this.cpurta = new CPURta(model, (new CPURta(true)).getDefaultTRT(model), defaultIAMapping, CommonUtils.getPUs(model));
+		}
+		if (this.cpurta.getModel() == null) {
+			log.debug("Model is empty. Please check the model path.");
+			return ;
+		}
+		this.cpurta.setContention(this.cpurta.getIA(), this.cpurta.getModel());
+	}
+
+	/**
+	 * Check the readiness of the observed class instance
+	 * @param cpurta		the instance of CPURtaIA class
+	 * @return
+	 * 				boolean value that indicates whether cpurta instance is ready
+	 */
+	protected boolean isTheRTAClassReady(final CPURta cpurta) {
+		if (cpurta.getModel() == null) {
+			log.debug("Model Setting needs to be done for cpurta!");
+			return false;
+		} else if (cpurta.getTRT() == null) {
+			log.debug("TRT Setting needs to be done for cpurta!");
+			return false;
+		} else if (cpurta.getIA() == null) {
+			log.debug("IA Setting needs to be done for cpurta!");
+			return false;
+		} else if (cpurta.getPUl().size() == 0) {
+			log.debug("PUl Setting needs to be done for cpurta!");
+			return false;
+		} else if (cpurta.getCT() == null) {
+			log.debug("CT Setting needs to be done for cpurta!");
+			return false;
+		}
+		return true;
+	}
+
+	/**************************************************************************************/
+	
+	public void testSingleCoreReaction(final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			System.out.println("< " + ec.getName() + " >");
+			final List<Task> taskChain = getECTaskList(ec);
+			if (taskChain.size() == 0) {
+				log.error("This task chain is empty.");
+				return ;
+			}
+			final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+					.distinct().collect(Collectors.toList());
+			if (puList.size() > 1) {
+				log.error("SingleCore Reaction can not be calculated, "
+						+ "The tasks are mapped to more than one processing unit.");
+				return ;
+			}
+			final ProcessingUnit pu = puList.get(0);
+			final Task task_0 = taskChain.get(0);
+			final List<Task> taskList = cpurta.getSortedTaskList(task_0, pu, cpurta);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time hyper = this.getHyperPeriod(taskList);
+			final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
+			final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+			final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
+			for (int i = 0; i < chainsToCheck; i++) {
+				System.out.println("* " + i + "-th instance: ");
+				Time initRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time wcRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				initRct = this.getSingleCoreInitialRct_(i, ec, cpurta);
+				if (initRct.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+					System.out.println("ERROR: This is not a vaild chain!");
+				} else {
+					wcRct = this.getSingleCoreWCRct_(i, ec, cpurta);
+					if (initRct.compareTo(wcRct) == 0) {
+						System.out.println("---Initial Reaction(only): " + initRct.adjustUnit());
+					} else {
+						System.out.println("---Initial Reaction: " + initRct.adjustUnit());
+						System.out.println("---Worst-case Reaction: " + wcRct.adjustUnit());
+					}
+				}
+			}
+		}
+	}
+	
+	public Time getSingleCoreInitialRct(final EventChain ec, final SINGLE_CASE latencyCase, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			if (taskChain.size() == 0) {
+				log.error("This task chain is empty.");
+				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			}
+			final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+					.distinct().collect(Collectors.toList());
+			if (puList.size() > 1) {
+				log.error("SingleCore Reaction can not be calculated, "
+						+ "The tasks are mapped to more than one processing unit.");
+				return null;
+			}
+			final ProcessingUnit pu = puList.get(0);
+			final Task task_0 = taskChain.get(0);
+			final List<Task> taskList = cpurta.getSortedTaskList(task_0, pu, cpurta);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time hyper = this.getHyperPeriod(taskList);
+			final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
+			final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+			final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
+			/* Checking the first element's all instances in the hyper-period to see whether each can make a chain 
+			 * and to calculate latency if they can */
+			final ArrayList<Time> latencyList = new ArrayList<Time>();
+			for (int i = 0; i < chainsToCheck; i++) {
+				Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				lat = this.getSingleCoreInitialRct_(i, ec, cpurta);
+				/* Beginning-case */
+				if ((i == 0) && latencyCase.equals(SINGLE_CASE.CRITICAL)) {
+					return lat;
+				}
+				if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+					latencyList.add(lat);
+				}
+			}
+			Collections.sort(latencyList, new TimeComp());
+			/* Best-case */
+			if (latencyCase.equals(SINGLE_CASE.BCLAT)) {
+				return latencyList.get(0);
+			}
+			/* Worst-case */
+			return latencyList.get(latencyList.size()-1);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	protected Time getSingleCoreInitialRct_(final int i, final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			final Task task_0 = taskChain.get(0);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			lat = this.getCRtoRT(i, task_0, cpurta);
+			for (int j = 1; j < taskChain.size(); j++) {
+				final Task task = taskChain.get(j);
+				final BigInteger latBI = AmaltheaServices.convertToPicoSeconds(lat);
+				final BigDecimal latBD = BigDecimal.valueOf(latBI.doubleValue());
+				final Time period = CommonUtils.getStimInTime(task);
+				final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+				final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
+				final Task preTask = taskChain.get(j-1);
+				final Time pre_period = CommonUtils.getStimInTime(preTask);
+				final BigInteger pre_periodBI = AmaltheaServices.convertToPicoSeconds(pre_period);
+				final BigDecimal pre_periodBD = BigDecimal.valueOf(pre_periodBI.doubleValue());
+				// TODO: check whether the next current task instance or the subsequent task instance comes first
+				// * compare the time difference between them - should be easy
+				// final Time compare = this.getCTR(cei, preTask, cpurta);
+				// * you should consider initial pending time! (offset + ip of pretask VS offset + ip of task)
+				final List<Task> preHPList = cpurta.getHigherPriorityTasks(preTask, cpurta);
+				long offset = 0;
+				/* To check whether the observed task is a higher priority than the previous chain element */
+				if (preHPList.contains(task)) {
+					final BigDecimal offsetBD = latBD.divide(periodBD, 0, BigDecimal.ROUND_CEILING);
+					offset = offsetBD.longValue();
+				} else {
+					final BigDecimal flo = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_FLOOR);
+					offset = (flo.multiply(pre_periodBD)).divide(periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+				}
+				final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+				final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, cpurta);
+				Time taskCRRT = this.getCRtoRT(offset, task, cpurta);
+				// TODO: the most important part (exceptions) write this part alone in the report. with the example situations written in your notebook.
+				/* The current task is a higher priority than the previous one */
+				if (preHPList.contains(task)) {
+					final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, cpurta);
+					if (preTaskCRRT.compareTo(taskCRRT) < 0) {
+						return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					}
+				}
+				/* The current task is a lower priority than the previous one */
+				else {
+					Time taskCRIP = this.getCRtoIP(offset, task, cpurta);
+					if (preTaskCRIP.compareTo(taskCRIP) < 0) {
+						offset = offset-1;
+						taskCRIP = this.getCRtoIP(offset, task, cpurta);
+						/* it can not make a task chain */
+						if (lat.compareTo(taskCRIP) > 0 || preTaskCRIP.compareTo(taskCRIP) < 0) {
+							return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						}
+						taskCRRT = this.getCRtoRT(offset, task, cpurta);
+					}
+				}
+				lat = taskCRRT;
+			}
+			/* delete the offset time */
+			if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+				lat = lat.subtract(period_0.multiply(i));
+			}
+			return lat;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getSingleCoreWCRct(final EventChain ec, final SINGLE_CASE latencyCase, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			if (taskChain.size() == 0) {
+				log.error("This task chain is empty.");
+				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			}
+			final List<ProcessingUnit> puList = taskChain.stream().map(s -> cpurta.getPU(s, cpurta))
+					.distinct().collect(Collectors.toList());
+			if (puList.size() > 1) {
+				log.error("SingleCore Reaction can not be calculated, "
+						+ "The tasks are mapped to more than one processing unit.");
+				return null;
+			}
+			final ProcessingUnit pu = puList.get(0);
+			final Task task_0 = taskChain.get(0);
+			final List<Task> taskList = cpurta.getSortedTaskList(task_0, pu, cpurta);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time hyper = this.getHyperPeriod(taskList);
+			final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
+			final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+			final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
+			/* Checking the first element's all instances in the hyper-period to see whether each can make a chain 
+			 * and to calculate latency if they can */
+			final ArrayList<Time> latencyList = new ArrayList<Time>();
+			for (int i = 0; i < chainsToCheck; i++) {
+				Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				lat = this.getSingleCoreWCRct_(i, ec, cpurta);
+				/* Beginning-case */
+				if ((i == 0) && latencyCase.equals(SINGLE_CASE.CRITICAL)) {
+					return lat;
+				}
+				if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+					latencyList.add(lat);
+				}
+			}
+			Collections.sort(latencyList, new TimeComp());
+			/* Best-case */
+			if (latencyCase.equals(SINGLE_CASE.BCLAT)) {
+				return latencyList.get(0);
+			}
+			/* Worst-case */
+			return latencyList.get(latencyList.size()-1);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	protected Time getSingleCoreWCRct_(final int i, final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			final Task task_0 = taskChain.get(0);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			Time temp = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			Time pre_previousVal = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			lat = this.getCRtoRT(i, task_0, cpurta);
+			for (int j = 1; j < taskChain.size(); j++) {
+				final Task task = taskChain.get(j);
+				final BigInteger latBI = AmaltheaServices.convertToPicoSeconds(lat);
+				final BigDecimal latBD = BigDecimal.valueOf(latBI.doubleValue());
+				final Time period = CommonUtils.getStimInTime(task);
+				final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+				final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
+				final Task preTask = taskChain.get(j-1);
+				final Time pre_period = CommonUtils.getStimInTime(preTask);
+				final BigInteger pre_periodBI = AmaltheaServices.convertToPicoSeconds(pre_period);
+				final BigDecimal pre_periodBD = BigDecimal.valueOf(pre_periodBI.doubleValue());
+				// TODO: check whether the next current task instance or the subsequent task instance comes first
+				// * compare the time difference between them - should be easy
+				// final Time compare = this.getCTR(cei, preTask, cpurta);
+				// * you should consider initial pending time! (offset + ip of pretask VS offset + ip of task)
+				final List<Task> preHPList = cpurta.getHigherPriorityTasks(preTask, cpurta);
+				final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
+				// TODO: the most important part (exceptions) write this part alone in the report. with the example situations written in your notebook.
+				/* The current task is a higher priority than the previous one */
+				Time taskCRRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				if (preHPList.contains(task)) {
+					final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, cpurta);
+					final BigInteger preTaskCrrtBI = AmaltheaServices.convertToPicoSeconds(preTaskCRRT);
+					final BigDecimal preTaskCrrtBD = BigDecimal.valueOf(preTaskCrrtBI.longValue());
+					final long offwhp = preTaskCrrtBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+					final Time crrt_cr = this.getCRtoRT(offwhp, task, cpurta);
+					final Time crrt_cr_ = this.getCRtoRT(offwhp-1, task, cpurta);
+					/* When there is an instance(s) of \tau_j between f(j-1)_x and the crrt time of the next instance of \tau_{j-1} */
+					if ((preTaskCrrtBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) && 
+							(lat.compareTo(crrt_cr) < 0) &&
+							(preTaskCRRT.compareTo(crrt_cr) > 0)) {
+						taskCRRT = crrt_cr;
+					}
+					/* In the worst-case, this part is only needed when the current task's priority is higher than the previous one's.
+					 * Because the current task's crrt is calculated based on the crrt time of the next instance of the previous task. 
+					 * Due to the fact that there can be more than one instance of the higher priority task between the lower priority task's instances. */
+					else if ((preTaskCrrtBI.mod(periodBI).compareTo(BigInteger.ZERO) == 0) &&
+							(lat.compareTo(crrt_cr_) < 0) &&
+							(preTaskCRRT.compareTo(crrt_cr_) > 0)) {
+						taskCRRT = crrt_cr_;
+					}
+				}
+				/* The current task is a lower priority than the previous one */
+				else {
+					final Time previousValIP = this.getCRtoIP(preTask_offset-1, preTask, cpurta);
+					final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, cpurta);
+					final BigInteger preTaskCripBI = AmaltheaServices.convertToPicoSeconds(preTaskCRIP);
+					final BigDecimal preTaskCripBD = BigDecimal.valueOf(preTaskCripBI.longValue());
+					final long offlhp = preTaskCripBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+					final Time crip = this.getCRtoIP(offlhp, task, cpurta);
+					/* When there is an instance(s) of \tau_j between f(j-1)_x and the crip time of the next instance of \tau_{j-1} */
+					if ((preTaskCripBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) && 
+							(previousValIP.compareTo(crip) < 0) &&
+							(preTaskCRIP.compareTo(crip) > 0)) {
+						taskCRRT = this.getCRtoRT(offlhp, task, cpurta);
+					}
+					/* In the worst-case, this part is only needed when the current task's priority is lower than the previous one's
+					 * Because the current task's crrt is calculated based on the crip time of the next instance of \tau_{j-1}.
+					 * Due to the fact that there can be no instance of the lower priority task between the higher priority task's instances. */
+					else {
+						/* When \tau_j is the second element of the chain and there is no instance of \tau_j between f(j-1)_x and the crip time of the next instance of \tau_{j-1} */
+						if (pre_previousVal.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+							return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						}
+						taskCRRT = this.getCRWC(task, preTask, 1, lat, pre_previousVal, cpurta);
+						/* To consider a situation where there is another chain path that goes through the earlier instance of \tau_{j-1} */
+						if (taskCRRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
+							return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+						}
+					}
+				}
+				temp = lat;
+				lat = taskCRRT;
+				pre_previousVal = temp;
+			}
+			/* delete the offset time */
+			if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
+				lat = lat.subtract(period_0.multiply(i));
+			}
+			return lat;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	private Time getCRWC(final Task task, final Task preTask, final long k, 
+			final Time pre, final Time prepre, final CPURta cpurta) {
+		final BigInteger preBI = AmaltheaServices.convertToPicoSeconds(pre);
+		final BigDecimal preBD = BigDecimal.valueOf(preBI.longValue());
+		final Time period = CommonUtils.getStimInTime(task);
+		final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+		final BigDecimal periodBD = BigDecimal.valueOf(periodBI.longValue());
+		final Time prePeriod = CommonUtils.getStimInTime(preTask);
+		final BigInteger prePeriodBI = AmaltheaServices.convertToPicoSeconds(prePeriod);
+		final BigDecimal prePeriodBD = BigDecimal.valueOf(prePeriodBI.longValue());
+		final long preOffcr = preBD.divide(prePeriodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+		final long offcr = preBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
+		final long offcr_ = offcr - 1;
+		final Time preCripCr = this.getCRtoIP(preOffcr - k, preTask, cpurta);
+		final Time crrtCr = this.getCRtoRT(offcr, task, cpurta);
+		final Time crrtCr_ = this.getCRtoRT(offcr_, task, cpurta);
+		final Time cripCr = this.getCRtoIP(offcr, task, cpurta);
+		final Time cripCr_ = this.getCRtoIP(offcr_, task, cpurta);
+		if (preCripCr.compareTo(prepre) < 0) {
+			return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		} else if ((preBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) && 
+				(cripCr.compareTo(pre) < 0) &&
+				(cripCr.compareTo(preCripCr) > 0)){
+			return crrtCr;
+		} else if ((preBI.mod(periodBI).compareTo(BigInteger.ZERO) == 0) && 
+				(cripCr_.compareTo(pre) < 0) &&
+				(cripCr_.compareTo(preCripCr) > 0)){
+			return crrtCr_;
+		} else {
+			return this.getCRWC(task, preTask, k+1, pre, prepre, cpurta);
+		}
+	}
+	
+	public Time getBCReactionImplicit(final EventChain ec, final CPURta cpurta) {
+		Time bcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+				final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+				final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+				bcRctImplicit = bcRctImplicit.add(bcrt);
+				if (i != 0) {
+					final Time bcip = this.getBCInitialPending(task, cpurta);
+					bcRctImplicit = bcRctImplicit.subtract(bcip);
+				}
+			}
+			return bcRctImplicit;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCReactionImplicit(final EventChain ec, final CPURta cpurta) {
+		Time wcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			final Task task_0 = taskChain.get(0);
+			final ProcessingUnit pu_0 = cpurta.getPU(task_0, cpurta);
+			final List<Task> taskList_0 = cpurta.getSortedTaskList(task_0, pu_0, cpurta);
+			final Time rt_0 = cpurta.preciseTestCPURT(task_0, taskList_0, TimeType.WCET, pu_0);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			wcRctImplicit = wcRctImplicit.add(rt_0);
+			wcRctImplicit = wcRctImplicit.add(period_0);
+			for (int i = 1; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+				final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+				final Time rt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+				wcRctImplicit = wcRctImplicit.add(rt);
+				if (i != taskChain.size() - 1) {
+					final Time period = CommonUtils.getStimInTime(task);
+					final Time bcip = this.getBCInitialPending(task, cpurta);
+					wcRctImplicit = wcRctImplicit.add(period.subtract(bcip));
+				} else {
+					final Time wcip = this.getWCInitialPending(task, cpurta);
+					wcRctImplicit = wcRctImplicit.subtract(wcip);
+				}
+			}
+			return wcRctImplicit;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
+		return getBCReactionImplicit(ec, cpurta);
+	}
+	
+	public Time getWCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
+		Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+				final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+				final Time period = CommonUtils.getStimInTime(task);
+				final Time rt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+				wcInitialRct = wcInitialRct.add(rt);
+				if (i != 0) {
+					final Task preTask = taskChain.get(i-1);
+					final Time prePeriod = CommonUtils.getStimInTime(preTask);
+					if (period.compareTo(prePeriod) >= 0 && taskChain.size() - 1 < 3) {
+						final Time wcip = this.getWCInitialPending(task, cpurta);
+						wcInitialRct = wcInitialRct.add(prePeriod.subtract(wcip));
+					} else if (period.compareTo(prePeriod) >= 0 && i == taskChain.size() - 1) {
+						final Time wcip = this.getWCInitialPending(task, cpurta);
+						wcInitialRct = wcInitialRct.subtract(wcip);
+					} else if (period.compareTo(prePeriod) >= 0 && i == 1) {
+						final Time bcip = this.getBCInitialPending(task, cpurta);
+						wcInitialRct = wcInitialRct.add(prePeriod.add(period).subtract(bcip));
+					} else {
+						final Time bcip = this.getBCInitialPending(task, cpurta);
+						wcInitialRct = wcInitialRct.add(period.subtract(bcip));
+					}
+				}
+			}
+			return wcInitialRct;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCReactionLET(final EventChain ec, final CPURta cpurta) {
+		Time bcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final Time period = CommonUtils.getStimInTime(task);
+				bcRctLET = bcRctLET.add(period);
+			}
+			return bcRctLET;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCReactionLET(final EventChain ec, final CPURta cpurta) {
+		Time wcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final Time period = CommonUtils.getStimInTime(task);
+				if (i != taskChain.size() - 1) {
+					wcRctLET = wcRctLET.add(period.multiply(2));
+				} else {
+					wcRctLET = wcRctLET.add(period);
+				}
+			}
+			return wcRctLET;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCInitialRctLET(final EventChain ec, final CPURta cpurta) {
+		return getBCReactionLET(ec, cpurta);
+	}
+	
+	public Time getWCInitialRctLET(final EventChain ec, final CPURta cpurta) {
+		Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final Time period = CommonUtils.getStimInTime(task);
+				wcInitialRct = wcInitialRct.add(period);
+				if (i != 0) {
+					final Task preTask = taskChain.get(i-1);
+					final Time prePeriod = CommonUtils.getStimInTime(preTask);
+					if (period.compareTo(prePeriod) > 0) {
+						wcInitialRct = wcInitialRct.add(prePeriod);
+					} else {
+						wcInitialRct = wcInitialRct.add(period);
+					}
+				}
+			}
+			return wcInitialRct;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCAgeImplicit(final EventChain ec, final CPURta cpurta) {
+		Time bcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			final Task task_0 = taskChain.get(0);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time bcInitialRct = getBCInitialRctImplicit(ec, cpurta);
+			final Time wcReaction = getWCReactionImplicit(ec, cpurta);
+			if ((period_0.add(bcInitialRct)).compareTo(wcReaction) < 0) {
+				final Task lastTask = taskChain.get(taskChain.size() - 1);
+				final Time lastTaskAge = getBCTaskAgeImplicit(lastTask, cpurta);
+				bcAgeImplicit = bcAgeImplicit.add(lastTaskAge);
+			} else {
+				bcAgeImplicit = bcAgeImplicit.add(period_0.add(bcInitialRct).subtract(wcReaction));
+			}
+			return bcAgeImplicit;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCAgeImplicit(final EventChain ec, final CPURta cpurta) {
+		Time wcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			final Task task_0 = taskChain.get(0);
+			final Time period_0 = CommonUtils.getStimInTime(task_0);
+			final Time wcInitialRct = getWCInitialRctImplicit(ec, cpurta);
+			final Time bcInitialRct = getBCInitialRctImplicit(ec, cpurta);
+			wcAgeImplicit = wcAgeImplicit.add(period_0.add(wcInitialRct).subtract(bcInitialRct));
+			return wcAgeImplicit;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCBCSubAgeImplicit(final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final Time wcAgeRctImplicit = this.getWCReactionImplicit(ec, cpurta);
+			final Time bcAgeRctImplicit = this.getBCReactionImplicit(ec, cpurta);
+			return wcAgeRctImplicit.subtract(bcAgeRctImplicit);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCAgeLET(final EventChain ec, final CPURta cpurta) {
+		Time bcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			final Task lastTask = taskChain.get(taskChain.size() - 1);
+			final Time lastTaskPeriod = CommonUtils.getStimInTime(lastTask);
+			bcAgeLET = bcAgeLET.add(lastTaskPeriod);
+			return bcAgeLET;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCAgeLET(final EventChain ec, final CPURta cpurta) {
+		Time wcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				final Time period = FactoryUtil.createTime(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task)), TimeUnit.PS);
+				if (i == 0) {
+					wcAgeLET = wcAgeLET.add(period);
+				} else {
+					if (period.compareTo(wcAgeLET) == 0) {
+						wcAgeLET = period.multiply(2);
+					} else if (period.compareTo(wcAgeLET) > 0) {
+						wcAgeLET = period;
+					} else {
+						final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
+						final BigInteger wcAgeLETBI = AmaltheaServices.convertToPicoSeconds(wcAgeLET);
+						final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
+						final BigDecimal wcAgeLETBD = BigDecimal.valueOf(wcAgeLETBI.doubleValue());
+						if (wcAgeLETBI.mod(periodBI) != BigInteger.ZERO) {
+							final BigDecimal ceiledValueBD = wcAgeLETBD.divide(periodBD, 0, BigDecimal.ROUND_CEILING);
+							final BigInteger ceiledValueBI = BigInteger.valueOf(ceiledValueBD.longValue());
+							wcAgeLET = FactoryUtil.createTime(periodBI.multiply(ceiledValueBI), TimeUnit.PS);
+						} else {
+							wcAgeLET = FactoryUtil.createTime(periodBI.multiply(wcAgeLETBI.divide(periodBI)
+									.add(BigInteger.ONE)), TimeUnit.PS);
+						}
+					}
+				}
+			}
+			return wcAgeLET;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCBCSubAgeLET(final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final Time wcAgeRctLET = this.getWCReactionLET(ec, cpurta);
+			final Time bcAgeRctLET = this.getBCReactionLET(ec, cpurta);
+			return wcAgeRctLET.subtract(bcAgeRctLET);
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCTaskAgeImplicit(final Task task, final CPURta cpurta) {
+		Time bcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+			final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+			final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+			final Time wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+			final Time period = CommonUtils.getStimInTime(task);
+			bcTaskAge = bcTaskAge.add(period.subtract(wcrt).add(bcrt));
+			return bcTaskAge;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCTaskAgeImplicit(final Task task, final CPURta cpurta) {
+		Time wcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (isTheRTAClassReady(cpurta)) {
+			final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+			final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+			final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+			final Time wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
+			final Time period = CommonUtils.getStimInTime(task);
+			wcTaskAge = wcTaskAge.add(period.subtract(bcrt).add(wcrt));
+			return wcTaskAge;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getBCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Time> bcDataAgeList = new ArrayList<Time>();
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				if (isMappedToCPU(task, cpurta)) {
+					Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
+					if (cpurta.getTriggeringTaskList().contains(task)) {
+						final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+						final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
+						final InterProcessStimulus ips = ipt.getStimulus();
+						final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
+						final Set<Label> gpuLabelSet = SoftwareUtil.getAccessedLabelSet(gpuTask, null);
+						labelSet.addAll(gpuLabelSet);
+						labelSet = labelSet.stream().distinct().collect(Collectors.toSet());
+					}
+					if(labelSet.contains(label)) {
+						final Time bcDataAge = getBCTaskAgeImplicit(task, cpurta);
+						bcDataAgeList.add(bcDataAge);
+					}
+				} else {
+					/* GPU Task - there is no best case or worst case reponse time for GPU Task => Age Latency = Period */
+					bcDataAgeList.add(CommonUtils.getStimInTime(task));
+				}
+			}
+			if (bcDataAgeList.size() != 0) {
+				Collections.sort(bcDataAgeList, new TimeComp());
+				return bcDataAgeList.get(0);
+			}
+			log.error("This chain does not have the observed label.");
+			return null;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	public Time getWCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
+		if (isTheRTAClassReady(cpurta)) {
+			final List<Time> wcDataAgeList = new ArrayList<Time>();
+			final List<Task> taskChain = getECTaskList(ec);
+			for (int i = 0; i < taskChain.size(); i++) {
+				final Task task = taskChain.get(i);
+				if (isMappedToCPU(task, cpurta)) {
+					Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
+					if (cpurta.getTriggeringTaskList().contains(task)) {
+						final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+						final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
+						final InterProcessStimulus ips = ipt.getStimulus();
+						final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
+						final Set<Label> gpuLabelSet = SoftwareUtil.getAccessedLabelSet(gpuTask, null);
+						labelSet.addAll(gpuLabelSet);
+						labelSet = labelSet.stream().distinct().collect(Collectors.toSet());
+					}
+					if(labelSet.contains(label)) {
+						final Time wcDataAge = getWCTaskAgeImplicit(task, cpurta);
+						wcDataAgeList.add(wcDataAge);
+					}
+				} else {
+					/* GPU Task - there is no best case or worst case reponse time for GPU Task => Age Latency = Period */
+					wcDataAgeList.add(CommonUtils.getStimInTime(task));
+				}
+			}
+			if (wcDataAgeList.size() != 0) {
+				Collections.sort(wcDataAgeList, new TimeComp());
+				return wcDataAgeList.get(0);
+			}
+			log.error("This chain does not have the observed label.");
+			return null;
+		}
+		log.error("cpurta instance is not ready!");
+		return null;
+	}
+	
+	/**************************************************************************************/
+
+	protected Time getBCInitialPending(final Task task, final CPURta cpurta) {
+		if (this.isTheRTAClassReady(cpurta)) {
+			/*
+			final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+			final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+			final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final Time bcct = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, cpurta);
+			return bcrt.subtract(bcct);
+			*/
+			// TODO: find the best-case initial pending in the given task's hyper-period 
+			// (for E2E Latency with the worst-case sampling interval time.)
+			return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		}
+		return null;
+	}
+	
+	protected Time getWCInitialPending(final Task task, final CPURta cpurta) {
+		if (this.isTheRTAClassReady(cpurta)) {
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+			final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
+			if (hpList.size() == 0) {
+				return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+			}
+			final Task oneHigherTask = hpList.get(hpList.size()-1);
+			Time wcIPTime = cpurta.preciseTestCPURT(oneHigherTask, hpList, TimeType.WCET, pu);
+			BigInteger wcIPTimeBI = AmaltheaServices.convertToPicoSeconds(wcIPTime);
+			for (int i = 0; i < hpList.size(); i++) {
+				final Task curTask = hpList.get(i);
+				final Time curPeriod = CommonUtils.getStimInTime(curTask);
+				BigInteger curPeriodBI = AmaltheaServices.convertToPicoSeconds(curPeriod);
+				if (i == hpList.size()-1 || wcIPTimeBI.compareTo(curPeriodBI) < 0) {
+					break;
+				} else if (wcIPTimeBI.mod(curPeriodBI) == BigInteger.ZERO) {
+					final Time curExeTime = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.WCET, cpurta);
+					final BigInteger curExeTimeBI = AmaltheaServices.convertToPicoSeconds(curExeTime);
+					wcIPTimeBI = wcIPTimeBI.add(curExeTimeBI);
+					i = -1;
+				}
+			}
+			wcIPTime = FactoryUtil.createTime(wcIPTimeBI, TimeUnit.PS);
+			return wcIPTime;
+		}
+		return null;
+	}
+	
+	protected Time getCRtoRT(final long offset, final Task task, final CPURta cpurta) {
+		Time crToRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (this.isTheRTAClassReady(cpurta)) {
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+			final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+			final Time hyper = this.getHyperPeriod(taskList);
+			final Time period = CommonUtils.getStimInTime(task);
+			final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+			final BigInteger period_BI = AmaltheaServices.convertToPicoSeconds(period);
+			final long cycle = hyper_BI.divide(period_BI).longValue();
+			if (offset % cycle != 0) {
+				final Time wcct = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.WCET, cpurta);
+				final Time initialTime = period.multiply(offset).add(wcct);
+				crToRT = initialTime;
+				/* Incremental CRtoRT Part */
+				final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
+				for (int i = 0; i < hpList.size(); i++) {
+					final BigInteger time_BI = AmaltheaServices.convertToPicoSeconds(crToRT);
+					final BigDecimal time_BD = BigDecimal.valueOf(time_BI.doubleValue());
+					final Task hpTask = hpList.get(i);
+					final Time hpWcct = rtaut.getExecutionTimeforCPUTaskIA(hpTask, pu, TimeType.WCET, cpurta);
+					final Time hpPeriod = CommonUtils.getStimInTime(hpTask);
+					final BigInteger hpPeriod_BI = AmaltheaServices.convertToPicoSeconds(hpPeriod);
+					final BigDecimal hpPeriod_BD = BigDecimal.valueOf(hpPeriod_BI.doubleValue());
+					long hpOffset = time_BD.divide(hpPeriod_BD, 0, BigDecimal.ROUND_FLOOR).longValue();
+					if (hpPeriod.multiply(hpOffset).add(hpWcct).compareTo(crToRT.subtract(wcct)) > 0 && time_BI.mod(hpPeriod_BI).longValue() != 0) {
+						crToRT = hpPeriod.multiply(hpOffset).add(hpWcct).add(wcct);
+						i = -1;
+					}
+				}
+			} else {
+				crToRT = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu).add(period.multiply(offset));
+			}
+			return crToRT;
+		}
+		return null;
+	}
+	
+	protected Time getCRtoIP(final long offset, final Task task, final CPURta cpurta) {
+		Time crToIP = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		if (this.isTheRTAClassReady(cpurta)) {
+			final RTARuntimeUtil rtaut = new RTARuntimeUtil();
+			final ProcessingUnit pu = cpurta.getPU(task, cpurta);
+			final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
+			final Time hyper = this.getHyperPeriod(taskList);
+			final Time period = CommonUtils.getStimInTime(task);
+			final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
+			final BigInteger period_BI = AmaltheaServices.convertToPicoSeconds(period);
+			final long cycle = hyper_BI.divide(period_BI).longValue();
+			if (offset % cycle != 0) {
+				final Time initialTime = period.multiply(offset);
+				crToIP = initialTime;
+				/* Incremental CRtoIP Part */
+				final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
+				for (int i = 0; i < hpList.size(); i++) {
+					final BigInteger time_BI = AmaltheaServices.convertToPicoSeconds(crToIP);
+					final BigDecimal time_BD = BigDecimal.valueOf(time_BI.doubleValue());
+					final Task hpTask = hpList.get(i);
+					final Time hpWcct = rtaut.getExecutionTimeforCPUTaskIA(hpTask, pu, TimeType.WCET, cpurta);
+					final Time hpPeriod = CommonUtils.getStimInTime(hpTask);
+					final BigInteger hpPeriod_BI = AmaltheaServices.convertToPicoSeconds(hpPeriod);
+					final BigDecimal hpPeriod_BD = BigDecimal.valueOf(hpPeriod_BI.doubleValue());
+					final long hpOffset = time_BD.divide(hpPeriod_BD, 0, BigDecimal.ROUND_FLOOR).longValue();
+					if (hpPeriod.multiply(hpOffset).add(hpWcct).compareTo(crToIP) > 0) {
+						crToIP = hpPeriod.multiply(hpOffset).add(hpWcct);
+						i = -1;
+					}
+				}
+			} else {
+				crToIP = this.getWCInitialPending(task, cpurta).add(period.multiply(offset));
+			}
+			return crToIP;
+		}
+		return null;
+	}
+	
+	protected Time getHyperPeriod(List<Task> taskChain) {
+		final List<Time> periodList = taskChain.stream().map(s -> CommonUtils.getStimInTime(s))
+				.collect(Collectors.toList());
+		Time result = periodList.get(0);
+		BigInteger resultBI = AmaltheaServices.convertToPicoSeconds(result);
+		for (int i = 1; i < periodList.size(); i++) {
+			final BigInteger comTime = AmaltheaServices.convertToPicoSeconds(periodList.get(i));
+			resultBI = getLCM(resultBI, comTime);
+		}
+		result = FactoryUtil.createTime(resultBI, TimeUnit.PS);
+		return result;
+	}
+	
+	private BigInteger getLCM(BigInteger time0, BigInteger time1) {
+		return time0.multiply(time1.divide(getGCD(time0, time1)));
+	}
+	
+	private BigInteger getGCD(BigInteger time0, BigInteger time1) {
+		while (time1.compareTo(BigInteger.ZERO) == 1) {
+			BigInteger temp = time1;
+			time1 = time0.mod(time1);
+			time0 = temp;
+		}
+		return time0;
+	}
+	
+	/**
+	 * Get an Event-Chain Entity List (Task-based)
+	 * @param ec			the observed event chain
+	 * @return			
+	 * 				the corresponding EC task list
+	 */
+	public List<Task> getECTaskList(final EventChain ec) {
+		final List<Task> chain = new ArrayList<Task>();
+		for (int i = 0; i < ec.getItems().size(); i++) {
+			final EventChainItem eci = ec.getItems().get(i);
+			if (eci instanceof EventChainContainer) {
+				final EventChainContainer ecc = (EventChainContainer) eci;
+				final Event stiEvent = ecc.getEventChain().getStimulus();
+				if (stiEvent instanceof ProcessEvent) {
+					final Task stiTask = (Task)((ProcessEvent) stiEvent).getEntity();
+					chain.add(stiTask);
+				}
+				if (i == ec.getItems().size() - 1) {
+					final Event resEvent = ecc.getEventChain().getResponse();
+					if (resEvent instanceof ProcessEvent) {
+						final Task resTask = (Task)((ProcessEvent) resEvent).getEntity();
+						chain.add(resTask);
+					}
+					break;
+				}
+			}
+		}
+		return chain;
+	}
+	
+	/**
+	 * conver an event-chain to a list of Labels that belong to the chain
+	 * @param ec			the observed event-chain
+	 * @return
+	 * 				a list of the observed event-chain
+	 */
+	public List<Label> convertECtoLabels(final EventChain ec, final CPURta cpurta) {
+		final List<Task> chain = getECTaskList(ec);
+		final List<Label> labels = new ArrayList<Label>();
+		for (int i = 0; i < chain.size(); i++) {
+			final Task task = chain.get(i);
+			final List<Runnable> runnables = SoftwareUtil.getRunnableList(task, null);
+			for (int j = 0; j < runnables.size(); j++) {
+				final Runnable runnable = runnables.get(j);
+				final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
+				final List<Label> temp = laList.stream().map(s -> s.getData()).distinct().collect(Collectors.toList());
+				labels.addAll(temp);
+			}
+			/* runnables from the triggered task (gpu task) */
+			if (cpurta.getTriggeringTaskList().contains(task)) {
+				final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
+				final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
+				final InterProcessStimulus ips = ipt.getStimulus();
+				final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
+				final List<Runnable> gpuRunnables = SoftwareUtil.getRunnableList(gpuTask, null);
+				for (int j = 0; j < gpuRunnables.size(); j++) {
+					final Runnable runnable = gpuRunnables.get(j);
+					final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
+					final List<Label> temp = laList.stream().map(s -> s.getData()).distinct().collect(Collectors.toList());
+					labels.addAll(temp);
+				}
+			}
+		}
+		final List<Label> labelList = labels.stream().distinct().collect(Collectors.toList());
+		return labelList;
+	}
+
+	/**
+	 * To check whether or not the observed task is mapped to CPU (according to the integer array)
+	 * @param task				the observed task
+	 * @param cpurta			the instance of CPURta class that contains model & mapping IA info
+	 * @return
+	 * 				boolean value that says whether or not it is mapped to CPU
+	 */
+	private static boolean isMappedToCPU (final Task task, final CPURta cpurta) {
+		/* The observed task is a GPU task */
+		if (cpurta.getGpuTaskList().contains(task)) {
+			final int index = cpurta.getModel().getSwModel().getTasks().indexOf(task);
+			final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
+			final int[] ia = cpurta.getIA();
+			/* when the observed GPU task is mapped to GPU */
+			if (ia[index] > cpuThreshold) {
+				return false;
+			}
+		}
+		/* when the observed task(CPU or GPU) is mapped to CPU */
+		return true;
+	}
+}
+
+/**
+ * @Date: July 10-2019
+ * @version 1.0
+ *			This inner class is used for sorting a Time type list.
+ *			If the Time of a is smaller than that of b, it returns -1.
+ *			If the Time of a is bigger than that of b, it returns 1.
+ */
+class TimeComp implements Comparator<Time> {
+	@Override
+	public int compare(final Time a, final Time b) {
+		if (a.compareTo(b) < 0) {
+			return -1;
+		}
+		return 1;
+	}
 }
\ No newline at end of file
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/IRTA.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/IRTA.java
new file mode 100644
index 0000000..726d59e
--- /dev/null
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/IRTA.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Dortmund University of Applied Sciences and Arts.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     FH Dortmund - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.app4mc.gsoc_rta;
+
+import java.util.HashMap;
+
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
+
+public interface IRTA {
+
+	/**
+	 * Get the sum of all response times contained in an AMALTHEA model
+	 * @param timeType (BCET, WCET supported)
+	 * @return Time response time sum across all tasks
+	 */
+	public Time getRTSum(final TimeType timeType);
+
+	/**
+	 * @return Hashmap<Task,Time> all tasks with corresponding response times
+	 */
+	public HashMap<Task, Time> getTRT();
+
+	/**
+	 * Get the response time of a task based on offsets for interProcessStimuli
+	 * @param t Task
+	 * @return Time reponse time
+	 */
+	public Time getRT(final Task t, final TimeType timeType);
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
index 7d19a19..73bf841 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/RTARuntimeUtil.java
@@ -1,573 +1,561 @@
-/*******************************************************************************

- * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.

- *

- * This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License 2.0

- * which accompanies this distribution, and is available at

- * https://www.eclipse.org/legal/epl-2.0/

- *

- * SPDX-License-Identifier: EPL-2.0

- *

- * Contributors: FH Dortmund - initial API and implementation

- * 

- *******************************************************************************/

-package org.eclipse.app4mc.gsoc_rta;

-

-import java.math.BigInteger;

-import java.util.ArrayList;

-import java.util.HashMap;

-import java.util.List;

-import java.util.stream.Collectors;

-

-import org.apache.log4j.Logger;

-import org.eclipse.app4mc.amalthea.model.AmaltheaServices;

-import org.eclipse.app4mc.amalthea.model.CallSequenceItem;

-import org.eclipse.app4mc.amalthea.model.ClearEvent;

-import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;

-import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;

-import org.eclipse.app4mc.amalthea.model.Label;

-import org.eclipse.app4mc.amalthea.model.LabelAccess;

-import org.eclipse.app4mc.amalthea.model.LabelAccessEnum;

-import org.eclipse.app4mc.amalthea.model.ProcessingUnit;

-import org.eclipse.app4mc.amalthea.model.Runnable;

-import org.eclipse.app4mc.amalthea.model.SetEvent;

-import org.eclipse.app4mc.amalthea.model.Task;

-import org.eclipse.app4mc.amalthea.model.TaskRunnableCall;

-import org.eclipse.app4mc.amalthea.model.Ticks;

-import org.eclipse.app4mc.amalthea.model.Time;

-import org.eclipse.app4mc.amalthea.model.TimeUnit;

-import org.eclipse.app4mc.amalthea.model.WaitEvent;

-import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;

-import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;

-import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;

-import org.eclipse.emf.common.util.EList;

-

-/**

- * Date: August 21-2019

- * @author Junhyung Ki

- * @version 1.0

- *					This class is to support CPURta class. Response Time Analysis contains low level calculation 

- *					such as deriving execution time of a Task or Runnable. Execution time calculation varies depending on the analyzed model. 

- *					Therefore, it is necessary to separate from Response Time calculation to increase adaptability.

- *					Only 'getExecutionTimeforCPUTask' method is accessible for CPURta and the rest are sub-methods of it.

- */

-public class RTARuntimeUtil {

-	/**

-	 * Calculate execution time of the given task under one of the four cases with some configurations.

-	 * Since this method is used by CPURta, the visibility should be 'public'

-	 * 1. triggering task in the synchronous mode

-	 * 2. triggering task in the asynchronous mode

-	 * 3. GPU task on CPU

-	 * 4. task with only Ticks

-	 * @param task				the observed task

-	 * @param pu				ProcessingUnit that would compute the given task (A57 or Denver)

-	 * @param executionCase		BCET, ACET, WCET

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

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

-	 * @return

-	 * 			execution time of the observed task

-	 */

-	public Time getExecutionTimeforCPUTask(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {

-		Logger.getLogger(RTARuntimeUtil.class);

-		/* set the default result time variable as 0s */

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		/* check if the current task is a triggering task.

-		 * If so, check whether or not it triggers the target task which is newly mapped to CPU.

-		 * In that case, returns 0 ps */

-		if (doesThisTaskTriggerCPUTask(task, cpurta)) {

-			return result;

-		}

-		/* contention time */

-		final Time contention = cpurta.getCT().contentionForTask(task);

-		/* The list of runnables of the given task */

-		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);

-		/* To identify the index of the triggerEvent */

-		final List<CallSequenceItem> callSequenceList = SoftwareUtil.collectCalls(task, null, 

-				(call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent

-						|| call instanceof SetEvent || call instanceof WaitEvent));

-		int indexforTrigger = 0;

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

-			if (callSequenceList.get(i) instanceof InterProcessTrigger) {

-				indexforTrigger = i;

-			}

-		}

-		/* To distinguish CPU Tasks between Sync & Async */

-		if (isTriggeringTask(task)) {

-			/* all should be synchronous (wait should not be ignored) - active wait */

-			if (SharedConsts.synchronousOffloading == true) {

-				result = syncTypeOperation(indexforTrigger, callSequenceList, runnableList, pu, executionCase, cpurta);

-				/* if this task has the OffloadingAsync runnable, subtract the runnable part from the result */

-				if (doesTaskHaveAsyncRunnable(task, cpurta)) {

-					result = result.subtract(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));

-				}

-			}

-			/* all should be asynchronous (wait should be ignored) - passive wait */

-			else {

-				result = asyncTypeOperation(runnableList, pu, executionCase);

-				/* if this task is missing the OffloadingAsync runnable, add the runnable part to the result */

-				if (!doesTaskHaveAsyncRunnable(task, cpurta)) {

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

-				}

-			}

-		}

-		else {

-			/* GPU Origin Task on CPU & No Triggering Behavior (No InterProcessTrigger) */

-			if (!(callSequenceList.get(indexforTrigger) instanceof InterProcessTrigger)) {

-				/* GPU Origin task that is newly mapped to CPU */

-				if (cpurta.getGpuTaskList().contains(task)) {

-					result = result.add(getExecutionTimeForGPUTaskOnCPU(task, runnableList, pu, executionCase, cpurta));

-					result = result.add(contention);

-					return result;

-				}

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

-				for (final Runnable r : runnableList) {

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

-				}

-			}

-		}

-		result = result.add(contention);

-		return result;

-	}

-

-	/**

-	 * Find out whether the given triggering task(that has an InterProcessTrigger) triggers a GPU task which is newly mapped to CPU.

-	 * If the ProcessingUnit index of the triggered task is bigger than the biggest CPU index, that means the triggered task is mapped to GPU

-	 * which would return false.

-	 * @param task			the observed task

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

-	 * 						(to get the task List & the integer array to identify the ProcessingUnit index of the triggered task)

-	 * @return

-	 * 			boolean value (true: the observed task triggers a task that is mapped to CPU / 

-	 * 						   false: the observed task triggers a task that is mapped to GPU)

-	 */

-	private boolean doesThisTaskTriggerCPUTask(final Task task, final CPURta cpurta) {

-		if (cpurta.getTriggeringTaskList().contains(task)) {

-			final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(task, null, 

-					(call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent

-							|| call instanceof SetEvent || call instanceof WaitEvent));

-			final InterProcessStimulus ips = ((InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next())

-					.getStimulus();

-			final EList<Task> allTaskList = cpurta.getModel().getSwModel().getTasks();

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

-			final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;

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

-				if (ia[i] > cpuThreshold) {

-					final Task theTask = allTaskList.get(i);

-					if (theTask.getStimuli().get(0) instanceof InterProcessStimulus) {

-						final InterProcessStimulus thisIPS = (InterProcessStimulus) theTask.getStimuli().get(0);

-						if (ips.equals(thisIPS)) {

-							Logger.getLogger(RTARuntimeUtil.class).debug("Confirmation: The triggered task mapped to (GPU)");

-							return false;

-						}

-					}

-				}

-			}

-			Logger.getLogger(RTARuntimeUtil.class).debug("Confirmation: The triggered task mapped to (CPU)");

-			return true;

-		}

-		return false;

-	}

-

-	/**

-	 * Calculate execution time of the given runnableList in a synchronous manner.

-	 * (execution time of pre-processing) + GPU task response time + (execution time of post-processing)

-	 * @param indexforTrigger	Integer variable that is used to get InterProcessTrigger to identify the triggered GPU task

-	 * @param callSequenceList	callSequenceList List variable that is used to get InterProcessTrigger to identify the triggered GPU task

-	 * @param runnableList		the observed runnable List to calculate execution time in the synchronous mode

-	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)

-	 * @param executionCase		BCET, ACET, WCET

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

-	 * 							(to get the identified triggered GPU task in the model)

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

-	 * @return

-	 * 			synchronous execution time of the observed set

-	 */

-	private Time syncTypeOperation(final int indexforTrigger, final List<CallSequenceItem> callSequenceList, final List<Runnable> runnableList,

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

-		Logger.getLogger(RTARuntimeUtil.class).debug("TYPE: SYNC");

-		/* set the default result time variable as 0s */

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		/* Sum all the runnable ExecutionTime of the CPU Task */

-		for (final Runnable r : runnableList) {

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

-		}

-		final InterProcessTrigger ipt = (InterProcessTrigger) callSequenceList.get(indexforTrigger);

-		final Task triggeredGPUTask = cpurta.getModel().getSwModel().getTasks().stream().filter(t -> t.getStimuli().get(0).equals(ipt.getStimulus())).iterator()

-				.next();

-		result = result.add(cpurta.getTRT().get(triggeredGPUTask));

-		return result;

-	}

-

-	/**

-	 * Calculate execution time of the given runnableList in an asynchronous manner.

-	 * (execution time of pre-processing) + (execution time of post-processing) 

-	 * @param runnableList		the observed runnable List to calculate execution time in the asynchronous mode

-	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)

-	 * @param executionCase		BCET, ACET, WCET

-	 * @return

-	 * 			asynchronous execution time of the observed runnable List

-	 */

-	private Time asyncTypeOperation(final List<Runnable> runnableList, final ProcessingUnit pu, final TimeType executionCase) {

-		Logger.getLogger(RTARuntimeUtil.class).debug("TYPE: ASYNC");

-		/**

-		 * <Asynchronous Task> et_t=sum_{runnable calls before GPU trigger

-		 * event}et_r + et_{runnable calls after GPU trigger event};

-		 */

-		/* set the default result time variable as 0s */

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		/* Sum all the runnable ExecutionTime */

-		for (final Runnable r : runnableList) {

-			/* In case of Pre_Detection_Post task, the AsyncOffloading runnable is already taken into account here. */

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

-		}

-		return result;

-	}

-

-	/**

-	 * Identify whether or not the given task has the OffloadingAsyncCosts Runnable (that takes costs into account in the Asynchronous mode)

-	 * which some triggering tasks do not have.

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

-	 * @param task			the observed task

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

-	 * 						(to access to the triggeringTaskList List<Task> variable that contains tasks with an InterProcessTrigger)

-	 * @return

-	 * 			boolean value of the result

-	 */

-	protected static boolean doesTaskHaveAsyncRunnable (final Task task, final CPURta cpurta) {

-		boolean result = false;

-		if (cpurta.getTriggeringTaskList().contains(task)) {

-			final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(task, null, 

-					(call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent

-							|| call instanceof SetEvent || call instanceof WaitEvent));

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

-			List<CallSequenceItem> clearEvent = callList.stream().filter(s -> s instanceof ClearEvent).collect(Collectors.toList());

-			if (clearEvent.size() != 0) {

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

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

-					result = true;

-				}

-			}

-		} else {

-			Logger.getLogger(RTARuntimeUtil.class).debug("ERROR: This task is not a triggering task!!");

-		}

-		return result;

-	}

-	

-	/**

-	 * Calculate execution time of the given task which was originally designed for GPU but newly mapped to CPU by Generic Algorithm Mapping.

-	 * It should ignore offloading runnables and take the required labels(read from pre-processing, write from post-processing) into account.

-	 * The method follows Read / Compute(Ticks) / Write semantic.

-	 * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)

-	 * @param task				the observed task

-	 * @param runnableList		runnable list of the given task

-	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)

-	 * @param executionCase		BCET, ACET, WCET

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

-	 * 							(to access to the gpuToCpuLabels HashMap variable that contains List<Label> of required read & write labels)

-	 * @return

-	 * 			execution time of the observed task

-	 */

-	private Time getExecutionTimeForGPUTaskOnCPU(final Task task, final List<Runnable> runnableList, final ProcessingUnit pu, 

-			final TimeType executionCase, final CPURta cpurta) {

-		Logger.getLogger(RTARuntimeUtil.class).debug("TYPE: GPUTaskOnCPU // " + "Task: " + task.getName());

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		Runnable funcRunnable = null;

-		for (final Runnable r : runnableList) {

-			final List<Ticks> thisTicksList = SoftwareUtil.getTicks(r, null);

-			if (thisTicksList.size() != 0) {

-				funcRunnable = r;

-				break;

-			}

-		}

-		final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);

-		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();

-		final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();

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

-		final List<Label> readLabelList = thisLabelList.get(0);

-		final List<Label> writeLabelList = thisLabelList.get(1);

-		for (final Label l : readLabelList) {

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

-		}

-		for (final Label l : writeLabelList) {

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

-		}

-		double readLatency = 0;

-		double writeLatency = 0;

-		if (executionCase.equals(TimeType.WCET)) {

-			readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();

-			writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();

-		} else if (executionCase.equals(TimeType.BCET)) {

-			readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();

-			writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();

-		} else {

-			readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();

-			writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();

-		}

-		/* Read (LabelAccess): */

-		double readAccessParameter = 0;

-		double sizeofReadLabels = 0;

-		for (final Label rl : readLabelList) {

-			sizeofReadLabels += rl.getSize().getNumberBytes();

-		}

-		readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / freq));

-		final Time readAccess = parameter.multiply(readAccessParameter);

-		result = result.add(readAccess); // LabelAccess(Read) added

-		/* Execution (Ticks): */

-		final List<Ticks> ticksList = SoftwareUtil.getTicks(funcRunnable, null);

-		for (final Ticks t : ticksList) {

-			// TODO: This line Should be replaced into below in the version 0.9.5 */

-			final Time tickExecution = CommonUtils.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.4

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

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

-		}

-		/* Write (LabelAccess): */

-		double writeAccessParameter = 0;

-		double sizeofWriteLabels = 0;

-		for (final Label wl : writeLabelList) {

-			sizeofWriteLabels += wl.getSize().getNumberBytes();

-		}

-		writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / freq));

-		final Time writeAccess = parameter.multiply(writeAccessParameter);

-		result = result.add(writeAccess); // LabelAccess(Write) added

-		return result;

-	}

-	

-	/**

-	 * Calculate execution time of the given runnable.

-	 * The method consider Read / Compute(Ticks) / Write semantic.

-	 * @param runnable			the observed runnable

-	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)

-	 * @param executionCase		BCET, ACET, WCET

-	 * @return

-	 * 			execution time of the observed runnable

-	 */

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

-		Logger.getLogger(RTARuntimeUtil.class).debug(executionCase.toString());

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();

-		double readLatency = 0;

-		double writeLatency = 0;

-		if (pu.getAccessElements().size() == 0) {

-			readLatency = 30; // Default value will be assigned

-			writeLatency = 30; // Default value of will be assigned

-		} else {

-			if (executionCase.equals(TimeType.WCET)) {

-				readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();

-				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();

-			} else if (executionCase.equals(TimeType.BCET)) {

-				readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();

-				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();

-			} else {

-				readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();

-				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();

-			}

-		}

-		/* Read & Write Memory Access Time */

-		result = result.add(getRunnableMemoryAccessTime(runnable, freq, readLatency, writeLatency));

-		/* Execution (Ticks): */

-		final List<Ticks> ticksList = SoftwareUtil.getTicks(runnable, null);

-		for (final Ticks t : ticksList) {

-			// TODO: This line Should be replaced into below in the version 0.9.5 */

-			final Time tickExecution = CommonUtils.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.4

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

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

-		}

-		return result;

-	}

-

-	/**

-	 * Calculate memory access time of the observed task.

-	 * Since this method is used by CPURta, the visibility should be 'public'

-	 * @param task				the observed task

-	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)

-	 * @param executionCase		BCET, ACET, WCET

-	 * @return

-	 * 			memory access time of the observed task

-	 */

-	public Time getTaskMemoryAccessTime (final Task task, final ProcessingUnit pu, final TimeType executionCase) {

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();

-		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);

-		double readLatency = 0;

-		double writeLatency = 0;

-		if (pu.getAccessElements().size() == 0) {

-			readLatency = 30; // Default value will be assigned

-			writeLatency = 30; // Default value of will be assigned

-		} else {

-			if (executionCase.equals(TimeType.WCET)) {

-				readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();

-				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();

-			} else if (executionCase.equals(TimeType.BCET)) {

-				readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();

-				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();

-			} else {

-				readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();

-				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();

-			}

-		}

-		for(final Runnable r : runnableList ) {

-			result = result.add(getRunnableMemoryAccessTime(r, freq, readLatency, writeLatency));

-		}

-		return result;

-	}

-	

-	/**

-	 * Calculate memory access time of the observed runnable.

-	 * The method follows Read / Compute(Ticks) / Write semantic.

-	 * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)

-	 * @param runnable			the observed runnable

-	 * @param frequency			frequency value of the Processing Unit

-	 * @param readLatency		readLatency value of the Processing Unit

-	 * @param writeLatency		writeLatency value of the Processing Unit

-	 * @return

-	 * 			memory access time of the observed runnable

-	 */

-	private Time getRunnableMemoryAccessTime (final Runnable runnable, final double frequency, 

-			final double readLatency, final double writeLatency) {

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);

-		final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(runnable, null);

-		final List<LabelAccess> readList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.READ)).collect(Collectors.toList());

-		final List<LabelAccess> writeList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.WRITE)).collect(Collectors.toList());

-		/* Read (LabelAccess): */

-		double readAccessParameter = 0;

-		double sizeofReadLabels = 0;

-		for (final LabelAccess rl : readList) {

-			sizeofReadLabels += rl.getData().getSize().getNumberBytes();

-		}

-		readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / frequency));

-		final Time readAccess = parameter.multiply(readAccessParameter);

-		result = result.add(readAccess); // LabelAccess(Read) added

-		/* Write (LabelAccess): */

-		double writeAccessParameter = 0;

-		double sizeofWriteLabels = 0;

-		for (final LabelAccess wl : writeList) {

-			sizeofWriteLabels += wl.getData().getSize().getNumberBytes();

-		}

-		writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / frequency));

-		final Time writeAccess = parameter.multiply(writeAccessParameter);

-		result = result.add(writeAccess); // LabelAccess(Write) added

-		return result;

-	}

-

-	/**

-	 * Identify whether the given task has an InterProcessTrigger or not.

-	 * @param task			the observed task

-	 * @return

-	 * 			boolean value of the result

-	 */

-	private static boolean isTriggeringTask(final Task task) {

-		/* true: Triggering Task, false: Non-Triggering Task */

-		boolean result = false;

-		final List<CallSequenceItem> callList = SoftwareUtil.collectCalls(task, null, 

-				(call -> call instanceof TaskRunnableCall || call instanceof InterProcessTrigger || call instanceof ClearEvent

-						|| call instanceof SetEvent || call instanceof WaitEvent));

-		List<CallSequenceItem> iptList = callList.stream().filter(s -> s instanceof InterProcessTrigger).collect(Collectors.toList());

-		if (iptList.size() != 0) {

-			result = true;

-		}

-		return result;

-	}

-	

-	/******************************************* Implicit Communication Paradigm *************************************************/

-	

-	/**

-	 * For the implicit communication paradigm

-	 * Time[0] = copy-in time for the observed task, Time[1] = copy-out time for the observed task

-	 * if a GPU task mapped to CPU is passed here, we also need to consider its required labels from Pre-Pro processing runnables

-	 * @param task				the observed task

-	 * @param pu				the processing unit that the observed task is mapped to

-	 * @param executionCase		WCET, BCET, ACET

-	 * @return

-	 * 				Time array that contains copy-in, copy-out time of the observed task

-	 */

-	public Time[] getLocalCopyTimeArray(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {

-		Time[] ta = new Time[2];

-		Time readCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		Time writeCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		/* The observed task is a GPU task */

-		if (cpurta.getGpuTaskList().contains(task)) {

-			final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();

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

-			final List<Label> readLabels = thisLabelList.get(0);

-			final List<Label> writeLabels = thisLabelList.get(1);

-			for (final Label rl : readLabels) {

-				readCopy = readCopy.add(getCopyEngineTime(rl, pu, executionCase, true));

-			}

-			ta[0] = readCopy;

-			for (final Label wl : writeLabels) {

-				writeCopy = writeCopy.add(getCopyEngineTime(wl, pu, executionCase, false));

-			}

-			ta[1] = writeCopy;

-			return ta;	

-		}

-		/* The observed task is a CPU task */

-		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);

-		final List<Label> readList = new ArrayList<Label>();

-		final List<Label> writeList = new ArrayList<Label>();

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

-			final Runnable runnable = runnableList.get(i);

-			final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);

-			final List<Label> rList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.READ))

-					.map(s->s.getData()).collect(Collectors.toList());

-			rList.stream().forEach(s -> readList.add(s));

-			final List<Label> wList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.WRITE))

-					.map(s->s.getData()).collect(Collectors.toList());

-			wList.stream().forEach(s -> writeList.add(s));

-		}

-		final List<Label> readLabels = readList.stream().distinct().collect(Collectors.toList());

-		final List<Label> writeLabels = writeList.stream().distinct().collect(Collectors.toList());

-		for (final Label rl : readLabels) {

-			readCopy = readCopy.add(getCopyEngineTime(rl, pu, executionCase, true));

-		}

-		ta[0] = readCopy;

-		for (final Label wl : writeLabels) {

-			writeCopy = writeCopy.add(getCopyEngineTime(wl, pu, executionCase, false));

-		}

-		ta[1] = writeCopy;

-		return ta;

-	}

-	

-	/**

-	 * The method is used to calculate CopyEngine time for single label.

-	 * @param label				the observed label

-	 * @param pu				ProcessingUnit that would process the given label

-	 * @param executionCase		BCET, ACET, WCET

-	 * @param readOrWrite		when the given runnable is 'runnable_0'(the first callSquence of the task), it is read(true),

-	 * 							when the given runnable is 'runnable_Last'(the last callSquence of the task), it is write(false).

-	 * @return

-	 * 				the given label copy engine time

-	 */

-	private Time getCopyEngineTime(final Label label, final ProcessingUnit pu, final TimeType executionCase, final boolean readOrWrite) {

-		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-		final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);

-		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();

-		double latency = 0;

-		/* Read */

-		if(readOrWrite) {

-			if (executionCase.equals(TimeType.BCET)) {

-				latency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();

-			} else if (executionCase.equals(TimeType.ACET)) {

-				latency = pu.getAccessElements().get(0).getReadLatency().getAverage();

-			} else if (executionCase.equals(TimeType.WCET)) {

-				latency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();

-			}

-		}

-		/* Write */

-		else {

-			if (executionCase.equals(TimeType.BCET)) {

-				latency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();

-			} else if (executionCase.equals(TimeType.ACET)) {

-				latency = pu.getAccessElements().get(0).getWriteLatency().getAverage();

-			} else if (executionCase.equals(TimeType.WCET)) {

-				latency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();

-			}

-		}

-		double labelAccessParameter = 0;

-		final double labelSize = label.getSize().getNumberBytes();

-		labelAccessParameter = (Math.ceil(labelSize / 64.0) * (latency / freq));

-		final Time labelAccess = parameter.multiply(labelAccessParameter);

-		result = result.add(labelAccess); // LabelAccess(Read) added

-		return result;

-	}

+/*******************************************************************************
+ * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     FH Dortmund - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.app4mc.gsoc_rta;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.eclipse.app4mc.gsoc_rta.CommonUtils;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts;
+import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
+import org.eclipse.app4mc.amalthea.model.ClearEvent;
+import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
+import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
+import org.eclipse.app4mc.amalthea.model.Label;
+import org.eclipse.app4mc.amalthea.model.LabelAccess;
+import org.eclipse.app4mc.amalthea.model.LabelAccessEnum;
+import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.Runnable;
+import org.eclipse.app4mc.amalthea.model.RunnableCall;
+import org.eclipse.app4mc.amalthea.model.SetEvent;
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Ticks;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.TimeUnit;
+import org.eclipse.app4mc.amalthea.model.WaitEvent;
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil;
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
+import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
+import org.eclipse.emf.common.util.EList;
+
+public class RTARuntimeUtil {
+	final static Logger log = Logger.getLogger(RTARuntimeUtil.class);
+	/**
+	 * Calculate execution time of the given task under one of the four cases with some configurations.
+	 * Since this method is used by CPURta, the visibility should be 'public'
+	 * 1. triggering task in the synchronous mode
+	 * 2. triggering task in the asynchronous mode
+	 * 3. GPU task on CPU
+	 * 4. task with only Ticks
+	 * @param task				the observed task
+	 * @param pu				ProcessingUnit that would compute the given task (A57 or Denver)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @param cpurta			the instance of CPURta class that calls this method
+	 * 							(to access to the cumuAcTime Time variable that accumulate access latency)
+	 * @return
+	 * 			execution time of the observed task
+	 */
+	public Time getExecutionTimeforCPUTaskIA(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
+		log.setLevel(Level.ERROR);
+		/* set the default result time variable as 0s */
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		/* check if the current task is a triggering task.
+		 * If so, check whether or not it triggers the target task which is newly mapped to CPU.
+		 * In that case, returns 0 ps */
+		if (doesThisTaskTriggerCPUTask(task, cpurta)) {
+			return result;
+		}
+		/* contention time */
+		final Time contention = cpurta.getCT().contentionForTask(task);
+		/* The list of runnables of the given task */
+		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
+		/* To identify the index of the triggerEvent */
+		final List<ActivityGraphItem> callSequenceList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+				|| call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+		int indexforTrigger = 0;
+		for (int i = 0; i < callSequenceList.size(); i++) {
+			if (callSequenceList.get(i) instanceof InterProcessTrigger) {
+				indexforTrigger = i;
+			}
+		}
+		/* To distinguish CPU Tasks between Sync & Async */
+		if (isTriggeringTask(task)) {
+			/* all should be synchronous (wait should not be ignored) - active wait */
+			if (SharedConsts.synchronousOffloading == true) {
+				result = syncTypeOperation(indexforTrigger, callSequenceList, runnableList, pu, executionCase, cpurta);
+				/* if this task has the OffloadingAsync runnable, subtract the runnable part from the result */
+				if (doesTaskHaveAsyncRunnable(task, cpurta)) {
+					result = result.subtract(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));
+				}
+			}
+			/* all should be asynchronous (wait should be ignored) - passive wait */
+			else {
+				result = asyncTypeOperation(runnableList, pu, executionCase);
+				/* if this task is missing the OffloadingAsync runnable, add the runnable part to the result */
+				if (!doesTaskHaveAsyncRunnable(task, cpurta)) {
+					result = result.add(getExecutionTimeForRTARunnable(cpurta.offloadingAsyncRunnable, pu, executionCase));
+				}
+			}
+		}
+		else {
+			/* GPU Origin Task on CPU & No Triggering Behavior (No InterProcessTrigger) */
+			if (!(callSequenceList.get(indexforTrigger) instanceof InterProcessTrigger)) {
+				/* GPU Origin task that is newly mapped to CPU */
+				if (cpurta.getGpuTaskList().contains(task)) {
+					result = result.add(getExecutionTimeForGPUTaskOnCPU(task, runnableList, pu, executionCase, cpurta));
+					result = result.add(contention);
+					return result;
+				}
+				/* No Triggering Behavior (No InterProcessTrigger) */
+				for (final Runnable r : runnableList) {
+					result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
+				}
+			}
+		}
+		result = result.add(contention);
+		return result;
+	}
+
+	/**
+	 * Find out whether the given triggering task(that has an InterProcessTrigger) triggers a GPU task which is newly mapped to CPU.
+	 * If the ProcessingUnit index of the triggered task is bigger than the biggest CPU index, that means the triggered task is mapped to GPU
+	 * which would return false.
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURtaIA class that calls this method
+	 * 						(to get the task List & the integer array to identify the ProcessingUnit index of the triggered task)
+	 * @return
+	 * 			boolean value (true: the observed task triggers a task that is mapped to CPU / 
+	 * 						   false: the observed task triggers a task that is mapped to GPU)
+	 */
+	private boolean doesThisTaskTriggerCPUTask(final Task task, final CPURta cpurta) {
+		if (cpurta.getTriggeringTaskList().contains(task)) {
+			final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+					|| call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+			final InterProcessStimulus ips = ((InterProcessTrigger) callList.stream().filter(s -> s instanceof InterProcessTrigger).iterator().next())
+					.getStimulus();
+			final EList<Task> allTaskList = cpurta.getModel().getSwModel().getTasks();
+			final int[] ia = cpurta.getIA();
+			final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
+			for (int i = 0; i < ia.length; i++) {
+				if (ia[i] > cpuThreshold) {
+					final Task theTask = allTaskList.get(i);
+					if (theTask.getStimuli().get(0) instanceof InterProcessStimulus) {
+						final InterProcessStimulus thisIPS = (InterProcessStimulus) theTask.getStimuli().get(0);
+						if (ips.equals(thisIPS)) {
+							log.debug("Confirmation: The triggered task mapped to (GPU)");
+							return false;
+						}
+					}
+				}
+			}
+			log.debug("Confirmation: The triggered task mapped to (CPU)");
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Calculate execution time of the given runnableList in a synchronous manner.
+	 * (execution time of pre-processing) + GPU task response time + (execution time of post-processing)
+	 * @param indexforTrigger	Integer variable that is used to get InterProcessTrigger to identify the triggered GPU task
+	 * @param callSequenceList	callSequenceList List variable that is used to get InterProcessTrigger to identify the triggered GPU task
+	 * @param runnableList		the observed runnable List to calculate execution time in the synchronous mode
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @param cpurta			the instance of CPURtaIA class that calls this method
+	 * 							(to get the identified triggered GPU task in the model)
+	 * 							(to access to the cumuAcTime Time variable that accumulate access latency)
+	 * @return
+	 * 			synchronous execution time of the observed set
+	 */
+	private Time syncTypeOperation(final int indexforTrigger, final List<ActivityGraphItem> callSequenceList, final List<Runnable> runnableList,
+			final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
+		log.debug("TYPE: SYNC");
+		/* set the default result time variable as 0s */
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		/* Sum all the runnable ExecutionTime of the CPU Task */
+		for (final Runnable r : runnableList) {
+			result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
+		}
+		final InterProcessTrigger ipt = (InterProcessTrigger) callSequenceList.get(indexforTrigger);
+		final Task triggeredGPUTask = cpurta.getModel().getSwModel().getTasks().stream().filter(t -> t.getStimuli().get(0).equals(ipt.getStimulus())).iterator()
+				.next();
+		result = result.add(cpurta.getTRT().get(triggeredGPUTask));
+		return result;
+	}
+
+	/**
+	 * Calculate execution time of the given runnableList in an asynchronous manner.
+	 * (execution time of pre-processing) + (execution time of post-processing) 
+	 * @param runnableList		the observed runnable List to calculate execution time in the asynchronous mode
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @return
+	 * 			asynchronous execution time of the observed runnable List
+	 */
+	private Time asyncTypeOperation(final List<Runnable> runnableList, final ProcessingUnit pu, final TimeType executionCase) {
+		log.debug("TYPE: ASYNC");
+		/**
+		 * <Asynchronous Task> et_t=sum_{runnable calls before GPU trigger
+		 * event}et_r + et_{runnable calls after GPU trigger event};
+		 */
+		/* set the default result time variable as 0s */
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		/* Sum all the runnable ExecutionTime */
+		for (final Runnable r : runnableList) {
+			/* In case of Pre_Detection_Post task, the AsyncOffloading runnable is already taken into account here. */
+			result = result.add(getExecutionTimeForRTARunnable(r, pu, executionCase));
+		}
+		return result;
+	}
+
+	/**
+	 * Identify whether or not the given task has the OffloadingAsyncCosts Runnable (that takes costs into account in the Asynchronous mode)
+	 * which some triggering tasks do not have.
+	 * Since this method is used by CPURtaIA, the visibility should be 'protected'
+	 * @param task			the observed task
+	 * @param cpurta		the instance of CPURtaIA class that calls this method
+	 * 						(to access to the triggeringTaskList List<Task> variable that contains tasks with an InterProcessTrigger)
+	 * @return
+	 * 			boolean value of the result
+	 */
+	protected static boolean doesTaskHaveAsyncRunnable(final Task task, final CPURta cpurta) {
+		boolean result = false;
+		if (cpurta.getTriggeringTaskList().contains(task)) {
+			final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+					|| call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+			final int waitIndex = callList.indexOf(callList.stream().filter(s -> s instanceof WaitEvent).iterator().next());
+			final List<ActivityGraphItem> clearEvent = callList.stream().filter(s -> s instanceof ClearEvent).collect(Collectors.toList());
+			if (clearEvent.size() != 0) {
+				final int clearIndex = callList.indexOf(callList.stream().filter(s -> s instanceof ClearEvent).iterator().next());
+				if ((clearIndex - waitIndex) > 1) {
+					result = true;
+				}
+			}
+		} else {
+			log.debug("ERROR: This task is not a triggering task!!");
+		}
+		return result;
+	}
+	
+	/**
+	 * Calculate execution time of the given task which was originally designed for GPU but newly mapped to CPU by Generic Algorithm Mapping.
+	 * It should ignore offloading runnables and take the required labels(read from pre-processing, write from post-processing) into account.
+	 * The method follows Read / Compute(Ticks) / Write semantic.
+	 * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)
+	 * @param task				the observed task
+	 * @param runnableList		runnable list of the given task
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @param cpurta			the instance of CPURtaIA class that calls this method
+	 * 							(to access to the gpuToCpuLabels HashMap variable that contains List<Label> of required read & write labels)
+	 * @return
+	 * 			execution time of the observed task
+	 */
+	private Time getExecutionTimeForGPUTaskOnCPU(final Task task, final List<Runnable> runnableList, final ProcessingUnit pu, 
+			final TimeType executionCase, final CPURta cpurta) {
+		log.debug("TYPE: GPUTaskOnCPU // " + "Task: " + task.getName());
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		Runnable funcRunnable = null;
+		for (final Runnable r : runnableList) {
+			final List<Ticks> thisTicksList = SoftwareUtil.getTicks(r, null);
+			if (thisTicksList.size() != 0) {
+				funcRunnable = r;
+				break;
+			}
+		}
+		final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
+		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+		final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();
+		final List<List<Label>> thisLabelList = gtcl.get(task);
+		final List<Label> readLabelList = thisLabelList.get(0);
+		final List<Label> writeLabelList = thisLabelList.get(1);
+		for (final Label l : readLabelList) {
+			log.debug("Label(Read): " + l.getName() + " // (" + task.getName() + ")");
+		}
+		for (final Label l : writeLabelList) {
+			log.debug("Label(Write): " + l.getName() + " // (" + task.getName() + ")");
+		}
+		double readLatency = 0;
+		double writeLatency = 0;
+		if (executionCase.equals(TimeType.WCET)) {
+			readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+			writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+		} else if (executionCase.equals(TimeType.BCET)) {
+			readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+			writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+		} else {
+			readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+			writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+		}
+		/* Read (LabelAccess): */
+		double readAccessParameter = 0;
+		double sizeofReadLabels = 0;
+		for (final Label rl : readLabelList) {
+			sizeofReadLabels += rl.getSize().getNumberBytes();
+		}
+		readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / freq));
+		final Time readAccess = parameter.multiply(readAccessParameter);
+		result = result.add(readAccess); // LabelAccess(Read) added
+		/* Execution (Ticks): */
+		final List<Ticks> ticksList = SoftwareUtil.getTicks(funcRunnable, null);
+		for (final Ticks t : ticksList) {
+			final Time tickExecution = CommonUtils.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.4
+			result = result.add(tickExecution); // Execution(Ticks) added
+		}
+		/* Write (LabelAccess): */
+		double writeAccessParameter = 0;
+		double sizeofWriteLabels = 0;
+		for (final Label wl : writeLabelList) {
+			sizeofWriteLabels += wl.getSize().getNumberBytes();
+		}
+		writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / freq));
+		final Time writeAccess = parameter.multiply(writeAccessParameter);
+		result = result.add(writeAccess); // LabelAccess(Write) added
+		return result;
+	}
+
+	/**
+	 * Calculate execution time of the given runnable.
+	 * The method consider Read / Compute(Ticks) / Write semantic.
+	 * @param runnable			the observed runnable
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @return
+	 * 			execution time of the observed runnable
+	 */
+	private Time getExecutionTimeForRTARunnable(final Runnable runnable, final ProcessingUnit pu, final TimeType executionCase) {
+		log.debug(executionCase.toString());
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+		double readLatency = 0;
+		double writeLatency = 0;
+		if (pu.getAccessElements().size() == 0) {
+			readLatency = 30; // Default value will be assigned
+			writeLatency = 30; // Default value of will be assigned
+		} else {
+			if (executionCase.equals(TimeType.WCET)) {
+				readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+			} else if (executionCase.equals(TimeType.BCET)) {
+				readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+			} else {
+				readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+			}
+		}
+		/* Read & Write Memory Access Time */
+		result = result.add(getRunnableMemoryAccessTime(runnable, freq, readLatency, writeLatency));
+		/* Execution (Ticks): */
+		final List<Ticks> ticksList = SoftwareUtil.getTicks(runnable, null);
+		for (final Ticks t : ticksList) {
+			final Time tickExecution = RuntimeUtil.getExecutionTimeForTicks(t, pu, executionCase); // 0.9.5
+			result = result.add(tickExecution); // Execution(Ticks) added
+		}
+		return result;
+	}
+
+	/**
+	 * Calculate memory access time of the observed task.
+	 * Since this method is used by CPURta, the visibility should be 'public'
+	 * @param task				the observed task
+	 * @param pu				ProcessingUnit that would compute the given runnable (A57 or Denver)
+	 * @param executionCase		BCET, ACET, WCET
+	 * @return
+	 * 			memory access time of the observed task
+	 */
+	public Time getTaskMemoryAccessTime(final Task task, final ProcessingUnit pu, final TimeType executionCase) {
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
+		double readLatency = 0;
+		double writeLatency = 0;
+		if (pu.getAccessElements().size() == 0) {
+			readLatency = 30; // Default value will be assigned
+			writeLatency = 30; // Default value of will be assigned
+		} else {
+			if (executionCase.equals(TimeType.WCET)) {
+				readLatency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+			} else if (executionCase.equals(TimeType.BCET)) {
+				readLatency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+			} else {
+				readLatency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+				writeLatency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+			}
+		}
+		for (final Runnable r : runnableList) {
+			result = result.add(getRunnableMemoryAccessTime(r, freq, readLatency, writeLatency));
+		}
+		return result;
+	}
+
+	/**
+	 * Calculate memory access time of the observed runnable.
+	 * The method follows Read / Compute(Ticks) / Write semantic.
+	 * Read(Write)_Access_Time = Round_UP(Size_of_Read_Labels / 64.0 Bytes) * (Read_Latency / Frequency)
+	 * @param runnable			the observed runnable
+	 * @param frequency			frequency value of the Processing Unit
+	 * @param readLatency		readLatency value of the Processing Unit
+	 * @param writeLatency		writeLatency value of the Processing Unit
+	 * @return
+	 * 			memory access time of the observed runnable
+	 */
+	public Time getRunnableMemoryAccessTime(final Runnable runnable, final double frequency, final double readLatency, final double writeLatency) {
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
+		final List<LabelAccess> thisLAList = SoftwareUtil.getLabelAccessList(runnable, null);
+		final List<LabelAccess> readList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.READ)).collect(Collectors.toList());
+		final List<LabelAccess> writeList = thisLAList.stream().filter(x -> (x.getAccess()).equals(LabelAccessEnum.WRITE)).collect(Collectors.toList());
+		/* Read (LabelAccess): */
+		double readAccessParameter = 0;
+		double sizeofReadLabels = 0;
+		for (final LabelAccess rl : readList) {
+			sizeofReadLabels += rl.getData().getSize().getNumberBytes();
+		}
+		readAccessParameter = (Math.ceil(sizeofReadLabels / 64.0) * (readLatency / frequency));
+		final Time readAccess = parameter.multiply(readAccessParameter);
+		result = result.add(readAccess); // LabelAccess(Read) added
+		/* Write (LabelAccess): */
+		double writeAccessParameter = 0;
+		double sizeofWriteLabels = 0;
+		for (final LabelAccess wl : writeList) {
+			sizeofWriteLabels += wl.getData().getSize().getNumberBytes();
+		}
+		writeAccessParameter = (Math.ceil(sizeofWriteLabels / 64.0) * (writeLatency / frequency));
+		final Time writeAccess = parameter.multiply(writeAccessParameter);
+		result = result.add(writeAccess); // LabelAccess(Write) added
+		return result;
+	}
+
+	/**
+	 * Identify whether the given task has an InterProcessTrigger or not.
+	 * @param task			the observed task
+	 * @return
+	 * 			boolean value of the result
+	 */
+	protected static boolean isTriggeringTask(final Task task) {
+		/* true: Triggering Task, false: Non-Triggering Task */
+		boolean result = false;
+		final List<ActivityGraphItem> callList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof RunnableCall
+				|| call instanceof InterProcessTrigger || call instanceof ClearEvent || call instanceof SetEvent || call instanceof WaitEvent));
+		final List<ActivityGraphItem> iptList = callList.stream().filter(s -> s instanceof InterProcessTrigger).collect(Collectors.toList());
+		if (iptList.size() != 0) {
+			result = true;
+		}
+		return result;
+	}
+
+	/******************************************* Implicit Communication Paradigm *************************************************/
+
+	/**
+	 * For the implicit communication paradigm
+	 * Time[0] = copy-in time for the observed task, Time[1] = copy-out time for the observed task
+	 * if a GPU task mapped to CPU is passed here, we also need to consider its required labels from Pre-Pro processing runnables
+	 * @param task				the observed task
+	 * @param pu				the processing unit that the observed task is mapped to
+	 * @param executionCase		WCET, BCET, ACET
+	 * @param cpurta			the instance of CPURtaIA class that calls this method
+	 * @return
+	 * 				Time array that contains copy-in, copy-out time of the observed task
+	 */
+	protected Time[] getLocalCopyTimeArray(final Task task, final ProcessingUnit pu, final TimeType executionCase, final CPURta cpurta) {
+		final Time[] ta = new Time[2];
+		Time readCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		Time writeCopy = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		/* The observed task is a GPU task */
+		if (cpurta.getGpuTaskList().contains(task)) {
+			final HashMap<Task, List<List<Label>>> gtcl = cpurta.getGTCL();
+			final List<List<Label>> thisLabelList = gtcl.get(task);
+			final List<Label> readLabels = thisLabelList.get(0);
+			final List<Label> writeLabels = thisLabelList.get(1);
+			for (final Label rl : readLabels) {
+				readCopy = readCopy.add(this.getLocalCopyTime(rl, pu, executionCase, true));
+			}
+			ta[0] = readCopy;
+			for (final Label wl : writeLabels) {
+				writeCopy = writeCopy.add(this.getLocalCopyTime(wl, pu, executionCase, false));
+			}
+			ta[1] = writeCopy;
+			return ta;
+		}
+		/* The observed task is a CPU task */
+		final List<Runnable> runnableList = SoftwareUtil.getRunnableList(task, null);
+		final List<Label> readList = new ArrayList<Label>();
+		final List<Label> writeList = new ArrayList<Label>();
+		for (int i = 0; i < runnableList.size(); i++) {
+			final Runnable runnable = runnableList.get(i);
+			final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
+			final List<Label> rList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.READ))
+					.map(s -> s.getData()).collect(Collectors.toList());
+			rList.stream().forEach(s -> readList.add(s));
+			final List<Label> wList = laList.stream().filter(s -> (s.getAccess()).equals(LabelAccessEnum.WRITE))
+					.map(s -> s.getData()).collect(Collectors.toList());
+			wList.stream().forEach(s -> writeList.add(s));
+		}
+		final List<Label> readLabels = readList.stream().distinct().collect(Collectors.toList());
+		final List<Label> writeLabels = writeList.stream().distinct().collect(Collectors.toList());
+		for (final Label rl : readLabels) {
+			readCopy = readCopy.add(this.getLocalCopyTime(rl, pu, executionCase, true));
+		}
+		ta[0] = readCopy;
+		for (final Label wl : writeLabels) {
+			writeCopy = writeCopy.add(this.getLocalCopyTime(wl, pu, executionCase, false));
+		}
+		ta[1] = writeCopy;
+		return ta;
+	}
+
+	/**
+	 * The method is used to calculate LocalCopy time for single label.
+	 * @param label				the observed label
+	 * @param pu				ProcessingUnit that would process the given label
+	 * @param executionCase		BCET, ACET, WCET
+	 * @param readOrWrite		when the given runnable is 'runnable_0'(the first callSquence of the task), it is read(true),
+	 * 							when the given runnable is 'runnable_Last'(the last callSquence of the task), it is write(false).
+	 * @return
+	 * 				the given LocalCopy time
+	 */
+	private Time getLocalCopyTime(final Label label, final ProcessingUnit pu, final TimeType executionCase, final boolean readOrWrite) {
+		Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+		final Time parameter = FactoryUtil.createTime(BigInteger.ONE, TimeUnit.S);
+		final double freq = AmaltheaServices.convertToHertz(pu.getFrequencyDomain().getDefaultValue()).longValue();
+		double latency = 0;
+		/* Read */
+		if (readOrWrite) {
+			if (executionCase.equals(TimeType.BCET)) {
+				latency = pu.getAccessElements().get(0).getReadLatency().getLowerBound();
+			} else if (executionCase.equals(TimeType.ACET)) {
+				latency = pu.getAccessElements().get(0).getReadLatency().getAverage();
+			} else if (executionCase.equals(TimeType.WCET)) {
+				latency = pu.getAccessElements().get(0).getReadLatency().getUpperBound();
+			}
+		}
+		/* Write */
+		else {
+			if (executionCase.equals(TimeType.BCET)) {
+				latency = pu.getAccessElements().get(0).getWriteLatency().getLowerBound();
+			} else if (executionCase.equals(TimeType.ACET)) {
+				latency = pu.getAccessElements().get(0).getWriteLatency().getAverage();
+			} else if (executionCase.equals(TimeType.WCET)) {
+				latency = pu.getAccessElements().get(0).getWriteLatency().getUpperBound();
+			}
+		}
+		double labelAccessParameter = 0;
+		final double labelSize = label.getSize().getNumberBytes();
+		labelAccessParameter = (Math.ceil(labelSize / 64.0) * (latency / freq));
+		final Time labelAccess = parameter.multiply(labelAccessParameter);
+		result = result.add(labelAccess); // LabelAccess(Read) added
+		return result;
+	}
 }
\ No newline at end of file
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java
index 8e8a72e..e763bd8 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/SharedConsts.java
@@ -16,21 +16,26 @@
 import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
 
 public class SharedConsts {
+
+	public static int RUNTIMESEC = 2 * 60 * 60;
+
 	/*-----------Measurement Configuration--------------–*/
 	public static TimeType timeType = TimeType.WCET;
 	public static boolean onlyWrittenLabelsCE = true;
 	public static boolean synchronousOffloading = false;
 	public static boolean useModelTimeSlices = false;
-	public static boolean ignoreInfeasibility = true;
+	public static boolean ignoreInfeasibility = false;
 	public static int[] timeSlices;
 	public static long timeSliceLengthPS = 1000000000l;
-	public static final boolean levelIBusyPeriod = false;
+	public static boolean levelIBusyPeriod = false;
 	public static TS_DERIV tsDeriv = TS_DERIV.TSxPrio;
 	public static OPT_TYPE optimize = OPT_TYPE.RESPONSETIMESUM;
+	public static final boolean considerGlobalBlocking = false;
+	public static final boolean considerLocalBlocking = false;
+	public static boolean offsetCPURTA = true;
+	public static final boolean zeroHigh = true;
 	/*-----------End Measur. Configuration--------------–*/
 
-	/* Arbitrary Integer Array (GA scenario) */
-	public static final int[] defaultIAMapping = new int[] { 4, 1, 1, 3, 4, 0, 3, 3, 3, 0, 6, 2, 5, 6 };
 
 	public enum OPT_TYPE {
 		TASKCHAINS, RESPONSETIMESUM, LOADBALANCING
@@ -47,4 +52,8 @@
 	public enum ComParadigm {
 		DIRECT, IMPLICIT
 	}
-}
\ No newline at end of file
+	
+	public enum SINGLE_CASE {
+		BCLAT, WCLAT, CRITICAL
+	}
+}
diff --git a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
index f71f927..19d822d 100644
--- a/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
+++ b/eclipse-tools/responseTime-analyzer/plugins/org.eclipse.app4mc.gsoc_rta/src/org/eclipse/app4mc/gsoc_rta/ui/APP4RTA.java
@@ -1,1057 +1,1057 @@
-/*******************************************************************************

- * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.

- *

- * This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License 2.0

- * which accompanies this distribution, and is available at

- * https://www.eclipse.org/legal/epl-2.0/

- *

- * SPDX-License-Identifier: EPL-2.0

- *

- * Contributors: Junhyung Ki - initial API and implementation

- * 

- *******************************************************************************/

-package org.eclipse.app4mc.gsoc_rta.ui;

-

-import java.awt.Color;

-import java.awt.EventQueue;

-import java.awt.Font;

-import java.awt.List;

-import java.awt.event.ActionEvent;

-import java.awt.event.ActionListener;

-import java.io.File;

-import java.math.BigInteger;

-import java.util.HashMap;

-import java.util.stream.Collectors;

-

-import javax.swing.ButtonGroup;

-import javax.swing.JButton;

-import javax.swing.JComboBox;

-import javax.swing.JFrame;

-import javax.swing.JFileChooser;

-import javax.swing.JLabel;

-import javax.swing.JOptionPane;

-import javax.swing.JRadioButton;

-import javax.swing.JTextField;

-

-import org.apache.log4j.Level;

-import org.apache.log4j.Logger;

-import org.eclipse.app4mc.amalthea.model.Amalthea;

-import org.eclipse.app4mc.amalthea.model.AmaltheaServices;

-import org.eclipse.app4mc.amalthea.model.EventChain;

-import org.eclipse.app4mc.amalthea.model.Label;

-import org.eclipse.app4mc.amalthea.model.ProcessingUnit;

-import org.eclipse.app4mc.amalthea.model.PuType;

-import org.eclipse.app4mc.amalthea.model.Task;

-import org.eclipse.app4mc.amalthea.model.Time;

-import org.eclipse.app4mc.amalthea.model.TimeUnit;

-import org.eclipse.app4mc.amalthea.model.io.AmaltheaLoader;

-import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;

-import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;

-import org.eclipse.app4mc.gsoc_rta.*;

-import org.eclipse.app4mc.gsoc_rta.SharedConsts.ComParadigm;

-import org.eclipse.emf.common.util.EList;

-import javax.swing.SwingConstants;

-import javax.swing.filechooser.FileNameExtensionFilter;

-import javax.swing.JSeparator;

-

-/**

- * Date: August 21-2019 

- * @author Junhyung Ki

- * @version 1.0

- *					The purpose of this class is to provide users a better visual and increase usability of Response Time Analysis.

- */

-@SuppressWarnings("serial")

-public class APP4RTA extends JFrame {

-	private static JComboBox<String> ecComboBox = new JComboBox<String>();

-	

-	private CPURta cpurta = new CPURta();

-	private E2ELatency e2e = new E2ELatency();

-	private Amalthea currentModel = null;

-	private java.util.List<ProcessingUnit> currentPUList = null;

-	private int[] currentIA = null;

-	private EList<Task> allTaskList = null;

-	private EList<EventChain> currentECList = null;

-	private EventChain currentEC = null;

-	private java.util.List<Task> currentTaskChain = null;

-	private File currentFile = null;

-	

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

-	private JFrame frame;

-	private int selectedECIndex = -1;

-	private boolean schedulability_flag = false;

-	private ComParadigm currentParadigm = null;

-	JFileChooser fileChooser;

-	JTextField selectedModelLbl;

-	

-	private JLabel jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10, 

-		jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19;

-	private JTextField tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9, 

-		tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19;

-	private JLabel[] jLabelArray = {

-			jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10, 

-			jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19

-	};

-	private JTextField[] jTextFieldArray= {

-			tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9, 

-			tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19

-	};

-	

-	private JLabel jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7;

-	private JLabel jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h;

-	private List l0, l1, l2, l3, l4, l5, l6, l7;

-	private List rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7;

-	private JLabel[] puLabelArray = {

-			jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7

-	};

-	private JLabel[] rtListLabelArray = {

-			jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h

-	};

-	private List[] puListArray = {

-			l0, l1, l2, l3, l4, l5, l6, l7

-	};

-	private List[] rtListArray = {

-			rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7

-	};

-	

-	private JLabel ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6, 

-		ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13;

-	private JTextField jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,

-		jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13;

-	private JLabel[] ecLabelArray = {

-			ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6,

-			ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13

-	};

-	private JTextField[] ecJTPArray = {

-			jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,

-			jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13

-	};

-	

-	private List list, list_1, list_2;

-

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

-		EventQueue.invokeLater(new Runnable() {

-			public void run() {

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

-				Logger.getRootLogger().setLevel(Level.ERROR);

-				final APP4RTA window = new APP4RTA();

-				window.frame.setVisible(true);

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

-			}

-		});

-	}

-

-	public APP4RTA() {

-		initialize();

-	}

-	

-	private void initialize() {

-		frame = new JFrame();

-		frame.getContentPane().setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		frame.setBounds(0, 31, 1200, 1027);

-		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

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

-		

-		JLabel lblSelectTheModel = new JLabel("Amalthea Model");

-		lblSelectTheModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));

-		lblSelectTheModel.setBounds(10, 13, 120, 22);

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

-		

-		JLabel lblTaskName = new JLabel("Task Name");

-		lblTaskName.setForeground(new Color(139, 0, 0));

-		lblTaskName.setFont(new Font("Sitka Heading", Font.BOLD, 12));

-		lblTaskName.setHorizontalAlignment(SwingConstants.CENTER);

-		lblTaskName.setBounds(15, 43, 70, 16);

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

-		

-		JLabel lblPuNum = new JLabel("PU Num");

-		lblPuNum.setForeground(new Color(0, 0, 255));

-		lblPuNum.setHorizontalAlignment(SwingConstants.CENTER);

-		lblPuNum.setFont(new Font("Sitka Heading", Font.BOLD, 12));

-		lblPuNum.setBounds(92, 43, 70, 16);

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

-		

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

-		btnDefualtIa.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent arg0) {

-				if (cpurta.getModel() == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: A model is not loaded.");

-					return ;

-				} else if (cpurta.getTRT() == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: TRT HashMap is not loaded.");

-					return ;

-				} else if (cpurta.getPUl().size() == 0) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Processing Unit List is not loaded.");

-					return ;

-				}

-				final int[] defaultIA = SharedConsts.defaultIAMapping;

-				if (cpurta.getModel().getSwModel().getTasks().size() == defaultIA.length) {

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

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

-					}

-					return ;

-				} else if (currentPUList.size() == 1) {

-					final int numOfTasks = cpurta.getModel().getSwModel().getTasks().size();

-					for (int i = 0; i < numOfTasks; i++) {

-						jTextFieldArray[i].setText("0");

-					}

-					return ;

-				}

-				String str = "";

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

-					if (i == currentPUList.size() - 1) {

-						str = str + i; 

-						break;

-					}

-					str = str + i + ", ";

-				}

-				JOptionPane.showMessageDialog(frame, "ERROR: The length of the default integer array does not match with\n"

-						+ "the number of tasks in the target model.\n\n" + "Please assign the number(s) manually.\n" 

-						+ "Available PU number(s): " + str);

-			}

-		});

-		

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

-		btnEnterIA.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

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

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

-					if (jTextFieldArray[i].getText().length() == 0) {

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

-						return ;

-					} else if (jTextFieldArray[i].getText().charAt(0) < 48 || jTextFieldArray[i].getText().charAt(0) > 54) {

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

-						return ;

-					} else if (i >= 0 && i <= 9 && Integer.parseInt(jTextFieldArray[i].getText()) == 6) {

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

-								+ "Please assign different IA value for " + "(" + allTaskList.get(i).getName() + ")");

-						return ;

-					} else if (i == jTextFieldArray.length-1 && Integer.parseInt(jTextFieldArray[i].getText()) != 6) {

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

-						return ;

-					}

-					currentIA[i] = Integer.parseInt(jTextFieldArray[i].getText());

-				}

-				cpurta.setIA(currentIA);

-				cpurta.setContention(currentIA, currentModel);

-				puTaskListHM = cpurta.be_getPUTaskListHashMap(currentModel);

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

-					if (puListArray[i].getItemCount() == 0) {

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

-							puListArray[i].add((puTaskListHM.get(i).get(j)).getName());

-						}

-					}

-				}

-			}

-		});

-		

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

-		rdbtnSynchronous.setForeground(new Color(139, 0, 0));

-		rdbtnSynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		

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

-		rdbtnAsynchronous.setForeground(new Color(0, 0, 255));

-		rdbtnAsynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		

-		ButtonGroup offloadingMode = new ButtonGroup();

-		offloadingMode.add(rdbtnSynchronous);

-		offloadingMode.add(rdbtnAsynchronous);

-		

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

-		rdbtnWorstCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		rdbtnWorstCase.setForeground(Color.DARK_GRAY);

-		

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

-		rdbtnAverageCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		rdbtnAverageCase.setForeground(Color.DARK_GRAY);

-		

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

-		rdbtnBestCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		rdbtnBestCase.setForeground(Color.DARK_GRAY);

-

-		ButtonGroup executionMode = new ButtonGroup();

-		executionMode.add(rdbtnWorstCase);

-		executionMode.add(rdbtnAverageCase);

-		executionMode.add(rdbtnBestCase);

-		

-		JLabel lblSchedulability = new JLabel("Schedulability");

-		JTextField schedulability = new JTextField();

-		schedulability.setHorizontalAlignment(SwingConstants.RIGHT);

-		schedulability.setEditable(false);

-		

-		JLabel lblMemAccCost = new JLabel("Cumulated Memory-Access Cost");

-		JTextField memAccCost = new JTextField();

-		memAccCost.setHorizontalAlignment(SwingConstants.RIGHT);

-		memAccCost.setEditable(false);

-		

-		JLabel lblCumulContention = new JLabel("Cumulated Contention");

-		JTextField cumulContention = new JTextField();

-		cumulContention.setHorizontalAlignment(SwingConstants.RIGHT);

-		cumulContention.setEditable(false);

-		

-		JLabel lblComputation = new JLabel("Computation");

-		JTextField computation = new JTextField();

-		computation.setHorizontalAlignment(SwingConstants.RIGHT);

-		computation.setEditable(false);

-		

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

-		JTextField rtSum = new JTextField();

-		rtSum.setHorizontalAlignment(SwingConstants.RIGHT);

-		rtSum.setEditable(false);

-		

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

-		btnCalculate.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent arg0) {

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

-					if (jTextFieldArray[i].getText().length() == 0) {

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

-						return ;

-					}

-				}				

-				if (rdbtnSynchronous.isSelected()) {

-					SharedConsts.synchronousOffloading = true;

-				} else if (rdbtnAsynchronous.isSelected()) {

-					SharedConsts.synchronousOffloading = false;

-				} else {

-					JOptionPane.showMessageDialog(frame, "ERROR: You should choose an offloading mode! (Sync / Async)");

-					return ;

-				}

-				if (rdbtnWorstCase.isSelected()) {

-					SharedConsts.timeType = TimeType.WCET;

-				} else if (rdbtnAverageCase.isSelected()) {

-					SharedConsts.timeType = TimeType.ACET;

-				} else if (rdbtnBestCase.isSelected()) {

-					SharedConsts.timeType = TimeType.BCET;

-				} else {

-					JOptionPane.showMessageDialog(frame, "ERROR: You should choose an execution case! (Worst Case / Average Case / Best Case)");

-					return ;

-				}

-				if (currentIA == null || puTaskListHM.size() == 0) {

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

-					return ;

-				}

-				schedulability_flag = true;

-				Time pRtSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

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

-					final ProcessingUnit pu = cpurta.getPUl().get(i);

-					final java.util.List<Task> thisPUTaskList = puTaskListHM.get(i);

-					Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-					if (rtListArray[i].getItemCount() == 0) {

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

-							for (Task t : thisPUTaskList) {

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

-								final Time thisPeriod = CommonUtils.getStimInTime(t);

-								final BigInteger period = AmaltheaServices.convertToPicoSeconds(thisPeriod);

-								if (AmaltheaServices.convertToPicoSeconds(thisRT).compareTo(period) > 0) {

-									rtListArray[i].add("Non Scheduleable! => MAX Value");

-									schedulability_flag = false;

-								} else if (AmaltheaServices.convertToPicoSeconds(thisRT).equals(BigInteger.ZERO)) {

-									rtListArray[i].add("0 ps (GPU Task on CPU)");

-								} else {

-									rtListArray[i].add(thisRT.toString());

-								}

-								pRtSum = pRtSum.add(thisRT);

-							}

-						} else {

-							for (Task t : thisPUTaskList) {

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

-								rtListArray[i].add(thisRT.toString());

-								pRtSum = pRtSum.add(thisRT);

-							}

-						}

-					}

-				}

-				if (schedulability_flag) {

-					schedulability.setText("Scheduleable! :)");

-					memAccCost.setText("" + cpurta.getCumulatedMemAccCosts());

-					cumulContention.setText("" + cpurta.getCumulatedContention());

-					computation.setText("" + (pRtSum.subtract(cpurta.getCumulatedMemAccCosts())).subtract(cpurta.getCumulatedContention()));

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

-				} else {

-					schedulability.setText("Non Scheduleable! :(");

-					memAccCost.setText("Not Available.");

-					cumulContention.setText("Not Available.");

-					computation.setText("Not Available.");

-					rtSum.setText("Not Available.");

-				}

-			}

-		});

-		

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

-		btnReset.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

-				currentIA = null;

-				cpurta.setIA(currentIA);

-				cpurta.setContention(currentIA, currentModel);

-				/* latency time initializing */

-				cpurta.initCumulatedMemAccCosts();

-				cpurta.initCumulatedContention();

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

-					jTextFieldArray[i].setText("");

-				}

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

-					puListArray[i].removeAll();

-				}

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

-					rtListArray[i].removeAll();

-				}

-				offloadingMode.setSelected(null, false);

-				executionMode.setSelected(null, false);

-				schedulability.setText(null);

-				memAccCost.setText(null);

-				cumulContention.setText(null);

-				computation.setText(null);

-				rtSum.setText(null);

-				currentIA = null;

-				puTaskListHM = null;

-				frame.revalidate();

-				frame.repaint();

-			}

-		});

-

-		selectedModelLbl = new JTextField();

-		selectedModelLbl.setEditable(false);

-		selectedModelLbl.setBounds(142, 13, 206, 22);

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

-		selectedModelLbl.setColumns(10);

-		

-		JButton amaltheaSchBtn = new JButton("Search Amalthea");

-		amaltheaSchBtn.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

-				final String userDirLocation = System.getProperty("user.dir");

-				File userDir = new File(userDirLocation);

-				fileChooser = new JFileChooser(userDir);

-				fileChooser.setAcceptAllFileFilterUsed(false);

-		        FileNameExtensionFilter filter = new FileNameExtensionFilter("Amalthea models", "amxmi");

-		        fileChooser.addChoosableFileFilter(filter);

-		        fileChooser.setDialogTitle("Open File");

-		        int result = fileChooser.showOpenDialog(null);

-		        if (result == JFileChooser.APPROVE_OPTION) {

-		        	final Amalthea loadedModel = AmaltheaLoader.loadFromFile(fileChooser.getSelectedFile());

-		        	if (loadedModel.getVersion().compareTo("0.9.4") != 0) {

-		        		JOptionPane.showMessageDialog(frame, "Error: This model should be migrated to the version 0.9.4");

-		        		return ;

-		        	}

-		        	/* Something was selected before */

-		        	if (currentFile != null) {

-		        		/* The selected file is equal to the previous file => Do nothing */

-		        		if (fileChooser.getSelectedFile().equals(currentFile)) {

-		        			JOptionPane.showMessageDialog(frame, "Same Model");

-		        			return ;

-		        		}

-		        		/* If the selected file is different to the previous one => Remove and Do Normal. */

-		        		else {

-		        			schedulability.setText(null);

-		    				memAccCost.setText(null);

-		    				cumulContention.setText(null);

-		    				computation.setText(null);

-		    				rtSum.setText(null);

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

-								frame.remove(jLabelArray[i]);

-								frame.remove(jTextFieldArray[i]);

-							}

-							frame.remove(btnDefualtIa);

-							frame.remove(btnEnterIA);

-							frame.remove(rdbtnSynchronous);

-							frame.remove(rdbtnAsynchronous);

-							frame.remove(rdbtnWorstCase);

-							frame.remove(rdbtnAverageCase);

-							frame.remove(rdbtnBestCase);

-							frame.remove(btnCalculate);

-							frame.remove(btnReset);

-							frame.remove(lblSchedulability);

-							frame.remove(schedulability);

-							frame.remove(lblMemAccCost);

-							frame.remove(memAccCost);

-							frame.remove(lblCumulContention);

-							frame.remove(cumulContention);

-							frame.remove(lblComputation);

-							frame.remove(computation);

-							frame.remove(lblResponseTimeSum);

-							frame.remove(rtSum);

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

-								frame.remove(puLabelArray[i]);

-								frame.remove(rtListLabelArray[i]);

-								frame.remove(puListArray[i]);

-								frame.remove(rtListArray[i]);

-							}

-							frame.remove(ecComboBox);

-		        		}

-		        	}

-		        	/* Something was not selected before => Do normal */

-		        	currentFile = fileChooser.getSelectedFile();

-		        	selectedModelLbl.setText(currentFile.getName());

-		        	currentModel = loadedModel;

-					currentPUList = CommonUtils.getPUs(currentModel);

-					if (currentPUList.get(0).getAccessElements().size() == 0) {

-						JOptionPane.showMessageDialog(frame, "The selected model's processing unit(s) does(do) not have 'read & write Latency' values.\n\n"

-								+ "Therefore, the default value of 30 will be assigned for them.\n"

-								+ "This will affect the response time results.");

-					}

-					cpurta.setModel(currentModel);

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

-					cpurta.setPUl(currentPUList);

-					allTaskList = currentModel.getSwModel().getTasks();

-					if (allTaskList.size() > 20) {

-						JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + allTaskList.size() + " Tasks. (Limit: 20)\n" 

-								+ "Please choose a different model.");

-						return ;

-					} else if (currentPUList.size() > 8) {

-						JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + currentPUList.size() + " Processing Units. (Limit: 8)\n"

-								+ "Please choose a different model.");

-						return ;

-					}

-					/* Task Indices */

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

-						jLabelArray[i] = new JLabel(allTaskList.get(i).getName());

-						jLabelArray[i].setBounds(12, (60+(i*24)), 97, 16);

-						frame.getContentPane().add(jLabelArray[i]);

-						jTextFieldArray[i] = new JTextField();

-						jTextFieldArray[i].setColumns(10);

-						jTextFieldArray[i].setBounds(118, (60+(i*24)), 22, 22);

-						frame.getContentPane().add(jTextFieldArray[i]);

-					}

-					/* DefaultIA Button */

-					btnDefualtIa.setBounds(155, 60, 97, 25);

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

-					/* EnterIA Button */

-					btnEnterIA.setBounds(155, 90, 97, 25);

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

-					/* Sync Radio Button */

-					rdbtnSynchronous.setBounds(152, 125, 126, 25);

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

-					/* Async Radio Button */

-					rdbtnAsynchronous.setBounds(152, 145, 126, 25);

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

-					/* WorstCase Radio Button */

-					rdbtnWorstCase.setBounds(152, 175, 107, 25);

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

-					/* AverageCase Radio Button */

-					rdbtnAverageCase.setBounds(152, 195, 107, 25);

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

-					/* BestCase Radio Button */

-					rdbtnBestCase.setBounds(152, 215, 107, 25);

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

-					/* Calculate Button */

-					btnCalculate.setBounds(155, 252, 97, 25);

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

-					/* Reset Button */

-					btnReset.setBounds(155, 282, 97, 25);

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

-					/* Schedulability Label & TextField */

-					lblSchedulability.setBounds(157, 323, 200, 16);

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

-					schedulability.setBounds(155, 343, 200, 22);

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

-					/* MemAccCost Label & TextField */

-					lblMemAccCost.setBounds(157, 368, 200, 16);

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

-					memAccCost.setBounds(155, 388, 200, 22);

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

-					/* CumulContention Label & TextField */

-					lblCumulContention.setBounds(157, 413, 200, 16);

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

-					cumulContention.setBounds(155, 433, 200, 22);

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

-					/* Computation */

-					lblComputation.setBounds(157, 458, 200, 16);

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

-					computation.setBounds(155, 478, 200, 22);

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

-					/* ResponseTime Sum Label & TextField */

-					lblResponseTimeSum.setBounds(157, 503, 200, 16);

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

-					rtSum.setBounds(155, 523, 200, 22);

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

-					/* PU & RT Lists */

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

-						puLabelArray[i] = new JLabel(i +": " + currentPUList.get(i).getDefinition().getName());

-						rtListLabelArray[i] = new JLabel("Response Time");

-						puListArray[i] = new List();

-						rtListArray[i] = new List();

-						if (i >= 0 && i < 4) {

-							puLabelArray[i].setBounds((387+(i*200)), 50, 87, 22);

-							rtListLabelArray[i].setBounds((474+(i*200)), 50, 88, 22);

-							puListArray[i].setBounds((385+(i*200)), 75, 87, 145);

-							rtListArray[i].setBounds((475+(i*200)), 75, 87, 145);

-						} else if (i >= 4) {

-							puLabelArray[i].setBounds((387+((i-4)*200)), 225, 87, 22);

-							rtListLabelArray[i].setBounds((474+((i-4)*200)), 225, 88, 22);

-							puListArray[i].setBounds((385+((i-4)*200)), 250, 87, 145);

-							rtListArray[i].setBounds((475+((i-4)*200)), 250, 87, 145);

-						}

-						frame.getContentPane().add(puLabelArray[i]);

-						frame.getContentPane().add(rtListLabelArray[i]);

-						frame.getContentPane().add(puListArray[i]);

-						frame.getContentPane().add(rtListArray[i]);

-					}

-					/* E2ELatency Part */

-					currentECList = currentModel.getConstraintsModel().getEventChains();

-					if (currentECList.size() != 0) {

-						final String[] ecComboArray = new String[currentECList.size()];

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

-							ecComboArray[i] = currentECList.get(i).getName();

-						}

-						ecComboBox = new JComboBox<String>(ecComboArray);

-						ecComboBox.setBounds(150, 570, 206, 22);

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

-						ecComboBox.setSelectedItem(null);

-					} else {

-						JOptionPane.showMessageDialog(frame, "WARNING: The selected model has no Event-Chain.\n"

-								+ "End-to-End Event-Chain Latency Calculation is impossible with this model.");

-						// TODO: Something needs to be done here to prevent E2ELatency calculation.

-					}

-					frame.revalidate();

-					frame.repaint();

-		        }

-			}

-		});

-		amaltheaSchBtn.setBounds(348, 12, 133, 24);

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

-

-		JLabel lblEventChainModel = new JLabel("EVENT CHAIN MODEL");

-		lblEventChainModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));

-		lblEventChainModel.setBounds(10, 570, 136, 22);

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

-		

-		JRadioButton rdbtnDirect = new JRadioButton("Direct");

-		rdbtnDirect.setForeground(new Color(139, 0, 0));

-		rdbtnDirect.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		rdbtnDirect.setBounds(530, 569, 70, 25);

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

-		

-		JRadioButton rdbtnImplicit = new JRadioButton("Implicit");

-		rdbtnImplicit.setForeground(new Color(0, 0, 255));

-		rdbtnImplicit.setFont(new Font("Sitka Heading", Font.BOLD, 13));

-		rdbtnImplicit.setBounds(596, 569, 79, 25);

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

-		

-		ButtonGroup paradigmMode = new ButtonGroup();

-		paradigmMode.add(rdbtnDirect);

-		paradigmMode.add(rdbtnImplicit);

-		

-		JLabel lblNewLabel = new JLabel("Direct & Implicit Communication Paradigm");

-		lblNewLabel.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));

-		lblNewLabel.setBounds(10, 605, 293, 16);

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

-		

-		JLabel lblWorstcaseReaction = new JLabel("WC Reaction");

-		lblWorstcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);

-		lblWorstcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblWorstcaseReaction.setBounds(10, 627, 90, 16);

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

-		

-		JTextField txtField0 = new JTextField();

-		txtField0.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField0.setBounds(103, 625, 200, 22);

-		txtField0.setEditable(false);

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

-		

-		JLabel lblBestcaseReaction = new JLabel("BC Reaction");

-		lblBestcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblBestcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);

-		lblBestcaseReaction.setBounds(10, 656, 90, 16);

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

-		

-		JTextField txtField1 = new JTextField();

-		txtField1.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField1.setBounds(103, 654, 200, 22);

-		txtField1.setEditable(false);

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

-		

-		JLabel lblLetCommunicationParadigm = new JLabel("LET Communication Paradigm");

-		lblLetCommunicationParadigm.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));

-		lblLetCommunicationParadigm.setBounds(10, 688, 193, 16);

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

-		

-		JLabel lblWcReaction = new JLabel("WC Reaction");

-		lblWcReaction.setHorizontalAlignment(SwingConstants.CENTER);

-		lblWcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblWcReaction.setBounds(10, 710, 90, 16);

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

-		

-		JTextField txtField2 = new JTextField();

-		txtField2.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField2.setBounds(103, 708, 200, 22);

-		txtField2.setEditable(false);

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

-		

-		JLabel lblBcReaction = new JLabel("BC Reaction");

-		lblBcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblBcReaction.setHorizontalAlignment(SwingConstants.CENTER);

-		lblBcReaction.setBounds(10, 739, 90, 16);

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

-		

-		JTextField txtField3 = new JTextField();

-		txtField3.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField3.setBounds(103, 737, 200, 22);

-		txtField3.setEditable(false);

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

-		

-		JLabel lblTaskChain = new JLabel("Task Chain Age (Direct & Implicit)");

-		lblTaskChain.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));

-		lblTaskChain.setBounds(338, 605, 222, 16);

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

-		

-		JLabel lblWcAge = new JLabel("WC Age");

-		lblWcAge.setHorizontalAlignment(SwingConstants.CENTER);

-		lblWcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblWcAge.setBounds(350, 627, 58, 16);

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

-		

-		JTextField txtField4 = new JTextField();

-		txtField4.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField4.setBounds(413, 625, 200, 22);

-		txtField4.setEditable(false);

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

-		

-		JLabel lblBcAge = new JLabel("BC Age");

-		lblBcAge.setHorizontalAlignment(SwingConstants.CENTER);

-		lblBcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblBcAge.setBounds(350, 656, 58, 16);

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

-		

-		JTextField txtField5 = new JTextField();

-		txtField5.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField5.setBounds(413, 654, 200, 22);

-		txtField5.setEditable(false);

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

-		

-		JLabel lblEarlyReaction = new JLabel("Early Reaction (Direct & Implicit)");

-		lblEarlyReaction.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));

-		lblEarlyReaction.setBounds(338, 688, 232, 16);

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

-		

-		JLabel lblWcErct = new JLabel("WC E-Rct");

-		lblWcErct.setHorizontalAlignment(SwingConstants.CENTER);

-		lblWcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblWcErct.setBounds(338, 710, 70, 16);

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

-		

-		JTextField txtField6 = new JTextField();

-		txtField6.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField6.setBounds(413, 708, 200, 22);

-		txtField6.setEditable(false);

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

-		

-		JLabel lblBcErct = new JLabel("BC E-Rct");

-		lblBcErct.setHorizontalAlignment(SwingConstants.CENTER);

-		lblBcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblBcErct.setBounds(338, 739, 70, 16);

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

-		

-		JTextField txtField7 = new JTextField();

-		txtField7.setHorizontalAlignment(SwingConstants.RIGHT);

-		txtField7.setBounds(413, 737, 200, 22);

-		txtField7.setEditable(false);

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

-		

-		JLabel lblDataAge = new JLabel("Data Age");

-		lblDataAge.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));

-		lblDataAge.setBounds(10, 771, 58, 16);

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

-		

-		JLabel lblContainedLabels = new JLabel("Contained Labels");

-		lblContainedLabels.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblContainedLabels.setBounds(10, 791, 136, 16);

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

-		

-		list = new List();

-		list.setBounds(10, 810, 155, 160);

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

-		

-		JLabel lblWorstcaseAge = new JLabel("Worst-case Age");

-		lblWorstcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblWorstcaseAge.setBounds(177, 791, 136, 16);

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

-		

-		list_1 = new List();

-		list_1.setBounds(177, 810, 155, 160);

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

-		

-		JLabel lblBestcaseAge = new JLabel("Best-case Age");

-		lblBestcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));

-		lblBestcaseAge.setBounds(344, 791, 136, 16);

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

-		

-		list_2 = new List();

-		list_2.setBounds(344, 810, 155, 160);

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

-		

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

-		ecSelect.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

-				if (currentModel == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");

-					return ;

-				} else if (currentECList == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Event-Chain List is empty somehow.");

-					return ;

-				} else if (currentECList.size() == 0) {

-					JOptionPane.showMessageDialog(frame, "ERROR: There is no Event-Chain in this model.");

-					return ;

-				} else if (ecComboBox.getSelectedItem() == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");

-					return ;

-				} else if (puTaskListHM == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been assigned.");

-					return ;

-				} else if (offloadingMode.getSelection() == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Choose an offloading mode. (Sync / Async)");

-					return ;

-				} else if (schedulability_flag == false) {

-					String offMode = null;

-					if (SharedConsts.synchronousOffloading == true) {

-						offMode = "Sync";

-					} else if (SharedConsts.synchronousOffloading == false) {

-						offMode = "Aync";

-					}

-					String tType = null;

-					if (SharedConsts.timeType.equals(TimeType.WCET)) {

-						tType = "WC";

-					} else if (SharedConsts.timeType.equals(TimeType.ACET)) {

-						tType = "AC";

-					} else if (SharedConsts.timeType.equals(TimeType.BCET)) {

-						tType = "BC";

-					}

-					String iaFeedback = "";

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

-						if (i == currentIA.length - 1) {

-							iaFeedback = iaFeedback + currentIA[i];

-						} else {

-							iaFeedback = iaFeedback + currentIA[i] + ", ";

-						}

-					}

-					JOptionPane.showMessageDialog(frame, "ERROR: The entered IA value is not schedulable with the current configuration.\n\n"

-							+ "Current Integer Arrary: { " + iaFeedback + " }\n\n"

-							+ "Current Configuration: Offloading Mode(" + offMode + "), ExecutionCase(" + tType + ")");

-					return ;

-				} else if (paradigmMode.getSelection() == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Choose a communication paradigm. (Direct / Implicit)");

-					return ;

-				}

-				final int thisIndex = ecComboBox.getSelectedIndex();

-				/* Something was selected before */

-				if (selectedECIndex != -1) {

-					/* If the selected Event-Chain is the same as before => Do Nothing */

-					if (selectedECIndex == thisIndex) {

-						if (currentParadigm != null) {

-							ComParadigm changedParadigm = null;

-							if (rdbtnDirect.isSelected()) {

-								changedParadigm = ComParadigm.DIRECT;

-							} else if (rdbtnImplicit.isSelected()) {

-								changedParadigm = ComParadigm.IMPLICIT;

-							}

-							if (currentParadigm.equals(changedParadigm)) {

-								JOptionPane.showMessageDialog(frame, "Same Paradigm & Same Event-Chain.");

-								return ;

-							}

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

-								frame.remove(ecLabelArray[i]);

-								frame.remove(ecJTPArray[i]);

-							}

-						}

-					} 

-					/* If the selected Event-Chain is different to the previous one => Remove and Do Normal. */

-					else if (selectedECIndex != thisIndex) {

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

-							frame.remove(ecLabelArray[i]);

-							frame.remove(ecJTPArray[i]);

-						}

-						selectedECIndex = thisIndex;

-					}

-				}

-				selectedECIndex = thisIndex;

-				currentEC = currentECList.get(thisIndex);

-				currentTaskChain = e2e.getECTaskList(currentEC);

-				if (currentTaskChain.size() == 0 ) {

-					JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has no chain-element.");

-					txtField0.setText("Not Available.");

-					txtField1.setText("Not Available.");

-					txtField2.setText("Not Available.");

-					txtField3.setText("Not Available.");

-					txtField4.setText("Not Available.");

-					txtField5.setText("Not Available.");

-					txtField6.setText("Not Available.");

-					txtField7.setText("Not Available.");

-					list.removeAll();

-					list.add("Not Available.");

-					list_1.removeAll();

-					list_1.add("Not Available.");

-					list_2.removeAll();

-					list_2.add("Not Available.");

-					return ;

-				}

-				else if (currentTaskChain.size() > 14) {

-					JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has more than " + currentTaskChain.size() + " elements. (Limit: 14)\n");

-					txtField0.setText("Not Available.");

-					txtField1.setText("Not Available.");

-					txtField2.setText("Not Available.");

-					txtField3.setText("Not Available.");

-					txtField4.setText("Not Available.");

-					txtField5.setText("Not Available.");

-					txtField6.setText("Not Available.");

-					txtField7.setText("Not Available.");

-					list.removeAll();

-					list.add("Not Available.");

-					list_1.removeAll();

-					list_1.add("Not Available.");

-					list_2.removeAll();

-					list_2.add("Not Available.");

-					return ;

-				}

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

-					final Task task = currentTaskChain.get(i);

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

-						java.util.List<Task> puTaskList = puTaskListHM.get(j);

-						if (puTaskList.stream().filter(s -> s.equals(task)).collect(Collectors.toList()).size() != 0) {

-							final ProcessingUnit pu = currentPUList.get(j);

-							ecLabelArray[i] = new JLabel((i+1) + ": " + pu.getName() + " (" + pu.getDefinition().getName() + ")");

-							ecJTPArray[i] = new JTextField();

-							ecJTPArray[i].setText(task.getName());

-							ecJTPArray[i].setEditable(false);

-							if (i < 7) {

-								ecLabelArray[i].setBounds(750, (604+(50*i)), 187, 16);

-								ecJTPArray[i].setBounds(750, (624+(50*i)), 187, 22);

-							} else {

-								ecLabelArray[i].setBounds(950, (604+(50*(i-7))), 187, 16);

-								ecJTPArray[i].setBounds(950, (624+(50*(i-7))), 187, 22);

-							}

-							frame.getContentPane().add(ecLabelArray[i]);

-							frame.getContentPane().add(ecJTPArray[i]);

-							break;

-						}

-					}

-				}

-				

-				/* Calculation Part */

-				if (currentModel == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");

-					return ;

-				} else if (ecComboBox.getSelectedItem() == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");

-					return ;

-				} else if (currentIA == null) {

-					JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been entered.");

-					return ;

-				}

-				if (list.getItemCount() > 0) {

-					list.removeAll();

-					list_1.removeAll();

-					list_2.removeAll();

-				}

-				/* Sometimes the same task can not be schedulable in the implicit communication due to the LocalCopy cost time */

-				Time rctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				Time rctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				Time ageWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				Time ageBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				Time eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				Time eRctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-				

-				/* PARADIGM */

-				if (rdbtnDirect.isSelected()) {

-					currentParadigm = ComParadigm.DIRECT;

-					rctWC = e2e.getTCReactionWC(currentEC, currentParadigm, cpurta);

-					rctBC = e2e.getTCReactionBC(currentEC, currentParadigm, cpurta);

-					ageWC = e2e.getTaskChainAge(currentEC, TimeType.WCET, currentParadigm, cpurta);

-					ageBC = e2e.getTaskChainAge(currentEC, TimeType.BCET, currentParadigm, cpurta);

-					eRctWC = e2e.getEarlyReaction(currentEC, TimeType.WCET, currentParadigm, cpurta);

-					eRctBC = e2e.getEarlyReaction(currentEC, TimeType.BCET, currentParadigm, cpurta);

-				} else if (rdbtnImplicit.isSelected()) {

-					currentParadigm = ComParadigm.IMPLICIT;

-					rctWC = e2e.getTCReactionWC(currentEC, currentParadigm, cpurta);

-					rctBC = e2e.getTCReactionBC(currentEC, currentParadigm, cpurta);

-					ageWC = e2e.getTaskChainAge(currentEC, TimeType.WCET, currentParadigm, cpurta);

-					ageBC = e2e.getTaskChainAge(currentEC, TimeType.BCET, currentParadigm, cpurta);

-					eRctWC = e2e.getEarlyReaction(currentEC, TimeType.WCET, currentParadigm, cpurta);

-					eRctBC = e2e.getEarlyReaction(currentEC, TimeType.BCET, currentParadigm, cpurta);

-				}

-				if (rctWC.getValue().equals(BigInteger.ZERO)) {

-					txtField0.setText("Not Schedulable (LocalCopy Cost)");

-				} else {

-					txtField0.setText("" + rctWC);

-				}

-				if (rctBC.getValue().equals(BigInteger.ZERO)) {

-					txtField1.setText("Not Schedulable (LocalCopy Cost)");

-				} else {

-					txtField1.setText("" + rctBC);

-				}

-				txtField2.setText("" + e2e.getLetReactionWC(currentEC, cpurta));

-				txtField3.setText("" + e2e.getLetReactionBC(currentEC, cpurta));

-				txtField4.setText("" + ageWC);

-				txtField5.setText("" + ageBC);

-				if (eRctWC.getValue().equals(BigInteger.ZERO)) {

-					txtField6.setText("Not Schedulable (LocalCopy Cost)");

-				} else {

-					txtField6.setText("" + eRctWC);

-				}

-				if (eRctBC.getValue().equals(BigInteger.ZERO)) {

-					txtField7.setText("Not Schedulable (LocalCopy Cost)");

-				} else {

-					txtField7.setText("" + eRctBC);

-				}

-				final EList<Label> labelList = currentModel.getSwModel().getLabels();

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

-					Time datAgeLatWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-					Time datAgeLatBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);

-					datAgeLatWC = e2e.getDataAge(labelList.get(i), currentEC, TimeType.WCET, currentParadigm, cpurta);

-					datAgeLatBC = e2e.getDataAge(labelList.get(i), currentEC, TimeType.BCET, currentParadigm, cpurta);

-					if (datAgeLatWC != null && datAgeLatBC != null) {

-						list.add(labelList.get(i).getName());

-						list_1.add(datAgeLatWC + "");

-						list_2.add(datAgeLatBC + "");

-					}

-				}

-				frame.revalidate();

-				frame.repaint();

-			}

-		});

-		ecSelect.setBounds(356, 569, 90, 25);

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

-		

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

-		btnNewButton_1.addActionListener(new ActionListener() {

-			public void actionPerformed(ActionEvent e) {

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

-					ecLabelArray[i].setText(null);

-					frame.remove(ecLabelArray[i]);

-					ecJTPArray[i].setText(null);

-					frame.remove(ecJTPArray[i]);

-				}

-				selectedECIndex = -1;

-				currentParadigm = null;

-				txtField0.setText("");

-				txtField1.setText("");

-				txtField2.setText("");

-				txtField3.setText("");

-				txtField4.setText("");

-				txtField5.setText("");

-				txtField6.setText("");

-				txtField7.setText("");

-				paradigmMode.setSelected(null, false);

-				list.removeAll();

-				list_1.removeAll();

-				list_2.removeAll();

-				frame.revalidate();

-				frame.repaint();

-			}

-		});

-		btnNewButton_1.setBounds(445, 569, 70, 25);

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

-		

-		JLabel lblTaskChain_1 = new JLabel("Task Chain >");

-		lblTaskChain_1.setFont(new Font("Segoe UI Emoji", Font.BOLD, 13));

-		lblTaskChain_1.setBounds(646, 605, 90, 16);

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

-		

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

-		lblApprta.setForeground(Color.DARK_GRAY);

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

-		lblApprta.setBounds(1050, 1, 120, 34);

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

-		

-		JSeparator separator = new JSeparator();

-		separator.setBounds(10, 557, 1160, 2);

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

-	}

+/*******************************************************************************
+ * Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors: Junhyung Ki - initial API and implementation
+ * 
+ *******************************************************************************/
+package org.eclipse.app4mc.gsoc_rta.ui;
+
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.List;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.stream.Collectors;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.eclipse.app4mc.amalthea.model.Amalthea;
+import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
+import org.eclipse.app4mc.amalthea.model.EventChain;
+import org.eclipse.app4mc.amalthea.model.Label;
+import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
+import org.eclipse.app4mc.amalthea.model.PuType;
+import org.eclipse.app4mc.amalthea.model.Task;
+import org.eclipse.app4mc.amalthea.model.Time;
+import org.eclipse.app4mc.amalthea.model.TimeUnit;
+import org.eclipse.app4mc.amalthea.model.io.AmaltheaLoader;
+import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
+import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
+import org.eclipse.app4mc.gsoc_rta.*;
+import org.eclipse.app4mc.gsoc_rta.SharedConsts.ComParadigm;
+import org.eclipse.emf.common.util.EList;
+import javax.swing.SwingConstants;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.JSeparator;
+
+/**
+ * Date: August 21-2019 
+ * @author Junhyung Ki
+ * @version 1.0
+ *					The purpose of this class is to provide users a better visual and increase usability of Response Time Analysis.
+ */
+@SuppressWarnings("serial")
+public class APP4RTA extends JFrame {
+	private static JComboBox<String> ecComboBox = new JComboBox<String>();
+	
+	private CPURta cpurta = new CPURta(false);
+	private E2ELatency e2e = new E2ELatency();
+	private Amalthea currentModel = null;
+	private java.util.List<ProcessingUnit> currentPUList = null;
+	private int[] currentIA = null;
+	private EList<Task> allTaskList = null;
+	private EList<EventChain> currentECList = null;
+	private EventChain currentEC = null;
+	private java.util.List<Task> currentTaskChain = null;
+	private File currentFile = null;
+	
+	private HashMap<Integer, java.util.List<Task>> puTaskListHM;
+	private JFrame frame;
+	private int selectedECIndex = -1;
+	private boolean schedulability_flag = false;
+	private ComParadigm currentParadigm = null;
+	JFileChooser fileChooser;
+	JTextField selectedModelLbl;
+	
+	private JLabel jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10, 
+		jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19;
+	private JTextField tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9, 
+		tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19;
+	private JLabel[] jLabelArray = {
+			jl0, jl1, jl2, jl3, jl4, jl5, jl6, jl7, jl8, jl9, jl10, 
+			jl11, jl12, jl13, jl14, jl15, jl16, jl17, jl18, jl19
+	};
+	private JTextField[] jTextFieldArray= {
+			tf0, tf1, tf2, tf3, tf4, tf5, tf6, tf7, tf8, tf9, 
+			tf10, tf11, tf12, tf13, tf14, tf15, tf16, tf17, tf18, tf19
+	};
+	
+	private JLabel jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7;
+	private JLabel jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h;
+	private List l0, l1, l2, l3, l4, l5, l6, l7;
+	private List rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7;
+	private JLabel[] puLabelArray = {
+			jl_0, jl_1, jl_2, jl_3, jl_4, jl_5, jl_6, jl_7
+	};
+	private JLabel[] rtListLabelArray = {
+			jl_a, jl_b, jl_c, jl_d, jl_e, jl_f, jl_g, jl_h
+	};
+	private List[] puListArray = {
+			l0, l1, l2, l3, l4, l5, l6, l7
+	};
+	private List[] rtListArray = {
+			rtL0, rtL1, rtL2, rtL3, rtL4, rtL5, rtL6, rtL7
+	};
+	
+	private JLabel ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6, 
+		ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13;
+	private JTextField jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,
+		jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13;
+	private JLabel[] ecLabelArray = {
+			ecL0, ecL1, ecL2, ecL3, ecL4, ecL5, ecL6,
+			ecL7, ecL8, ecL9, ecL10, ecL11, ecL12, ecL13
+	};
+	private JTextField[] ecJTPArray = {
+			jtf0, jtf1, jtf2, jtf3, jtf4, jtf5, jtf6,
+			jtf7, jtf8, jtf9, jtf10, jtf11, jtf12, jtf13
+	};
+	
+	private List list, list_1, list_2;
+
+	public static void main(String[] args) {
+		EventQueue.invokeLater(new Runnable() {
+			public void run() {
+				org.apache.log4j.BasicConfigurator.configure();
+				Logger.getRootLogger().setLevel(Level.ERROR);
+				final APP4RTA window = new APP4RTA();
+				window.frame.setVisible(true);
+				window.frame.setTitle("APP4RTA");
+			}
+		});
+	}
+
+	public APP4RTA() {
+		initialize();
+	}
+	
+	private void initialize() {
+		frame = new JFrame();
+		frame.getContentPane().setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		frame.setBounds(0, 31, 1200, 1027);
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+		frame.getContentPane().setLayout(null);
+		
+		JLabel lblSelectTheModel = new JLabel("Amalthea Model");
+		lblSelectTheModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));
+		lblSelectTheModel.setBounds(10, 13, 120, 22);
+		frame.getContentPane().add(lblSelectTheModel);
+		
+		JLabel lblTaskName = new JLabel("Task Name");
+		lblTaskName.setForeground(new Color(139, 0, 0));
+		lblTaskName.setFont(new Font("Sitka Heading", Font.BOLD, 12));
+		lblTaskName.setHorizontalAlignment(SwingConstants.CENTER);
+		lblTaskName.setBounds(15, 43, 70, 16);
+		frame.getContentPane().add(lblTaskName);
+		
+		JLabel lblPuNum = new JLabel("PU Num");
+		lblPuNum.setForeground(new Color(0, 0, 255));
+		lblPuNum.setHorizontalAlignment(SwingConstants.CENTER);
+		lblPuNum.setFont(new Font("Sitka Heading", Font.BOLD, 12));
+		lblPuNum.setBounds(92, 43, 70, 16);
+		frame.getContentPane().add(lblPuNum);
+		
+		JButton btnDefualtIa = new JButton("Defualt IA");
+		btnDefualtIa.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent arg0) {
+				if (cpurta.getModel() == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: A model is not loaded.");
+					return ;
+				} else if (cpurta.getTRT() == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: TRT HashMap is not loaded.");
+					return ;
+				} else if (cpurta.getPUl().size() == 0) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Processing Unit List is not loaded.");
+					return ;
+				}
+				final int[] defaultIA = SharedConsts.defaultIAMapping;
+				if (cpurta.getModel().getSwModel().getTasks().size() == defaultIA.length) {
+					for (int i = 0; i < defaultIA.length; i++) {
+						jTextFieldArray[i].setText("" + defaultIA[i]);
+					}
+					return ;
+				} else if (currentPUList.size() == 1) {
+					final int numOfTasks = cpurta.getModel().getSwModel().getTasks().size();
+					for (int i = 0; i < numOfTasks; i++) {
+						jTextFieldArray[i].setText("0");
+					}
+					return ;
+				}
+				String str = "";
+				for (int i = 0; i < currentPUList.size(); i++) {
+					if (i == currentPUList.size() - 1) {
+						str = str + i; 
+						break;
+					}
+					str = str + i + ", ";
+				}
+				JOptionPane.showMessageDialog(frame, "ERROR: The length of the default integer array does not match with\n"
+						+ "the number of tasks in the target model.\n\n" + "Please assign the number(s) manually.\n" 
+						+ "Available PU number(s): " + str);
+			}
+		});
+		
+		JButton btnEnterIA = new JButton("Enter IA");
+		btnEnterIA.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				currentIA = new int[cpurta.getModel().getSwModel().getTasks().size()];
+				for (int i = 0; i < allTaskList.size(); i++) {
+					if (jTextFieldArray[i].getText().length() == 0) {
+						JOptionPane.showMessageDialog(frame, "ERROR: Fill the rest of the array!");
+						return ;
+					} else if (jTextFieldArray[i].getText().charAt(0) < 48 || jTextFieldArray[i].getText().charAt(0) > 54) {
+						JOptionPane.showMessageDialog(frame, "ERROR: Wrong array value!");
+						return ;
+					} else if (i >= 0 && i <= 9 && Integer.parseInt(jTextFieldArray[i].getText()) == 6) {
+						JOptionPane.showMessageDialog(frame, "ERROR: CPU Tasks should not be mapped to GPU! \n\n"
+								+ "Please assign different IA value for " + "(" + allTaskList.get(i).getName() + ")");
+						return ;
+					} else if (i == jTextFieldArray.length-1 && Integer.parseInt(jTextFieldArray[i].getText()) != 6) {
+						JOptionPane.showMessageDialog(frame, "ERROR: 'Detection' task can not be mapped to CPU!");
+						return ;
+					}
+					currentIA[i] = Integer.parseInt(jTextFieldArray[i].getText());
+				}
+				cpurta.setIA(currentIA);
+				cpurta.setContention(currentIA, currentModel);
+				puTaskListHM = cpurta.getPUTaskListHashMap(currentModel);
+				for (int i = 0; i < puTaskListHM.size(); i++) {
+					if (puListArray[i].getItemCount() == 0) {
+						for (int j = 0; j < puTaskListHM.get(i).size(); j++) {	
+							puListArray[i].add((puTaskListHM.get(i).get(j)).getName());
+						}
+					}
+				}
+			}
+		});
+		
+		JRadioButton rdbtnSynchronous = new JRadioButton("Synchronous");
+		rdbtnSynchronous.setForeground(new Color(139, 0, 0));
+		rdbtnSynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		
+		JRadioButton rdbtnAsynchronous = new JRadioButton("Asynchronous");
+		rdbtnAsynchronous.setForeground(new Color(0, 0, 255));
+		rdbtnAsynchronous.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		
+		ButtonGroup offloadingMode = new ButtonGroup();
+		offloadingMode.add(rdbtnSynchronous);
+		offloadingMode.add(rdbtnAsynchronous);
+		
+		JRadioButton rdbtnWorstCase = new JRadioButton("Worst-Case");
+		rdbtnWorstCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		rdbtnWorstCase.setForeground(Color.DARK_GRAY);
+		
+		JRadioButton rdbtnAverageCase = new JRadioButton("Average-Case");
+		rdbtnAverageCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		rdbtnAverageCase.setForeground(Color.DARK_GRAY);
+		
+		JRadioButton rdbtnBestCase = new JRadioButton("Best-Case");
+		rdbtnBestCase.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		rdbtnBestCase.setForeground(Color.DARK_GRAY);
+
+		ButtonGroup executionMode = new ButtonGroup();
+		executionMode.add(rdbtnWorstCase);
+		executionMode.add(rdbtnAverageCase);
+		executionMode.add(rdbtnBestCase);
+		
+		JLabel lblSchedulability = new JLabel("Schedulability");
+		JTextField schedulability = new JTextField();
+		schedulability.setHorizontalAlignment(SwingConstants.RIGHT);
+		schedulability.setEditable(false);
+		
+		JLabel lblMemAccCost = new JLabel("Cumulated Memory-Access Cost");
+		JTextField memAccCost = new JTextField();
+		memAccCost.setHorizontalAlignment(SwingConstants.RIGHT);
+		memAccCost.setEditable(false);
+		
+		JLabel lblCumulContention = new JLabel("Cumulated Contention");
+		JTextField cumulContention = new JTextField();
+		cumulContention.setHorizontalAlignment(SwingConstants.RIGHT);
+		cumulContention.setEditable(false);
+		
+		JLabel lblComputation = new JLabel("Computation");
+		JTextField computation = new JTextField();
+		computation.setHorizontalAlignment(SwingConstants.RIGHT);
+		computation.setEditable(false);
+		
+		JLabel lblResponseTimeSum = new JLabel("Response Time Sum");
+		JTextField rtSum = new JTextField();
+		rtSum.setHorizontalAlignment(SwingConstants.RIGHT);
+		rtSum.setEditable(false);
+		
+		JButton btnCalculate = new JButton("Calculate");
+		btnCalculate.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent arg0) {
+				for (int i = 0; i < allTaskList.size(); i++) {
+					if (jTextFieldArray[i].getText().length() == 0) {
+						JOptionPane.showMessageDialog(frame, "ERROR: Fill the array first!");
+						return ;
+					}
+				}				
+				if (rdbtnSynchronous.isSelected()) {
+					SharedConsts.synchronousOffloading = true;
+				} else if (rdbtnAsynchronous.isSelected()) {
+					SharedConsts.synchronousOffloading = false;
+				} else {
+					JOptionPane.showMessageDialog(frame, "ERROR: You should choose an offloading mode! (Sync / Async)");
+					return ;
+				}
+				if (rdbtnWorstCase.isSelected()) {
+					SharedConsts.timeType = TimeType.WCET;
+				} else if (rdbtnAverageCase.isSelected()) {
+					SharedConsts.timeType = TimeType.ACET;
+				} else if (rdbtnBestCase.isSelected()) {
+					SharedConsts.timeType = TimeType.BCET;
+				} else {
+					JOptionPane.showMessageDialog(frame, "ERROR: You should choose an execution case! (Worst Case / Average Case / Best Case)");
+					return ;
+				}
+				if (currentIA == null || puTaskListHM.size() == 0) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Click the 'Enter IA' button.");
+					return ;
+				}
+				schedulability_flag = true;
+				Time pRtSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				for (int i = 0; i < puTaskListHM.size(); i++) {
+					final ProcessingUnit pu = cpurta.getPUl().get(i);
+					final java.util.List<Task> thisPUTaskList = puTaskListHM.get(i);
+					Time thisRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					if (rtListArray[i].getItemCount() == 0) {
+						if (pu.getDefinition().getPuType().equals(PuType.CPU)) {
+							for (Task t : thisPUTaskList) {
+								thisRT = cpurta.preciseTestCPURT(t, thisPUTaskList, SharedConsts.timeType, pu);
+								final Time thisPeriod = CommonUtils.getStimInTime(t);
+								final BigInteger period = AmaltheaServices.convertToPicoSeconds(thisPeriod);
+								if (AmaltheaServices.convertToPicoSeconds(thisRT).compareTo(period) > 0) {
+									rtListArray[i].add("Non Scheduleable! => MAX Value");
+									schedulability_flag = false;
+								} else if (AmaltheaServices.convertToPicoSeconds(thisRT).equals(BigInteger.ZERO)) {
+									rtListArray[i].add("0 ps (GPU Task on CPU)");
+								} else {
+									rtListArray[i].add(thisRT.toString());
+								}
+								pRtSum = pRtSum.add(thisRT);
+							}
+						} else {
+							for (Task t : thisPUTaskList) {
+								thisRT = cpurta.getTRT().get(t);
+								rtListArray[i].add(thisRT.toString());
+								pRtSum = pRtSum.add(thisRT);
+							}
+						}
+					}
+				}
+				if (schedulability_flag) {
+					schedulability.setText("Scheduleable! :)");
+					memAccCost.setText("" + cpurta.getCumulatedMemAccCosts());
+					cumulContention.setText("" + cpurta.getCumulatedContention());
+					computation.setText("" + (pRtSum.subtract(cpurta.getCumulatedMemAccCosts())).subtract(cpurta.getCumulatedContention()));
+					rtSum.setText(pRtSum.toString());
+				} else {
+					schedulability.setText("Non Scheduleable! :(");
+					memAccCost.setText("Not Available.");
+					cumulContention.setText("Not Available.");
+					computation.setText("Not Available.");
+					rtSum.setText("Not Available.");
+				}
+			}
+		});
+		
+		JButton btnReset = new JButton("Reset");
+		btnReset.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				currentIA = null;
+				cpurta.setIA(currentIA);
+				cpurta.setContention(currentIA, currentModel);
+				/* latency time initializing */
+				cpurta.initCumulatedMemAccCosts();
+				cpurta.initCumulatedContention();
+				for (int i = 0; i < allTaskList.size(); i++) {
+					jTextFieldArray[i].setText("");
+				}
+				for (int i = 0; i < currentPUList.size(); i++) {
+					puListArray[i].removeAll();
+				}
+				for (int i = 0; i < currentPUList.size(); i++) {
+					rtListArray[i].removeAll();
+				}
+				offloadingMode.setSelected(null, false);
+				executionMode.setSelected(null, false);
+				schedulability.setText(null);
+				memAccCost.setText(null);
+				cumulContention.setText(null);
+				computation.setText(null);
+				rtSum.setText(null);
+				currentIA = null;
+				puTaskListHM = null;
+				frame.revalidate();
+				frame.repaint();
+			}
+		});
+
+		selectedModelLbl = new JTextField();
+		selectedModelLbl.setEditable(false);
+		selectedModelLbl.setBounds(142, 13, 206, 22);
+		frame.getContentPane().add(selectedModelLbl);
+		selectedModelLbl.setColumns(10);
+		
+		JButton amaltheaSchBtn = new JButton("Search Amalthea");
+		amaltheaSchBtn.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				final String userDirLocation = System.getProperty("user.dir");
+				File userDir = new File(userDirLocation);
+				fileChooser = new JFileChooser(userDir);
+				fileChooser.setAcceptAllFileFilterUsed(false);
+		        FileNameExtensionFilter filter = new FileNameExtensionFilter("Amalthea models", "amxmi");
+		        fileChooser.addChoosableFileFilter(filter);
+		        fileChooser.setDialogTitle("Open File");
+		        int result = fileChooser.showOpenDialog(null);
+		        if (result == JFileChooser.APPROVE_OPTION) {
+		        	final Amalthea loadedModel = AmaltheaLoader.loadFromFile(fileChooser.getSelectedFile());
+		        	if (loadedModel.getVersion().compareTo("0.9.5") != 0) {
+		        		JOptionPane.showMessageDialog(frame, "Error: This model should be migrated to the version 0.9.4");
+		        		return ;
+		        	}
+		        	/* Something was selected before */
+		        	if (currentFile != null) {
+		        		/* The selected file is equal to the previous file => Do nothing */
+		        		if (fileChooser.getSelectedFile().equals(currentFile)) {
+		        			JOptionPane.showMessageDialog(frame, "Same Model");
+		        			return ;
+		        		}
+		        		/* If the selected file is different to the previous one => Remove and Do Normal. */
+		        		else {
+		        			schedulability.setText(null);
+		    				memAccCost.setText(null);
+		    				cumulContention.setText(null);
+		    				computation.setText(null);
+		    				rtSum.setText(null);
+		        			for (int i = 0; i < allTaskList.size(); i++) {
+								frame.remove(jLabelArray[i]);
+								frame.remove(jTextFieldArray[i]);
+							}
+							frame.remove(btnDefualtIa);
+							frame.remove(btnEnterIA);
+							frame.remove(rdbtnSynchronous);
+							frame.remove(rdbtnAsynchronous);
+							frame.remove(rdbtnWorstCase);
+							frame.remove(rdbtnAverageCase);
+							frame.remove(rdbtnBestCase);
+							frame.remove(btnCalculate);
+							frame.remove(btnReset);
+							frame.remove(lblSchedulability);
+							frame.remove(schedulability);
+							frame.remove(lblMemAccCost);
+							frame.remove(memAccCost);
+							frame.remove(lblCumulContention);
+							frame.remove(cumulContention);
+							frame.remove(lblComputation);
+							frame.remove(computation);
+							frame.remove(lblResponseTimeSum);
+							frame.remove(rtSum);
+							for (int i = 0; i < currentPUList.size(); i++) {
+								frame.remove(puLabelArray[i]);
+								frame.remove(rtListLabelArray[i]);
+								frame.remove(puListArray[i]);
+								frame.remove(rtListArray[i]);
+							}
+							frame.remove(ecComboBox);
+		        		}
+		        	}
+		        	/* Something was not selected before => Do normal */
+		        	currentFile = fileChooser.getSelectedFile();
+		        	selectedModelLbl.setText(currentFile.getName());
+		        	currentModel = loadedModel;
+					currentPUList = CommonUtils.getPUs(currentModel);
+					if (currentPUList.get(0).getAccessElements().size() == 0) {
+						JOptionPane.showMessageDialog(frame, "The selected model's processing unit(s) does(do) not have 'read & write Latency' values.\n\n"
+								+ "Therefore, the default value of 30 will be assigned for them.\n"
+								+ "This will affect the response time results.");
+					}
+					cpurta.setModel(currentModel);
+					cpurta.setTRT(cpurta.getDefaultTRT(currentModel));
+					cpurta.setPUl(currentPUList);
+					allTaskList = currentModel.getSwModel().getTasks();
+					if (allTaskList.size() > 20) {
+						JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + allTaskList.size() + " Tasks. (Limit: 20)\n" 
+								+ "Please choose a different model.");
+						return ;
+					} else if (currentPUList.size() > 8) {
+						JOptionPane.showMessageDialog(frame, "ERROR: The selected model has " + currentPUList.size() + " Processing Units. (Limit: 8)\n"
+								+ "Please choose a different model.");
+						return ;
+					}
+					/* Task Indices */
+					for (int i = 0; i < allTaskList.size(); i++) {
+						jLabelArray[i] = new JLabel(allTaskList.get(i).getName());
+						jLabelArray[i].setBounds(12, (60+(i*24)), 97, 16);
+						frame.getContentPane().add(jLabelArray[i]);
+						jTextFieldArray[i] = new JTextField();
+						jTextFieldArray[i].setColumns(10);
+						jTextFieldArray[i].setBounds(118, (60+(i*24)), 22, 22);
+						frame.getContentPane().add(jTextFieldArray[i]);
+					}
+					/* DefaultIA Button */
+					btnDefualtIa.setBounds(155, 60, 97, 25);
+					frame.getContentPane().add(btnDefualtIa);
+					/* EnterIA Button */
+					btnEnterIA.setBounds(155, 90, 97, 25);
+					frame.getContentPane().add(btnEnterIA);
+					/* Sync Radio Button */
+					rdbtnSynchronous.setBounds(152, 125, 126, 25);
+					frame.getContentPane().add(rdbtnSynchronous);
+					/* Async Radio Button */
+					rdbtnAsynchronous.setBounds(152, 145, 126, 25);
+					frame.getContentPane().add(rdbtnAsynchronous);
+					/* WorstCase Radio Button */
+					rdbtnWorstCase.setBounds(152, 175, 107, 25);
+					frame.getContentPane().add(rdbtnWorstCase);
+					/* AverageCase Radio Button */
+					rdbtnAverageCase.setBounds(152, 195, 107, 25);
+					frame.getContentPane().add(rdbtnAverageCase);
+					/* BestCase Radio Button */
+					rdbtnBestCase.setBounds(152, 215, 107, 25);
+					frame.getContentPane().add(rdbtnBestCase);
+					/* Calculate Button */
+					btnCalculate.setBounds(155, 252, 97, 25);
+					frame.getContentPane().add(btnCalculate);
+					/* Reset Button */
+					btnReset.setBounds(155, 282, 97, 25);
+					frame.getContentPane().add(btnReset);
+					/* Schedulability Label & TextField */
+					lblSchedulability.setBounds(157, 323, 200, 16);
+					frame.getContentPane().add(lblSchedulability);
+					schedulability.setBounds(155, 343, 200, 22);
+					frame.getContentPane().add(schedulability);
+					/* MemAccCost Label & TextField */
+					lblMemAccCost.setBounds(157, 368, 200, 16);
+					frame.getContentPane().add(lblMemAccCost);
+					memAccCost.setBounds(155, 388, 200, 22);
+					frame.getContentPane().add(memAccCost);
+					/* CumulContention Label & TextField */
+					lblCumulContention.setBounds(157, 413, 200, 16);
+					frame.getContentPane().add(lblCumulContention);
+					cumulContention.setBounds(155, 433, 200, 22);
+					frame.getContentPane().add(cumulContention);
+					/* Computation */
+					lblComputation.setBounds(157, 458, 200, 16);
+					frame.getContentPane().add(lblComputation);
+					computation.setBounds(155, 478, 200, 22);
+					frame.getContentPane().add(computation);
+					/* ResponseTime Sum Label & TextField */
+					lblResponseTimeSum.setBounds(157, 503, 200, 16);
+					frame.getContentPane().add(lblResponseTimeSum);
+					rtSum.setBounds(155, 523, 200, 22);
+					frame.getContentPane().add(rtSum);
+					/* PU & RT Lists */
+					for (int i = 0; i < currentPUList.size(); i++) {
+						puLabelArray[i] = new JLabel(i +": " + currentPUList.get(i).getDefinition().getName());
+						rtListLabelArray[i] = new JLabel("Response Time");
+						puListArray[i] = new List();
+						rtListArray[i] = new List();
+						if (i >= 0 && i < 4) {
+							puLabelArray[i].setBounds((387+(i*200)), 50, 87, 22);
+							rtListLabelArray[i].setBounds((474+(i*200)), 50, 88, 22);
+							puListArray[i].setBounds((385+(i*200)), 75, 87, 145);
+							rtListArray[i].setBounds((475+(i*200)), 75, 87, 145);
+						} else if (i >= 4) {
+							puLabelArray[i].setBounds((387+((i-4)*200)), 225, 87, 22);
+							rtListLabelArray[i].setBounds((474+((i-4)*200)), 225, 88, 22);
+							puListArray[i].setBounds((385+((i-4)*200)), 250, 87, 145);
+							rtListArray[i].setBounds((475+((i-4)*200)), 250, 87, 145);
+						}
+						frame.getContentPane().add(puLabelArray[i]);
+						frame.getContentPane().add(rtListLabelArray[i]);
+						frame.getContentPane().add(puListArray[i]);
+						frame.getContentPane().add(rtListArray[i]);
+					}
+					/* E2ELatency Part */
+					currentECList = currentModel.getConstraintsModel().getEventChains();
+					if (currentECList.size() != 0) {
+						final String[] ecComboArray = new String[currentECList.size()];
+						for (int i = 0; i < currentECList.size(); i++) {
+							ecComboArray[i] = currentECList.get(i).getName();
+						}
+						ecComboBox = new JComboBox<String>(ecComboArray);
+						ecComboBox.setBounds(150, 570, 206, 22);
+						frame.getContentPane().add(ecComboBox);
+						ecComboBox.setSelectedItem(null);
+					} else {
+						JOptionPane.showMessageDialog(frame, "WARNING: The selected model has no Event-Chain.\n"
+								+ "End-to-End Event-Chain Latency Calculation is impossible with this model.");
+						// TODO: Something needs to be done here to prevent E2ELatency calculation.
+					}
+					frame.revalidate();
+					frame.repaint();
+		        }
+			}
+		});
+		amaltheaSchBtn.setBounds(348, 12, 133, 24);
+		frame.getContentPane().add(amaltheaSchBtn);
+
+		JLabel lblEventChainModel = new JLabel("EVENT CHAIN MODEL");
+		lblEventChainModel.setFont(new Font("Stencil BT", Font.PLAIN, 13));
+		lblEventChainModel.setBounds(10, 570, 136, 22);
+		frame.getContentPane().add(lblEventChainModel);
+		
+		JRadioButton rdbtnDirect = new JRadioButton("Direct");
+		rdbtnDirect.setForeground(new Color(139, 0, 0));
+		rdbtnDirect.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		rdbtnDirect.setBounds(530, 569, 70, 25);
+		frame.getContentPane().add(rdbtnDirect);
+		
+		JRadioButton rdbtnImplicit = new JRadioButton("Implicit");
+		rdbtnImplicit.setForeground(new Color(0, 0, 255));
+		rdbtnImplicit.setFont(new Font("Sitka Heading", Font.BOLD, 13));
+		rdbtnImplicit.setBounds(596, 569, 79, 25);
+		frame.getContentPane().add(rdbtnImplicit);
+		
+		ButtonGroup paradigmMode = new ButtonGroup();
+		paradigmMode.add(rdbtnDirect);
+		paradigmMode.add(rdbtnImplicit);
+		
+		JLabel lblNewLabel = new JLabel("Direct & Implicit Communication Paradigm");
+		lblNewLabel.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblNewLabel.setBounds(10, 605, 293, 16);
+		frame.getContentPane().add(lblNewLabel);
+		
+		JLabel lblWorstcaseReaction = new JLabel("WC Reaction");
+		lblWorstcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWorstcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWorstcaseReaction.setBounds(10, 627, 90, 16);
+		frame.getContentPane().add(lblWorstcaseReaction);
+		
+		JTextField txtField0 = new JTextField();
+		txtField0.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField0.setBounds(103, 625, 200, 22);
+		txtField0.setEditable(false);
+		frame.getContentPane().add(txtField0);
+		
+		JLabel lblBestcaseReaction = new JLabel("BC Reaction");
+		lblBestcaseReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBestcaseReaction.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBestcaseReaction.setBounds(10, 656, 90, 16);
+		frame.getContentPane().add(lblBestcaseReaction);
+		
+		JTextField txtField1 = new JTextField();
+		txtField1.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField1.setBounds(103, 654, 200, 22);
+		txtField1.setEditable(false);
+		frame.getContentPane().add(txtField1);
+		
+		JLabel lblLetCommunicationParadigm = new JLabel("LET Communication Paradigm");
+		lblLetCommunicationParadigm.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblLetCommunicationParadigm.setBounds(10, 688, 193, 16);
+		frame.getContentPane().add(lblLetCommunicationParadigm);
+		
+		JLabel lblWcReaction = new JLabel("WC Reaction");
+		lblWcReaction.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWcReaction.setBounds(10, 710, 90, 16);
+		frame.getContentPane().add(lblWcReaction);
+		
+		JTextField txtField2 = new JTextField();
+		txtField2.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField2.setBounds(103, 708, 200, 22);
+		txtField2.setEditable(false);
+		frame.getContentPane().add(txtField2);
+		
+		JLabel lblBcReaction = new JLabel("BC Reaction");
+		lblBcReaction.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBcReaction.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBcReaction.setBounds(10, 739, 90, 16);
+		frame.getContentPane().add(lblBcReaction);
+		
+		JTextField txtField3 = new JTextField();
+		txtField3.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField3.setBounds(103, 737, 200, 22);
+		txtField3.setEditable(false);
+		frame.getContentPane().add(txtField3);
+		
+		JLabel lblTaskChain = new JLabel("Task Chain Age (Direct & Implicit)");
+		lblTaskChain.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblTaskChain.setBounds(338, 605, 222, 16);
+		frame.getContentPane().add(lblTaskChain);
+		
+		JLabel lblWcAge = new JLabel("WC Age");
+		lblWcAge.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWcAge.setBounds(350, 627, 58, 16);
+		frame.getContentPane().add(lblWcAge);
+		
+		JTextField txtField4 = new JTextField();
+		txtField4.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField4.setBounds(413, 625, 200, 22);
+		txtField4.setEditable(false);
+		frame.getContentPane().add(txtField4);
+		
+		JLabel lblBcAge = new JLabel("BC Age");
+		lblBcAge.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBcAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBcAge.setBounds(350, 656, 58, 16);
+		frame.getContentPane().add(lblBcAge);
+		
+		JTextField txtField5 = new JTextField();
+		txtField5.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField5.setBounds(413, 654, 200, 22);
+		txtField5.setEditable(false);
+		frame.getContentPane().add(txtField5);
+		
+		JLabel lblEarlyReaction = new JLabel("Early Reaction (Direct & Implicit)");
+		lblEarlyReaction.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblEarlyReaction.setBounds(338, 688, 232, 16);
+		frame.getContentPane().add(lblEarlyReaction);
+		
+		JLabel lblWcErct = new JLabel("WC E-Rct");
+		lblWcErct.setHorizontalAlignment(SwingConstants.CENTER);
+		lblWcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWcErct.setBounds(338, 710, 70, 16);
+		frame.getContentPane().add(lblWcErct);
+		
+		JTextField txtField6 = new JTextField();
+		txtField6.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField6.setBounds(413, 708, 200, 22);
+		txtField6.setEditable(false);
+		frame.getContentPane().add(txtField6);
+		
+		JLabel lblBcErct = new JLabel("BC E-Rct");
+		lblBcErct.setHorizontalAlignment(SwingConstants.CENTER);
+		lblBcErct.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBcErct.setBounds(338, 739, 70, 16);
+		frame.getContentPane().add(lblBcErct);
+		
+		JTextField txtField7 = new JTextField();
+		txtField7.setHorizontalAlignment(SwingConstants.RIGHT);
+		txtField7.setBounds(413, 737, 200, 22);
+		txtField7.setEditable(false);
+		frame.getContentPane().add(txtField7);
+		
+		JLabel lblDataAge = new JLabel("Data Age");
+		lblDataAge.setFont(new Font("Sitka Text", Font.BOLD | Font.ITALIC, 13));
+		lblDataAge.setBounds(10, 771, 58, 16);
+		frame.getContentPane().add(lblDataAge);
+		
+		JLabel lblContainedLabels = new JLabel("Contained Labels");
+		lblContainedLabels.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblContainedLabels.setBounds(10, 791, 136, 16);
+		frame.getContentPane().add(lblContainedLabels);
+		
+		list = new List();
+		list.setBounds(10, 810, 155, 160);
+		frame.getContentPane().add(list);
+		
+		JLabel lblWorstcaseAge = new JLabel("Worst-case Age");
+		lblWorstcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblWorstcaseAge.setBounds(177, 791, 136, 16);
+		frame.getContentPane().add(lblWorstcaseAge);
+		
+		list_1 = new List();
+		list_1.setBounds(177, 810, 155, 160);
+		frame.getContentPane().add(list_1);
+		
+		JLabel lblBestcaseAge = new JLabel("Best-case Age");
+		lblBestcaseAge.setFont(new Font("Sitka Small", Font.PLAIN, 13));
+		lblBestcaseAge.setBounds(344, 791, 136, 16);
+		frame.getContentPane().add(lblBestcaseAge);
+		
+		list_2 = new List();
+		list_2.setBounds(344, 810, 155, 160);
+		frame.getContentPane().add(list_2);
+		
+		JButton ecSelect = new JButton("Calculate");
+		ecSelect.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				if (currentModel == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");
+					return ;
+				} else if (currentECList == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Event-Chain List is empty somehow.");
+					return ;
+				} else if (currentECList.size() == 0) {
+					JOptionPane.showMessageDialog(frame, "ERROR: There is no Event-Chain in this model.");
+					return ;
+				} else if (ecComboBox.getSelectedItem() == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");
+					return ;
+				} else if (puTaskListHM == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been assigned.");
+					return ;
+				} else if (offloadingMode.getSelection() == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Choose an offloading mode. (Sync / Async)");
+					return ;
+				} else if (schedulability_flag == false) {
+					String offMode = null;
+					if (SharedConsts.synchronousOffloading == true) {
+						offMode = "Sync";
+					} else if (SharedConsts.synchronousOffloading == false) {
+						offMode = "Aync";
+					}
+					String tType = null;
+					if (SharedConsts.timeType.equals(TimeType.WCET)) {
+						tType = "WC";
+					} else if (SharedConsts.timeType.equals(TimeType.ACET)) {
+						tType = "AC";
+					} else if (SharedConsts.timeType.equals(TimeType.BCET)) {
+						tType = "BC";
+					}
+					String iaFeedback = "";
+					for (int i = 0; i < currentIA.length; i++) {
+						if (i == currentIA.length - 1) {
+							iaFeedback = iaFeedback + currentIA[i];
+						} else {
+							iaFeedback = iaFeedback + currentIA[i] + ", ";
+						}
+					}
+					JOptionPane.showMessageDialog(frame, "ERROR: The entered IA value is not schedulable with the current configuration.\n\n"
+							+ "Current Integer Arrary: { " + iaFeedback + " }\n\n"
+							+ "Current Configuration: Offloading Mode(" + offMode + "), ExecutionCase(" + tType + ")");
+					return ;
+				} else if (paradigmMode.getSelection() == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Choose a communication paradigm. (Direct / Implicit)");
+					return ;
+				}
+				final int thisIndex = ecComboBox.getSelectedIndex();
+				/* Something was selected before */
+				if (selectedECIndex != -1) {
+					/* If the selected Event-Chain is the same as before => Do Nothing */
+					if (selectedECIndex == thisIndex) {
+						if (currentParadigm != null) {
+							ComParadigm changedParadigm = null;
+							if (rdbtnDirect.isSelected()) {
+								changedParadigm = ComParadigm.DIRECT;
+							} else if (rdbtnImplicit.isSelected()) {
+								changedParadigm = ComParadigm.IMPLICIT;
+							}
+							if (currentParadigm.equals(changedParadigm)) {
+								JOptionPane.showMessageDialog(frame, "Same Paradigm & Same Event-Chain.");
+								return ;
+							}
+							for (int i = 0; i < currentTaskChain.size(); i++) {
+								frame.remove(ecLabelArray[i]);
+								frame.remove(ecJTPArray[i]);
+							}
+						}
+					} 
+					/* If the selected Event-Chain is different to the previous one => Remove and Do Normal. */
+					else if (selectedECIndex != thisIndex) {
+						for (int i = 0; i < currentTaskChain.size(); i++) {
+							frame.remove(ecLabelArray[i]);
+							frame.remove(ecJTPArray[i]);
+						}
+						selectedECIndex = thisIndex;
+					}
+				}
+				selectedECIndex = thisIndex;
+				currentEC = currentECList.get(thisIndex);
+				currentTaskChain = e2e.getECTaskList(currentEC);
+				if (currentTaskChain.size() == 0 ) {
+					JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has no chain-element.");
+					txtField0.setText("Not Available.");
+					txtField1.setText("Not Available.");
+					txtField2.setText("Not Available.");
+					txtField3.setText("Not Available.");
+					txtField4.setText("Not Available.");
+					txtField5.setText("Not Available.");
+					txtField6.setText("Not Available.");
+					txtField7.setText("Not Available.");
+					list.removeAll();
+					list.add("Not Available.");
+					list_1.removeAll();
+					list_1.add("Not Available.");
+					list_2.removeAll();
+					list_2.add("Not Available.");
+					return ;
+				}
+				else if (currentTaskChain.size() > 14) {
+					JOptionPane.showMessageDialog(frame, "ERROR: The selected Event-Chain has more than " + currentTaskChain.size() + " elements. (Limit: 14)\n");
+					txtField0.setText("Not Available.");
+					txtField1.setText("Not Available.");
+					txtField2.setText("Not Available.");
+					txtField3.setText("Not Available.");
+					txtField4.setText("Not Available.");
+					txtField5.setText("Not Available.");
+					txtField6.setText("Not Available.");
+					txtField7.setText("Not Available.");
+					list.removeAll();
+					list.add("Not Available.");
+					list_1.removeAll();
+					list_1.add("Not Available.");
+					list_2.removeAll();
+					list_2.add("Not Available.");
+					return ;
+				}
+				for (int i = 0; i < currentTaskChain.size(); i++) {
+					final Task task = currentTaskChain.get(i);
+					for (int j = 0; j < puTaskListHM.size(); j++) {
+						java.util.List<Task> puTaskList = puTaskListHM.get(j);
+						if (puTaskList.stream().filter(s -> s.equals(task)).collect(Collectors.toList()).size() != 0) {
+							final ProcessingUnit pu = currentPUList.get(j);
+							ecLabelArray[i] = new JLabel((i+1) + ": " + pu.getName() + " (" + pu.getDefinition().getName() + ")");
+							ecJTPArray[i] = new JTextField();
+							ecJTPArray[i].setText(task.getName());
+							ecJTPArray[i].setEditable(false);
+							if (i < 7) {
+								ecLabelArray[i].setBounds(750, (604+(50*i)), 187, 16);
+								ecJTPArray[i].setBounds(750, (624+(50*i)), 187, 22);
+							} else {
+								ecLabelArray[i].setBounds(950, (604+(50*(i-7))), 187, 16);
+								ecJTPArray[i].setBounds(950, (624+(50*(i-7))), 187, 22);
+							}
+							frame.getContentPane().add(ecLabelArray[i]);
+							frame.getContentPane().add(ecJTPArray[i]);
+							break;
+						}
+					}
+				}
+				
+				/* Calculation Part */
+				if (currentModel == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Select an AMALTHEA model first.");
+					return ;
+				} else if (ecComboBox.getSelectedItem() == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: Select an Event-Chain.");
+					return ;
+				} else if (currentIA == null) {
+					JOptionPane.showMessageDialog(frame, "ERROR: IA(Integer Array) has not been entered.");
+					return ;
+				}
+				if (list.getItemCount() > 0) {
+					list.removeAll();
+					list_1.removeAll();
+					list_2.removeAll();
+				}
+				/* Sometimes the same task can not be schedulable in the implicit communication due to the LocalCopy cost time */
+				Time rctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time rctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time ageWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time ageBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time eRctWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				Time eRctBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+				
+				/* PARADIGM */
+				if (rdbtnDirect.isSelected()) {
+					currentParadigm = ComParadigm.DIRECT;
+					rctWC = e2e.getWCReactionImplicit(currentEC, cpurta);
+					rctBC = e2e.getBCReactionImplicit(currentEC, cpurta);
+					ageWC = e2e.getWCAgeImplicit(currentEC, cpurta);
+					ageBC = e2e.getBCAgeImplicit(currentEC, cpurta);
+					eRctWC = e2e.getWCInitialRctImplicit(currentEC, cpurta);
+					eRctBC = e2e.getBCInitialRctImplicit(currentEC, cpurta);
+				} else if (rdbtnImplicit.isSelected()) {
+					currentParadigm = ComParadigm.IMPLICIT;
+					rctWC = e2e.getWCReactionImplicit(currentEC, cpurta);
+					rctBC = e2e.getBCReactionImplicit(currentEC, cpurta);
+					ageWC = e2e.getWCAgeImplicit(currentEC, cpurta);
+					ageBC = e2e.getBCAgeImplicit(currentEC, cpurta);
+					eRctWC = e2e.getWCInitialRctImplicit(currentEC, cpurta);
+					eRctBC = e2e.getBCInitialRctImplicit(currentEC, cpurta);
+				}
+				if (rctWC.getValue().equals(BigInteger.ZERO)) {
+					txtField0.setText("Not Schedulable (LocalCopy Cost)");
+				} else {
+					txtField0.setText("" + rctWC);
+				}
+				if (rctBC.getValue().equals(BigInteger.ZERO)) {
+					txtField1.setText("Not Schedulable (LocalCopy Cost)");
+				} else {
+					txtField1.setText("" + rctBC);
+				}
+				txtField2.setText("" + e2e.getWCReactionLET(currentEC, cpurta).adjustUnit());
+				txtField3.setText("" + e2e.getBCReactionLET(currentEC, cpurta).adjustUnit());
+				txtField4.setText("" + ageWC);
+				txtField5.setText("" + ageBC);
+				if (eRctWC.getValue().equals(BigInteger.ZERO)) {
+					txtField6.setText("Not Schedulable (LocalCopy Cost)");
+				} else {
+					txtField6.setText("" + eRctWC);
+				}
+				if (eRctBC.getValue().equals(BigInteger.ZERO)) {
+					txtField7.setText("Not Schedulable (LocalCopy Cost)");
+				} else {
+					txtField7.setText("" + eRctBC);
+				}
+				final EList<Label> labelList = currentModel.getSwModel().getLabels();
+				for (int i = 0; i < labelList.size(); i++) {
+					Time datAgeLatWC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					Time datAgeLatBC = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
+					datAgeLatWC = e2e.getWCDataAge(labelList.get(i), currentEC, cpurta);
+					datAgeLatBC = e2e.getBCDataAge(labelList.get(i), currentEC, cpurta);
+					if (datAgeLatWC != null && datAgeLatBC != null) {
+						list.add(labelList.get(i).getName());
+						list_1.add(datAgeLatWC + "");
+						list_2.add(datAgeLatBC + "");
+					}
+				}
+				frame.revalidate();
+				frame.repaint();
+			}
+		});
+		ecSelect.setBounds(356, 569, 90, 25);
+		frame.getContentPane().add(ecSelect);
+		
+		JButton btnNewButton_1 = new JButton("Reset");
+		btnNewButton_1.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				for (int i = 0; i < currentTaskChain.size(); i++) {
+					ecLabelArray[i].setText(null);
+					frame.remove(ecLabelArray[i]);
+					ecJTPArray[i].setText(null);
+					frame.remove(ecJTPArray[i]);
+				}
+				selectedECIndex = -1;
+				currentParadigm = null;
+				txtField0.setText("");
+				txtField1.setText("");
+				txtField2.setText("");
+				txtField3.setText("");
+				txtField4.setText("");
+				txtField5.setText("");
+				txtField6.setText("");
+				txtField7.setText("");
+				paradigmMode.setSelected(null, false);
+				list.removeAll();
+				list_1.removeAll();
+				list_2.removeAll();
+				frame.revalidate();
+				frame.repaint();
+			}
+		});
+		btnNewButton_1.setBounds(445, 569, 70, 25);
+		frame.getContentPane().add(btnNewButton_1);
+		
+		JLabel lblTaskChain_1 = new JLabel("Task Chain >");
+		lblTaskChain_1.setFont(new Font("Segoe UI Emoji", Font.BOLD, 13));
+		lblTaskChain_1.setBounds(646, 605, 90, 16);
+		frame.getContentPane().add(lblTaskChain_1);
+		
+		JLabel lblApprta = new JLabel("APP4RTA");
+		lblApprta.setForeground(Color.DARK_GRAY);
+		lblApprta.setFont(new Font("Snap ITC", Font.ITALIC, 20));
+		lblApprta.setBounds(1050, 1, 120, 34);
+		frame.getContentPane().add(lblApprta);
+		
+		JSeparator separator = new JSeparator();
+		separator.setBounds(10, 557, 1160, 2);
+		frame.getContentPane().add(separator);
+	}
 }
\ No newline at end of file