Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rentz-Reichert2013-05-08 07:18:33 +0000
committerHenrik Rentz-Reichert2013-05-08 07:18:33 +0000
commitdc717ef8ba86ade2257e9edbaad0b7e674e16516 (patch)
treecaaa3ea041b179c90e0e51c5c164d45f54c02867 /plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/NodeGen.xtend
parentf66b6409a314363934f9b4e5c7bc484116ec739e (diff)
downloadorg.eclipse.etrice-dc717ef8ba86ade2257e9edbaad0b7e674e16516.tar.gz
org.eclipse.etrice-dc717ef8ba86ade2257e9edbaad0b7e674e16516.tar.xz
org.eclipse.etrice-dc717ef8ba86ade2257e9edbaad0b7e674e16516.zip
[generator.c] bug 402275: Implementation of Codegenerator and C-Runtime for physical model
https://bugs.eclipse.org/bugs/show_bug.cgi?id=402275
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.xtend225
1 files changed, 144 insertions, 81 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 6f90198ed..810536396 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
@@ -34,6 +34,13 @@ import org.eclipse.xtext.generator.JavaIoFileSystemAccess
import static extension org.eclipse.etrice.core.room.util.RoomHelpers.*
import org.eclipse.etrice.core.etphys.eTPhys.ExecMode
+import org.eclipse.etrice.core.room.Port
+import org.eclipse.etrice.core.room.SPPRef
+import org.eclipse.etrice.core.room.SAPRef
+import org.eclipse.etrice.generator.base.IntelligentSeparator
+import java.util.HashSet
+import org.eclipse.etrice.core.genmodel.etricegen.IDiagnostician
+import org.eclipse.etrice.core.etphys.eTPhys.PhysicalThread
@Singleton
class NodeGen {
@@ -45,6 +52,7 @@ class NodeGen {
@Inject Initialization attrInitGenAddon
@Inject ILanguageExtension languageExt
@Inject ILogger logger
+ @Inject IDiagnostician diagnostician
def doGenerate(Root root) {
for (nr : ETMapUtil::getNodeRefs()) {
@@ -52,6 +60,16 @@ class NodeGen {
val ssi = root.getInstance(instpath) as SubSystemInstance
var filepath = ssi.subSystemClass.generationTargetPath+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)
+ }
+
logger.logInfo("generating Node declaration: '"+file+"' in '"+filepath+"'")
fileAccess.setOutputPath(filepath)
fileAccess.generateFile(file, root.generateHeaderFile(ssi))
@@ -59,17 +77,17 @@ class NodeGen {
file = nr.getCSourceFileName(ssi)
logger.logInfo("generating Node implementation: '"+file+"' in '"+filepath+"'")
fileAccess.setOutputPath(filepath)
- fileAccess.generateFile(file, root.generateSourceFile(ssi))
+ fileAccess.generateFile(file, root.generateSourceFile(ssi, usedThreads))
file = nr.getInstSourceFileName(ssi)
logger.logInfo("generating Node instance file: '"+file+"' in '"+filepath+"'")
fileAccess.setOutputPath(filepath)
- fileAccess.generateFile(file, root.generateInstanceFile(ssi))
+ fileAccess.generateFile(file, root.generateInstanceFile(ssi, usedThreads))
file = nr.getDispSourceFileName(ssi)
logger.logInfo("generating Node dispatcher file: '"+file+"' in '"+filepath+"'")
fileAccess.setOutputPath(filepath)
- fileAccess.generateFile(file, root.generateDispatcherFile(ssi))
+ fileAccess.generateFile(file, root.generateDispatcherFile(ssi, usedThreads))
}
}
}
@@ -87,6 +105,8 @@ class NodeGen {
*/
«generateIncludeGuardBegin(clsname)»
+
+ #include "etDatatypes.h"
««« TODOCGENPHYS: user code?
«helpers.userCode(ssc.userCode1)»
@@ -99,7 +119,7 @@ class NodeGen {
void «clsname»_init(void); /* lifecycle init */
void «clsname»_start(void); /* lifecycle start */
- void «clsname»_run(void); /* lifecycle run */
+ void «clsname»_run(etBool runAsTest); /* lifecycle run */
void «clsname»_stop(void); /* lifecycle stop */
void «clsname»_destroy(void); /* lifecycle destroy */
@@ -115,10 +135,11 @@ class NodeGen {
'''
}
- def private generateSourceFile(Root root, SubSystemInstance ssi) {
+ 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
@@ -127,19 +148,22 @@ class NodeGen {
*
*/
+ #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 SubSytsem «ssi.name» */
+ /* data for Node «nr.name» with SubSystem «ssi.name» */
typedef struct «clsname» {
char *name;
volatile int shutdownRequest;
@@ -160,7 +184,7 @@ class NodeGen {
etTime interval;
/* initialization of all message services */
- «FOR thread: nr.type.threads»
+ «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;
@@ -186,7 +210,7 @@ class NodeGen {
static void «clsname»_startMessageServices(void) {
ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "startMessageServices")
- «FOR thread: nr.type.threads»
+ «FOR thread: threads»
etMessageService_start(&msgService_«thread.name»);
«ENDFOR»
@@ -196,7 +220,7 @@ class NodeGen {
static void «clsname»_stopMessageServices(void) {
ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "stopMessageServices")
- «FOR thread: nr.type.threads»
+ «FOR thread: threads»
etMessageService_stop(&msgService_«thread.name»);
«ENDFOR»
@@ -206,7 +230,7 @@ class NodeGen {
static void «clsname»_destroyMessageServices(void) {
ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "destroyMessageServices")
- «FOR thread: nr.type.threads»
+ «FOR thread: threads»
etMessageService_destroy(&msgService_«thread.name»);
«ENDFOR»
@@ -236,32 +260,26 @@ class NodeGen {
ET_MSC_LOGGER_SYNC_EXIT
}
- void «clsname»_run(void) {
+ void «clsname»_run(etBool runAsTest) {
ET_MSC_LOGGER_SYNC_ENTRY("«clsname»", "run")
-««« TODOCGENPHYS: main loop
- etThread_sleep(1000);
-
-««« #ifdef ET_RUNTIME_ENDLESS
-««« while(!(«ssc.name»Inst.shutdownRequest)){
-««« if (etTimer_executeNeeded()){
-««« etMessageService_execute(&msgService_Thread1);
-««« «generateDatadrivenExecutes(root, ssi)»
-««« }
-««« }
-««« #else
-««« uint32 loopCounter = 0;
-««« while(!(«ssc.name»Inst.shutdownRequest)){
-««« if (etTimer_executeNeeded()){
-««« etMessageService_execute(&msgService_Thread1);
-««« «generateDatadrivenExecutes(root, ssi)»
-««« etLogger_logInfo("Execute");
-««« if (loopCounter++ > ET_RUNTIME_MAXLOOP){
-««« break;
-««« }
-««« }
-««« }
-««« #endif
+ if (runAsTest) {
+ etSema_waitForWakeup(etRuntime_getTerminateSemaphore());
+ }
+ else {
+ printf("type quit to exit\n");
+ 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
}
@@ -323,7 +341,7 @@ class NodeGen {
'''
}
- def private generateInstanceFile(Root root, SubSystemInstance ssi) {
+ def private generateInstanceFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
val nr = ETMapUtil::getNodeRef(ssi)
'''
/**
@@ -336,18 +354,18 @@ class NodeGen {
#include "messaging/etMessageService.h"
- /* include all used ActorClasses */
- «FOR actorClass : root.getUsedActorClasses()»
- #include "«actorClass.name».h"
+ /* include all referenced ActorClasses */
+ «FOR actorClass : root.getReferencedActorClasses(ssi.subSystemClass)»
+ #include «actorClass.includePath»
«ENDFOR»
- /* include all used ProtcolClasses */
- «FOR protocolClass : root.getUsedProtocolClasses()»
- #include "«protocolClass.name».h"
+ /* 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»
+ «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»
@@ -365,7 +383,7 @@ class NodeGen {
/* forward declaration of variable port structs */
«FOR ai: ssi.allContainedInstances»
«IF ai.orderedIfItemInstances.empty»
- /*nothing to do */
+ /* nothing to do */
«ELSE»
«FOR pi:ai.orderedIfItemInstances»
«IF pi.protocol.getPortClass(pi.conjugated)?.attributes?.size > 0»
@@ -392,62 +410,83 @@ class NodeGen {
}
def private genActorInstanceInitializer(Root root, ActorInstance ai) {
- var instName = ai.path.pathName
+ val instName = ai.path.pathName
- // list of replicated ports
- var replPorts = new ArrayList<InterfaceItemInstance>()
- replPorts.addAll(ai.orderedIfItemInstances.filter(e|e.replicated))
- var haveReplSubPorts = replPorts.findFirst(e|!e.peers.empty)!=null
+ // 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)
- var simplePorts = ai.orderedIfItemInstances.filter(e|e.simple)
+ val simplePorts = ai.orderedIfItemInstances.filter(e|e.simple)
- // list of event ports, simple first, then replicated
- var eventPorts = new ArrayList<InterfaceItemInstance>()
- eventPorts.addAll(simplePorts.filter(p|p.protocol.commType==CommunicationType::EVENT_DRIVEN).union(replPorts))
-
- var dataPorts = simplePorts.filter(p|p.protocol.commType==CommunicationType::DATA_DRIVEN)
- var recvPorts = dataPorts.filter(p|p instanceof PortInstance && !(p as PortInstance).port.conjugated)
- var sendPorts = dataPorts.filter(p|p instanceof PortInstance && (p as PortInstance).port.conjugated)
+ // 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
- var offsets = new HashMap<InterfaceItemInstance, Integer>()
+ val offsets = new HashMap<InterfaceItemInstance, Integer>()
var offset = 0
- for (p: replPorts) {
+ for (p: replEventItems) {
offsets.put(p, offset)
offset = offset + p.peers.size
}
- var replSubPortsArray = if (haveReplSubPorts) instName+"_repl_sub_ports" else "NULL"
-
+ var replSubPortsArray = if (haveReplSubItems) instName+"_repl_sub_ports" else "NULL"
+ val haveConstData = !simpleEventItems.empty || !recvPorts.empty || !replEventItems.empty
+ val sep = new IntelligentSeparator(",");
'''
- «IF haveReplSubPorts»
+ «IF haveReplSubItems»
static const etReplSubPort «replSubPortsArray»[«offset»] = {
/* Replicated Sub Ports: {varData, msgService, peerAddress, localId, index} */
- «FOR pi : replPorts.filter(e|!e.peers.empty) SEPARATOR ","»
+ «FOR pi : replEventItems.filter(e|!e.peers.empty) SEPARATOR ","»
«genReplSubPortInitializers(root, ai, pi)»
«ENDFOR»
};
«ENDIF»
- «IF !(eventPorts.empty && recvPorts.empty)»
+ «IF haveConstData»
static const «ai.actorClass.name»_const «instName»_const = {
/* Ports: {varData, msgService, peerAddress, localId} */
- «FOR pi : eventPorts SEPARATOR ","»
- «IF pi.simple»
- «genPortInitializer(root, ai, pi)»
- «ELSE»
- {«pi.peers.size», «replSubPortsArray»+«offsets.get(pi)»}
- «ENDIF»
+ /* simple ports */
+ «FOR pi : simpleEventPorts»
+ «sep»«genPortInitializer(root, ai, pi)»
«ENDFOR»
- «IF !eventPorts.empty && !recvPorts.empty»,«ENDIF»
/* data receive ports */
- «FOR pi : recvPorts SEPARATOR ","»
- «genRecvPortInitializer(root, ai, pi)»
+ «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»,
@@ -458,7 +497,6 @@ class NodeGen {
/* state and history are initialized in init fuction */
};
- «ENDIF»
'''}
def private String genPortInitializer(Root root, ActorInstance ai, InterfaceItemInstance pi) {
@@ -481,7 +519,7 @@ class NodeGen {
«FOR m : pc.incomingMessages SEPARATOR ","»
«m.data.refType.type.defaultValue»
«ENDFOR»
- }
+ } /* send port «pi.name» */
'''
}
@@ -527,7 +565,7 @@ class NodeGen {
return result
}
- def private generateDispatcherFile(Root root, SubSystemInstance ssi) {
+ def private generateDispatcherFile(Root root, SubSystemInstance ssi, HashSet<PhysicalThread> usedThreads) {
val nr = ETMapUtil::getNodeRef(ssi)
'''
@@ -543,16 +581,16 @@ class NodeGen {
#include "debugging/etLogger.h"
#include "debugging/etMSCLogger.h"
- «FOR thread: nr.type.threads SEPARATOR "\n"»
+ «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»_execute(void){
+ 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»);
@@ -571,7 +609,7 @@ class NodeGen {
case MESSAGESERVICE_ADDRESS:
«IF !executedInstances.empty»
if (msg->evtID == etSystemProtocol_IN_poll)
- MsgDispatcher_«thread.name»_execute();
+ MsgDispatcher_«thread.name»_poll();
else
«ENDIF»
if (msg->evtID == etSystemProtocol_IN_terminate)
@@ -630,4 +668,29 @@ class NodeGen {
'''
}
-}
+ 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