Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend')
-rw-r--r--plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend1444
1 files changed, 722 insertions, 722 deletions
diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend
index 92dff5f3c..ed722fa13 100644
--- a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend
+++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend
@@ -1,722 +1,722 @@
-/*******************************************************************************
- * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * CONTRIBUTORS:
- * Henrik Rentz-Reichert (initial contribution)
- * Thomas Schuetz (changed for C code generator)
- *
- *******************************************************************************/
-
-package org.eclipse.etrice.generator.c.gen
-
-import com.google.inject.Inject
-import com.google.inject.Singleton
-import java.util.ArrayList
-import java.util.HashMap
-import java.util.HashSet
-import org.eclipse.etrice.core.etmap.util.ETMapUtil
-import org.eclipse.etrice.core.etphys.eTPhys.ExecMode
-import org.eclipse.etrice.core.etphys.eTPhys.PhysicalThread
-import org.eclipse.etrice.core.genmodel.etricegen.ActorInstance
-import org.eclipse.etrice.core.genmodel.etricegen.IDiagnostician
-import org.eclipse.etrice.core.genmodel.etricegen.InterfaceItemInstance
-import org.eclipse.etrice.core.genmodel.etricegen.PortInstance
-import org.eclipse.etrice.core.genmodel.etricegen.Root
-import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance
-import org.eclipse.etrice.core.room.ActorCommunicationType
-import org.eclipse.etrice.core.room.CommunicationType
-import org.eclipse.etrice.core.room.Port
-import org.eclipse.etrice.core.room.ProtocolClass
-import org.eclipse.etrice.core.room.SAPRef
-import org.eclipse.etrice.core.room.SPPRef
-import org.eclipse.etrice.generator.base.IGeneratorFileIo
-import org.eclipse.etrice.generator.base.IntelligentSeparator
-import org.eclipse.etrice.generator.generic.ILanguageExtension
-import org.eclipse.etrice.generator.generic.ProcedureHelpers
-import org.eclipse.etrice.generator.generic.RoomExtensions
-
-import static extension org.eclipse.etrice.core.room.util.RoomHelpers.*
-import org.eclipse.etrice.generator.base.GlobalGeneratorSettings
-
-@Singleton
-class NodeGen {
-
- @Inject extension CExtensions
- @Inject extension RoomExtensions
- @Inject extension ProcedureHelpers helpers
-
- @Inject IGeneratorFileIo fileIO
- @Inject Initialization attrInitGenAddon
- @Inject ILanguageExtension languageExt
- @Inject IDiagnostician diagnostician
-
- def doGenerate(Root root) {
- for (nr : ETMapUtil::getNodeRefs()) {
- for (instpath : ETMapUtil::getSubSystemInstancePaths(nr)) {
- val ssi = root.getInstance(instpath) as SubSystemInstance
- val filepath = ssi.subSystemClass.generationTargetPath+ssi.subSystemClass.getPath
- val infopath = ssi.subSystemClass.generationInfoPath+ssi.subSystemClass.getPath
- var file = nr.getCHeaderFileName(ssi)
-
- checkDataPorts(ssi)
-
- val usedThreads = new HashSet<PhysicalThread>();
- for (thread: nr.type.threads) {
- val instancesOnThread = ssi.allContainedInstances.filter(ai|ETMapUtil::getPhysicalThread(ai)==thread)
- if (!instancesOnThread.empty)
- usedThreads.add(thread)
- }
-
- fileIO.generateFile("generating Node declaration", filepath, infopath, file, root.generateHeaderFile(ssi))
-
- file = nr.getCSourceFileName(ssi)
- fileIO.generateFile("generating Node implementation", filepath, infopath, file, root.generateSourceFile(ssi, usedThreads))
-
- file = nr.getInstSourceFileName(ssi)
- fileIO.generateFile("generating Node instance file", filepath, infopath, file, root.generateInstanceFile(ssi, usedThreads))
-
- file = nr.getDispSourceFileName(ssi)
- fileIO.generateFile("generating Node dispatcher file", filepath, infopath, file, root.generateDispatcherFile(ssi, usedThreads))
- }
- }
- }
-
- def private generateHeaderFile(Root root, SubSystemInstance ssi) {
- val nr = ETMapUtil::getNodeRef(ssi)
- val ssc = ssi.subSystemClass
- val clsname = nr.name+"_"+ssi.name
- '''
- /**
- * @author generated by eTrice
- *
- * Header File of Node «nr.name» with SubSystem «ssi.name»
- *
- */
-
- «generateIncludeGuardBegin(clsname)»
-
- #include "etDatatypes.h"
-
-««« TODOCGENPHYS: user code?
- «helpers.userCode(ssc.userCode1)»
-
-
- /* lifecycle functions
- * init -> start -> run (loop) -> stop -> destroy
- */
-
- void «clsname»_init(void); /* lifecycle init */
- void «clsname»_start(void); /* lifecycle start */
-
- void «clsname»_run(etBool runAsTest); /* lifecycle run */
-
- void «clsname»_stop(void); /* lifecycle stop */
- void «clsname»_destroy(void); /* lifecycle destroy */
-
- void «clsname»_shutdown(void); /* shutdown the dispatcher loop */
-
-««« TODOCGENPHYS: user code?
- «helpers.userCode(ssc.userCode2)»
-
- «generateIncludeGuardEnd(clsname)»
-
-
- '''
- }
-
- def private generateSourceFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
- val nr = ETMapUtil::getNodeRef(ssi)
- val ssc = ssi.subSystemClass
- val clsname = nr.name+"_"+ssi.name
- val threads = nr.type.threads.filter(t|usedThreads.contains(t))
- '''
- /**
- * @author generated by eTrice
- *
- * Source File of Node «nr.name» with SubSystem «ssi.name»
- *
- */
-
- #include <stdio.h>
-
- #include "«nr.getCHeaderFileName(ssi)»"
-
- #include "debugging/etLogger.h"
- #include "debugging/etMSCLogger.h"
- #include "messaging/etSystemProtocol.h"
- #include "osal/etTimer.h"
- #include "osal/etSema.h"
- #include "runtime/etRuntime.h"
- #include "etRuntimeConfig.h"
-
-««« TODOCGENPHYS: user code?
- «helpers.userCode(ssc.userCode3)»
-
- /* data for Node «nr.name» with SubSystem «ssi.name» */
- typedef struct «clsname» {
- char *name;
- volatile int shutdownRequest;
- } «clsname»;
-
- static «clsname» «clsname»Inst = {"«clsname»", 0};
-
- static void «clsname»_initActorInstances(void);
- static void «clsname»_constructActorInstances(void);
-
- /* include instances for all classes */
- #include "«nr.getInstSourceFileName(ssi)»"
- #include "«nr.getDispSourceFileName(ssi)»"
-
- static void «clsname»_initMessageServices(void) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "initMessageServices")
- {
- etTime interval;
-
- /* initialization of all message services */
- «FOR thread: threads»
- «IF thread.execmode==ExecMode::POLLED || thread.execmode==ExecMode::MIXED»
-««« interval.sec = «thread.sec» <-- use convenience functions to split time in sec and nsec
- interval.sec = 0;
- interval.nSec = «thread.time»;
- «ENDIF»
- etMessageService_init(
- &msgService_«thread.name»,
- msgBuffer_«thread.name»,
- «thread.name.toUpperCase»_POOL_SIZE,
- «thread.name.toUpperCase»_BLOCK_SIZE,
- «thread.stacksize»,
- «thread.prio»,
- interval,
- MsgDispatcher_«thread.name»_receiveMessage,
- EXECMODE_«thread.execmode.toString.toUpperCase»);
-
- «ENDFOR»
- }
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- static void «clsname»_startMessageServices(void) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "startMessageServices")
-
- «FOR thread: threads»
- etMessageService_start(&msgService_«thread.name»);
- «ENDFOR»
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- static void «clsname»_stopMessageServices(void) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "stopMessageServices")
-
- «FOR thread: threads»
- etMessageService_stop(&msgService_«thread.name»);
- «ENDFOR»
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- static void «clsname»_destroyMessageServices(void) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "destroyMessageServices")
-
- «FOR thread: threads»
- etMessageService_destroy(&msgService_«thread.name»);
- «ENDFOR»
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- void «clsname»_init(void) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "init")
- etLogger_logInfoF("%s_init", «clsname»Inst.name);
-
- /* construct all actors */
- «clsname»_constructActorInstances();
-
- /* initialization of all message services */
- «clsname»_initMessageServices();
-
- /* init all actors */
- «clsname»_initActorInstances();
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- void «clsname»_start(void) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "start")
- etLogger_logInfoF("%s_start", «clsname»Inst.name);
- «clsname»_startMessageServices();
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- void «clsname»_run(etBool runAsTest) {
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "run")
-
- if (runAsTest) {
- etSema_waitForWakeup(etRuntime_getTerminateSemaphore());
- }
- else {
- printf("type quit to exit\n");
- fflush(stdout);
- while (TRUE) {
- char line[64];
-
- if (fgets(line, 64, stdin) == NULL) {
- printf("got NULL\n");
- break;
- }
- else if (strncmp(line, "quit", 4)==0){
- break;
- }
- }
- }
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- void «clsname»_stop(void){
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "stop")
- etLogger_logInfoF("%s_stop", «clsname»Inst.name);
-
- «clsname»_stopMessageServices();
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- void «clsname»_destroy(void){
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "destroy")
- etLogger_logInfoF("%s_destroy", «clsname»Inst.name);
- «FOR ai : ssi.allContainedInstances.reverseView»
- «IF !ai.actorClass.operations.filter(op|op.destructor).empty»
- «languageExt.memberInUse(ai.actorClass.name, languageExt.destructorName(ai.actorClass.name))»(&«ai.path.getPathName()»);
- «ENDIF»
- «ENDFOR»
-
- «clsname»_destroyMessageServices();
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- void «clsname»_shutdown(void){
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "shutdown")
- etLogger_logInfoF("%s_shutdown", «clsname»Inst.name);
-
- «clsname»Inst.shutdownRequest = 1;
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
-
- static void «clsname»_constructActorInstances(void){
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "constructActorInstances")
-
- «FOR ai : ssi.allContainedInstances»
- «IF !ai.actorClass.operations.filter(op|op.constructor).empty»
- «languageExt.memberInUse(ai.actorClass.name, languageExt.constructorName(ai.actorClass.name))»(&«ai.path.getPathName()»);
- «ENDIF»
- «ENDFOR»
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
-
- static void «clsname»_initActorInstances(void){
- ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "initActorInstances")
-
- «FOR ai : ssi.allContainedInstances»
- «ai.actorClass.name»_init(&«ai.path.getPathName()»);
- «ENDFOR»
-
- ET_MSC_LOGGER_SYNC_EXIT
- }
- '''
- }
-
- def private generateInstanceFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
- val nr = ETMapUtil::getNodeRef(ssi)
- '''
- /**
- * @author generated by eTrice
- *
- * Instance File of Node «nr.name» with SubSystem «ssi.name»
- * - instantiation of all actor instances and port instances
- * - configuration of data and connection of ports
- */
-
- #include "messaging/etMessageService.h"
-
- /* include all referenced ActorClasses */
- «FOR actorClass : root.getReferencedActorClasses(ssi.subSystemClass)»
- #include «actorClass.includePath»
- «ENDFOR»
-
- /* include all referenced ProtcolClasses */
- «FOR protocolClass : root.getReferencedProtocolClasses(ssi.subSystemClass)»
- #include «protocolClass.includePath»
- «ENDFOR»
-
- /* instantiation of message services and message buffers */
- «FOR thread: nr.type.threads.filter(t|usedThreads.contains(t))»
- /* «thread.name» */
- #define «thread.name.toUpperCase»_POOL_SIZE «thread.msgpoolsize»
- #define «thread.name.toUpperCase»_BLOCK_SIZE «thread.msgblocksize»
- static uint8 msgBuffer_«thread.name»[«thread.name.toUpperCase»_POOL_SIZE * «thread.name.toUpperCase»_BLOCK_SIZE];
- static etMessageService msgService_«thread.name»;
- «ENDFOR»
-
- /* declarations of all ActorClass instances (const and variable structs) */
-
- /* forward declaration of variable actor structs */
- «FOR ai : ssi.allContainedInstances»
- static «ai.actorClass.name» «ai.path.getPathName()»;
- «ENDFOR»
-
- /* forward declaration of variable port structs */
- «FOR ai: ssi.allContainedInstances»
- «IF ai.orderedIfItemInstances.empty»
- /* nothing to do */
- «ELSE»
- «FOR pi:ai.orderedIfItemInstances»
- «IF pi.protocol.getPortClass(pi.conjugated)?.attributes?.size > 0»
- static «pi.protocol.getPortClassName(pi.conjugated)»_var «pi.path.pathName»_var«IF pi.replicated»[«pi.peers.size»]«ENDIF»={
- «FOR Integer i:1.. if(pi.peers.size==0)1 else pi.peers.size SEPARATOR ', '»
- «attrInitGenAddon.generateAttributeInit(pi, pi.interfaceItem.portClass.attributes)»
- «ENDFOR»};
- «ENDIF»
- «ENDFOR»
- «ENDIF»
- «ENDFOR»
-
- «FOR ai : ssi.allContainedInstances»
-
- /* instance «ai.path.getPathName()» */
- «IF !GlobalGeneratorSettings::generateMSCInstrumentation && ai.orderedIfItemInstances.empty»
- /* no ports/saps/services - nothing to initialize statically */
- «ELSE»
- «genActorInstanceInitializer(root, ai)»
- «ENDIF»
- «ENDFOR»
-
- '''
- }
-
- def private genActorInstanceInitializer(Root root, ActorInstance ai) {
- val instName = ai.path.pathName
-
- // list of replicated interface items (all are event driven ports)
- val replEventItems = new ArrayList<InterfaceItemInstance>()
- replEventItems.addAll(ai.orderedIfItemInstances.filter(e|e.replicated))
- val haveReplSubItems = replEventItems.findFirst(e|!e.peers.empty)!=null
- val replEventPorts = replEventItems.filter(i|i.interfaceItem instanceof Port)
- val replEventSPPs = replEventItems.filter(i|i.interfaceItem instanceof SPPRef)
-
- val simplePorts = ai.orderedIfItemInstances.filter(e|e.simple)
-
- // list of simple event interface items
- val simpleEventItems = new ArrayList<InterfaceItemInstance>()
- simpleEventItems.addAll(simplePorts.filter(p|p.protocol.commType==CommunicationType::EVENT_DRIVEN))
-
- // lists of event driven ports and saps
- val simpleEventPorts = simpleEventItems.filter(i|i.interfaceItem instanceof Port)
- val simpleEventSAPs = simpleEventItems.filter(i|i.interfaceItem instanceof SAPRef)
-
- val dataPorts = simplePorts.filter(p|p.protocol.commType==CommunicationType::DATA_DRIVEN)
- val recvPorts = dataPorts.filter(p|p instanceof PortInstance && !(p as PortInstance).port.conjugated)
- val sendPorts = dataPorts.filter(p|p instanceof PortInstance && (p as PortInstance).port.conjugated)
-
- // compute replicated port offsets
- val offsets = new HashMap<InterfaceItemInstance, Integer>()
- var offset = 0
- for (p: replEventItems) {
- offsets.put(p, offset)
- offset = offset + p.peers.size
- }
-
- var replSubPortsArray = if (haveReplSubItems) instName+"_repl_sub_ports" else "NULL"
- val haveConstData = !simpleEventItems.empty || !recvPorts.empty || !replEventItems.empty
- || GlobalGeneratorSettings::generateMSCInstrumentation
- val sep = new IntelligentSeparator(",");
- '''
- «IF haveReplSubItems»
- static const etReplSubPort «replSubPortsArray»[«offset»] = {
- /* Replicated Sub Ports: {varData, msgService, peerAddress, localId, index} */
- «FOR pi : replEventItems.filter(e|!e.peers.empty) SEPARATOR ","»
- «genReplSubPortInitializers(root, ai, pi)»
- «ENDFOR»
- };
- «ENDIF»
- «IF haveConstData»
- static const «ai.actorClass.name»_const «instName»_const = {
- «IF GlobalGeneratorSettings::generateMSCInstrumentation»
- «sep»"«ai.path»"
-
- «ENDIF»
- /* Ports: {varData, msgService, peerAddress, localId} */
- /* simple ports */
- «FOR pi : simpleEventPorts»
- «sep»«genPortInitializer(root, ai, pi)»
- «ENDFOR»
-
- /* data receive ports */
- «FOR pi : recvPorts»
- «sep»«genRecvPortInitializer(root, ai, pi)»
- «ENDFOR»
-
- /* saps */
- «FOR pi : simpleEventSAPs»
- «sep»«genPortInitializer(root, ai, pi)»
- «ENDFOR»
-
- /* replicated ports */
- «FOR pi : replEventPorts»
- «sep»{«pi.peers.size», «replSubPortsArray»+«offsets.get(pi)»}
- «ENDFOR»
-
- /* services */
- «FOR pi : replEventSPPs»
- «sep»{«pi.peers.size», «replSubPortsArray»+«offsets.get(pi)»}
- «ENDFOR»
- };
- «ENDIF»
- static «ai.actorClass.name» «instName» = {
- «IF haveConstData»
- &«instName»_const,
-
- «ENDIF»
- /* data send ports */
- «FOR pi : sendPorts»
- «pi.genSendPortInitializer»,
- «ENDFOR»
-
- /* attributes */
- «attrInitGenAddon.generateAttributeInit(ai, ai.actorClass.allAttributes)»
-
- /* state and history are initialized in init fuction */
- };
- '''}
-
- def private String genPortInitializer(Root root, ActorInstance ai, InterfaceItemInstance pi) {
- val objId = if (pi.peers.empty) 0 else pi.peers.get(0).objId
- val idx = if (pi.peers.empty) 0 else pi.peers.get(0).peers.indexOf(pi)
- val msgSvc = if (pi.peers.empty) "NULL" else "&msgService_"+ETMapUtil::getPhysicalThread(pi.peers.get(0).eContainer as ActorInstance).name
- val myInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) ",\""+(pi.eContainer as ActorInstance).path+"\","
- else ""
- val peerInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) "\""+(pi.peers.get(0).eContainer as ActorInstance).path+"\""
- else ""
-
- "{"+getInterfaceItemInstanceData(pi)+", "
- +msgSvc+", "
- +(objId+idx)+"+BASE_ADDRESS, "
- +(root.getExpandedActorClass(ai).getInterfaceItemLocalId(pi.interfaceItem)+1)
- +myInst
- +peerInst
- +"} /* Port "+pi.name+" */"
- }
-
- def private genSendPortInitializer(InterfaceItemInstance pi) {
- val pc = (pi as PortInstance).port.protocol as ProtocolClass
-
- '''
- {
- «FOR m : pc.incomingMessages SEPARATOR ","»
- «m.data.refType.type.defaultValue»
- «ENDFOR»
- } /* send port «pi.name» */
- '''
- }
-
- def private getInterfaceItemInstanceData(InterfaceItemInstance pi){
- if (pi.protocol.getPortClass(pi.conjugated)== null) return "NULL"
- if (pi.protocol.getPortClass(pi.conjugated).attributes.empty){
- return "NULL"
- }else{
- return "&"+pi.path.pathName+"_var"
- }
- }
-
-
- def private String genRecvPortInitializer(Root root, ActorInstance ai, InterfaceItemInstance pi) {
- if (pi.peers.empty)
- return "{NULL}"
-
- var peer = pi.peers.get(0)
- var peerInst = pi.peers.get(0).eContainer() as ActorInstance
- var instName = peerInst.path.pathName
-
- "{&"+instName+"."+peer.name+"}"
- }
-
- def private String genReplSubPortInitializers(Root root, ActorInstance ai, InterfaceItemInstance pi) {
- var result = ""
- val myInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) ",\""+(pi.eContainer as ActorInstance).path+"\","
- else ""
-
- for (p: pi.peers) {
- val idx = pi.peers.indexOf(p)
- val comma = if (idx<pi.peers.size-1) "," else ""
- val thread = ETMapUtil::getPhysicalThread(p.eContainer as ActorInstance).name
- var iiiD = getInterfaceItemInstanceData(pi)
- val peerInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) "\""+(p.eContainer as ActorInstance).path+"\""
- else ""
- iiiD = if (iiiD.equals("NULL")) iiiD+"," else iiiD+"["+idx+"],"
- result = result +
- "{{"+iiiD
- +"&msgService_"+thread+", "
- +p.objId+"+BASE_ADDRESS, "
- +(root.getExpandedActorClass(ai).getInterfaceItemLocalId(pi.interfaceItem)+1)
- +myInst
- +peerInst
- +"},"
- +idx
- +"}"+comma+" /* Repl Sub Port "+pi.name+" idx +"+idx+"*/\n"
- }
-
- return result
- }
-
- def private generateDispatcherFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
- val nr = ETMapUtil::getNodeRef(ssi)
-
- '''
- /**
- * @author generated by eTrice
- *
- * Dispatcher File of Node «nr.name» with SubSystem «ssi.name»
- * - one generated message dispatcher (receiveMessage) for each MessageService (Thread)
- * - one generated execute dispatcher (execute) for each MessageService (Thread)
- */
-
- #include "messaging/etMessageReceiver.h"
- #include "debugging/etLogger.h"
- #include "debugging/etMSCLogger.h"
-
- «FOR thread: nr.type.threads.filter(t|usedThreads.contains(t)) SEPARATOR "\n"»
- «val instancesOnThread = ssi.allContainedInstances.filter(ai|ETMapUtil::getPhysicalThread(ai)==thread)»
- «val dispatchedInstances = instancesOnThread.filter(ai|ai.actorClass.commType == ActorCommunicationType::EVENT_DRIVEN || ai.actorClass.commType == ActorCommunicationType::ASYNCHRONOUS)»
- «val executedInstances = instancesOnThread.filter(ai|ai.actorClass.commType == ActorCommunicationType::DATA_DRIVEN || ai.actorClass.commType == ActorCommunicationType::ASYNCHRONOUS)»
-
- «IF executedInstances.size > 0»
- /**
- * generated execute function for all cyclic execute calls for the async or datadriven actor instances of thread "«thread.name»"
- */
- static void MsgDispatcher_«thread.name»_poll(void){
- ET_MSC_LOGGER_SYNC_ENTRY("MsgDispatcher_«thread.name»", "execute")
- «FOR ai : executedInstances»
- «ai.actorClass.name»_execute((void*)&«ai.path.pathName»);
- «ENDFOR»
- ET_MSC_LOGGER_SYNC_EXIT
- }
- «ENDIF»
-
- /**
- * generated dispatch function for all messages for the thread "«thread.name»"
- */
- static etBool MsgDispatcher_«thread.name»_receiveMessage(const etMessage* msg){
- ET_MSC_LOGGER_SYNC_ENTRY("MsgDispatcher_«thread.name»", "receiveMessage")
- switch(msg->address){
-
- case MESSAGESERVICE_ADDRESS:
- «IF !executedInstances.empty»
- if (msg->evtID == etSystemProtocol_IN_poll)
- MsgDispatcher_«thread.name»_poll();
- else
- «ENDIF»
- if (msg->evtID == etSystemProtocol_IN_terminate)
- return FALSE;
- break;
- «FOR ai : dispatchedInstances»
-
- /* interface items of «ai.path» */
- «FOR pi : ai. orderedIfItemInstances.filter(p|p.protocol.commType==CommunicationType::EVENT_DRIVEN)»
- «IF pi.replicated»
- «FOR peer: pi.peers»
- case «pi.objId+pi.peers.indexOf(peer)»+BASE_ADDRESS:
- «IF (pi.protocol.handlesReceive(pi.isConjugated()))»
- switch (msg->evtID){
- «FOR h:getReceiveHandlers(pi.protocol,pi.isConjugated())»
- case «pi.protocol.name»_«h.msg.codeName»:
- «pi.protocol.getPortClassName(pi.isConjugated)»_«h.msg.name»_receiveHandler((etPort *)&«ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»],msg,(void*)&«ai.path.pathName»,«ai.actorClass.name»_receiveMessage);
- break;
- «ENDFOR»
- default: «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,(etPort*)&«ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»], msg);
- break;
- }
- «ELSE»
- «IF GlobalGeneratorSettings::generateMSCInstrumentation»
- ET_MSC_LOGGER_ASYNC_IN(
- «ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»].port.peerInstName,
- «pi.protocol.name»_getMessageString(msg->evtID),
- «ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»].port.myInstName
- )
- «ENDIF»
- «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,&«ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»].port, msg);
- «ENDIF»
- break;
- «ENDFOR»
- «ELSE»
- case «pi.objId»+BASE_ADDRESS:
- «IF (pi.protocol.handlesReceive(pi.isConjugated()))»
- switch (msg->evtID){
- «FOR h:getReceiveHandlers(pi.protocol,pi.isConjugated())»
- case «pi.protocol.name»_«h.msg.codeName»:
- «pi.protocol.getPortClassName(pi.isConjugated)»_«h.msg.name»_receiveHandler((etPort *)&«ai.path.pathName»_const.«pi.name»,msg,(void*)&«ai.path.pathName»,«ai.actorClass.name»_receiveMessage);
- break;
- «ENDFOR»
- default: «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,(etPort*)&«ai.path.pathName»_const.«pi.name», msg);
- break;
- }
- «ELSE»
- «IF GlobalGeneratorSettings::generateMSCInstrumentation»
- ET_MSC_LOGGER_ASYNC_IN(
- ((etPort*)&«ai.path.pathName»_const.«pi.name»)->peerInstName,
- «pi.protocol.name»_getMessageString(msg->evtID),
- ((etPort*)&«ai.path.pathName»_const.«pi.name»)->myInstName
- )
- «ENDIF»
- «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,(etPort*)&«ai.path.pathName»_const.«pi.name», msg);
- «ENDIF»
- break;
- «ENDIF»
- «ENDFOR»
- «ENDFOR»
-
- default:
- etLogger_logErrorF("MessageService_«thread.name»_receiveMessage: address %d does not exist ", msg->address);
- break;
- }
- ET_MSC_LOGGER_SYNC_EXIT
- return TRUE;
- }
- «ENDFOR»
- '''
- }
-
- def private checkDataPorts(SubSystemInstance comp) {
- val found = new HashSet<String>()
- for (ai: comp.allContainedInstances) {
- val thread = ai.threadId
- for (pi: ai.orderedIfItemInstances) {
- if (pi.protocol.commType==CommunicationType::DATA_DRIVEN) {
- for (peer: pi.peers) {
- val peer_ai = peer.eContainer as ActorInstance
- val peer_thread = peer_ai.threadId
- if (thread!=peer_thread) {
- val path = pi.path
- val ppath = peer.path
- val pair = if (path.compareTo(ppath)<0) path+" and "+ppath
- else ppath+" and "+path
- if (!found.contains(pair)) {
- found.add(pair)
- diagnostician.error(pair+": data ports placed on different threads (not supported yet)",
- pi.interfaceItem, pi.interfaceItem.eContainingFeature)
- }
- }
- }
- }
- }
- }
- }
-}
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ * Thomas Schuetz (changed for C code generator)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.generator.c.gen
+
+import com.google.inject.Inject
+import com.google.inject.Singleton
+import java.util.ArrayList
+import java.util.HashMap
+import java.util.HashSet
+import org.eclipse.etrice.core.etmap.util.ETMapUtil
+import org.eclipse.etrice.core.etphys.eTPhys.ExecMode
+import org.eclipse.etrice.core.etphys.eTPhys.PhysicalThread
+import org.eclipse.etrice.core.genmodel.etricegen.ActorInstance
+import org.eclipse.etrice.core.genmodel.etricegen.IDiagnostician
+import org.eclipse.etrice.core.genmodel.etricegen.InterfaceItemInstance
+import org.eclipse.etrice.core.genmodel.etricegen.PortInstance
+import org.eclipse.etrice.core.genmodel.etricegen.Root
+import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance
+import org.eclipse.etrice.core.room.ActorCommunicationType
+import org.eclipse.etrice.core.room.CommunicationType
+import org.eclipse.etrice.core.room.Port
+import org.eclipse.etrice.core.room.ProtocolClass
+import org.eclipse.etrice.core.room.SAPRef
+import org.eclipse.etrice.core.room.SPPRef
+import org.eclipse.etrice.generator.base.IGeneratorFileIo
+import org.eclipse.etrice.generator.base.IntelligentSeparator
+import org.eclipse.etrice.generator.generic.ILanguageExtension
+import org.eclipse.etrice.generator.generic.ProcedureHelpers
+import org.eclipse.etrice.generator.generic.RoomExtensions
+
+import static extension org.eclipse.etrice.core.room.util.RoomHelpers.*
+import org.eclipse.etrice.generator.base.GlobalGeneratorSettings
+
+@Singleton
+class NodeGen {
+
+ @Inject extension CExtensions
+ @Inject extension RoomExtensions
+ @Inject extension ProcedureHelpers helpers
+
+ @Inject IGeneratorFileIo fileIO
+ @Inject Initialization attrInitGenAddon
+ @Inject ILanguageExtension languageExt
+ @Inject IDiagnostician diagnostician
+
+ def doGenerate(Root root) {
+ for (nr : ETMapUtil::getNodeRefs()) {
+ for (instpath : ETMapUtil::getSubSystemInstancePaths(nr)) {
+ val ssi = root.getInstance(instpath) as SubSystemInstance
+ val filepath = ssi.subSystemClass.generationTargetPath+ssi.subSystemClass.getPath
+ val infopath = ssi.subSystemClass.generationInfoPath+ssi.subSystemClass.getPath
+ var file = nr.getCHeaderFileName(ssi)
+
+ checkDataPorts(ssi)
+
+ val usedThreads = new HashSet<PhysicalThread>();
+ for (thread: nr.type.threads) {
+ val instancesOnThread = ssi.allContainedInstances.filter(ai|ETMapUtil::getPhysicalThread(ai)==thread)
+ if (!instancesOnThread.empty)
+ usedThreads.add(thread)
+ }
+
+ fileIO.generateFile("generating Node declaration", filepath, infopath, file, root.generateHeaderFile(ssi))
+
+ file = nr.getCSourceFileName(ssi)
+ fileIO.generateFile("generating Node implementation", filepath, infopath, file, root.generateSourceFile(ssi, usedThreads))
+
+ file = nr.getInstSourceFileName(ssi)
+ fileIO.generateFile("generating Node instance file", filepath, infopath, file, root.generateInstanceFile(ssi, usedThreads))
+
+ file = nr.getDispSourceFileName(ssi)
+ fileIO.generateFile("generating Node dispatcher file", filepath, infopath, file, root.generateDispatcherFile(ssi, usedThreads))
+ }
+ }
+ }
+
+ def private generateHeaderFile(Root root, SubSystemInstance ssi) {
+ val nr = ETMapUtil::getNodeRef(ssi)
+ val ssc = ssi.subSystemClass
+ val clsname = nr.name+"_"+ssi.name
+ '''
+ /**
+ * @author generated by eTrice
+ *
+ * Header File of Node «nr.name» with SubSystem «ssi.name»
+ *
+ */
+
+ «generateIncludeGuardBegin(clsname)»
+
+ #include "etDatatypes.h"
+
+««« TODOCGENPHYS: user code?
+ «helpers.userCode(ssc.userCode1)»
+
+
+ /* lifecycle functions
+ * init -> start -> run (loop) -> stop -> destroy
+ */
+
+ void «clsname»_init(void); /* lifecycle init */
+ void «clsname»_start(void); /* lifecycle start */
+
+ void «clsname»_run(etBool runAsTest); /* lifecycle run */
+
+ void «clsname»_stop(void); /* lifecycle stop */
+ void «clsname»_destroy(void); /* lifecycle destroy */
+
+ void «clsname»_shutdown(void); /* shutdown the dispatcher loop */
+
+««« TODOCGENPHYS: user code?
+ «helpers.userCode(ssc.userCode2)»
+
+ «generateIncludeGuardEnd(clsname)»
+
+
+ '''
+ }
+
+ def private generateSourceFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
+ val nr = ETMapUtil::getNodeRef(ssi)
+ val ssc = ssi.subSystemClass
+ val clsname = nr.name+"_"+ssi.name
+ val threads = nr.type.threads.filter(t|usedThreads.contains(t))
+ '''
+ /**
+ * @author generated by eTrice
+ *
+ * Source File of Node «nr.name» with SubSystem «ssi.name»
+ *
+ */
+
+ #include <stdio.h>
+
+ #include "«nr.getCHeaderFileName(ssi)»"
+
+ #include "debugging/etLogger.h"
+ #include "debugging/etMSCLogger.h"
+ #include "messaging/etSystemProtocol.h"
+ #include "osal/etTimer.h"
+ #include "osal/etSema.h"
+ #include "runtime/etRuntime.h"
+ #include "etRuntimeConfig.h"
+
+««« TODOCGENPHYS: user code?
+ «helpers.userCode(ssc.userCode3)»
+
+ /* data for Node «nr.name» with SubSystem «ssi.name» */
+ typedef struct «clsname» {
+ char *name;
+ volatile int shutdownRequest;
+ } «clsname»;
+
+ static «clsname» «clsname»Inst = {"«clsname»", 0};
+
+ static void «clsname»_initActorInstances(void);
+ static void «clsname»_constructActorInstances(void);
+
+ /* include instances for all classes */
+ #include "«nr.getInstSourceFileName(ssi)»"
+ #include "«nr.getDispSourceFileName(ssi)»"
+
+ static void «clsname»_initMessageServices(void) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "initMessageServices")
+ {
+ etTime interval;
+
+ /* initialization of all message services */
+ «FOR thread: threads»
+ «IF thread.execmode==ExecMode::POLLED || thread.execmode==ExecMode::MIXED»
+««« interval.sec = «thread.sec» <-- use convenience functions to split time in sec and nsec
+ interval.sec = 0;
+ interval.nSec = «thread.time»;
+ «ENDIF»
+ etMessageService_init(
+ &msgService_«thread.name»,
+ msgBuffer_«thread.name»,
+ «thread.name.toUpperCase»_POOL_SIZE,
+ «thread.name.toUpperCase»_BLOCK_SIZE,
+ «thread.stacksize»,
+ «thread.prio»,
+ interval,
+ MsgDispatcher_«thread.name»_receiveMessage,
+ EXECMODE_«thread.execmode.toString.toUpperCase»);
+
+ «ENDFOR»
+ }
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ static void «clsname»_startMessageServices(void) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "startMessageServices")
+
+ «FOR thread: threads»
+ etMessageService_start(&msgService_«thread.name»);
+ «ENDFOR»
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ static void «clsname»_stopMessageServices(void) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "stopMessageServices")
+
+ «FOR thread: threads»
+ etMessageService_stop(&msgService_«thread.name»);
+ «ENDFOR»
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ static void «clsname»_destroyMessageServices(void) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "destroyMessageServices")
+
+ «FOR thread: threads»
+ etMessageService_destroy(&msgService_«thread.name»);
+ «ENDFOR»
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ void «clsname»_init(void) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "init")
+ etLogger_logInfoF("%s_init", «clsname»Inst.name);
+
+ /* construct all actors */
+ «clsname»_constructActorInstances();
+
+ /* initialization of all message services */
+ «clsname»_initMessageServices();
+
+ /* init all actors */
+ «clsname»_initActorInstances();
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ void «clsname»_start(void) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "start")
+ etLogger_logInfoF("%s_start", «clsname»Inst.name);
+ «clsname»_startMessageServices();
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ void «clsname»_run(etBool runAsTest) {
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "run")
+
+ if (runAsTest) {
+ etSema_waitForWakeup(etRuntime_getTerminateSemaphore());
+ }
+ else {
+ printf("type quit to exit\n");
+ fflush(stdout);
+ while (TRUE) {
+ char line[64];
+
+ if (fgets(line, 64, stdin) == NULL) {
+ printf("got NULL\n");
+ break;
+ }
+ else if (strncmp(line, "quit", 4)==0){
+ break;
+ }
+ }
+ }
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ void «clsname»_stop(void){
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "stop")
+ etLogger_logInfoF("%s_stop", «clsname»Inst.name);
+
+ «clsname»_stopMessageServices();
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ void «clsname»_destroy(void){
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "destroy")
+ etLogger_logInfoF("%s_destroy", «clsname»Inst.name);
+ «FOR ai : ssi.allContainedInstances.reverseView»
+ «IF !ai.actorClass.operations.filter(op|op.destructor).empty»
+ «languageExt.memberInUse(ai.actorClass.name, languageExt.destructorName(ai.actorClass.name))»(&«ai.path.getPathName()»);
+ «ENDIF»
+ «ENDFOR»
+
+ «clsname»_destroyMessageServices();
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ void «clsname»_shutdown(void){
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "shutdown")
+ etLogger_logInfoF("%s_shutdown", «clsname»Inst.name);
+
+ «clsname»Inst.shutdownRequest = 1;
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+
+ static void «clsname»_constructActorInstances(void){
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "constructActorInstances")
+
+ «FOR ai : ssi.allContainedInstances»
+ «IF !ai.actorClass.operations.filter(op|op.constructor).empty»
+ «languageExt.memberInUse(ai.actorClass.name, languageExt.constructorName(ai.actorClass.name))»(&«ai.path.getPathName()»);
+ «ENDIF»
+ «ENDFOR»
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+
+ static void «clsname»_initActorInstances(void){
+ ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "initActorInstances")
+
+ «FOR ai : ssi.allContainedInstances»
+ «ai.actorClass.name»_init(&«ai.path.getPathName()»);
+ «ENDFOR»
+
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+ '''
+ }
+
+ def private generateInstanceFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
+ val nr = ETMapUtil::getNodeRef(ssi)
+ '''
+ /**
+ * @author generated by eTrice
+ *
+ * Instance File of Node «nr.name» with SubSystem «ssi.name»
+ * - instantiation of all actor instances and port instances
+ * - configuration of data and connection of ports
+ */
+
+ #include "messaging/etMessageService.h"
+
+ /* include all referenced ActorClasses */
+ «FOR actorClass : root.getReferencedActorClasses(ssi.subSystemClass)»
+ #include «actorClass.includePath»
+ «ENDFOR»
+
+ /* include all referenced ProtcolClasses */
+ «FOR protocolClass : root.getReferencedProtocolClasses(ssi.subSystemClass)»
+ #include «protocolClass.includePath»
+ «ENDFOR»
+
+ /* instantiation of message services and message buffers */
+ «FOR thread: nr.type.threads.filter(t|usedThreads.contains(t))»
+ /* «thread.name» */
+ #define «thread.name.toUpperCase»_POOL_SIZE «thread.msgpoolsize»
+ #define «thread.name.toUpperCase»_BLOCK_SIZE «thread.msgblocksize»
+ static uint8 msgBuffer_«thread.name»[«thread.name.toUpperCase»_POOL_SIZE * «thread.name.toUpperCase»_BLOCK_SIZE];
+ static etMessageService msgService_«thread.name»;
+ «ENDFOR»
+
+ /* declarations of all ActorClass instances (const and variable structs) */
+
+ /* forward declaration of variable actor structs */
+ «FOR ai : ssi.allContainedInstances»
+ static «ai.actorClass.name» «ai.path.getPathName()»;
+ «ENDFOR»
+
+ /* forward declaration of variable port structs */
+ «FOR ai: ssi.allContainedInstances»
+ «IF ai.orderedIfItemInstances.empty»
+ /* nothing to do */
+ «ELSE»
+ «FOR pi:ai.orderedIfItemInstances»
+ «IF pi.protocol.getPortClass(pi.conjugated)?.attributes?.size > 0»
+ static «pi.protocol.getPortClassName(pi.conjugated)»_var «pi.path.pathName»_var«IF pi.replicated»[«pi.peers.size»]«ENDIF»={
+ «FOR Integer i:1.. if(pi.peers.size==0)1 else pi.peers.size SEPARATOR ', '»
+ «attrInitGenAddon.generateAttributeInit(pi, pi.interfaceItem.portClass.attributes)»
+ «ENDFOR»};
+ «ENDIF»
+ «ENDFOR»
+ «ENDIF»
+ «ENDFOR»
+
+ «FOR ai : ssi.allContainedInstances»
+
+ /* instance «ai.path.getPathName()» */
+ «IF !GlobalGeneratorSettings::generateMSCInstrumentation && ai.orderedIfItemInstances.empty»
+ /* no ports/saps/services - nothing to initialize statically */
+ «ELSE»
+ «genActorInstanceInitializer(root, ai)»
+ «ENDIF»
+ «ENDFOR»
+
+ '''
+ }
+
+ def private genActorInstanceInitializer(Root root, ActorInstance ai) {
+ val instName = ai.path.pathName
+
+ // list of replicated interface items (all are event driven ports)
+ val replEventItems = new ArrayList<InterfaceItemInstance>()
+ replEventItems.addAll(ai.orderedIfItemInstances.filter(e|e.replicated))
+ val haveReplSubItems = replEventItems.findFirst(e|!e.peers.empty)!=null
+ val replEventPorts = replEventItems.filter(i|i.interfaceItem instanceof Port)
+ val replEventSPPs = replEventItems.filter(i|i.interfaceItem instanceof SPPRef)
+
+ val simplePorts = ai.orderedIfItemInstances.filter(e|e.simple)
+
+ // list of simple event interface items
+ val simpleEventItems = new ArrayList<InterfaceItemInstance>()
+ simpleEventItems.addAll(simplePorts.filter(p|p.protocol.commType==CommunicationType::EVENT_DRIVEN))
+
+ // lists of event driven ports and saps
+ val simpleEventPorts = simpleEventItems.filter(i|i.interfaceItem instanceof Port)
+ val simpleEventSAPs = simpleEventItems.filter(i|i.interfaceItem instanceof SAPRef)
+
+ val dataPorts = simplePorts.filter(p|p.protocol.commType==CommunicationType::DATA_DRIVEN)
+ val recvPorts = dataPorts.filter(p|p instanceof PortInstance && !(p as PortInstance).port.conjugated)
+ val sendPorts = dataPorts.filter(p|p instanceof PortInstance && (p as PortInstance).port.conjugated)
+
+ // compute replicated port offsets
+ val offsets = new HashMap<InterfaceItemInstance, Integer>()
+ var offset = 0
+ for (p: replEventItems) {
+ offsets.put(p, offset)
+ offset = offset + p.peers.size
+ }
+
+ var replSubPortsArray = if (haveReplSubItems) instName+"_repl_sub_ports" else "NULL"
+ val haveConstData = !simpleEventItems.empty || !recvPorts.empty || !replEventItems.empty
+ || GlobalGeneratorSettings::generateMSCInstrumentation
+ val sep = new IntelligentSeparator(",");
+ '''
+ «IF haveReplSubItems»
+ static const etReplSubPort «replSubPortsArray»[«offset»] = {
+ /* Replicated Sub Ports: {varData, msgService, peerAddress, localId, index} */
+ «FOR pi : replEventItems.filter(e|!e.peers.empty) SEPARATOR ","»
+ «genReplSubPortInitializers(root, ai, pi)»
+ «ENDFOR»
+ };
+ «ENDIF»
+ «IF haveConstData»
+ static const «ai.actorClass.name»_const «instName»_const = {
+ «IF GlobalGeneratorSettings::generateMSCInstrumentation»
+ «sep»"«ai.path»"
+
+ «ENDIF»
+ /* Ports: {varData, msgService, peerAddress, localId} */
+ /* simple ports */
+ «FOR pi : simpleEventPorts»
+ «sep»«genPortInitializer(root, ai, pi)»
+ «ENDFOR»
+
+ /* data receive ports */
+ «FOR pi : recvPorts»
+ «sep»«genRecvPortInitializer(root, ai, pi)»
+ «ENDFOR»
+
+ /* saps */
+ «FOR pi : simpleEventSAPs»
+ «sep»«genPortInitializer(root, ai, pi)»
+ «ENDFOR»
+
+ /* replicated ports */
+ «FOR pi : replEventPorts»
+ «sep»{«pi.peers.size», «replSubPortsArray»+«offsets.get(pi)»}
+ «ENDFOR»
+
+ /* services */
+ «FOR pi : replEventSPPs»
+ «sep»{«pi.peers.size», «replSubPortsArray»+«offsets.get(pi)»}
+ «ENDFOR»
+ };
+ «ENDIF»
+ static «ai.actorClass.name» «instName» = {
+ «IF haveConstData»
+ &«instName»_const,
+
+ «ENDIF»
+ /* data send ports */
+ «FOR pi : sendPorts»
+ «pi.genSendPortInitializer»,
+ «ENDFOR»
+
+ /* attributes */
+ «attrInitGenAddon.generateAttributeInit(ai, ai.actorClass.allAttributes)»
+
+ /* state and history are initialized in init fuction */
+ };
+ '''}
+
+ def private String genPortInitializer(Root root, ActorInstance ai, InterfaceItemInstance pi) {
+ val objId = if (pi.peers.empty) 0 else pi.peers.get(0).objId
+ val idx = if (pi.peers.empty) 0 else pi.peers.get(0).peers.indexOf(pi)
+ val msgSvc = if (pi.peers.empty) "NULL" else "&msgService_"+ETMapUtil::getPhysicalThread(pi.peers.get(0).eContainer as ActorInstance).name
+ val myInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) ",\""+(pi.eContainer as ActorInstance).path+"\","
+ else ""
+ val peerInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) "\""+(pi.peers.get(0).eContainer as ActorInstance).path+"\""
+ else ""
+
+ "{"+getInterfaceItemInstanceData(pi)+", "
+ +msgSvc+", "
+ +(objId+idx)+"+BASE_ADDRESS, "
+ +(root.getExpandedActorClass(ai).getInterfaceItemLocalId(pi.interfaceItem)+1)
+ +myInst
+ +peerInst
+ +"} /* Port "+pi.name+" */"
+ }
+
+ def private genSendPortInitializer(InterfaceItemInstance pi) {
+ val pc = (pi as PortInstance).port.protocol as ProtocolClass
+
+ '''
+ {
+ «FOR m : pc.incomingMessages SEPARATOR ","»
+ «m.data.refType.type.defaultValue»
+ «ENDFOR»
+ } /* send port «pi.name» */
+ '''
+ }
+
+ def private getInterfaceItemInstanceData(InterfaceItemInstance pi){
+ if (pi.protocol.getPortClass(pi.conjugated)== null) return "NULL"
+ if (pi.protocol.getPortClass(pi.conjugated).attributes.empty){
+ return "NULL"
+ }else{
+ return "&"+pi.path.pathName+"_var"
+ }
+ }
+
+
+ def private String genRecvPortInitializer(Root root, ActorInstance ai, InterfaceItemInstance pi) {
+ if (pi.peers.empty)
+ return "{NULL}"
+
+ var peer = pi.peers.get(0)
+ var peerInst = pi.peers.get(0).eContainer() as ActorInstance
+ var instName = peerInst.path.pathName
+
+ "{&"+instName+"."+peer.name+"}"
+ }
+
+ def private String genReplSubPortInitializers(Root root, ActorInstance ai, InterfaceItemInstance pi) {
+ var result = ""
+ val myInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) ",\""+(pi.eContainer as ActorInstance).path+"\","
+ else ""
+
+ for (p: pi.peers) {
+ val idx = pi.peers.indexOf(p)
+ val comma = if (idx<pi.peers.size-1) "," else ""
+ val thread = ETMapUtil::getPhysicalThread(p.eContainer as ActorInstance).name
+ var iiiD = getInterfaceItemInstanceData(pi)
+ val peerInst = if (GlobalGeneratorSettings::generateMSCInstrumentation) "\""+(p.eContainer as ActorInstance).path+"\""
+ else ""
+ iiiD = if (iiiD.equals("NULL")) iiiD+"," else iiiD+"["+idx+"],"
+ result = result +
+ "{{"+iiiD
+ +"&msgService_"+thread+", "
+ +p.objId+"+BASE_ADDRESS, "
+ +(root.getExpandedActorClass(ai).getInterfaceItemLocalId(pi.interfaceItem)+1)
+ +myInst
+ +peerInst
+ +"},"
+ +idx
+ +"}"+comma+" /* Repl Sub Port "+pi.name+" idx +"+idx+"*/\n"
+ }
+
+ return result
+ }
+
+ def private generateDispatcherFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
+ val nr = ETMapUtil::getNodeRef(ssi)
+
+ '''
+ /**
+ * @author generated by eTrice
+ *
+ * Dispatcher File of Node «nr.name» with SubSystem «ssi.name»
+ * - one generated message dispatcher (receiveMessage) for each MessageService (Thread)
+ * - one generated execute dispatcher (execute) for each MessageService (Thread)
+ */
+
+ #include "messaging/etMessageReceiver.h"
+ #include "debugging/etLogger.h"
+ #include "debugging/etMSCLogger.h"
+
+ «FOR thread: nr.type.threads.filter(t|usedThreads.contains(t)) SEPARATOR "\n"»
+ «val instancesOnThread = ssi.allContainedInstances.filter(ai|ETMapUtil::getPhysicalThread(ai)==thread)»
+ «val dispatchedInstances = instancesOnThread.filter(ai|ai.actorClass.commType == ActorCommunicationType::EVENT_DRIVEN || ai.actorClass.commType == ActorCommunicationType::ASYNCHRONOUS)»
+ «val executedInstances = instancesOnThread.filter(ai|ai.actorClass.commType == ActorCommunicationType::DATA_DRIVEN || ai.actorClass.commType == ActorCommunicationType::ASYNCHRONOUS)»
+
+ «IF executedInstances.size > 0»
+ /**
+ * generated execute function for all cyclic execute calls for the async or datadriven actor instances of thread "«thread.name»"
+ */
+ static void MsgDispatcher_«thread.name»_poll(void){
+ ET_MSC_LOGGER_SYNC_ENTRY("MsgDispatcher_«thread.name»", "execute")
+ «FOR ai : executedInstances»
+ «ai.actorClass.name»_execute((void*)&«ai.path.pathName»);
+ «ENDFOR»
+ ET_MSC_LOGGER_SYNC_EXIT
+ }
+ «ENDIF»
+
+ /**
+ * generated dispatch function for all messages for the thread "«thread.name»"
+ */
+ static etBool MsgDispatcher_«thread.name»_receiveMessage(const etMessage* msg){
+ ET_MSC_LOGGER_SYNC_ENTRY("MsgDispatcher_«thread.name»", "receiveMessage")
+ switch(msg->address){
+
+ case MESSAGESERVICE_ADDRESS:
+ «IF !executedInstances.empty»
+ if (msg->evtID == etSystemProtocol_IN_poll)
+ MsgDispatcher_«thread.name»_poll();
+ else
+ «ENDIF»
+ if (msg->evtID == etSystemProtocol_IN_terminate)
+ return FALSE;
+ break;
+ «FOR ai : dispatchedInstances»
+
+ /* interface items of «ai.path» */
+ «FOR pi : ai. orderedIfItemInstances.filter(p|p.protocol.commType==CommunicationType::EVENT_DRIVEN)»
+ «IF pi.replicated»
+ «FOR peer: pi.peers»
+ case «pi.objId+pi.peers.indexOf(peer)»+BASE_ADDRESS:
+ «IF (pi.protocol.handlesReceive(pi.isConjugated()))»
+ switch (msg->evtID){
+ «FOR h:getReceiveHandlers(pi.protocol,pi.isConjugated())»
+ case «pi.protocol.name»_«h.msg.codeName»:
+ «pi.protocol.getPortClassName(pi.isConjugated)»_«h.msg.name»_receiveHandler((etPort *)&«ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»],msg,(void*)&«ai.path.pathName»,«ai.actorClass.name»_receiveMessage);
+ break;
+ «ENDFOR»
+ default: «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,(etPort*)&«ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»], msg);
+ break;
+ }
+ «ELSE»
+ «IF GlobalGeneratorSettings::generateMSCInstrumentation»
+ ET_MSC_LOGGER_ASYNC_IN(
+ «ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»].port.peerInstName,
+ «pi.protocol.name»_getMessageString(msg->evtID),
+ «ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»].port.myInstName
+ )
+ «ENDIF»
+ «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,&«ai.path.pathName»_const.«pi.name».ports[«pi.peers.indexOf(peer)»].port, msg);
+ «ENDIF»
+ break;
+ «ENDFOR»
+ «ELSE»
+ case «pi.objId»+BASE_ADDRESS:
+ «IF (pi.protocol.handlesReceive(pi.isConjugated()))»
+ switch (msg->evtID){
+ «FOR h:getReceiveHandlers(pi.protocol,pi.isConjugated())»
+ case «pi.protocol.name»_«h.msg.codeName»:
+ «pi.protocol.getPortClassName(pi.isConjugated)»_«h.msg.name»_receiveHandler((etPort *)&«ai.path.pathName»_const.«pi.name»,msg,(void*)&«ai.path.pathName»,«ai.actorClass.name»_receiveMessage);
+ break;
+ «ENDFOR»
+ default: «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,(etPort*)&«ai.path.pathName»_const.«pi.name», msg);
+ break;
+ }
+ «ELSE»
+ «IF GlobalGeneratorSettings::generateMSCInstrumentation»
+ ET_MSC_LOGGER_ASYNC_IN(
+ ((etPort*)&«ai.path.pathName»_const.«pi.name»)->peerInstName,
+ «pi.protocol.name»_getMessageString(msg->evtID),
+ ((etPort*)&«ai.path.pathName»_const.«pi.name»)->myInstName
+ )
+ «ENDIF»
+ «ai.actorClass.name»_receiveMessage((void*)&«ai.path.pathName»,(etPort*)&«ai.path.pathName»_const.«pi.name», msg);
+ «ENDIF»
+ break;
+ «ENDIF»
+ «ENDFOR»
+ «ENDFOR»
+
+ default:
+ etLogger_logErrorF("MessageService_«thread.name»_receiveMessage: address %d does not exist ", msg->address);
+ break;
+ }
+ ET_MSC_LOGGER_SYNC_EXIT
+ return TRUE;
+ }
+ «ENDFOR»
+ '''
+ }
+
+ def private checkDataPorts(SubSystemInstance comp) {
+ val found = new HashSet<String>()
+ for (ai: comp.allContainedInstances) {
+ val thread = ai.threadId
+ for (pi: ai.orderedIfItemInstances) {
+ if (pi.protocol.commType==CommunicationType::DATA_DRIVEN) {
+ for (peer: pi.peers) {
+ val peer_ai = peer.eContainer as ActorInstance
+ val peer_thread = peer_ai.threadId
+ if (thread!=peer_thread) {
+ val path = pi.path
+ val ppath = peer.path
+ val pair = if (path.compareTo(ppath)<0) path+" and "+ppath
+ else ppath+" and "+path
+ if (!found.contains(pair)) {
+ found.add(pair)
+ diagnostician.error(pair+": data ports placed on different threads (not supported yet)",
+ pi.interfaceItem, pi.interfaceItem.eContainingFeature)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}

Back to the top