blob: aaa4aae70fec5e4e15c7ccca9e5f6dcf93d0aebf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Draeger Medical GmbH (http://www.draeger.com).
* 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:
* Peter Karlitschek (initial contribution)
*
*******************************************************************************/
package org.eclipse.etrice.generator.cpp.gen
import com.google.inject.Inject
import com.google.inject.Singleton
import java.util.Collection
import java.util.Map
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.builder.GenmodelConstants
import org.eclipse.etrice.core.genmodel.etricegen.Root
import org.eclipse.etrice.core.genmodel.etricegen.SubSystemInstance
import org.eclipse.etrice.core.genmodel.etricegen.WiredSubSystemClass
import org.eclipse.etrice.core.genmodel.fsm.fsmgen.IDiagnostician
import org.eclipse.etrice.core.room.SubSystemClass
import org.eclipse.etrice.generator.cpp.Main
import org.eclipse.etrice.generator.fsm.base.FileSystemHelpers
import org.eclipse.etrice.generator.fsm.base.IGeneratorFileIo
import org.eclipse.etrice.generator.generic.ProcedureHelpers
import org.eclipse.etrice.generator.generic.RoomExtensions
import static extension org.eclipse.etrice.generator.fsm.base.Indexed.*
import org.eclipse.etrice.core.common.converter.TimeConverter
@Singleton
class NodeGen {
@Inject extension CppExtensions
@Inject extension RoomExtensions
@Inject extension ProcedureHelpers
@Inject extension FileSystemHelpers
@Inject IGeneratorFileIo fileIO
@Inject IDiagnostician diagnostician
def doGenerate(Root root) {
val Map<SubSystemClass, WiredSubSystemClass> sscc2wired = newHashMap
root.wiredInstances.filter(typeof(WiredSubSystemClass)).forEach[sscc2wired.put(subSystemClass, it)]
for (nr : ETMapUtil::getNodeRefs()) {
for (instpath : ETMapUtil::getSubSystemInstancePaths(nr)) {
val ssi = root.getInstance(instpath) as SubSystemInstance
if (ssi!=null && ssi.subSystemClass.validGenerationLocation) {
val wired = sscc2wired.get(ssi.subSystemClass)
val path = ssi.subSystemClass.generationTargetPath+ssi.subSystemClass.getPath
val infopath = ssi.subSystemClass.generationInfoPath+ssi.subSystemClass.getPath
//checkDataPorts(ssi)
val usedThreads = ETMapUtil::getUsedThreads(nr, ssi)
fileIO.generateFile("generating Node declaration", path, infopath, getCppHeaderFileName(nr, ssi), root.generateHeaderFile(ssi, wired, usedThreads))
fileIO.generateFile("generating Node implementation", path, infopath, getCppSourceFileName(nr, ssi), root.generateSourceFile(ssi, wired, usedThreads))
}
}
}
}
def generateHeaderFile(Root root, SubSystemInstance comp, WiredSubSystemClass wired, Collection<PhysicalThread> usedThreads) {
val cc = comp.subSystemClass
val models = root.getReferencedModels(cc)
val nr = ETMapUtil::getNodeRef(comp)
val clsname = nr.getCppClassName(comp)
val threads = nr.type.threads.filter(t|usedThreads.contains(t))
'''
/**
* @author generated by eTrice
*
* Header File of SubSystemClass «clsname»
*
*/
«generateIncludeGuardBegin(clsname)»
#include "common/modelbase/SubSystemClassBase.h"
««« «FOR model : root.getReferencedModels(cc)»
««« ««« #include "«model.name».h"
««« «ENDFOR»
«cc.userCode(1, false)»
class «clsname» : public etRuntime::SubSystemClassBase{
«cc.userCode(2, false)»
public:
«FOR thread : threads.indexed»
static const int «thread.value.threadId»;
«ENDFOR»
«clsname»(IRTObject* parent, const std::string& name);
virtual void receiveEvent(etRuntime::InterfaceItemBase* ifitem, int evt, void* data);
virtual void instantiateMessageServices();
virtual void instantiateActors();
virtual void init();
«IF Main::settings.generateMSCInstrumentation»
etBool hasGeneratedMSCInstrumentation() const { return true; }
virtual void destroy();
«ENDIF»
private:
«clsname»();
«clsname»(«clsname» const&);
«clsname»& operator=(«clsname» const&);
};
«generateIncludeGuardEnd(cc.name)»
'''
}
def private getThreadId(PhysicalThread thread) {
"THREAD_"+thread.name.toUpperCase
}
def generateSourceFile(Root root, SubSystemInstance comp, WiredSubSystemClass wired, Collection<PhysicalThread> usedThreads) {
val cc = comp.subSystemClass
val models = root.getReferencedModels(cc)
val nr = ETMapUtil::getNodeRef(comp)
val clsname = nr.getCppClassName(comp)
val threads = nr.type.threads.filter(t|usedThreads.contains(t))
'''
/**
* @author generated by eTrice
*
* Source File of SubsystemClass «clsname»
*
*/
#include "«getCppHeaderFileName(nr, comp)»"
#include "common/debugging/DebuggingService.h"
#include "common/messaging/IMessageService.h"
#include "common/messaging/MessageService.h"
#include "common/messaging/MessageServiceController.h"
#include "common/messaging/RTServices.h"
#include "common/modelbase/InterfaceItemBase.h"
«FOR ai : comp.actorInstances»
#include "«ai.actorClass.actorIncludePath»"
«ENDFOR»
#include <iostream>
using namespace etRuntime;
«FOR thread : threads.indexed»
const int «clsname»::«thread.value.threadId» = «thread.index0»;
«ENDFOR»
«clsname»::«clsname»(IRTObject* parent, const std::string& name) :
SubSystemClassBase(parent, name)
{
}
void «clsname»::receiveEvent(InterfaceItemBase* ifitem, int evt, void* data){
}
void «clsname»::instantiateMessageServices(){
IMessageService* msgService;
«FOR thread: threads»
{
«IF thread.execmode==ExecMode::POLLED || thread.execmode==ExecMode::MIXED»
etTime interval;
interval.sec = «TimeConverter::split(thread.time, TimeConverter.SEC, true)»;
interval.nSec = «TimeConverter::split(thread.time, TimeConverter.MILLI_SEC, false)»L;
msgService = new MessageService(this, IMessageService::«thread.execmode.getName», interval, 0, «thread.threadId», "MessageService_«thread.name»", «thread.prio»);
«ELSE»
msgService = new MessageService(this, IMessageService::«thread.execmode.getName», 0, «thread.threadId», "MessageService_«thread.name»", «thread.prio»);
«ENDIF»
RTServices::getInstance().getMsgSvcCtrl().addMsgSvc(*msgService);
}
«ENDFOR»
}
void «clsname»::instantiateActors(){
// thread mappings
«FOR ai : comp.allContainedInstances»
«val mapped = ETMapUtil::getMappedThread(ai)»
«IF !(mapped.implicit || mapped.asParent)»
addPathToThread("«ai.path»", «mapped.thread.threadId»);
«ENDIF»
«ENDFOR»
// sub actors
«FOR sub : cc.actorRefs»
«IF sub.multiplicity>1»
for (int i=0; i<«sub.multiplicity»; ++i) {
«IF Main::settings.generateMSCInstrumentation»
DebuggingService::getInstance().addMessageActorCreate(*this, "«sub.name»«GenmodelConstants::INDEX_SEP»"+i);
«ENDIF»
new «sub.type.implementationClassName»(this, "«sub.name»«GenmodelConstants::INDEX_SEP»"+i);
}
«ELSE»
«IF Main::settings.generateMSCInstrumentation»
DebuggingService::getInstance().addMessageActorCreate(*this, "«sub.name»");
«ENDIF»
new «sub.type.implementationClassName»(this, "«sub.name»");
«ENDIF»
«ENDFOR»
// wiring
«FOR wire: wired.wires»
«if (wire.dataDriven) "DataPortBase" else "InterfaceItemBase"»::connect(this, "«wire.path1.join('/')»", "«wire.path2.join('/')»");
«ENDFOR»
}
void «clsname»::init(){
«IF Main::settings.generateMSCInstrumentation»
DebuggingService::getInstance().addVisibleComment("begin sub system initialization");
«ENDIF»
SubSystemClassBase::init();
«IF Main::settings.generateMSCInstrumentation»
DebuggingService::getInstance().addVisibleComment("done sub system initialization");
«ENDIF»
}
«IF Main::settings.generateMSCInstrumentation»
void «clsname»::destroy() {
DebuggingService::getInstance().addVisibleComment("begin sub system destruction");
SubSystemClassBase::destroy();
DebuggingService::getInstance().addVisibleComment("done sub system destruction");
}
«ENDIF»
'''
}
}