Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 263f807760f63e004caa8acef825b6224a3f8410 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                                  
                                                  
                                                      
                                                  

                                                       

                                                          
                                                           
                                                             
                                                        
                                                                          


           
                                                               




                                                            
                                      












                                                                                                                    



                  
                                                                         









                                                          
                                              
                 
                                                 
                 

                                                                    
                         
                 













                                                                            







                                                                    
                                                 
                 




                                                   
                                                                         







                                                          
                                                   

                                                 
                 











                                                                           


            
                                                                     

                                                                        
                                                                                            
                 
                    

                                                        
                 













                                                                                                                                           
                         








                                                                                                                                                     





                                                                                                             



                                                                                                                                                       
                        
                                                                             

                    

 
         




































                                                                                                                               












                                                                                                               
                                                              
                                                                        

                                                                                            
 

                                                 

                                                                                                         



                                                                                                                                                                
                                                                               
                                                                          
                                 
                                                                                            




                                                                                                                                 
                                                                                                                                                               

                                                                        
                                  
                                 
                                                                                                          

                                                          
                                                                                              
                                                                                                                                           



                                                                                                                  

                                                                                                                                                                                                    


                                                                        

                                  
                                                                                                            
                                                          
                                                                                                                                     

                                                                                                                  

                                                                                                                                                                                                      


                                                                        
                                  
                                 







                                                                                                                        
                                                                  





                                                              

                    
 








                                                                                                               
          







                                                                                                












                                                                                                                                                                                   

                                                                        


                                

                                                                                                                                                                       
                                                 

                                                                       
                  
                 
                 
 

         
                                                                                        
                 
                                                                            














                                                                                                                                                                                                 
 
/*******************************************************************************
 * 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 org.eclipse.etrice.core.room.ProtocolClass
import org.eclipse.etrice.core.room.CommunicationType
import org.eclipse.etrice.core.room.PrimitiveType
import org.eclipse.etrice.core.genmodel.base.ILogger
import org.eclipse.etrice.core.genmodel.etricegen.Root
import org.eclipse.xtext.generator.JavaIoFileSystemAccess

import org.eclipse.etrice.generator.generic.RoomExtensions
import org.eclipse.etrice.generator.generic.ProcedureHelpers
import org.eclipse.etrice.generator.generic.TypeHelpers
import org.eclipse.etrice.generator.generic.GenericProtocolClassGenerator


@Singleton
class ProtocolClassGen extends GenericProtocolClassGenerator {

	@Inject extension JavaIoFileSystemAccess fileAccess
	@Inject extension CExtensions stdExt
	@Inject extension RoomExtensions roomExt
	@Inject extension ProcedureHelpers helpers
	@Inject extension TypeHelpers
	@Inject ILogger logger
	
	def doGenerate(Root root) {
		for (pc: root.usedProtocolClasses) {
			var path = pc.generationTargetPath+pc.getPath

			logger.logInfo("generating ProtocolClass header '"+pc.getCHeaderFileName+"' in '"+path+"'")
			fileAccess.setOutputPath(path)
			fileAccess.generateFile(pc.getCHeaderFileName, root.generateHeaderFile(pc))

			logger.logInfo("generating ProtocolClass source '"+pc.getCSourceFileName+"' in '"+path+"'")
			fileAccess.setOutputPath(path)
			fileAccess.generateFile(pc.getCSourceFileName, root.generateSourceFile(pc))
		}
	}

	
	def private generateHeaderFile(Root root, ProtocolClass pc) {'''
		/**
		 * @author generated by eTrice
		 *
		 * Header File of ProtocolClass «pc.name»
		 * 
		 */

		«generateIncludeGuardBegin(pc.name)»
		
		#include "etDatatypes.h"
		#include "modelbase/etPort.h"
		
		«helpers.userCode(pc.userCode1)»
		
		«FOR dataClass : root.getReferencedDataClasses(pc)»
			#include "«dataClass.name».h"
		«ENDFOR»
		
		«IF pc.commType==CommunicationType::EVENT_DRIVEN»
			
			/* message IDs */
			«genMessageIDs(pc)»
			
			/*--------------------- port structs and methods */
			«portClassHeader(pc, false)»
			«portClassHeader(pc, true)»
		«ELSEIF pc.commType==CommunicationType::DATA_DRIVEN»
			/*--------------------- port structs and methods */
			«pc.genDataDrivenPortHeaders»
		«ELSEIF pc.commType==CommunicationType::SYNCHRONOUS»
			#error "synchronoue protocols not implemented yet"
		«ENDIF»
«««			«portClass(pc, false)»
«««			«portClass(pc, true)»

		/*--------------------- debug helpers */
		
		/* get message string for message id */
		const char* «pc.name»_getMessageString(int msg_id);

		«helpers.userCode(pc.userCode2)»
		
		«generateIncludeGuardEnd(pc.name)»
		
	'''
	}
	
	def private generateSourceFile(Root root, ProtocolClass pc) {'''
		/**
		 * @author generated by eTrice
		 *
		 * Source File of ProtocolClass «pc.name»
		 * 
		 */

		#include "«pc.getCHeaderFileName»"
		#include "debugging/etMSCLogger.h"

		«helpers.userCode(pc.userCode3)»
		
		/*--------------------- port methods */
		«IF pc.commType==CommunicationType::EVENT_DRIVEN»
			«portClassSource(pc, false)»
			«portClassSource(pc, true)»
			
			/*--------------------- debug helpers */
			«generateDebugHelpersImplementation(root, pc)»
		«ELSEIF pc.commType==CommunicationType::DATA_DRIVEN»
			«pc.genDataDrivenPortSources»
		«ELSEIF pc.commType==CommunicationType::SYNCHRONOUS»
			#error "synchronoue protocols not implemented yet"
		«ENDIF»
	'''
	}
	
	def private portClassHeader(ProtocolClass pc, Boolean conj){
		var portClassName = pc.getPortClassName(conj)
		var replPortClassName = pc.getPortClassName(conj, true)
		var messages = if (conj) pc.allIncomingMessages else pc.allOutgoingMessages
		
		'''
		typedef etPort «portClassName»;
		typedef etReplPort «replPortClassName»;
		
		«IF pc.getPortClass(conj)!=null»	
			«IF !(pc.getPortClass(conj).attributes.empty)»
/* variable part of PortClass (RAM) */
typedef struct «portClassName»_var «portClassName»_var; 
struct «portClassName»_var {
	«helpers.attributes(pc.getPortClass(conj).attributes)»
	};
				«FOR a:pc.getPortClass(conj).attributes»
					«IF a.defaultValueLiteral!=null»
						«logger.logInfo(portClassName+" "+a.name+": Attribute initialization not supported in C")»
					«ENDIF»
				«ENDFOR»
			«ENDIF»
		«ENDIF»
			
		«FOR message : messages»
			«var hasData = message.data!=null»
			«var typeName = if (hasData) message.data.refType.type.typeName else ""»
			«var refp = if (hasData && (!(message.data.refType.type instanceof PrimitiveType)||(message.data.refType.ref))) "*" else ""»
			«var data = if (hasData) ", "+typeName+refp+" data" else ""»
			«messageSignature(portClassName, message.name, "", data)»;
			«messageSignature(replPortClassName, message.name, "_broadcast", data)»;
			«messageSignature(replPortClassName, message.name, "", ", int idx"+data)»;
		«ENDFOR»
			
		«IF (pc.getPortClass(conj) != null)»	
			«helpers.operationsDeclaration(pc.getPortClass(conj).operations, portClassName)»
			«helpers.operationsDeclaration(pc.getPortClass(conj).operations, replPortClassName)»
		«ENDIF»
		
 		«IF pc.handlesReceive(conj)»
			«FOR h:getReceiveHandlers(pc,conj)»
void «portClassName»_«h.msg.name»_receiveHandler(«portClassName»* self, const etMessage* msg, void * actor, etActorReceiveMessage receiveMessageFunc);
			«ENDFOR»
		«ENDIF»
etInt32 «replPortClassName»_getReplication(const «replPortClassName»* self);
		'''
	}


	
	def private genDataDrivenPortHeaders(ProtocolClass pc) {
		var sentMsgs = pc.allIncomingMessages.filter(m|m.data!=null)
		
		'''
			/* data driven send port (conjugated) */
			typedef struct {
				«FOR msg : sentMsgs»
					«var typeName = msg.data.refType.type.typeName»
					«var refp = if (msg.data.refType.ref) "*" else ""»
					«typeName»«refp» «msg.name»;
				«ENDFOR»
			}
			«pc.getPortClassName(true)»;
			
			/* data driven receive port (regular) */
			typedef struct {
				const «pc.getPortClassName(true)»* peer;
			}
			«pc.getPortClassName(false)»;
			
			«FOR message : sentMsgs»
				«var hasData = message.data!=null»
				«var typeName = if (hasData) message.data.refType.type.typeName else ""»
				«var refp = if (hasData && !(message.data.refType.type instanceof PrimitiveType)) "*" else ""»
				«var data = if (hasData) ", "+typeName+refp+" data" else ""»
				«messageSetterSignature(pc.getPortClassName(true), message.name, data)»;
				«messageGetterSignature(pc.getPortClassName(false), message.name, typeName)»;
				
			«ENDFOR»
		'''
	}
	def private genDataDrivenPortSources(ProtocolClass pc) {
		var messages = pc.allIncomingMessages.filter(m|m.data!=null)
	'''
			«FOR message : messages»
				«var typeName =message.data.refType.type.typeName»
				«var refp = if (!(message.data.refType.type instanceof PrimitiveType)) "*" else ""»
				«var data = ", "+typeName+refp+" data"»
				«messageSetterSignature(pc.getPortClassName(true), message.name, data)» {
					self->«message.name» = data;
				}
				«messageGetterSignature(pc.getPortClassName(false), message.name, typeName)» {
					return self->peer->«message.name»;
				}
				
			«ENDFOR»
	'''
	}
	
	def private portClassSource(ProtocolClass pc, Boolean conj){
		var portClassName = pc.getPortClassName(conj)
		var replPortClassName = pc.getPortClassName(conj, true)
		var messages = if (conj) pc.allIncomingMessages else pc.allOutgoingMessages
		var dir = if (conj) "IN_" else "OUT_"

		'''
			«FOR message : messages»
				«var hasData = message.data!=null»
				«var typeName = if (hasData) message.data.refType.type.typeName else ""»
				«var refp = if (hasData && ((message.data.refType.ref))) "*" else ""»
				«var refpd = if (hasData && (!(message.data.refType.type instanceof PrimitiveType)||(message.data.refType.ref))) "*" else ""»
				«var refa = if (hasData && (!(message.data.refType.type instanceof PrimitiveType))&&(!(message.data.refType.ref))) "" else "&"»
				«var data = if (hasData) ", "+typeName+refpd+" data" else ""»
				«var dataCall = if (hasData) ", data" else ""»
				«var hdlr = message.getSendHandler(conj)»
				
				«messageSignature(portClassName, message.name, "", data)» {
					«IF hdlr != null»
						«FOR command : hdlr.detailCode.commands»	«command»
						«ENDFOR»									
					«ELSE»
						ET_MSC_LOGGER_SYNC_ENTRY("«portClassName»", "«message.name»")
							«sendMessageCall(hasData, "self", memberInUse(pc.name, dir+message.name), typeName+refp, refa+"data")»
						ET_MSC_LOGGER_SYNC_EXIT
					«ENDIF»
				}
				
				«messageSignature(replPortClassName, message.name, "_broadcast", data)» {
					«IF hdlr != null»
						int i;
						for (i=0; i<((etReplPort*)self)->size; ++i) {
							«portClassName»_«message.name»((etPort*)&((etReplPort*)self)->ports[i]«dataCall»);
						}					
					«ELSE»
						int i;
						ET_MSC_LOGGER_SYNC_ENTRY("«replPortClassName»", "«message.name»")
						for (i=0; i<((etReplPort*)self)->size; ++i) {
							«sendMessageCall(hasData, "((etPort*)&((etReplPort*)self)->ports[i])", memberInUse(pc.name, dir+message.name), typeName+refp, refa+"data")»
						}
						ET_MSC_LOGGER_SYNC_EXIT
					«ENDIF»
				}
				
				«messageSignature(replPortClassName, message.name, "", ", int idx"+data)» {
					«IF hdlr != null»
						«portClassName»_«message.name»((etPort*)&((etReplPort*)self)->ports[idx]«dataCall»);
					«ELSE»					
						ET_MSC_LOGGER_SYNC_ENTRY("«replPortClassName»", "«message.name»")
						if (0<=idx && idx<((etReplPort*)self)->size) {
							«sendMessageCall(hasData, "((etPort*)&((etReplPort*)self)->ports[idx])", memberInUse(pc.name, dir+message.name), typeName+refp, refa+"data")»
						}
						ET_MSC_LOGGER_SYNC_EXIT
					«ENDIF»
				}
			«ENDFOR»
			
			«IF (pc.getPortClass(conj) != null)»
				«helpers.operationsImplementation(pc.getPortClass(conj).operations, portClassName)»
				«helpers.operationsImplementation(pc.getPortClass(conj).operations, replPortClassName)»
			«ENDIF»

			// getReplication
			etInt32 «replPortClassName»_getReplication(const «replPortClassName»* self) {
				return ((etReplPort*)self)->size;
			}
			
			«IF pc.handlesReceive(conj)»
				«genReceiveHandlers(pc,conj)»
			«ENDIF»
			
		'''
	}

	def private sendMessageCall(boolean hasData, String self, String msg, String typeName, String data) {
		if (hasData)
			"etPort_sendMessage("+self+", "+msg+", sizeof("+typeName+"), "+data+");"
		else
			"etPort_sendMessage("+self+", "+msg+", 0, NULL);"
	}
	
	def private messageSignature(String className, String messageName, String methodSuffix, String data) {
		"void "+className+"_"+messageName+methodSuffix+"(const "+className+"* self"+data+")"
	}
	
	def private messageSetterSignature(String className, String messageName, String data) {
		"void "+className+"_"+messageName+"_set("+className+"* self"+data+")"
	}
	
	def private messageGetterSignature(String className, String messageName, String type) {
		type+" "+className+"_"+messageName+"_get(const "+className+"* const self)"
	}
	
//	def sendMessage(Message m, boolean conj) {'''
//	«var dir = if (conj) "IN" else "OUT"»
//	«var hdlr = m.getSendHandler(conj)»
//	«messageSignature(m)»{
//		if (getPeerAddress()!=null)
//				«IF m.data==null»getPeerMsgReceiver().receive(new EventMessage(getPeerAddress(), «dir»_«m.name»));
//				«ELSE»getPeerMsgReceiver().receive(new EventWithDataMessage(getPeerAddress(), «dir»_«m.name», «m.data.name»«IF (!m.data.ref)».deepCopy()«ENDIF»));
//			«ENDIF»
//	}
//	'''
//	}
	
	def private genReceiveHandlers(ProtocolClass pc, Boolean conj){
	var portClassName = pc.getPortClassName(conj)
	
	'''
	/* receiver handlers */
	«FOR h:getReceiveHandlers(pc,conj)»
		void «portClassName»_«h.msg.name»_receiveHandler(«portClassName»* self, const etMessage* msg, void * actor, etActorReceiveMessage receiveMessageFunc){
			«userCode(h.detailCode)»
			/* hand over the message to the actor:      */
			/* (*receiveMessageFunc)(actor, self, msg); */
		}
	«ENDFOR»
	'''}	

	
	
	def private generateDebugHelpersImplementation(Root root, ProtocolClass pc){'''
		
«««		TODO: make this optional or different for smaller footprint
		/* message names as strings for debugging (generate MSC) */
		static const char* «pc.name»_messageStrings[] = {"MIN", «FOR m : pc.getAllOutgoingMessages()»"«m.name»",«ENDFOR»«FOR m : pc.getAllIncomingMessages()»"«m.name»", «ENDFOR»"MAX"};

		const char* «pc.name»_getMessageString(int msg_id) {
			if (msg_id<«pc.name»_MSG_MIN || msg_id>«pc.name»_MSG_MAX+1){
				/* id out of range */
				return "Message ID out of range";
			}
			else{
				return «pc.name»_messageStrings[msg_id];
			}
		}
		'''
	}
	
}

Back to the top