Skip to content

Commit

Permalink
- Generate the Modelica code for FMI 2.0 Model Exchange fmus.
Browse files Browse the repository at this point in the history
- Added Wrapper functions for FMI 2.0 in libOpenModelicaFMIRuntimeC.

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@16631 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
adeas31 committed Jul 19, 2013
1 parent d7242d2 commit d8e452b
Show file tree
Hide file tree
Showing 10 changed files with 639 additions and 186 deletions.
259 changes: 93 additions & 166 deletions Compiler/Template/CodegenFMU.tpl

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions Compiler/Util/FMI.mo
Expand Up @@ -178,9 +178,12 @@ public function getFMIType
output String fmiType;
algorithm
fmiType := match(inFMIInfo)
case (INFO(fmiType = 0)) then "me";
case (INFO(fmiType = 1)) then "cs_st";
case (INFO(fmiType = 2)) then "cs_tool";
case (INFO(fmiVersion = "1.0", fmiType = 0)) then "me";
case (INFO(fmiVersion = "1.0", fmiType = 1)) then "cs_st";
case (INFO(fmiVersion = "1.0", fmiType = 2)) then "cs_tool";
case (INFO(fmiVersion = "2.0", fmiType = 1)) then "me";
case (INFO(fmiVersion = "2.0", fmiType = 2)) then "cs";
case (INFO(fmiVersion = "2.0", fmiType = 3)) then "me_cs";
end match;
end getFMIType;

Expand Down
47 changes: 35 additions & 12 deletions Compiler/runtime/FMIImpl.c
Expand Up @@ -64,8 +64,8 @@ static void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t l
}
}

/* Logger function used by the FMU internally */
static void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...)
/* Logger function used by the FMU 1.0 internally */
static void fmi1logger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...)
{
va_list argp;
va_start(argp, message);
Expand All @@ -74,6 +74,16 @@ static void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_statu
fflush(NULL);
}

/* Logger function used by the FMU 2.0 internally */
static void fmi2logger(fmi2_component_t c, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message, ...)
{
va_list argp;
va_start(argp, message);
fmi2_log_forwarding_v(c, instanceName, status, category, message, argp);
va_end(argp);
fflush(NULL);
}

/*
* functions that replaces the given character old with the character new in a string
*/
Expand Down Expand Up @@ -604,23 +614,18 @@ int FMIImpl__initializeFMIImport(const char* file_name, const char* working_dire
*experimentAnnotation = NULL;
*modelVariablesInstance = mk_some(0);
*modelVariablesList = NULL;
static int init = 0;
// JM callbacks
static jm_callbacks callbacks;
// FMI callback functions
static fmi1_callback_functions_t callback_functions;
if (!init) {
init = 1;
static int init_jm_callbacks = 0;
if (!init_jm_callbacks) {
init_jm_callbacks = 1;
callbacks.malloc = malloc;
callbacks.calloc = calloc;
callbacks.realloc = realloc;
callbacks.free = free;
callbacks.logger = importlogger;
callbacks.log_level = fmi_log_level;
callbacks.context = 0;
callback_functions.logger = fmilogger;
callback_functions.allocateMemory = calloc;
callback_functions.freeMemory = free;
}
fmi_import_context_t* context = fmi_import_allocate_context(&callbacks);
*fmiContext = mk_some(context);
Expand All @@ -634,6 +639,15 @@ int FMIImpl__initializeFMIImport(const char* file_name, const char* working_dire
return 0;
}
if (version == 1) {
static int init_fmi1_callback_functions = 0;
// FMI callback functions
static fmi1_callback_functions_t fmi1_callback_functions;
if (!init_fmi1_callback_functions) {
init_fmi1_callback_functions = 1;
fmi1_callback_functions.logger = fmi1logger;
fmi1_callback_functions.allocateMemory = calloc;
fmi1_callback_functions.freeMemory = free;
}
// parse the xml file
fmi1_import_t* fmi;
fmi = fmi1_import_parse_xml(context, working_directory);
Expand All @@ -645,7 +659,7 @@ int FMIImpl__initializeFMIImport(const char* file_name, const char* working_dire
*fmiInstance = mk_some(fmi);
// Load the binary (dll/so)
jm_status_enu_t status;
status = fmi1_import_create_dllfmu(fmi, callback_functions, 0);
status = fmi1_import_create_dllfmu(fmi, fmi1_callback_functions, 0);
if (status == jm_status_error) {
fmi1_import_free(fmi);
fmi_import_free_context(context);
Expand All @@ -654,6 +668,15 @@ int FMIImpl__initializeFMIImport(const char* file_name, const char* working_dire
}
FMIImpl__initializeFMI1Import(fmi, fmiInfo, version, experimentAnnotation, modelVariablesInstance, modelVariablesList, input_connectors, output_connectors);
} else if (version == 2) {
static int init_fmi2_callback_functions = 0;
// FMI callback functions
static fmi2_callback_functions_t fmi2_callback_functions;
if (!init_fmi2_callback_functions) {
init_fmi2_callback_functions = 1;
fmi2_callback_functions.logger = fmi2logger;
fmi2_callback_functions.allocateMemory = calloc;
fmi2_callback_functions.freeMemory = free;
}
// parse the xml file
fmi2_import_t* fmi;
fmi = fmi2_import_parse_xml(context, working_directory, NULL);
Expand All @@ -665,7 +688,7 @@ int FMIImpl__initializeFMIImport(const char* file_name, const char* working_dire
*fmiInstance = mk_some(fmi);
// Load the binary (dll/so)
jm_status_enu_t status;
status = fmi2_import_create_dllfmu(fmi, fmi2_import_get_fmu_kind(fmi), NULL);
status = fmi2_import_create_dllfmu(fmi, fmi2_import_get_fmu_kind(fmi), &fmi2_callback_functions);
if (status == jm_status_error) {
fmi2_import_free(fmi);
fmi_import_free_context(context);
Expand Down
7 changes: 2 additions & 5 deletions SimulationRuntime/c/fmi/FMI1Common.h
Expand Up @@ -31,13 +31,10 @@
#ifndef FMI1COMMON__H_
#define FMI1COMMON__H_

#include <stdio.h>
#include <stdlib.h>

#include "fmilib.h"
#include "FMICommon.h"

/*
* Structure used as External Object in the generated Modelica code of the imported FMU.
* Structure used as an External Object in the generated Modelica code of the imported FMU.
* Used for FMI 1.0 Model Exchange.
*/
typedef struct {
Expand Down
1 change: 1 addition & 0 deletions SimulationRuntime/c/fmi/FMI1ModelExchange.c
Expand Up @@ -32,6 +32,7 @@
extern "C" {
#endif

#include "FMICommon.h"
#include "FMI1Common.h"

void* FMI1ModelExchangeConstructor_OMC(int fmi_log_level, char* working_directory, char* instanceName, int debugLogging)
Expand Down
170 changes: 170 additions & 0 deletions SimulationRuntime/c/fmi/FMI2Common.c
@@ -0,0 +1,170 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
* OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

#ifdef __cplusplus
extern "C" {
#endif

#include "FMI2Common.h"

/*
* Used for logging import messages.
*/
void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message)
{
printf("module = %s, log level = %s: %s\n", module, jm_log_level_to_string(log_level), message);fflush(NULL);
}

/*
* Used for logging FMU messages.
* Logger function used by the FMU 2.0 internally.
*/
void fmi2logger(fmi2_component_t c, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message, ...)
{
va_list argp;
va_start(argp, message);
fmi2_log_forwarding_v(c, instanceName, status, category, message, argp);
va_end(argp);
fflush(NULL);
}

/*
* OpenModelica uses signed integers and according to FMI specifications the value references should be unsigned integers.
* So to overcome this we use value references as Real in the Modelica code.
* This function converts back the value references from double to int and use them in FMI specific functions.
*/
fmi2_value_reference_t* real_to_fmi2_value_reference(int numberOfValueReferences, double* valuesReferences)
{
fmi2_value_reference_t* valuesReferences_int = malloc(sizeof(fmi2_value_reference_t)*numberOfValueReferences);
int i;
for (i = 0 ; i < numberOfValueReferences ; i++)
valuesReferences_int[i] = (int)valuesReferences[i];
return valuesReferences_int;
}

/*
* Wrapper for the FMI function fmiGetReal.
* parameter flowStatesInput is dummy and is only used to run the equations in sequence.
* Returns realValues.
*/
void fmi2GetReal_OMC(void* in_fmi2me, int numberOfValueReferences, double* realValuesReferences, double flowStatesInput, double* realValues)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, realValuesReferences);
fmi2_import_get_real(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_real_t*)realValues);
free(valuesReferences_int);
}

/*
* Wrapper for the FMI function fmiSetReal.
* Returns status.
*/
void fmi2SetReal_OMC(void* in_fmi2me, int numberOfValueReferences, double* realValuesReferences, double* realValues, double* out_Values)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, realValuesReferences);
fmi2_import_set_real(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_real_t*)realValues);
}

/*
* Wrapper for the FMI function fmiGetInteger.
* parameter flowStatesInput is dummy and is only used to run the equations in sequence.
* Returns integerValues.
*/
void fmi2GetInteger_OMC(void* in_fmi2me, int numberOfValueReferences, double* integerValuesReferences, double flowStatesInput, int* integerValues)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, integerValuesReferences);
fmi2_import_get_integer(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_integer_t*)integerValues);
free(valuesReferences_int);
}

/*
* Wrapper for the FMI function fmiSetInteger.
* Returns status.
*/
void fmi2SetInteger_OMC(void* in_fmi2me, int numberOfValueReferences, double* integerValuesReferences, int* integerValues, double* out_Values)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, integerValuesReferences);
fmi2_import_set_integer(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_integer_t*)integerValues);
}

/*
* Wrapper for the FMI function fmiGetBoolean.
* parameter flowStatesInput is dummy and is only used to run the equations in sequence.
* Returns booleanValues.
*/
void fmi2GetBoolean_OMC(void* in_fmi2me, int numberOfValueReferences, double* booleanValuesReferences, double flowStatesInput, int* booleanValues)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, booleanValuesReferences);
fmi2_import_get_boolean(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_boolean_t*)booleanValues);
free(valuesReferences_int);
}

/*
* Wrapper for the FMI function fmiSetBoolean.
* Returns status.
*/
void fmi2SetBoolean_OMC(void* in_fmi2me, int numberOfValueReferences, double* booleanValuesReferences, int* booleanValues, double* out_Values)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, booleanValuesReferences);
fmi2_import_set_boolean(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_boolean_t*)booleanValues);
}

/*
* Wrapper for the FMI function fmiGetString.
* parameter flowStatesInput is dummy and is only used to run the equations in sequence.
* Returns stringValues.
*/
void fmi2GetString_OMC(void* in_fmi2me, int numberOfValueReferences, double* stringValuesReferences, double flowStatesInput, char** stringValues)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, stringValuesReferences);
fmi2_import_get_string(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_string_t*)stringValues);
free(valuesReferences_int);
}

/*
* Wrapper for the FMI function fmiSetString.
* Returns status.
*/
void fmi2SetString_OMC(void* in_fmi2me, int numberOfValueReferences, double* stringValuesReferences, char** stringValues, double* out_Values)
{
FMI2ModelExchange* FMI2ME = (FMI2ModelExchange*)in_fmi2me;
fmi2_value_reference_t* valuesReferences_int = real_to_fmi2_value_reference(numberOfValueReferences, stringValuesReferences);
fmi2_import_set_string(FMI2ME->FMIImportInstance, valuesReferences_int, numberOfValueReferences, (fmi2_string_t*)stringValues);
}

#ifdef __cplusplus
}
#endif
57 changes: 57 additions & 0 deletions SimulationRuntime/c/fmi/FMI2Common.h
@@ -0,0 +1,57 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-CurrentYear, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
* OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

#ifndef FMI2COMMON__H_
#define FMI2COMMON__H_

#include "FMICommon.h"

/*
* Structure used as an External Object in the generated Modelica code of the imported FMU.
* Used for FMI 2.0 Model Exchange.
*/
typedef struct {
int FMILogLevel;
jm_callbacks JMCallbacks;
fmi_import_context_t* FMIImportContext;
fmi2_callback_functions_t FMICallbackFunctions;
char* FMIWorkingDirectory;
fmi2_import_t* FMIImportInstance;
char* FMIInstanceName;
int FMIDebugLogging;
int FMIToleranceControlled;
double FMIRelativeTolerance;
fmi2_event_info_t* FMIEventInfo;
} FMI2ModelExchange;

void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message);
void fmi2logger(fmi2_component_t c, fmi2_string_t instanceName, fmi2_status_t status, fmi2_string_t category, fmi2_string_t message, ...);

#endif

0 comments on commit d8e452b

Please sign in to comment.