blob: 3464893a3b451d7c082f3c5cd1418922f31420ca [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2020
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
******************************************************************************/
/*------------------------------------------------------------------------------
-
- Copyright (c) 2015-2016 University of Padova, ITALY - Intecs SpA
- All rights reserved. This program and the accompanying materials
- are made available under the terms of the Eclipse Public License v2.0
- which accompanies this distribution, and is available at
- http://www.eclipse.org/legal/epl-v20.html
-
- Contributors:
-
- Alessandro Zovi azovi@math.unipd.it
- Stefano Puri stefano.puri@intecs.it
- Laura Baracchi laura.baracchi@intecs.it
- Nicholas Pacini nicholas.pacini@intecs.it
-
- Initial API and implementation and/or initial documentation
------------------------------------------------------------------------------*/package org.polarsys.chess.multicore.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Component;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.InstanceSpecification;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Package;
import org.polarsys.chess.chessmlprofile.Predictability.DeploymentConfiguration.HardwareBaseline.CH_HwProcessor;
import org.polarsys.chess.chessmlprofile.Predictability.RTComponentModel.CHRtSpecification;
import org.polarsys.chess.core.profiles.CHESSProfileManager;
import org.polarsys.chess.core.util.uml.ModelError;
import org.polarsys.chess.core.util.uml.UMLUtils;
import org.polarsys.chess.multicore.dialogs.SystemSelectionDialog;
import org.polarsys.chess.multicore.model.AbstractCommand;
import org.polarsys.chess.multicore.model.CHCore;
import org.polarsys.chess.multicore.model.CHTask;
import org.polarsys.chess.multicore.model.SupertaskInfo;
import org.polarsys.chess.multicore.partitioning.Bin;
import org.polarsys.chess.multicore.partitioning.BinPackerFactory;
import org.polarsys.chess.multicore.partitioning.RUNReduction;
import org.polarsys.chess.multicore.partitioning.Task;
import org.polarsys.chess.multicore.utils.GeneratorUtils;
import org.polarsys.chess.multicore.utils.QueryUtils;
import org.polarsys.chess.multicore.utils.QueryUtils.OccKindInfo;
import org.polarsys.chess.validator.constraints.StringParser;
/**
* The Class GenerateTask2CoreAssignmentsCommand.
*/
public class GenerateTask2CoreAssignmentsCommand extends AbstractCommand {
/** The operation list. */
private HashMap<CHTask, EList<CHTask>> operationList;
/** The core 2 chtask. */
private Map<CHCore, LinkedHashSet<Object>> core2chtask;
/** The processors. */
private EList<InstanceSpecification> processors;
/** The cores. */
private EList<CHCore> cores = new BasicEList<CHCore>();
/** The assigned operations. */
private Set<CHTask> assignedOperations = new HashSet<CHTask>();
/** The processors map. */
private Map<Package, EList<InstanceSpecification>> processorsMap = new HashMap<Package, EList<InstanceSpecification>>();
/** The cores map. */
private Map<InstanceSpecification, EList<CHCore>> coresMap = new HashMap<InstanceSpecification, EList<CHCore>>();
/** The hw system. */
private static Component hwSystem;
/** The hw systems list. */
private EList<InstanceSpecification> hwSystemsList = new BasicEList<InstanceSpecification>();
/** The use RUN. */
private boolean useRUN;
/** The supertask info list. */
private List<SupertaskInfo> supertaskInfoList;
/** The core 2 supertask. */
private HashMap<SupertaskInfo, LinkedHashSet<Object>> core2supertask;
/**
* Open selector to choose HW system where assign tasks.
*
* @param umlModel the uml model
* @param hwSystemsList the hw systems list
* @return the instance specification
*/
private static InstanceSpecification openSystemSelector(Model umlModel, EList<InstanceSpecification> hwSystemsList) {
// First of all show selector to select HwSystem
List<InstanceSpecification> systemSelection = new ArrayList<InstanceSpecification>();
for (InstanceSpecification syst : hwSystemsList) {
systemSelection.add(syst);
}
Shell activeShell = Display.getDefault().getActiveShell();
SystemSelectionDialog systemDialog = new SystemSelectionDialog(activeShell, systemSelection, "Select System where to assign tasks");
if (systemDialog.open() == Window.OK) {
String selectedSystemQN = systemDialog.getSystemName();
EList<Element> allElems = umlModel.allOwnedElements();
for (Element elem : allElems) {
InstanceSpecification theSystem;
if (elem instanceof InstanceSpecification) {
theSystem = (InstanceSpecification) elem;
if (theSystem.getQualifiedName() != null && theSystem.getQualifiedName().equals(selectedSystemQN)) {
Classifier classif = theSystem.getClassifiers().get(0);
hwSystem = (Component) classif;
return theSystem;
}
}
}
}
return null;
}
/* (non-Javadoc)
* @see org.polarsys.chess.multicore.model.AbstractCommand#execute()
*/
@Override
public void execute() throws ModelError {
queryContent(umlModel);
int howMany = hwSystemsList.size();
InstanceSpecification theSystem = null;
if (howMany > 1) {
theSystem = openSystemSelector(umlModel, hwSystemsList);
} else {
theSystem = hwSystemsList.get(0);
}
if (theSystem != null) {
Package pack = QueryUtils.getOwnerCHGaResourcePlatformPackage(umlModel, theSystem);
EList<InstanceSpecification> processorList = processorsMap.get(pack);
cores = new BasicEList<CHCore>();
if (processorList != null) {
for (InstanceSpecification proc : processorList) {
EList<CHCore> coreList = coresMap.get(proc);
for (CHCore core : coreList) {
cores.add(core);
}
}
}
executeTask2CoreCalculator(false);
// printContent();
if (core2chtask != null) {
updateModel();
}
}
}
/**
* Execute task 2 core calculator.
*
* @param forceUseOfRUN the force use of RUN
* @throws ModelError the model error
*/
protected void executeTask2CoreCalculator(boolean forceUseOfRUN) throws ModelError {
List<Bin> allBins = new ArrayList<Bin>();
List<Task> allTasks = new ArrayList<Task>();
System.out.format("We have %d cores\n", cores.size());
// init bins
for (int i = 0; i < cores.size(); i++)
allBins.add(new Bin(i));
for (CHTask chRtSpecification : operationList.keySet()) {
String occKind = chRtSpecification.getCHRtSpecification().getOccKind();
OccKindInfo info = QueryUtils.getOccKindInfo(occKind);
double c_ = QueryUtils.getWCET(chRtSpecification.getCHRtSpecification());
/* add the wcet for each operation relative to this chrtspec */
for (CHTask spec : operationList.get(chRtSpecification)) {
double c_1 = QueryUtils.getWCET(spec.getCHRtSpecification());
c_ += c_1;
}
StringParser sp = new StringParser();
double d_ = sp.getValueNFP(chRtSpecification.getCHRtSpecification().getRlDl());
double t_ = info.value;
// d_ = xxx.remove(0);
// t_ = d_;
String name = getTaskID(chRtSpecification.getCHRtSpecification());
float c = (float) c_;// exec time
float d = (float) d_;// deadline
float t = (float) t_;// period
float o = 0;// TODO insert offset in stereotype
double u_ = c / t;
float u = (float) u_;
System.out.println("Task " + name + " -> " + c + " " + d + " " + t + " -> " + u);
allTasks.add(new Task(name, new Float(c), new Float(d), new Float(t), new Float(o), null));
}
Map<Bin, List<Task>> firstPack = BinPackerFactory.getBinPacker(org.polarsys.chess.multicore.partitioning.Heuristic.WORST_FIT).pack(allBins, allTasks);
Map<Bin, List<Task>> reductionTree = new Hashtable<Bin, List<Task>>(firstPack);
useRUN = reductionTree.size() > allBins.size();
if (forceUseOfRUN)
useRUN = true;
if (useRUN) {
System.out.println("Starting RUN packing");
allTasks = new ArrayList<Task>();
for (Bin bin : reductionTree.keySet())
allTasks.add(new Task(bin.getId().toString(), bin.getCapacity()));
reductionTree = new RUNReduction().pack(null, allTasks);
for (java.util.Map.Entry<Bin, List<Task>> row : reductionTree.entrySet()) {
System.out.print("LEVEL " + row.getKey().getLevel() + "-" + row.getKey().getId() + "(U=" + row.getKey().getCapacity() + ") -> {");
for (Task t : row.getValue())
System.out.print(" " + t.getId() + ",");
System.out.println("}");
}
buildRUNAssociations(firstPack, reductionTree);
} else
// Build model results
buildAssociations(firstPack);
}
/**
* Builds the RUN associations.
*
* @param firstPack the first pack
* @param reductionTree the reduction tree
* @throws ModelError the model error
*/
private void buildRUNAssociations(Map<Bin, List<Task>> firstPack, Map<Bin, List<Task>> reductionTree) throws ModelError {
// add chtasks which represent real tasks to the core map and add the
// related operation chain to the same core
// TODO solve the following problem: the related operations may be shared
// between tasks which can be assigned to different cores!
core2supertask = new HashMap<SupertaskInfo, LinkedHashSet<Object>>();
Object[] firstPackSorted = firstPack.entrySet().toArray();
Arrays.sort(firstPackSorted, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
if (((Entry<Bin, List<Task>>) o1).getKey().getId() > ((Entry<Bin, List<Task>>) o2).getKey().getId())
return 1;
else if (((Entry<Bin, List<Task>>) o1).getKey().getId() < ((Entry<Bin, List<Task>>) o2).getKey().getId())
return -1;
else
return 0;
}
});
Object[] allBins = reductionTree.keySet().toArray();
Arrays.sort(allBins, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
if (((Bin) o1).getLevel() > ((Bin) o2).getLevel())
return -1;
else if (((Bin) o1).getLevel() < ((Bin) o2).getLevel())
return 1;
else
return 0;
}
});
// DEPTH-FIRST print
// root level
CH_HwProcessor procInstance = QueryUtils.getAllProcessorInstances(umlModel).get(0);
int maxLevel = ((Bin) allBins[0]).getLevel();
System.out.println("-- Primary Schedulers\n");
System.out.println("Scheduler (");
System.out.println(" Type => Primary_Scheduler,");
System.out.println(" Name => Scheduler_1,");
System.out.println(" Policy => ( Type => RUN ),");
System.out.println(" Host => Multicore_1 );");// TODO: depends on CHRT
// specification
System.out.println("\n-- Primary Scheduling Servers and Secondary Schedulers\n");
int indexSupertask = 0;
// all levels of the tree in the interval (root,0]
supertaskInfoList = new ArrayList<SupertaskInfo>();
for (int i = 1; (i < allBins.length) && (((Bin) allBins[i]).getLevel() >= 0); i++) {
createSupertaskInfo(procInstance, indexSupertask, ((Bin) allBins[i]).getCapacity());
assignedOperations = new HashSet<CHTask>();
// first pack: print leaf nodes
if (((Bin) allBins[i]).getLevel() == 0) {
List<Task> tasks = reductionTree.get(((Bin) allBins[i]));
LinkedHashSet<Object> list = new LinkedHashSet<Object>();
for (Task task : tasks) {
List<Task> leaves = ((Entry<Bin, List<Task>>) firstPackSorted[new Integer(task.getId())]).getValue();
for (Task leaf : leaves) {
System.out.println("Scheduling_Server (");
System.out.println(" Type => Regular,");
System.out.println(" Name => " + leaf.getId() + ",");
System.out.println(" Server_Sched_Parameters => (");
System.out.println(" Type => EDF_policy,");
System.out.println(" Deadline => " + leaf.getT() + ",");
System.out.println(" Preassigned => No),");
System.out.println(" Scheduler => SecondaryScheduler_" + indexSupertask + ");");
System.out.println();
CHTask owningTask = getCHRTFromTask(leaf);
list.add(owningTask);
addRelatedOperations(owningTask, list);
}
}
core2supertask.put(supertaskInfoList.get(indexSupertask), list);
}
indexSupertask++;
}
}
/**
* Creates the supertask info.
*
* @param ch_HwProcessor the ch hw processor
* @param indexSupertask the index supertask
* @param capacity the capacity
*/
private void createSupertaskInfo(CH_HwProcessor ch_HwProcessor, int indexSupertask, Float capacity) {
SupertaskInfo si = new SupertaskInfo(ch_HwProcessor.getBase_InstanceSpecification(), "SuperTask_" + indexSupertask, capacity);
supertaskInfoList.add(si);
System.out.println("--*************** BRANCH ***************");
System.out.println("Scheduling_Server (");
System.out.println(" Type => Regular,");
System.out.println(" Name => SuperTask_" + indexSupertask + ",");
System.out.println(" Server_Sched_parameters => ( Type => RUN_Supertask,");
System.out.println(" Utilization => " + capacity + " ),"); // FIXME:
// utilization
// is
// not
// expressed
// as U
// in
// Geoffrey's
// example
System.out.println(" Scheduler => Scheduler_1 );");
System.out.println();
System.out.println("Scheduler (");
System.out.println(" Type => Secondary_Scheduler,");
System.out.println(" Name => SecondaryScheduler_" + indexSupertask + ",");
System.out.println(" Policy => ( Type => EDF,");
System.out.println(" Worst_Context_Switch => 20 ),");// FIXME: based on
// Compagnin paper
// at ECRTS2014
System.out.println(" Server => SuperTask_" + indexSupertask + " );");
System.out.println();
}
/**
* Builds the associations.
*
* @param firstPack the first pack
*/
public void buildAssociations(Map<Bin, List<Task>> firstPack) {
// add chtasks which represent real tasks to the core map and add the
// related operation chain to the same core
// TODO solve the following problem: the related operations may be shared
// between tasks which can be assigned to different cores!
core2chtask = new HashMap<CHCore, LinkedHashSet<Object>>();
int coreIndex = 0;
for (Bin core : firstPack.keySet()) {
assignedOperations = new HashSet<CHTask>();
LinkedHashSet<Object> list = new LinkedHashSet<Object>();
for (Task task : firstPack.get(core)) {
CHTask owningTask = getCHRTFromTask(task);
list.add(owningTask);
addRelatedOperations(owningTask, list);
}
core2chtask.put(cores.get(coreIndex++), list);
}
}
// the related operations of a task are assigned to the same core of the task,
// TODO for now every operation shared by multiple tasks is assigned to the
/**
* Adds the related operations.
*
* @param owningTask the owning task
* @param list the list
*/
// same core of the first task that was processed
private void addRelatedOperations(CHTask owningTask, LinkedHashSet<Object> list) {
for (CHTask operation : operationList.get(owningTask)) {
if (!assignedOperations.contains(operation)) {
list.add(operation);
assignedOperations.add(operation);
}
}
}
/**
* Gets the task ID.
*
* @param chRtSpecification the ch rt specification
* @return the task ID
*/
private String getTaskID(CHRtSpecification chRtSpecification) {
return chRtSpecification.getContext().getName() + UMLUtils.getElementID(chRtSpecification.getContext());
}
/**
* Gets the CHRT from task.
*
* @param task the task
* @return the CHRT from task
*/
private CHTask getCHRTFromTask(Task task) {
for (CHTask chtask : operationList.keySet()) {
if (getTaskID(chtask.getCHRtSpecification()).equals(task.getId()))
return chtask;
}
return null;
}
/**
* Prints the content.
*/
private void printContent() {
System.out.println("Tasks:");
for (CHTask chtask : operationList.keySet()) {
System.out.println(chtask);
}
}
/**
* Update model.
*/
protected void updateModel() {
boolean b1 = core2chtask != null && !core2chtask.isEmpty();
boolean b2 = core2supertask != null && !core2supertask.isEmpty();
if (b1 || b2) {
TransactionalEditingDomain editingDomain = TransactionUtil.getEditingDomain(umlModel);
editingDomain.getCommandStack().execute(new Com(editingDomain));
}
}
/**
* Query content.
*
* @param owner the owner
* @throws ModelError the model error
*/
protected void queryContent(Model owner) throws ModelError {
EList<CH_HwProcessor> x = QueryUtils.getAllProcessorInstances(umlModel);
x = QueryUtils.filterMultiCoreProcessors(x);
if (x.size() > 1)
throw new ModelError("Assignment generation works only on single processor systems");
// Look for Packages stereotyped as CHGAResourcePlatform in the Deployment
// View
EList<Package> packages = QueryUtils.getResourcePlatformPackages(umlModel, CHESSProfileManager.DEPLOYMENT_VIEW);
if (packages.size() == 0) {
ModelError me = new ModelError("Error in model: no Package stereotyped as CHGAResourcePlatform in the Deployment View!");
throw me;
}
hwSystemsList = new BasicEList<InstanceSpecification>();
for (Package pack : packages) {
EList<InstanceSpecification> processors = new BasicEList<InstanceSpecification>();
for (CH_HwProcessor ch_processor : QueryUtils.getAllProcessorInstancesInPackage(pack)) {
InstanceSpecification instSpec = ch_processor.getBase_InstanceSpecification();
processors.add(instSpec);
EList<CHCore> theCores = QueryUtils.getCores(ch_processor);
coresMap.put(instSpec, theCores);
cores.addAll(theCores);
}
InstanceSpecification theSystem = UMLUtils.getRootInstanceInPackage(pack);
hwSystemsList.add(theSystem);
processorsMap.put(pack, processors);
}
if (hwSystemsList.isEmpty()) {
ModelError me = new ModelError("Error in model: no System in the Deployment View!");
throw me;
}
EList<InstanceSpecification> instances = UMLUtils.getAllComponentInstances(umlModel, true);
EList<CHTask> chtasks = QueryUtils.getCHTasksList(instances);
operationList = QueryUtils.getOperationChain(umlModel, chtasks);
}
/**
* The Class Com.
*/
class Com extends RecordingCommand {
/**
* Instantiates a new com.
*
* @param domain the domain
*/
public Com(TransactionalEditingDomain domain) {
super(domain);
}
/* (non-Javadoc)
* @see org.eclipse.emf.transaction.RecordingCommand#doExecute()
*/
@Override
protected void doExecute() {
try {
QueryUtils.deleteTask2CoreAssociations(hwSystem);
if (!useRUN)
GeneratorUtils.buildTask2CoreAssociations(hwSystem, core2chtask);
else
GeneratorUtils.buildTask2SuperTaskAssociations(hwSystem, core2supertask, supertaskInfoList);
} catch (Exception e) {
throw new OperationCanceledException(e.getMessage());
}
}
}
}