added transformer Channels --> data flow connections
added transformer EventChains --> DataFlow, see prerequisites in documentation
added DataFlowUtils
updated event chain test model
updated test model folder structure
Signed-off-by: Sebastian Reiser <Sebastian.Reiser@de.bosch.com>
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/ModelTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/ModelTransformer.xtend
index 32e97d5..92c8f42 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/ModelTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/ModelTransformer.xtend
@@ -16,6 +16,7 @@
import templates.m2m.stimuli.StimuliTransformer
import templates.m2m.sw.SWTransformer
import com.google.inject.Singleton
+import templates.m2m.constraints.ConstraintsTransformer
@Singleton
class ModelTransformer extends AbstractAmaltheaInchronTransformer{
@@ -30,6 +31,9 @@
@Inject extension SWTransformer swTransformer
+ @Inject extension ConstraintsTransformer constraintsTransformer
+
+
/**
* This method creates the object of INCHRON Model element, and fills it by invoking various transformations
@@ -51,6 +55,8 @@
stimuliTransformer.transformStimuliModel(amalthea.stimuliModel, it)
swTransformer.transformSWModel(amalthea.swModel, it)
+
+ constraintsTransformer.transformConstraintsModel
}
/**
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/ConstraintsTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/ConstraintsTransformer.xtend
new file mode 100644
index 0000000..7d3c1e3
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/ConstraintsTransformer.xtend
@@ -0,0 +1,35 @@
+/**
+ * *******************************************************************************
+ * Copyright (c) 2019 Robert Bosch GmbH and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Robert Bosch GmbH - initial API and implementation
+ * *******************************************************************************
+ */
+
+package templates.m2m.constraints
+
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import templates.AbstractAmaltheaInchronTransformer
+import templates.m2m.constraints.EventChainTransformer
+import org.eclipse.app4mc.amalthea.model.EventChain
+
+@Singleton
+class ConstraintsTransformer extends AbstractAmaltheaInchronTransformer {
+
+ @Inject EventChainTransformer eventChainTransformer
+
+ def transformConstraintsModel() {
+ getAmaltheaRoot()?.constraintsModel?.eventChains?.forEach(EventChain eventChain | {
+ eventChainTransformer.createDataFlow(eventChain);
+ })
+ }
+
+}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/EventChainReferenceTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/EventChainReferenceTransformer.xtend
new file mode 100644
index 0000000..f5fd590
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/EventChainReferenceTransformer.xtend
@@ -0,0 +1,108 @@
+/**
+ * *******************************************************************************
+ * Copyright (c) 2019 Robert Bosch GmbH and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Robert Bosch GmbH - initial API and implementation
+ * *******************************************************************************
+ */
+
+package templates.m2m.constraints
+
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import com.inchron.realtime.root.model.DataFlowEdge
+import com.inchron.realtime.root.model.VariableAccess
+import java.util.List
+import org.eclipse.app4mc.amalthea.model.AbstractEventChain
+import org.eclipse.app4mc.amalthea.model.ChannelAccess
+import org.eclipse.app4mc.amalthea.model.ChannelEvent
+import org.eclipse.app4mc.amalthea.model.EventChainReference
+import templates.AbstractAmaltheaInchronTransformer
+import templates.m2m.sw.runnableItem.ChannelAccessTransformer
+import templates.m2m.utils.DataFlowUtils
+
+@Singleton
+class EventChainReferenceTransformer extends AbstractAmaltheaInchronTransformer {
+
+ @Inject EventChainTransformer eventChainTransformer
+ @Inject ChannelAccessTransformer channelAccessTransformer
+
+
+ def create inchronModelFactory.createDataFlowReference createDataFlowReference(EventChainReference amltEventEventChainReference,
+ AbstractEventChain amltAbstractEventChain) {
+
+ it.dataFlow = eventChainTransformer.createDataFlow(amltEventEventChainReference.eventChain)
+
+ // assume entire event chain is referenced
+ it.stimulus = getInitialStimulus(it.dataFlow.edges).stimulus
+ it.response = getUltimateResponse(it.dataFlow.edges).response
+
+
+ //check if a only a portion of the data floW is selected in parent Amalthea event chain
+ val ChannelAccess amltCutoffStimulus = DataFlowUtils.findChannelAccess(amltAbstractEventChain.stimulus)
+ val ChannelAccess amltCutoffResponse = DataFlowUtils.findChannelAccess(amltAbstractEventChain.response)
+
+ val VariableAccess csCutoffStimulus = channelAccessTransformer.createVariableAccess((amltAbstractEventChain.stimulus as ChannelEvent).process, amltCutoffStimulus)
+ val VariableAccess csCutoffResponse = channelAccessTransformer.createVariableAccess((amltAbstractEventChain.response as ChannelEvent).process, amltCutoffResponse)
+
+ for(DataFlowEdge dataFlowEdge : dataFlow.edges){
+ if (dataFlowEdge.stimulus === csCutoffStimulus){
+ it.stimulus = csCutoffStimulus
+ }
+ if (dataFlowEdge.response === csCutoffResponse){
+ it.response = csCutoffResponse
+ }
+ }
+
+ }
+
+
+ private def DataFlowEdge getInitialStimulus(List<DataFlowEdge> list) {
+ for(DataFlowEdge item : list){
+ if (isInitial(item, list)){
+ return item
+ }
+ }
+ return null
+ }
+
+ private def Boolean isInitial(DataFlowEdge item, List<DataFlowEdge> list){
+ for (DataFlowEdge listItem : list){
+ if(item.stimulus === listItem.response){
+ //check item's stimulus is another item's response --> checked item has predecessor --> not start of event chain
+ return false
+ }
+ }
+ return true
+ }
+
+ private def DataFlowEdge getUltimateResponse(List<DataFlowEdge> list) {
+ for(DataFlowEdge item : list){
+ if (isUltimate(item, list)){
+ return item
+ }
+ }
+ return null
+ }
+
+ private def Boolean isUltimate(DataFlowEdge item, List<DataFlowEdge> list){
+ for (DataFlowEdge listItem : list){
+ if(item.response === listItem.stimulus){
+ // item's response is list item's stimulus --> checked item has successor --> not end of event chain
+ return false
+ }
+ }
+ return true
+ }
+
+}
+
+
+
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/EventChainTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/EventChainTransformer.xtend
new file mode 100644
index 0000000..11fdbab
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/constraints/EventChainTransformer.xtend
@@ -0,0 +1,101 @@
+/**
+ * *******************************************************************************
+ * Copyright (c) 2019 Robert Bosch GmbH and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Robert Bosch GmbH - initial API and implementation
+ * *******************************************************************************
+ */
+
+package templates.m2m.constraints
+
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import com.inchron.realtime.root.model.DataFlow
+import com.inchron.realtime.root.model.DataFlowEdge
+import org.eclipse.app4mc.amalthea.model.AbstractEventChain
+import org.eclipse.app4mc.amalthea.model.ChannelAccess
+import org.eclipse.app4mc.amalthea.model.ChannelEvent
+import org.eclipse.app4mc.amalthea.model.EventChain
+import org.eclipse.app4mc.amalthea.model.EventChainContainer
+import org.eclipse.app4mc.amalthea.model.EventChainItem
+import org.eclipse.app4mc.amalthea.model.EventChainReference
+import org.eclipse.app4mc.amalthea.model.Process
+import templates.AbstractAmaltheaInchronTransformer
+import templates.m2m.sw.runnableItem.ChannelAccessTransformer
+import templates.m2m.utils.DataFlowUtils
+
+@Singleton
+class EventChainTransformer extends AbstractAmaltheaInchronTransformer {
+
+ @Inject EventChainReferenceTransformer eventChainReferenceTransformer
+ @Inject ChannelAccessTransformer channelAccessTransformer
+
+ def create inchronModelFactory.createDataFlow createDataFlow(EventChain amltEventChain) {
+
+ //check if amalthea structure is feasible to be transformed to data flow
+ //list of checks:
+ // - no circular dependencies within nested event chain references
+ // - channel event specifies: runnable, channel, access type (send or receive)
+ // - stimulus and response are of type channel event
+ // - stimulus and responsecan be traced to ONE specific channel access runnable item
+ // - rules above also apply to nested and referenced event chains
+ // Note: strands are not supported and will be neglected
+ if (DataFlowUtils.isDataFlow(amltEventChain)){
+ it.name = amltEventChain.name
+ extendDataFlow(it, amltEventChain)
+ getInchronRoot.eventChains.add(it)
+ } else {
+ //do event sequence sequence
+ getLogger.error("Event chain " + amltEventChain.name + " cannot be converted, as it is not a feasible data flow")
+ }
+ }
+
+ def void extendDataFlow(DataFlow dataFlow, AbstractEventChain amltAbstractEventChain) {
+ if (!amltAbstractEventChain.segments.isEmpty) {
+ //event chain is hierarchical --> step down
+ amltAbstractEventChain.segments.forEach[EventChainItem amltEventChainItem | { //item may be a container or a reference
+ if (amltEventChainItem instanceof EventChainContainer){
+ //recursively process contained (sub)event chain
+ extendDataFlow(dataFlow, (amltEventChainItem as EventChainContainer).eventChain)
+ } else if (amltEventChainItem instanceof EventChainReference) {
+ //create [cs]DataFlowReference from [amlt]EventChainReference
+
+ dataFlow.references.add(eventChainReferenceTransformer.createDataFlowReference(
+ (amltEventChainItem as EventChainReference), amltAbstractEventChain))
+ }
+ }]
+ }
+ else {
+ //create new edge
+ val DataFlowEdge dataFlowEdge = inchronModelFactory.createDataFlowEdge
+
+ //set stimulus and receiver according to channel events
+ val Process stimulusTask = (amltAbstractEventChain.stimulus as ChannelEvent).process
+ val ChannelAccess stimulus = DataFlowUtils.findChannelAccess(amltAbstractEventChain.stimulus as ChannelEvent)
+ if (stimulus !== null){
+ dataFlowEdge.stimulus = channelAccessTransformer.createVariableAccess(stimulusTask, stimulus)
+ } else {
+ dataFlowEdge.stimulus = null;
+ }
+
+ val Process responseTask = (amltAbstractEventChain.response as ChannelEvent).process
+ val ChannelAccess response = DataFlowUtils.findChannelAccess(amltAbstractEventChain.response as ChannelEvent)
+ if (response !== null){
+ dataFlowEdge.response = channelAccessTransformer.createVariableAccess(responseTask, response)
+ } else {
+ dataFlowEdge.response = null;
+ }
+
+ //add new edge dataflow
+ dataFlow.edges.add(dataFlowEdge)
+ }
+ }
+
+}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/stimuli/StimuliTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/stimuli/StimuliTransformer.xtend
index 6dff2d9..6a3175e 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/stimuli/StimuliTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/stimuli/StimuliTransformer.xtend
@@ -102,5 +102,6 @@
}
def create inchronModelFactory.createActivationConnection createActivationConnection(Stimulus amltStimulus) {
+ it.name = amltStimulus.name
}
}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/CallGraphTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/CallGraphTransformer.xtend
index f9aa9a1..02485c8 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/CallGraphTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/CallGraphTransformer.xtend
@@ -17,9 +17,7 @@
import com.google.inject.Inject
import com.google.inject.Singleton
-import com.inchron.realtime.root.model.GraphEntryBase
import com.inchron.realtime.root.model.ModeSwitch
-import com.inchron.realtime.root.model.util.ModelSwitch
import java.util.ArrayList
import java.util.Map
import org.eclipse.app4mc.amalthea.model.CallGraph
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/ModeSwitchTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/ModeSwitchTransformer.xtend
index 99b3565..39046d0 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/ModeSwitchTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/ModeSwitchTransformer.xtend
@@ -15,16 +15,15 @@
package templates.m2m.sw
import com.google.inject.Inject
+import com.google.inject.Singleton
import com.inchron.realtime.root.model.Component
+import com.inchron.realtime.root.model.FunctionCall
import java.util.Map
import org.eclipse.app4mc.amalthea.model.GraphEntryBase
import org.eclipse.app4mc.amalthea.model.ModeSwitch
import org.eclipse.app4mc.amalthea.model.Process
import org.eclipse.app4mc.amalthea.model.RunnableModeSwitch
import templates.utils.AmltCacheModel
-import com.inchron.realtime.root.model.FunctionCall
-import com.google.inject.Singleton
-import java.util.ArrayList
@Singleton
class ModeSwitchTransformer extends GraphEntryBaseTransformer {
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableItemTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableItemTransformer.xtend
index b088280..559d810 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableItemTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableItemTransformer.xtend
@@ -31,8 +31,7 @@
import org.eclipse.app4mc.amalthea.model.RunnableModeSwitch
import org.eclipse.app4mc.amalthea.model.Ticks
import templates.AbstractAmaltheaInchronTransformer
-import templates.m2m.sw.runnableItem.ChannelReceiveTransformer
-import templates.m2m.sw.runnableItem.ChannelSendTransformer
+import templates.m2m.sw.runnableItem.ChannelAccessTransformer
import templates.m2m.sw.runnableItem.RunnableCallTransformer
import templates.m2m.sw.runnableItem.TicksTransformer
@@ -43,9 +42,8 @@
@Inject TicksTransformer ticksTransformer
@Inject ModeSwitchTransformer modeSwitchTransformer
@Inject CustomEventTriggerTransformer customEventTriggerTransformer
- @Inject ModeLabelTransformer modeLabelTransformer
- @Inject ChannelReceiveTransformer channelReceiveTransformer
- @Inject ChannelSendTransformer channelSendTransformer
+ @Inject ModeLabelTransformer modeLabelTransformer
+ @Inject ChannelAccessTransformer channelAccessTransformer
def List<CallSequenceItem> transformRunnableItem(Component inchronComponent, Process amltTask,
RunnableItem amltRunnableItem) {
@@ -74,9 +72,9 @@
list.add(inchronModeSwitchPoint)
}
} else if (amltRunnableItem instanceof ChannelReceive) {
- list.add(channelReceiveTransformer.createVariableReadAccess(amltRunnableItem as ChannelReceive))
+ list.add(channelAccessTransformer.createVariableAccess(amltTask, amltRunnableItem as ChannelReceive))
} else if (amltRunnableItem instanceof ChannelSend) {
- list.add(channelSendTransformer.createVariableWriteAccess(amltRunnableItem as ChannelSend))
+ list.add(channelAccessTransformer.createVariableAccess(amltTask, amltRunnableItem as ChannelSend))
}
return list
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableTransformer.xtend
index 655ddc6..5826a0f 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/RunnableTransformer.xtend
@@ -37,7 +37,7 @@
inchronComponent.functions.add(it)
- it.name = amltRunnable.name
+ it.name = amltTask.name + "-" + amltRunnable.name
val inchronCallGraph = inchronModelFactory.createCallGraph
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelAccessTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelAccessTransformer.xtend
new file mode 100644
index 0000000..21ba008
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelAccessTransformer.xtend
@@ -0,0 +1,120 @@
+/**
+ * *******************************************************************************
+ * Copyright (c) 2019 Robert Bosch GmbH and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Robert Bosch GmbH - initial API and implementation
+ * *******************************************************************************
+ */
+
+package templates.m2m.sw.runnableItem
+
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import com.inchron.realtime.root.model.DataFlowConnection
+import com.inchron.realtime.root.model.VariableReadAccessPolicy
+import com.inchron.realtime.root.model.VariableReadAccessType
+import com.inchron.realtime.root.model.VariableWriteAccessType
+import com.inchron.realtime.root.model.memory.DataAccessType
+import org.eclipse.app4mc.amalthea.model.ChannelReceive
+import org.eclipse.app4mc.amalthea.model.ChannelSend
+import org.eclipse.app4mc.amalthea.model.Process
+import org.eclipse.app4mc.amalthea.model.ReceiveOperation
+import templates.AbstractAmaltheaInchronTransformer
+import templates.m2m.sw.ChannelTransformer
+
+@Singleton
+class ChannelAccessTransformer extends AbstractAmaltheaInchronTransformer {
+
+ @Inject ChannelTransformer channelTransformer
+ @Inject TransmissionPolicyTransformer transmissionPolicyTransformer
+
+ private static Integer enumeratorRead = 0;
+ private static Integer enumeratorSend = 0
+
+ def dispatch create inchronModelFactory.createVariableReadAccess createVariableAccess(Process amltTask, ChannelReceive amltChannelReceive) {
+ //create/get dataflow
+ it.connection = channelTransformer.createDataFlowConnection(amltChannelReceive.data)
+ //set attributes
+ val name = amltTask.name + "_receive_" + it.connection.name + "_" + enumeratorRead
+ it.dataMustBeNew = amltChannelReceive.dataMustBeNew
+ it.index = amltChannelReceive.elementIndex
+ it.isBuffered = true
+ it.name = name
+ it.label = name
+ it.lowerBound = amltChannelReceive.lowerBound
+ it.number = amltChannelReceive.elements
+
+ //set data access policy
+ if (amltChannelReceive.transmissionPolicy !== null){
+ it.dataAccess = transmissionPolicyTransformer.createExplicitDataAccess(amltTask, amltChannelReceive.transmissionPolicy)
+ } else {
+ it.dataAccess = inchronMemoryFactory.createExplicitDataAccess
+ }
+ it.dataAccess.accessType = DataAccessType.READ;
+
+
+ //assign operation type: FIFO, LIFO, TAKE, READ
+ if (amltChannelReceive.receiveOperation === ReceiveOperation.FIFO_READ) {
+ it.isTake = false;
+ it.policy = VariableReadAccessPolicy.FIFO
+ }
+ else if (amltChannelReceive.receiveOperation === ReceiveOperation.FIFO_TAKE) {
+ it.isTake = true;
+ it.policy = VariableReadAccessPolicy.LIFO
+ }
+ else if (amltChannelReceive.receiveOperation === ReceiveOperation.LIFO_READ) {
+ it.isTake = false;
+ it.policy = VariableReadAccessPolicy.FIFO
+ }
+ else if (amltChannelReceive.receiveOperation === ReceiveOperation.LIFO_TAKE) {
+ it.isTake = true;
+ it.policy = VariableReadAccessPolicy.LIFO
+ }
+
+ //assign type
+ it.type = VariableReadAccessType.GENERIC
+
+ //add read access to dataflow connection's receiver list
+ it.connection.requesters.add(it)
+
+ enumeratorRead = enumeratorRead + 1
+ }
+
+
+ def dispatch create inchronModelFactory.createVariableWriteAccess createVariableAccess(Process amltTask, ChannelSend amltChannelSend) {
+ //create/get dataflow
+ val DataFlowConnection connectionTmp = channelTransformer.createDataFlowConnection(amltChannelSend.data)
+ //set attributes
+ val name = amltTask.name + "_send_" + connectionTmp.name + "_" + enumeratorSend
+ //issue an error if connection's provider is already set
+ if (connectionTmp.provider !== null){
+ logger.error("Transformation for Channel to Inchron DataFlowConnection supports only one writer per channel. Updating provider of data flow connection " + connectionTmp.name +
+ ", replacing " + connectionTmp.provider.name + " with " + name)
+ }
+ it.connection = connectionTmp
+ it.name = name
+ it.label = name
+ it.isBuffered = true
+ it.number = amltChannelSend.elements
+
+ //set data access policy
+ if (amltChannelSend.transmissionPolicy !== null){
+ it.dataAccess = transmissionPolicyTransformer.createExplicitDataAccess(amltTask, amltChannelSend.transmissionPolicy)
+ } else {
+ it.dataAccess = inchronMemoryFactory.createExplicitDataAccess
+ }
+ it.dataAccess.accessType = DataAccessType.WRITE;
+
+ //assign type
+ it.type = VariableWriteAccessType.GENERIC
+
+ enumeratorSend = enumeratorSend + 1
+ }
+}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelReceiveTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelReceiveTransformer.xtend
deleted file mode 100644
index 1e6155e..0000000
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelReceiveTransformer.xtend
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * *******************************************************************************
- * Copyright (c) 2019 Robert Bosch GmbH and others.
- *
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Robert Bosch GmbH - initial API and implementation
- * *******************************************************************************
- */
-
-package templates.m2m.sw.runnableItem
-
-import com.google.inject.Inject
-import com.google.inject.Singleton
-import com.inchron.realtime.root.model.VariableReadAccessPolicy
-import com.inchron.realtime.root.model.VariableReadAccessType
-import com.inchron.realtime.root.model.memory.DataAccessType
-import org.eclipse.app4mc.amalthea.model.ChannelReceive
-import org.eclipse.app4mc.amalthea.model.ReceiveOperation
-import templates.AbstractAmaltheaInchronTransformer
-import templates.m2m.sw.ChannelTransformer
-
-@Singleton
-class ChannelReceiveTransformer extends AbstractAmaltheaInchronTransformer {
-
- @Inject ChannelTransformer channelTransformer
- @Inject TransmissionPolicyTransformer transmissionPolicyTransformer
-
- private static Integer enumerator = 0;
-
- def create inchronModelFactory.createVariableReadAccess createVariableReadAccess(ChannelReceive amltChannelReceive) {
- it.connection = channelTransformer.createDataFlowConnection(amltChannelReceive.data)
- it.dataMustBeNew = amltChannelReceive.dataMustBeNew
- it.index = amltChannelReceive.elementIndex
- it.isBuffered = true
- it.name = it.connection.name + "_" + enumerator
- it.label = it.connection.name + "_" + enumerator
- it.lowerBound = amltChannelReceive.lowerBound
- it.number = amltChannelReceive.elements
-
- //set data access policy
- if (amltChannelReceive.transmissionPolicy !== null){
- it.dataAccess = transmissionPolicyTransformer.createExplicitDataAccess(amltChannelReceive.transmissionPolicy)
- } else {
- it.dataAccess = inchronMemoryFactory.createExplicitDataAccess
- }
- it.dataAccess.accessType = DataAccessType.READ;
-
-
- //assign operation type: FIFO, LIFO, TAKE, READ
- if (amltChannelReceive.receiveOperation === ReceiveOperation.FIFO_READ) {
- it.isTake = false;
- it.policy = VariableReadAccessPolicy.FIFO
- }
- else if (amltChannelReceive.receiveOperation === ReceiveOperation.FIFO_TAKE) {
- it.isTake = true;
- it.policy = VariableReadAccessPolicy.LIFO
- }
- else if (amltChannelReceive.receiveOperation === ReceiveOperation.LIFO_READ) {
- it.isTake = false;
- it.policy = VariableReadAccessPolicy.FIFO
- }
- else if (amltChannelReceive.receiveOperation === ReceiveOperation.LIFO_TAKE) {
- it.isTake = true;
- it.policy = VariableReadAccessPolicy.LIFO
- }
-
- //assign type
- it.type = VariableReadAccessType.GENERIC
-
- //add read access to dataflow connection's receiver list
- it.connection.requesters.add(it)
-
- enumerator = enumerator + 1
- }
-
-
-}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelSendTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelSendTransformer.xtend
deleted file mode 100644
index 9303912..0000000
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/ChannelSendTransformer.xtend
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * *******************************************************************************
- * Copyright (c) 2019 Robert Bosch GmbH and others.
- *
- * This program and the accompanying materials are made
- * available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * Robert Bosch GmbH - initial API and implementation
- * *******************************************************************************
- */
-
-package templates.m2m.sw.runnableItem
-
-import com.google.inject.Inject
-import com.google.inject.Singleton
-import com.inchron.realtime.root.model.VariableWriteAccessType
-import com.inchron.realtime.root.model.memory.DataAccessType
-import org.eclipse.app4mc.amalthea.model.ChannelSend
-import templates.AbstractAmaltheaInchronTransformer
-import templates.m2m.sw.ChannelTransformer
-
-@Singleton
-class ChannelSendTransformer extends AbstractAmaltheaInchronTransformer {
-
- @Inject ChannelTransformer channelTransformer
- @Inject TransmissionPolicyTransformer transmissionPolicyTransformer
-
- private static Integer enumerator = 0
-
- def create inchronModelFactory.createVariableWriteAccess createVariableWriteAccess(ChannelSend amltChannelSend) {
- it.connection = channelTransformer.createDataFlowConnection(amltChannelSend.data)
- it.isBuffered = true
- it.number = amltChannelSend.elements
- it.name = it.connection.name + "_" + enumerator
- it.label = it.connection.name + "_" + enumerator
-
- //set data access policy
- if (amltChannelSend.transmissionPolicy !== null){
- it.dataAccess = transmissionPolicyTransformer.createExplicitDataAccess(amltChannelSend.transmissionPolicy)
- } else {
- it.dataAccess = inchronMemoryFactory.createExplicitDataAccess
- }
- it.dataAccess.accessType = DataAccessType.WRITE;
-
- //assign type
- it.type = VariableWriteAccessType.GENERIC
-
- //add read access to dataflow connection's receiver list
- if (it.connection.provider !== null){
- logger.error("Transformation for Channel to Inchron DataFlowConnection supports only one writer per channel")
- } else {
- it.connection.provider = it
- }
-
- enumerator = enumerator + 1
- }
-}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TicksTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TicksTransformer.xtend
index 05dfb27..360c9fb 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TicksTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TicksTransformer.xtend
@@ -15,7 +15,10 @@
package templates.m2m.sw.runnableItem
+import com.google.inject.Singleton
+import com.inchron.realtime.root.model.Time
import com.inchron.realtime.root.model.TimeDistributionType
+import com.inchron.realtime.root.model.TimeUnit
import org.eclipse.app4mc.amalthea.model.Amalthea
import org.eclipse.app4mc.amalthea.model.DiscreteValueBetaDistribution
import org.eclipse.app4mc.amalthea.model.DiscreteValueGaussDistribution
@@ -24,12 +27,8 @@
import org.eclipse.app4mc.amalthea.model.Process
import org.eclipse.app4mc.amalthea.model.Ticks
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.ecore.util.EcoreUtil
import templates.AbstractAmaltheaInchronTransformer
-import templates.m2m.utils.TimeTransformer
-import com.google.inject.Singleton
@Singleton
class TicksTransformer extends AbstractAmaltheaInchronTransformer {
@@ -37,7 +36,6 @@
def create inchronModelFactory.createResourceConsumption createResourceConsumption(Process amltTask,
Ticks amltTicks) {
it.name = "RC"
- //it.timeDistribution = createTimeDistribution(amltTask, amltTicks)
it.timeDistribution = createTicksDistribution(amltTask, amltTicks)
}
@@ -46,139 +44,64 @@
var amltCores = DeploymentUtil.getAssignedCoreForProcess(amltTask,
EcoreUtil.getRootContainer(amltTask) as Amalthea);
- if (amltCores.size > 0) {
- val amltCore = amltCores?.get(0)
- it.min = createTimeTicks( amltTicks?.^default.lowerBound)
- it.mean = createTimeTicks(amltTicks?.^default.average)
- it.max = createTimeTicks(amltTicks?.^default.upperBound)
- it.sigma = inchronModelFactory.createTime
- it.type = TimeDistributionType.MAX
- it.alpha = 0
- it.beta = 0
- var amltDistribution = amltTicks?.extended?.get(amltCore)
-
- if (amltDistribution === null) {
- amltDistribution = amltTicks.^default
- }
-
- if (amltDistribution instanceof DiscreteValueGaussDistribution) {
- it.type = TimeDistributionType.NORMAL
- it.sigma = createTimeTicks(amltDistribution.sd)
- } else if (amltDistribution instanceof DiscreteValueUniformDistribution) {
- it.type = TimeDistributionType.UNIFORM
- } else if (amltDistribution instanceof DiscreteValueBetaDistribution) {
- } else if (amltDistribution instanceof DiscreteValueHistogram) {
- it.type = TimeDistributionType.DISCRETE
- amltDistribution.entries.forEach [ amltEntry |
- val amltAvg = (amltEntry.upperBound + amltEntry.lowerBound) / 2;
- val amltOccurrences = amltEntry.occurrences
- var inchronDiscreteDistributionEntry = inchronModelFactory.createDiscreteDistributionEntry
- inchronDiscreteDistributionEntry.count = amltOccurrences
- inchronDiscreteDistributionEntry.execTime = createTimeTicks(amltAvg)
- it.discreteDistribution.add(inchronDiscreteDistributionEntry)
- ]
- }
+ //get distribution (extended if provided by the model element)
+ val amltCore = amltCores?.get(0)
+ var amltDistribution = amltTicks?.extended.get(amltCore?.definition)
+ if (amltDistribution === null) {
+ amltDistribution = amltTicks.^default
}
-
- }
-
-
- def create inchronModelFactory.createTime createTimeTicks(Double value) {
- it.value = Math.round(value)
- it.unit = com.inchron.realtime.root.model.TimeUnit.T
- }
-
-
- def create inchronModelFactory.createTime createTimeTicks(Long value) {
- it.value = value
- it.unit = com.inchron.realtime.root.model.TimeUnit.T
- }
-
-
- def create inchronModelFactory.createTime createTimeTicks(Integer value) {
- it.value = value
- it.unit = com.inchron.realtime.root.model.TimeUnit.T
- }
-
-
- def create inchronModelFactory.createTimeDistribution createTimeDistribution(Process amltTask, Ticks amltTicks) {
-
- val timeUtils = new TimeTransformer
-
- var amltCores = DeploymentUtil.getAssignedCoreForProcess(amltTask,
- EcoreUtil.getRootContainer(amltTask) as Amalthea);
-
- if (amltCores.size > 0) {
-
- val amltCore = amltCores?.get(0)
- it.min = timeUtils.createTime(RuntimeUtil.getExecutionTimeForTicks(amltTicks, amltCore, TimeType.BCET))
- it.mean = timeUtils.createTime(RuntimeUtil.getExecutionTimeForTicks(amltTicks, amltCore, TimeType.ACET))
- it.max = timeUtils.createTime(RuntimeUtil.getExecutionTimeForTicks(amltTicks, amltCore, TimeType.WCET))
-
- it.sigma = inchronModelFactory.createTime
- it.type = TimeDistributionType.MAX
- it.alpha = 0
- it.beta = 0
- var amltDistribution = amltTicks?.extended?.get(amltCore)
-
- if (amltDistribution === null) {
- amltDistribution = amltTicks.^default
- }
-
- if (amltDistribution instanceof DiscreteValueGaussDistribution) {
- it.type = TimeDistributionType.NORMAL
-
- val sdCycles = amltDistribution.sd
-
- it.sigma = timeUtils.createTime(
- RuntimeUtil.getExecutionTimeForCycles(sdCycles, amltCore?.frequencyDomain?.defaultValue))
-
- } else if (amltDistribution instanceof DiscreteValueUniformDistribution) {
- it.type = TimeDistributionType.UNIFORM
- } else if (amltDistribution instanceof DiscreteValueBetaDistribution) {
- } else if (amltDistribution instanceof DiscreteValueHistogram) {
- it.type = TimeDistributionType.DISCRETE
-
- amltDistribution.entries.forEach [ amltEntry |
-
- val amltAvg = (amltEntry.upperBound + amltEntry.lowerBound) / 2;
-
- val amltOccurrences = amltEntry.occurrences
-
- var inchronDiscreteDistributionEntry = inchronModelFactory.createDiscreteDistributionEntry
-
- inchronDiscreteDistributionEntry.count = amltOccurrences
-
- inchronDiscreteDistributionEntry.execTime = timeUtils.createTime(
- RuntimeUtil.getExecutionTimeForCycles(amltAvg, amltCore?.frequencyDomain?.defaultValue))
-
- it.discreteDistribution.add(inchronDiscreteDistributionEntry)
- ]
- }
-
+
+ //transform basic elements
+ it.min = createTimeTicks( amltDistribution.lowerBound)
+ it.mean = createTimeTicks(amltDistribution.average)
+ it.max = createTimeTicks(amltDistribution.upperBound)
+ it.sigma = createTimeTicks(0)
+ it.type = TimeDistributionType.MAX
+ it.alpha = 0
+ it.beta = 0
+
+ // more sophisticated distributions
+ if (amltDistribution instanceof DiscreteValueGaussDistribution) {
+ it.type = TimeDistributionType.NORMAL
+ it.sigma = createTimeTicks(amltDistribution.sd)
+ } else if (amltDistribution instanceof DiscreteValueUniformDistribution) {
+ it.type = TimeDistributionType.UNIFORM
+ } else if (amltDistribution instanceof DiscreteValueBetaDistribution) {
+ //TODO: implement beta distribution transformer
+ } else if (amltDistribution instanceof DiscreteValueHistogram) {
+ it.type = TimeDistributionType.DISCRETE
+ amltDistribution.entries.forEach [ amltEntry | {
+ val amltAvg = (amltEntry.upperBound + amltEntry.lowerBound) / 2;
+ val amltOccurrences = amltEntry.occurrences
+ var inchronDiscreteDistributionEntry = inchronModelFactory.createDiscreteDistributionEntry
+ inchronDiscreteDistributionEntry.count = amltOccurrences
+ inchronDiscreteDistributionEntry.execTime = createTimeTicks(amltAvg)
+ it.discreteDistribution.add(inchronDiscreteDistributionEntry)
+ }]
}
-
-// if( amltTicks instanceof TimeGaussDistribution ) {
-// val amltNormal = amltTicks as TimeGaussDistribution
-// it.type = TimeDistributionType.NORMAL
-// it.mean = timeUtils.createTime( amltNormal.getMean() )
-// it.sigma = timeUtils.createTime( amltNormal.getSd() )
-// }
-// else if( amltTicks instanceof TimeUniformDistribution) {
-// val amltUniform = amltTicks as TimeUniformDistribution
-// it.type = TimeDistributionType.UNIFORM
-// it.min = timeUtils.createTime( amltUniform.lowerBound )
-// it.max = timeUtils.createTime( amltUniform.upperBound )
-// }
-// else if( amltTicks instanceof TimeBetaDistribution ) {
-// val amltBeta = amltTicks as TimeBetaDistribution
-// /* TODO: Currently INCHRON does not support the beta distribution.
-// * Mapping to Weibull is WRONG (and also no longer truncated). */
-// it.type = TimeDistributionType.WEIBULL
-// it.alpha = amltBeta.getAlpha()
-// it.beta = amltBeta.getBeta()
-// }
}
-// transform to resource consumption
+
+ def Time createTimeTicks(Double value) {
+ var Time time = inchronModelFactory.createTime
+ time.value = Math.round(value)
+ time.unit = TimeUnit.T
+ return time
+ }
+
+ def Time createTimeTicks(Long value) {
+ var Time time = inchronModelFactory.createTime
+ time.value = value
+ time.unit = TimeUnit.T
+ return time
+ }
+
+
+ def Time createTimeTicks(Integer value) {
+ var Time time = inchronModelFactory.createTime
+ time.value = value
+ time.unit = TimeUnit.T
+ return time
+ }
+
}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TransmissionPolicyTransformer.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TransmissionPolicyTransformer.xtend
index f23950e..231f36d 100644
--- a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TransmissionPolicyTransformer.xtend
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/sw/runnableItem/TransmissionPolicyTransformer.xtend
@@ -19,6 +19,7 @@
import org.eclipse.app4mc.amalthea.model.TransmissionPolicy
import templates.AbstractAmaltheaInchronTransformer
import com.google.inject.Inject
+import org.eclipse.app4mc.amalthea.model.Process
@Singleton
class TransmissionPolicyTransformer extends AbstractAmaltheaInchronTransformer {
@@ -26,7 +27,7 @@
@Inject TicksTransformer ticksTransformer
//TODO: this must be clarified when memory simulation details are set up by Inchron
- def create inchronMemoryFactory.createExplicitDataAccess createExplicitDataAccess(TransmissionPolicy amltTransmissionPolicy) {
+ def create inchronMemoryFactory.createExplicitDataAccess createExplicitDataAccess(Process amltTask, TransmissionPolicy amltTransmissionPolicy) {
it.chunkSize = amltTransmissionPolicy.chunkSize.getValue.intValue
it.chunkPeriod = ticksTransformer.createTimeTicks(amltTransmissionPolicy.chunkProcessingTicks)
}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/utils/DataFlowUtils.xtend b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/utils/DataFlowUtils.xtend
new file mode 100644
index 0000000..6a27135
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.m2m/src/templates/m2m/utils/DataFlowUtils.xtend
@@ -0,0 +1,155 @@
+/**
+ * *******************************************************************************
+ * Copyright (c) 2019 Robert Bosch GmbH and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Robert Bosch GmbH - initial API and implementation
+ * *******************************************************************************
+ */
+
+package templates.m2m.utils
+
+import java.util.LinkedList
+import java.util.List
+import org.eclipse.app4mc.amalthea.model.AbstractEventChain
+import org.eclipse.app4mc.amalthea.model.Channel
+import org.eclipse.app4mc.amalthea.model.ChannelAccess
+import org.eclipse.app4mc.amalthea.model.ChannelEvent
+import org.eclipse.app4mc.amalthea.model.ChannelEventType
+import org.eclipse.app4mc.amalthea.model.ChannelReceive
+import org.eclipse.app4mc.amalthea.model.ChannelSend
+import org.eclipse.app4mc.amalthea.model.Event
+import org.eclipse.app4mc.amalthea.model.EventChain
+import org.eclipse.app4mc.amalthea.model.EventChainContainer
+import org.eclipse.app4mc.amalthea.model.EventChainItem
+import org.eclipse.app4mc.amalthea.model.EventChainReference
+import org.eclipse.app4mc.amalthea.model.Runnable
+import org.eclipse.app4mc.amalthea.model.RunnableItem
+import org.eclipse.app4mc.amalthea.model.Process
+
+class DataFlowUtils {
+
+ static var List<AbstractEventChain> referencingEventChains
+
+ public static def boolean isDataFlow(EventChain eventChain){
+ isDataFlow(eventChain, false)
+ }
+
+ public static def boolean isDataFlow(EventChain eventChain, boolean isReference){
+ if (!isReference){
+ referencingEventChains = new LinkedList<AbstractEventChain>();
+ }
+ return evaluateEventChain(eventChain)
+ }
+
+ private static def boolean evaluateEventChain(AbstractEventChain eventChain){
+ if (!eventChain.segments.isEmpty){
+ for (EventChainItem eventChainItem : eventChain.segments){
+ if (eventChainItem instanceof EventChainReference){
+ referencingEventChains.add(eventChain)
+ evaluateEventChainItem(eventChainItem as EventChainReference)
+ } else if (eventChainItem instanceof EventChainContainer){
+ evaluateEventChainItem(eventChainItem as EventChainContainer)
+ } else {
+ return false;
+ }
+ }
+ } else {
+ if (findChannelAccess(eventChain.stimulus) === null){
+ return false
+ }
+ if (findChannelAccess(eventChain.response) === null){
+ return false
+ }
+ }
+
+ return true
+ }
+
+
+ private static def boolean evaluateEventChainItem(EventChainReference eventChainReference){
+ if(referencingEventChains.contains(eventChainReference.eventChain)){
+ //circular dependency within event chain references, as this instance is listed as referencing event chain
+ //this is not valid --> endless loop and stack overflow
+ return false
+ }
+ return isDataFlow(eventChainReference.eventChain, true)
+ }
+
+ private static def boolean evaluateEventChainItem(EventChainContainer eventChainContainer){
+ return evaluateEventChain(eventChainContainer?.eventChain)
+ }
+
+ public static def dispatch ChannelAccess findChannelAccess(Event amltEvent) {
+ //some event not of specialization type ChannelEvent
+ return null
+ }
+
+
+ public static def dispatch ChannelAccess findChannelAccess(ChannelEvent amltChannelEvent) {
+ val Channel channel = amltChannelEvent.entity;
+ val ChannelEventType eventType = amltChannelEvent.eventType;
+ val Runnable runnable = amltChannelEvent.runnable
+ val Process task = amltChannelEvent.process
+
+ if(runnable === null)
+ return null
+ if(task === null)
+ return null
+
+ if(!runnable.taskRunnableCalls.map[it.containingProcess].contains(task))
+ return null
+
+ if (eventType == ChannelEventType.SEND) {
+ return findChannelSend(runnable, channel)
+ } else if (eventType == ChannelEventType.RECEIVE) {
+ return findChannelReceive(runnable, channel)
+ } else {
+ return null;
+ }
+ }
+
+ private static def ChannelSend findChannelSend(Runnable runnable, Channel channel) {
+ var ChannelSend ret = null
+ for (RunnableItem runnableItem : runnable.runnableItems) {
+ if (runnableItem instanceof ChannelSend){
+ val channelSend = runnableItem as ChannelSend
+ if (channelSend.data === channel){
+ if (ret === null){
+ ret = channelSend
+ } else{
+ //multiple send accesses to this channel within runnable --> not valid
+ return null
+ }
+ }
+ }
+ }
+ return ret
+ }
+
+ private static def ChannelReceive findChannelReceive(Runnable runnable, Channel channel) {
+ var ChannelReceive ret = null
+ for (RunnableItem runnableItem : runnable.runnableItems) {
+ if (runnableItem instanceof ChannelReceive){
+ val channelReceive= runnableItem as ChannelReceive
+ if (channelReceive.data === channel){
+ if (ret === null){
+ ret = channelReceive
+ } else{
+ //multiple receive accesses to this channel within runnable --> not valid
+ return null
+ }
+ }
+ }
+ }
+ return ret
+ }
+
+
+}
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/EventChain2DataFlow/input/EventChainModel.amxmi b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/EventChain2DataFlow/input/EventChainModel.amxmi
new file mode 100644
index 0000000..f1fdf1d
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/EventChain2DataFlow/input/EventChainModel.amxmi
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<am:Amalthea xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:am="http://app4mc.eclipse.org/amalthea/0.9.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <swModel>
+ <tasks name="Task_1" stimuli="PeriodicStimulus_1?type=PeriodicStimulus" preemption="preemptive" multipleTaskActivationLimit="0">
+ <callGraph>
+ <graphEntries xsi:type="am:CallSequence" name="CallSequence_1">
+ <calls xsi:type="am:TaskRunnableCall" runnable="Runnable_1?type=Runnable">
+ <counter prescaler="0" offset="0"/>
+ </calls>
+ </graphEntries>
+ </callGraph>
+ </tasks>
+ <tasks name="Task_2" stimuli="PeriodicStimulus_1?type=PeriodicStimulus" preemption="preemptive" multipleTaskActivationLimit="0">
+ <callGraph>
+ <graphEntries xsi:type="am:CallSequence" name="">
+ <calls xsi:type="am:TaskRunnableCall" runnable="Runnable_2?type=Runnable"/>
+ </graphEntries>
+ </callGraph>
+ </tasks>
+ <tasks name="Task_3-1" stimuli="PeriodicStimulus_1?type=PeriodicStimulus" preemption="preemptive" multipleTaskActivationLimit="0">
+ <callGraph>
+ <graphEntries xsi:type="am:CallSequence" name="CallSequence_1">
+ <calls xsi:type="am:TaskRunnableCall" runnable="Runnable_3?type=Runnable"/>
+ </graphEntries>
+ </callGraph>
+ </tasks>
+ <tasks name="Task_3-2" stimuli="PeriodicStimulus_1?type=PeriodicStimulus" preemption="preemptive" multipleTaskActivationLimit="0">
+ <callGraph>
+ <graphEntries xsi:type="am:CallSequence" name="CallSequence_1">
+ <calls xsi:type="am:TaskRunnableCall" runnable="Runnable_3?type=Runnable"/>
+ </graphEntries>
+ </callGraph>
+ </tasks>
+ <runnables name="Runnable_1" callback="false" service="false">
+ <runnableItems xsi:type="am:ChannelReceive" data="Channel2?type=Channel" elements="2" receiveOperation="LIFO_Read" dataMustBeNew="false" elementIndex="0" lowerBound="2">
+ <transmissionPolicy chunkProcessingTicks="0" transmitRatio="1.0">
+ <chunkSize value="23" unit="B"/>
+ </transmissionPolicy>
+ </runnableItems>
+ <runnableItems xsi:type="am:Ticks">
+ <default xsi:type="am:DiscreteValueConstant" value="100000"/>
+ </runnableItems>
+ <runnableItems xsi:type="am:ChannelSend" data="Channel1?type=Channel" elements="23">
+ <transmissionPolicy chunkProcessingTicks="0" transmitRatio="1.0">
+ <chunkSize value="3" unit="B"/>
+ </transmissionPolicy>
+ </runnableItems>
+ </runnables>
+ <runnables name="Runnable_2" callback="false" service="false">
+ <runnableItems xsi:type="am:ChannelReceive" data="Channel1?type=Channel" elements="2" receiveOperation="FIFO_Take" dataMustBeNew="false" elementIndex="0" lowerBound="1">
+ <transmissionPolicy chunkProcessingTicks="0" transmitRatio="1.0">
+ <chunkSize value="42" unit="B"/>
+ </transmissionPolicy>
+ </runnableItems>
+ <runnableItems xsi:type="am:Ticks">
+ <default xsi:type="am:DiscreteValueConstant" value="100000"/>
+ </runnableItems>
+ <runnableItems xsi:type="am:ChannelSend" data="Channel2?type=Channel" elements="23">
+ <transmissionPolicy chunkProcessingTicks="0" transmitRatio="1.0">
+ <chunkSize value="3" unit="B"/>
+ </transmissionPolicy>
+ </runnableItems>
+ </runnables>
+ <runnables name="Runnable_3" callback="false" service="false">
+ <runnableItems xsi:type="am:Ticks">
+ <default xsi:type="am:DiscreteValueConstant" value="100000"/>
+ </runnableItems>
+ <runnableItems xsi:type="am:ChannelSend" data="Channel3?type=Channel" elements="23">
+ <transmissionPolicy chunkProcessingTicks="0" transmitRatio="1.0">
+ <chunkSize value="3" unit="B"/>
+ </transmissionPolicy>
+ </runnableItems>
+ </runnables>
+ <channels name="Channel1" defaultElements="1" maxElements="5">
+ <size value="22" unit="MB"/>
+ <elementType xsi:type="am:TypeRef" typeDef="BaseTypeDefinition_8?type=BaseTypeDefinition"/>
+ </channels>
+ <channels name="Channel2" defaultElements="1" maxElements="5">
+ <size value="44" unit="MB"/>
+ <elementType xsi:type="am:TypeRef" typeDef="BaseTypeDefinition_8?type=BaseTypeDefinition"/>
+ </channels>
+ <channels name="Channel3" defaultElements="1" maxElements="5">
+ <size value="44" unit="MB"/>
+ <elementType xsi:type="am:TypeRef" typeDef="BaseTypeDefinition_8?type=BaseTypeDefinition"/>
+ </channels>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_1">
+ <size value="8" unit="B"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_2">
+ <size value="0" unit="B"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_3">
+ <size value="0" unit="B"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_4">
+ <size value="4" unit="MB"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_5">
+ <size value="120" unit="kB"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_6">
+ <size value="10" unit="kB"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_7">
+ <size value="4" unit="MB"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_8">
+ <size value="20" unit="kB"/>
+ </typeDefinitions>
+ <typeDefinitions xsi:type="am:BaseTypeDefinition" name="BaseTypeDefinition_9">
+ <size value="180" unit="kB"/>
+ </typeDefinitions>
+ </swModel>
+ <hwModel>
+ <definitions xsi:type="am:ProcessingUnitDefinition" name="ProcessingUnitDefinition_1"/>
+ <definitions xsi:type="am:ProcessingUnitDefinition" name="ProcessingUnitDefinition_2"/>
+ <definitions xsi:type="am:MemoryDefinition" name="MemoryDefinition_1" memoryType="DRAM">
+ <size value="768" unit="kB"/>
+ <dataRate value="10" unit="MbitPerSecond"/>
+ </definitions>
+ <definitions xsi:type="am:MemoryDefinition" name="MemoryDefinition_2" memoryType="SRAM">
+ <size value="256" unit="kB"/>
+ <accessLatency xsi:type="am:DiscreteValueConstant" value="5"/>
+ </definitions>
+ <structures name="HwStructure_1" structureType="System">
+ <structures name="HwStructure_2" structureType="ECU">
+ <structures name="HwStructure_1" structureType="Microcontroller">
+ <modules xsi:type="am:ProcessingUnit" name="ProcessingUnit_1" frequencyDomain="FrequencyDomain_1?type=FrequencyDomain" definition="ProcessingUnitDefinition_1?type=ProcessingUnitDefinition">
+ <accessElements name="HwAccessElement_1" destination="Memory_1?type=Memory">
+ <readLatency xsi:type="am:DiscreteValueConstant" value="5"/>
+ <writeLatency xsi:type="am:DiscreteValueConstant" value="1"/>
+ </accessElements>
+ </modules>
+ <modules xsi:type="am:Memory" name="Memory_1" frequencyDomain="FrequencyDomain_1?type=FrequencyDomain" definition="MemoryDefinition_2?type=MemoryDefinition"/>
+ </structures>
+ <structures name="HwStructure_2" structureType="Microcontroller">
+ <modules xsi:type="am:ProcessingUnit" name="ProcessingUnit_2" frequencyDomain="FrequencyDomain_1?type=FrequencyDomain" definition="ProcessingUnitDefinition_2?type=ProcessingUnitDefinition">
+ <accessElements name="HwAccessElement_4" destination="Memory_2?type=Memory">
+ <readLatency xsi:type="am:DiscreteValueStatistics" lowerBound="10" upperBound="120" average="70.0"/>
+ <writeLatency xsi:type="am:DiscreteValueStatistics" lowerBound="90" upperBound="150" average="50.0"/>
+ </accessElements>
+ </modules>
+ <modules xsi:type="am:Memory" name="Memory_2" frequencyDomain="FrequencyDomain_1?type=FrequencyDomain" definition="MemoryDefinition_1?type=MemoryDefinition"/>
+ </structures>
+ </structures>
+ </structures>
+ <domains xsi:type="am:FrequencyDomain" name="FrequencyDomain_1" clockGating="false">
+ <defaultValue value="0.1" unit="GHz"/>
+ </domains>
+ </hwModel>
+ <osModel>
+ <operatingSystems name="OperatingSystem_1">
+ <taskSchedulers name="TaskScheduler_1">
+ <schedulingAlgorithm xsi:type="am:OSEK"/>
+ </taskSchedulers>
+ </operatingSystems>
+ </osModel>
+ <stimuliModel>
+ <stimuli xsi:type="am:PeriodicStimulus" name="PeriodicStimulus_1">
+ <offset value="0" unit="s"/>
+ <recurrence value="10" unit="ms"/>
+ </stimuli>
+ </stimuliModel>
+ <eventModel>
+ <events xsi:type="am:ChannelEvent" name="task1_runnable1_channel1_send" eventType="send" entity="Channel1?type=Channel" runnable="Runnable_1?type=Runnable" process="Task_1?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="task1_runnable1_channel2_receive" description="" eventType="receive" entity="Channel2?type=Channel" runnable="Runnable_1?type=Runnable" process="Task_1?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="task2_runnable2_channel1_receive" description="" eventType="receive" entity="Channel1?type=Channel" runnable="Runnable_2?type=Runnable" process="Task_2?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="task2_runnable2_channel2_send" eventType="send" entity="Channel2?type=Channel" runnable="Runnable_2?type=Runnable" process="Task_2?type=Task"/>
+ <events xsi:type="am:CustomEvent" name="customEvent0"/>
+ <events xsi:type="am:ChannelEvent" name="task1_channel1_allAccesses_r1" description="" entity="Channel1?type=Channel" runnable="Runnable_1?type=Runnable" process="Task_1?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="task1_channel1_send_r-notSet" eventType="send" entity="Channel1?type=Channel" process="Task_1?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="task1_channel-notSet_send_r1" eventType="send" runnable="Runnable_1?type=Runnable" process="Task_1?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="task1_channel1_send_r3" description="" eventType="send" entity="Channel1?type=Channel" process="Task_1?type=Task"/>
+ <events xsi:type="am:ChannelEvent" name="taskX_runnable1_channel1_send" eventType="send" entity="Channel1?type=Channel" runnable="Runnable_1?type=Runnable"/>
+ </eventModel>
+ <constraintsModel>
+ <eventChains name="SimpleEventChain" stimulus="task2_runnable2_channel2_send?type=ChannelEvent" response="task1_runnable1_channel2_receive?type=ChannelEvent"/>
+ <eventChains name="ReferenceEventChain" stimulus="task2_runnable2_channel1_receive?type=ChannelEvent" response="task1_runnable1_channel2_receive?type=ChannelEvent">
+ <segments xsi:type="am:EventChainReference" eventChain="Nested_EventChain?type=EventChain"/>
+ <segments xsi:type="am:EventChainReference" eventChain="SimpleEventChain?type=EventChain"/>
+ </eventChains>
+ <eventChains name="Nested_EventChain" stimulus="task1_runnable1_channel1_send?type=ChannelEvent" response="task1_runnable1_channel2_receive?type=ChannelEvent">
+ <segments xsi:type="am:EventChainContainer">
+ <eventChain name="SubEventChain3" stimulus="task2_runnable2_channel2_send?type=ChannelEvent" response="task1_runnable1_channel2_receive?type=ChannelEvent"/>
+ </segments>
+ <segments xsi:type="am:EventChainContainer">
+ <eventChain name="SubEventChain_1" stimulus="task1_channel-notSet_send_r1?type=ChannelEvent" response="task2_runnable2_channel2_send?type=ChannelEvent">
+ <segments xsi:type="am:EventChainContainer">
+ <eventChain name="SubEventChain_1_1" stimulus="task1_runnable1_channel1_send?type=ChannelEvent" response="task2_runnable2_channel1_receive?type=ChannelEvent"/>
+ </segments>
+ <segments xsi:type="am:EventChainContainer">
+ <eventChain name="SubEventChain_1_2" stimulus="task2_runnable2_channel1_receive?type=ChannelEvent" response="task2_runnable2_channel2_send?type=ChannelEvent"/>
+ </segments>
+ </eventChain>
+ </segments>
+ </eventChains>
+ <eventChains name="NotADataFlowEventChain_wrongEventType" stimulus="task2_runnable2_channel1_receive?type=ChannelEvent" response="customEvent0?type=CustomEvent"/>
+ <eventChains name="NotADataFlowEventChain_IllegalEventTypeInStimulus" stimulus="task1_channel1_allAccesses_r1?type=ChannelEvent" response="task1_runnable1_channel1_send?type=ChannelEvent"/>
+ <eventChains name="NotADataFlowEventChain_ChannelNotSet" stimulus="task1_channel-notSet_send_r1?type=ChannelEvent" response="task1_runnable1_channel1_send?type=ChannelEvent"/>
+ <eventChains name="NotADataFlowEventChain_RunnableNotSet" stimulus="task1_channel1_allAccesses_r1?type=ChannelEvent" response="task1_runnable1_channel1_send?type=ChannelEvent"/>
+ <eventChains name="NotADataFlowEventChain_RunnableNotContainsChannelAccess" stimulus="task1_channel1_send_r3?type=ChannelEvent" response="task1_runnable1_channel1_send?type=ChannelEvent"/>
+ <eventChains name="NotADataFlowEventChain_TaskNotSet" stimulus="task2_runnable2_channel1_receive?type=ChannelEvent" response="taskX_runnable1_channel1_send?type=ChannelEvent"/>
+ </constraintsModel>
+ <mappingModel>
+ <schedulerAllocation scheduler="TaskScheduler_1?type=TaskScheduler" responsibility="ProcessingUnit_1?type=ProcessingUnit ProcessingUnit_2?type=ProcessingUnit" executingPU="ProcessingUnit_1?type=ProcessingUnit"/>
+ <taskAllocation task="Task_1?type=Task" scheduler="TaskScheduler_1?type=TaskScheduler" affinity="ProcessingUnit_1?type=ProcessingUnit">
+ <schedulingParameters priority="20"/>
+ </taskAllocation>
+ <taskAllocation task="Task_2?type=Task" scheduler="TaskScheduler_1?type=TaskScheduler" affinity="ProcessingUnit_2?type=ProcessingUnit"/>
+ <memoryMapping abstractElement="Channel1?type=Channel" memory="Memory_1?type=Memory" memoryPositionAddress="0x2000"/>
+ <memoryMapping abstractElement="Channel2?type=Channel" memory="Memory_2?type=Memory" memoryPositionAddress="0x3000"/>
+ </mappingModel>
+ <componentsModel>
+ <components name="Component_1"/>
+ <components name="Component_2"/>
+ <components name="Component_3"/>
+ <components name="Component_4"/>
+ <components name="Component_5"/>
+ <components name="Component_6"/>
+ <components name="Component_7"/>
+ <components name="Component_8"/>
+ <components xsi:type="am:Composite" name="Composite_1">
+ <componentInstances name="ComponentInstance_1" type="Component_1?type=Component"/>
+ <componentInstances name="ComponentInstance_2" type="Component_2?type=Component"/>
+ <componentInstances name="ComponentInstance_3" type="Component_3?type=Component"/>
+ <componentInstances name="ComponentInstance_4" type="Component_1?type=Component"/>
+ </components>
+ <components xsi:type="am:Composite" name="Composite_2">
+ <componentInstances name="ComponentInstance_5" type="Component_4?type=Component"/>
+ <componentInstances name="ComponentInstance_6" type="Component_5?type=Component"/>
+ </components>
+ <components xsi:type="am:Composite" name="Composite_3">
+ <componentInstances name="ComponentInstance_7" type="Component_7?type=Component"/>
+ </components>
+ <systems name="System_1">
+ <componentInstances name="ComponentInstance_8" type="Component_6?type=Component"/>
+ <componentInstances name="ComponentInstance_9" type="Component_6?type=Component"/>
+ <componentInstances name="ComponentInstance_10" type="Composite_1?type=Composite"/>
+ <componentInstances name="ComponentInstance_11" type="Composite_2?type=Composite"/>
+ <componentInstances name="ComponentInstance_12" type="Composite_3?type=Composite"/>
+ </systems>
+ </componentsModel>
+</am:Amalthea>
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/EventChain2DataFlow/output/EventChainModel.iprx b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/EventChain2DataFlow/output/EventChainModel.iprx
new file mode 100644
index 0000000..95dc708
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/EventChain2DataFlow/output/EventChainModel.iprx
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="ASCII"?>
+<root:Root xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:model="http://inchron.com/realtime/root/2.98.3/model" xmlns:root="http://inchron.com/realtime/root/2.98.3" xmlns:stimulation="http://inchron.com/realtime/root/2.98.3/model/stimulation">
+ <model xsi:type="model:Model" name="Model" defaultScenario="//@model/@stimulationScenarios.0">
+ <clocks name="FrequencyDomain_1" users="//@model/@cpus.0/@memories.0 //@model/@cpus.0 //@model/@cpus.1/@memories.0 //@model/@cpus.1 //@model/@stimulationScenarios.0/@generators.0">
+ <frequency value="0.1" unit="GHz"/>
+ <range value="1" unit="s"/>
+ <startTimeFixed/>
+ <startTimeMin/>
+ <startTimeMax/>
+ <startValue/>
+ </clocks>
+ <cpus name="HwStructure_1" clock="//@model/@clocks.0" cpuModel="generic">
+ <cores name="ProcessingUnit_1"/>
+ <memories name="Memory_1" clock="//@model/@clocks.0" size="256000"/>
+ <memoryRegions name="ram" base="16777216" flags="290" pages="1" sections="data:bss:stack:heap"/>
+ <memoryRegions name="rom" base="33554432" flags="275" pages="1" sections="text"/>
+ </cpus>
+ <cpus name="HwStructure_2" clock="//@model/@clocks.0" cpuModel="generic">
+ <cores name="ProcessingUnit_2"/>
+ <memories name="Memory_2" clock="//@model/@clocks.0" size="768000"/>
+ <memoryRegions name="ram" base="16777216" flags="290" pages="1" sections="data:bss:stack:heap"/>
+ <memoryRegions name="rom" base="33554432" flags="275" pages="1" sections="text"/>
+ </cpus>
+ <connections xsi:type="model:DataFlowConnection" name="Channel1" communicationType="Queuing" defaultElements="1" provider="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.2" requesters="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.0" size="5"/>
+ <connections xsi:type="model:DataFlowConnection" name="Channel2" communicationType="Queuing" defaultElements="1" provider="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.2" requesters="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.0" size="5"/>
+ <eventChains xsi:type="model:DataFlow" name="SimpleEventChain">
+ <edges stimulus="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.2" response="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.0"/>
+ </eventChains>
+ <eventChains xsi:type="model:DataFlow" name="Nested_EventChain">
+ <edges stimulus="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.2" response="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.0"/>
+ <edges stimulus="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.2" response="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.0"/>
+ <edges stimulus="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.0" response="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.2"/>
+ </eventChains>
+ <eventChains xsi:type="model:DataFlow" name="ReferenceEventChain">
+ <references dataFlow="//@model/@eventChains.1" stimulus="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.0" response="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.0"/>
+ <references dataFlow="//@model/@eventChains.0" stimulus="//@model/@systems.0/@components.0/@functions.0/@callGraph/@graphEntries.0/@calls.2" response="//@model/@systems.0/@components.0/@functions.1/@callGraph/@graphEntries.0/@calls.0"/>
+ </eventChains>
+ <generalInfo creator="Amlt2Inchron 0.9.3 Fri Mar 29 07:21:35 CET 2019" version="1"/>
+ <stimulationScenarios name="DefaultScenario">
+ <generators xsi:type="stimulation:RandomStimuliGenerator" name="PeriodicStimulus_1" clock="//@model/@clocks.0">
+ <connections xsi:type="model:ActivationConnection" name="PeriodicStimulus_1" activators="//@model/@stimulationScenarios.0/@generators.0/@targets/@graphEntries.0/@calls.0">
+ <activations xsi:type="model:ActivateProcess" target="//@model/@systems.0/@rtosConfig/@schedulables.0/@schedulables.0/@schedulables.1"/>
+ <activations xsi:type="model:ActivateProcess" target="//@model/@systems.0/@rtosConfig/@schedulables.0/@schedulables.0/@schedulables.0"/>
+ </connections>
+ <targets>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:ActivationItem" name="ActivationItem" connection="//@model/@stimulationScenarios.0/@generators.0/@connections.0"/>
+ </graphEntries>
+ </targets>
+ <minInterArrivalTime/>
+ <period value="10" unit="ms"/>
+ <startOffset unit="s"/>
+ <startOffsetVariation/>
+ <variation/>
+ </generators>
+ </stimulationScenarios>
+ <systems xsi:type="model:GenericSystem" name="OperatingSystem_1_SYSTEM">
+ <components name="OperatingSystem_1_SWC">
+ <functions name="Task_2-Runnable_2">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:VariableReadAccess" name="Task_2_receive_Channel1_0" label="Task_2_receive_Channel1_0" connection="//@model/@connections.0" isBuffered="true" number="2" policy="LIFO" lowerBound="1">
+ <dataAccess chunkSize="42">
+ <chunkPeriod unit="T"/>
+ </dataAccess>
+ </calls>
+ <calls xsi:type="model:ResourceConsumption" name="RC">
+ <timeDistribution alpha="0.0" beta="0.0">
+ <min value="100000" unit="T"/>
+ <max value="100000" unit="T"/>
+ <mean value="100000" unit="T"/>
+ <sigma unit="T"/>
+ </timeDistribution>
+ </calls>
+ <calls xsi:type="model:VariableWriteAccess" name="Task_2_send_Channel2_0" label="Task_2_send_Channel2_0" connection="//@model/@connections.1" isBuffered="true" number="23">
+ <dataAccess accessType="Write" chunkSize="3">
+ <chunkPeriod unit="T"/>
+ </dataAccess>
+ </calls>
+ </graphEntries>
+ </callGraph>
+ </functions>
+ <functions name="Task_1-Runnable_1">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:VariableReadAccess" name="Task_1_receive_Channel2_1" label="Task_1_receive_Channel2_1" connection="//@model/@connections.1" isBuffered="true" number="2" isTake="false" lowerBound="2">
+ <dataAccess chunkSize="23">
+ <chunkPeriod unit="T"/>
+ </dataAccess>
+ </calls>
+ <calls xsi:type="model:ResourceConsumption" name="RC">
+ <timeDistribution alpha="0.0" beta="0.0">
+ <min value="100000" unit="T"/>
+ <max value="100000" unit="T"/>
+ <mean value="100000" unit="T"/>
+ <sigma unit="T"/>
+ </timeDistribution>
+ </calls>
+ <calls xsi:type="model:VariableWriteAccess" name="Task_1_send_Channel1_1" label="Task_1_send_Channel1_1" connection="//@model/@connections.0" isBuffered="true" number="23">
+ <dataAccess accessType="Write" chunkSize="3">
+ <chunkPeriod unit="T"/>
+ </dataAccess>
+ </calls>
+ </graphEntries>
+ </callGraph>
+ </functions>
+ </components>
+ <rtosModel name="generic" returnType="void"/>
+ <rtosConfig name="OperatingSystem_1">
+ <schedulables xsi:type="model:Scheduler" name="OperatingSystem_1_ISRDummy" cpuCores="//@model/@cpus.0/@cores.0 //@model/@cpus.1/@cores.0">
+ <schedulables xsi:type="model:Scheduler" name="TaskScheduler_1" cpuCores="//@model/@cpus.0/@cores.0 //@model/@cpus.1/@cores.0">
+ <schedulables xsi:type="model:Process" name="Task_1" cpuCores="//@model/@cpus.0/@cores.0">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:FunctionCall" name="call_Task_1-Runnable_1" function="//@model/@systems.0/@components.0/@functions.1"/>
+ </graphEntries>
+ </callGraph>
+ </schedulables>
+ <schedulables xsi:type="model:Process" name="Task_2" cpuCores="//@model/@cpus.1/@cores.0">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:FunctionCall" name="call_Task_2-Runnable_2" function="//@model/@systems.0/@components.0/@functions.0"/>
+ </graphEntries>
+ </callGraph>
+ </schedulables>
+ <timeSlice/>
+ <period/>
+ <maxRetard/>
+ <maxAdvance/>
+ </schedulables>
+ <timeSlice/>
+ <period/>
+ <maxRetard/>
+ <maxAdvance/>
+ </schedulables>
+ </rtosConfig>
+ </systems>
+ </model>
+</root:Root>
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/Ticks2TicksFlow/input/ExtendedTicksModel.amxmi b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/Ticks2TicksFlow/input/ExtendedTicksModel.amxmi
new file mode 100644
index 0000000..4d44f27
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/Ticks2TicksFlow/input/ExtendedTicksModel.amxmi
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<am:Amalthea xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:am="http://app4mc.eclipse.org/amalthea/0.9.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <swModel>
+ <tasks name="Task_1" stimuli="PeriodicStimulus_1?type=PeriodicStimulus" preemption="preemptive" multipleTaskActivationLimit="0">
+ <callGraph>
+ <graphEntries xsi:type="am:CallSequence" name="CallSequence_1">
+ <calls xsi:type="am:TaskRunnableCall" runnable="Runnable_1?type=Runnable">
+ <counter prescaler="0" offset="0"/>
+ </calls>
+ </graphEntries>
+ </callGraph>
+ </tasks>
+ <tasks name="Task_2" stimuli="PeriodicStimulus_1?type=PeriodicStimulus" preemption="preemptive" multipleTaskActivationLimit="0">
+ <callGraph>
+ <graphEntries xsi:type="am:CallSequence" name="">
+ <calls xsi:type="am:TaskRunnableCall" runnable="Runnable_1?type=Runnable"/>
+ </graphEntries>
+ </callGraph>
+ </tasks>
+ <runnables name="Runnable_1" callback="false" service="false">
+ <runnableItems xsi:type="am:Ticks">
+ <default xsi:type="am:DiscreteValueConstant" value="100"/>
+ <extended key="ProcessingUnitDefinition_1?type=ProcessingUnitDefinition">
+ <value xsi:type="am:DiscreteValueConstant" value="42"/>
+ </extended>
+ <extended key="ProcessingUnitDefinition_2?type=ProcessingUnitDefinition">
+ <value xsi:type="am:DiscreteValueConstant" value="23"/>
+ </extended>
+ </runnableItems>
+ <runnableItems xsi:type="am:Ticks">
+ <default xsi:type="am:DiscreteValueConstant" value="5"/>
+ </runnableItems>
+ </runnables>
+ </swModel>
+ <hwModel>
+ <definitions xsi:type="am:ProcessingUnitDefinition" name="ProcessingUnitDefinition_1"/>
+ <definitions xsi:type="am:ProcessingUnitDefinition" name="ProcessingUnitDefinition_2"/>
+ <structures name="HwStructure_1" structureType="System">
+ <structures name="HwStructure_2" structureType="ECU">
+ <structures name="HwStructure_1" structureType="Microcontroller">
+ <modules xsi:type="am:ProcessingUnit" name="ProcessingUnit_1" frequencyDomain="FrequencyDomain_1?type=FrequencyDomain" definition="ProcessingUnitDefinition_1?type=ProcessingUnitDefinition"/>
+ </structures>
+ <structures name="HwStructure_2" structureType="Microcontroller">
+ <modules xsi:type="am:ProcessingUnit" name="ProcessingUnit_2" frequencyDomain="FrequencyDomain_1?type=FrequencyDomain" definition="ProcessingUnitDefinition_2?type=ProcessingUnitDefinition"/>
+ </structures>
+ </structures>
+ </structures>
+ <domains xsi:type="am:FrequencyDomain" name="FrequencyDomain_1" clockGating="false">
+ <defaultValue value="0.1" unit="GHz"/>
+ </domains>
+ </hwModel>
+ <osModel>
+ <operatingSystems name="OperatingSystem_1">
+ <taskSchedulers name="TaskScheduler_1">
+ <schedulingAlgorithm xsi:type="am:OSEK"/>
+ </taskSchedulers>
+ </operatingSystems>
+ </osModel>
+ <stimuliModel>
+ <stimuli xsi:type="am:PeriodicStimulus" name="PeriodicStimulus_1">
+ <offset value="0" unit="s"/>
+ <recurrence value="10" unit="ms"/>
+ </stimuli>
+ </stimuliModel>
+ <eventModel/>
+ <constraintsModel/>
+ <mappingModel>
+ <schedulerAllocation scheduler="TaskScheduler_1?type=TaskScheduler" responsibility="ProcessingUnit_1?type=ProcessingUnit ProcessingUnit_2?type=ProcessingUnit" executingPU="ProcessingUnit_1?type=ProcessingUnit"/>
+ <taskAllocation task="Task_1?type=Task" scheduler="TaskScheduler_1?type=TaskScheduler" affinity="ProcessingUnit_1?type=ProcessingUnit"/>
+ <taskAllocation task="Task_2?type=Task" scheduler="TaskScheduler_1?type=TaskScheduler" affinity="ProcessingUnit_2?type=ProcessingUnit"/>
+ </mappingModel>
+</am:Amalthea>
diff --git a/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/Ticks2TicksFlow/output/ExtendedTicksModel.iprx b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/Ticks2TicksFlow/output/ExtendedTicksModel.iprx
new file mode 100644
index 0000000..f7172f2
--- /dev/null
+++ b/eclipse-tools/model-transformation/examples/amlt2inchron/org.eclipse.app4mc.transform.to.inchron.product/testModels/Ticks2TicksFlow/output/ExtendedTicksModel.iprx
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="ASCII"?>
+<root:Root xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:model="http://inchron.com/realtime/root/2.98.3/model" xmlns:root="http://inchron.com/realtime/root/2.98.3" xmlns:stimulation="http://inchron.com/realtime/root/2.98.3/model/stimulation">
+ <model xsi:type="model:Model" name="Model" defaultScenario="//@model/@stimulationScenarios.0">
+ <clocks name="FrequencyDomain_1" users="//@model/@cpus.0 //@model/@cpus.1 //@model/@stimulationScenarios.0/@generators.0">
+ <frequency value="0.1" unit="GHz"/>
+ <range value="1" unit="s"/>
+ <startTimeFixed/>
+ <startTimeMin/>
+ <startTimeMax/>
+ <startValue/>
+ </clocks>
+ <cpus name="HwStructure_1" clock="//@model/@clocks.0" cpuModel="generic">
+ <cores name="ProcessingUnit_1"/>
+ <memoryRegions name="ram" base="16777216" flags="290" pages="1" sections="data:bss:stack:heap"/>
+ <memoryRegions name="rom" base="33554432" flags="275" pages="1" sections="text"/>
+ </cpus>
+ <cpus name="HwStructure_2" clock="//@model/@clocks.0" cpuModel="generic">
+ <cores name="ProcessingUnit_2"/>
+ <memoryRegions name="ram" base="16777216" flags="290" pages="1" sections="data:bss:stack:heap"/>
+ <memoryRegions name="rom" base="33554432" flags="275" pages="1" sections="text"/>
+ </cpus>
+ <generalInfo creator="Amlt2Inchron 0.9.3 Mon Mar 25 10:21:30 CET 2019" version="1"/>
+ <stimulationScenarios name="DefaultScenario">
+ <generators xsi:type="stimulation:RandomStimuliGenerator" name="PeriodicStimulus_1" clock="//@model/@clocks.0">
+ <connections xsi:type="model:ActivationConnection" name="PeriodicStimulus_1" activators="//@model/@stimulationScenarios.0/@generators.0/@targets/@graphEntries.0/@calls.0">
+ <activations xsi:type="model:ActivateProcess" target="//@model/@systems.0/@rtosConfig/@schedulables.0/@schedulables.0/@schedulables.1"/>
+ <activations xsi:type="model:ActivateProcess" target="//@model/@systems.0/@rtosConfig/@schedulables.0/@schedulables.0/@schedulables.0"/>
+ </connections>
+ <targets>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:ActivationItem" name="ActivationItem" connection="//@model/@stimulationScenarios.0/@generators.0/@connections.0"/>
+ </graphEntries>
+ </targets>
+ <minInterArrivalTime/>
+ <period value="10" unit="ms"/>
+ <startOffset unit="s"/>
+ <startOffsetVariation/>
+ <variation/>
+ </generators>
+ </stimulationScenarios>
+ <systems xsi:type="model:GenericSystem" name="OperatingSystem_1_SYSTEM">
+ <components name="OperatingSystem_1_SWC">
+ <functions name="Task_2-Runnable_1">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:ResourceConsumption" name="RC">
+ <timeDistribution alpha="0.0" beta="0.0">
+ <min value="23" unit="T"/>
+ <max value="23" unit="T"/>
+ <mean value="23" unit="T"/>
+ <sigma unit="T"/>
+ </timeDistribution>
+ </calls>
+ <calls xsi:type="model:ResourceConsumption" name="RC">
+ <timeDistribution alpha="0.0" beta="0.0">
+ <min value="5" unit="T"/>
+ <max value="5" unit="T"/>
+ <mean value="5" unit="T"/>
+ <sigma unit="T"/>
+ </timeDistribution>
+ </calls>
+ </graphEntries>
+ </callGraph>
+ </functions>
+ <functions name="Task_1-Runnable_1">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:ResourceConsumption" name="RC">
+ <timeDistribution alpha="0.0" beta="0.0">
+ <min value="42" unit="T"/>
+ <max value="42" unit="T"/>
+ <mean value="42" unit="T"/>
+ <sigma unit="T"/>
+ </timeDistribution>
+ </calls>
+ <calls xsi:type="model:ResourceConsumption" name="RC">
+ <timeDistribution alpha="0.0" beta="0.0">
+ <min value="5" unit="T"/>
+ <max value="5" unit="T"/>
+ <mean value="5" unit="T"/>
+ <sigma unit="T"/>
+ </timeDistribution>
+ </calls>
+ </graphEntries>
+ </callGraph>
+ </functions>
+ </components>
+ <rtosModel name="generic" returnType="void"/>
+ <rtosConfig name="OperatingSystem_1">
+ <schedulables xsi:type="model:Scheduler" name="OperatingSystem_1_ISRDummy" cpuCores="//@model/@cpus.0/@cores.0 //@model/@cpus.1/@cores.0">
+ <schedulables xsi:type="model:Scheduler" name="TaskScheduler_1" cpuCores="//@model/@cpus.0/@cores.0 //@model/@cpus.1/@cores.0">
+ <schedulables xsi:type="model:Process" name="Task_1" cpuCores="//@model/@cpus.0/@cores.0">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:FunctionCall" name="call_Task_1-Runnable_1" function="//@model/@systems.0/@components.0/@functions.1"/>
+ </graphEntries>
+ </callGraph>
+ </schedulables>
+ <schedulables xsi:type="model:Process" name="Task_2" cpuCores="//@model/@cpus.1/@cores.0">
+ <callGraph>
+ <graphEntries xsi:type="model:CallSequence" name="CS">
+ <calls xsi:type="model:FunctionCall" name="call_Task_2-Runnable_1" function="//@model/@systems.0/@components.0/@functions.0"/>
+ </graphEntries>
+ </callGraph>
+ </schedulables>
+ <timeSlice/>
+ <period/>
+ <maxRetard/>
+ <maxAdvance/>
+ </schedulables>
+ <timeSlice/>
+ <period/>
+ <maxRetard/>
+ <maxAdvance/>
+ </schedulables>
+ </rtosConfig>
+ </systems>
+ </model>
+</root:Root>