blob: 5872d9b547eb575551dc1a6103e4d599c9234489 [file] [log] [blame]
/*
-----------------------------------------------------------------------
-- CHESS M2M plugin --
-- --
-- Copyright (C) 2011-2012 --
-- University of Padova, ITALY --
-- --
-- Author: Alessandro Zovi azovi@math.unipd.it --
-- --
-- All rights reserved. This program and the accompanying materials --
-- are made available under the terms of the Eclipse Public License --
-- v1.0 which accompanies this distribution, and is available at --
-- http://www.eclipse.org/legal/epl-v20.html --
-- --
-- 20150114: SP change in getLifeLineInstance to avoid trouble --
-- in case of an InstanceSpecification whose name is a substring of --
-- another. --
-----------------------------------------------------------------------
*/
import ProfileUtils_Inst_full;
import UMLUtils_Inst_full;
import chess.lib;
import chess.libJava4QVTutils;
modeltype UML uses "http://www.eclipse.org/uml2/5.0.0/UML";
modeltype MARTEP uses "http://www.eclipse.org/papyrus/MARTE/1";
modeltype CHESS uses "http://CHESS";
modeltype ECORE uses "http://www.eclipse.org/emf/2002/Ecore";
modeltype MARTEGRM uses "http:///MARTE_Library/GRM_BasicTypes.ecore";
transformation CHESS_PIM2PSM(inout source:UML);
configuration property analysisType : String;
configuration property deadline : String;
configuration property scenario : String;
configuration property saAnalysis : String;
configuration property saE2EFlow : String;
property model : Model = null;
property psmView : Package = null;
property compView : Package = null;
property depView : Package = null;
property MARTEProfile : Profile = null;
property CHESSProfile : Profile = null;
--property platform : Package = null;
property psmPackage : Package = null;
property hostPackage : Package = null;
property operationPackage : Package = null;
property taskPackage : Package = null;
property partitionPackage : Package = null;
property analysisContextPackage : Package = null;
property assigns : Set(Comment) = null;
property partitionAssigns : Set(Comment) = null;
property specs : Set(Comment) = null;
property partitions :Set(Classifier) = null;
property slots : Set(Slot) = null;
property slotInstances : Set(Slot) = null;
property e2eOperations : Set(Operation) = null;
property instSpecPackage : Package = null;
//property instSpecFullPackage : Package = null;
property currentConcurRes : MARTE::SRM::SW_Concurrency::SwSchedulableResource = null;
property currentSlot : Slot = null;
/*Global variable for partition processing*/
property currentProcessor : InstanceSpecification = null;
property currentCore : String = null;
property currentHost : MARTE::SAM::SaExecHost = null;
property slotinAssigns = false;
property isRUN = false;
//property currentSharedRes : MARTE::SAM::SaSharedResource = null;
main() {
//analysisType:= "Schedulability";
//saAnalysis := "model::modelAnalysisView::modelRTAnalysisView::SaAnalysisContext1";
log("*** CHESS PIM->PSM transformation ***");
log("Performing " + analysisType + " Analysis");
log("Analysis Context is " + saAnalysis);
log("End2End Scenario is " + saE2EFlow);
model := source.rootObjects()![Model];
MARTEProfile := model.getView("ComponentView").getAppliedProfiles()->selectOne(name="GCM").owner.owner.oclAsType(Profile);
CHESSProfile := model.getAppliedProfiles()->selectOne(name="CHESS").oclAsType(Profile);
initUtils(MARTEProfile, CHESSProfile);
model.map psmModel();
}
mapping inout Model::psmModel() {
init{
psmView := self.getView("PSMView");
compView := self.getView("ComponentView");
depView := self.getView("DeploymentView");
var saAnalysisClass := self.allOwnedElements()[Class]->selectOne(qualifiedName=saAnalysis);
var saAnalysisCtx := saAnalysisClass.getMetaclass(SaAnalysisContextQN).oclAsType(MARTE::SAM::SaAnalysisContext);
//var platforms := saAnalysisCtx.platform->asSequence();
//instSpecPackage := platforms->first().oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
instSpecPackage := saAnalysisCtx.getSwSystemInstPackage();
}
assert fatal (instSpecPackage <> null)
with log("CHGaResourcesPlatform is not present: there should be one CHGaResourcePlatform in the Analysis Context");
assert fatal (instSpecPackage->size()=1)
with log("Ambiguous analysis scenario: there should be only one CHGaResourcePlatform in the Analysis Context");
log("<<CHGaResourcesPlatform>> found.");
instSpecPackage.map CHGaResourcePlatform2SaAnalysisContext(saAnalysisCtx);
}
//maps the Package of the SW instances to an AnalysisContext
mapping Package::CHGaResourcePlatform2SaAnalysisContext(saAnalysisCtx : MARTE::SAM::SaAnalysisContext) : Class {
init{
log("Generating <<SaAnalysisContext>> and necessary packages.");
psmPackage := object Package {
name := saAnalysisCtx.base_NamedElement.name + "_PSM";
};
hostPackage := object Package {
name := "Host";
};
operationPackage := object Package {
name := "Operation";
};
taskPackage := object Package {
name := "Task";
};
partitionPackage := object Package{
name := "Partition";
};
analysisContextPackage := object Package{
name := "AnalysisContext";
};
psmView.packagedElement += psmPackage;
psmPackage.packagedElement += hostPackage;
psmPackage.packagedElement += operationPackage;
psmPackage.packagedElement += taskPackage;
psmPackage.packagedElement += partitionPackage;
psmPackage.packagedElement += analysisContextPackage;
var psmPkg := psmPackage.applyStereotype(getCHESSStereotype("PSMPackage")).oclAsType(CHESS::Core::PSMPackage);
psmPkg.AnalysisContext := saAnalysisCtx;
}
// analysisContextPackage
analysisContextPackage.applyProfile(getMARTEProfile("GQAM"));
/*
Creation of the "AnalysisContext" package
(<<saAnalysisContext>> containing :
<<saEndToEndFlow>>, Constraint as <<gaLatencyObs>>,
<<gaWorkloadEvent>>, OpaqueAction as <<saStep>>)
*/
result.name := model.name + "_analysisContext";
analysisContextPackage.packagedElement += result;
// Apply the stereotype <<saAnalysisContext>>
var analysisC := result.applyStereotype(getMARTEStereotype("SaAnalysisContext")).oclAsType(MARTE::SAM::SaAnalysisContext);
analysisC.context += "(tool=mast,options=(invoke=true,recoverResults=true,overwriteResults=true,overwriteOutputModel=true,modeID=''))";
end{
// hostPackage
hostPackage.applyProfile(getMARTEProfile("HwComputing"));
hostPackage.applyProfile(getMARTEProfile("HwCommunication"));
hostPackage.applyProfile(getMARTEProfile("GQAM"));
// Retrieve all <<Assign>>
//assumption: Assign are owned by the System component in the DeploymentView
var systemComp = saAnalysisCtx.getSystem();
assert fatal (systemComp <> null)
with log("<<CHGaResourcesPlatform>> System is not present: there should be a CHGaResourcePlatform Package in the AnalysisContext.platform pointing to the System instances");
assigns := systemComp.allOwnedElements()[Comment]->select(isStereotyped(AssignQN))->asSet();
//retrieve Partitions Assign from the ComponentView
partitionAssigns := compView.allOwnedElements()[Comment]->select(isStereotyped(AssignQN))->asSet();
assert fatal (assigns <> null)
with log ("No <<Assign>> found in input model");
assigns.getTo()->asSet()->select(isProcessor())->HwProcessor2SaExecHostHelper();
//TODO
//ComputingResource does not contain info about number of cores so the following line should be removed...
//assigns.getTo()->asSet()->select(isComputingResource())->map HwComputingResource2SaExecHost();
self.ownedMember[InstanceSpecification]->select(isBus())->processBus();
// operationPackage
var comps := compView.allOwnedElements()[Component]->select(isStereotyped(ComponentImplementationQN));
/*Partition support Begin*/
var functParts := compView.allOwnedElements()[Component]->select(isStereotyped(FunctionalPartitionQN));
/*Partition support End*/
assert fatal (comps <> null)
with log ("No <<ComponentImplementation>> found in input model");
// taskPackage
slots := instSpecPackage.allOwnedElements()[Slot]->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
assert fatal (slots <> null)
with log ("No <<CHRtPortSlot>> found in input model");
specs := compView.allOwnedElements()[Comment]->select(isStereotyped(CHRtSpecificationQN))->asSet();
assert fatal (specs <> null)
with log ("No <<CHRtSpecification>> found in input model");
taskPackage.applyProfile(getMARTEProfile("GRM"));
/*in case of allocation of components to cores, the source of the Assign are slots, i.e. instances of ports
in case of avionics, functional components appears as source of Assign
*/
assigns->forEach(ass){
var asg := ass.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
//TODO assumption: one annotatedElement per Assign
var list := ass.getInstances(instSpecPackage);
if(list->size()>0){
slotinAssigns := false;
list->forEach(e){
//var id := e.getMetaclass("CHESS::Core::IdentifInstance").oclAsType(CHESS::Core::IdentifInstance);
slotInstances += e.slot->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
if(e.classifier.getMetaclass(FunctionalPartitionQN)->asSequence()->first()<>null){
partitions += e.classifier;
/*it is a partition*/
};
}
} else {
slotinAssigns := true;
var slotList := ass.getSlotInstances(instSpecPackage);
slotInstances += slotList;
}
};
log("Slot list(" + slotInstances->size().toString()+"):");
slotInstances->forEach(s){
log(" "+s.definingFeature.name);
};
log("Partition list(" + partitions->size().toString()+"):");
partitions->forEach(s){
log(" "+s.name);
};
log("");
log("*** Proceeds to create SwSchedulableResources and SaSteps ***");
/*If there are no functional partitions go here; in fact in case of partitions the 'from' field of the Assing has partition instance instead of slot*/
if(slotInstances->size()<>0){
slotInstances->forEach(s){
var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
specs->forEach(spec){
log("***Processing Slot" +s.getStringId()+ " defining feature " +s.getStringId()+ s.definingFeature.name+ " for " + s.owningInstance.name + s.owningInstance.getStringId() + " and operation "+ spec.context.name +".");
//maps only if the operation is deferred
s.map CHRtSlot2SwSchedulableResource(spec.base_Comment);
//now creates the <<SaStep>> operations
spec.base_Comment.CHRTComment2SaStep(s, s.owningInstance);
};
};
/*else process functional partitions*/
} else if (partitions->size()<>0) {
partitions->forEach(p){
var partitionInst := p.getPartitionInstance();
var pPSM := partitionInst.map Partition2Package();
currentProcessor := partitionInst.getAssignedProcessor();
currentCore := partitionInst.getAssignedCore();
var partition := partitionInst.map Partition2PSM();
currentHost := partition.getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
partitionInst.getComponentsOfPartition()->forEach(componentInst){
log("Analysing classifier" + componentInst.classifier![Classifier].name +" mapped on partition " +p.name);
/*
Assumption:
1)ARINCFunction operation cannot appear as provided operations
2)CHRtSPecification for ARINCFFunctions are associated to the Component Instance through the CHRtPortSlot (where the latter extends InstanceSpecification)
*/
//checking chrtSpec associated to the componentInstance
var chrtportslot := componentInst.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
var privateChrtSpecs := chrtportslot.cH_RtSpecification;
privateChrtSpecs->forEach(privatechrtspec){
var arincFuncStereo = privatechrtspec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
if (arincFuncStereo <> null) {
log("Mapping ARINCFunction " + privatechrtspec.context.name);
//fix any missing information for chrtspec, like period; derive it from the ARINCProcess
componentInst.getUpdatedArincFunChrtSpec(privatechrtspec.base_Comment.oclAsType(Comment));
//maps only if the operation is deferred
var schedRes : Class := componentInst.map Instance2SwSchedulableResource(privatechrtspec.base_Comment);
var temp : Class;
/*create a class that refere to the schedulabe resource in the right partition package*/
object temp : Class {
name := schedRes.name;
redefinedClassifier+=schedRes;
};
pPSM.packagedElement+=temp;
//now creates the <<SaStep>> operations
//componentInst.map InstanceUnprotected2SaStep(privatechrtspec.base_Comment, componentInst);
privatechrtspec.base_Comment.CHRTComment2SaStep(null, componentInst);
};
};
//checking chrtSpec associated to the componentInstance slots, i.e. provided chrtSpec
var componentInstSlots := componentInst.slot->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
componentInstSlots->forEach(componentInstSlot){
var specs := componentInstSlot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
specs->forEach(spec){
log("***Processing Slot" +componentInstSlot.getStringId()+ " defining feature " +componentInstSlot.getStringId()+ componentInstSlot.definingFeature.name+ " for " + componentInstSlot.owningInstance.name + componentInstSlot.owningInstance.getStringId() + " and operation "+ spec.context.name +".");
//ARINC Process must not be mapped
var arincFuncStereo = spec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
if (arincFuncStereo <> null){
//TODO it is allowed to have ARINCFunctions here, i.e. as provided operations?
//TODO fix any missing information for chrtspec, like period; derive it from the ARINCProcess
log("*********Processing provided ARINC FUNCTION...... !!!!!!!!!!!!!************** ");
componentInst.getUpdatedArincFunChrtSpec(spec.base_Comment.oclAsType(Comment));
//maps only if the operation is deferred
var schedRes : Class := componentInstSlot.map CHRtSlot2SwSchedulableResource(spec.base_Comment);
var temp : Class;
/*create a class that refere to the schedulabe resource in the right partition package*/
object temp : Class {
name := schedRes.name;
redefinedClassifier+=schedRes;
};
pPSM.packagedElement+=temp;
//now creates the <<SaStep>> operations
spec.base_Comment.CHRTComment2SaStep(componentInstSlot, componentInst);
}
};
};
};
};
} else {
//TODO error!
};
if(analysisType.equalsIgnoreCase("Schedulability")) then {
//Proceed to create the EndToEndWorkFlow now since all the necessary resources are generated
log("");
log("***Creating the EndToEndWorkFlow ***");
if(slotInstances->size()<>0){
slotInstances->forEach(s){
var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
specs->forEach(spec){
s.map slot2EndToEndWorkFlow(spec.base_Comment);
};
};
} else if (partitions->size()<>0) {
partitions->forEach(p){
/*TODO what happens if an operation calls an operation of a different partition?*/
var pInst := p.getPartitionInstance();
var pPSM := pInst.map Partition2PSM();
currentProcessor := pInst.getAssignedProcessor();
currentCore := pInst.getAssignedCore();
pInst.getComponentsOfPartition()->forEach(componentInst){
log("Analysing instance " + componentInst.classifier![Classifier].name +" mapped on partition " +p.name);
/*
Assumption:
1)ARINCFunction operation cannot appear as provided operations
2)CHRtSPecification for ARINCFFunctions are associated to the Component Instance through the CHRtPortSlot (where the latter extends InstanceSpecification)
*/
//checking chrtSpec associated to the componentInstance
var chrtportslot := componentInst.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
var privateChrtSpecs := chrtportslot.cH_RtSpecification;
privateChrtSpecs->forEach(privatechrtspec){
var arincFuncStereo = privatechrtspec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
if (arincFuncStereo <> null) {
log("Mapping ARINCFunction " + privatechrtspec.context.name);
privatechrtspec.base_Comment.map Instance2EndToEndWorkFlow(null, componentInst);
};
};
//end
var instances := componentInst.slot->select(owningInstance.classifier <> null and isCHRtPortSlotCorrect())->asSet();
instances->forEach(s){
var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
specs->forEach(spec){
//ARINC Process must not be mapped
var arincFuncStereo = spec.context.getMetaclass(ARINCFunctionQN).oclAsType(chessmlprofile::ARINCComponentModel::ARINCFunction);
if (arincFuncStereo <> null){
log("*********Processing provided ARINC FUNCTION...... TO BE DONE!!!!!!!!!!!!!************** ");
s.map slot2EndToEndWorkFlow(spec.base_Comment);
}
};
};
};
};
} else {
//TODO error!
};
} endif;
if(analysisType.equalsIgnoreCase("EndToEnd")) then {
//EndToEndWorkFlow for E2E Scenario
--2015/02/23 - NP: added a check to avoid null pointers @ c.qualifiedName and @ a.qualifiedName
var pimContext : Class = model.allOwnedElements()[Class]->selectOne(c : Class | not c.qualifiedName.oclIsUndefined() and c.qualifiedName.equalsIgnoreCase(saAnalysis));
var pimActivity : Activity = model.allOwnedElements()[Activity]->selectOne(a : Activity | not a.qualifiedName.oclIsUndefined() and a.qualifiedName.equalsIgnoreCase(saE2EFlow));
var interactions : Set(Interaction) := model.allOwnedElements()[Interaction];
interactions->forEach(interaction){
if(interaction.qualifiedName.equalsIgnoreCase(scenario)) then {
log(">>>>> Found End-To-End Scenario: " + interaction.name);
interaction.map Interaction2EndToEndWorkFlow(result, pimContext, pimActivity);
} endif;
log("e2e operations:");
e2eOperations->forEach(op){
log(" "+ op.name)
};
//Proceeds to create the EndToEndWorkFlow for those tasks not involved in the e2e scenario"
log("*** Proceeds to create the EndToEndWorkFlow ***");
slotInstances->forEach(s){
var specs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
specs->forEach(spec){
if(not e2eOperations->exists(op: Operation | op.name.equalsIgnoreCase(spec.context.name))) then {
log("Operation is: " + spec.context.name);
s.map slot2EndToEndWorkFlow(spec.base_Comment);
} endif;
};
};
};
} endif;
log("*** End of CHESS PIM->PSM transformation ***");
}
}
//context: the PSM analysisContext - used to read analysis reuslts to backpropagate to PIM
//pimContext, pimActivity: PIM entities to be updated by the backpropagation
//
mapping Interaction::Interaction2EndToEndWorkFlow(context : Class, pimContext : Class, pimActivity: Activity) : Activity{
init {
log("Generating <<EndToEndWorkFlow>> from " + self.name);
//First we get a list of ordered messages
//it is based on the assumption that each message starts with a progressive number to keep their order
var messageSequence : Sequence(Message) := self.message->sortedBy(name)->asSequence();
log("****** messages sequence");
messageSequence->forEach(msg){
log(" " + msg.name)
};
//get starting chrts for initializing the <<gaWorkloadEvent>> pattern
var startMsg := messageSequence->first();
var startChrts := startMsg.getMsgChrts();
}
result.name := self.name;
// Add the action to the owned behaviors of RTAnalysisContext
instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedBehavior += result;
//Apply the stereotype <<SaEndtoEndFlow>> to the activity
result.applyStereotype(getMARTEStereotype("SaEndtoEndFlow"));
//Global Timing Requirement
var actConstraint := new Constraint("Global_Timing_Req");
result.precondition += actConstraint;
var actInitialNode := result.createInitialNode();
var controlFlowInit := new ControlFlow("ControlFlowInit");
actInitialNode.outgoing += controlFlowInit;
result.edge += controlFlowInit;
//Apply stereotype <<gaLatencyObs>> and specify the deadline for the end to end flow
var gaLatencyObs := actConstraint.applyStereotype(getMARTEStereotype("GaLatencyObs")).oclAsType(MARTE::GQAM::GaLatencyObs);
gaLatencyObs.latency += deadline.parseNFPDuration("value");
//Apply stereotype <<gaWorkloadEvent>> and specify the release pattern of the end-to-end flow
var gaWorkloadEvent := actInitialNode.applyStereotype(getMARTEStereotype("GaWorkloadEvent")).oclAsType(MARTE::GQAM::GaWorkloadEvent);
gaWorkloadEvent.pattern := startChrts.occKind;
//create end2end action sequence
var resultNode := createE2EOpaqueActionsChain(messageSequence, result, actInitialNode);
//create final node
//var finalNode := new ActivityFinalNode("ActivityFinalNode1");
var finalNode := result.createFinalNode();
//result.node += finalNode;
resultNode.outgoing![ControlFlow].target := finalNode;
/*Stefano
//add entity to store traceability information in the model. This infomation can then be used later in the editor to show analysis results related to the PIM entites.
*/
var constr := new Constraint();
constr.constrainedElement += result;
constr.constrainedElement += pimActivity;
instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedRule += constr;
//end modification for traceability
}
//Return the nextE2ENode TODO - work in progress!!!
helper createE2EOpaqueActionsChain(in messageSequence : Sequence(Message), inout endToEndWorkFlow : Activity, inout currentNode : ActivityNode) : ActivityNode {
var nextNode := currentNode;
messageSequence->forEach(msg){
//log("operation is: " + msg.signature.name);
var currentChrts := msg.getMsgChrts();
//log("its context is: " +currentChrts.context.name);
//log("its partWithPort is: " +currentChrts.partWithPort.name);
//log("its occKind is: " +currentChrts.occKind.toString());
//log("its protection is: " +currentChrts.protection.toString());
//log("its WCET is: " +currentChrts.WCET.toString());
//log("Slot [createOpaqueActionsChain]: " + currentSlot.definingFeature.name);
//if operation is sporadic then create a get node before the operation node
nextNode := createSporadicRelatedNodes(currentChrts, currentSlot, endToEndWorkFlow, nextNode);
//Creates the subsequent OpaqueAction and ControlFlow
nextNode := createSaStepNode(currentChrts, currentSlot, endToEndWorkFlow, nextNode, currentSlot.owningInstance);
e2eOperations += currentChrts.context->oclAsType(Operation);
};
return nextNode;
}
/*
sourceSlot can be null, e.g. in case of ARINCFunction private operation
* IT SEEMS THAT THIS IS DUPLICATED, se helper below
helper createSaStepNode(in sourceCHRtComment: Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode,
ownerInstance : InstanceSpecification ) : ActivityNode {
var chrts := sourceCHRtComment.CHRtSpec();
var opNode := createOpaqueAction(opaqueActionName(sourceSlot, chrts), e2eActivity, prevE2ENode);
var opSaStep := opNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
// Set the <<SwSchedulableResource>> that executes the <<saStep>>
var concurRes := currentConcurRes;
if chrts.isDeferred() then
concurRes := sourceCHRtComment.getConcurRes(sourceSlot)//classResource.getMetaclass(SchedulableResourceQN).oclAsType(MARTE::GRM::SchedulableResource);
endif;
zzz
opSaStep.concurRes := concurRes;
// Retrieve the <<SaStep>> to use for the subusage
var saStep := sourceCHRtComment.resolve2SaStep().getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
opSaStep.subUsage += saStep;
//opSaStep.sharedRes += currentSharedRes;
return opNode;
}*/
/*sourceSlot can be null, in case of chrt referring private operation
*/
helper createSaStepNode(in currentCHRts: chessmlprofile::RTComponentModel::CHRtSpecification, in sourceSlot : Slot,
inout EndToEndWorkFlow : Activity, inout currentNode : ActivityNode, in ownerInstance:InstanceSpecification) : ActivityNode {
var actionname : String;
if (sourceSlot<> null) {
actionname := opaqueActionName(sourceSlot, currentCHRts);
}else{
actionname := opaqueActionName(ownerInstance, currentCHRts);
};
var opNode := createOpaqueAction(actionname, EndToEndWorkFlow, currentNode);
var opSaStep := opNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
//log("Slot [createSaStepNode]: " + currentSlot.definingFeature.name);
// Set the <<SwSchedulableResource>> that executes the <<saStep>>
var concurRes := currentConcurRes;
if currentCHRts.isDeferred() then {
if (sourceSlot<> null) {
concurRes := currentCHRts.base_Comment.getConcurRes(sourceSlot);
}else{
concurRes := currentCHRts.base_Comment.getConcurRes(ownerInstance);
}
}
endif;
log("********createSaStepNode in endToEnd Activity: concuRes is " + concurRes.toString());
opSaStep.concurRes := concurRes;
// Retrieve the <<SaStep>> to use for the subusage
var saStep := currentCHRts.base_Comment.resolve2SaStep().getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
log("********createSaStepNode in endToEnd Activity: subUsage is " + saStep.toString());
//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
opSaStep.subUsage += saStep;
//opSaStep.sharedRes += currentSharedRes;
return opNode;
}
/*
Creates Bus related entities given an InstanceSpecification of a Bus
*/
helper InstanceSpecification::processBus(){
log("Bus found for InstanceSpecification '"+self.name+"'.");
self.map HwBus2SaCommHost();
self.map HwBus2OperationClass();
self.linkedHwInstanceSpecifications()-> map BusProperty2GaCommChannel(self);
return null;
}
//NOT USED
//mapping Slot::CHRtSlot2SwSchedulableResourceStrict(chrt : Comment) : Class when {chrt.CHRtSpec().isDeferred()} {
// init{
// var res := self.owningInstance.resolveoneIn(InstanceSpecification::Instance2SwSchedulableResource, Class);
// if res = null then
// res := self.owningInstance.map Instance2SwSchedulableResource(chrt, self)
// else
// log(" Nothing to do")
// endif;
// result := res;
// }
//}
mapping Slot::CHRtSlot2SwSchedulableResource(chrt : Comment) : Class when {chrt.CHRtSpec().isDeferred()} {
init{
var res := self.owningInstance.map Slot2SwSchedulableResource(chrt, self);
result := res;
}
}
mapping InstanceSpecification::Partition2Package() : Package {
result.name := self.classifier![Classifier].name;
partitionPackage.packagedElement += result;
}
mapping InstanceSpecification::Partition2PSM() : Class {
result.name := self.classifier![Classifier].name;
var package := self.resolveoneIn(InstanceSpecification::Partition2Package, Package);
package.packagedElement += result;
var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
stHost.host := currentProcessor.getHost(currentCore);
stHost.otherSchedPolicy := "IMA";
var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
var par := self.classifier![Classifier].getMetaclass("CHESS::ComponentModel::FunctionalPartition").oclAsType(CHESS::ComponentModel::FunctionalPartition);
log("MAF");
log(par.MAF);
var schedParamMAF := "MAF=(value=" + par.MAF +")";
var schedParamSchedTable := "SCHED_TABLE=(value=\""+par.SchedulingTable+"\")";
sr.schedParams := "("+schedParamMAF+","+schedParamSchedTable+")";
}
mapping InstanceSpecification::Slot2SwSchedulableResource(chrtComment : Comment, slot : Slot) : Class when {chrtComment.CHRtSpec().isDeferred()} {
init{
var chrts := chrtComment.CHRtSpec();
var chrtportslot := slot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
var resourceName := chrts.schedulableResourceName(chrtportslot);
log(" Operation '" + chrts.context.name + "' is deferred. Generating <<SwSchedulableResource>> '" + resourceName + "'.");
}
result.name := resourceName;
taskPackage.packagedElement += result;
var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
sr.isProtected := false;
var schedParams := "fp(priority=(" + chrts.relativePriority.normalizeNFPInteger() +", source=meas))";
//TODO assume <<Assign>> 'from' and 'to' typed as InstanceSpecification
// Find the deployment node (InstanceSpecification), based on <<Assign>> directives
if(currentHost <> null){
sr.host := currentHost;//currentProcessor.getHost(currentCore);
} else {
if(slotinAssigns){
<<<<<<< HEAD
var hostClassifier := getAssignToFrom_MemoryPartition(slot, chrt);
if (isRUN){
sr.host := hostClassifier.getSupertaskHost(getAssignedSupertaskFrom_MemoryPartition(slot, chrt));
schedParams := "edf(deadline=(" + chrts.rlDl +", source=meas))";
} else {
sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(slot, chrt));
};
=======
var hostClassifier := getAssignToFrom_MemoryPartition(slot, chrtComment);
sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(slot, chrtComment));
>>>>>>> origin/develop
} else {
var hostClassifier := getAssignToFrom_MemoryPartition(slot.owningInstance);
sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(slot.owningInstance));
}
};
assert fatal (sr.host <> null)
with log("Null Host for SwSchedulableResource '" +result.name+ "'.");
sr.schedParams := schedParams;
}
//to be used when the CHRTSpecification is attached to a component instance and not to a port slot, e.g. in case of ARINCFUnctions decorating private operations
mapping InstanceSpecification::Instance2SwSchedulableResource(chrtComment : Comment) : Class when {chrtComment.CHRtSpec().isDeferred()} {
init{
var chrts := chrtComment.CHRtSpec();
var chrtportslot := self.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
var resourceName := chrts.schedulableResourceName(chrtportslot);
log(" Operation '" + chrts.context.name + "' is deferred. Generating <<SwSchedulableResource>> '" + resourceName + "'.");
}
result.name := resourceName;
taskPackage.packagedElement += result;
var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
sr.isProtected := false;
var schedParams := "fp(priority=(value=" + chrts.relativePriority.normalizeNFPInteger() +", source=meas))";
//TODO assume <<Assign>> 'from' and 'to' typed as InstanceSpecification
// Find the deployment node (InstanceSpecification), based on <<Assign>> directives
if(currentHost <> null){
sr.host := currentHost;//currentProcessor.getHost(currentCore);
} else {
if(slotinAssigns){
log("**************WARNING: Instance2SwSchedulableResource, this flow has not been implemented yet!!!!!");
}
else {
var hostClassifier := getAssignToFrom_MemoryPartition(self);
sr.host := hostClassifier.getHost(getAssignedCoreFrom_MemoryPartition(self));
}
};
assert fatal (sr.host <> null)
with log("Null Host for SwSchedulableResource '" +result.name+ "'.");
sr.schedParams := schedParams;
}
/*
Given a InstanceSpecification representing a Processor/ComputingResource,
return the already generated SaExecHost
*/
query InstanceSpecification::getHost(core: String) : MARTE::SAM::SaExecHost {
if(core<>null) {
var ress := self.resolveIn(InstanceSpecification::HwProcessor2SaExecHost, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
if(ress->size() = 1){
var cpu := ress->selectOne(base_Classifier.name=self.name);
assert fatal (cpu <> null)
with log("Host "+self.name+" not found.");
return cpu;
};
var res := ress->selectOne(base_Classifier.name=self.name+"_"+core);
if(res = null){
res := ress->selectOne(base_Classifier.name=self.name+"_core"+core);
};
if(res <> null){
return res;
};
};
var res := self.resolveoneIn(InstanceSpecification::HwProcessor2SaExecHost, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
//TODO the following lines should be removed
if res.oclIsInvalid() or res = null then
return self.resolveoneIn(InstanceSpecification::HwComputingResource2SaExecHost, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost)
endif;
return res;
}
<<<<<<< HEAD
/*
Given a InstanceSpecification representing a Processor/ComputingResource,
return the already generated SaExecHost
*/
query InstanceSpecification::getSupertaskHost(supertask: String) : MARTE::SAM::SaExecHost {
var ress := self.resolveIn(InstanceSpecification::HwProcessor2SaExecHostSupertask, Class).getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
if(ress->size() = 1){
var cpu := ress->selectOne(base_Classifier.name=self.name);
assert fatal (cpu <> null)
with log("Host "+self.name+" not found.");
return cpu;
};
var res := ress->selectOne(base_Classifier.name=self.name+supertask);
if(res <> null){
return res;
};
assert fatal (res <> null)
with log("Unable to find the assigned supertask");
return null;
}
helper createSaStepNode(in sourceCHRtComment: Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
var chrts := sourceCHRtComment.CHRtSpec();
var opNode := createOpaqueAction(opaqueActionName(sourceSlot, chrts), e2eActivity, prevE2ENode);
var opSaStep := opNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
// Set the <<SwSchedulableResource>> that executes the <<saStep>>
var concurRes := currentConcurRes;
if chrts.isDeferred() then
concurRes := sourceCHRtComment.getConcurRes(sourceSlot)//classResource.getMetaclass(SchedulableResourceQN).oclAsType(MARTE::GRM::SchedulableResource);
endif;
opSaStep.concurRes := concurRes;
// Retrieve the <<SaStep>> to use for the subusage
var saStep := sourceSlot.resolve2SaStep(chrts.base_Comment).getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
opSaStep.subUsage += saStep;
//opSaStep.sharedRes += currentSharedRes;
return opNode;
}
=======
>>>>>>> origin/develop
//Stefano: not clear what this method is intended to implement!!!
helper createSubUsage(in sourceCHRtComment: Comment, in sourceSlot : Slot, ownerInstance : InstanceSpecification) {
var chrts := sourceCHRtComment.CHRtSpec();
//log(" ***********WARNING 3 : createSubUsage, chrt = " + chrts.toString() + " sourceSlot = "+sourceSlot.owningInstance.toString());
var owningSaStep := sourceSlot.resolveoneIn(Comment::CHRTCommentProtected2SaStep, Operation).getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
//log("createSubUsage, owningSaStep = " + owningSaStep.toString());
owningSaStep.subUsage += sourceCHRtComment.resolve2SaStep().getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
}
/*
Author: Stefano Puri
Given a CHRtSpecification representing an operation using another operation,
it sets the dependencies through the subusage field of the SaStep mapped to the requiring operation
*/
helper createSubUsage(in reqCHRtSpec: chessmlprofile::RTComponentModel::CHRtSpecification, in provCHRtSpec: chessmlprofile::RTComponentModel::CHRtSpecification) {
//var requiringPSMOperation = requiringSlot.resolve2SaStep(reqCHRtSpec.base_Comment);
var requiringPSMOperation = reqCHRtSpec.base_Comment.resolve2SaStep();
log("requiringPSMOperation = " + requiringPSMOperation.toString());
//var piPSMOperation = providingSlot.resolve2SaStep();
var piPSMOperation = provCHRtSpec.base_Comment.resolve2SaStep();
log("usedPSMOperation = " + piPSMOperation.toString());
var reqSaStep = requiringPSMOperation.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
var provSaStep = piPSMOperation.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
log("usedStep = " + provSaStep.toString());
reqSaStep.subUsage += provSaStep;
}
/*
Given a comment related to a CHRtSlot return the corresponding schedulable resource
*/
query Comment::getConcurRes(slot : Slot) : MARTE::SRM::SW_Concurrency::SwSchedulableResource {
var chrtportslot := slot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
var classResource := slot.resolveIn(Slot::CHRtSlot2SwSchedulableResource, Class)->selectOne(
name=self.CHRtSpec().schedulableResourceName(chrtportslot));
return classResource.getMetaclass(SwSchedulableResourceQN).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
}
/*
Given an instance decorated with a CHRTSPecification returns the corresponding schedulable resource
*/
query Comment::getConcurRes(instance : InstanceSpecification) : MARTE::SRM::SW_Concurrency::SwSchedulableResource {
var chrtportslot := instance.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot);
log("");
log("+++++++++++++++++");
log("SEARCHING CONCURRES with NAME "+self.CHRtSpec().schedulableResourceName(chrtportslot));
log("");
var classResource := instance.resolveIn(InstanceSpecification::Instance2SwSchedulableResource, Class)->selectOne(
name=self.CHRtSpec().schedulableResourceName(chrtportslot));
log("FOUND "+classResource.toString());
log("");
return classResource.getMetaclass(SwSchedulableResourceQN).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
}
/*
Given a Comment stereotyped with CHRtSpecification returns the SaStep Operation previously created
*/
query Comment::resolve2SaStep() : Operation {
var chrts := self.CHRtSpec();
var ops : Sequence(Operation);
log("Comment::resolve2SaStep, chrtSpecification = "+chrts.toString() +", context = "+chrts.context.toString());
if (chrts.isSporadic()) then {
ops := self.resolveIn(Comment::CHRTCommentSporadic2SaStep, Operation);
}
else {
if (chrts.isProtected()) then {
ops := self.resolveIn(Comment::CHRTCommentProtected2SaStep, Operation);
} else {
log("Comment::resolve2SaStep: resolve in Comment::CHRTCommentUnprotected2SaStep");
ops := self.resolveIn(Comment::CHRTCommentUnprotected2SaStep, Operation);
} endif;
}
endif;
ops->forEach(op) {
if op.name = chrts.context.name() then
return op
endif;
};
return null;
}
//"receive" node and "get" node
helper createSporadicRelatedNodes(in currentOp : chessmlprofile::RTComponentModel::CHRtSpecification, in currentSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
if currentOp.isSporadic() then {
var nextE2ENode := prevE2ENode;
var riSlot := currentSlot.getCorrespondingSlot();
//If the current operation responds to a remote call, creates the "receive" node first
var connectingBus = getConnectingBus(currentSlot.owningInstance, riSlot.owningInstance);
if connectingBus <> null then
nextE2ENode := createReceiveOp(connectingBus, currentSlot, e2eActivity, nextE2ENode)
endif;
//If the current operation is sporadic, attaches the "get" operation before the operation node
//TODO Stefano: the following get operation should be set as subUsage of the sporadic SaStep Operation created in the PSM, it should not appear as activity
//return createGetOp(currentOp.base_Comment, currentSlot, e2eActivity, nextE2ENode);
return nextE2ENode;
}
else
return prevE2ENode
endif;
return null;
}
/*
//Return the nextE2ENode
currentSlot can be null, in case of private operation
*/
helper createOpaqueActionsChainFull(in currentIsGuarded : Boolean, in currentCHRtComment : Comment, in currentSlot : Slot,
inout e2eActivity : Activity, inout prevE2ENode : ActivityNode, in owningInstance : InstanceSpecification) : ActivityNode {
var currentCHRTSpec := currentCHRtComment.CHRtSpec();
var nextE2ENode := prevE2ENode;
log("CreateOpaqueActionChain: currentIsGuarded = "+currentIsGuarded.toString());
//TODO Assumption: if currentSlot is null, i.e. the current operation is private, then the current chrtspec cannot be sporadic
//if operation is sporadic then create receive + get nodes before the operation node
nextE2ENode := createSporadicRelatedNodes(currentCHRTSpec, currentSlot, e2eActivity, nextE2ENode);
//Creates the subsequent OpaqueAction and ControlFlow
nextE2ENode := createSaStepNode(currentCHRTSpec, currentSlot, e2eActivity, nextE2ENode, owningInstance);
//this does not create sporadic related nodes=>nextE2ENode := createSaStepNode(currentCHRtComment, currentSlot,e2eActivity, prevE2ENode);
//if the operation has a ICB-Activity then parse its CallOperationNodes
currentCHRTSpec.context.method![Activity].collectCallOperationNodes()->forEach(calledOpNode){
//var riSlot := calledOpNode.onPort.portToSlot(currentSlot.owningInstance);
var riSlots := calledOpNode.portToSlotFull(owningInstance);
riSlots->forEach(riSlot){
log(" Search for piSlot from riSlot '" + riSlot.owningInstance.name + riSlot.owningInstance.getStringId() + riSlot.definingFeature.name + riSlot.getStringId() + "'.");
var usedPiSlot := riSlot.getCorrespondingSlot();
log(" Found piSlot '" + usedPiSlot.owningInstance.name+usedPiSlot.owningInstance.getStringId() + usedPiSlot.definingFeature.name + usedPiSlot.getStringId() + "'.");
var usedPiCHRtSpec := usedPiSlot.CHRtSpecForOperation(calledOpNode.operation);
var bus := getConnectingBus(owningInstance, usedPiSlot.owningInstance);
//if it is a remote call, attach a send operation
if bus <> null then{
log("it is a remote call...");
if (currentSlot = null)
log("*****************WARNING createOpaqueActionsChainFull: the current slot is null, the operation is private; this path is not currently supported ...");
if usedPiCHRtSpec.isDeferred() then
return createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
else
//if it is a simple operation, proceeds with the subsequent call
nextE2ENode := createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
endif
}
else{
log("it is a local call...");
//otherwise it is a local call
//if it is a simple operation, simply add it to the endtoendworkflow and proceeds with the subsequent call
if usedPiCHRtSpec.isDeferred() then {
// Calls "put" operation
//TODO Stefano: the following get operation should be set as subUsage of the sporadic SaStep Operation created in the PSM, it should not appear as activity
//nextE2ENode := createPutOp(usedPiCHRtSpec.base_Comment, usedPiSlot, e2eActivity, nextE2ENode)
}
else
//if the node is protected all its CallOperation must be inserted in the subUsage of the SaStep Operation (created in the Operation Package) instead of creating a SaStep node
if usedPiCHRtSpec.isProtected() then {
//Stefano: why should a create a subUsagesChain here? Just a subusage is enough.
//nextE2ENode := createSubUsagesChain(currentOp.base_Comment, usedPiCHRtSpec.base_Comment, usedPiSlot, e2eActivity, nextE2ENode)
log("... and protected: create sub usage");
createSubUsage(currentCHRtComment.CHRtSpec(),usedPiCHRtSpec);
}
else{
//TODO Stefano: is this correct?
log("... WARNING 234325: check this oncreateOpaqueActionsChainFull mapping");
nextE2ENode := createOpaqueActionsChainFull(usedPiCHRtSpec.isProtected(),usedPiCHRtSpec.base_Comment, usedPiSlot, e2eActivity, nextE2ENode, usedPiSlot.owningInstance)
}endif
endif
}
endif;
}
};
return nextE2ENode;
}
//NOT USED
/*
helper createSubUsagesChain(in enclosingCHRTComment : Comment, in currentCHRtComment : Comment, in currentSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode,
ownerInstance:InstanceSpecification) : ActivityNode {
var currentOp := currentCHRtComment.CHRtSpec();
var nextE2ENode := prevE2ENode;
log("createSubUsagesChain... currentSlot="+currentSlot.owningInstance.toString());
nextE2ENode := createSporadicRelatedNodes(currentOp, currentSlot, e2eActivity, nextE2ENode);
//Creates the subsequent OpaqueAction and ControlFlow
if not currentOp.isDeferred() then
createSubUsage(currentCHRtComment, currentSlot)
else
nextE2ENode := createSaStepNode(currentCHRtComment, currentSlot, e2eActivity, nextE2ENode, ownerInstance)
endif;
//if the operation has a ICB-Activity then parse its CallOperationNodes
currentOp.context.method![Activity].collectCallOperationNodes()->forEach(calledOpNode){
var riSlots := calledOpNode.portToSlotFull(currentSlot.owningInstance);
riSlots->forEach(riSlot){
var piSlot := riSlot.getCorrespondingSlot();
var piOp := piSlot.CHRtSpecForOperation(calledOpNode.operation);
var bus := getConnectingBus(currentSlot.owningInstance, piSlot.owningInstance);
//if it is a remote call, attaches a send operation
if bus <> null then
if piOp.isDeferred() then
return createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
else
//if it is a simple operation, proceeds with the subsequent call
nextE2ENode := createSendOp(bus, currentSlot, e2eActivity, nextE2ENode)
endif
else
//otherwise it is a local call
//if it is a simple operation, simply add it to the endtoendworkflow and proceeds with the subsequent call
if not piOp.isDeferred() then
nextE2ENode := createSubUsagesChain(currentOp.base_Comment, piOp.base_Comment, piSlot, e2eActivity, nextE2ENode, ownerInstance)
else
//Calls put operation
return createPutOp(piOp.base_Comment, piSlot, e2eActivity, nextE2ENode)
endif
endif;
}
};
return nextE2ENode;
}
*/
helper createPutOp(in sourceCHRtComment : Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
var putSpec := sourceCHRtComment.CHRtSpec();
var putOp := //putSpec.base_Comment.resolveoneIn(Comment::SporadicOperation2SaSharedResource, Class).ownedOperation->selectOne(name="put");
sourceSlot.owningInstance.resolveoneIn(InstanceSpecification::SporadicOperation2SwMutualExclusionResource, Class).ownedOperation->selectOne(name="put");
var putNode := createOpaqueAction(sourceSlot.owningInstance.name + "_" + putOp.name, e2eActivity, prevE2ENode);
var opSaStep := putNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
// Set the <<SwSchedulableResource>> that executes the <<saStep>>
opSaStep.concurRes := currentConcurRes;//sourceCHRtComment.getConcurRes(sourceSlot);
// Retrieve the <<SaStep>> to use for the subusage
var saStep := putOp.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
opSaStep.subUsage += saStep;
return putNode;
}
helper createGetOp(in sourceCHRtComment : Comment, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
var getSpec := sourceCHRtComment.CHRtSpec();
var getOp := //getSpec.base_Comment.resolveoneIn(Comment::SporadicOperation2SaSharedResource, Class).ownedOperation->selectOne(name="get");
sourceSlot.owningInstance.resolveoneIn(InstanceSpecification::SporadicOperation2SwMutualExclusionResource, Class).ownedOperation->selectOne(name="get");
var getNode := createOpaqueAction(sourceSlot.owningInstance.name + "_" + getOp.name, e2eActivity, prevE2ENode);
var opSaStep := getNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
// Set the <<SchedulableResource>> that executes the <<saStep>>
//var classResource : Class := currentCHRtComment.resolveIn(Comment::CHRtSlot2SchedulableResource, Class)->selectOne(name=getSpec.genResourceName());
opSaStep.concurRes := sourceCHRtComment.getConcurRes(sourceSlot);//classResource.getMetaclass(SchedulableResourceQN).oclAsType(MARTE::GRM::SchedulableResource);
// Retrieve the <<SaStep>> to use for the subusage
var saStep := getOp.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
//Add the newly created operation as subUsage of the OpaqueAction(<<saStep>>)
opSaStep.subUsage += saStep;
return getNode;
}
helper createSendOp(in connectingBus : InstanceSpecification, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
return createBusOp(connectingBus, "send", sourceSlot, e2eActivity, prevE2ENode);
}
helper createReceiveOp(in connectingBus : InstanceSpecification, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
return createBusOp(connectingBus, "receive", sourceSlot, e2eActivity, prevE2ENode);
}
//opType must be "receive" or "send"
helper createBusOp(in connectingBus : InstanceSpecification, in opType : String, in sourceSlot : Slot, inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
log(" Attaching '"+ opType +"' operation for communication channel '" + connectingBus.name + "'.");
var sendNode := createOpaqueAction(connectingBus.name + "_" + opType, e2eActivity, prevE2ENode);
var sendSaStep := sendNode.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
//var gaCommChannel := getAssignToFrom(sourceSlot.CHRtSpec().partWithPort.property2InstanceSpec()).resolveoneIn(InstanceSpecification::BusProperty2GaCommChannel, Class).getMetaclass(GaCommChannelQN).oclAsType(MARTE::GQAM::GaCommChannel);
var gaCommChannel := getAssignToFrom_MemoryPartition(sourceSlot.owningInstance).resolveoneIn(InstanceSpecification::BusProperty2GaCommChannel, Class).getMetaclass(GaCommChannelQN).oclAsType(MARTE::GQAM::GaCommChannel);
sendSaStep.concurRes := gaCommChannel;
//TODO Assumption: send operation unique for each HwBus
var sendOp : Operation := connectingBus.resolveoneIn(InstanceSpecification::HwBus2OperationClass, Class).ownedOperation->selectOne(name.endsWith("_" + opType));
sendSaStep.subUsage += sendOp.getMetaclass(SaStepQN).oclAsType(MARTE::SAM::SaStep);
return sendNode;
}
helper createOpaqueAction(in name : String , inout e2eActivity : Activity, inout prevE2ENode : ActivityNode) : ActivityNode {
//var node := new OpaqueAction(name);
var node := e2eActivity.createOpaqueAction(name);
var edge := new ControlFlow("ControlFlow_" + node.name);
e2eActivity.node += node;
e2eActivity.edge += edge;
node.outgoing += edge;
//TODO Assumption: only one outgoing activity edge per node
prevE2ENode.outgoing![ControlFlow].target := node;
return node;
}
mapping Slot::Slot2Class4SaStep() : Class {
var name := operationClassName(self, "operations");
log(" <<SaStep>> operation class not found. Generating '" + name + "'.");
result.name := name;
operationPackage.packagedElement += result;
}
mapping InstanceSpecification::InstanceSpecification2Class4SaStep() : Class {
var name := operationClassName(self, "operations");
log(" <<SaStep>> operation class not found. Generating '" + name + "'.");
result.name := name;
operationPackage.packagedElement += result;
}
/*SLot can be null, e.g. in case of private ARINCFunction
*/
helper Comment::CHRTComment2SaStep(slot : Slot, owningInstance : InstanceSpecification) : Operation {
if self.CHRtSpec().isSporadic() then
return self.map CHRTCommentSporadic2SaStep(slot, owningInstance)
endif;
if self.CHRtSpec().isProtected() then
return self.map CHRTCommentProtected2SaStep(slot, owningInstance)
else
return self.map CHRTCommentUnprotected2SaStep(slot, owningInstance)
endif;
return null;
}
/*
//NOT USED
mapping Slot::CHRTCommentUnprotected2SaStepStrict(chrt : Comment) : Operation when {not chrt.CHRtSpec().isProtected()} {
init{
var res := self.owningInstance.resolveoneIn(InstanceSpecification::UnprotectedOperation2SaStep, Operation);
if res = null then {
log(" Generating <<SaStep>> for operation '" + chrt.CHRtSpec().context.name + "'.");
res := self.owningInstance.map UnprotectedOperation2SaStep(chrt, self);
} else
log(" Nothing to do")
endif;
result := res;
}
}*/
/*slot can be null, e.g. private ARINCFunction case
*/
mapping Comment::CHRTCommentUnprotected2SaStep(slot : Slot, owningInstance : InstanceSpecification) : Operation when {not self.CHRtSpec().isProtected()} {
init{
log(" Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
var res := owningInstance.map UnprotectedOperation2SaStep(self, slot, owningInstance);
result := res;
}
}
mapping InstanceSpecification::UnprotectedOperation2SaStep(chrt : Comment, slot : Slot, owningInstance : InstanceSpecification) : Operation when {not chrt.CHRtSpec().isProtected()} {
init{
if chrt.CHRtSpec().isDeferred() then
log(" Operation is cyclic.")
else
log(" Operation is unprotected.")
endif;
var chrts := chrt.CHRtSpec();
var selfOperation := chrts.context.oclAsType(Operation);
//Create a new Class containing this operation of the PI if it does not exist yet
var owner : Class;
if(slot<>null){
owner := slot.Slot2Class4SaStepProxy();
}else{
owner := owningInstance.Instance2Class4SaStepProxy();
};
result := new Operation(selfOperation);
}
owner.ownedOperation += result;
// Convert the newly created operation to a <<saStep>>
var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
saStep.execTime += chrt.getWCET();//chrts.localWCET;
//createSubUsageForPSMOperation(selfOperation, result, slot.owningInstance)
}
/*to be used for ARINCFunction mapping
mapping InstanceSpecification::InstanceUnprotected2SaStep(chrt : Comment, instance : InstanceSpecification) : Operation when {not chrt.CHRtSpec().isProtected()} {
init{
if chrt.CHRtSpec().isDeferred() then
log("Mapping InstanceUnprotected2SaStep: Operation is cyclic.")
else
log("Mapping InstanceUnprotected2SaStep: Operation is unprotected.")
endif;
var chrts := chrt.CHRtSpec();
var selfOperation := chrts.context.oclAsType(Operation);
//Create a new Class containing this operation of the PI if it does not exist yet
var owner := instance.Instance2Class4SaStepProxy();
result := new Operation(selfOperation);
}
owner.ownedOperation += result;
// Convert the newly created operation to a <<saStep>>
var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
saStep.execTime += chrt.getWCET();//chrts.localWCET;
//createSubUsageForPSMOperation(selfOperation, result, slot.owningInstance)
}*/
mapping Comment::CHRTCommentProtected2SaStepStrict(slot : Slot, ownerInstance:InstanceSpecification) : Operation
when {self.CHRtSpec().isProtected()} {
init{
//one Slot can have different chrtSpecification associated and so it can be mapped to multiple SaStep...
//TODO Operation's name can be a problem when used as identifier...
var res := ownerInstance.resolveIn(InstanceSpecification::InstanceProtected2SaStep, Operation)-> selectOne
(name=self.CHRtSpec().context.name);
if res = null then {
log(" Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
res := ownerInstance.map InstanceProtected2SaStep(self, slot);
} else
log(" Nothing to do")
endif;
result := res;
}
}
/*
@param slot: can be null, e.g. in case of private ARINCFUnction
*/
mapping Comment::CHRTCommentProtected2SaStep(slot : Slot, ownerInstance:InstanceSpecification) : Operation when {self.CHRtSpec().isProtected()} {
init{
log(" Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
var res := ownerInstance.map InstanceProtected2SaStep(self, slot);
result := res;
}
}
/*
//NOT USED
mapping InstanceSpecification::InstanceProtected2SaStepStrict(chrt : Comment, slot : Slot) : Operation when {chrt.CHRtSpec().isProtected()} {
//TODO Assumes 1 state (SwMutualExclusionResource) for each PI with guarded operations
init{
log(" Operation is protected.");
var chrts := chrt.CHRtSpec();
var selfOperation := chrts.context.oclAsType(Operation);
var owner := self.resolveoneIn(InstanceSpecification::ProtectedOperation2SwMutualExclusionResource, Class);
result := new Operation(selfOperation);
}
//Create a new SwMutualExclusionResource containing this operation for each PI port
if owner = null then
owner := self.map ProtectedOperation2SwMutualExclusionResource(chrt, slot)
endif;
var saMutualExRes := owner.getMetaclass("MARTE::MARTE_DesignModel::SRM::SW_Interaction::SwMutualExclusionResource").oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
//apply also a SaSharedResource in order to add it to sastep.sharedres
var saSharedRes := owner.getMetaclass("MARTE::MARTE_AnalysisModel::SAM::SaSharedResource").oclAsType(MARTE::SAM::SaSharedResource);
owner.ownedOperation += result;
// Convert the newly created operation to a <<saStep>>
var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
saStep.execTime += chrt.getWCET();//chrts.localWCET;
// The sharedRes will be set on the SaStep of the end to end workflow
saStep.sharedRes += saSharedRes;
}*/
/*
slot can be null, e.g. in case of private ARINCFunction
*/
mapping InstanceSpecification::InstanceProtected2SaStep(chrt : Comment, slot : Slot) : Operation when {chrt.CHRtSpec().isProtected()} {
//Assumes 1 state (SwMutualExclusionResource) for each InstanceSpecification with PI with guarded operations
init{
log(" Operation is protected.");
var chrts := chrt.CHRtSpec();
var selfOperation := chrts.context.oclAsType(Operation);
log("Check if the protected resource has already been created");
var owner := self.resolveoneIn(InstanceSpecification::ProtectedOperation2SwMutualExclusionResource, Class);
if owner = null then
//Create a new SwMutualExclusionResource containing this operation for each PI port
owner := self.map ProtectedOperation2SwMutualExclusionResource(chrt)
else
log("<<SwMutualExclusionResource>> found, nothing to do")
endif;
result := new Operation(selfOperation);
}
var saMutualExRes := owner.getMetaclass("MARTE::MARTE_DesignModel::SRM::SW_Interaction::SwMutualExclusionResource").oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
//apply also a SaSharedResource in order to add it to sastep.sharedres
var saSharedRes := owner.getMetaclass("MARTE::MARTE_AnalysisModel::SAM::SaSharedResource").oclAsType(MARTE::SAM::SaSharedResource);
owner.ownedOperation += result;
// Convert the newly created operation to a <<saStep>>
var saStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
saStep.execTime += chrt.getWCET();//chrts.localWCET;
// The sharedRes will be set on the SaStep of the end to end workflow
saStep.sharedRes += saSharedRes;
}
mapping InstanceSpecification::ProtectedOperation2SwMutualExclusionResource(annotation : Comment) : Class {
var name := self.name + "_state";
log(" <<SwMutualExclusionResource>> class not found. Generating '"+name+"' ");
result.name := name;
operationPackage.packagedElement += result;
var mutualExRes := result.applyStereotype(getMARTEStereotype("SwMutualExclusionResource")).oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
var saSharedRes := result.applyStereotype(getMARTEStereotype("SaSharedResource")).oclAsType(MARTE::SAM::SaSharedResource);
//saSharedRes.ceiling := "(value="+ self.CHRtSpec().ceiling +", source=req)";
//saSharedRes.ceiling := annotation.CHRtSpec().ceiling;
result.setCeiling2(annotation.CHRtSpec().ceiling);
result.setProtectKind2("PriorityCeiling");
}
/*
//NOT USED
mapping Slot::CHRTCommentSporadic2SaStepStrict(chrt : Comment) : Operation when {chrt.CHRtSpec().isSporadic()} {
//TODO Assumes 1 state (SwMutualExclusionResource) for each sporadic operation
init{
var res := self.owningInstance.resolveoneIn(InstanceSpecification::InstanceSporadic2SaStep, Operation);
if res = null then {
log(" Generating <<SaStep>> for operation '" + chrt.CHRtSpec().context.name + "'.");
res := self.owningInstance.map InstanceSporadic2SaStep(chrt, self);
} else
log(" Nothing to do")
endif;
result := res;
}
}*/
mapping Comment::CHRTCommentSporadic2SaStep(slot : Slot, ownerInstance:InstanceSpecification) : Operation
when {self.CHRtSpec().isSporadic()} {
init{
log(" Generating <<SaStep>> for operation '" + self.CHRtSpec().context.name + "'.");
var res := self.map InstanceSporadic2SaStep(slot, ownerInstance);
result := res;
}
}
helper Slot::Slot2Class4SaStepProxy() : Class {
var owner := self.resolveoneIn(Slot::Slot2Class4SaStep, Class);
if owner = null then {
owner := self.map Slot2Class4SaStep();
} endif;
return owner;
}
helper InstanceSpecification::Instance2Class4SaStepProxy() : Class {
var owner := self.resolveoneIn(Slot::Slot2Class4SaStep, Class);
if owner = null then {
owner := self.map InstanceSpecification2Class4SaStep();
} endif;
return owner;
}
/*
slot can be null, e.g. in case of private ARINCFunction
*/
mapping Comment::InstanceSporadic2SaStep(slot : Slot, ownerInstance:InstanceSpecification): Operation
when{self.CHRtSpec().isSporadic()} {
//TODO Assumes 1 state (SwMutualExclusionResource) for each sporadic operation
init{
log(" Operation is sporadic.");
var chrts := self.CHRtSpec();
var selfOperation := chrts.context.oclAsType(Operation);
var owner : Class;
if (slot <> null){
owner := slot.Slot2Class4SaStepProxy();
}else{
owner := ownerInstance.Instance2Class4SaStepProxy();
};
//Create a new SwMutualExclusionResource containing the put/get operation associated to this sporadic operation
var protectedState := ownerInstance.map SporadicOperation2SwMutualExclusionResource(self, slot);
result := new Operation(selfOperation);
}
owner.ownedOperation += result;
// Convert the newly created operation to a <<saStep>>
var localSaStep := result.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
localSaStep.execTime += self.getWCET();//chrts.localWCET;
//createSubUsageForPSMOperation(selfOperation, result, slot.owningInstance)
}
/*
slot can be null, e.g. in case of private ARINCFunction
*/
mapping InstanceSpecification::SporadicOperation2SwMutualExclusionResource(chrt : Comment, slot : Slot) : Class {
init{
var name : String;
if (slot <> null){
name := operationClassName(slot, chrt.CHRtSpec().context.name() + "_state");
}else{
name := operationClassName(self, chrt.CHRtSpec().context.name() + "_state");
};
log(" Generating <<SwMutualExclusionResource>> '" + name + "'.");
log(" NOTE 'put' and 'get' operations execution times are hardcoded: (worst=0.0,value=0.0,best=0.0,unit=ms)");
var putOp : Operation := new Operation("put");
var getOp : Operation := new Operation("get");
}
result.name := name;
operationPackage.packagedElement += result;
var swMutualExRes := result.applyStereotype(getMARTEStereotype("SwMutualExclusionResource")).oclAsType(MARTE::SRM::SW_Interaction::SwMutualExclusionResource);
//apply also a SaSharedResource in order to add it to sastep.sharedres
var saSharedRes := result.applyStereotype(getMARTEStereotype("SaSharedResource")).oclAsType(MARTE::SAM::SaSharedResource);
result.setCeiling2(chrt.CHRtSpec().ceiling);
result.setProtectKind2("PriorityCeiling");
result.ownedOperation += putOp;
result.ownedOperation += getOp;
var saPutOp := putOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
saPutOp.sharedRes += saSharedRes;
var saGetOp := getOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
saGetOp.sharedRes += saSharedRes;
saPutOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
saGetOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
}
mapping InstanceSpecification::HwBus2OperationClass() : Class {
init{
log(" Generating Bus operations. NOTE: 'send' and 'receive' execution times are hardcoded.");
log(" 'send' execution time is (worst=0.0,value=0.0,best=0.0,unit=ms)");
log(" 'receive' execution time is (worst=0.0,value=0.0,best=0.0,unit=ms)");
var sendOp : Operation := new Operation(self.name + "_send");
var receiveOp : Operation := new Operation(self.name + "_receive");
}
result.name := self.name + "_operation";
operationPackage.packagedElement+=result;
result.ownedOperation += sendOp;
result.ownedOperation += receiveOp;
var stsendOp := sendOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
var streceiveOp := receiveOp.applyStereotype(getMARTEStereotype("SaStep")).oclAsType(MARTE::SAM::SaStep);
//TODO for the moment exec time is hardcoded
stsendOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
streceiveOp.execTime := "(worst=0.0,value=0.0,best=0.0,unit=ms)";
}
/*
<<HwBus>>
It represents a special resource able to transfer data.
It is characterized by its address and word widths, these are functional values, usually different from the wires number of
its corresponding HW_Channel seeing that buses may be multiplexed or serial.
<<SaCommHost>>
In a communication host (e.g., network and bus), the related schedulable resource element is CommunicationChannel,
which may be characterized by concrete scheduling parameters (like the packet size).
*/
mapping InstanceSpecification::HwBus2SaCommHost() : Class {
init{
log (" Generating <<SaCommHost>>.");
var hwBus := self.getMetaclass(CHHwBusQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwBus);
}
result.name := self.name;
hostPackage.packagedElement += result;
var stHost := result.applyStereotype(getMARTEStereotype("SaCommHost")).oclAsType(MARTE::SAM::SaCommHost);
stHost.speedFactor := hwBus.speedFactor;//DEF"";
if stHost.speedFactor = null or stHost.speedFactor = "" then
stHost.speedFactor := "(value=1.0)"
endif;
stHost.blockT := hwBus.blockT;//DEF (worst=0.0,unit=ms)
if stHost.blockT->size() = 0 then
stHost.blockT += "(worst=0.0,unit=ms)"
endif;
stHost.packetT := hwBus.packetT;
if stHost.packetT->size() = 0 then
stHost.packetT += "(worst=1.0,unit=ms)"
endif;
}
/*
<<GaCommChannel>>
A logical communications layer connecting SchedulableResources.
*/
mapping InstanceSpecification::BusProperty2GaCommChannel(in host : InstanceSpecification) : Class {
log(" Found connected InstanceSpecification '" + self.name + "'. Generating <<GaCommChannel>>.");
log(" Scheduling parameters are hardcoded: fp(priority=(value=24,source=meas))");
result.name := self.name + "_" + host.name + "_server";
hostPackage.packagedElement += result;
var stCommChannel := result.applyStereotype(getMARTEStereotype("GaCommChannel")).oclAsType(MARTE::GQAM::GaCommChannel);
stCommChannel.host := host.resolveoneIn(InstanceSpecification::HwBus2SaCommHost, Class).getMetaclass(SaCommHostQN).oclAsType(MARTE::SAM::SaCommHost);
//TODO schedParams?
stCommChannel.schedParams := "fp(priority=(value=24,source=meas))";
}
/*
<<HwComputingResource>>
It is a high level concept that denotes an active execution resource.
Such resources are often clocked and may support a range of operating frequencies.
<<SaExecHost>>
A CPU or other device which executes functional steps. The SaExecHost stereotype adds schedulability metrics, interrupt
overheads, and utilization of scheduling processing.
*/
mapping InstanceSpecification::HwComputingResource2SaExecHost() : Class {
log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwComputingResource>> '" + self.classifier().name + "'.");
var hcr := self.getMetaclass(CHHwComputingResourceQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwComputingResource);
result.name := self.name;
hostPackage.packagedElement += result;
var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
stHost.schedPriRange := "[1..256]";
stHost.speedFactor := hcr.speedFactor;//"(value=1.0)";
}
helper InstanceSpecification::HwProcessor2SaExecHostHelper() : OclVoid {
log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwProcessor>> '" + self.classifier().name + "'.");
var i: Integer := 0;
var n: Integer := self.getNumberOfCores();
log("number of cores "+n.toString());
//check if it is RUN
isRUN := self.classifier().isRUN();
var schedPolicy := "partitioned";
if(isRUN){
schedPolicy := "global(RUN)";
};
var p := self.map HwProcessor2SaExecHost(null);
var pHost := p.getMetaclass("SaExecHost").oclAsType(MARTE::SAM::SaExecHost);
pHost.otherSchedPolicy := schedPolicy;
//Generate cores and assign the processor as the host for each core
while(n>1 and i < n) {
var c := self.map HwProcessor2SaExecHost("_core"+i.toString());
//TODO the following lines may be removed
var cc := object Class {
redefinedClassifier+=c;
name := c.name;
};
p.nestedClassifier +=cc;
c.getMetaclass("SaExecHost").oclAsType(MARTE::SAM::SaExecHost).host := pHost;
i := i + 1;
};
//Generates the supertasks
if(isRUN){
var supertasks := self.classifier().getRUNSupertasks();
supertasks->forEach(supertaskInfo){
var stname := supertaskInfo->asSequence()->first();
var stcapacity := supertaskInfo->last();
self.map HwProcessor2SaExecHostSupertask(stname, stcapacity);
};
};
}
mapping InstanceSpecification::HwProcessor2SaExecHostSupertask(supertask : String, capacity : String) : Class {
var message := "";
var name := self.name;
if(supertask<>null){
message := "'and supertask " + supertask;
name := name + supertask;
};
var host := self.resolveoneIn(InstanceSpecification::HwProcessor2SaExecHost, Class);
var saHost := host.getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwProcessor>> '" + self.classifier().name + message);
var hcr := self.getMetaclass(CHHwProcessorQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwProcessor);
result.name := name;
hostPackage.packagedElement += result;
var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
stHost.schedPriRange := "[1..256]";
stHost.speedFactor := hcr.speedFactor;
stHost.host := saHost;
stHost.schedPolicy := GRM_BasicTypes::SchedPolicyKind::EarliestDeadlineFirst;
stHost.otherSchedPolicy := "RUN";
var sr := result.applyStereotype(getMARTEStereotype("SwSchedulableResource")).oclAsType(MARTE::SRM::SW_Concurrency::SwSchedulableResource);
var schedParam := "capacity=(value=" + capacity +")";
sr.schedParams := "("+schedParam+")";
}
mapping InstanceSpecification::HwProcessor2SaExecHost(core : String) : Class {
var message := "";
var name := self.name;
if(core<>null){
message := "'and Core " + core;
name := name + core;
};
var host := self.resolveoneIn(InstanceSpecification::HwProcessor2SaExecHost, Class);
var saHost := host.getMetaclass(SaExecHostQN).oclAsType(MARTE::SAM::SaExecHost);
log("Generating <<SaExecHost>> from instanceSpecification '"+self.name+"' corresponding to <<CH_HwProcessor>> '" + self.classifier().name + message);
var hcr := self.getMetaclass(CHHwProcessorQN).oclAsType(chessmlprofile::HardwareBaseline::CH_HwProcessor);
result.name := name;
hostPackage.packagedElement += result;
var stHost := result.applyStereotype(getMARTEStereotype("SaExecHost")).oclAsType(MARTE::SAM::SaExecHost);
stHost.schedPriRange := "[1..256]";
stHost.speedFactor := hcr.speedFactor;
stHost.host := saHost;
}
/*
//NOT USED
//Create a new Activity as <<SaEndToEndFlow>>
mapping Slot::slot2EndToEndWorkFlowStrict(chrt : Comment) : Activity when {chrt.CHRtSpec().isDeferred()} {
init {
var res := self.owningInstance.resolveoneIn(InstanceSpecification::Instance2EndToEndWorkFlow, Activity);
if res = null then
res := self.owningInstance.map Instance2EndToEndWorkFlow(chrt, self)
else
log(" Nothing to do")
endif;
result := res;
}
}*/
//Create a new Activity as <<SaEndToEndFlow>>
mapping Slot::slot2EndToEndWorkFlow(chrt : Comment) : Activity when {chrt.CHRtSpec().isDeferred()} {
init {
var res := chrt.map Instance2EndToEndWorkFlow(self, self.owningInstance);
result := res;
}
}
/*
@param slot: can be null, in case chrt refers a private operation, i.e. ARINCFunction operation
*/
mapping Comment::Instance2EndToEndWorkFlow(slot : Slot, inst : InstanceSpecification) : Activity when {self.CHRtSpec().isDeferred()} {
init {
log("Generating <<EndToEndWorkFlow>> from the Instance"+ " for '" + inst.name + inst.getStringId() + "' and operation "+ self.CHRtSpec().context.name +".");
var chrts := self.CHRtSpec();
var actionName : String;
if (slot<>null){
actionName := opaqueActionName(slot, chrts);
}
else{
actionName := opaqueActionName(inst, chrts);
};
// entities for single and distributed communication
//var actInitialNode := new InitialNode("InitialNode1");
var controlFlowInit := new ControlFlow("ControlFlow1");
var actConstraint := new Constraint("Global_Timing_Req");
//setting internal references
//actInitialNode.outgoing += controlFlowInit;
}
/*Stefano
//add entity to store traceability information in the model. This infomation can then be used later in the editor to show analysis results related to the PIM entites.
//I would like to use a Dependency here between the Activity and the originating slot and chrt Comment, but in UML Comment cannot be referenced by dependency.
//so here I use Constraint...*/
var constr := new Constraint();
constr.constrainedElement += result;
constr.constrainedElement += slot;
constr.constrainedElement += self;
constr.constrainedElement += inst;
instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedRule += constr;
//end modification for traceability
result.name := actionName;
// Add the action to the owned behaviors of RTAnalysisContext
instSpecPackage.resolveoneIn(Package::CHGaResourcePlatform2SaAnalysisContext, Class).ownedBehavior += result;
//Apply the stereotype <<SaEndtoEndFlow>> to the activity
result.applyStereotype(getMARTEStereotype("SaEndtoEndFlow"));
result.precondition += actConstraint;
//we need to have the original deadline in a field not overritten by the MAST analysis
var e2estereo : Stereotype := result.getApplicableStereotype("MARTE::MARTE_AnalysisModel::SAM::SaEndtoEndFlow");
var e2eflow : MARTE::SAM::SaEndtoEndFlow = result.getStereotypeApplication(e2estereo).oclAsType(MARTE::SAM::SaEndtoEndFlow);
e2eflow.end2EndD += chrts.rlDl;
var actInitialNode := result.createInitialNode();
actInitialNode.outgoing += controlFlowInit;
result.edge += controlFlowInit;
//Apply stereotype <<gaLatencyObs>> and specify the deadline for the end to end flow
var gaLatencyObs := actConstraint.applyStereotype(getMARTEStereotype("GaLatencyObs")).oclAsType(MARTE::GQAM::GaLatencyObs);
//var relativeDeadline : String := "(value=" + CHRtRlDl + ",unit=ms)";
gaLatencyObs.latency += chrts.rlDl;
//if the current operation is deferred, it will be the first on the ICB
if (slot <> null) {
currentConcurRes := self.getConcurRes(slot);
}
else {
currentConcurRes := self.getConcurRes(inst);
};
//Apply stereotype <<gaWorkloadEvent>> and specify the release pattern
//of the end-to-end flow
var gaWorkloadEvent := actInitialNode.applyStereotype(getMARTEStereotype("GaWorkloadEvent")).oclAsType(MARTE::GQAM::GaWorkloadEvent);
gaWorkloadEvent.pattern := chrts.occKind;
var resultNode := createOpaqueActionsChainFull(chrts.isProtected(), self, slot, result, actInitialNode, inst);
//create final node
//var finalNode := new ActivityFinalNode("ActivityFinalNode1");
var finalNode := result.createFinalNode();
//result.node += finalNode;
//TODO assumption only one activity edge per node
resultNode.outgoing![ControlFlow].target := finalNode;
}
query chessmlprofile::RTComponentModel::CHRtSpecification::isDeferred() : Boolean {
var arrivalPattern := self.occKind.getArrivalPatternType();
//the operation is deferred if the arrival pattern is: periodic, sporadic, bursty
if arrivalPattern.oclIsInvalid() then
return false
endif;
return (arrivalPattern <> null and arrivalPattern.length() <> 0);
}
query chessmlprofile::RTComponentModel::CHRtSpecification::isSporadic() : Boolean {
var arrivalPattern := self.occKind.getArrivalPatternType();
if (arrivalPattern.oclIsUndefined()) then
return false
endif;
return (arrivalPattern.equalsIgnoreCase("sporadic"));// and self.isGuarded());
}
query chessmlprofile::RTComponentModel::CHRtSpecification::isProtected() : Boolean {
return (not self.isDeferred()) and self.protection = MARTE::HLAM::CallConcurrencyKind::guarded;
}
query Port::getCHrtSpecComment() : Comment {
return specs->selectOne(annotatedElement![Port] = self);
}
query InstanceSpecification::linkedHwInstanceSpecifications() : Set(InstanceSpecification) {
var res : Set(InstanceSpecification) := Set{};
var links := self.owner.ownedElement[InstanceSpecification]->select(classifier->size() = 0);
//var candidates := self.owner.ownedElement[InstanceSpecification] - links;
var busLinks := links->select(allOwnedElements()[InstanceValue]->selectOne(instance = self) <> null);
busLinks->forEach(l){
var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
res += l.allOwnedElements()[InstanceValue]->select(instance <> self).instance;
};
return res;
}
/*
Given a InstanceSpecification representing a Functional Partition
return the Components assigned to it
*/
query InstanceSpecification::getPartitionComponents() : Set(InstanceSpecification) {
var res : Set(InstanceSpecification) := Set{};
return res;
}
query getConnectingBusInstance(senderProcessor: InstanceSpecification, receiverProcessor: InstanceSpecification) : InstanceSpecification {
// get the hw connections and buses
//var links : Set(InstanceSpecification):= senderProcessor.owner.ownedElement[InstanceSpecification]->select(isStereotyped("CHESS::Dependability::DependableComponent::Propagation"));
var links : Set(InstanceSpecification):= senderProcessor.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
var buses := senderProcessor.owner.ownedElement[InstanceSpecification]->select(classifier->selectOne(isStereotyped(CHHwBusQN))<>null);
//for each bus, selects its connectors and check if the two processors are connected by 2 of those
buses->forEach(bus){
var busLinks := links->select(allOwnedElements()[InstanceValue]->selectOne(instance = bus) <> null);
var sender := busLinks->selectOne(allOwnedElements()[InstanceValue]->selectOne(instance = senderProcessor) <> null) <> null;
var receiver := busLinks->selectOne(allOwnedElements()[InstanceValue]->selectOne(instance = receiverProcessor) <> null) <> null;
if sender and receiver then {
log(" Found a bus interconnection: " + bus.name + ".");
return bus;
} endif;
};
return null;
}
query getConnectingBus(riIns : InstanceSpecification, piIns : InstanceSpecification) : InstanceSpecification {
var senderHwInstance := getAssignToFrom_MemoryPartition(riIns);
var receiverHwInstance := getAssignToFrom_MemoryPartition(piIns);
if senderHwInstance <> receiverHwInstance then
return getConnectingBusInstance(senderHwInstance, receiverHwInstance)
endif;
return null;
}
//query Port::getConnectedPort() : Port {
// var bindingConnector := self.getConnector();
// var myConnectorEnd := (bindingConnector.allOwnedElements()[ConnectorEnd])-> selectOne(role <> self);
// return myConnectorEnd.role.oclAsType(Port);
//}
//query Port::getConnectedPartWithPort() : Property {
// var bindingConnector := self.getConnector();
// var otherEnd := (bindingConnector.allOwnedElements()[ConnectorEnd])-> selectOne(role <> self);
// return otherEnd.partWithPort;
//}
//query Port::getCorrespondingSlot() : Slot {
// return slots->selectOne(definingFeature = self);
//}
query Slot::listAll() : Slot {
var riPiLinks := self.owner.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
riPiLinks->forEach(l) {
//TODO Assumption: each link has 2 and only 2 ends
var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
log("FIRST");
log("Instance", ends->first().instance![InstanceSpecification].name + ends->first().instance![InstanceSpecification].getStringId());
log("Slot", ends->first().owner![Slot].definingFeature![Port].name + ends->first().owner![Slot].getStringId());
log("LAST");
log("Instance", ends->last().instance![InstanceSpecification].name + ends->last().instance![InstanceSpecification].getStringId());
log("Slot", ends->last().owner![Slot].definingFeature![Port].name + ends->last().owner![Slot].getStringId());
};
return null;
}
/*Returns the slot connnected to the given slot, if any
*/
query Slot::getCorrespondingSlot() : Slot {
var riPiLinks := self.owner.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
riPiLinks->forEach(l){
//TODO Assumption: each link has 2 and only 2 ends
var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
// bug fixed: check also if the instance is the same, not only the slot
var bFirst := ends->first().instance![InstanceSpecification] = self.owningInstance;
bFirst := bFirst and
ends->first().owner![Slot].definingFeature![Port] = self.definingFeature;
var bLast := ends->last().instance![InstanceSpecification] = self.owningInstance;
bLast := bLast and
ends->last().owner![Slot].definingFeature![Port] = self.definingFeature;
if bFirst then {
var s := ends->last();
return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
} else
if bLast then {
var s := ends->first();//res += ends->first().instance//candidates->selectOne(ownedElement[Slot]->selectOne(s | s = ends->first()) <> null)
return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
} endif
endif;
};
return null;
}
/*
query Slot::getCorrespondingSlotFull() : Slot {
/*if we are not working with instSpecFull, we are on instSpec so use simpler checks to get the corresponding slot*
if(self.owner.owner![Package].name.endsWith("instSpec")) then {
return self.getCorrespondingSlot();
}endif;
var riPiLinks := self.owner.owner.ownedElement[InstanceSpecification]->select(classifier -> size() = 0);
riPiLinks->forEach(l){
//TODO Assumption: each link has 2 and only 2 ends
var ends := l.allOwnedElements()[InstanceValue]->asOrderedSet();
// bug fixed: check also if the instance is the same, not only the slot
var bFirst := ends->first().instance![InstanceSpecification] = self.owningInstance;
bFirst := bFirst and
ends->first().instance![InstanceSpecification].getId() = self.owningInstance.getId();
bFirst := bFirst and
ends->first().owner![Slot].definingFeature![Port] = self.definingFeature;
bFirst := bFirst and self.getId() = ends->first().owner![Slot].getId();
var bLast := ends->last().instance![InstanceSpecification] = self.owningInstance;
bLast := bLast and
ends->last().instance![InstanceSpecification].getId() = self.owningInstance.getId();
bLast := bLast and
ends->last().owner![Slot].definingFeature![Port] = self.definingFeature;
bLast := bLast and self.getId() = ends->last().owner![Slot].getId();
if bFirst then {
var s := ends->last();
return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
} else
if bLast then {
var s := ends->first();//res += ends->first().instance//candidates->selectOne(ownedElement[Slot]->selectOne(s | s = ends->first()) <> null)
return s.instance.slot->selectOne(definingFeature = s.owner![Slot].definingFeature);
} endif
endif;
};
return null;
}*/
/*
Return the "to" attribute of a given <Assign>Comment
*/
query Comment::getTo() : InstanceSpecification{
var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.to![InstanceSpecification];
}
query getAssignForInstance(p : InstanceSpecification) : MARTE::Alloc::Assign {
return assigns->selectOne(isAssignForInstance(p)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
}
query getAssignForInstance(p : Slot, c : Comment) : MARTE::Alloc::Assign {
return assigns->selectOne(isAssignForInstance(p, c)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
}
query InstanceSpecification::getComponentsOfPartition() : Set(InstanceSpecification) {
return partitionAssigns->select(isAssignForPartition(self)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign)._from.oclAsType(InstanceSpecification)->asSet();
}
query Classifier::getPartitionInstance() : InstanceSpecification {
return partitionAssigns->selectOne(isAssignForPartition(self)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign).to![InstanceSpecification].oclAsType(InstanceSpecification);
}
query InstanceSpecification::getAssignedCore() : String {
var c := assigns->selectOne(isAssignFromPartitionInstance(self));
return c.getCoreFromContraint();
}
query InstanceSpecification::getAssignedProcessor() : InstanceSpecification {
var c : MARTE::Alloc::Assign := assigns->selectOne(isAssignFromPartitionInstance(self)).getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return c.to![InstanceSpecification];
}
query Comment::isAssignFromPartitionInstance(p : InstanceSpecification) : Boolean {
var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return ass._from![InstanceSpecification] = p;
}
query Comment::isAssignForInstance(spec : InstanceSpecification) : Boolean {
var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
//return ass._from![InstanceSpecification] = spec.getSourceInstanceSpec() and self.isReferringId(spec.getId());
return ass._from![InstanceSpecification] = spec;
}
query Comment::isAssignForInstance(spec : Slot, chrt : Comment) : Boolean {
var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
var context := self.getContextFromContraint();
return ass._from![Slot].definingFeature = spec.definingFeature and context = chrt.CHRtSpec().context.name;
}
query Comment::isAssignForPartition(p : InstanceSpecification) : Boolean {
var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return ass.to![InstanceSpecification] = p;
}
query Comment::isAssignForPartition(p : Classifier) : Boolean {
var ass := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return ass.to![InstanceSpecification].classifier![Classifier] = p;
}
query getAssignToFrom_MemoryPartition(p : Slot, c : Comment) : InstanceSpecification {
var ass := getAssignForInstance(p, c);
var toInstance := ass.to![InstanceSpecification];
var toClass := toInstance.classifier![Classifier];
if toClass.isStereotyped(MemoryPartitionQN) then {
var a := assigns -> selectOne(isAssignedFrom(toInstance));
var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.to![InstanceSpecification];
} else //it is an hardware component
return ass.to![InstanceSpecification]
endif;
return null;
}
query getAssignedSupertaskFrom_MemoryPartition(p : Slot, c : Comment) : String {
var ass := getAssignForInstance(p, c);
var toInstance := ass.to![InstanceSpecification];
var toClass := toInstance.classifier![Classifier];
if toClass.isStereotyped(MemoryPartitionQN) then {
var a := assigns -> selectOne(isAssignedFrom(toInstance));
var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.base_Comment.getSupertaskFromContraint();
} else //it is an hardware component
return ass.base_Comment.getSupertaskFromContraint()
endif;
return null;
}
query getAssignedCoreFrom_MemoryPartition(p : Slot, c : Comment) : String {
//TODO how do we get a core if there is a memory partition?
var ass := getAssignForInstance(p, c);
var toInstance := ass.to![InstanceSpecification];
var toClass := toInstance.classifier![Classifier];
if toClass.isStereotyped(MemoryPartitionQN) then {
var a := assigns -> selectOne(isAssignedFrom(toInstance));
var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.base_Comment.getCoreFromContraint();
} else //it is an hardware component
return ass.base_Comment.getCoreFromContraint()
endif;
return null;
}
query getAssignToFrom_MemoryPartition(p : InstanceSpecification) : InstanceSpecification {
var ass := getAssignForInstance(p);
var toInstance := ass.to![InstanceSpecification];
var toClass := toInstance.classifier![Classifier];
if toClass.isStereotyped(MemoryPartitionQN) then {
var a := assigns -> selectOne(isAssignedFrom(toInstance));
var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.to![InstanceSpecification];
} else //it is an hardware component
return ass.to![InstanceSpecification]
endif;
return null;
}
query getAssignedCoreFrom_MemoryPartition(p : InstanceSpecification) : String {
//TODO how do we get a core if there is a memory partition?
var ass := getAssignForInstance(p);
var toInstance := ass.to![InstanceSpecification];
var toClass := toInstance.classifier![Classifier];
if toClass.isStereotyped(MemoryPartitionQN) then {
var a := assigns -> selectOne(isAssignedFrom(toInstance));
var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.base_Comment.getCoreFromContraint();
} else //it is an hardware component
return ass.base_Comment.getCoreFromContraint()
endif;
return null;
}
//query getAssignToFrom(p : InstanceSpecification) : InstanceSpecification {
// var a := assigns -> selectOne(isAssignedFrom(p));
// var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
// return asg.to![InstanceSpecification];
//}
//query getAssignFromTo(p : InstanceSpecification) : InstanceSpecification {
// var a := assigns -> selectOne(isAssignedTo(p));
// var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
// return asg._from![InstanceSpecification];
//}
query Comment::isAssignedFrom(p : InstanceSpecification) : Boolean {
var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg._from![InstanceSpecification] = p;
}
query Comment::isAssignedTo(p : InstanceSpecification) : Boolean {
var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::Alloc::Assign);
return asg.to![InstanceSpecification] = p;
}
//query InstanceSpecification::RIportSize(port : Port): Integer {
// return self.allOwnedElements()[Slot]->select(isRI())->size();
//}
//query InstanceSpecification::PIportSize(port : Port): Integer {
// return self.allOwnedElements()[Slot]->select(isPI())->size();
//}
//query InstanceSpecification::getRIportFromIndex(port : Port, i : Integer): Integer {
// var n := self.RIportSize(port);
// return i.mod(n);
//}
//query Slot::isRI() : Boolean {
// var cp := self.definingFeature![Port].getMetaclass(ClientServerPortQN).oclAsType(MARTE::GCM::ClientServerPort);
// return cp.reqInterface->isEmpty();
//}
//query Slot::isPI() : Boolean {
// var cp := self.definingFeature![Port].getMetaclass(ClientServerPortQN).oclAsType(MARTE::GCM::ClientServerPort);
// return cp.provInterface->isEmpty();
//}
query ConnectableElement::getLifeLineInstance(instances : Set(InstanceSpecification)) : InstanceSpecification {
var nonNullInstances : Set(InstanceSpecification) := instances->select(instance : InstanceSpecification | not instance.name.oclIsUndefined());
// 20150114: SP corrected next line to avoid trouble in case of an InstanceSpecification whose name is a substring of another
//return nonNullInstances->selectOne(instance : InstanceSpecification | instance.name.indexOf(name) > 0);
return nonNullInstances->selectOne(instance : InstanceSpecification | instance.name.endsWith("."+self.name));
}
helper Message::getMsgChrts() : chessmlprofile::RTComponentModel::CHRtSpecification {
//log("getMsgChrts... "+self.name);
var chrts : chessmlprofile::RTComponentModel::CHRtSpecification := null;
//log(self.name);
//get the operation
var operation : Operation := self.signature.oclAsType(Operation);
log("operation =" + operation.name);
//assume that Message's receiveEvent is of type MessageOccurrenceSpecification
var receiveEvent : MessageOccurrenceSpecification := self.receiveEvent.oclAsType(MessageOccurrenceSpecification);
log("receiveEvent= "+receiveEvent.name);
//assume that Message's receiveEvent covers only one lifeline
var lifeline : Lifeline := receiveEvent.covered->asSequence()->first();
log("Lifeline= "+lifeline.name);
//get the instance related to Lifeline's' "represents" feature
log("Found Lifeline for property: " + lifeline.represents.name + " with Type: " + lifeline.represents.type.name);
//search for instance in the CHGaResourcePlatform
var instance := lifeline.represents.getLifeLineInstance(instSpecPackage.allOwnedElements()[InstanceSpecification]);
log("Found Instance " + instance.name);
//get the instance's chrtPortSlots with a ChRtSpecification comment whose context is equal to the inital operation
var startInstSlots : Set(Slot):= instance.slot->select(isStereotyped(CHRtPortSlotQN));
startInstSlots->forEach(s){
var chrtSpecs := s.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot).cH_RtSpecification;
chrtSpecs->forEach(spec){
if(spec.context.qualifiedName.equalsIgnoreCase(operation.qualifiedName)) then {
chrts := spec;
currentSlot := s;
log("Slot [getMsgChrts]: " + s.definingFeature.name);
} endif;
};
};
//log("+++++++++++++ context: " + startChrts.context.name);
return chrts;
}
//assumption: the SaAnalysisContext.platform owns the reference to the package of the HW instances (to be considered for the analysis) available in the DeploymentView.
//returns the component which types the root HW instance stored in the package of the HW instances available in the DeploymentView.
query MARTE::SAM::SaAnalysisContext::getSystem() : Component {
var platforms : Set(MARTE::GQAM::GaResourcesPlatform) := self.platform->asSet();
platforms->forEach (plat){
var package : Element := plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
var found : Boolean = false;
while (not found) {
var owner : Element = package.owner;
if (owner.isStereotyped(DeploymentViewQN)){
found :=true;
break;
}else{
if (owner.oclIsTypeOf(Model)){
break;
}
};
package := owner;
};
if (found) {
package := plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
//package is in the deploymentView, search the system Component
var rootInst : InstanceSpecification := package.oclAsType(Package).getRootInstanceInPackage();
var classifier := rootInst.classifier -> asSequence() -> first();
log("found system component "+ classifier.name);
return classifier.oclAsType(Component);
}
};
return null;
}
//assumption: the SaAnalysisContext.platform owns the reference to the package of the SW instances (to be considered for the analysis) available in the ComponentView.
//returns the packages of the SW instances referred by SaAnalysisContext.platform
query MARTE::SAM::SaAnalysisContext::getSwSystemInstPackage() : Package {
var platforms : Set(MARTE::GQAM::GaResourcesPlatform) := self.platform->asSet();
platforms->forEach (plat){
var package : Element := plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package;
var found : Boolean = false;
while (not found) {
var owner : Element = package.owner;
if (owner.isStereotyped(ComponentViewQN)){
found :=true;
break;
}else{
if (owner.oclIsTypeOf(Model)){
break;
}
};
package := owner;
};
if (found) {
log("found SwSystemInstPackage "+ plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package.oclAsType(Package).name);
return plat.oclAsType(CHESS::Core::CHGaResourcePlatform).base_Package.oclAsType(Package);
}
};
return null;
}