Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 9934fcfea207fe51baf146ac500d14c198e2cad5 (plain) (tree)


















                                                                                  
                                                  





                                                              
                                                        
                                                                          


           
                                                               




                                                            
                                      












                                                                                                                    














                                                                 
                                              
                 
                                                 
                 

                                                                    


                                  
                                    











                                                                    
                                                 
                 













                                                                 
                                                   

                                                 
































































































































                                                                                                                                                                          

                                                                        
                                                                                            
                 
                    
                 


                                                                







                                                                                                                               
                                 



                                                             
                                                              
                                                                        

                                                                                            
                 

                                                 




                                                                                                                               
                                 
                                                                                            
                                                                                                      
                                                                              
                                                                                                                                                  
                                          

                                                                
                                 
                                                                                                          


                                                                                                          
                                                                                                                                                                        



                                                                
                                                                                                            

                                                                                                          
                                                                                                                                                                          


                                                                
                                 

                    
 








                                                                                                               

          
                                                
















                                                                                                                                                                                   
                                                                            














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

import org.eclipse.etrice.generator.extensions.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 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»
		
		/* message IDs */
		«genMessageIDs(pc)»

		/*--------------------- port classes */
		«portClassHeader(pc, false)»
		«portClassHeader(pc, true)»
«««			«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 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 classes */
		«portClassSource(pc, false)»
		«portClassSource(pc, true)»
		
		/*--------------------- debug helpers */
		«generateDebugHelpersImplementation(root, pc)»
	'''
	}
	
	
	
	def portClass(ProtocolClass pc, Boolean conj) {'''
«««		«var name = pc.getPortClassName(conj)»
«««		«var pclass = pc.getPortClass(conj)»
		
«««		// port class
«««		static public class «name» extends PortBase {
«««			«IF pclass!=null»
«««				«helpers.UserCode(pclass.userCode)»
«««			«ENDIF»
«««			// constructors
«««			public «name»(IEventReceiver actor, String name, int localId, Address addr, Address peerAddress) {
«««				super(actor, name, localId, 0, addr, peerAddress);
«««				DebuggingService.getInstance().addPortInstance(this);
«««			}
«««			public «name»(IEventReceiver actor, String name, int localId, int idx, Address addr, Address peerAddress) {
«««				super(actor, name, localId, idx, addr, peerAddress);
«««				DebuggingService.getInstance().addPortInstance(this);
«««			}
«««		
«««			@Override
«««			public void receive(Message m) {
«««					if (!(m instanceof EventMessage))
«««						return;
«««					EventMessage msg = (EventMessage) m;
«««					if (msg.getEvtId() <= 0 || msg.getEvtId() >= MSG_MAX)
«««						System.out.println("unknown");
«««					else {
«««						if (messageStrings[msg.getEvtId()] != "timerTick"){
«««							// TODOTS: model switch for activation
«««							DebuggingService.getInstance().addMessageAsyncIn(getPeerAddress(), getAddress(), messageStrings[msg.getEvtId()]);
«««						}
«««						«IF pc.handlesReceive(conj)»
«««						switch (msg.getEvtId()) {
«««							«FOR hdlr : pc.getReceiveHandlers(conj)»
«««								case «hdlr.msg.getCodeName()»:
«««								{
«««									«FOR command : hdlr.detailCode.commands»
«««										«command»
«««									«ENDFOR»
«««								}
«««								break;
«««							«ENDFOR»
«««							default:
«««						«ENDIF»
«««							if (msg instanceof EventWithDataMessage)
«««								getActor().receiveEvent(this, msg.getEvtId(), ((EventWithDataMessage)msg).getData());
«««							else
«««								getActor().receiveEvent(this, msg.getEvtId(), null);
«««						«IF pc.handlesReceive(conj)»
«««						}
«««						«ENDIF»
«««					}
«««			}
«««		
«««			«IF pclass!=null»
«««				«helpers.Attributes(pclass.attributes)»
«««				«helpers.OperationsDeclaration(pclass.operations, name)»
«««			«ENDIF»
«««			
«««			// sent messages
«««			«FOR m : pc.getOutgoing(conj)»
«««				«sendMessage(m, conj)»
«««			«ENDFOR»
«««		}
		
«««		// replicated port class
«««		static public class «name»Repl {
«««			private ArrayList<«name»> ports;
«««			private int replication;
«««		
«««			public «name»Repl(IEventReceiver actor, String name, int localId, Address[] addr,
«««					Address[] peerAddress) {
«««				replication = addr.length;
«««				ports = new ArrayList<«pc.name».«name»>(replication);
«««				for (int i=0; i<replication; ++i) {
«««					ports.add(new «name»(
«««							actor, name+i, localId, i, addr[i], peerAddress[i]));
«««				}
«««			}
«««			
«««			public int getReplication() {
«««				return replication;
«««			}
«««			
«««			public int getIndexOf(InterfaceItemBase ifitem){
«««					return ifitem.getIdx();
«««				}
«««			
«««			public «name» get(int i) {
«««				return ports.get(i);
«««			}
«««			
«««			«IF conj»
«««			// incoming messages
«««			«FOR m : pc.getAllIncomingMessages()»
«««			«messageSignature(m)»{
«««				for (int i=0; i<replication; ++i) {
«««					ports.get(i).«messageCall(m)»;
«««				}
«««			}
«««			«ENDFOR»
«««			«ELSE»
«««			// outgoing messages
«««			«FOR m : pc.getAllOutgoingMessages()»
«««			«messageSignature(m)»{
«««				for (int i=0; i<replication; ++i) {
«««					ports.get(i).«messageCall(m)»;
«««				}
«««			}
«««			«ENDFOR»
«««			«ENDIF»
«««		}
		
	'''
	}

	def 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»;
			
			«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)) "*" 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»
		'''
	}
	
	def 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.type instanceof PrimitiveType)) "*" else ""»
				«var refa = if (hasData && (message.data.refType.type instanceof PrimitiveType)) "&" else ""»
				«var data = if (hasData) ", "+typeName+refp+" data" else ""»
				
				«messageSignature(portClassName, message.name, "", data)» {
					ET_MSC_LOGGER_SYNC_ENTRY("«portClassName»", "«message.name»")
					if (self->receiveMessageFunc!=NULL) {
						«sendMessageCall(hasData, "self", memberInUse(pc.name, dir+message.name), typeName, refa+"data")»
					}
					ET_MSC_LOGGER_SYNC_EXIT
				}
				
				«messageSignature(replPortClassName, message.name, "_broadcast", data)» {
					int i;
					ET_MSC_LOGGER_SYNC_ENTRY("«replPortClassName»", "«message.name»")
					for (i=0; i<self->size; ++i) {
						«sendMessageCall(hasData, "(etPort*)(&self->ports[i])", memberInUse(pc.name, dir+message.name), typeName, refa+"data")»
					}
					ET_MSC_LOGGER_SYNC_EXIT
				}
				
				«messageSignature(replPortClassName, message.name, "", ", int idx"+data)» {
					ET_MSC_LOGGER_SYNC_ENTRY("«replPortClassName»", "«message.name»")
					if (0<=idx && idx<self->size) {
						«sendMessageCall(hasData, "(etPort*)(&self->ports[idx])", memberInUse(pc.name, dir+message.name), typeName, refa+"data")»
					}
					ET_MSC_LOGGER_SYNC_EXIT
				}
			«ENDFOR»
		'''
	}

	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 messageCall(Message m) {'''
	«m.name»(«IF m.data!=null» «m.data.name»«ENDIF»)
	'''}
	
//	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 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