Program Listing for File fmu_templates.h#
↰ Return to documentation for file (sdv_dbc_util\fmu_templates.h)
const char szBuildDescriptionTemplate[] = R"code(<!--
@file %buiddescription_path%
@date %date%
This file is the fmi Build Description xml.
This file was generated by the DBC utility from:
%dbc_sources%
%dbc_version%
-->
%buildDescription_xml%
)code";
const char szMappingCMakeFileListsTemplate[] = R"code(
# @file %cmakefilelists_path%
# This file is cmake project file.
# This file was generated by the DBC utility from:
# %dbc_sources%
# %dbc_version%
# Based on CMakeLists.txt from https://github.com/modelica/Reference-FMUs
# only FMI 2.0, only CoSimulation
# without fumsim
# Only valid for Windows
if ( WIN32 )
# Enforce CMake version 3.20 or newer needed for path function
cmake_minimum_required (VERSION 3.20)
# Use new policy for project version settings and default warning level
cmake_policy(SET CMP0048 NEW) # requires CMake 3.14
cmake_policy(SET CMP0092 NEW) # requires CMake 3.15
project (%model_Identifier%Project)
# Use C++17 support
set(CMAKE_CXX_STANDARD 17)
# Library symbols are hidden by default
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Set the SDV_FRAMEWORK_DEV_INCLUDE if not defined yet
if (NOT DEFINED SDV_FRAMEWORK_DEV_INCLUDE)
if (NOT DEFINED ENV{SDV_FRAMEWORK_DEV_INCLUDE})
message( FATAL_ERROR "The environment variable SDV_FRAMEWORK_DEV_INCLUDE needs to be pointing to the SDV V-API development include files location!")
endif()
set (SDV_FRAMEWORK_DEV_INCLUDE "$ENV{SDV_FRAMEWORK_DEV_INCLUDE}")
endif()
# Include link to export directory of SDV V-API development include files location
include_directories(${SDV_FRAMEWORK_DEV_INCLUDE})
set(VAPI_CORE_SDV_BINARY_DIR ${CMAKE_BINARY_DIR}/bin)
set(MODEL_NAME %model_Identifier%)
set(TARGET_NAME ${MODEL_NAME})
set(FMU_FULL_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/fmus/${MODEL_NAME}.fmu")
FUNCTION(cat IN_FILE OUT_FILE)
file(READ ${IN_FILE} CONTENTS)
file(APPEND ${OUT_FILE} "${CONTENTS}")
ENDFUNCTION()
set(FMI_VERSION 2 CACHE STRING "FMI Version")
set_property(CACHE FMI_VERSION PROPERTY STRINGS 2)
set(FMI_TYPE CS CACHE STRING "FMI Version")
set_property(CACHE FMI_TYPE PROPERTY STRINGS CS)
set(FMI_TYPE "")
set (FMI_PLATFORM win32)
if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
set (FMI_PLATFORM win64)
endif ()
SET(HEADERS
${MODEL_NAME}/config.h
include/cosimulation.h
include/model.h
)
SET(HEADERS
${HEADERS}
include/fmi2Functions.h
include/fmi2FunctionTypes.h
include/fmi2TypesPlatform.h
)
SET(SOURCES
${MODEL_NAME}/model.cpp
src/fmi${FMI_VERSION}Functions.c
src/cosimulation.c
)
add_library(${TARGET_NAME} SHARED
${HEADERS}
${SOURCES}
${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
${MODEL_NAME}/buildDescription.xml
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fmus)
set(FMU_BUILD_DIR temp/${MODEL_NAME})
target_compile_definitions(${TARGET_NAME} PRIVATE
FMI_VERSION=${FMI_VERSION}
DISABLE_PREFIX
)
#[[
if (MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc")
endif()
]]
target_compile_definitions(${TARGET_NAME} PRIVATE FMI_COSIMULATION)
target_include_directories(${TARGET_NAME} PRIVATE include ${MODEL_NAME})
target_link_libraries(${TARGET_NAME} Winmm Ws2_32 Rpcrt4.lib)
set_target_properties(${TARGET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
LIBRARY_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${FMU_BUILD_DIR}/binaries/${FMI_PLATFORM}"
)
set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "")
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${MODEL_NAME})
# modelDescription.xml
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/FMI${FMI_VERSION}${FMI_TYPE}.xml
"${FMU_BUILD_DIR}/modelDescription.xml"
)
set(ARCHIVE_FILES "modelDescription.xml" "binaries")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources")
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/${MODEL_NAME}/resources"
"${FMU_BUILD_DIR}/resources/"
)
set(ARCHIVE_FILES ${ARCHIVE_FILES} "resources")
endif()
# When windows robocopy command (using cmd.exe) is used to copy files its important to set the dependencies
# to assure that the copy command is finished before the next custom action to avoid copy/file access failures
# Copy sdv binaries of this FMU
set(DEST_DIR "${FMU_BUILD_DIR}/resources")
set(SOURCE_DIR_EXAMPLES_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
add_custom_target(copy_function_sdv_files_${TARGET_NAME} DEPENDS ${TARGET_NAME})
add_custom_command(TARGET copy_function_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_EXAMPLES_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_EXAMPLES_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_function_sdv_files_${TARGET_NAME} ${TARGET_NAME})
# Copy framework sdv binaries
set(SOURCE_DIR_CORE_BIN "${SDV_FRAMEWORK_RUNTIME}")
add_custom_target(copy_framework_sdv_files_${TARGET_NAME} DEPENDS copy_function_sdv_files_${TARGET_NAME})
add_custom_command(TARGET copy_framework_sdv_files_${TARGET_NAME}
COMMAND cmd /C "robocopy \"${SOURCE_DIR_CORE_BIN}\" \"${DEST_DIR}\" *.pdb *.sdv /NP /R:3 /W:5 || exit /b 0"
COMMENT "Copying contents from ${SOURCE_DIR_CORE_BIN} to ${DEST_DIR}, include only *.pdb *.sdv files"
)
add_dependencies(copy_framework_sdv_files_${TARGET_NAME} copy_function_sdv_files_${TARGET_NAME})
# FMU content created, all files copied
# to zip the files create a new target 'create_zip' which is build after all files have been copied
add_custom_target(create_zip_${TARGET_NAME} ALL DEPENDS copy_framework_sdv_files_${TARGET_NAME} )
add_custom_command(TARGET create_zip_${TARGET_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E tar "cfv" ${FMU_FULL_FILE_NAME} --format=zip ${ARCHIVE_FILES}
WORKING_DIRECTORY ${FMU_BUILD_DIR}
COMMENT "Creating ZIP ${FMU_FULL_FILE_NAME}"
)
add_dependencies(create_zip_${TARGET_NAME} copy_framework_sdv_files_${TARGET_NAME})
#TODO
#add_dependencies(${TARGET_NAME} <add_cmake_target_this_depends_on>)
endif ()
)code";
const char szConfigHTemplate[] = R"code(
#ifndef %safeguardconfig%
#define %safeguardconfig%
#include <stdint.h>
// define class name and unique id
#define MODEL_IDENTIFIER %model_Identifier%
#define INSTANTIATION_TOKEN "%model_guid%"
#define FMI_VERSION 2
#define CO_SIMULATION
// define model size
#define NX 0
#define NZ 0
#define GET_INT32
#define SET_INT32
#define GET_FLAOT64
#define SET_FLOAT64
#define EVENT_UPDATE
#define CLEAN_UP
#define FIXED_SOLVER_STEP 0.04
#define DEFAULT_STOP_TIME 10
typedef enum {
%value_reference%
} ValueReference;
typedef struct {
%model_data%
} ModelData;
#endif // !defined %safeguardconfig%
)code";
const char szFMI2XMLTemplate[] = R"code(<?xml version="1.0" encoding="UTF-8"?>
<fmiModelDescription
fmiVersion = "2.0"
modelName = "%model_Identifier%"
guid = "%model_guid%"
description = "TargetLink FMU for %model_Identifier%"
generationTool = "TargetLink was generated by the DBC utility: %dbc_sources%"
generationDateAndTime = "%date%"
variableNamingConvention = "structured"
numberOfEventIndicators = "0">
<CoSimulation
modelIdentifier = "%model_Identifier%"
canHandleVariableCommunicationStepSize = "false"
canGetAndSetFMUstate = "false"
canSerializeFMUstate = "false"
providesDirectionalDerivative = "false"
canBeInstantiatedOnlyOncePerProcess = "true"
canInterpolateInputs = "false"
canRunAsynchronuously = "false">
<SourceFiles>
<File name="all.c"/>
</SourceFiles>
</CoSimulation>
<DefaultExperiment startTime="0" stepSize="0.01"/>
<ModelVariables>
%model_variables%
</ModelVariables>
<ModelStructure>
<Outputs>
<Unknown index="%unknown_index%"/>
</Outputs>
</ModelStructure>
</fmiModelDescription>
)code";
const char szModelCPPTemplate[] = R"code(
#include <memory>
#include <vector>
#include <iostream>
#include <fstream>
#include <support/timer.h>
#include "signal_identifier.h"
#include <support/signal_support.h>
#include <support/app_control.h>
%global_signals%
// in case the simulation timer should be used
sdv::core::ITimerSimulationStep* g_pTimerSimulationStep;
std::unique_ptr<sdv::app::CAppControl> g_appcontrol;
bool InitializeAppControl(const std::string& resource, const std::string& configFileName)
{
auto bResult = g_appcontrol->AddModuleSearchDir( resource );
bResult &= g_appcontrol->Startup("");
g_appcontrol->SetConfigMode();
bResult &= g_appcontrol->AddConfigSearchDir( resource );
if (!configFileName.empty())
{
bResult &= g_appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
}
return bResult;
}
sdv::core::EConfigProcessResult RegisterAllSignals()
{
std::string msg = "register all signals: ";
sdv::core::CDispatchService dispatch;
%global_signals_register%
%global_signals_register_check%
return sdv::core::EConfigProcessResult::failed;
}
bool ResetAllSignals()
{
sdv::core::CDispatchService dispatch;
%global_signals_reset%
SDV_LOG_INFO("Reset signals");
return true;
}
bool CreateCoreServiceTomlFile(const std::string& resources)
{
std::ofstream tomlFile("sdv_core_reloc.toml");
if (tomlFile.is_open())
{
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
tomlFile << resources;
tomlFile << "\"\n";
tomlFile.close();
return true;
}
return false;
}
bool OpenAPILoad(const std::string& resources)
{
bool success = CreateCoreServiceTomlFile(resources);
g_appcontrol = std::make_unique<sdv::app::CAppControl> ();
//
// TODO: Dispatch service must be loaded first, adjust the correct toml file
//
success &= InitializeAppControl(resources, "data_dispatch_config_file.toml");
if (!success)
{
std::cout << "Error: InitializeAppControl() failed" << std::endl;
SDV_LOG_ERROR("Failed InitializeAppControl");
return false;
}
success &= RegisterAllSignals() == sdv::core::EConfigProcessResult::successful;
if (!success)
{
SDV_LOG_ERROR("Signals could not be registered");
}
%vapi_load_config_files%
g_appcontrol->SetRunningMode();
return success;
}
void OpenAPIShutdown()
{
ResetAllSignals();
}
#ifdef __cplusplus
extern "C" {
#endif
#include <float.h> // for DBL_EPSILON
#include <math.h> // for fabs()
#include "config.h"
#include "model.h"
Status cleanup(ModelInstance*)
{
SDV_LOG_INFO("Shutting down...");
OpenAPIShutdown();
return OK;
}
bool setStartValues(ModelInstance* comp)
{
std::string path(comp->resourceLocation);
std::string resourcePath = path.substr(8);
std::replace(resourcePath.begin(), resourcePath.end(), '\\', '/');
if (!OpenAPILoad(resourcePath))
{
std::cout << "Error: OpenAPILoad() failed." << std::endl;
comp->terminateSimulation = true;
return false;
}
// TODO: move this to initialize()?
comp->nextEventTime = 0;
comp->nextEventTimeDefined = true;
return true;
}
Status calculateValues(ModelInstance* comp)
{
UNUSED(comp);
// nothing to do
return OK;
}
Status getFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
%getFloat64%
return OK;
}
Status getInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
%getInt32%
return OK;
}
Status setFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
%setFloat64%
return OK;
}
Status setInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
{
ASSERT_NVALUES(1);
%setInt32%
return OK;
}
void eventUpdate(ModelInstance* comp)
{
%event_update%
double epsilon = (1.0 + fabs(comp->time)) * DBL_EPSILON;
if (comp->nextEventTimeDefined && comp->time + epsilon >= comp->nextEventTime) {
comp->nextEventTime += FIXED_SOLVER_STEP;
}
comp->valuesOfContinuousStatesChanged = false;
comp->nominalsOfContinuousStatesChanged = false;
comp->terminateSimulation = false;
comp->nextEventTimeDefined = true;
}
#ifdef __cplusplus
} // end of extern "C"
#endif
)code";
const char szMappingSignalIdentifierTemplate[] = R"code(
#ifndef %safeguardsignalidentifier%
#define %safeguardsignalidentifier%
namespace %object_prefix%
{
// Data Dispatch Service signal names to dbc variable names C-type RX/TX vss name space
%signals%
} // %object_prefix%
#endif // %safeguardsignalidentifier%
)code";
const char szDataDispatchServiceTomlFile[] = R"code([Configuration]
Version = 100
[[Component]]
Path = "data_dispatch_service.sdv"
Class = "DataDispatchService"
)code";
const char szSimulationTaskTimerServiceTomlFile[] = R"code([Configuration]
Version = 100
[[Component]]
Path = "simulation_task_timer.sdv"
Class = "SimulationTaskTimerService"
)code";
const char szTaskTimerhServiceTomlFile[] = R"code([Configuration]
Version = 100
[[Component]]
Path = "task_timer.sdv"
Class = "TaskTimerService"
)code";