blob: 3840d3de7caca0e3a588b8690d9cc836531ff74d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Dortmund University of Applied Sciences and Arts.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* FH Dortmund - initial API and implementation
*******************************************************************************/
package org.eclipse.app4mc.gsoc_rta;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.log4j.Logger;
import org.eclipse.app4mc.gsoc_rta.CommonUtils;
import org.eclipse.app4mc.amalthea.model.ActivityGraphItem;
import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
import org.eclipse.app4mc.amalthea.model.Event;
import org.eclipse.app4mc.amalthea.model.EventChain;
import org.eclipse.app4mc.amalthea.model.EventChainContainer;
import org.eclipse.app4mc.amalthea.model.EventChainItem;
import org.eclipse.app4mc.amalthea.model.InterProcessStimulus;
import org.eclipse.app4mc.amalthea.model.InterProcessTrigger;
import org.eclipse.app4mc.amalthea.model.Label;
import org.eclipse.app4mc.amalthea.model.LabelAccess;
import org.eclipse.app4mc.amalthea.model.ProcessEvent;
import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.model.Task;
import org.eclipse.app4mc.amalthea.model.Time;
import org.eclipse.app4mc.amalthea.model.TimeUnit;
import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
import org.eclipse.emf.common.util.EList;
public class E2ELatency {
final Logger log = Logger.getLogger(E2ELatency.class);
public static StringBuffer sb = new StringBuffer();
public enum SinglecoreLatCase {
CriInitRct, BCInitRct, WCInitRct,
CriWCRct, BCWCRct, WCWCRct
}
public enum MulticoreLatCase {
BCRctIm, BCRctLET,
WCRctIm, WCRctLET,
BCInitRctIm, BCInitRctLET,
WCInitRctIm, WCInitRctLET,
BCAgeIm, BCAgeLET,
WCAgeIm, WCAgeLET
}
/**
* To derive the total sum of all task chains' latency values
* @param cpurta the instance of CPURta class
* @param pu processing unit that computes task chains' latency
* @param latCase the target single-core latency case
* @return
* the total sum of all task chains' latency values
*/
public Time getSingleTCLsum(final CPURta cpurta, final ProcessingUnit pu, final SinglecoreLatCase latCase) {
if (cpurta == null) {
log.debug("The cpurta instance is empty. Please check the instance.");
return null;
} else if (cpurta.getModel() == null) {
log.debug("Model is empty. Please check the model path.");
return null;
}
Time tclSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
final EList<EventChain> ecList = cpurta.getModel().getConstraintsModel().getEventChains();
for (int i = 0; i < ecList.size(); i++) {
final EventChain chain = ecList.get(i);
log.debug("\n");
log.debug(" ----- " + chain.getName() + " ----- ");
Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (latCase.equals(SinglecoreLatCase.CriInitRct) || latCase.equals(SinglecoreLatCase.BCInitRct)
|| latCase.equals(SinglecoreLatCase.WCInitRct)) {
lat = this.getSingleCoreInitialRct(ecList.get(i), pu, latCase, cpurta);
} else if (latCase.equals(SinglecoreLatCase.CriWCRct) || latCase.equals(SinglecoreLatCase.BCWCRct)
|| latCase.equals(SinglecoreLatCase.WCWCRct)) {
lat = this.getSingleCoreWCRct(chain, pu, latCase, cpurta);
}
tclSum = tclSum.add(lat);
}
return tclSum;
}
/**
* To derive the total sum of all task chains' multi-core latency values
* @param cpurta the instance of CPURta class
* @param latCase the target multi-core latency case
* @return
* the total sum of all task chains' multi-core latency values
*/
public Time getMultiTCLsum(final CPURta cpurta, final MulticoreLatCase latCase) {
if (cpurta == null) {
log.debug("The cpurta instance is empty. Please check the instance.");
return null;
} else if (cpurta.getModel() == null) {
log.debug("Model is empty. Please check the model path.");
return null;
}
Time tclSum = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
final EList<EventChain> ecList = cpurta.getModel().getConstraintsModel().getEventChains();
for (int i = 0; i < ecList.size(); i++) {
final EventChain chain = ecList.get(i);
log.debug("");
log.debug(" ----- " + chain.getName() + " ----- ");
Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (latCase.equals(MulticoreLatCase.BCRctIm)) {
lat = this.getBCReactionImplicit(chain, cpurta);
log.debug("Best-case Task-Chain Reaction(Implicit): " + lat);
} else if (latCase.equals(MulticoreLatCase.BCRctLET)) {
lat = this.getBCReactionLET(chain, cpurta);
log.debug("Best-case Task-Chain Reaction(LET): " + lat);
} else if (latCase.equals(MulticoreLatCase.WCRctIm)) {
lat = this.getWCReactionImplicit(chain, cpurta);
log.debug("Worst-case Task-Chain Reaction(Implicit): " + lat);
} else if (latCase.equals(MulticoreLatCase.WCRctLET)) {
lat = this.getWCReactionLET(chain, cpurta);
log.debug("Worst-case Task-Chain Reaction(LET): " + lat);
} else if (latCase.equals(MulticoreLatCase.BCInitRctIm)) {
lat = this.getBCInitialRctImplicit(chain, cpurta);
log.debug("Best-case Initial Task-Chain Reaction(Implicit): " + lat);
} else if (latCase.equals(MulticoreLatCase.BCInitRctLET)) {
lat = this.getBCInitialRctLET(chain, cpurta);
log.debug("Best-case Initial Task-Chain Reaction(LET): " + lat);
} else if (latCase.equals(MulticoreLatCase.WCInitRctIm)) {
lat = this.getWCInitialRctImplicit(chain, cpurta);
log.debug("Worst-case Initial Task-Chain Reaction(Implicit): " + lat);
} else if (latCase.equals(MulticoreLatCase.WCInitRctLET)) {
lat = this.getWCInitialRctLET(chain, cpurta);
log.debug("Worst-case Initial Task-Chain Reaction(LET): " + lat);
} else if (latCase.equals(MulticoreLatCase.BCAgeIm)) {
lat = this.getBCAgeImplicit(chain, cpurta);
log.debug("Best-case Task-Chain Age(Implicit): " + lat);
} else if (latCase.equals(MulticoreLatCase.BCAgeLET)) {
lat = this.getBCAgeLET(chain, cpurta);
log.debug("Best-case Task-Chain Age(LET): " + lat);
} else if (latCase.equals(MulticoreLatCase.WCAgeIm)) {
lat = this.getWCAgeImplicit(chain, cpurta);
log.debug("Worst-case Task-Chain Age(Implicit): " + lat);
} else if (latCase.equals(MulticoreLatCase.WCAgeLET)) {
lat = this.getWCAgeLET(chain, cpurta);
log.debug("Worst-case Task-Chain Age(LET): " + lat);
}
if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) < 0) {
log.error("Error: Latency is smaller than 0!");
return null;
}
tclSum = tclSum.add(lat);
}
log.debug("");
return tclSum;
}
/**
* Check the readiness of the observed class instance
* @param cpurta the instance of CPURta class
* @return
* boolean value that indicates whether cpurta instance is ready
*/
protected boolean isTheRTAClassReadySingle(final CPURta cpurta) {
if (cpurta.getModel() == null) {
log.debug("Model Setting needs to be done for cpurta!");
return false;
} else if (cpurta.getCT() == null) {
log.debug("CT Setting needs to be done for cpurta!");
return false;
}
return true;
}
/**
* Check the readiness of the observed class instance
* @param cpurta the instance of CPURta class
* @return
* boolean value that indicates whether cpurta instance is ready
*/
protected boolean isTheRTAClassReadyMulti(final CPURta cpurta) {
if (cpurta.getModel() == null) {
log.debug("Model Setting needs to be done for cpurta!");
return false;
} else if (cpurta.getTRT() == null) {
log.debug("TRT Setting needs to be done for cpurta!");
return false;
} else if (cpurta.getIA() == null) {
log.debug("IA Setting needs to be done for cpurta!");
return false;
} else if (cpurta.getPUl().size() == 0) {
log.debug("PUl Setting needs to be done for cpurta!");
return false;
} else if (cpurta.getCT() == null) {
log.debug("CT Setting needs to be done for cpurta!");
return false;
}
return true;
}
/**
* To derive the observed event chain's initial single-core reaction according to the target latency case
* @param ec the observed event chain
* @param pu processing unit that computes the observed event chain
* @param latCase the target single-core latency case (critical-case, best-case, worst-case)
* @param cpurta the instance of CPURta class
* @return
* the initial single-core reaction time of the observed event chain with the given latCase
*/
public Time getSingleCoreInitialRct(final EventChain ec, final ProcessingUnit pu, final SinglecoreLatCase latCase, final CPURta cpurta) {
if (isTheRTAClassReadySingle(cpurta)) {
if (latCase.equals(SinglecoreLatCase.CriWCRct) || latCase.equals(SinglecoreLatCase.BCWCRct)
|| latCase.equals(SinglecoreLatCase.WCWCRct)) {
log.error("latCase needs to be changed into one of three: CriInitRct, BCInitRct, WCInitRct");
return null;
}
final List<Task> taskChain = getECTaskList(ec);
if (taskChain.size() == 0) {
log.error("This task chain is empty.");
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
final Task task_0 = taskChain.get(0);
final List<Task> sortedChain = cpurta.taskSorting(taskChain);
final Time period_0 = CommonUtils.getStimInTime(task_0);
final Time hyper = this.getHyperPeriod(sortedChain);
final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
/* Checking the first element's all instances in the hyper-period to see whether each can make a chain
* and to calculate latency if they can */
final List<Time> latencyList = new ArrayList<Time>();
for (int i = 0; i < chainsToCheck; i++) {
Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
lat = this.getSingleCoreInitialRct_(i, ec, pu, cpurta);
/* Critical-case */
if ((i == 0) && latCase.equals(SinglecoreLatCase.CriInitRct)) {
return lat;
}
if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
latencyList.add(lat);
}
log.debug(i + "-th instance: " + lat);
}
Collections.sort(latencyList, new TimeComp());
/* Best-case */
if (latCase.equals(SinglecoreLatCase.BCInitRct)) {
return latencyList.get(0);
}
/* Worst-case */
return latencyList.get(latencyList.size()-1);
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* To derive the initial single-core reaction that starts with (i+1)_th instance of the first task
* in the observed event chain (in the hyper-period with the critical instant)
* @param i the number(i+1) of the observed instance of the first of the event chain in the hyper-period
* @param ec the observed event chain
* @param pu processing unit that computes the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the initial single-core reaction of the observed task chain starting with (i+1)_th instance of the first task
*/
protected Time getSingleCoreInitialRct_(final int i, final EventChain ec, final ProcessingUnit pu, final CPURta cpurta) {
if (isTheRTAClassReadySingle(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
final Task task_0 = taskChain.get(0);
final Time period_0 = CommonUtils.getStimInTime(task_0);
Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
lat = this.getCRtoRT(i, task_0, taskChain, pu, cpurta);
for (int j = 1; j < taskChain.size(); j++) {
final Task task = taskChain.get(j);
final BigInteger latBI = AmaltheaServices.convertToPicoSeconds(lat);
final BigDecimal latBD = BigDecimal.valueOf(latBI.doubleValue());
final Time period = CommonUtils.getStimInTime(task);
final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
final Task preTask = taskChain.get(j-1);
final Time pre_period = CommonUtils.getStimInTime(preTask);
final BigInteger pre_periodBI = AmaltheaServices.convertToPicoSeconds(pre_period);
final BigDecimal pre_periodBD = BigDecimal.valueOf(pre_periodBI.doubleValue());
final List<Task> preHPList = cpurta.getHigherPriorityTasksInChain(preTask, taskChain);
long offset = 0;
/* To check whether the observed task is a higher priority than the previous chain element */
if (preHPList.contains(task)) {
final BigDecimal offsetBD = latBD.divide(periodBD, 0, BigDecimal.ROUND_CEILING);
offset = offsetBD.longValue();
} else {
final BigDecimal flo = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_FLOOR);
offset = (flo.multiply(pre_periodBD)).divide(periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
}
final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, taskChain, pu, cpurta);
Time taskCRRT = this.getCRtoRT(offset, task, taskChain, pu, cpurta);
/* The current task is a higher priority than the previous one */
if (preHPList.contains(task)) {
final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, taskChain, pu, cpurta);
if (preTaskCRRT.compareTo(taskCRRT) < 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
}
/* The current task is a lower priority than the previous one */
else {
Time taskCRIP = this.getCRtoIP(offset, task, taskChain, pu, cpurta);
if (preTaskCRIP.compareTo(taskCRIP) < 0) {
offset = offset-1;
taskCRIP = this.getCRtoIP(offset, task, taskChain, pu, cpurta);
/* it can not make a task chain */
if (lat.compareTo(taskCRIP) > 0 || preTaskCRIP.compareTo(taskCRIP) < 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
taskCRRT = this.getCRtoRT(offset, task, taskChain, pu, cpurta);
}
}
lat = taskCRRT;
}
/* delete the offset time */
if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
lat = lat.subtract(period_0.multiply(i));
}
return lat;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* To derive the observed event chain's worst-case single-core reaction according to the target latency case
* @param ec the observed event chain
* @param pu processing unit that computes the observed event chain
* @param latCase the target single-core latency case (critical-case, best-case, worst-case)
* @param cpurta the instance of CPURta class
* @return
* the worst-case single-core reaction time of the observed event chain with the given latCase
*/
public Time getSingleCoreWCRct(final EventChain ec, final ProcessingUnit pu, final SinglecoreLatCase latCase, final CPURta cpurta) {
if (isTheRTAClassReadySingle(cpurta)) {
if (latCase.equals(SinglecoreLatCase.CriInitRct) || latCase.equals(SinglecoreLatCase.BCInitRct)
|| latCase.equals(SinglecoreLatCase.WCInitRct)) {
log.error("latCase needs to be changed into one of three: CriWCRct, BCWCRct, WCWCRct");
return null;
}
final List<Task> taskChain = getECTaskList(ec);
if (taskChain.size() == 0) {
log.error("This task chain is empty.");
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
final Task task_0 = taskChain.get(0);
final List<Task> sortedChain = cpurta.taskSorting(taskChain);
final Time period_0 = CommonUtils.getStimInTime(task_0);
final Time hyper = this.getHyperPeriod(sortedChain);
final BigInteger period_0_BI = AmaltheaServices.convertToPicoSeconds(period_0);
final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
final long chainsToCheck = hyper_BI.divide(period_0_BI).longValue();
/* Checking the first element's all instances in the hyper-period to see whether each can make a chain
* and to calculate latency if they can */
final List<Time> latencyList = new ArrayList<Time>();
for (int i = 0; i < chainsToCheck; i++) {
Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
lat = this.getSingleCoreWCRct_(i, ec, pu, cpurta);
/* Critical-case */
if ((i == 0) && latCase.equals(SinglecoreLatCase.CriWCRct)) {
return lat;
}
if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
latencyList.add(lat);
}
log.debug(i + "-th instance: " + lat);
}
Collections.sort(latencyList, new TimeComp());
/* Best-case */
if (latCase.equals(SinglecoreLatCase.BCWCRct)) {
return latencyList.get(0);
}
/* Worst-case */
return latencyList.get(latencyList.size()-1);
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* To derive the worst-case single-core reaction that starts with (i+1)_th instance of the first task
* in the observed event chain (in the hyper-period with the critical instant)
* @param i the number(i+1) of the observed instance of the first of the event chain in the hyper-period
* @param ec the observed event chain
* @param pu processing unit that computes the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case single-core reaction of the observed task chain starting with (i+1)_th instance of the first task
*/
protected Time getSingleCoreWCRct_(final int i, final EventChain ec, final ProcessingUnit pu, final CPURta cpurta) {
if (isTheRTAClassReadySingle(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
final Task task_0 = taskChain.get(0);
final Time period_0 = CommonUtils.getStimInTime(task_0);
Time temp = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
Time pre_previousVal = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
Time lat = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
lat = this.getCRtoRT(i, task_0, taskChain, pu, cpurta);
for (int j = 1; j < taskChain.size(); j++) {
final Task task = taskChain.get(j);
final BigInteger latBI = AmaltheaServices.convertToPicoSeconds(lat);
final BigDecimal latBD = BigDecimal.valueOf(latBI.doubleValue());
final Time period = CommonUtils.getStimInTime(task);
final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
final Task preTask = taskChain.get(j-1);
final Time pre_period = CommonUtils.getStimInTime(preTask);
final BigInteger pre_periodBI = AmaltheaServices.convertToPicoSeconds(pre_period);
final BigDecimal pre_periodBD = BigDecimal.valueOf(pre_periodBI.doubleValue());
final List<Task> preHPList = cpurta.getHigherPriorityTasksInChain(preTask, taskChain);
final long preTask_offset = latBD.divide(pre_periodBD, 0, BigDecimal.ROUND_CEILING).longValue();
/* The current task is a higher priority than the previous one */
Time taskCRRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (preHPList.contains(task)) {
final Time preTaskCRRT = this.getCRtoRT(preTask_offset, preTask, taskChain, pu, cpurta);
final BigInteger preTaskCrrtBI = AmaltheaServices.convertToPicoSeconds(preTaskCRRT);
final BigDecimal preTaskCrrtBD = BigDecimal.valueOf(preTaskCrrtBI.longValue());
final long offwhp = preTaskCrrtBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
final Time crrt_cr = this.getCRtoRT(offwhp, task, taskChain, pu, cpurta);
final Time crrt_cr_ = this.getCRtoRT(offwhp-1, task, taskChain, pu, cpurta);
/* When there is an instance(s) of \tau_j between f(j-1)_x and the crrt time of the next instance of \tau_{j-1} */
if ((preTaskCrrtBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) &&
(lat.compareTo(crrt_cr) < 0) &&
(preTaskCRRT.compareTo(crrt_cr) > 0)) {
taskCRRT = crrt_cr;
}
/* In the worst-case, this part is only needed when the current task's priority is higher than the previous one's.
* Because the current task's crrt is calculated based on the crrt time of the next instance of the previous task.
* Due to the fact that there can be more than one instance of the higher priority task between the lower priority task's instances. */
else if ((preTaskCrrtBI.mod(periodBI).compareTo(BigInteger.ZERO) == 0) &&
(lat.compareTo(crrt_cr_) < 0) &&
(preTaskCRRT.compareTo(crrt_cr_) > 0)) {
taskCRRT = crrt_cr_;
}
}
/* The current task is a lower priority than the previous one */
else {
final Time previousValIP = this.getCRtoIP(preTask_offset-1, preTask, taskChain, pu, cpurta);
final Time preTaskCRIP = this.getCRtoIP(preTask_offset, preTask, taskChain, pu, cpurta);
final BigInteger preTaskCripBI = AmaltheaServices.convertToPicoSeconds(preTaskCRIP);
final BigDecimal preTaskCripBD = BigDecimal.valueOf(preTaskCripBI.longValue());
final long offlhp = preTaskCripBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
final Time crip = this.getCRtoIP(offlhp, task, taskChain, pu, cpurta);
/* When there is an instance(s) of \tau_j between f(j-1)_x and the crip time of the next instance of \tau_{j-1} */
if ((preTaskCripBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) &&
(previousValIP.compareTo(crip) < 0) &&
(preTaskCRIP.compareTo(crip) > 0)) {
taskCRRT = this.getCRtoRT(offlhp, task, taskChain, pu, cpurta);
}
/* In the worst-case, this part is only needed when the current task's priority is lower than the previous one's
* Because the current task's crrt is calculated based on the crip time of the next instance of \tau_{j-1}.
* Due to the fact that there can be no instance of the lower priority task between the higher priority task's instances. */
else {
/* When \tau_j is the second element of the chain and there is no instance of \tau_j between f(j-1)_x and the crip time of the next instance of \tau_{j-1} */
if (pre_previousVal.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
taskCRRT = this.getCRWC(task, preTask, 1, lat, pre_previousVal, taskChain, pu, cpurta);
/* To consider a situation where there is another chain path that goes through the earlier instance of \tau_{j-1} */
if (taskCRRT.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) == 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
}
}
temp = lat;
lat = taskCRRT;
pre_previousVal = temp;
}
/* delete the offset time */
if (lat.compareTo(FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS)) != 0) {
lat = lat.subtract(period_0.multiply(i));
}
return lat;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* this method is used by getSingleCoreWCRct_() when getSingleCoreWCRct_() fails to identify a valid task's instance.
* the method is intended to find an alternative chain path from the time point of prepre:
* : the finishing point of the worst-case reaction of the successor of preTask.
* @param task the observed task
* @param preTask the successor of the observed task
* @param k constant to subtract to calculate the initial point to identify the alternative chain path
* @param pre the finishing point of the worst-case reaction of preTask
* @param prepre the finishing point of the worst-case reaction of the successor of preTask
* @param chain the observed task chain
* @param pu processing unit that computes the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the alternative getSingleCoreWCRct_() result (the crwc time value of the observed task)
*/
private Time getCRWC(final Task task, final Task preTask, final long k,
final Time pre, final Time prepre, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
final BigInteger preBI = AmaltheaServices.convertToPicoSeconds(pre);
final BigDecimal preBD = BigDecimal.valueOf(preBI.longValue());
final Time period = CommonUtils.getStimInTime(task);
final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
final BigDecimal periodBD = BigDecimal.valueOf(periodBI.longValue());
final Time prePeriod = CommonUtils.getStimInTime(preTask);
final BigInteger prePeriodBI = AmaltheaServices.convertToPicoSeconds(prePeriod);
final BigDecimal prePeriodBD = BigDecimal.valueOf(prePeriodBI.longValue());
final long preOffcr = preBD.divide(prePeriodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
final long offcr = preBD.divide(periodBD, 0, BigDecimal.ROUND_FLOOR).longValue();
final long offcr_ = offcr - 1;
final Time preCripCr = this.getCRtoIP(preOffcr - k, preTask, chain, pu, cpurta);
final Time crrtCr = this.getCRtoRT(offcr, task, chain, pu, cpurta);
final Time crrtCr_ = this.getCRtoRT(offcr_, task, chain, pu, cpurta);
final Time cripCr = this.getCRtoIP(offcr, task, chain, pu, cpurta);
final Time cripCr_ = this.getCRtoIP(offcr_, task, chain, pu, cpurta);
if (preCripCr.compareTo(prepre) < 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
} else if ((preBI.mod(periodBI).compareTo(BigInteger.ZERO) != 0) &&
(cripCr.compareTo(pre) < 0) &&
(cripCr.compareTo(preCripCr) > 0)){
return crrtCr;
} else if ((preBI.mod(periodBI).compareTo(BigInteger.ZERO) == 0) &&
(cripCr_.compareTo(pre) < 0) &&
(cripCr_.compareTo(preCripCr) > 0)){
return crrtCr_;
} else {
return this.getCRWC(task, preTask, k+1, pre, prepre, chain, pu, cpurta);
}
}
/**
* to derive the best-case reaction of the observed event chain with Implicit communication
* (for now calculation is done with direct response time functions)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case reaction of the observed event chain with Implicit communication
*/
public Time getBCReactionImplicit(final EventChain ec, final CPURta cpurta) {
Time bcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
bcRctImplicit = bcRctImplicit.add(bcrt);
if (i != 0) {
final Time bcip = this.getBCInitialPending(task, cpurta);
bcRctImplicit = bcRctImplicit.subtract(bcip);
}
}
return bcRctImplicit;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the worst-case reaction of the observed event chain with Implicit communication
* (for now calculation is done with direct response time functions)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case reaction of the observed event chain with Implicit communication
*/
public Time getWCReactionImplicit(final EventChain ec, final CPURta cpurta) {
Time wcRctImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
final Task task_0 = taskChain.get(0);
final ProcessingUnit pu_0 = cpurta.getPU(task_0, cpurta);
final List<Task> taskList_0 = cpurta.getSortedTaskList(task_0, pu_0, cpurta);
final Time rt_0 = cpurta.preciseTestCPURT(task_0, taskList_0, TimeType.WCET, pu_0);
final Time period_0 = CommonUtils.getStimInTime(task_0);
wcRctImplicit = wcRctImplicit.add(rt_0);
wcRctImplicit = wcRctImplicit.add(period_0);
for (int i = 1; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
final Time rt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
wcRctImplicit = wcRctImplicit.add(rt);
if (i != taskChain.size() - 1) {
final Time period = CommonUtils.getStimInTime(task);
final Time bcip = this.getBCInitialPending(task, cpurta);
wcRctImplicit = wcRctImplicit.add(period.subtract(bcip));
} else {
final Time wcip = this.getWCInitialPending(task, cpurta);
wcRctImplicit = wcRctImplicit.subtract(wcip);
}
}
return wcRctImplicit;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case initial reaction of the observed event chain with Implicit communication
* (for now calculation is done with direct response time functions)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case initial reaction of the observed event chain with Implicit communication
*/
public Time getBCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
return getBCReactionImplicit(ec, cpurta);
}
/**
* to derive the worst-case initial reaction of the observed event chain with Implicit communication
* (for now calculation is done with direct response time functions)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case initial reaction of the observed event chain with Implicit communication
*/
public Time getWCInitialRctImplicit(final EventChain ec, final CPURta cpurta) {
Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
final Time period = CommonUtils.getStimInTime(task);
final Time rt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
wcInitialRct = wcInitialRct.add(rt);
if (i != 0) {
final Task preTask = taskChain.get(i-1);
final Time prePeriod = CommonUtils.getStimInTime(preTask);
if (period.compareTo(prePeriod) >= 0 && taskChain.size() - 1 < 3) {
final Time wcip = this.getWCInitialPending(task, cpurta);
wcInitialRct = wcInitialRct.add(prePeriod.subtract(wcip));
} else if (period.compareTo(prePeriod) >= 0 && i == taskChain.size() - 1) {
final Time wcip = this.getWCInitialPending(task, cpurta);
wcInitialRct = wcInitialRct.subtract(wcip);
} else if (period.compareTo(prePeriod) >= 0 && i == 1) {
final Time bcip = this.getBCInitialPending(task, cpurta);
wcInitialRct = wcInitialRct.add(prePeriod.add(period).subtract(bcip));
} else {
final Time bcip = this.getBCInitialPending(task, cpurta);
wcInitialRct = wcInitialRct.add(period.subtract(bcip));
}
}
}
return wcInitialRct;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case reaction of the observed event chain with LET communication
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case reaction of the observed event chain with LET communication
*/
public Time getBCReactionLET(final EventChain ec, final CPURta cpurta) {
Time bcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final Time period = CommonUtils.getStimInTime(task);
bcRctLET = bcRctLET.add(period);
}
return bcRctLET;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the worst-case reaction of the observed event chain with LET communication
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case reaction of the observed event chain with LET communication
*/
public Time getWCReactionLET(final EventChain ec, final CPURta cpurta) {
Time wcRctLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final Time period = CommonUtils.getStimInTime(task);
if (i != taskChain.size() - 1) {
wcRctLET = wcRctLET.add(period.multiply(2));
} else {
wcRctLET = wcRctLET.add(period);
}
}
return wcRctLET;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case initial reaction of the observed event chain with LET communication
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case initial reaction of the observed event chain with LET communication
*/
public Time getBCInitialRctLET(final EventChain ec, final CPURta cpurta) {
return getBCReactionLET(ec, cpurta);
}
/**
* to derive the worst-case initial reaction of the observed event chain with LET communication
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case initial reaction of the observed event chain with LET communication
*/
public Time getWCInitialRctLET(final EventChain ec, final CPURta cpurta) {
Time wcInitialRct = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final Time period = CommonUtils.getStimInTime(task);
wcInitialRct = wcInitialRct.add(period);
if (i != 0) {
final Task preTask = taskChain.get(i-1);
final Time prePeriod = CommonUtils.getStimInTime(preTask);
if (period.compareTo(prePeriod) > 0) {
wcInitialRct = wcInitialRct.add(prePeriod);
} else {
wcInitialRct = wcInitialRct.add(period);
}
}
}
return wcInitialRct;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case age of the observed event chain with Implicit communication
* (for now calculation is done with direct response time functions)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case age of the observed event chain with Implicit communication
*/
public Time getBCAgeImplicit(final EventChain ec, final CPURta cpurta) {
Time bcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
final Task task_0 = taskChain.get(0);
final Time period_0 = CommonUtils.getStimInTime(task_0);
final Time bcInitialRct = getBCInitialRctImplicit(ec, cpurta);
final Time wcReaction = getWCReactionImplicit(ec, cpurta);
if ((period_0.add(bcInitialRct)).compareTo(wcReaction) < 0) {
final Task lastTask = taskChain.get(taskChain.size() - 1);
final Time lastTaskAge = getBCTaskAgeImplicit(lastTask, cpurta);
bcAgeImplicit = bcAgeImplicit.add(lastTaskAge);
} else {
bcAgeImplicit = bcAgeImplicit.add(period_0.add(bcInitialRct).subtract(wcReaction));
}
return bcAgeImplicit;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the worst-case age of the observed event chain with Implicit communication
* (for now calculation is done with direct response time functions)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case age of the observed event chain with Implicit communication
*/
public Time getWCAgeImplicit(final EventChain ec, final CPURta cpurta) {
Time wcAgeImplicit = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
final Task task_0 = taskChain.get(0);
final Time period_0 = CommonUtils.getStimInTime(task_0);
final Time wcInitialRct = getWCInitialRctImplicit(ec, cpurta);
final Time bcInitialRct = getBCInitialRctImplicit(ec, cpurta);
wcAgeImplicit = wcAgeImplicit.add(period_0.add(wcInitialRct).subtract(bcInitialRct));
return wcAgeImplicit;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the subtraction between the worst- and best-case reaction times of the observed event chain with Implicit communication
* (to compare to the worst-case age of the observed event chain with Implicit communication)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the subtraction between the worst- and best-case reaction times with Implicit communication
*/
public Time getWCBCSubAgeImplicit(final EventChain ec, final CPURta cpurta) {
if (isTheRTAClassReadyMulti(cpurta)) {
final Time wcAgeRctImplicit = this.getWCReactionImplicit(ec, cpurta);
final Time bcAgeRctImplicit = this.getBCReactionImplicit(ec, cpurta);
return wcAgeRctImplicit.subtract(bcAgeRctImplicit);
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case age of the observed event chain with LET communication
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case age of the observed event chain with LET communication
*/
public Time getBCAgeLET(final EventChain ec, final CPURta cpurta) {
Time bcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
final Task lastTask = taskChain.get(taskChain.size() - 1);
final Time lastTaskPeriod = CommonUtils.getStimInTime(lastTask);
bcAgeLET = bcAgeLET.add(lastTaskPeriod);
return bcAgeLET;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the worst-case age of the observed event chain with LET communication
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case age of the observed event chain with LET communication
*/
public Time getWCAgeLET(final EventChain ec, final CPURta cpurta) {
Time wcAgeLET = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
final Time period = FactoryUtil.createTime(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(task)), TimeUnit.PS);
if (i == 0) {
wcAgeLET = wcAgeLET.add(period);
} else {
if (period.compareTo(wcAgeLET) == 0) {
wcAgeLET = period.multiply(2);
} else if (period.compareTo(wcAgeLET) > 0) {
wcAgeLET = period;
} else {
final BigInteger periodBI = AmaltheaServices.convertToPicoSeconds(period);
final BigInteger wcAgeLETBI = AmaltheaServices.convertToPicoSeconds(wcAgeLET);
final BigDecimal periodBD = BigDecimal.valueOf(periodBI.doubleValue());
final BigDecimal wcAgeLETBD = BigDecimal.valueOf(wcAgeLETBI.doubleValue());
if (wcAgeLETBI.mod(periodBI) != BigInteger.ZERO) {
final BigDecimal ceiledValueBD = wcAgeLETBD.divide(periodBD, 0, BigDecimal.ROUND_CEILING);
final BigInteger ceiledValueBI = BigInteger.valueOf(ceiledValueBD.longValue());
wcAgeLET = FactoryUtil.createTime(periodBI.multiply(ceiledValueBI), TimeUnit.PS);
} else {
wcAgeLET = FactoryUtil.createTime(periodBI.multiply(wcAgeLETBI.divide(periodBI)
.add(BigInteger.ONE)), TimeUnit.PS);
}
}
}
}
return wcAgeLET;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the subtraction between the worst- and best-case reaction times of the observed event chain with LET communication
* (to compare to the worst-case age of the observed event chain with LET communication)
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the subtraction between the worst- and best-case reaction times with LET communication
*/
public Time getWCBCSubAgeLET(final EventChain ec, final CPURta cpurta) {
if (isTheRTAClassReadyMulti(cpurta)) {
final Time wcRctLET = this.getWCReactionLET(ec, cpurta);
final Time bcRctLET = this.getBCReactionLET(ec, cpurta);
return wcRctLET.subtract(bcRctLET);
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case task age latency of the observed task with Implicit communication
* (for now calculation is done with direct response time functions)
* @param task the observed task
* @param cpurta the instance of CPURta class
* @return
* the best-case task age latency of the observed task with Implicit communication
*/
public Time getBCTaskAgeImplicit(final Task task, final CPURta cpurta) {
Time bcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
final Time wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
final Time period = CommonUtils.getStimInTime(task);
bcTaskAge = bcTaskAge.add(period.subtract(wcrt).add(bcrt));
return bcTaskAge;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the worst-case task age latency of the observed task with Implicit communication
* (for now calculation is done with direct response time functions)
* @param task the observed task
* @param cpurta the instance of CPURta class
* @return
* the worst-case task age latency of the observed task with Implicit communication
*/
public Time getWCTaskAgeImplicit(final Task task, final CPURta cpurta) {
Time wcTaskAge = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (isTheRTAClassReadyMulti(cpurta)) {
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
final Time wcrt = cpurta.preciseTestCPURT(task, taskList, TimeType.WCET, pu);
final Time period = CommonUtils.getStimInTime(task);
wcTaskAge = wcTaskAge.add(period.subtract(bcrt).add(wcrt));
return wcTaskAge;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case data age regarding the observed label in the given event chain
* @param label the observed label
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the best-case data age regarding the observed label in the given event chain
*/
public Time getBCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Time> bcDataAgeList = new ArrayList<Time>();
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
if (isMappedToCPU(task, cpurta)) {
Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
if (cpurta.getTriggeringTaskList().contains(task)) {
final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
final InterProcessStimulus ips = ipt.getStimulus();
final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
final Set<Label> gpuLabelSet = SoftwareUtil.getAccessedLabelSet(gpuTask, null);
labelSet.addAll(gpuLabelSet);
labelSet = labelSet.stream().distinct().collect(Collectors.toSet());
}
if(labelSet.contains(label)) {
final Time bcDataAge = getBCTaskAgeImplicit(task, cpurta);
bcDataAgeList.add(bcDataAge);
}
} else {
/* GPU Task - there is no best case or worst case reponse time for GPU Task => Age Latency = Period */
bcDataAgeList.add(CommonUtils.getStimInTime(task));
}
}
if (bcDataAgeList.size() != 0) {
Collections.sort(bcDataAgeList, new TimeComp());
return bcDataAgeList.get(0);
}
log.error("This chain does not have the observed label.");
return null;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the worst-case data age regarding the observed label in the given event chain
* @param label the observed label
* @param ec the observed event chain
* @param cpurta the instance of CPURta class
* @return
* the worst-case data age regarding the observed label in the given event chain
*/
public Time getWCDataAge(final Label label, final EventChain ec, final CPURta cpurta) {
if (isTheRTAClassReadyMulti(cpurta)) {
final List<Time> wcDataAgeList = new ArrayList<Time>();
final List<Task> taskChain = getECTaskList(ec);
for (int i = 0; i < taskChain.size(); i++) {
final Task task = taskChain.get(i);
if (isMappedToCPU(task, cpurta)) {
Set<Label> labelSet = SoftwareUtil.getAccessedLabelSet(task, null);
if (cpurta.getTriggeringTaskList().contains(task)) {
final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
final InterProcessStimulus ips = ipt.getStimulus();
final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
final Set<Label> gpuLabelSet = SoftwareUtil.getAccessedLabelSet(gpuTask, null);
labelSet.addAll(gpuLabelSet);
labelSet = labelSet.stream().distinct().collect(Collectors.toSet());
}
if(labelSet.contains(label)) {
final Time wcDataAge = getWCTaskAgeImplicit(task, cpurta);
wcDataAgeList.add(wcDataAge);
}
} else {
/* GPU Task - there is no best case or worst case reponse time for GPU Task => Age Latency = Period */
wcDataAgeList.add(CommonUtils.getStimInTime(task));
}
}
if (wcDataAgeList.size() != 0) {
Collections.sort(wcDataAgeList, new TimeComp());
return wcDataAgeList.get(0);
}
log.error("This chain does not have the observed label.");
return null;
}
log.error("cpurta instance is not ready!");
return null;
}
/**
* to derive the best-case intial pending time of the observed task
* @param task the observed task
* @param cpurta the instance of CPURta class
* @return
* the best-case intial pending time of the observed task
*/
protected Time getBCInitialPending(final Task task, final CPURta cpurta) {
if (this.isTheRTAClassReadyMulti(cpurta)) {
/*
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> taskList = cpurta.getSortedTaskList(task, pu, cpurta);
final Time bcrt = cpurta.bestCaseCPURT(task, taskList, pu);
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
final Time bcct = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.BCET, cpurta);
return bcrt.subtract(bcct);
*/
// TODO: find the best-case initial pending in the given task's hyper-period
// (for E2E Latency with the worst-case sampling interval time.)
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
return null;
}
/**
* to derive the worst-case initial pending time of the observed task with the observed task chain
* @param task the observed task
* @param chain the observed task chain
* @param pu processing unit that computes to derive the wc initial pending time
* @param cpurta the instance of CPURta class
* @return
* the worst-case initial pending time of the observed task in the observed task chain
*/
protected Time getWCInitialPending(final Task task, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
if (this.isTheRTAClassReadySingle(cpurta)) {
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
final List<Task> hpList = cpurta.getHigherPriorityTasksInChain(task, chain);
if (hpList.size() == 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
final Task oneHigherTask = hpList.get(hpList.size()-1);
Time wcIPTime = cpurta.preciseTestCPURT(oneHigherTask, hpList, TimeType.WCET, pu);
BigInteger wcIPTimeBI = AmaltheaServices.convertToPicoSeconds(wcIPTime);
for (int i = 0; i < hpList.size(); i++) {
final Task curTask = hpList.get(i);
final Time curPeriod = CommonUtils.getStimInTime(curTask);
BigInteger curPeriodBI = AmaltheaServices.convertToPicoSeconds(curPeriod);
if (i == hpList.size()-1 || wcIPTimeBI.compareTo(curPeriodBI) < 0) {
break;
} else if (wcIPTimeBI.mod(curPeriodBI) == BigInteger.ZERO) {
final Time curExeTime = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.WCET, cpurta);
final BigInteger curExeTimeBI = AmaltheaServices.convertToPicoSeconds(curExeTime);
wcIPTimeBI = wcIPTimeBI.add(curExeTimeBI);
i = -1;
}
}
wcIPTime = FactoryUtil.createTime(wcIPTimeBI, TimeUnit.PS);
return wcIPTime;
}
return null;
}
/**
* to derive the worst-case initial pending time of the observed task
* @param task the observed task
* @param cpurta the instance of CPURta class
* @return
* the worst-case initial pending time of the observed task
*/
protected Time getWCInitialPending(final Task task, final CPURta cpurta) {
if (this.isTheRTAClassReadyMulti(cpurta)) {
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
final ProcessingUnit pu = cpurta.getPU(task, cpurta);
final List<Task> hpList = cpurta.getHigherPriorityTasks(task, cpurta);
if (hpList.size() == 0) {
return FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
}
final Task oneHigherTask = hpList.get(hpList.size()-1);
Time wcIPTime = cpurta.preciseTestCPURT(oneHigherTask, hpList, TimeType.WCET, pu);
BigInteger wcIPTimeBI = AmaltheaServices.convertToPicoSeconds(wcIPTime);
for (int i = 0; i < hpList.size(); i++) {
final Task curTask = hpList.get(i);
final Time curPeriod = CommonUtils.getStimInTime(curTask);
BigInteger curPeriodBI = AmaltheaServices.convertToPicoSeconds(curPeriod);
if (i == hpList.size()-1 || wcIPTimeBI.compareTo(curPeriodBI) < 0) {
break;
} else if (wcIPTimeBI.mod(curPeriodBI) == BigInteger.ZERO) {
final Time curExeTime = rtaut.getExecutionTimeforCPUTaskIA(curTask, pu, TimeType.WCET, cpurta);
final BigInteger curExeTimeBI = AmaltheaServices.convertToPicoSeconds(curExeTime);
wcIPTimeBI = wcIPTimeBI.add(curExeTimeBI);
i = -1;
}
}
wcIPTime = FactoryUtil.createTime(wcIPTimeBI, TimeUnit.PS);
return wcIPTime;
}
return null;
}
/**
* to derive the time between the critical instant and the given offset's task instance's finishing point
* @param offset the offset constant number (to set the initial point to analyze, initial point: offset * period of task)
* @param task the target task to derive the time between the critical instant and its current instance's finishing point
* @param chain the observed task chain
* @param pu processing unit that computes to derive the crrt time
* @param cpurta the instance of CPURta class
* @return
* the time between the critical instant and the given offset's task instance's finishing point
*/
protected Time getCRtoRT(final long offset, final Task task, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
Time crToRT = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (this.isTheRTAClassReadySingle(cpurta)) {
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
final List<Task> sortedChain = cpurta.taskSorting(chain);
final Time hyper = this.getHyperPeriod(sortedChain);
final Time period = CommonUtils.getStimInTime(task);
final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
final BigInteger period_BI = AmaltheaServices.convertToPicoSeconds(period);
final long cycle = hyper_BI.divide(period_BI).longValue();
if (offset % cycle != 0) {
final Time wcct = rtaut.getExecutionTimeforCPUTaskIA(task, pu, TimeType.WCET, cpurta);
final Time initialTime = period.multiply(offset).add(wcct);
crToRT = initialTime;
/* Incremental CRtoRT Part */
final List<Task> hpList = cpurta.getHigherPriorityTasksInChain(task, chain);
for (int i = 0; i < hpList.size(); i++) {
final BigInteger time_BI = AmaltheaServices.convertToPicoSeconds(crToRT);
final BigDecimal time_BD = BigDecimal.valueOf(time_BI.doubleValue());
final Task hpTask = hpList.get(i);
final Time hpWcct = rtaut.getExecutionTimeforCPUTaskIA(hpTask, pu, TimeType.WCET, cpurta);
final Time hpPeriod = CommonUtils.getStimInTime(hpTask);
final BigInteger hpPeriod_BI = AmaltheaServices.convertToPicoSeconds(hpPeriod);
final BigDecimal hpPeriod_BD = BigDecimal.valueOf(hpPeriod_BI.doubleValue());
long hpOffset = time_BD.divide(hpPeriod_BD, 0, BigDecimal.ROUND_FLOOR).longValue();
if (hpPeriod.multiply(hpOffset).add(hpWcct).compareTo(crToRT.subtract(wcct)) > 0 && time_BI.mod(hpPeriod_BI).longValue() != 0) {
crToRT = hpPeriod.multiply(hpOffset).add(hpWcct).add(wcct);
i = -1;
}
}
} else {
crToRT = cpurta.preciseTestCPURT(task, sortedChain, TimeType.WCET, pu).add(period.multiply(offset));
}
return crToRT;
}
return null;
}
/**
* to derive the time between the critical instant and the given offset's task instance's starting point
* @param offset the offset constant number (to set the initial point to analyze, initial point: offset * period of task)
* @param task the target task to derive the time between the critical instant and its current instance's starting point
* @param chain the observed task chain
* @param pu processing unit that computes to derive the crip time
* @param cpurta the instance of CPURta class
* @return
* the time between the critical instant and the given offset's task instance's starting point
*/
protected Time getCRtoIP(final long offset, final Task task, final List<Task> chain, final ProcessingUnit pu, final CPURta cpurta) {
Time crToIP = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
if (this.isTheRTAClassReadySingle(cpurta)) {
final RTARuntimeUtil rtaut = new RTARuntimeUtil();
final List<Task> sortedChain = cpurta.taskSorting(chain);
final Time hyper = this.getHyperPeriod(sortedChain);
final Time period = CommonUtils.getStimInTime(task);
final BigInteger hyper_BI = AmaltheaServices.convertToPicoSeconds(hyper);
final BigInteger period_BI = AmaltheaServices.convertToPicoSeconds(period);
final long cycle = hyper_BI.divide(period_BI).longValue();
if (offset % cycle != 0) {
final Time initialTime = period.multiply(offset);
crToIP = initialTime;
/* Incremental CRtoIP Part */
final List<Task> hpList = cpurta.getHigherPriorityTasksInChain(task, chain);
for (int i = 0; i < hpList.size(); i++) {
final BigInteger time_BI = AmaltheaServices.convertToPicoSeconds(crToIP);
final BigDecimal time_BD = BigDecimal.valueOf(time_BI.doubleValue());
final Task hpTask = hpList.get(i);
final Time hpWcct = rtaut.getExecutionTimeforCPUTaskIA(hpTask, pu, TimeType.WCET, cpurta);
final Time hpPeriod = CommonUtils.getStimInTime(hpTask);
final BigInteger hpPeriod_BI = AmaltheaServices.convertToPicoSeconds(hpPeriod);
final BigDecimal hpPeriod_BD = BigDecimal.valueOf(hpPeriod_BI.doubleValue());
final long hpOffset = time_BD.divide(hpPeriod_BD, 0, BigDecimal.ROUND_FLOOR).longValue();
if (hpPeriod.multiply(hpOffset).add(hpWcct).compareTo(crToIP) > 0) {
crToIP = hpPeriod.multiply(hpOffset).add(hpWcct);
i = -1;
}
}
} else {
crToIP = this.getWCInitialPending(task, chain, pu, cpurta).add(period.multiply(offset));
}
return crToIP;
}
return null;
}
/**
* to derive the hyper-period of the observed task chain
* @param taskChain the observed task chain
* @return
* the hyper-period of the observed task chain
*/
protected Time getHyperPeriod(List<Task> taskChain) {
final List<Time> periodList = taskChain.stream().map(s -> CommonUtils.getStimInTime(s))
.collect(Collectors.toList());
Time result = periodList.get(0);
BigInteger resultBI = AmaltheaServices.convertToPicoSeconds(result);
for (int i = 1; i < periodList.size(); i++) {
final BigInteger comTime = AmaltheaServices.convertToPicoSeconds(periodList.get(i));
resultBI = getLCM(resultBI, comTime);
}
result = FactoryUtil.createTime(resultBI, TimeUnit.PS);
return result;
}
/**
* to derive the least common multiple of two different BigInteger values
* @param time0 BigInteger A
* @param time1 BigInteger B
* @return
* the least common multiple of BigInteger A and BigInteger B
*/
private BigInteger getLCM(BigInteger time0, BigInteger time1) {
return time0.multiply(time1.divide(getGCD(time0, time1)));
}
/**
* to derive the greatest common divisor of two different BigInteger values
* @param time0 BigInteger A
* @param time1 BigInteger B
* @return
* the greatest common divisor of BigInteger A and BigInteger B
*/
private BigInteger getGCD(BigInteger time0, BigInteger time1) {
while (time1.compareTo(BigInteger.ZERO) == 1) {
BigInteger temp = time1;
time1 = time0.mod(time1);
time0 = temp;
}
return time0;
}
/**
* Get an Event-Chain Entity List (Task-based)
* @param ec the observed event chain
* @return
* the corresponding EC task list
*/
public List<Task> getECTaskList(final EventChain ec) {
final List<Task> chain = new ArrayList<Task>();
for (int i = 0; i < ec.getItems().size(); i++) {
final EventChainItem eci = ec.getItems().get(i);
if (eci instanceof EventChainContainer) {
final EventChainContainer ecc = (EventChainContainer) eci;
final Event stiEvent = ecc.getEventChain().getStimulus();
if (stiEvent instanceof ProcessEvent) {
final Task stiTask = (Task)((ProcessEvent) stiEvent).getEntity();
chain.add(stiTask);
}
if (i == ec.getItems().size() - 1) {
final Event resEvent = ecc.getEventChain().getResponse();
if (resEvent instanceof ProcessEvent) {
final Task resTask = (Task)((ProcessEvent) resEvent).getEntity();
chain.add(resTask);
}
break;
}
}
}
return chain;
}
/**
* conver an event-chain to a list of Labels that belong to the chain
* @param ec the observed event-chain
* @return
* a list of the observed event-chain
*/
public List<Label> convertECtoLabels(final EventChain ec, final CPURta cpurta) {
final List<Task> chain = getECTaskList(ec);
final List<Label> labels = new ArrayList<Label>();
for (int i = 0; i < chain.size(); i++) {
final Task task = chain.get(i);
final List<Runnable> runnables = SoftwareUtil.getRunnableList(task, null);
for (int j = 0; j < runnables.size(); j++) {
final Runnable runnable = runnables.get(j);
final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
final List<Label> temp = laList.stream().map(s -> s.getData()).distinct().collect(Collectors.toList());
labels.addAll(temp);
}
/* runnables from the triggered task (gpu task) */
if (cpurta.getTriggeringTaskList().contains(task)) {
final List<ActivityGraphItem> triggerList = SoftwareUtil.collectActivityGraphItems(task.getActivityGraph(), null, (call -> call instanceof InterProcessTrigger));
final InterProcessTrigger ipt = (InterProcessTrigger) triggerList.get(0);
final InterProcessStimulus ips = ipt.getStimulus();
final Task gpuTask = cpurta.getGpuTaskList().stream().filter(s -> s.getStimuli().get(0).equals(ips)).iterator().next();
final List<Runnable> gpuRunnables = SoftwareUtil.getRunnableList(gpuTask, null);
for (int j = 0; j < gpuRunnables.size(); j++) {
final Runnable runnable = gpuRunnables.get(j);
final List<LabelAccess> laList = SoftwareUtil.getLabelAccessList(runnable, null);
final List<Label> temp = laList.stream().map(s -> s.getData()).distinct().collect(Collectors.toList());
labels.addAll(temp);
}
}
}
final List<Label> labelList = labels.stream().distinct().collect(Collectors.toList());
return labelList;
}
/**
* To check whether or not the observed task is mapped to CPU (according to the integer array)
* @param task the observed task
* @param cpurta the instance of CPURta class that contains model & mapping IA info
* @return
* boolean value that says whether or not it is mapped to CPU
*/
private static boolean isMappedToCPU (final Task task, final CPURta cpurta) {
/* The observed task is a GPU task */
if (cpurta.getGpuTaskList().contains(task)) {
final int index = cpurta.getModel().getSwModel().getTasks().indexOf(task);
final int cpuThreshold = CommonUtils.getNumberofCPUs(cpurta.getModel()) - 1;
final int[] ia = cpurta.getIA();
/* when the observed GPU task is mapped to GPU */
if (ia[index] > cpuThreshold) {
return false;
}
}
/* when the observed task(CPU or GPU) is mapped to CPU */
return true;
}
}
/**
* @Date: July 10-2019
* @version 1.0
* This inner class is used for sorting a Time type list.
* If the Time of a is smaller than that of b, it returns -1.
* If the Time of a is bigger than that of b, it returns 1.
*/
class TimeComp implements Comparator<Time> {
@Override
public int compare(final Time a, final Time b) {
if (a.compareTo(b) < 0) {
return -1;
}
return 1;
}
}