blob: fcaf471e3245962b123e13f9684226ededb25311 [file] [log] [blame]
Zakir Meer9f251f52018-06-17 16:21:31 +02001package templates
2
3import com.inchron.realtime.root.model.CallSequenceItem
4import com.inchron.realtime.root.model.GenericSystem
5import com.inchron.realtime.root.model.SemaphoreAccessType
6import com.inchron.realtime.root.model.TimeDistributionType
7import com.inchron.realtime.root.model.TimeUnit
8import java.util.ArrayList
9import java.util.List
10import java.util.Set
11import org.eclipse.app4mc.amalthea.model.Amalthea
12import org.eclipse.app4mc.amalthea.model.AsynchronousServerCall
13import org.eclipse.app4mc.amalthea.model.CallGraph
14import org.eclipse.app4mc.amalthea.model.CallSequence
15import org.eclipse.app4mc.amalthea.model.ChannelReceive
16import org.eclipse.app4mc.amalthea.model.ChannelSend
17import org.eclipse.app4mc.amalthea.model.CustomEventTrigger
18import org.eclipse.app4mc.amalthea.model.ExecutionNeed
19import org.eclipse.app4mc.amalthea.model.Group
20import org.eclipse.app4mc.amalthea.model.HwFeature
21import org.eclipse.app4mc.amalthea.model.ISR
22import org.eclipse.app4mc.amalthea.model.InterProcessTrigger
23import org.eclipse.app4mc.amalthea.model.LabelAccess
24import org.eclipse.app4mc.amalthea.model.ModeLabelAccess
25import org.eclipse.app4mc.amalthea.model.ModeSwitch
26import org.eclipse.app4mc.amalthea.model.Need
27import org.eclipse.app4mc.amalthea.model.NeedConstant
28import org.eclipse.app4mc.amalthea.model.NeedDeviation
29import org.eclipse.app4mc.amalthea.model.Preemption
30import org.eclipse.app4mc.amalthea.model.ProbabilitySwitch
31import org.eclipse.app4mc.amalthea.model.Process
32import org.eclipse.app4mc.amalthea.model.ProcessingUnit
33import org.eclipse.app4mc.amalthea.model.Runnable
34import org.eclipse.app4mc.amalthea.model.RunnableCall
35import org.eclipse.app4mc.amalthea.model.RunnableModeSwitch
36import org.eclipse.app4mc.amalthea.model.RunnableProbabilitySwitch
37import org.eclipse.app4mc.amalthea.model.SemaphoreAccess
38import org.eclipse.app4mc.amalthea.model.SemaphoreAccessEnum
39import org.eclipse.app4mc.amalthea.model.SenderReceiverRead
40import org.eclipse.app4mc.amalthea.model.SenderReceiverWrite
41import org.eclipse.app4mc.amalthea.model.SynchronousServerCall
42import org.eclipse.app4mc.amalthea.model.Task
43import org.eclipse.app4mc.amalthea.model.TaskRunnableCall
44import org.eclipse.app4mc.amalthea.model.Time
45import org.eclipse.app4mc.amalthea.model.util.DeploymentUtil
46import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil
47import org.eclipse.app4mc.amalthea.model.util.RuntimeUtil.TimeType
48import org.eclipse.emf.common.util.EMap
49import org.eclipse.emf.ecore.util.EcoreUtil
50import templates.utils.AmltCacheModel
51
52/**
53 * This class is responsible to convert Amalthea SW Model eleemnts to corresponding Inchron elements and invoke other transformation classes
54 */
55public class SWTransformer extends AbstractAmaltheaInchronTransformer {
56
57 /**
58 * Creating a Inchron Process element from Amalthea ISR element
59 */
60 def create inchronModelFactory.createProcess createProcess(ISR amltISR){
61 it.isr = true
62 it.name=amltISR.name
63 /*-Building a cache of Stimuli name and the "List of Process" elements to which it is associated to */
64 val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel)
65 amltISR.stimuli.forEach[stimuli |
66 amltCache.cacheAmltStimuliInchronProcessMap(stimuli.getName, it)
67 ]
68
69 }
70
71
72 /**
73 * Creating a Inchron Process element from Amalthea Task element
74 */
75 def create inchronModelFactory.createProcess createProcess(Task amltTask){
76 it.isr = false
77 it.name=amltTask.name
78
79 //TODO: schedule between runnables for co-operative
80 if(amltTask.preemption == Preemption.NON_PREEMPTIVE || amltTask.preemption == Preemption.COOPERATIVE){
81 it.preemptable=false
82 }else{
83 it.preemptable=true
84 }
85
86 if(amltTask.callGraph !=null){
87 /*-building a inchron CallGraph element from amalthea CallGraph */
88 it.callGraph=createCallGraph(amltTask.callGraph)
89 }
90
91 /*-Building a cache of Stimuli name and the "List of Process" elements to which it is associated to */
92 val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel)
93 amltTask.stimuli.forEach[stimuli |
94 amltCache.cacheAmltStimuliInchronProcessMap(stimuli.getName, it)
95 ]
96
97 }
98
99 /**
100 * This method is used to create a Inchron CallGraph element from Amalthea CallGraph element
101 */
102 def create inchronModelFactory.createCallGraph createCallGraph(CallGraph amltCallGraph){
103
104 amltCallGraph.graphEntries.forEach[amltGraphEntry|
105
106 if(amltGraphEntry instanceof CallSequence){
107
108 it.graphEntries.add(createCallSequence(amltGraphEntry as CallSequence))
109
110 }else if(amltGraphEntry instanceof ModeSwitch){
111 it.graphEntries.add(createModeSwitch(amltGraphEntry as ModeSwitch))
112
113 }else if(amltGraphEntry instanceof ProbabilitySwitch){
114 it.graphEntries.add(createProbabilitySwitch(amltGraphEntry as ProbabilitySwitch))
115
116 }
117 ]
118
119 }
120
121 /**
122 * This method is used to create inchron CallSequence object from Amalthea CallSequence element.
123 *
124 * Below are the CallSequence items are currently supported:
125 * <br>1.TaskRunnableCall
126 * <br>2.InterProcessTrigger
127 *
128 */
129 def create inchronModelFactory.createCallSequence createCallSequence(CallSequence amltCallSequence){
130 it.name=amltCallSequence.name
131 amltCallSequence?.calls.forEach[amltCallsequenceItem|
132
133 //todo: handle other CallSequenceItem's
134
135 if(amltCallsequenceItem instanceof TaskRunnableCall){
136
137 it.calls.add(createFunctionCall(amltCallsequenceItem as TaskRunnableCall))
138 }
139
140 if (amltCallsequenceItem instanceof InterProcessTrigger) {
141 it.calls.add(createActivationItem(amltCallsequenceItem as InterProcessTrigger))
142 }
143 ]
144 }
145
146 /**
147 * This method is used to create inchron InterProcessTrigger element from Amalthea ActivationItem element
148 */
149 def create inchronModelFactory.createActivationItem createActivationItem(InterProcessTrigger trigger) {
150
151 val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel)
152
153 val tasks = amltCache.interProcessTriggerRelationsMap.get(trigger.stimulus.name);
154
155 val inchronConnection=amltCache.inchronConnectionElementsMap.get(trigger.stimulus.name)
156
157 it.connection =inchronConnection
158
159 if(tasks !=null){
160 for ( task : tasks) {
161 val inchronActivateProcess=createActivateProcess(trigger, task as Task)
162 inchronConnection.activations.add(inchronActivateProcess)
163 }
164
165 }else{
166 //Note: This is the case where Stimulus is not InterProcessStimulus or there are no Process elements to which this stimulus is triggering
167 }
168
169 }
170
171 /**
172 * This method is used to create inchron ActivateProcess element from Amalthea InterProcessTrigger
173 */
174 def create inchronModelFactory.createActivateProcess createActivateProcess(InterProcessTrigger trigger, Task amltTask) {
175
176 it.target = createProcess(amltTask);
177 it.offset = trigger.counter.offset as int
178 it.period = trigger.counter.prescaler as int
179 }
180
181
182 def create inchronModelFactory.createModeSwitch createModeSwitch(ModeSwitch amltModeSwitch){
183 //TODO: need to enhance it in near future
184 }
185
186 def create inchronModelFactory.createProbabilitySwitch createProbabilitySwitch(ProbabilitySwitch amltProbabilitySwitch){
187 //TODO: need to enhance it in near future
188 }
189
190 /**
191 * This method is used to create inchron FunctionCall element from RunnableCall element
192 */
193 def create inchronModelFactory.createFunctionCall createFunctionCall(RunnableCall amltRunnableCall){
194
195 var amltProcess=amltRunnableCall.getParentContainer(Process)
196
197 var inchronComponent=createComponent(amltProcess)
198
199
200 val inchronGenericSystem= getInchronGenericSystem(amltProcess)
201
202 if(inchronGenericSystem !=null){
203 inchronGenericSystem.components.add(inchronComponent)
204
205 }
206
207 var inchronFunction=createFunction(amltProcess, amltRunnableCall.runnable)
208
209 inchronComponent.functions.add(inchronFunction)
210
211 it.function=inchronFunction
212 }
213
214
215 /**
216 * This method is used to create inchron FunctionCall element from TaskRunnableCall element
217 */
218 def create inchronModelFactory.createFunctionCall createFunctionCall(TaskRunnableCall amltTaskRunnableCall){
219
220 var amltProcess=amltTaskRunnableCall.getParentContainer(Process)
221
222 var inchronComponent=createComponent(amltProcess)
223
224 val inchronGenericSystem= getInchronGenericSystem(amltProcess)
225
226 if(inchronGenericSystem !=null){
227 inchronGenericSystem.components.add(inchronComponent)
228
229 }
230
231 var inchronFunction=createFunction(amltProcess, amltTaskRunnableCall.runnable)
232
233 it.function=inchronFunction
234
235 inchronComponent.functions.add(inchronFunction)
236
237 it.offset=amltTaskRunnableCall?.counter?.offset.intValue
238
239 it.period=amltTaskRunnableCall?.counter?.prescaler.intValue
240 }
241
242 /**
243 * This method is used to fetch the inchron GenericSystem object for a specific Amalthea Process element
244 */
245 def GenericSystem getInchronGenericSystem(Process amltProcess) {
246
247 val Set<ProcessingUnit> cores=DeploymentUtil.getAssignedCoreForProcess(amltProcess as Process, EcoreUtil.getRootContainer(amltProcess) as Amalthea)
248
249 val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel)
250
251 //TODO: write validaiton to assure that only 1 core is present
252
253 //TODO: currently taking 1st core
254
255 if(cores.size>0){
256 //TODO: clarify if this approach is OK !!
257 val amltCore=cores.get(0)
258
259 val amltMicroController=amltCore.eContainer
260
261 val inchronGenericSystem=amltCache.mappingAmltMicroController_GenericSystem.get(amltMicroController)
262
263 return inchronGenericSystem
264 }
265 }
266
267
268 def create inchronModelFactory.createComponent createComponent(Process amltProcess){
269
270 it.name=amltProcess.name
271 }
272
273 def create inchronModelFactory.createFunction createFunction(Process amltProcess, Runnable amltRunnable){
274
275 it.name=amltRunnable.name
276
277 it.callGraph=inchronModelFactory.createCallGraph
278
279 val inchronCallSequence=inchronModelFactory.createCallSequence
280
281 it.callGraph.graphEntries.add(inchronCallSequence)
282
283 amltRunnable?.runnableItems.forEach[amltRunnableItem|
284
285 if(amltRunnableItem instanceof AsynchronousServerCall){
286
287 }
288 else if(amltRunnableItem instanceof ChannelReceive){
289
290 }
291 else if(amltRunnableItem instanceof ChannelSend){
292
293 }
294 else if(amltRunnableItem instanceof CustomEventTrigger){
295
296 }
297 else if(amltRunnableItem instanceof Group){
298
299 }
300 else if(amltRunnableItem instanceof LabelAccess){
301
302 }
303 else if(amltRunnableItem instanceof ModeLabelAccess){
304
305 }
306 else if(amltRunnableItem instanceof RunnableCall){
307
308 inchronCallSequence.calls.add(createFunctionCall( amltRunnableItem))
309
310
311 }else if(amltRunnableItem instanceof ExecutionNeed){//Earlier it was RunnableInstructions
312
313 inchronCallSequence.calls.add(createResourceConsumption(amltProcess, amltRunnableItem))
314 }
315 else if(amltRunnableItem instanceof RunnableModeSwitch){
316
317 }
318 else if(amltRunnableItem instanceof RunnableProbabilitySwitch){
319
320 }
321 else if(amltRunnableItem instanceof SemaphoreAccess){
322 inchronCallSequence.calls.addAll(semaphoreInterruptCreation(amltRunnableItem))
323 }
324
325 else if(amltRunnableItem instanceof SenderReceiverRead){
326
327 }
328 else if(amltRunnableItem instanceof SenderReceiverWrite){
329
330 }
331 else if(amltRunnableItem instanceof SynchronousServerCall){
332
333 }
334 ]
335 }
336
337 def create inchronModelFactory.createSemaphoreAccess createSemaphoreAccess(SemaphoreAccess amltAccess) {
338
339 val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel)
340
341 val amltSemaphoreName=amltAccess?.semaphore?.name
342
343 //TODO CREATE THIS THE RIGHT WAY!
344 var inchronSemaphore = amltCache.getInchronSemaphoreCacheElement(amltSemaphoreName)// = createSemaphore(amltSemaphore);
345 //SemaphoreAccessType.;
346 //amltAccess.access;
347
348 switch (amltAccess.access) {
349 case SemaphoreAccessEnum.RELEASE: {
350 it.type = SemaphoreAccessType.RELEASE
351 }
352 case SemaphoreAccessEnum.EXCLUSIVE: {
353 it.type = SemaphoreAccessType.EXCLUSIVE
354 }
355 case SemaphoreAccessEnum.REQUEST : {
356 it.type = SemaphoreAccessType.REQUEST
357 }
358 }
359 it.semaphore = inchronSemaphore;
360
361
362 }
363
364 def List<CallSequenceItem> semaphoreInterruptCreation(SemaphoreAccess amltAccess){
365
366 val List<CallSequenceItem> items=new ArrayList
367
368 switch (amltAccess.access) {
369
370 case SemaphoreAccessEnum.RELEASE: {
371
372 items.add(createSemaphoreAccess(amltAccess))
373
374 items.add(createResumeAllInterrupts(amltAccess))
375
376 }
377 case SemaphoreAccessEnum.EXCLUSIVE: {
378 //TODO:check semantics
379 items.add(createSuspendAllInterrupts(amltAccess))
380 items.add(createSemaphoreAccess(amltAccess))
381
382 }
383 case SemaphoreAccessEnum.REQUEST : {
384
385 items.add(createSuspendAllInterrupts(amltAccess))
386 items.add(createSemaphoreAccess(amltAccess))
387
388
389 }
390 }
391 return items
392 }
393
394 /*
395 * LL: SemaphoreAccess object should be mandatorily supplied here, as Xtend caches the elements based on input parameters
396 */
397 def create inchronModelFactory.createSuspendAllInterrupts createSuspendAllInterrupts(SemaphoreAccess amltAccess) {
398 it.offset=0
399 it.period=0
400 }
401
402 /*
403 * LL: SemaphoreAccess object should be mandatorily supplied here, as Xtend caches the elements based on input parameters
404 */
405 def create inchronModelFactory.createResumeAllInterrupts createResumeAllInterrupts(SemaphoreAccess amltAccess) {
406 it.offset=0
407 it.period=0
408 }
409
410
411 def create inchronModelFactory.createResourceConsumption createResourceConsumption(Process amltProcess, ExecutionNeed amltRunnableInstructions){
412 val AmltCacheModel amltCache=customObjsStore.getInstance(AmltCacheModel)
413
414
415 if(amltProcess instanceof Task){
416
417
418 var listOfTaskAllocations=amltCache.tasks_TaskAllocationMap.get(amltProcess as Task)
419
420 listOfTaskAllocations?.forEach[amltTaskAllocation|
421 var amltScheduler=amltTaskAllocation.scheduler
422
423 var amltSchedulerAllocation=amltCache.taskScheduler_schedulerAllocationMap.get(amltScheduler)
424
425 //TODO: What if affinity is not set and core should be derived from SchedulerMapping?
426 var List cores1=amltTaskAllocation.affinity
427
428 var List cores2 =(amltSchedulerAllocation.responsibility)
429
430 //to obtain only common Core objects across both lists
431 cores1.retainAll(cores2)
432
433 //TODO: write assumptions about core mapping of tasks (if it is 1 to 1 mapping ?)
434
435 if(cores1.size==1){
436 var timeDistribution=inchronModelFactory.createTimeDistribution
437 //TODO: uniform as a starting point --- more complex distributions need to be simulated
438 timeDistribution.type = TimeDistributionType.UNIFORM
439 timeDistribution.bcet = getRuntimeForRunnableInstruction(amltRunnableInstructions, TimeType.BCET, cores1.get(0) as ProcessingUnit);
440 timeDistribution.wcet = getRuntimeForRunnableInstruction(amltRunnableInstructions, TimeType.WCET, cores1.get(0) as ProcessingUnit);
441 timeDistribution.mean = getRuntimeForRunnableInstruction(amltRunnableInstructions, TimeType.ACET, cores1.get(0) as ProcessingUnit);
442 it.timeDistribution = timeDistribution
443
444 }
445 ]
446 }
447 }
448
449
450
451 //TODO: Check if some of this methods can be part of AMALTHEA
452 //TODO: set getInstructionCountForInstruction to public in APP4MC UTILS
453 def com.inchron.realtime.root.model.Time getRuntimeForRunnableInstruction(ExecutionNeed amltRunnableInstructions, TimeType timeType, ProcessingUnit core) {
454 //TODO: handle extended instructions
455 var amltInstructions = getInstructionCountForInstruction(amltRunnableInstructions.^default, timeType);
456 val hwFeatureFromExecutionNeed = getHwFeatureFromExecutionNeed(amltRunnableInstructions,core)
457 var amltTime = RuntimeUtil.getExecutionTimeForExecutionNeedValueCount(amltInstructions, core, hwFeatureFromExecutionNeed,null);
458 return getInchronTimeValue(amltTime);
459
460 }
461
462 def HwFeature getHwFeatureFromExecutionNeed(ExecutionNeed executionNeed, ProcessingUnit processingUnit){
463
464 val EMap<String, Need> defaultMap = executionNeed.^default
465
466 if(defaultMap.size>0){
467 val processingUnitDefinition = processingUnit.definition
468 if(processingUnitDefinition!=null){
469 for(feature: processingUnitDefinition?.features){
470 //TODO:At present supporting only HwFeatureCategory with name "Instructions"
471 if(feature.containingCategory?.name.equals("Instructions")){
472 return feature
473 }
474 }
475 }
476 }
477
478 return null
479 }
480
481 def Long getInstructionCountForInstruction(EMap<String, Need> defaultMap, TimeType execTimeType) {
482
483
484 for(need: defaultMap.values){
485 if(need instanceof NeedDeviation) {
486 var NeedDeviation instDeviation = need as NeedDeviation ;
487 switch(execTimeType) {
488 case ACET: {
489 return RuntimeUtil.getMean(instDeviation.getDeviation().getDistribution(), instDeviation.getDeviation().getLowerBound().getValue(), instDeviation.getDeviation().getUpperBound().getValue())
490 }
491 case BCET: {
492 return instDeviation.getDeviation().getLowerBound().getValue()
493 }
494 case WCET: {
495 return instDeviation.getDeviation().getUpperBound().getValue();
496 }
497 default:
498 return RuntimeUtil.getMean(instDeviation.getDeviation().getDistribution(), instDeviation.getDeviation().getLowerBound().getValue(), instDeviation.getDeviation().getUpperBound().getValue())
499
500
501 }
502 } else if(need instanceof NeedConstant) {
503 return (need as NeedConstant).getValue();
504 }
505
506 }
507
508
509 return 0L;
510 }
511
512 def com.inchron.realtime.root.model.Time getInchronTimeValue(Time amltTime) {
513 var result = inchronModelFactory.createTime
514
515 result.value = amltTime.value.longValue;
516 switch (amltTime.unit.getName) {
517 case "s": {
518 result.unit = TimeUnit.S
519 }
520 case "ms": {
521 result.unit = TimeUnit.MS
522 }
523 case "us": {
524 result.unit = TimeUnit.US
525 }
526 case "ns": {
527 result.unit = TimeUnit.NS
528 }
529 case "ps": {
530 result.unit = TimeUnit.PS
531 }
532 }
533 return result;
534 }
535
536
537}