package org.eclipse.etrice.generator.cpp.gen
import com.google.inject.Inject
import com.google.inject.Singleton
import org.eclipse.etrice.core.genmodel.base.ILogger
import org.eclipse.etrice.core.genmodel.etricegen.Root
import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance
import org.eclipse.etrice.core.room.SubSystemClass
import org.eclipse.etrice.generator.generic.ConfigExtension
import org.eclipse.etrice.generator.generic.ProcedureHelpers
import org.eclipse.etrice.generator.generic.RoomExtensions
import org.eclipse.etrice.generator.generic.TypeHelpers
import org.eclipse.xtext.generator.JavaIoFileSystemAccess
import static extension org.eclipse.etrice.generator.base.Indexed.*
import org.eclipse.etrice.core.genmodel.etricegen.ActorInstance
@Singleton
class SubSystemClassGen {
@Inject JavaIoFileSystemAccess fileAccess
@Inject extension CppExtensions
@Inject extension RoomExtensions
@Inject extension ConfigExtension
@Inject extension ProcedureHelpers
@Inject extension TypeHelpers
@Inject ILogger logger
def doGenerate(Root root) {
for (ssi: root.subSystemInstances) {
var path = ssi.subSystemClass.generationTargetPath+ssi.subSystemClass.getPath
var file = ssi.subSystemClass.getCppHeaderFileName
logger.logInfo("generating SubSystemClass declaration: '"+file+"' in '"+path+"'")
fileAccess.setOutputPath(path)
fileAccess.generateFile(file, root.generateHeaderFile(ssi, ssi.subSystemClass))
file = ssi.subSystemClass.getCppSourceFileName
logger.logInfo("generating SubSystemClass implementation: '"+file+"' in '"+path+"'")
fileAccess.setOutputPath(path)
fileAccess.generateFile(file, root.generateSourceFile(ssi, ssi.subSystemClass))
// file = ssi.subSystemClass.getInstSourceFileName
// logger.logInfo("generating SubSystemClass instance file: '"+file+"' in '"+path+"'")
// fileAccess.setOutputPath(path)
// fileAccess.generateFile(file, root.generateInstanceFile(ssi, ssi.subSystemClass))
//
// file = ssi.subSystemClass.getDispSourceFileName
// logger.logInfo("generating SubSystemClass dispatcher file: '"+file+"' in '"+path+"'")
// fileAccess.setOutputPath(path)
// fileAccess.generateFile(file, root.generateDispatcherFile(ssi, ssi.subSystemClass))
}
}
def generateHeaderFile(Root root, SubSystemInstance comp, SubSystemClass cc) {'''
/**
* @author generated by eTrice
*
* Header File of SubSystemClass «comp.name»
*
*/
«generateIncludeGuardBegin(comp.name)»
#include "platforms/generic/etDatatypes.h"
#include "common/messaging/IRTObject.h"
#include "common/modelbase/PortBase.h"
#include "common/modelbase/InterfaceItemBase.h"
#include "common/modelbase/ActorClassBase.h"
#include "common/modelbase/SubSystemClassBase.h"
#include "common/messaging/Address.h"
#include "common/messaging/IMessageReceiver.h"
#include "common/debugging/DebuggingService.h"
#include <string>
#include <vector>
«FOR model : root.getReferencedModels(cc)»
««« #include "«model.name».h"
«ENDFOR»
«cc.userCode(1)»
class «comp.name» : public etRuntime::SubSystemClassBase{
«cc.userCode(2)»
public:
«comp.name»(IRTObject* parent, std::string name)
: etRuntime::SubSystemClassBase(parent, name)
{
}
virtual void receiveEvent(const etRuntime::InterfaceItemBase& ifitem, int evt, void* data);
virtual void instantiateMessageServices();
virtual void instantiateActors();
private:
std::vector<etRuntime::MessageService*> m_msgServices;
};
«generateIncludeGuardEnd(comp.name)»
'''
}
def generateSourceFile(Root root, SubSystemInstance comp, SubSystemClass cc) {'''
/**
* @author generated by eTrice
*
* Source File of SubsystemClass «cc.name»
*
*/
#include "«cc.getCppHeaderFileName»"
#include "common/debugging/DebuggingService.h"
#include "common/messaging/RTSystemServicesProtocol.h"
«FOR ai : comp.allContainedInstances»
#include "«ai.actorClass.path»«ai.actorClass.name».h"
«ENDFOR»
#include <iostream>
using namespace etRuntime;
void «comp.name»::receiveEvent(const InterfaceItemBase& ifitem, int evt, void* data){
}
void «comp.name»::instantiateMessageServices(){
m_msgServices.push_back( new MessageService(this, Address(0, 0, 0),"MessageService_Main") );
«FOR thread : cc.threads»
m_msgServices.push_back(new MessageService(this, Address(0, «cc.threads.indexOf(thread)+1», 0),"MessageService_«thread.name»", «thread.prio»));
«ENDFOR»
for (std::vector<MessageService*>::iterator it=m_msgServices.begin(); it != m_msgServices.end(); ++it) {
RTServices::getInstance().getMsgSvcCtrl().addMsgSvc( *(*it));
}
}
void «comp.name»::instantiateActors(){
// all addresses
// Addresses for the Subsystem Systemport
«FOR ai : comp.allContainedInstances.indexed(comp.maxObjId)»
Address addr_item_SystemPort_«comp.allContainedInstances.indexOf(ai.value)»(0,0,«ai.index1»);
«ENDFOR»
«FOR ai : comp.allContainedInstances»
// actor instance «ai.path» itself => Systemport Address
// TODOTJ: For each Actor, multiple addresses should be generated (actor?, systemport, debugport)
Address addr_item_«ai.path.getPathName()»(0,«ai.threadId»,«ai.objId»);
// interface items of «ai.path»
«FOR pi : ai.orderedIfItemInstances»
«IF pi.replicated»
«FOR peer : pi.peers»
«var i = pi.peers.indexOf(peer)»
Address addr_item_«pi.path.getPathName()»_«i»(0,«pi.threadId»,«pi.objId+i»);
«ENDFOR»
«ELSE»
Address addr_item_«pi.path.getPathName()»(0,«ai.threadId»,«pi.objId»);
«ENDIF»
«ENDFOR»
«ENDFOR»
// instantiate all actor instances
m_instances.reserve(«comp.allContainedInstances.size»);
«FOR ai : comp.allContainedInstances»
//----------------------------------------------------------------------------------------------
// addresses for actor instance: «ai.name»
//----------------------------------------------------------------------------------------------
«generateOwnInterfaceItemAddresses(ai)»
«generatePeerInterfaceItemAddresses(ai, comp)»
m_instances[«comp.allContainedInstances.indexOf(ai)»] = new «ai.actorClass.name»(
«IF ai.eContainer instanceof SubSystemInstance»
this,
«ELSE»
m_instances[«comp.allContainedInstances.indexOf(ai.eContainer)»],
«ENDIF»
"«ai.name»",
«ai.name»_ownInterfaceItemAddresses,
«ai.name»_peerInterfaceItemAddresses
);
«ENDFOR»
// apply instance attribute configurations
«FOR ai : comp.allContainedInstances»
«var attrConfigs = ai.configAttributes»
«var portConfigs = ai.getConfigPorts»
«IF !attrConfigs.empty || !portConfigs.empty»
{
«var aiName = "inst"»
«ai.actorClass.name» «aiName» = («ai.actorClass.name») m_instances[«comp.allContainedInstances.indexOf(ai)»];
«FOR attrConfig : attrConfigs»
«var a = attrConfig.attribute»
«var value = attrConfig.value.stringValue(a)»
«IF !a.isArray»
«aiName».«a.name.invokeSetter(ai.actorClass.name, value)»;
«ELSEIF value.startsWith("{")»
«aiName».«a.name.invokeSetter(ai.actorClass.name, "new "+a.refType.type.typeName+"[]"+value)»;
«ELSE»
{
«a.refType.type.typeName»[] array = «aiName».«a.name.invokeGetter(ai.actorClass.name)»;
for (int i=0;i<«a.size»;i++){
array[i] = «value»;
}
}
«ENDIF»
«ENDFOR»
«FOR portConfig : portConfigs»
«var item = portConfig.item»
«FOR attrConfig : portConfig.attributes»
«var a = attrConfig.attribute»
«var value = attrConfig.value.stringValue(a)»
«var refToItem = aiName+"."+item.name.invokeGetter(item.portClassName)»
«IF !a.isArray»
«refToItem».«a.name.invokeSetter(item.portClassName, value)»;
«ELSEIF value.startsWith("{")»
«refToItem».«a.name.invokeSetter(ai.actorClass.name, "new "+a.refType.type.typeName+"[]"+value)»;
«ELSE»
{
«a.refType.type.typeName»[] array = «refToItem».«a.name.invokeGetter(ai.actorClass.name)»;
for (int i=0;i<«a.size»;i++){
array[i] = «value»;
}
}
«ENDIF»
«ENDFOR»
«ENDFOR»
}
«ENDIF»
«ENDFOR»
//----------------------------------------------------------------------------------------------
// addresses for the subsystem system port
//----------------------------------------------------------------------------------------------
std::vector<Address> ownAddresses(«comp.allContainedInstances.size»);
«FOR ai : comp.allContainedInstances»
ownAddresses[«comp.allContainedInstances.indexOf(ai)»] = addr_item_SystemPort_«comp.allContainedInstances.indexOf(ai)»;
«ENDFOR»
std::vector<Address> peerAddresses(«comp.allContainedInstances.size»);
«FOR ai : comp.allContainedInstances»
peerAddresses[«comp.allContainedInstances.indexOf(ai)»] = addr_item_«ai.path.getPathName()»;
«ENDFOR»
// create the subsystem system port
m_RTSystemPort = new RTSystemServicesProtocolConjPortRepl(*this, this, "RTSystemPort",
0, //local ID
ownAddresses,
peerAddresses);
}
'''
}
def generateOwnInterfaceItemAddresses(ActorInstance ai) '''
std::vector<std::vector<Address> > «ai.name»_ownInterfaceItemAddresses;
std::vector<Address> «ai.name»_actorInstanceAddresses(1);
«ai.name»_actorInstanceAddresses[0] = addr_item_«ai.path.getPathName()»;
«ai.name»_ownInterfaceItemAddresses.push_back(«ai.name»_actorInstanceAddresses);
«FOR pi : ai.orderedIfItemInstances»
«IF pi.replicated»
«IF pi.peers.empty»
std::vector<Address> «ai.name»_«pi.name»Addresses;
«ELSE»
std::vector<Address> «ai.name»_«pi.name»Addresses(«pi.peers.size»);
«FOR peer : pi.peers»
«ai.name»_«pi.name»Addresses[«pi.peers.indexOf(peer)»] = addr_item_«pi.path.getPathName()»_«pi.peers.indexOf(peer)»;
«ENDFOR»
«ENDIF»
«ELSE»
std::vector<Address> «ai.name»_«pi.name»Addresses(1);
«ai.name»_«pi.name»Addresses[0] = addr_item_«pi.path.getPathName()»;
«ENDIF»
«ai.name»_ownInterfaceItemAddresses.push_back(«ai.name»_«pi.name»Addresses);
«ENDFOR»
'''
def generatePeerInterfaceItemAddresses(ActorInstance ai, SubSystemInstance comp) '''
std::vector<std::vector<Address> > «ai.name»_peerInterfaceItemAddresses;
std::vector<Address> «ai.name»_systemPortAddresses(1);
«ai.name»_systemPortAddresses[0] = addr_item_SystemPort_«comp.allContainedInstances.indexOf(ai)»;
«ai.name»_peerInterfaceItemAddresses.push_back(«ai.name»_systemPortAddresses);
«FOR pi : ai.orderedIfItemInstances »
«IF pi.replicated && pi.peers.isEmpty»
«ELSE»
«IF pi.peers.empty»
std::vector<Address> «ai.name»_«pi.name»PeerAddresses;
«ELSE»
std::vector<Address> «ai.name»_«pi.name»PeerAddresses(«pi.peers.size»);
«FOR pp : pi.peers»
«IF pp.replicated»
«ai.name»_«pi.name»PeerAddresses[«pi.peers.indexOf(pp)»] = addr_item_«pp.path.getPathName()»_«pp.peers.indexOf(pi)»;
«ELSE»
«ai.name»_«pi.name»PeerAddresses[«pi.peers.indexOf(pp)»] = addr_item_«pp.path.getPathName()»;
«ENDIF»
«ENDFOR»
«ENDIF»
«ai.name»_peerInterfaceItemAddresses.push_back(«ai.name»_«pi.name»PeerAddresses);
«ENDIF»
«ENDFOR»
'''
}