| package templates |
| |
| import com.inchron.realtime.root.model.CallSequenceItem |
| import com.inchron.realtime.root.model.GenericSystem |
| import com.inchron.realtime.root.model.SemaphoreAccessType |
| import com.inchron.realtime.root.model.TimeDistributionType |
| import com.inchron.realtime.root.model.TimeUnit |
| import java.util.ArrayList |
| import java.util.List |
| import java.util.Set |
| import org.eclipse.app4mc.amalthea.model.Amalthea |
| import org.eclipse.app4mc.amalthea.model.AsynchronousServerCall |
| import org.eclipse.app4mc.amalthea.model.CallGraph |
| import org.eclipse.app4mc.amalthea.model.CallSequence |
| import org.eclipse.app4mc.amalthea.model.ChannelReceive |
| import org.eclipse.app4mc.amalthea.model.ChannelSend |
| import org.eclipse.app4mc.amalthea.model.CustomEventTrigger |
| import org.eclipse.app4mc.amalthea.model.ExecutionNeed |
| import org.eclipse.app4mc.amalthea.model.Group |
| import org.eclipse.app4mc.amalthea.model.HwFeature |
| import org.eclipse.app4mc.amalthea.model.ISR |
| import org.eclipse.app4mc.amalthea.model.InterProcessTrigger |
| import org.eclipse.app4mc.amalthea.model.LabelAccess |
| import org.eclipse.app4mc.amalthea.model.ModeLabelAccess |
| import org.eclipse.app4mc.amalthea.model.ModeSwitch |
| import org.eclipse.app4mc.amalthea.model.Need |
| import org.eclipse.app4mc.amalthea.model.NeedConstant |
| import org.eclipse.app4mc.amalthea.model.NeedDeviation |
| import org.eclipse.app4mc.amalthea.model.Preemption |
| import org.eclipse.app4mc.amalthea.model.ProbabilitySwitch |
| import org.eclipse.app4mc.amalthea.model.Process |
| import org.eclipse.app4mc.amalthea.model.ProcessingUnit |
| import org.eclipse.app4mc.amalthea.model.Runnable |
| import org.eclipse.app4mc.amalthea.model.RunnableCall |
| import org.eclipse.app4mc.amalthea.model.RunnableModeSwitch |
| import org.eclipse.app4mc.amalthea.model.RunnableProbabilitySwitch |
| import org.eclipse.app4mc.amalthea.model.SemaphoreAccess |
| import org.eclipse.app4mc.amalthea.model.SemaphoreAccessEnum |
| import org.eclipse.app4mc.amalthea.model.SenderReceiverRead |
| import org.eclipse.app4mc.amalthea.model.SenderReceiverWrite |
| import org.eclipse.app4mc.amalthea.model.SynchronousServerCall |
| import org.eclipse.app4mc.amalthea.model.Task |
| import org.eclipse.app4mc.amalthea.model.TaskRunnableCall |
| import org.eclipse.app4mc.amalthea.model.Time |
| import org.eclipse.app4mc.amalthea.model.util.DeploymentUtil |
| import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil |
| import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType |
| import org.eclipse.emf.common.util.EMap |
| import org.eclipse.emf.ecore.util.EcoreUtil |
| import templates.utils.AmltCacheModel |
| |
| /** |
| * This class is responsible to convert Amalthea SW Model eleemnts to corresponding Inchron elements and invoke other transformation classes |
| */ |
| public class SWTransformer extends AbstractAmaltheaInchronTransformer { |
| |
| /** |
| * Creating a Inchron Process element from Amalthea ISR element |
| */ |
| def create inchronModelFactory.createProcess createProcess(ISR amltISR){ |
| it.isr = true |
| it.name=amltISR.name |
| /*-Building a cache of Stimuli name and the "List of Process" elements to which it is associated to */ |
| val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel) |
| amltISR.stimuli.forEach[stimuli | |
| amltCache.cacheAmltStimuliInchronProcessMap(stimuli.getName, it) |
| ] |
| |
| } |
| |
| |
| /** |
| * Creating a Inchron Process element from Amalthea Task element |
| */ |
| def create inchronModelFactory.createProcess createProcess(Task amltTask){ |
| it.isr = false |
| it.name=amltTask.name |
| |
| //TODO: schedule between runnables for co-operative |
| if(amltTask.preemption == Preemption.NON_PREEMPTIVE || amltTask.preemption == Preemption.COOPERATIVE){ |
| it.preemptable=false |
| }else{ |
| it.preemptable=true |
| } |
| |
| if(amltTask.callGraph !=null){ |
| /*-building a inchron CallGraph element from amalthea CallGraph */ |
| it.callGraph=createCallGraph(amltTask.callGraph) |
| } |
| |
| /*-Building a cache of Stimuli name and the "List of Process" elements to which it is associated to */ |
| val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel) |
| amltTask.stimuli.forEach[stimuli | |
| amltCache.cacheAmltStimuliInchronProcessMap(stimuli.getName, it) |
| ] |
| |
| } |
| |
| /** |
| * This method is used to create a Inchron CallGraph element from Amalthea CallGraph element |
| */ |
| def create inchronModelFactory.createCallGraph createCallGraph(CallGraph amltCallGraph){ |
| |
| amltCallGraph.graphEntries.forEach[amltGraphEntry| |
| |
| if(amltGraphEntry instanceof CallSequence){ |
| |
| it.graphEntries.add(createCallSequence(amltGraphEntry as CallSequence)) |
| |
| }else if(amltGraphEntry instanceof ModeSwitch){ |
| it.graphEntries.add(createModeSwitch(amltGraphEntry as ModeSwitch)) |
| |
| }else if(amltGraphEntry instanceof ProbabilitySwitch){ |
| it.graphEntries.add(createProbabilitySwitch(amltGraphEntry as ProbabilitySwitch)) |
| |
| } |
| ] |
| |
| } |
| |
| /** |
| * This method is used to create inchron CallSequence object from Amalthea CallSequence element. |
| * |
| * Below are the CallSequence items are currently supported: |
| * <br>1.TaskRunnableCall |
| * <br>2.InterProcessTrigger |
| * |
| */ |
| def create inchronModelFactory.createCallSequence createCallSequence(CallSequence amltCallSequence){ |
| it.name=amltCallSequence.name |
| amltCallSequence?.calls.forEach[amltCallsequenceItem| |
| |
| //todo: handle other CallSequenceItem's |
| |
| if(amltCallsequenceItem instanceof TaskRunnableCall){ |
| |
| it.calls.add(createFunctionCall(amltCallsequenceItem as TaskRunnableCall)) |
| } |
| |
| if (amltCallsequenceItem instanceof InterProcessTrigger) { |
| it.calls.add(createActivationItem(amltCallsequenceItem as InterProcessTrigger)) |
| } |
| ] |
| } |
| |
| /** |
| * This method is used to create inchron InterProcessTrigger element from Amalthea ActivationItem element |
| */ |
| def create inchronModelFactory.createActivationItem createActivationItem(InterProcessTrigger trigger) { |
| |
| val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel) |
| |
| val tasks = amltCache.interProcessTriggerRelationsMap.get(trigger.stimulus.name); |
| |
| val inchronConnection=amltCache.inchronConnectionElementsMap.get(trigger.stimulus.name) |
| |
| it.connection =inchronConnection |
| |
| if(tasks !=null){ |
| for ( task : tasks) { |
| val inchronActivateProcess=createActivateProcess(trigger, task as Task) |
| inchronConnection.activations.add(inchronActivateProcess) |
| } |
| |
| }else{ |
| //Note: This is the case where Stimulus is not InterProcessStimulus or there are no Process elements to which this stimulus is triggering |
| } |
| |
| } |
| |
| /** |
| * This method is used to create inchron ActivateProcess element from Amalthea InterProcessTrigger |
| */ |
| def create inchronModelFactory.createActivateProcess createActivateProcess(InterProcessTrigger trigger, Task amltTask) { |
| |
| it.target = createProcess(amltTask); |
| it.offset = trigger.counter.offset as int |
| it.period = trigger.counter.prescaler as int |
| } |
| |
| |
| def create inchronModelFactory.createModeSwitch createModeSwitch(ModeSwitch amltModeSwitch){ |
| //TODO: need to enhance it in near future |
| } |
| |
| def create inchronModelFactory.createProbabilitySwitch createProbabilitySwitch(ProbabilitySwitch amltProbabilitySwitch){ |
| //TODO: need to enhance it in near future |
| } |
| |
| /** |
| * This method is used to create inchron FunctionCall element from RunnableCall element |
| */ |
| def create inchronModelFactory.createFunctionCall createFunctionCall(RunnableCall amltRunnableCall){ |
| |
| var amltProcess=amltRunnableCall.getParentContainer(Process) |
| |
| var inchronComponent=createComponent(amltProcess) |
| |
| |
| val inchronGenericSystem= getInchronGenericSystem(amltProcess) |
| |
| if(inchronGenericSystem !=null){ |
| inchronGenericSystem.components.add(inchronComponent) |
| |
| } |
| |
| var inchronFunction=createFunction(amltProcess, amltRunnableCall.runnable) |
| |
| inchronComponent.functions.add(inchronFunction) |
| |
| it.function=inchronFunction |
| } |
| |
| |
| /** |
| * This method is used to create inchron FunctionCall element from TaskRunnableCall element |
| */ |
| def create inchronModelFactory.createFunctionCall createFunctionCall(TaskRunnableCall amltTaskRunnableCall){ |
| |
| var amltProcess=amltTaskRunnableCall.getParentContainer(Process) |
| |
| var inchronComponent=createComponent(amltProcess) |
| |
| val inchronGenericSystem= getInchronGenericSystem(amltProcess) |
| |
| if(inchronGenericSystem !=null){ |
| inchronGenericSystem.components.add(inchronComponent) |
| |
| } |
| |
| var inchronFunction=createFunction(amltProcess, amltTaskRunnableCall.runnable) |
| |
| it.function=inchronFunction |
| |
| inchronComponent.functions.add(inchronFunction) |
| |
| it.offset=amltTaskRunnableCall?.counter?.offset.intValue |
| |
| it.period=amltTaskRunnableCall?.counter?.prescaler.intValue |
| } |
| |
| /** |
| * This method is used to fetch the inchron GenericSystem object for a specific Amalthea Process element |
| */ |
| def GenericSystem getInchronGenericSystem(Process amltProcess) { |
| |
| val Set<ProcessingUnit> cores=DeploymentUtil.getAssignedCoreForProcess(amltProcess as Process, EcoreUtil.getRootContainer(amltProcess) as Amalthea) |
| |
| val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel) |
| |
| //TODO: write validaiton to assure that only 1 core is present |
| |
| //TODO: currently taking 1st core |
| |
| if(cores.size>0){ |
| //TODO: clarify if this approach is OK !! |
| val amltCore=cores.get(0) |
| |
| val amltMicroController=amltCore.eContainer |
| |
| val inchronGenericSystem=amltCache.mappingAmltMicroController_GenericSystem.get(amltMicroController) |
| |
| return inchronGenericSystem |
| } |
| } |
| |
| |
| def create inchronModelFactory.createComponent createComponent(Process amltProcess){ |
| |
| it.name=amltProcess.name |
| } |
| |
| def create inchronModelFactory.createFunction createFunction(Process amltProcess, Runnable amltRunnable){ |
| |
| it.name=amltRunnable.name |
| |
| it.callGraph=inchronModelFactory.createCallGraph |
| |
| val inchronCallSequence=inchronModelFactory.createCallSequence |
| |
| it.callGraph.graphEntries.add(inchronCallSequence) |
| |
| amltRunnable?.runnableItems.forEach[amltRunnableItem| |
| |
| if(amltRunnableItem instanceof AsynchronousServerCall){ |
| |
| } |
| else if(amltRunnableItem instanceof ChannelReceive){ |
| |
| } |
| else if(amltRunnableItem instanceof ChannelSend){ |
| |
| } |
| else if(amltRunnableItem instanceof CustomEventTrigger){ |
| |
| } |
| else if(amltRunnableItem instanceof Group){ |
| |
| } |
| else if(amltRunnableItem instanceof LabelAccess){ |
| |
| } |
| else if(amltRunnableItem instanceof ModeLabelAccess){ |
| |
| } |
| else if(amltRunnableItem instanceof RunnableCall){ |
| |
| inchronCallSequence.calls.add(createFunctionCall( amltRunnableItem)) |
| |
| |
| }else if(amltRunnableItem instanceof ExecutionNeed){//Earlier it was RunnableInstructions |
| |
| inchronCallSequence.calls.add(createResourceConsumption(amltProcess, amltRunnableItem)) |
| } |
| else if(amltRunnableItem instanceof RunnableModeSwitch){ |
| |
| } |
| else if(amltRunnableItem instanceof RunnableProbabilitySwitch){ |
| |
| } |
| else if(amltRunnableItem instanceof SemaphoreAccess){ |
| inchronCallSequence.calls.addAll(semaphoreInterruptCreation(amltRunnableItem)) |
| } |
| |
| else if(amltRunnableItem instanceof SenderReceiverRead){ |
| |
| } |
| else if(amltRunnableItem instanceof SenderReceiverWrite){ |
| |
| } |
| else if(amltRunnableItem instanceof SynchronousServerCall){ |
| |
| } |
| ] |
| } |
| |
| def create inchronModelFactory.createSemaphoreAccess createSemaphoreAccess(SemaphoreAccess amltAccess) { |
| |
| val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel) |
| |
| val amltSemaphoreName=amltAccess?.semaphore?.name |
| |
| //TODO CREATE THIS THE RIGHT WAY! |
| var inchronSemaphore = amltCache.getInchronSemaphoreCacheElement(amltSemaphoreName)// = createSemaphore(amltSemaphore); |
| //SemaphoreAccessType.; |
| //amltAccess.access; |
| |
| switch (amltAccess.access) { |
| case SemaphoreAccessEnum.RELEASE: { |
| it.type = SemaphoreAccessType.RELEASE |
| } |
| case SemaphoreAccessEnum.EXCLUSIVE: { |
| it.type = SemaphoreAccessType.EXCLUSIVE |
| } |
| case SemaphoreAccessEnum.REQUEST : { |
| it.type = SemaphoreAccessType.REQUEST |
| } |
| } |
| it.semaphore = inchronSemaphore; |
| |
| |
| } |
| |
| def List<CallSequenceItem> semaphoreInterruptCreation(SemaphoreAccess amltAccess){ |
| |
| val List<CallSequenceItem> items=new ArrayList |
| |
| switch (amltAccess.access) { |
| |
| case SemaphoreAccessEnum.RELEASE: { |
| |
| items.add(createSemaphoreAccess(amltAccess)) |
| |
| items.add(createResumeAllInterrupts(amltAccess)) |
| |
| } |
| case SemaphoreAccessEnum.EXCLUSIVE: { |
| //TODO:check semantics |
| items.add(createSuspendAllInterrupts(amltAccess)) |
| items.add(createSemaphoreAccess(amltAccess)) |
| |
| } |
| case SemaphoreAccessEnum.REQUEST : { |
| |
| items.add(createSuspendAllInterrupts(amltAccess)) |
| items.add(createSemaphoreAccess(amltAccess)) |
| |
| |
| } |
| } |
| return items |
| } |
| |
| /* |
| * LL: SemaphoreAccess object should be mandatorily supplied here, as Xtend caches the elements based on input parameters |
| */ |
| def create inchronModelFactory.createSuspendAllInterrupts createSuspendAllInterrupts(SemaphoreAccess amltAccess) { |
| it.offset=0 |
| it.period=0 |
| } |
| |
| /* |
| * LL: SemaphoreAccess object should be mandatorily supplied here, as Xtend caches the elements based on input parameters |
| */ |
| def create inchronModelFactory.createResumeAllInterrupts createResumeAllInterrupts(SemaphoreAccess amltAccess) { |
| it.offset=0 |
| it.period=0 |
| } |
| |
| |
| def create inchronModelFactory.createResourceConsumption createResourceConsumption(Process amltProcess, ExecutionNeed amltRunnableInstructions){ |
| val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel) |
| |
| |
| if(amltProcess instanceof Task){ |
| |
| |
| var listOfTaskAllocations=amltCache.tasks_TaskAllocationMap.get(amltProcess as Task) |
| |
| listOfTaskAllocations?.forEach[amltTaskAllocation| |
| var amltScheduler=amltTaskAllocation.scheduler |
| |
| var amltSchedulerAllocation=amltCache.taskScheduler_schedulerAllocationMap.get(amltScheduler) |
| |
| //TODO: What if affinity is not set and core should be derived from SchedulerMapping? |
| var List cores1=amltTaskAllocation.affinity |
| |
| var List cores2 =(amltSchedulerAllocation.responsibility) |
| |
| //to obtain only common Core objects across both lists |
| cores1.retainAll(cores2) |
| |
| //TODO: write assumptions about core mapping of tasks (if it is 1 to 1 mapping ?) |
| |
| if(cores1.size==1){ |
| var timeDistribution=inchronModelFactory.createTimeDistribution |
| //TODO: uniform as a starting point --- more complex distributions need to be simulated |
| timeDistribution.type = TimeDistributionType.UNIFORM |
| timeDistribution.bcet = getRuntimeForRunnableInstruction(amltRunnableInstructions, TimeType.BCET, cores1.get(0) as ProcessingUnit); |
| timeDistribution.wcet = getRuntimeForRunnableInstruction(amltRunnableInstructions, TimeType.WCET, cores1.get(0) as ProcessingUnit); |
| timeDistribution.mean = getRuntimeForRunnableInstruction(amltRunnableInstructions, TimeType.ACET, cores1.get(0) as ProcessingUnit); |
| it.timeDistribution = timeDistribution |
| |
| } |
| ] |
| } |
| } |
| |
| |
| |
| //TODO: Check if some of this methods can be part of AMALTHEA |
| //TODO: set getInstructionCountForInstruction to public in APP4MC UTILS |
| def com.inchron.realtime.root.model.Time getRuntimeForRunnableInstruction(ExecutionNeed amltRunnableInstructions, TimeType timeType, ProcessingUnit core) { |
| //TODO: handle extended instructions |
| var amltInstructions = getInstructionCountForInstruction(amltRunnableInstructions.^default, timeType); |
| val hwFeatureFromExecutionNeed = getHwFeatureFromExecutionNeed(amltRunnableInstructions,core) |
| var amltTime = RuntimeUtil.getExecutionTimeForExecutionNeedValueCount(amltInstructions, core, hwFeatureFromExecutionNeed,null); |
| return getInchronTimeValue(amltTime); |
| |
| } |
| |
| def HwFeature getHwFeatureFromExecutionNeed(ExecutionNeed executionNeed, ProcessingUnit processingUnit){ |
| |
| val EMap<String, Need> defaultMap = executionNeed.^default |
| |
| if(defaultMap.size>0){ |
| val processingUnitDefinition = processingUnit.definition |
| if(processingUnitDefinition!=null){ |
| for(feature: processingUnitDefinition?.features){ |
| //TODO:At present supporting only HwFeatureCategory with name "Instructions" |
| if(feature.containingCategory?.name.equals("Instructions")){ |
| return feature |
| } |
| } |
| } |
| } |
| |
| return null |
| } |
| |
| def Long getInstructionCountForInstruction(EMap<String, Need> defaultMap, TimeType execTimeType) { |
| |
| |
| for(need: defaultMap.values){ |
| if(need instanceof NeedDeviation) { |
| var NeedDeviation instDeviation = need as NeedDeviation ; |
| switch(execTimeType) { |
| case ACET: { |
| return RuntimeUtil.getMean(instDeviation.getDeviation().getDistribution(), instDeviation.getDeviation().getLowerBound().getValue(), instDeviation.getDeviation().getUpperBound().getValue()) |
| } |
| case BCET: { |
| return instDeviation.getDeviation().getLowerBound().getValue() |
| } |
| case WCET: { |
| return instDeviation.getDeviation().getUpperBound().getValue(); |
| } |
| default: |
| return RuntimeUtil.getMean(instDeviation.getDeviation().getDistribution(), instDeviation.getDeviation().getLowerBound().getValue(), instDeviation.getDeviation().getUpperBound().getValue()) |
| |
| |
| } |
| } else if(need instanceof NeedConstant) { |
| return (need as NeedConstant).getValue(); |
| } |
| |
| } |
| |
| |
| return 0L; |
| } |
| |
| def com.inchron.realtime.root.model.Time getInchronTimeValue(Time amltTime) { |
| var result = inchronModelFactory.createTime |
| |
| result.value = amltTime.value.longValue; |
| switch (amltTime.unit.getName) { |
| case "s": { |
| result.unit = TimeUnit.S |
| } |
| case "ms": { |
| result.unit = TimeUnit.MS |
| } |
| case "us": { |
| result.unit = TimeUnit.US |
| } |
| case "ns": { |
| result.unit = TimeUnit.NS |
| } |
| case "ps": { |
| result.unit = TimeUnit.PS |
| } |
| } |
| return result; |
| } |
| |
| |
| } |