| /* |
| ----------------------------------------------------------------------- |
| -- 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; |
| |
| } |
| |
| |
| |