| /* |
| ----------------------------------------------------------------------- |
| -- CHESS ceiling assignment transformation -- |
| -- -- |
| -- Copyright (C) 2011-2012 -- |
| -- University of Padova, ITALY -- |
| -- -- |
| -- Authors: Marco Panunzio panunzio@math.unipd.it -- |
| -- 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 -- |
| ----------------------------------------------------------------------- |
| */ |
| |
| import ProfileUtils_Inst_full; |
| import UMLUtils_Inst_full; |
| import chess.lib; |
| |
| modeltype UML uses "http://www.eclipse.org/uml2/2.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"; |
| |
| transformation CHESS_Assignment(inout source:UML); |
| |
| property model : Model = null; |
| property MARTEProfile : Profile = null; |
| property CHESSProfile : Profile = null; |
| |
| property assigns : Set(Comment) = null; |
| |
| property compView : Package = null; |
| property deplView : Package = null; |
| |
| property instSpecPackage : Package = null; |
| property instSpecPackageDepl : Package = null; |
| |
| |
| main() { |
| log("*** CHESS Ceiling assignment transformation ***"); |
| 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); |
| |
| compView := model.getView("ComponentView"); |
| instSpecPackage := compView.allOwnedElements()[Package]->selectOne(not getMetaclass("CHESS::Core::CHGaResourcePlatform").oclIsUndefined()); |
| |
| |
| deplView := model.getView("DeploymentView"); |
| instSpecPackageDepl := deplView.allOwnedElements()[Package]->selectOne(not getMetaclass("CHESS::Core::CHGaResourcePlatform").oclIsUndefined()); |
| assigns := deplView.allOwnedElements()[Comment]->select(isStereotyped(AssignQN)); |
| |
| model.map ModelWithCeiling(); |
| log("*** End of CHESS Ceiling assignment transformation ***"); |
| } |
| |
| helper Set(Slot)::printCeilings(){ |
| self->forEach(ps) { |
| var specs : Sequence(chessmlprofile::RTComponentModel::CHRtSpecification) := (ps.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot)).cH_RtSpecification->asSequence(); |
| specs->forEach(spec) { |
| var x := ps.definingFeature.qualifiedName + " " + spec.context.qualifiedName; |
| x := x + " "+ spec.ceiling; |
| log(x); |
| } |
| }; |
| } |
| |
| mapping inout Model::ModelWithCeiling() { |
| init{ |
| var chrtPortSlotList : Set(Slot) :=instSpecPackage.allOwnedElements()[Slot]->select(ps | ps.isStereotyped(CHRtPortSlotQN))->asSet(); |
| } |
| |
| // Initialization of own ceilings of cyclic and sporadic operations |
| // Initialization of ceiling of protected operation |
| // Initialization of ceiling of unprotected operation |
| chrtPortSlotList->forEach(ps) { |
| var specs : Sequence(chessmlprofile::RTComponentModel::CHRtSpecification) := (ps.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot)).cH_RtSpecification->asSequence(); |
| specs->forEach(spec) { |
| if (spec.isDeferred()) then { |
| spec.ceiling := spec.relativePriority |
| } else { |
| spec.ceiling := "-127"; |
| } endif; |
| } |
| }; |
| |
| log("Before:"); |
| chrtPortSlotList->printCeilings(); |
| |
| // Ceiling propagation |
| chrtPortSlotList->forEach(ps) { |
| var specs : Sequence(chessmlprofile::RTComponentModel::CHRtSpecification) := (ps.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot)).cH_RtSpecification->asSequence(); |
| specs->forEach(spec) { |
| if (spec.isDeferred()) then { |
| ps.map propagateCeiling(spec); |
| } endif |
| } |
| }; |
| |
| log("After:"); |
| chrtPortSlotList->printCeilings(); |
| |
| |
| //After ceiling propagation, remove ceilings of unprotected operations |
| chrtPortSlotList->forEach(ps) { |
| var specs : Sequence(chessmlprofile::RTComponentModel::CHRtSpecification) := (ps.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot)).cH_RtSpecification->asSequence(); |
| specs->forEach(spec) { |
| if ((not spec.isDeferred()) and (not spec.isProtected())) then { |
| spec.ceiling := null; |
| } endif |
| } |
| } |
| |
| } |
| |
| mapping inout Slot::propagateCeiling(spec : chessmlprofile::RTComponentModel::CHRtSpecification) { |
| init { |
| var ceilingToPropagate := spec.ceiling; |
| var sourceOp : Operation := spec.context.oclAsType(Operation); |
| var currInstance : InstanceSpecification := self.owningInstance; |
| } |
| |
| if (sourceOp.method->notEmpty()) then { |
| var act := (sourceOp.method->asSequence()->first().oclAsType(Activity)); |
| var coaList := act.collectCallOperationNodes(); |
| |
| coaList->forEach(coa) { |
| var calledOp := coa.operation; |
| var riPort := coa.onPort; |
| var riSlot : Slot := currInstance.slot[definingFeature = riPort]->any(true); |
| var connectedSlot : Slot := riSlot.getConnectedSlot(currInstance); |
| var CHRtSpec := connectedSlot.CHRtSpecForOperation(calledOp); |
| |
| /* If the component instances are deployed on different nodes |
| * we need to set the ceiling priority to the priority of the |
| * server task of the middleware. |
| * Currently it is hardcoded to 27. |
| */ |
| |
| if (not riSlot.owningInstance.isDeployedOnSameProcesor(connectedSlot.owningInstance)) then |
| ceilingToPropagate := "27" |
| endif; |
| |
| |
| if (ceilingToPropagate.asInteger() > CHRtSpec.ceiling.asInteger()) then { |
| if (CHRtSpec.isDeferred()) then { |
| //Raise the ceiling of the OBCS and terminate |
| CHRtSpec.ceiling := ceilingToPropagate; |
| |
| } else { |
| if (CHRtSpec.isProtected()) then { |
| //Raise the ceiling of the protected object |
| // (i.e. all protected operations of the slot) |
| // and recursively continue |
| CHRtSpec.ceiling := ceilingToPropagate; |
| connectedSlot.map propagateCeiling(CHRtSpec); |
| |
| var specs : Sequence(chessmlprofile::RTComponentModel::CHRtSpecification) := |
| (connectedSlot.getMetaclass(CHRtPortSlotQN).oclAsType(chessmlprofile::RTComponentModel::CHRtPortSlot)).cH_RtSpecification->asSequence(); |
| specs ->forEach(mySpec) { |
| |
| if (mySpec.isProtected()) then { |
| if (ceilingToPropagate.asInteger() > mySpec.ceiling.asInteger()) then { |
| mySpec.ceiling := ceilingToPropagate; |
| connectedSlot.map propagateCeiling(mySpec); |
| } endif; |
| } endif; |
| } |
| } else {//Unprotected |
| CHRtSpec.ceiling := ceilingToPropagate; |
| connectedSlot.map propagateCeiling(CHRtSpec); |
| } endif; |
| } endif; |
| } endif; |
| }; |
| } endif; |
| |
| } |
| |
| query InstanceSpecification::isConnectorInstance() : Boolean { |
| if (self.classifier->isEmpty()) then |
| if (self.slot->any(true).isStereotyped(ClientServerPortQN)) then |
| return true |
| endif |
| endif; |
| return false; |
| } |
| |
| query Element::isNullOrInvalid() : Boolean { |
| if(self.oclIsInvalid() or self.oclIsUndefined())then |
| return true |
| endif; |
| return self.isNull(); |
| } |
| |
| query Slot::getConnectedSlot(compInst : InstanceSpecification) : Slot { |
| var riPort := self.definingFeature.oclAsType(Port); |
| var myInstanceValue : InstanceValue := null; |
| var connectorPIslot : Slot := null; |
| var targetInstance : InstanceSpecification := null; |
| |
| var connectorInstList := InstanceSpecification.allInstances()->select(classifier->size() = 0); |
| connectorInstList->forEach(connInst) { |
| var candidateSlot : Slot := connInst.slot->selectOne(definingFeature = riPort); |
| if (candidateSlot.oclIsInvalid()) continue endif; |
| if (not candidateSlot.isNullOrInvalid()) then { |
| myInstanceValue := (candidateSlot.allOwnedElements()[InstanceValue])->selectOne(instance = compInst); |
| if (myInstanceValue.oclIsInvalid()) continue endif; |
| if (not myInstanceValue.isNullOrInvalid()) then { |
| connectorPIslot := connInst.slot->selectOne(definingFeature <> riPort); |
| targetInstance := connectorPIslot.value->selectOne(true).oclAsType(InstanceValue).instance; |
| return targetInstance.slot->selectOne(definingFeature = connectorPIslot.definingFeature); |
| } endif; |
| } endif; |
| |
| }; |
| return null; |
| } |
| |
| query InstanceSpecification::isDeployedOnSameProcesor(is : InstanceSpecification) : Boolean { |
| var proc1 : InstanceSpecification := getDeploymentProcessor(self); |
| return proc1 = getDeploymentProcessor(is); |
| } |
| |
| |
| query getDeploymentProcessor(p : InstanceSpecification) : InstanceSpecification { |
| var a := assigns -> selectOne(isAssignedFrom(p)); |
| var asg := a.getMetaclass(AssignQN).oclAsType(MARTE::MARTE_Foundations::Alloc::Assign); |
| return asg.to![InstanceSpecification]; |
| } |
| |
| /** |
| * Start of reused code by azovi |
| */ |
| |
| /* |
| Given an ICB-Activity return the list of all its CallOperationAction nodes, |
| assuming that their are all connected in a single chain: no loops and branches. |
| |
| older version. current one has been moved in UMLUtils_Inst_full.qvto |
| */ |
| query Activity::collectCallOperationNodesOLD() : Sequence(CallOperationAction) { |
| var nodes : Sequence(CallOperationAction) := Sequence{}; |
| var prevNode : ActivityNode := self.node![InitialNode]; |
| var nextNode : ActivityNode; |
| while(true){ |
| nextNode := prevNode.outgoing->any(true).target.oclAsType(CallOperationAction); |
| if (nextNode.oclIsInvalid()) break endif; |
| if (not nextNode.isNullOrInvalid()) then { |
| nodes += nextNode.oclAsType(CallOperationAction); |
| prevNode := nextNode; |
| } |
| else{ |
| break; |
| } |
| endif; |
| }; |
| return nodes; |
| } |
| |
| 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(); |
| return (arrivalPattern.equalsIgnoreCase("sporadic"));// and self.isGuarded()); |
| } |
| |
| query chessmlprofile::RTComponentModel::CHRtSpecification::isProtected() : Boolean { |
| return (not self.isDeferred()) and self.protection = MARTE::MARTE_DesignModel::HLAM::CallConcurrencyKind::guarded; |
| } |
| |
| query Port::getConnectedPort() : Port { |
| var bindingConnector := self.getConnector(); |
| var myConnectorEnd := (bindingConnector.allOwnedElements()[ConnectorEnd])-> selectOne(role <> self); |
| return myConnectorEnd.role.oclAsType(Port); |
| } |
| |
| |
| query Comment::isAssignedFrom(p : InstanceSpecification) : Boolean { |
| var asg := self.getMetaclass(AssignQN).oclAsType(MARTE::MARTE_Foundations::Alloc::Assign); |
| return asg._from![InstanceSpecification] = p; |
| } |