blob: 1b7f0006e7b1fea2abb888896b889bdabbadc2f3 [file] [log] [blame]
The Bao Bui8e98dab2020-06-10 19:27:25 +02001/*******************************************************************************
The Bao Bui697a6152020-06-15 10:44:18 +02002 * Copyright (c) 2020 Dortmund University of Applied Sciences and Arts.
The Bao Bui8e98dab2020-06-10 19:27:25 +02003 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
The Bao Buiadfdc4f2020-07-20 20:46:02 +020011 * Contributors: The Bao Bui
The Bao Bui8e98dab2020-06-10 19:27:25 +020012 * FH Dortmund - initial API and implementation
13 *******************************************************************************/
14package org.eclipse.app4mc.gsoc_rta;
15
16import java.math.BigDecimal;
17import java.math.BigInteger;
18import java.math.RoundingMode;
19import java.text.DecimalFormat;
20import java.util.ArrayList;
21import java.util.Arrays;
22import java.util.Collections;
23import java.util.List;
24
The Bao Bui24690e42020-07-31 12:25:04 +020025import org.slf4j.Logger;
26import org.slf4j.LoggerFactory;
The Bao Bui8e98dab2020-06-10 19:27:25 +020027import org.eclipse.app4mc.amalthea.model.Amalthea;
28import org.eclipse.app4mc.amalthea.model.AmaltheaServices;
29import org.eclipse.app4mc.amalthea.model.ProcessingUnit;
30import org.eclipse.app4mc.amalthea.model.Runnable;
31import org.eclipse.app4mc.amalthea.model.Task;
32import org.eclipse.app4mc.amalthea.model.Time;
33import org.eclipse.app4mc.amalthea.model.TimeUnit;
34import org.eclipse.app4mc.amalthea.model.util.FactoryUtil;
35import org.eclipse.app4mc.amalthea.model.util.SoftwareUtil;
36import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType;
37import org.eclipse.emf.common.util.EList;
38
39public class NPandPRTA {
40 private final int[] ia;
41 private final Amalthea model;
42 private final int[] preemptionTypeArray;
The Bao Buiadfdc4f2020-07-20 20:46:02 +020043 private boolean schedubilityCheck = true;
44 //Adding decimal Format for better visual checking when debugging
45 //ie 6000000000 ps -> 6,000,000,000 ps
46 private DecimalFormat df = new DecimalFormat("#,###.##");
The Bao Bui24690e42020-07-31 12:25:04 +020047 final Logger log = LoggerFactory.getLogger(NPandPRTA.class);
48 boolean logDebug = log.isDebugEnabled();
49 boolean logInfo = log.isInfoEnabled();
50 boolean logError = log.isErrorEnabled();
The Bao Bui8e98dab2020-06-10 19:27:25 +020051
52 /*
53 * PreemptionTypeArray will have the same length with mapping indexArray (ia), just with different value
54 * This will be set up when the class is initialize, the meaning of the number in array are:
55 * 0 = preemptive
56 * 1 = non-preemptive
57 * 2 = cooperative
58 *
59 * ia = { 5, 1, 5, 0, 1, 0, 2, 1, 2, 1, 6, 3, 4, 6 } - mapping array
60 * pta = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,} - the preemption type array
61 * this mean the first and second task of the model have non-preemption mode, the rest are preemptive
62 */
The Bao Buiadfdc4f2020-07-20 20:46:02 +020063
64
65
66 public boolean isSchedubilityCheck() {
67 return schedubilityCheck;
68 }
69
70 /**Default = true.
71 *
72 * True = return result after comparing task's blocking time and period.
73 * False = return result as long as ultilization value is less than 100 percent.
74 * @param schedubilityCheck
75 */
76 public void setSchedubilityCheck(boolean schedubilityCheck) {
77 this.schedubilityCheck = schedubilityCheck;
78 }
79
The Bao Bui8e98dab2020-06-10 19:27:25 +020080 public NPandPRTA(final Amalthea modelp, final int[] iap) {
81 this.ia = iap;
82 this.model = modelp;
83 this.preemptionTypeArray = new int[iap.length];
84 setupPTArray();
85 }
86
87 /**
The Bao Buicc5b5392020-07-20 21:05:36 +020088 * Calculate classic RTA of task using this formula Ri = Ci + Sum j among HP(i)[Ri/Tj]*Cj
The Bao Bui8e98dab2020-06-10 19:27:25 +020089 * https://www.it.uu.se/edu/course/homepage/realtid/ht10/schedule/Scheduling-periodic.pdf
90 * @param thisTask
The Bao Buiadfdc4f2020-07-20 20:46:02 +020091 * @param thisIA
The Bao Bui8e98dab2020-06-10 19:27:25 +020092 * @return
93 */
The Bao Buiadfdc4f2020-07-20 20:46:02 +020094 public Time getResponseTimeViaRecurrenceRelation(Task thisTask, int[] ia, final TimeType executionCase) {
The Bao Bui8e98dab2020-06-10 19:27:25 +020095 Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
96 /*Initialize variable to compare previous and current iteration in the formula*/
97 BigDecimal temp = BigDecimal.valueOf(2.0);
98
The Bao Buiadfdc4f2020-07-20 20:46:02 +020099 int[] thisIA = ia.clone();
The Bao Bui4773c692020-06-16 18:01:23 +0200100 CPURta rtaia = new CPURta(this.model);
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200101 List<Task> groupTaskList = groupTask(thisTask, thisIA);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200102 List<Task> sortedTaskList = rtaia.taskSorting(groupTaskList);
103
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200104 /* Check ultilization value here, if ultiValue > 100% then ultiCheck = false*/
105 boolean ultiCheck = getUltilizationCheck(sortedTaskList, thisIA, executionCase);
106 if (!ultiCheck) {
107 //result is 0
108 return result;
109 }
The Bao Bui24690e42020-07-31 12:25:04 +0200110
The Bao Bui8e98dab2020-06-10 19:27:25 +0200111 int taskIndex = sortedTaskList.indexOf(thisTask);
112 //Loop through all task inside the list (until thisTask)
113 for (int i = 0; i < taskIndex + 1; i++) {
114 //Highest priority -> get executed first all the damn time
115 if (taskIndex == 0) {
The Bao Bui24690e42020-07-31 12:25:04 +0200116 if (logDebug) {
117 String exeTimeString = df.format(getExecutionTime(thisTask, thisIA, executionCase).getValue());
118 log.debug("{} ps - Task [{}] recurrence response time", exeTimeString, thisTask.getName());
119 }
120
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200121 return getExecutionTime(thisTask, thisIA, executionCase);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200122 }
123
124 //Calculate rta by looping until the result of the previous and current are the same
125 else if (i == taskIndex) {
126 BigDecimal rZero = BigDecimal.ZERO;
127 /*Set up r_0 for the calculation*/
128 for (int j = 0; j < i + 1; j++) {
129 Task jTask = sortedTaskList.get(j);
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200130 Time jTaskExecutionTime = getExecutionTime(jTask, thisIA, executionCase);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200131 BigDecimal bigDecVal = new BigDecimal(jTaskExecutionTime.getValue());
132 rZero = rZero.add(bigDecVal);
133 }
134
135 BigDecimal currentVal = rZero;
136
137 //iterate until current value = previous value
138 while (!temp.equals(currentVal)) {
139 temp = currentVal;
140
141 /**
142 * The iteration loop of
The Bao Bui24690e42020-07-31 12:25:04 +0200143 * Ri = Ci + Sum of all hp(i)[Ri/Tj]*Cj (round up)
The Bao Bui8e98dab2020-06-10 19:27:25 +0200144 * k loop are the part after the Sum symbol, after the loop we add Ci
145 */
146 BigDecimal iteration = BigDecimal.ZERO;
147 for (int k = 0; k < i; k++) {
148 Task kTask = sortedTaskList.get(k);
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200149 Time kTaskExecutionTime = getExecutionTime(kTask, thisIA, executionCase);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200150 Time kTaskPeriod = CommonUtils.getStimInTime(kTask);
151 //Need to change all time value to PS for calculation
152 BigInteger kTaskPeriodInPs = AmaltheaServices.convertToPicoSeconds(kTaskPeriod);
153
154 //execution time and period in bigDecimal
155 BigDecimal kTaskExetimeDec = new BigDecimal(kTaskExecutionTime.getValue());
156 BigDecimal kTaskPeriodDec = new BigDecimal(kTaskPeriodInPs);
157
158 // multiplyPart = [Ri/Tj] * Cj
159 // RiTj = roundupPart, Cj = kTaskExetimeDec
The Bao Bui24690e42020-07-31 12:25:04 +0200160 BigDecimal roundUpPart = currentVal.divide(kTaskPeriodDec, 0, RoundingMode.CEILING);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200161 BigDecimal multiplyPart = roundUpPart.multiply(kTaskExetimeDec);
162 iteration = iteration.add(multiplyPart);
163 }
164 //Adding Ci after the iteration
165 Task iTask = sortedTaskList.get(i);
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200166 BigDecimal iTaskExecutionTimeDec = new BigDecimal(getExecutionTime(iTask, thisIA, executionCase).getValue());
The Bao Bui8e98dab2020-06-10 19:27:25 +0200167 currentVal = iteration.add(iTaskExecutionTimeDec);
168 }
169 BigDecimal thisTaskPeriodInBigDec = new BigDecimal(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(thisTask)));
The Bao Bui24690e42020-07-31 12:25:04 +0200170 if (currentVal.compareTo(thisTaskPeriodInBigDec) > 0 && this.schedubilityCheck) {
171
172 if (logError) {
173 String currentValString = df.format(currentVal);
174 String thisTaskPeriodInBigDecString = df.format(thisTaskPeriodInBigDec);
175 log.error("!!! UNSCHEDULABLE !!!");
176 log.error("Response time of task [{}] is bigger than its period, return 0 for RT ", thisTask.getName());
177 log.error("{} > {}", currentValString, thisTaskPeriodInBigDecString);
178 }
179
The Bao Bui8e98dab2020-06-10 19:27:25 +0200180 //result is 0
181 return result;
182 }
The Bao Bui24690e42020-07-31 12:25:04 +0200183 if (logInfo) {
184 String currentValString = df.format(currentVal);
185 log.info("{} ps - Task [{}] recurrence response time", currentValString, thisTask.getName());
186 }
The Bao Bui8e98dab2020-06-10 19:27:25 +0200187
The Bao Bui8e98dab2020-06-10 19:27:25 +0200188 //result is currentVal calculated above
189 result.setValue(currentVal.toBigInteger());
190 }
191 }
192 return result;
193 }
194
195 /**
The Bao Buicc5b5392020-07-20 21:05:36 +0200196 * Calculate RT of thisTask using busy window technique (level-i busy period)
197 * No blocking time is present here. This function is used for just simple preemptive environment case
198 * @param thisTask
199 * @param ia
200 * @param executionCase
201 * @return Time responseTime
202 */
203 public Time getResponseTimeViaLvI(Task thisTask, int[] ia, TimeType executionCase) {
204 Time responseTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
205
206 int[] thisIA = ia.clone();
207 CPURta rtaia = new CPURta(this.model);
208 List<Task> groupTaskList = groupTask(thisTask, thisIA);
209 List<Task> sortedTaskList = rtaia.taskSorting(groupTaskList);
210
211
212 /* Check ultilization value here, if ultiValue > 100% then ultiCheck = false*/
213 boolean ultiCheck = getUltilizationCheck(sortedTaskList, thisIA, executionCase);
214 if (!ultiCheck) {
215 //result is 0
216 return responseTime;
217 }
218
219 int taskIndex = sortedTaskList.indexOf(thisTask);
220 Time iPeriodTime = CommonUtils.getStimInTime(thisTask);
221 BigInteger iPeriodInPs = AmaltheaServices.convertToPicoSeconds(iPeriodTime);
222 Time iExecutionTime = getExecutionTime(thisTask, thisIA, executionCase);
223
224 /* ----- Get LEVEL - I for each task ------ */
225 BigDecimal lv0 = BigDecimal.ZERO;
226 BigDecimal currentLv = BigDecimal.ONE;
227
228 BigDecimal iPeriod = new BigDecimal(iPeriodInPs);
229 BigDecimal iExe = new BigDecimal(iExecutionTime.getValue());
230 BigDecimal iResponseTime = BigDecimal.ZERO;
231 while (!currentLv.equals(lv0)) {
232 lv0 = currentLv;
233 //entry = each small sum of [Li/Tj]Cj, p_j >= p_i ( i = taskIndex)
234 BigDecimal iterationValue = BigDecimal.ZERO;
235 for (int entry = 0; entry < taskIndex + 1; entry++) {
236 Task entryTask = sortedTaskList.get(entry);
237 BigInteger entryPeriodInPs = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(entryTask));
238 BigDecimal entryPeriod = new BigDecimal(entryPeriodInPs);
239 BigDecimal entryExe = new BigDecimal(getExecutionTime(entryTask, thisIA, executionCase).getValue());
240
241 BigDecimal roundUp = currentLv.divide(entryPeriod, 0, RoundingMode.CEILING);
242 BigDecimal entryValue = roundUp.multiply(entryExe);
The Bao Bui24690e42020-07-31 12:25:04 +0200243 if (logDebug) {
244 String roundUpString = df.format(roundUp);
245 String entryValueString = df.format(entryValue);
246 log.debug("{} round up x {}entryValue", roundUpString, entryValueString);
247 }
248
The Bao Buicc5b5392020-07-20 21:05:36 +0200249
250 iterationValue = iterationValue.add(entryValue);
251 }
252 currentLv = iterationValue;
253 }
The Bao Bui24690e42020-07-31 12:25:04 +0200254 if (logDebug) {
255 String lv0String = df.format(lv0);
256 log.debug("{} ps - level-i ", lv0String);
257 }
258
The Bao Buicc5b5392020-07-20 21:05:36 +0200259
260 /* ----- Get K (total task iteration) ------ */
261 int bigK = lv0.divide(iPeriod, 0, RoundingMode.CEILING).intValue();
262
263 /* ----- Get finishing time for each task ------ */
264 for (int smallK = 1; smallK <= bigK; smallK++) {
The Bao Bui24690e42020-07-31 12:25:04 +0200265
266 log.debug(" --- k instance : {}/{} --------------------------------------------", smallK, bigK);
The Bao Buicc5b5392020-07-20 21:05:36 +0200267 BigDecimal kLv = BigDecimal.ZERO;
268 BigDecimal currentKLv = BigDecimal.ONE;
269 BigDecimal kCi = iExe.multiply(BigDecimal.valueOf(smallK));
270 int smallK1 = smallK - 1;
271 int counter = 0;
272
273 while (!kLv.equals(currentKLv)) {
274 currentKLv = kLv;
275 //entry = each small sum of [Li/Tj]Cj, p_j > p_i, not >=
276 BigDecimal iterationValue = BigDecimal.ZERO;
277 for (int entry = 0; entry < taskIndex; entry++) {
278 Task entryTask = sortedTaskList.get(entry);
279 BigInteger entryPeriodInPs = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(entryTask));
280 BigDecimal entryPeriod = new BigDecimal(entryPeriodInPs);
281 BigDecimal entryExe = new BigDecimal(getExecutionTime(entryTask, thisIA, executionCase).getValue());
282
283 BigDecimal roundUp = currentKLv.divide(entryPeriod, 0, RoundingMode.CEILING);
284 BigDecimal entryValue = roundUp.multiply(entryExe);
285
286 iterationValue = iterationValue.add(entryValue);
287 if (counter == 0) {
288 iterationValue = BigDecimal.ZERO;
289 counter++;
290 break;
291 }
292 }
293 kLv = iterationValue;
294 kLv = kLv.add(kCi); //add k*Ci at the end of iteration
The Bao Bui24690e42020-07-31 12:25:04 +0200295 if (logDebug) {
296 log.debug("finishTime = iterationValue + k*Ci: ");
297 String s1 = df.format(iterationValue);
298 String s2 = df.format(kCi);
299 String s3 = df.format(kLv);
300 log.debug("{} + {} + {}", s1, s2, s3);
301 }
302
303
The Bao Buicc5b5392020-07-20 21:05:36 +0200304 }
305 /* ----- Get response time for each task (k) ------ */
306 BigDecimal taskStartTime = iPeriod.multiply(BigDecimal.valueOf(smallK1));
The Bao Bui24690e42020-07-31 12:25:04 +0200307 if (logDebug) {
308 String s1 = df.format(taskStartTime);
309 String s2 = df.format(kLv);
310 log.debug("start time (k*period): {} - finishing time {}", s1, s2);
311 }
312
The Bao Buicc5b5392020-07-20 21:05:36 +0200313 BigDecimal taskResponseTime = kLv.subtract(taskStartTime);
The Bao Bui24690e42020-07-31 12:25:04 +0200314 if (logDebug) {
315 String s1 = df.format(taskResponseTime);
316 log.debug("{} - this k instance response time", s1);
317 }
318
The Bao Buicc5b5392020-07-20 21:05:36 +0200319 if (taskResponseTime.compareTo(iResponseTime) >= 0) {
320 iResponseTime = taskResponseTime;
321 }
The Bao Bui24690e42020-07-31 12:25:04 +0200322 if (logDebug) {
323 String s1 = df.format(iResponseTime);
324 log.debug("{} - biggest response time so far ", s1);
325 }
The Bao Buicc5b5392020-07-20 21:05:36 +0200326 }
The Bao Bui24690e42020-07-31 12:25:04 +0200327 String taskName = thisTask.getName();
328 if (logInfo) {
329 String s1 = df.format(iResponseTime);
330 log.info("{} ps - Task [{}] level-i response time", s1, taskName);
331 }
332
The Bao Buicc5b5392020-07-20 21:05:36 +0200333
334 //Check schedulability
335 if (iResponseTime.compareTo(iPeriod) > 0 && this.schedubilityCheck) {
336 log.error("!!! UNSCHEDULABLE !!!");
The Bao Bui24690e42020-07-31 12:25:04 +0200337 log.error("Response time of task [{}] is bigger than its period, return 0 for RT ", taskName);
338 if (logError) {
339 String s1 = df.format(iResponseTime);
340 String s2 = df.format(iPeriod);
341 log.error("{} > {} ", s1, s2);
342 }
343
344
The Bao Buicc5b5392020-07-20 21:05:36 +0200345 //result is 0
346 return responseTime;
347 }
348 //Set response time value after all calculation above
349 responseTime.setValue(iResponseTime.toBigInteger());
350
351 return responseTime;
352
353 }
The Bao Bui4773c692020-06-16 18:01:23 +0200354
355 /**
356 * Calculate the execution time of longest/biggest runnable within task.
357 * @param thisTask
358 * @param ia
359 * @param executionCase
360 * @return
361 */
362 private Time getLongestRunnableExecutionTime(Task thisTask, int[] ia, TimeType executionCase) {
The Bao Bui4773c692020-06-16 18:01:23 +0200363 //set up decimal format for debugging
364 DecimalFormat df = new DecimalFormat("#,###.##");
365
366 final int currentIndex = this.model.getSwModel().getTasks().indexOf(thisTask); //get index of the task in the array
367 final int PUI = ia[currentIndex]; // get the index of processing unit
368 final List<ProcessingUnit> pul = CommonUtils.getPUs(this.model);
369 final ProcessingUnit pu = pul.get(PUI);
370
371 //comparing value to get the longer one
372 Time longest = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
373
374 final List<Runnable> runnableList = SoftwareUtil.getRunnableList(thisTask, null);
375 RTARuntimeUtil rtautil = new RTARuntimeUtil();
376 //In case a task doesn't invoke any runnable, better be careful than be sorry
377 if (!runnableList.isEmpty()) {
378 for (Runnable r : runnableList) {
379 Time runnableTime = rtautil.getExecutionTimeForRTARunnable(r, pu, executionCase);
380 if (longest.compareTo(runnableTime) <= 0) {
381 longest = runnableTime;
382 }
383 }
384 }
385
386 if (runnableList.isEmpty()) {
The Bao Bui24690e42020-07-31 12:25:04 +0200387
388 log.error("!!!The task [{}] is doing nothing, no runnable called",thisTask.getName());
The Bao Bui4773c692020-06-16 18:01:23 +0200389 }
390
The Bao Bui24690e42020-07-31 12:25:04 +0200391 if (logDebug)
392 {
393 String s1 = df.format(longest.getValue());
394 log.debug("{} ps - Longest runnable of task [{}]", s1, thisTask.getName());
395 }
The Bao Bui4773c692020-06-16 18:01:23 +0200396 return longest;
397 }
398
399 /**
The Bao Bui24690e42020-07-31 12:25:04 +0200400 * Use when task is non-preemptive
401 * Calculation thisTask's response time via level-i busy window technique.
402 * reason is for non-preemp task, finishing time = start time + execution time.
403 * Response time = finishing time - period, (using k-instance)
The Bao Bui8e98dab2020-06-10 19:27:25 +0200404 * @param thisTask
405 * @param ia
406 * @param executionCase
The Bao Bui24690e42020-07-31 12:25:04 +0200407 * @param pTypeArray - leave null if don't use
408 * @boolean usePtypeArray - true if use pType array, otherwise false
The Bao Bui8e98dab2020-06-10 19:27:25 +0200409 * @return
410 */
The Bao Bui24690e42020-07-31 12:25:04 +0200411 public Time getNonPreemptaskRTA(Task thisTask, int[] ia, TimeType executionCase, int[] pTypeArray, boolean usePtypeArray) {
The Bao Bui8e98dab2020-06-10 19:27:25 +0200412 //Adding decimal Format for better visual checking when debugging
413 //ie 6000000000 ps -> 6,000,000,000 ps
The Bao Bui24690e42020-07-31 12:25:04 +0200414 Time responseTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
415
416
417 //time that lp tasks may block thisTask in worst case response time
418 BigDecimal blockingTime = new BigDecimal(getLowerPriorityBlockingTime(thisTask, ia, executionCase, pTypeArray, usePtypeArray).getValue());
419
The Bao Bui4773c692020-06-16 18:01:23 +0200420 CPURta rtaia = new CPURta(this.model);
The Bao Bui24690e42020-07-31 12:25:04 +0200421 int[] thisIA = ia.clone();
The Bao Bui4773c692020-06-16 18:01:23 +0200422
The Bao Bui24690e42020-07-31 12:25:04 +0200423 List<Task> sortedTaskList = rtaia.taskSorting(groupTask(thisTask, thisIA));
The Bao Bui8e98dab2020-06-10 19:27:25 +0200424
The Bao Bui24690e42020-07-31 12:25:04 +0200425 /* Check ultilization value here, if ultiValue > 100% then ultiCheck = false*/
426 boolean ultiCheck = getUltilizationCheck(sortedTaskList, thisIA, executionCase);
427 if (!ultiCheck) {
428 //response time = 0 here, cuz the core would be damned if we use this set
429 return responseTime;
The Bao Bui8e98dab2020-06-10 19:27:25 +0200430 }
431
The Bao Bui24690e42020-07-31 12:25:04 +0200432 int taskIndex = sortedTaskList.indexOf(thisTask);
433 Time iPeriodTime = CommonUtils.getStimInTime(thisTask);
434 BigInteger iPeriodInPs = AmaltheaServices.convertToPicoSeconds(iPeriodTime);
435 Time iExecutionTime = getExecutionTime(thisTask, thisIA, executionCase);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200436
The Bao Bui8e98dab2020-06-10 19:27:25 +0200437
The Bao Bui24690e42020-07-31 12:25:04 +0200438 /* ----- Get LEVEL - I for each task ------ */
439 BigDecimal lv0 = BigDecimal.ZERO;
440 BigDecimal currentLv = BigDecimal.ONE;
441
442 BigDecimal iPeriod = new BigDecimal(iPeriodInPs);
443 BigDecimal iExe = new BigDecimal(iExecutionTime.getValue());
444 BigDecimal iResponseTime = BigDecimal.ZERO;
445 String taskName = thisTask.getName();
446 /* If blocking time is equal/bigger than task period, then unschedulable for sure,
447 * just return 0 and warning, no need for further calculation*/
448 if (blockingTime.compareTo(iPeriod) >= 0 && this.schedubilityCheck) {
The Bao Bui8e98dab2020-06-10 19:27:25 +0200449 log.error("!!! UNSCHEDULABLE !!!");
The Bao Bui24690e42020-07-31 12:25:04 +0200450 log.error("Blocking time of task [{}] is bigger than its period, return 0 for RT ", taskName);
451 if (logError) {
452 String s1 = df.format(blockingTime);
453 String s2 = df.format(iPeriod);
454 log.error("{} > {} ", s1, s2);
455 }
The Bao Bui8e98dab2020-06-10 19:27:25 +0200456 //result is 0
The Bao Bui24690e42020-07-31 12:25:04 +0200457 return responseTime;
The Bao Bui8e98dab2020-06-10 19:27:25 +0200458 }
The Bao Bui8e98dab2020-06-10 19:27:25 +0200459
The Bao Bui24690e42020-07-31 12:25:04 +0200460 //sum of execution time of all tasks with higher prio not including this task (in TU Dortmund say included, they are imbecile )
461 BigDecimal hpCiSum = BigDecimal.ZERO;
462
463 int iterationCounterLvI = 0;
464 while (!currentLv.equals(lv0)) {
465 lv0 = currentLv;
466 //entry = each small sum of [Li/Tj]Cj, p_j >= p_i ( i = taskIndex)
467 BigDecimal iterationValue = BigDecimal.ZERO;
468
469 for (int entry = 0; entry < taskIndex + 1; entry++) {
470 Task entryTask = sortedTaskList.get(entry);
471 BigInteger entryPeriodInPs = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(entryTask));
472 BigDecimal entryPeriod = new BigDecimal(entryPeriodInPs);
473 BigDecimal entryExe = new BigDecimal(getExecutionTime(entryTask, thisIA, executionCase).getValue());
474
475 BigDecimal roundUp = currentLv.divide(entryPeriod, 0, RoundingMode.CEILING);
476 BigDecimal entryValue = roundUp.multiply(entryExe);
477
478 iterationValue = iterationValue.add(entryValue);
479 }
480 //First entry of level-i = Bi + Ci, the sum above doesn't exist (or maybe 1, not gonna risk it hence the code below)
481 //check non-premptive scheduler from TUDortmund pdf, google that shit
482 if (iterationCounterLvI == 0) {
483 iterationValue = iExe;
484 }
485 iterationCounterLvI++;
486 /* -- Add blocking for nonpreemptive here-- current lv plus blocking*/
487 iterationValue = iterationValue.add(blockingTime);
488 currentLv = iterationValue;
489 }
490 if (logDebug) {
491 String lv0String = df.format(lv0);
492 log.debug("{} ps - level-i ", lv0String);
493 }
494 /* ----- Get K (total task iteration) ------ */
495 int bigK = lv0.divide(iPeriod, 0, RoundingMode.CEILING).intValue();
496
497 /* ----- Get start time for each task ------ */
498 /**
499 * Things get more complicated from here, we get preemption from higher prio, blocking from lower prio
500 * so we have to calculate the START TIMEEEE with blocking, my man
501 */
502 for (int smallK = 1; smallK <= bigK; smallK++) {
503 log.debug(" --- k instance : {}/{} --------------------------------------------", smallK, bigK);
504 BigDecimal kLv = BigDecimal.ZERO;
505 BigDecimal currentKLv = BigDecimal.ONE;
506 int smallK1 = smallK - 1;
507 BigDecimal kCi1 = iExe.multiply(BigDecimal.valueOf(smallK1));
508
509 //Equation from Tu Dortmund for this is wrong, it's < taskIndex, not < i.
510 for (int entry = 0; entry < taskIndex; entry++) {
511 Task entryTask = sortedTaskList.get(entry);
512 BigDecimal entryExe = new BigDecimal(getExecutionTime(entryTask, thisIA, executionCase).getValue());
513 hpCiSum = hpCiSum.add(entryExe);
514 }
515
516 int iterationCounterK = 0;
517
518 while (!kLv.equals(currentKLv)) {
519 currentKLv = kLv;
520 //entry = each small sum of [Li/Tj]Cj (rown down), j > i, not >=
521 BigDecimal iterationValue = BigDecimal.ZERO;
522 for (int entry = 0; entry < taskIndex; entry++) {
523 Task entryTask = sortedTaskList.get(entry);
524 BigInteger entryPeriodInPs = AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(entryTask));
525 BigDecimal entryPeriod = new BigDecimal(entryPeriodInPs);
526 BigDecimal entryExe = new BigDecimal(getExecutionTime(entryTask, thisIA, executionCase).getValue());
527
528 BigDecimal roundDown = currentKLv.divide(entryPeriod, 0, RoundingMode.FLOOR);
529 BigDecimal roundDownPlusOne = roundDown.add(BigDecimal.ONE);
530 BigDecimal entryValue = roundDownPlusOne.multiply(entryExe);
531
532 iterationValue = iterationValue.add(entryValue);
533 }
534 kLv = iterationValue;
535 kLv = kLv.add(kCi1); //add k*Ci at the end of iteration
536
537 //first iteration = Bi + hpCiSum
538 if (iterationCounterK == 0) {
539 log.debug("hpCiSum - {} blocking {}", hpCiSum, blockingTime);
540 kLv = hpCiSum;
541 //reseti this for next k-task
542 hpCiSum = BigDecimal.ZERO;
543 }
544 log.debug("iterationValue + (k-1)*Ci + blockingtime (ignore if first iteration)");
545 log.debug("{} + {} + {}", iterationValue, kCi1, blockingTime);
546 kLv = kLv.add(blockingTime); // add blocking time here
547 log.debug("current iteration : {}", kLv);
548 iterationCounterK++;
549 }
550 /* ----- Get response time for each task (k) ------ */
551 BigDecimal taskStartTime = kLv;
552 BigDecimal taskFinishingTime = taskStartTime.add(iExe);
553 BigDecimal taskStartPeriod = iPeriod.multiply(BigDecimal.valueOf(smallK1));
554
555 if (logDebug) {
556 String s1 = df.format(taskStartTime);
557 String s2 = df.format(iExe);
558 String s3 = df.format(taskFinishingTime);
559 String s4 = df.format(taskStartPeriod);
560 log.debug("start time : {} + execution time: {} + finishing time: {}; period: {}", s1, s2, s3, s4);
561 }
562 BigDecimal taskResponseTime = taskFinishingTime.subtract(taskStartPeriod);
563 if (logDebug) {
564 String s1 = df.format(taskResponseTime);
565 log.debug("{} - this k instance response time ", s1);
566 }
567
568 if (taskResponseTime.compareTo(iResponseTime) >= 0) {
569 iResponseTime = taskResponseTime;
570 }
571 if (logDebug) {
572 String s1 = df.format(iResponseTime);
573 log.debug("{} - biggest response time so far ", s1);
574 }
575 }
576 if (logInfo) {
577 String s1 = df.format(iResponseTime);
578 log.info("{} ps - Task [{}] response time (non-preemp level-i)", s1, taskName);
579 }
580
581 //Check schedulability
582 if (iResponseTime.compareTo(iPeriod) > 0 && this.schedubilityCheck) {
583 log.error("!!! UNSCHEDULABLE !!!");
584 log.error("Response time of task [{}] is bigger than its period, return 0 for RT ", taskName);
585 if (logError) {
586 String s1 = df.format(iResponseTime);
587 String s2 = df.format(iPeriod);
588 log.error("{} > {} ", s1, s2);
589 }
590 //result is 0
591 return responseTime;
592 }
593 //Set response time value after all calculation above
594 responseTime.setValue(iResponseTime.toBigInteger());
595
596 return responseTime;
The Bao Bui8e98dab2020-06-10 19:27:25 +0200597 }
598
The Bao Bui24690e42020-07-31 12:25:04 +0200599 /**
600 * Calculate time that [thisTask] would be blocked by lower priority task (when lp task is non-preemptive type or cooperative type)
601 * @param thisTask
602 * @param ia
603 * @param executionCase
604 * @param pTypeArray - leave null if don't use
605 * @boolean usePtypeArray - true if use pType array, otherwise false
606 * @return Time blockingTime
607 */
608 public Time getLowerPriorityBlockingTime(Task thisTask, int[] ia, TimeType executionCase, int[] pTypeArray, boolean usePtypeArray) {
The Bao Bui8e98dab2020-06-10 19:27:25 +0200609
The Bao Bui24690e42020-07-31 12:25:04 +0200610 Time blockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
611 int[] preemptiveArray;
612 int[] thisIA = ia.clone();
613 if (usePtypeArray) {
614 preemptiveArray = pTypeArray.clone();
615 }
616 else {
617 preemptiveArray = this.preemptionTypeArray.clone();
618 }
619
620 /*Get list of tasks that are on the same processor, then sort it from higher prio -> lower prio*/
621 CPURta rtaia = new CPURta(this.model);
622 EList<Task> listTask = this.model.getSwModel().getTasks(); //just get all the task on the list, for fun, or check it yourself below
623 List<Task> groupTaskList = groupTask(thisTask, thisIA);
624 List<Task> sortedTaskList = rtaia.taskSorting(groupTaskList);
625 String taskName = thisTask.getName();
626
627 if (logDebug) {
628 String s1 = CommonUtils.getStimInTime(thisTask).toString();
629 log.debug("-- get blocking time of task [{}] - period: {} ", taskName, s1);
630 }
631
632 /*Reverse the order from highest -> lowest to the opposite lowest -> highest,whatever in front of our index is lower priority */
633 Collections.reverse(sortedTaskList);
634
635 /*------------------- Get blocking time from lp task ------------------*/
636 /* Loop through all the task in the sorted Task list and until we see thisTask, calculate blocking time while looping,
637 * the longest among all blocking time will be WCBlockingTime for [thisTask]
638 * I have reversed the order of the task list above so we will capture all task with lower priority via top down iteration
639 * lowest -> highest prio
640 * and when we get to [thisTask], that means we have scanned all task with lower priority -> break the loop
641 */
642 for (Task task : sortedTaskList) {
643 //Get out of the loop when we met thisTask in the sorted task list
644 //Without this, lowerPriorityTaskList will add the task with higher priority
645 if (task.equals(thisTask)) {
646 break;
647 }
648
649 Time tempBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
650 int taskIndex = listTask.indexOf(task);
651 int preempTypeValue = preemptiveArray[taskIndex];//listTask used to get preemptive type my dude,
652 String preemp = task.getPreemption().getLiteral();
653 Time taskPeriod = CommonUtils.getStimInTime(task);
654
655 log.debug(" checking task" + " [{}] - period {}- preemptiveType : {}", task.getName(), taskPeriod, preemp);
656 //If task has lower priority and is non-preemptive (preempTypeValue = 1 ), calculate that task's execution time
657 if (!task.equals(thisTask) && preempTypeValue == 1) {
658 tempBlockingTime = getExecutionTime(task, thisIA, executionCase);
659 if (logDebug) {
660 String s1 = df.format(tempBlockingTime.getValue());
661 String s2 = task.getName();
662 log.debug("{} ps - non-preemptive blocking time from task [{}]", s1, s2);
663 }
664 if (tempBlockingTime.compareTo(blockingTime) >= 0)
665 blockingTime = tempBlockingTime;
666
667 }
668
669 //If task has lower priority and is cooperative (preempTypeValue = 2 ), calculate the longest runnable
670 else if (!task.equals(thisTask) && preempTypeValue == 2) {
671 tempBlockingTime = getLongestRunnableExecutionTime(task, thisIA, executionCase);
672 if (logDebug) {
673 String s1 = df.format(tempBlockingTime.getValue());
674 String s2 = task.getName();
675 log.debug("{} ps - cooperative blocking time from task [{}]", s1, s2);
676 }
677 if (tempBlockingTime.compareTo(blockingTime) >= 0)
678 blockingTime = tempBlockingTime;
679 }
680 /* If all lower priority task are neither non-preemptive nor cooperative, blocking time = 0 (because it can only be preemptive)
681 * These line can be omit but meh, for a clearer picture (or messy I don't know)*/
682 if (tempBlockingTime.compareTo(blockingTime) >= 0)
683 blockingTime = tempBlockingTime;
684 }
685 if (logDebug) {
686 String s1 = df.format(blockingTime.getValue());
687 String s2 = thisTask.getName();
688 log.debug("{} ps - worst case blocking time of task [{}] from lower priority tasks", s1, s2);
689 }
690 return blockingTime;
691 }
The Bao Bui8e98dab2020-06-10 19:27:25 +0200692 /**
The Bao Bui4773c692020-06-16 18:01:23 +0200693 * Calculation uses classic RTA + max(max_{j of type NP and in lp(i)} C_j; max_{k of type C and in lp(i)} c_k.
694 * basically just add a blocking time
695 * (choose the longest time, task A will be block by another task (B/C/D) depends on each's execution time
696 * or each's runnable's execution time) among tasks within the same processor depend on each's preemption mode
697 * @param thisTask
698 * @param ia
699 * @param executionCase
700 * @return
701 */
702 public Time getMixedPreempRTA(Task thisTask, int[] ia, TimeType executionCase) {
703 //Adding decimal Format for better visual checking when debugging
704 //ie 6000000000 ps -> 6,000,000,000 ps
705 DecimalFormat df = new DecimalFormat("#,###.##");
The Bao Bui4773c692020-06-16 18:01:23 +0200706 EList<Task> listTask = this.model.getSwModel().getTasks();
707 Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
708 Time nonPreempBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
709 Time coopBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200710 Time taskClassicRTA = getResponseTimeViaRecurrenceRelation(thisTask, ia, executionCase);
The Bao Bui4773c692020-06-16 18:01:23 +0200711 CPURta rtaia = new CPURta(this.model);
712
713 List<Task> sortedTaskList = rtaia.taskSorting(groupTask(thisTask, ia));
714
715 //Reverse the order from highest -> lowest to the opposite lowest -> highest
716 Collections.reverse(sortedTaskList);
717 List<Task> npLowerPriorityTaskList = new ArrayList<>();
718 List<Task> coopLowerPriorityTaskList = new ArrayList<>();
719
720
721 /*Loop through all the task in the sorted Task list and add them to lowerPriorityTaskList until we see thisTask
722 * I have reversed the order of the task list above so we will capture all task with lower priority via top down iteration
723 * lowest -> highest prio
724 */
725 for (Task task : sortedTaskList) {
726 int taskIndex = listTask.indexOf(task);
727 int preempTypeValue = this.preemptionTypeArray[taskIndex];
728 //add task to our list if it has lower priority and is non-preemptive (preempTypeValue = 1 )
729 if (!task.equals(thisTask) && preempTypeValue == 1) {
730 npLowerPriorityTaskList.add(task);
731 }
732
733 //add task to the list if has lower priority and in cooperative (preempTypeValue = 2 )
734 else if (!task.equals(thisTask) && preempTypeValue == 2) {
735 coopLowerPriorityTaskList.add(task);
736 }
737 //Get out of the loop when we met thisTask in the sorted task list
738 //Without this, lowerPriorityTaskList may add the task with higher priority
739 else if (task.equals(thisTask)) {
740 break;
741 }
742 }
743
744
745 /**
746 * if there is no non-preemptive task with lower priority allocate to the processor
747 */
748 if (npLowerPriorityTaskList.isEmpty()) {
749 //blockingTime = 0 initially
750 result = result.add(nonPreempBlockingTime);
751 log.debug(df.format(nonPreempBlockingTime.getValue()) + " ps - Non-preemptive blocking time, no blocking");
752 }
753
754 /**
755 * if there is no cooperative task with lower priority in the same processor
756 */
757 if (coopLowerPriorityTaskList.isEmpty()) {
758 //coop blocking time = 0
759 result = result.add(coopBlockingTime);
760 log.debug(df.format(coopBlockingTime.getValue()) + " ps - Cooperative blocking time, no blocking");
761 }
762
763
764 /**
765 * adding blocking time of lower priority task with non-preemptive mode and cooperative
766 * Take the longer blocking time among the 2
767 * Only block if there either/both task in our task lists (coop + np)
768 */
769 if (!npLowerPriorityTaskList.isEmpty() || !coopLowerPriorityTaskList.isEmpty()) {
770 for (Task task : npLowerPriorityTaskList) {
771 int taskIndex = listTask.indexOf(task);
772 Time currentBlockingTime = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
773
774 /**
775 * 1 task can only have either np or coop preemption mode anyway
776 */
777 if (this.preemptionTypeArray[taskIndex] == 1) {
778 currentBlockingTime = getExecutionTime(task, ia, executionCase);
779 }
780 else if (this.preemptionTypeArray[taskIndex] == 2) {
781 currentBlockingTime = getLongestRunnableExecutionTime(thisTask, ia, executionCase);
782 }
783
784 /**
785 * after the above we will have the time that [thisTask] is blocked by [task] potentially
786 * We only need to loop through all task in [listTask] to find which [task] block [thisTask] the longest
787 *
788 */
789
790 //Compare to find the longer one when iterate
791 if (nonPreempBlockingTime.compareTo(currentBlockingTime) <= 0) {
792 nonPreempBlockingTime = currentBlockingTime;
793 }
794 log.debug(df.format(currentBlockingTime.getValue()) + " ps - Lower priority task [" + task.getName() + "] blockingTime");
795 }
796 //add blocking time when we have find the maximum execution time among
797 result = result.add(nonPreempBlockingTime);
798 log.debug(df.format(nonPreempBlockingTime.getValue()) + " ps - Final Non-preemptive/coop blocking time: ");
799 }
800 //final result should be RTA = blockingTime + classicRTA(task)
801 result = result.add(taskClassicRTA);
802
803
804 BigDecimal thisTaskPeriodInBigDec = new BigDecimal(AmaltheaServices.convertToPicoSeconds(CommonUtils.getStimInTime(thisTask)));
805 if (result.getValue().compareTo(thisTaskPeriodInBigDec.toBigInteger()) > 0) {
806 log.error("!!! UNSCHEDULABLE !!!");
807 log.error("Response time of task [" + thisTask.getName() + "] is bigger than its period, return 0 for RT ");
808 log.error(df.format(result.getValue()) + " > " + df.format(thisTaskPeriodInBigDec));
809 //result is 0
810 result.setValue(BigInteger.ZERO);
811 return result;
812 }
813 log.debug(df.format(result.getValue()) + "ps - Task [" + thisTask.getName() + "] NP environment response time :");
814
815 return result;
816 }
817
818
819 /**
The Bao Bui8e98dab2020-06-10 19:27:25 +0200820 * this function will get PURE execution time via calculate execution time of task's runnables
821 * @param thisTask
822 * @param ia
823 * @return
824 */
825 public Time getPureExecutionTime(Task thisTask, int[] ia, final TimeType executionCase) {
826 Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
827 final int currentIndex = this.model.getSwModel().getTasks().indexOf(thisTask); //get index of the task in the array
828 final int PUI = ia[currentIndex]; // get the index of processing unit
829 final List<ProcessingUnit> pul = CommonUtils.getPUs(this.model);
830 final ProcessingUnit pu = pul.get(PUI);
831 RTARuntimeUtil rtautil = new RTARuntimeUtil();
The Bao Bui4773c692020-06-16 18:01:23 +0200832
The Bao Bui8e98dab2020-06-10 19:27:25 +0200833 /* The list of runnables of the given task */
834 final List<Runnable> runnableList = SoftwareUtil.getRunnableList(thisTask, null);
835
836 /*Add all execution time of runnable inside thisTask to get its PURE execution time*/
837 for (Runnable r : runnableList) {
838 Time runnableExecutionTime = rtautil.getExecutionTimeForRTARunnable(r, pu, executionCase);
839 result = result.add(runnableExecutionTime);
840 }
841 return result;
842 }
843
844 /**May sound stupid in the beginning but this will make things easier to control when
845 * Adding blocking/contention at the end of the function.
846 * @param thisTask
847 * @param ia
848 * @param executionCase
849 * @return
850 */
851 private Time getExecutionTime(Task thisTask, int[] ia, final TimeType executionCase) {
852 Time result = FactoryUtil.createTime(BigInteger.ZERO, TimeUnit.PS);
853
854 result = result.add(getPureExecutionTime(thisTask, ia, executionCase));
855 /**
856 * Add other blocking/waiting method here if needed.
857 */
858 return result;
859 }
The Bao Buiadfdc4f2020-07-20 20:46:02 +0200860
861 /**
862 * Get core ultilization percentage by Sum all [Ci/Ti] (i = tasks in the same core)
863 * return false If [Ci/Ti] > 1 or ulti percentage > 100%
864 * groupTask = List<Task> that in the same core
865 * @param groupTask
866 * @param ia
867 * @param executionCase
868 * @return
869 */
870
871 public boolean getUltilizationCheck(List<Task> groupTask, int[] ia, TimeType executionCase) {
872 boolean checkValue = true;
873 BigDecimal ultiValue = BigDecimal.ZERO;
874 int[] thisIA = ia.clone();
875 for (Task task : groupTask) {
876 Time taskPeriod = CommonUtils.getStimInTime(task);
877 Time taskExe = getExecutionTime(task, thisIA, executionCase);
878 BigDecimal numerator = new BigDecimal(taskExe.getValue());
879 BigDecimal denominator = new BigDecimal(AmaltheaServices.convertToPicoSeconds(taskPeriod));
880 //scale = 9 here means 9 digit after the damn commaaaaa, why scale 9? because feng shui my dude.
881 BigDecimal division = numerator.divide(denominator, 9, RoundingMode.HALF_UP);
882 ultiValue = ultiValue.add(division);
883 }
884 log.debug(ultiValue.multiply(BigDecimal.valueOf(100)) + " % - core ultilization Value ");
885
886 //if ultilization percentage > 100% then core exceed it maximum workable ability, should never happen
887 if (ultiValue.compareTo(BigDecimal.ONE) > 0) {
888 log.error("!!! UNSCHEDULABLE !!!");
889 log.error("Ultilization value :" + ultiValue.multiply(BigDecimal.valueOf(100)) + " exceed 100% ");
890 checkValue = false;
891 }
892
893 return checkValue;
894 }
The Bao Bui8e98dab2020-06-10 19:27:25 +0200895
896 /**
897 * Initialize preemptive array.
898 */
899
900 private void setupPTArray() {
The Bao Bui8e98dab2020-06-10 19:27:25 +0200901 log.debug("Initialize class NPandPRTA");
902 EList<Task> listTask = this.model.getSwModel().getTasks();
903 for (Task task : listTask) {
904 int taskIndex = listTask.indexOf(task);
905 String preemp = task.getPreemption().getLiteral();
906 if (preemp.matches("preemptive")) {
907 this.preemptionTypeArray[taskIndex] = 0;
908 }
909 else if (preemp.matches("non_preemptive")) {
910 this.preemptionTypeArray[taskIndex] = 1;
911 }
912 else if (preemp.matches("cooperative")) {
913 this.preemptionTypeArray[taskIndex] = 2;
914 }
915 }
916
The Bao Bui24690e42020-07-31 12:25:04 +0200917 if (logDebug)
918 {
919 String s1 = Arrays.toString(this.ia);
920 String s2 = Arrays.toString(this.preemptionTypeArray) ;
921 log.debug("{} - ia", s1);
922 log.debug("{} - pta",s2);
923 }
924
The Bao Bui8e98dab2020-06-10 19:27:25 +0200925
926 }
927
928 private List<Task> groupTask(final Task thisTask, int[] ia) {
929 final List<Task> stepOneTaskList = new ArrayList<>();
930 final EList<Task> taskList = this.model.getSwModel().getTasks();
931 final int currentIndex = this.model.getSwModel().getTasks().indexOf(thisTask);
The Bao Bui4773c692020-06-16 18:01:23 +0200932
933 CPURta rtaia = new CPURta(this.model);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200934 final int PUI = ia[currentIndex];
935 for (int i = 0; i < ia.length; i++) {
936 if (PUI == ia[i]) {
937 stepOneTaskList.add(taskList.get(i));
938 }
939 }
940
941 return rtaia.taskSorting(stepOneTaskList);
The Bao Bui8e98dab2020-06-10 19:27:25 +0200942
The Bao Bui4773c692020-06-16 18:01:23 +0200943 }
The Bao Bui8e98dab2020-06-10 19:27:25 +0200944
945
946}