diff --git a/libs/util/src/win/os.c b/libs/util/src/win/os.c
index ed71dac..66742ad 100644
--- a/libs/util/src/win/os.c
+++ b/libs/util/src/win/os.c
@@ -87,10 +87,25 @@ const char * mcx_os_get_errno_descr(int errnum) {
int mcx_os_path_exists(const char * path) {
int ret;
- wchar_t * wPath = mcx_string_to_widechar(path);
+ char * absoluteNormalizedPath = NULL;
+ wchar_t * wPath = NULL;
+
+ absoluteNormalizedPath = mcx_os_path_normalize(path);
+ if (path && !absoluteNormalizedPath) {
+ mcx_log(LOG_ERROR, "Util: Could not convert path '%s' to a normalized absolute path", path);
+ return 0;
+ }
+
+ wPath = mcx_string_to_widechar(absoluteNormalizedPath);
+
+ if (absoluteNormalizedPath) {
+ mcx_free(absoluteNormalizedPath);
+ }
ret = (_waccess(wPath, 0) != -1);
- mcx_free(wPath);
+ if (wPath) {
+ mcx_free(wPath);
+ }
return ret;
}
diff --git a/src/CentralParts.h b/src/CentralParts.h
index 7740e94..653e54d 100644
--- a/src/CentralParts.h
+++ b/src/CentralParts.h
@@ -100,7 +100,6 @@ typedef enum DecoupleTypeDef {
DECOUPLE_ALWAYS = 0x4
} DecoupleType;
-// Note: the enum values are mandatory because the enum is used in integer context
typedef enum PolyOrderTypeDef {
POLY_CONSTANT = 0
, POLY_LINEAR = 1
@@ -150,6 +149,7 @@ typedef enum StoreLevel {
STORE_NONE = 1,
STORE_SYNCHRONIZATION = 2,
STORE_COUPLING = 3,
+ STORE_MICRO = 4,
} StoreLevel;
typedef enum {
diff --git a/src/components/ComponentTypes.c b/src/components/ComponentTypes.c
index 7cc989f..503824e 100644
--- a/src/components/ComponentTypes.c
+++ b/src/components/ComponentTypes.c
@@ -38,8 +38,10 @@ OBJECT_CLASS(ComponentType, Object);
/*****************************************************************************/
/* ComponentTypeConstant */
/*****************************************************************************/
+const char * const compConstantTypeString = "CONSTANT";
+
static const char * ComponentTypeConstantToString(ComponentType * type) {
- return "CONSTANT";
+ return compConstantTypeString;
}
static void ComponentTypeConstantDestructor(ComponentTypeConstant * type) {
diff --git a/src/components/ComponentTypes.h b/src/components/ComponentTypes.h
index a4043be..0152de7 100644
--- a/src/components/ComponentTypes.h
+++ b/src/components/ComponentTypes.h
@@ -28,6 +28,7 @@ struct ComponentType {
};
+extern const char * const compConstantTypeString;
extern const ObjectClass _ComponentTypeConstant;
typedef struct ComponentTypeConstant {
ComponentType _;
diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c
index 5e1f472..95daef9 100644
--- a/src/components/comp_constant.c
+++ b/src/components/comp_constant.c
@@ -18,12 +18,6 @@ extern "C" {
#endif /* __cplusplus */
-typedef struct CompConstant {
- Component _;
-
- ChannelValue ** values;
-} CompConstant;
-
static McxStatus Read(Component * comp, ComponentInput * input, const struct Config * const config) {
CompConstant * compConstant = (CompConstant *)comp;
ConstantInput * constantInput = (ConstantInput *)input;
@@ -62,6 +56,43 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con
return RETURN_OK;
}
+static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) {
+ Component * comp = (Component *) (compConstant);
+ Databus * db = comp->GetDatabus(comp);
+ size_t numVecOut = DatabusGetOutVectorChannelsNum(db);
+ size_t i = 0;
+ size_t sum = 0;
+ ChannelValue * value = NULL;
+ VectorChannelInfo * vInfo = NULL;
+ size_t numCh = 0;
+ size_t startIdx = 0;
+ size_t endIdx = 0;
+
+ for (i = 0; i < numVecOut; i++) {
+ vInfo = DatabusGetOutVectorChannelInfo(db, i);
+ startIdx = vInfo->GetStartIndex(vInfo);
+ endIdx = vInfo->GetEndIndex(vInfo);
+ numCh = endIdx - startIdx + 1;
+
+ sum += numCh;
+ if (sum > idx) {
+ break;
+ }
+ }
+
+ if (i >= numVecOut) {
+ ComponentLog(comp, LOG_ERROR, "GetValue: Invalid index (%zu) provided", idx);
+ return NULL;
+ }
+
+ value = compConstant->values[i];
+ if (!vInfo->IsScalar(vInfo)) {
+ value += idx - (sum - numCh);
+ }
+
+ return value;
+}
+
static McxStatus Setup(Component * comp) {
CompConstant * constComp = (CompConstant *)comp;
McxStatus retVal = RETURN_OK;
@@ -118,13 +149,15 @@ static void CompConstantDestructor(CompConstant * compConst) {
static Component * CompConstantCreate(Component * comp) {
CompConstant * self = (CompConstant *)comp;
- // map to local funciotns
+ // map to local functions
comp->Read = Read;
comp->Setup = Setup;
comp->Initialize = Initialize;
comp->GetFinishState = CompConstantGetFinishState;
+ // local functions
+ self->GetValue = GetValue;
// local values
self->values = NULL;
diff --git a/src/components/comp_constant.h b/src/components/comp_constant.h
index 46e5b14..5c2957e 100644
--- a/src/components/comp_constant.h
+++ b/src/components/comp_constant.h
@@ -12,13 +12,28 @@
#define MCX_COMPONENTS_COMP_CONSTANT_H
#include "core/Component.h"
+#include "core/channels/ChannelValue.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
+
+typedef struct CompConstant CompConstant;
+
extern const struct ObjectClass _CompConstant;
+typedef ChannelValue * (*fCompConstantGetValue)(CompConstant * compConstant, size_t idx);
+
+struct CompConstant {
+ Component _;
+
+ fCompConstantGetValue GetValue;
+
+ ChannelValue ** values;
+};
+
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif /* __cplusplus */
diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c
index 4b3fee0..8dd698c 100644
--- a/src/components/comp_fmu.c
+++ b/src/components/comp_fmu.c
@@ -13,6 +13,8 @@
#include "FMI/fmi_import_context.h"
#include "components/comp_fmu_impl.h"
#include "core/Databus.h"
+#include "core/Component_impl.h"
+#include "core/channels/ChannelInfo.h"
#include "fmilib.h"
#include "fmu/Fmu1Value.h"
#include "fmu/Fmu2Value.h"
@@ -54,9 +56,9 @@ static McxStatus Fmu1SetupDatabus(Component * comp) {
jm_status_enu_t status = jm_status_success;
- const char * channelName = info->GetNameInTool(info);
+ const char * channelName = info->nameInTool;
if (NULL == channelName) {
- channelName = info->GetName(info);
+ channelName = ChannelInfoGetName(info);
}
var = fmi1_import_get_variable_by_name(fmu1->fmiImport, channelName);
@@ -65,10 +67,10 @@ static McxStatus Fmu1SetupDatabus(Component * comp) {
return RETURN_ERROR;
}
- if (info->GetType(info) != Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))) {
+ if (info->type != Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))) {
ComponentLog(comp, LOG_ERROR, "Variable types of %s do not match", channelName);
ComponentLog(comp, LOG_ERROR, "Expected: %s, Imported from FMU: %s",
- ChannelTypeToString(info->GetType(info)), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))));
+ ChannelTypeToString(info->type), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))));
return RETURN_ERROR;
}
@@ -103,9 +105,9 @@ static McxStatus Fmu1SetupDatabus(Component * comp) {
fmi1_import_variable_t * var = NULL;
jm_status_enu_t status = jm_status_success;
- const char * channelName = info->GetNameInTool(info);
+ const char * channelName = info->nameInTool;
if (NULL == channelName) {
- channelName = info->GetName(info);
+ channelName = ChannelInfoGetName(info);
}
var = fmi1_import_get_variable_by_name(fmu1->fmiImport, channelName);
@@ -114,10 +116,10 @@ static McxStatus Fmu1SetupDatabus(Component * comp) {
return RETURN_ERROR;
}
- if (info->GetType(info) != Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))) {
+ if (info->type != Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))) {
ComponentLog(comp, LOG_ERROR, "Variable types of %s do not match", channelName);
ComponentLog(comp, LOG_ERROR, "Expected: %s, Imported from FMU: %s",
- ChannelTypeToString(info->GetType(info)), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))));
+ ChannelTypeToString(info->type), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))));
return RETURN_ERROR;
}
@@ -385,15 +387,15 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat
Fmu2Value * val = (Fmu2Value *) vals->At(vals, i);
if (DatabusChannelInIsValid(db, i)) {
- const char * channelName = info->GetNameInTool(info);
+ const char * channelName = info->nameInTool;
if (NULL == channelName) {
- channelName = info->GetName(info);
+ channelName = ChannelInfoGetName(info);
}
val->SetChannel(val, info->channel);
- if (val->val.type != info->GetType(info)) {
- ChannelValueInit(&val->val, info->GetType(info));
+ if (val->val.type != info->type) {
+ ChannelValueInit(&val->val, info->type);
}
retVal = DatabusSetInReference(db, i,
ChannelValueReference(&val->val),
@@ -423,13 +425,13 @@ static McxStatus Fmu2SetupChannelOut(ObjectContainer /* Fmu2Values */ * vals, Da
ChannelInfo * info = DatabusInfoGetChannel(dbInfo, i);
Fmu2Value * val = (Fmu2Value *) vals->At(vals, i);
- const char * channelName = info->GetNameInTool(info);
+ const char * channelName = info->nameInTool;
if (NULL == channelName) {
- channelName = info->GetName(info);
+ channelName = ChannelInfoGetName(info);
}
- if (val->val.type != info->GetType(info)) {
- ChannelValueInit(&val->val, info->GetType(info));
+ if (val->val.type != info->type) {
+ ChannelValueInit(&val->val, info->type);
}
retVal = DatabusSetOutReference(db, i,
ChannelValueReference(&val->val),
@@ -509,13 +511,13 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab
Fmu2Value * val = NULL;
fmi2_import_variable_t * var = NULL;
- const char * channelName = info->GetNameInTool(info);
+ const char * channelName = info->nameInTool;
if (NULL == channelName) {
- channelName = info->GetName(info);
+ channelName = ChannelInfoGetName(info);
}
// TODO: move content of if-else blocks to separate functions
- if (info->IsBinary(info)) {
+ if (ChannelInfoIsBinary(info)) {
// see https://github.com/OpenSimulationInterface/osi-sensor-model-packaging for more info
char * channelNameLo = mcx_string_merge(2, channelName, ".base.lo");
char * channelNameHi = mcx_string_merge(2, channelName, ".base.hi");
@@ -580,10 +582,10 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab
return RETURN_ERROR;
}
- if (info->GetType(info) != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))) {
+ if (info->type != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))) {
mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelName);
mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix,
- ChannelTypeToString(info->GetType(info)),
+ ChannelTypeToString(info->type),
ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))));
return RETURN_ERROR;
}
@@ -620,12 +622,12 @@ static McxStatus Fmu2ReadChannelOut(ObjectContainer /* Fmu2Value */ * vals, Data
Fmu2Value * val = NULL;
fmi2_import_variable_t * var = NULL;
- const char * channelName = info->GetNameInTool(info);
+ const char * channelName = info->nameInTool;
if (NULL == channelName) {
- channelName = info->GetName(info);
+ channelName = ChannelInfoGetName(info);
}
- if (info->IsBinary(info)) {
+ if (ChannelInfoIsBinary(info)) {
char * channelNameLo = mcx_string_merge(2, channelName, ".base.lo");
char * channelNameHi = mcx_string_merge(2, channelName, ".base.hi");
char * channelNameSize = mcx_string_merge(2, channelName, ".size");
@@ -689,10 +691,10 @@ static McxStatus Fmu2ReadChannelOut(ObjectContainer /* Fmu2Value */ * vals, Data
return RETURN_ERROR;
}
- if (info->GetType(info) != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))) {
+ if (info->type != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))) {
mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelName);
mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s",
- ChannelTypeToString(info->GetType(info)), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))));
+ ChannelTypeToString(info->type), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))));
return RETURN_ERROR;
}
@@ -852,6 +854,24 @@ static McxStatus Fmu2Read(Component * comp, ComponentInput * input, const struct
return RETURN_OK;
}
+static McxStatus Fmu2CollectConnectedInputs(Component * comp) {
+ CompFMU * compFmu = (CompFMU *)comp;
+ size_t num = compFmu->fmu2.in->Size(compFmu->fmu2.in);
+
+ for (size_t i = 0; i < num; i++) {
+ Fmu2Value * val = (Fmu2Value *)compFmu->fmu2.in->At(compFmu->fmu2.in, i);
+
+ if (val->channel && val->channel->IsConnected(val->channel)) {
+ McxStatus retVal = compFmu->fmu2.connectedIn->PushBack(compFmu->fmu2.connectedIn, (Object *)val);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+ }
+ }
+
+ return RETURN_OK;
+}
+
static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime) {
CompFMU * compFmu = (CompFMU *) comp;
int a = FALSE;
@@ -863,7 +883,6 @@ static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime
McxStatus retVal = RETURN_OK;
-
// Set variables
retVal = Fmu2SetVariableArray(fmu2, fmu2->params);
if (RETURN_OK != retVal) {
@@ -958,12 +977,14 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double
McxStatus retVal;
fmi2_status_t status = fmi2_status_ok;
+ TimeSnapshotStart(&comp->data->rtData.funcTimings.rtInput);
// Set variables
- retVal = Fmu2SetVariableArray(fmu2, fmu2->in);
+ retVal = Fmu2SetVariableArray(fmu2, fmu2->connectedIn);
if (RETURN_OK != retVal) {
ComponentLog(comp, LOG_ERROR, "Setting inChannels failed");
return RETURN_ERROR;
}
+ TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtInput);
// Do calculations
status = fmi2_import_do_step(fmu2->fmiImport, compFmu->lastCommunicationTimePoint, deltaTime, fmi2_true);
@@ -1008,22 +1029,6 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double
compFmu->lastCommunicationTimePoint += deltaTime;
- // Get outputs
- retVal = Fmu2GetVariableArray(fmu2, fmu2->out);
- if (RETURN_OK != retVal) {
- ComponentLog(comp, LOG_ERROR, "Retrieving outChannels failed");
- return RETURN_ERROR;
- }
-
- // local variables
- if (compFmu->localValues) {
- retVal = Fmu2GetVariableArray(fmu2, fmu2->localValues);
- if (RETURN_OK != retVal) {
- ComponentLog(comp, LOG_ERROR, "Retrieving local variables failed");
- return RETURN_ERROR;
- }
- }
-
return RETURN_OK;
}
@@ -1287,6 +1292,7 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) {
Fmu2CommonStruct * fmu2 = &comp_fmu->fmu2;
McxStatus retVal;
+ TimeSnapshotStart(&comp->data->rtData.funcTimings.rtOutput);
retVal = Fmu2GetVariableArray(fmu2, fmu2->out);
if (RETURN_OK != retVal) {
ComponentLog(comp, LOG_ERROR, "Initialization computation failed");
@@ -1298,6 +1304,7 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) {
ComponentLog(comp, LOG_ERROR, "Initialization computation failed");
return RETURN_ERROR;
}
+ TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtOutput);
return RETURN_OK;
}
@@ -1359,6 +1366,8 @@ static Component * CompFMUCreate(Component * comp) {
comp->DoStep = Fmu2DoStep;
comp->Setup = CompFmuSetup;
+ comp->OnConnectionsDone = Fmu2CollectConnectedInputs;
+
comp->UpdateInChannels = Fmu2UpdateInChannels;
comp->UpdateInitialOutChannels = Fmu2UpdateOutChannels;
comp->UpdateOutChannels = Fmu2UpdateOutChannels;
diff --git a/src/core/Component.c b/src/core/Component.c
index ef09db6..eb05b1c 100644
--- a/src/core/Component.c
+++ b/src/core/Component.c
@@ -17,7 +17,6 @@
#include "core/Model.h"
#include "core/channels/Channel.h"
#include "core/channels/Channel_impl.h"
-#include "core/connections/Connection_impl.h"
#include "steptypes/StepType.h"
#include "storage/ComponentStorage.h"
#include "storage/ResultsStorage.h"
@@ -57,7 +56,7 @@ void ComponentLog(const Component * comp, LogSeverity sev, const char * format,
}
}
-McxStatus ComponentRead(Component * comp, ComponentInput * input) {
+McxStatus ComponentRead(Component * comp, ComponentInput * input, const struct Config * const config) {
InputElement * inputElement = (InputElement *)input;
McxStatus retVal = RETURN_OK;
@@ -149,6 +148,7 @@ McxStatus ComponentRead(Component * comp, ComponentInput * input) {
if (input->results->rtFactor.defined) {
comp->data->rtData.defined = TRUE;
comp->data->rtData.enabled = input->results->rtFactor.value;
+ comp->data->rtData.funcTimings.profilingTimesEnabled = config->profilingMode;
}
retVal = comp->data->storage->Read(comp->data->storage, input->results);
@@ -180,6 +180,7 @@ McxStatus ComponentSetup(Component * comp) {
if (comp->data->model->task) {
if (!comp->data->rtData.defined) {
comp->data->rtData.enabled = comp->data->model->task->rtFactorEnabled;
+ comp->data->rtData.funcTimings.profilingTimesEnabled = comp->data->model->config->profilingMode;
}
if (comp->data->model->task->params) {
@@ -201,87 +202,139 @@ McxStatus ComponentSetup(Component * comp) {
if (RETURN_OK != retVal) {
ComponentLog(comp, LOG_ERROR, "Could not setup real time factor");
return RETURN_ERROR;
- }
+ }
+
+ return RETURN_OK;
+}
+
+static McxStatus DefineTimingChannel(Component * comp, const char * chName, const char * unit, const void * reference) {
+ McxStatus retVal = RETURN_OK;
+
+ char * id = CreateChannelID(comp->GetName(comp), chName);
+ if (!id) {
+ ComponentLog(comp, LOG_ERROR, "Could not create ID for timing port %s", chName);
+ return RETURN_ERROR;
+ }
+
+ retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, unit, reference, CHANNEL_DOUBLE);
+
+ mcx_free(id);
+
+ if (retVal == RETURN_ERROR) {
+ ComponentLog(comp, LOG_ERROR, "Could not add timing port %s", chName);
+ return RETURN_ERROR;
+ }
return RETURN_OK;
}
static McxStatus ComponentSetupRTFactor(Component * comp) {
- // Add rt factor
if (comp->data->rtData.enabled) {
- char * id = NULL;
+ McxStatus retVal = RETURN_OK;
- id = CreateChannelID(comp->GetName(comp), "RealTime Clock");
- if (!id) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock");
- return RETURN_ERROR;
- }
- if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock", id, GetTimeUnitString(), &comp->data->rtData.simTimeTotal, CHANNEL_DOUBLE)) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock");
- mcx_free(id);
+ // RealTime channels
+ retVal = DefineTimingChannel(comp, "RealTime Clock", GetTimeUnitString(), &comp->data->rtData.rtTotalSum_s);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- mcx_free(id);
- id = CreateChannelID(comp->GetName(comp), "RealTime Clock Calc");
- if (!id) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock Calc");
+ retVal = DefineTimingChannel(comp, "RealTime Clock Calc", GetTimeUnitString(), &comp->data->rtData.rtCalcSum_s);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock Calc", id, GetTimeUnitString(), &comp->data->rtData.simTime, CHANNEL_DOUBLE)) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock Calc");
- mcx_free(id);
+
+ retVal = DefineTimingChannel(comp, "RealTime Factor Calc", "-", &comp->data->rtData.rtFactorCalc);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- mcx_free(id);
- id = CreateChannelID(comp->GetName(comp), "RealTime Factor Calc");
- if (!id) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor Calc");
+ retVal = DefineTimingChannel(comp, "RealTime Factor Calc (Avg)", "-", &comp->data->rtData.rtFactorCalcAvg);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc", id, "-", &comp->data->rtData.rtFactor, CHANNEL_DOUBLE)) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor Calc");
- mcx_free(id);
+
+ retVal = DefineTimingChannel(comp, "RealTime Factor", "-", &comp->data->rtData.rtFactorTotal);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- mcx_free(id);
- id = CreateChannelID(comp->GetName(comp), "RealTime Factor Calc (Avg)");
- if (!id) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor Calc (Avg)");
+ retVal = DefineTimingChannel(comp, "RealTime Factor (Avg)", "-", &comp->data->rtData.rtFactorTotalAvg);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc (Avg)", id, "-", &comp->data->rtData.rtFactorAvg, CHANNEL_DOUBLE)) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor Calc (Avg)");
- mcx_free(id);
+
+ // Scheduling channels
+ retVal = DefineTimingChannel(comp, "CalcStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtCalc.startTime);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- mcx_free(id);
- id = CreateChannelID(comp->GetName(comp), "RealTime Factor");
- if (!id) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor");
+ retVal = DefineTimingChannel(comp, "CalcEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtCalc.endTime);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor", id, "-", &comp->data->rtData.totalRtFactor, CHANNEL_DOUBLE)) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor");
- mcx_free(id);
+
+ retVal = DefineTimingChannel(comp, "SyncStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtSync.startTime);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- mcx_free(id);
- id = CreateChannelID(comp->GetName(comp), "RealTime Factor (Avg)");
- if (!id) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock Calc");
+ retVal = DefineTimingChannel(comp, "SyncEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtSync.endTime);
+ if (RETURN_ERROR == retVal) {
return RETURN_ERROR;
}
- if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor (Avg)", id, "-", &comp->data->rtData.totalRtFactorAvg, CHANNEL_DOUBLE)) {
- ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock Calc");
- mcx_free(id);
- return RETURN_ERROR;
+
+ if (comp->data->rtData.funcTimings.profilingTimesEnabled) {
+ retVal = DefineTimingChannel(comp, "InputStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtInput.startTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "InputEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtInput.endTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "OutputStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtOutput.startTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "OutputEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtOutput.endTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "StoreStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtStore.snapshot.startTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "StoreEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtStore.snapshot.endTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "StoreInStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtStoreIn.snapshot.startTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "StoreInEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtStoreIn.snapshot.endTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "TriggerInStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtTriggerIn.startTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ retVal = DefineTimingChannel(comp, "TriggerInEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtTriggerIn.endTime);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
}
- mcx_free(id);
}
return RETURN_OK;
@@ -386,10 +439,17 @@ static McxStatus ComponentStore(Component * comp, ChannelStoreType chType, doubl
McxStatus ComponentInitialize(Component * comp, size_t group, double startTime) {
comp->data->time = startTime;
- comp->data->rtData.startTime = startTime;
- mcx_time_get(&comp->data->rtData.startClock);
- comp->data->rtData.lastDoStepClock = comp->data->rtData.startClock;
- comp->data->rtData.lastCommDoStepClock = comp->data->rtData.startClock;
+ comp->data->rtData.simStartTime = startTime;
+
+ return RETURN_OK;
+}
+
+McxStatus ComponentBeforeDoSteps(Component * comp, void * param) {
+ FunctionTimingsSetGlobalSimStart(&comp->data->rtData.funcTimings, (McxTime *)param);
+
+ mcx_time_get(&comp->data->rtData.rtCompStart);
+ comp->data->rtData.rtLastEndCalc = comp->data->rtData.rtCompStart;
+ comp->data->rtData.rtLastCompEnd = comp->data->rtData.rtCompStart;
return RETURN_OK;
}
@@ -430,14 +490,13 @@ McxStatus ComponentUpdateOutChannels(Component * comp, TimeInterval * time) {
McxStatus ComponentDoStep(Component * comp, size_t group, double time, double deltaTime, double endTime, int isNewStep) {
McxStatus retVal = RETURN_OK;
- McxTime start, end, diff; /* of this DoStep call */
double startTime;
- McxTime totalDiff, totalDiffAvg;
+ McxTime rtTotal, rtTotalSum;
if (comp->data->rtData.enabled) {
/* data for local rt factor */
startTime = comp->GetTime(comp);
- mcx_time_get(&start);
+ TimeSnapshotStart(&comp->data->rtData.funcTimings.rtCalc);
}
MCX_DEBUG_LOG("DoStep: %.16f -> %.16f", time, endTime);
@@ -484,43 +543,39 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de
}
if (comp->data->rtData.enabled) {
+ McxTime rtDeltaCalc;
ComponentRTFactorData * rtData = &comp->data->rtData;
- double timeDiff = endTime - rtData->startTime;
+ double simCalcSum = endTime - rtData->simStartTime;
- /* wall time of this DoStep */
- mcx_time_get(&end);
+ TimeSnapshotEnd(&rtData->funcTimings.rtCalc);
+ mcx_time_diff(&rtData->funcTimings.rtCalc.start, &rtData->funcTimings.rtCalc.end, &rtDeltaCalc); // data for local rt factor
- /* data for local rt factor */
- mcx_time_diff(&start, &end, &diff);
+ mcx_time_diff(&rtData->rtLastCompEnd, &rtData->funcTimings.rtCalc.end, &rtTotal); // data for total rt factor and avg rt factor
+ mcx_time_diff(&rtData->rtCompStart, &rtData->funcTimings.rtCalc.end, &rtTotalSum);
- /* data for total rt factor and avg rt factor */
- mcx_time_diff(&rtData->lastCommDoStepClock, &end, &totalDiff);
- mcx_time_diff(&rtData->startClock, &end, &totalDiffAvg);
+ rtData->rtLastEndCalc = rtData->funcTimings.rtCalc.end; // udpate wall clock for next dostep
- /* udpate wall clock for next dostep */
- rtData->lastDoStepClock = end;
+ mcx_time_add(&rtData->rtCalcSum, &rtDeltaCalc, &rtData->rtCalcSum); // ticks of all DoSteps of this component since start
+ mcx_time_add(&rtData->rtCommStepTime, &rtDeltaCalc, &rtData->rtCommStepTime); // ticks of all DoSteps of this component for the current communication step
- /* ticks of all DoSteps of this component since start */
- mcx_time_add(&rtData->simClock, &diff, &rtData->simClock);
+ /* time of all DoSteps of this component since start/for the current communication step */
+ rtData->rtCalcSum_s = mcx_time_to_seconds(&rtData->rtCalcSum);
+ rtData->rtTotalSum_s = mcx_time_to_seconds(&rtTotalSum);
- /* ticks of all DoSteps of this component for the current communication step */
- mcx_time_add(&rtData->stepClock, &diff, &rtData->stepClock);
+ rtData->rtCommStepTime_s = mcx_time_to_seconds(&rtData->rtCommStepTime);
- /* time of all DoSteps of this component since start/for the current communication step */
- rtData->simTime = mcx_time_to_seconds(&rtData->simClock);
- rtData->simTimeTotal = mcx_time_to_seconds(&totalDiffAvg);
- rtData->stepTime = mcx_time_to_seconds(&rtData->stepClock);
+ rtData->simCommStepTime += comp->GetTime(comp) - startTime; // simulation time of the current communication time step
- /* simulation time of the current communication time step */
- rtData->commTime += comp->GetTime(comp) - startTime;
+ rtData->rtFactorCalc = rtData->rtCommStepTime_s / rtData->simCommStepTime;
+ rtData->rtFactorCalcAvg = rtData->rtCalcSum_s / simCalcSum;
- /* local (only this component) rt factor */
- rtData->rtFactor = rtData->stepTime / rtData->commTime;
- rtData->rtFactorAvg = rtData->simTime / timeDiff;
+ // Total = (all components + framework) rt factor
+ // Sum = from simulation begin
- /* total (all components + framework) rt factor */
- rtData->totalRtFactor = mcx_time_to_seconds(&totalDiff) / rtData->commTime;
- rtData->totalRtFactorAvg = mcx_time_to_seconds(&totalDiffAvg) / timeDiff;
+ rtData->rtFactorTotal = mcx_time_to_seconds(&rtTotal) / rtData->simCommStepTime;
+ rtData->rtFactorTotalAvg = rtData->rtTotalSum_s / simCalcSum;
+
+ FunctionTimingsCalculateTimeDiffs(&rtData->funcTimings);
}
return RETURN_OK;
@@ -558,6 +613,73 @@ static size_t ComponentGetNumWriteRTFactorChannels(const Component * comp) {
return DatabusInfoGetNumWriteChannels(DatabusGetRTFactorInfo(comp->data->databus));
}
+static size_t ComponentGetNumObservableChannels(const Component * comp) {
+ size_t num = 0;
+
+ num += DatabusGetOutChannelsNum(comp->data->databus);
+ num += DatabusGetInChannelsNum(comp->data->databus);
+ num += DatabusGetLocalChannelsNum(comp->data->databus);
+ num += DatabusGetRTFactorChannelsNum(comp->data->databus);
+
+ return num;
+}
+
+static McxStatus AddObservableChannels(const Component * comp, StringContainer * container, size_t * count) {
+ size_t numOut = comp->GetNumOutChannels(comp);
+ size_t numIn = comp->GetNumInChannels(comp);
+ size_t numLocal = comp->GetNumLocalChannels(comp);
+ size_t numRTFactor = comp->GetNumRTFactorChannels(comp);
+
+ size_t i = 0;
+ Databus * db = comp->GetDatabus(comp);
+
+ for (i = 0; i < numOut; i++) {
+ Channel * channel = (Channel *) DatabusGetOutChannel(db, i);
+ char * id = channel->info.id;
+
+ if (NULL != id) {
+ StringContainerSetKeyValue(container, *count, id, channel);
+ (*count)++;
+ }
+ }
+
+ for (i = 0; i < numIn; i++) {
+ Channel * channel = (Channel *) DatabusGetInChannel(db, i);
+ char * id = channel->info.id;
+ int isValid = DatabusChannelInIsValid(db, i);
+
+ if (NULL != id && isValid) {
+ StringContainerSetKeyValue(container, *count, id, channel);
+ (*count)++;
+ }
+ }
+
+ for (i = 0; i < numLocal; i++) {
+ Channel * channel = (Channel *) DatabusGetLocalChannel(db, i);
+ char * id = channel->info.id;
+ int isValid = DatabusChannelLocalIsValid(db, i);
+
+ if (NULL != id && isValid) {
+ StringContainerSetKeyValue(container, *count, id, channel);
+ (*count)++;
+ }
+ }
+
+ for (i = 0; i < numRTFactor; i++) {
+ Channel * channel = (Channel *) DatabusGetRTFactorChannel(db, i);
+ char * id = channel->info.id;
+ int isValid = DatabusChannelRTFactorIsValid(db, i);
+
+ if (NULL != id && isValid) {
+ StringContainerSetKeyValue(container, *count, id, channel);
+ (*count)++;
+ }
+ }
+
+ return RETURN_OK;
+}
+
+
static size_t ComponentGetNumConnectedOutChannels(const Component * comp) {
size_t count = 0;
size_t i = 0;
@@ -670,32 +792,38 @@ struct Dependencies * ComponentGetInOutGroupsNoDependency(const Component * comp
McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time) {
McxStatus retVal = RETURN_OK;
+ ComponentRTFactorData * rtData = &comp->data->rtData;
+
+ mcx_time_init(&rtData->rtCommStepTime);
+ rtData->simCommStepTime = 0;
+ rtData->rtLastCompEnd = rtData->rtLastEndCalc;
- mcx_time_init(&comp->data->rtData.stepClock);
- comp->data->rtData.commTime = 0;
- comp->data->rtData.lastCommDoStepClock = comp->data->rtData.lastDoStepClock;
+ TimeSnapshotStart(&rtData->funcTimings.rtSync);
retVal = DatabusEnterCommunicationMode(comp->data->databus, time->startTime);
if (RETURN_OK != retVal) {
ComponentLog(comp, LOG_ERROR, "Cannot enter communication mode at time %.17g s", time->startTime);
return RETURN_ERROR;
}
- ComponentUpdateOutChannels(comp, time);
+ TimeSnapshotEnd(&rtData->funcTimings.rtSync);
return RETURN_OK;
}
-McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectContainer * connections, TimeInterval * time) {
+McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time) {
McxStatus retVal = RETURN_OK;
+ ComponentRTFactorData * rtData = &comp->data->rtData;
+
+ mcx_time_init(&rtData->rtCommStepTime);
+ rtData->simCommStepTime = 0;
+ rtData->rtLastCompEnd = rtData->rtLastEndCalc;
- mcx_time_init(&comp->data->rtData.stepClock);
- comp->data->rtData.commTime = 0;
- comp->data->rtData.lastCommDoStepClock = comp->data->rtData.lastDoStepClock;
+ TimeSnapshotStart(&rtData->funcTimings.rtSync);
retVal = DatabusEnterCommunicationModeForConnections(comp->data->databus, connections, time->startTime);
if (RETURN_OK != retVal) {
ComponentLog(comp, LOG_ERROR, "Cannot enter communication mode for connections at time %.17g s", time->startTime);
return RETURN_ERROR;
}
- ComponentUpdateOutChannels(comp, time);
+ TimeSnapshotEnd(&rtData->funcTimings.rtSync);
return RETURN_OK;
}
@@ -826,13 +954,13 @@ static int ComponentGetSequenceNumber(const Component * comp) {
return comp->data->triggerSequence;
}
-static ObjectContainer * ComponentGetConnections(Component * fromComp, Component * toComp) {
+static ObjectList * ComponentGetConnections(Component * fromComp, Component * toComp) {
size_t i = 0;
size_t j = 0;
McxStatus retVal = RETURN_OK;
struct Databus * db = fromComp->GetDatabus(fromComp);
- ObjectContainer * connections = (ObjectContainer *) object_create(ObjectContainer);
+ ObjectList * connections = (ObjectList *) object_create(ObjectList);
if (!connections) {
return NULL;
@@ -840,13 +968,14 @@ static ObjectContainer * ComponentGetConnections(Component * fromComp, Component
for (i = 0; i < DatabusGetOutChannelsNum(db); i++) {
ChannelOut * out = DatabusGetOutChannel(db, i);
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
+ size_t connSize = conns->Size(conns);
- for (j = 0; j < conns->Size(conns); j++) {
+ for (j = 0; j < connSize; j++) {
Connection * conn = (Connection *) conns->At(conns, j);
ConnectionInfo * info = conn->GetInfo(conn);
- if (info->GetTargetComponent(info) == toComp) {
+ if (info->targetComponent == toComp) {
retVal = connections->PushBack(connections, (Object *) conn);
if (RETURN_OK != retVal) {
ComponentLog(fromComp, LOG_ERROR, "Could not collect connections");
@@ -881,9 +1010,10 @@ McxStatus ComponentOutConnectionsEnterInitMode(Component * comp) {
for (i = 0; i < numOutChannels; i++) {
ChannelOut * out = DatabusGetOutChannel(db, i);
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
+ size_t connSize = conns->Size(conns);
- for (j = 0; j < conns->Size(conns); j++) {
+ for (j = 0; j < connSize; j++) {
Connection * connection = (Connection *) conns->At(conns, j);
retVal = connection->EnterInitializationMode(connection);
if (RETURN_OK != retVal) { // error message in calling function
@@ -901,9 +1031,10 @@ McxStatus ComponentDoOutConnectionsInitialization(Component * comp, int onlyIfDe
for (i = 0; i < numOutChannels; i++) {
ChannelOut * out = DatabusGetOutChannel(db, i);
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
+ size_t connSize = conns->Size(conns);
- for (j = 0; j < conns->Size(conns); j++) {
+ for (j = 0; j < connSize; j++) {
Connection * connection = (Connection *) conns->At(conns, j);
if (!onlyIfDecoupled || connection->IsDecoupled(connection)) {
@@ -928,9 +1059,10 @@ McxStatus ComponentOutConnectionsExitInitMode(Component * comp, double time) {
for (i = 0; i < numOutChannels; i++) {
ChannelOut * out = DatabusGetOutChannel(db, i);
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
+ size_t connSize = conns->Size(conns);
- for (j = 0; j < conns->Size(conns); j++) {
+ for (j = 0; j < connSize; j++) {
Connection * connection = (Connection *) conns->At(conns, j);
retVal = connection->ExitInitializationMode(connection, time);
if (RETURN_OK != retVal) { // error message in calling function
@@ -1015,7 +1147,7 @@ Component * CreateComponentFromComponentInput(ComponentFactory * factory,
}
// General Data
- retVal = ComponentRead(comp, componentInput);
+ retVal = ComponentRead(comp, componentInput, config);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "Model: Could not create element data");
object_destroy(comp);
@@ -1073,6 +1205,7 @@ static Component * ComponentCreate(Component * comp) {
comp->Store = ComponentStore;
comp->DoStep = NULL;
+ comp->PostDoStep = NULL;
comp->Finish = NULL;
comp->GetNumInChannels = ComponentGetNumInChannels;
@@ -1106,6 +1239,8 @@ static Component * ComponentCreate(Component * comp) {
comp->SetModel = ComponentSetModel;
+ comp->ContainsComponent = NULL;
+
comp->GetDatabus = ComponentGetDatabus;
comp->GetName = ComponentGetName;
comp->GetModel = ComponentGetModel;
@@ -1153,9 +1288,118 @@ static Component * ComponentCreate(Component * comp) {
comp->data->typeString = NULL;
+
+ comp->GetNumObservableChannels = ComponentGetNumObservableChannels;
+ comp->AddObservableChannels = AddObservableChannels;
+
+ comp->OnConnectionsDone = NULL;
+
return comp;
}
+void TimeSnapshotStart(TimeSnapshot * snapshot) {
+ if (!snapshot->enabled) {
+ return;
+ }
+
+ mcx_time_get(&snapshot->start);
+}
+
+void TimeSnapshotEnd(TimeSnapshot * snapshot) {
+ if (!snapshot->enabled) {
+ return;
+ }
+
+ mcx_time_get(&snapshot->end);
+}
+
+static void TimeSnapshotDiffToMicroSeconds(TimeSnapshot * snapshot, McxTime * startTimePoint) {
+ McxTime start;
+ McxTime end;
+
+ mcx_time_diff(startTimePoint, &snapshot->start, &start);
+ mcx_time_diff(startTimePoint, &snapshot->end, &end);
+
+ snapshot->startTime = mcx_time_to_micro_s(&start);
+ snapshot->endTime = mcx_time_to_micro_s(&end);
+
+ snapshot->startTime = snapshot->startTime < 0.0 ? 0.0 : snapshot->startTime;
+ snapshot->endTime = snapshot->endTime < 0.0 ? 0.0 : snapshot->endTime;
+}
+
+static void TimeSnapshotInit(TimeSnapshot * snapshot) {
+ snapshot->enabled = FALSE;
+
+ mcx_time_init(&snapshot->start);
+ mcx_time_init(&snapshot->end);
+
+ snapshot->startTime = 0.0;
+ snapshot->endTime = 0.0;
+}
+
+static void DelayedTimeSnapshotInit(DelayedTimeSnapshot * snapshot) {
+ TimeSnapshotInit(&snapshot->snapshot);
+
+ snapshot->startTimePre = 0.0;
+ snapshot->endTimePre = 0.0;
+}
+
+static void DelayedTimeSnapshotDiffToMicroSeconds(DelayedTimeSnapshot * snapshot, McxTime * startTimePoint) {
+ McxTime start;
+ McxTime end;
+
+ snapshot->snapshot.startTime = snapshot->startTimePre;
+ snapshot->snapshot.endTime = snapshot->endTimePre;;
+
+ mcx_time_diff(startTimePoint, &snapshot->snapshot.start, &start);
+ mcx_time_diff(startTimePoint, &snapshot->snapshot.end, &end);
+
+ snapshot->startTimePre = mcx_time_to_micro_s(&start);
+ snapshot->endTimePre = mcx_time_to_micro_s(&end);
+}
+
+void FunctionTimingsCalculateTimeDiffs(FunctionTimings * timings) {
+ TimeSnapshotDiffToMicroSeconds(&timings->rtCalc, &timings->rtGlobalSimStart);
+ TimeSnapshotDiffToMicroSeconds(&timings->rtSync, &timings->rtGlobalSimStart);
+
+ TimeSnapshotDiffToMicroSeconds(&timings->rtInput, &timings->rtGlobalSimStart);
+ TimeSnapshotDiffToMicroSeconds(&timings->rtOutput, &timings->rtGlobalSimStart);
+ TimeSnapshotDiffToMicroSeconds(&timings->rtTriggerIn, &timings->rtGlobalSimStart);
+
+ DelayedTimeSnapshotDiffToMicroSeconds(&timings->rtStore, &timings->rtGlobalSimStart);
+ DelayedTimeSnapshotDiffToMicroSeconds(&timings->rtStoreIn, &timings->rtGlobalSimStart);
+}
+
+void FunctionTimingsSetGlobalSimStart(FunctionTimings * timings, McxTime * simStart) {
+ timings->rtGlobalSimStart = *simStart;
+
+ timings->rtCalc.enabled = TRUE;
+ timings->rtSync.enabled = TRUE;
+
+ timings->rtInput.enabled = TRUE;
+ timings->rtOutput.enabled = TRUE;
+ timings->rtTriggerIn.enabled = TRUE;
+
+ timings->rtStore.snapshot.enabled = TRUE;
+ timings->rtStoreIn.snapshot.enabled = TRUE;
+}
+
+static void FunctionTimingsInit(FunctionTimings * timings) {
+ mcx_time_init(&timings->rtGlobalSimStart);
+
+ timings->profilingTimesEnabled = FALSE;
+
+ TimeSnapshotInit(&timings->rtCalc);
+ TimeSnapshotInit(&timings->rtSync);
+
+ TimeSnapshotInit(&timings->rtInput);
+ TimeSnapshotInit(&timings->rtOutput);
+ TimeSnapshotInit(&timings->rtTriggerIn);
+
+ DelayedTimeSnapshotInit(&timings->rtStore);
+ DelayedTimeSnapshotInit(&timings->rtStoreIn);
+}
+
static void ComponentDataDestructor(ComponentData * data) {
object_destroy(data->databus);
@@ -1200,24 +1444,28 @@ static ComponentData * ComponentDataCreate(ComponentData * data) {
rtData->defined = FALSE;
rtData->enabled = FALSE;
- mcx_time_init(&rtData->simClock);
- mcx_time_init(&rtData->stepClock);
+ mcx_time_init(&rtData->rtCalcSum);
+ mcx_time_init(&rtData->rtCommStepTime);
+
+ rtData->rtCalcSum_s = 0.;
+ rtData->rtTotalSum_s = 0.;
+
+ rtData->rtCommStepTime_s = 0.;
+
+ rtData->simStartTime = 0.;
+ rtData->simCommStepTime = 0.;
- rtData->simTime = 0.;
- rtData->simTimeTotal = 0.;
- rtData->stepTime = 0.;
- rtData->startTime = 0.;
- rtData->commTime = 0.;
+ rtData->rtFactorCalc = 0.;
+ rtData->rtFactorCalcAvg = 0.;
- rtData->rtFactor = 0.;
- rtData->rtFactorAvg = 0.;
+ mcx_time_init(&rtData->rtCompStart);
+ mcx_time_init(&rtData->rtLastEndCalc);
+ mcx_time_init(&rtData->rtLastCompEnd);
- mcx_time_init(&rtData->startClock);
- mcx_time_init(&rtData->lastDoStepClock);
- mcx_time_init(&rtData->lastCommDoStepClock);
+ FunctionTimingsInit(&rtData->funcTimings);
- rtData->totalRtFactor = 0.;
- rtData->totalRtFactorAvg = 0.;
+ rtData->rtFactorTotal = 0.;
+ rtData->rtFactorTotalAvg = 0.;
data->hasOwnInputEvaluationTime = FALSE;
data->useInputsAtCouplingStepEndTime = FALSE;
diff --git a/src/core/Component.h b/src/core/Component.h
index 406dfd2..9d6f1cc 100644
--- a/src/core/Component.h
+++ b/src/core/Component.h
@@ -17,12 +17,12 @@
#include "core/Dependency.h"
#include "objects/StringContainer.h"
#include "reader/model/components/ComponentInput.h"
+#include "core/connections/ConnectionInfo.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-
typedef enum ComponentFinishState {
COMP_IS_FINISHED,
COMP_IS_NOT_FINISHED,
@@ -34,7 +34,6 @@ struct Model;
struct ComponentData;
struct ChannelInfo;
struct Connection;
-struct ConnectionInfo;
struct StepTypeParams;
struct ResultsStorage;
struct ComponentStorage;
@@ -49,9 +48,12 @@ typedef McxStatus (* fComponentUpdateOutChannels)(Component * comp);
typedef McxStatus (* fComponentUpdateInChannels)(Component * comp);
+typedef int (* fComponentContainsComponent)(Component * comp, const Component * otherComp);
+
typedef struct ComponentStorage * (* fComponentGetStorage)(const Component * comp);
typedef McxStatus (* fComponentDoStep)(Component * comp, size_t group, double time,
double deltaTime, double endTime, int isNewStep);
+typedef McxStatus (*fComponentPostDoStep)(Component * comp);
typedef McxStatus (* fComponentFinish)(Component * comp, FinishState * finishState);
typedef size_t (* fComponentGetNumber)(const Component * comp);
@@ -72,13 +74,15 @@ typedef int (* fComponentOneOutputOneGroup)(Component * comp);
typedef ComponentFinishState (* fComponentGetFinishState)(const Component * comp);
typedef void (* fComponentSetIsFinished)(Component * comp);
+typedef McxStatus (* fOnConnectionsDone)(Component* comp);
+
typedef struct Databus * (* fComponentGetDatabus)(const Component * comp);
typedef const char * (* fComponentGetName)(const Component * comp);
typedef struct Model * (* fComponentGetModel)(const Component * comp);
typedef size_t (* fComponentGetID)(const Component * comp);
typedef int (* fComponentGetSequenceNumber)(const Component * comp);
typedef int (* fComponentGetCPUIdx)(const Component * comp);
-typedef ObjectContainer * (*fComponentGetConnections)(Component * fromComp, Component * toComp);
+typedef ObjectList * (*fComponentGetConnections)(Component * fromComp, Component * toComp);
typedef struct PpdLink * (* fGetPPDLink)(struct Component * comp);
typedef ChannelMode (* fGetChannelDefaultMode)(struct Component * comp);
@@ -100,6 +104,8 @@ typedef McxStatus (*fComponentSetDouble)(Component * comp, double offset);
typedef void (*fComponentSetIsPartOfInitCalculation)(Component * comp, int isPartOfInitCalculation);
+typedef McxStatus (* fAddObservableChannels)(const Component * comp, StringContainer * container, size_t * count);
+
extern const struct ObjectClass _Component;
struct Component {
@@ -136,6 +142,7 @@ struct Component {
fComponentStore Store;
fComponentDoStep DoStep;
+ fComponentPostDoStep PostDoStep;
fComponentFinish Finish;
// Read and Setup Channels
@@ -189,6 +196,8 @@ struct Component {
fComponentSetModel SetModel;
+ fComponentContainsComponent ContainsComponent;
+
fComponentGetDatabus GetDatabus;
fComponentGetName GetName;
fComponentGetName GetType;
@@ -212,19 +221,25 @@ struct Component {
fComponentSetDouble SetResultTimeOffset;
+ fComponentGetNumber GetNumObservableChannels;
+ fAddObservableChannels AddObservableChannels;
+
+ fOnConnectionsDone OnConnectionsDone;
+
struct ComponentData * data;
};
/* these functions have to be called by subclasses */
void ComponentLog(const Component * comp, LogSeverity sev, const char * format, ...);
-McxStatus ComponentRead(Component * comp, ComponentInput * input);
+McxStatus ComponentRead(Component * comp, ComponentInput * input, const struct Config * const config);
McxStatus ComponentSetup(Component * comp);
McxStatus ComponentRegisterStorage(Component* comp, struct ResultsStorage* storage);
McxStatus ComponentInitialize(Component * comp, size_t group, double startTime);
McxStatus ComponentExitInitializationMode(Component * comp);
+McxStatus ComponentBeforeDoSteps(Component * comp, void * param);
McxStatus ComponentUpdateOutChannels(Component * comp, TimeInterval * time);
@@ -233,9 +248,9 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de
McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, struct StepTypeParams * params);
McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time);
-McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectContainer * connections, TimeInterval * time);
+McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time);
-struct ConnectionInfo * GetInConnectionInfo(const Component * comp, size_t channelID);
+ConnectionInfo * GetInConnectionInfo(const Component * comp, size_t channelID);
struct Connection * GetInConnection(const Component * comp, size_t channelID);
size_t ComponentGetNumOutGroups(const Component * comp);
diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h
index f680118..4eb5098 100644
--- a/src/core/Component_impl.h
+++ b/src/core/Component_impl.h
@@ -24,6 +24,50 @@ extern "C" {
struct Model;
struct Databus;
+typedef struct {
+ int enabled;
+
+ McxTime start;
+ McxTime end;
+
+ double startTime;
+ double endTime;
+} TimeSnapshot;
+
+
+void TimeSnapshotStart(TimeSnapshot * snapshot);
+void TimeSnapshotEnd(TimeSnapshot * snapshot);
+
+
+typedef struct {
+ TimeSnapshot snapshot;
+
+ double startTimePre;
+ double endTimePre;
+} DelayedTimeSnapshot;
+
+
+typedef struct {
+ McxTime rtGlobalSimStart; // wall clock of start of simulation
+
+ TimeSnapshot rtCalc;
+ TimeSnapshot rtSync;
+
+ int profilingTimesEnabled;
+
+ TimeSnapshot rtInput;
+ TimeSnapshot rtOutput;
+ TimeSnapshot rtTriggerIn;
+
+ DelayedTimeSnapshot rtStore;
+ DelayedTimeSnapshot rtStoreIn;
+} FunctionTimings;
+
+
+void FunctionTimingsCalculateTimeDiffs(FunctionTimings * timings);
+void FunctionTimingsSetGlobalSimStart(FunctionTimings * timings, McxTime * simStart);
+
+
typedef struct ComponentRTFactorData ComponentRTFactorData;
struct ComponentRTFactorData {
@@ -33,27 +77,31 @@ struct ComponentRTFactorData {
int defined;
int enabled;
- McxTime simClock; /* ticks in doStep since simulation start */
- McxTime stepClock; /* ticks in the current communication step */
+ McxTime rtCalcSum; // ticks in doStep since simulation start
+ double rtCalcSum_s; // time in doSteps since simulation start
+
+ McxTime rtCommStepTime; // ticks in the current communication step
+ double rtCommStepTime_s; // time in the current communication step
+
+ double simCommStepTime; // simulated time in current communication step
+
+ double rtTotalSum_s; // time since initialize
+
+ double simStartTime; // start time of simulation
- double simTime; /* time in doStep since simulation start */
- double simTimeTotal; /* time since initialize */
- double stepTime; /* time in the current communication step */
+ double rtFactorCalc;
+ double rtFactorCalcAvg;
- double startTime; /* start time of simulation */
- double commTime; /* simulated time in current communication step */
+ double rtFactorTotal;
+ double rtFactorTotalAvg;
- double rtFactor;
- double rtFactorAvg;
+ McxTime rtCompStart; // wall clock of start of component
- McxTime startClock; /* wall clock of start of simulation */
- McxTime lastDoStepClock; /* wall clock of last DoStep */
+ McxTime rtLastEndCalc; // wall clock of last Calc End
- /* wall clock of last DoStep before entering communication mode */
- McxTime lastCommDoStepClock;
+ McxTime rtLastCompEnd; // wall clock of last DoStep before entering communication mode
- double totalRtFactor;
- double totalRtFactorAvg;
+ FunctionTimings funcTimings;
};
diff --git a/src/core/Config.c b/src/core/Config.c
index ecd81e5..6842a0b 100644
--- a/src/core/Config.c
+++ b/src/core/Config.c
@@ -49,7 +49,7 @@ void CreateLogHeader(Config * config, LogSeverity sev) {
char * currentWorkingDirectory;
time(&config->timeStamp);
- strftime(timeString, TIMESTAMPLENGTH-1, "%a, %d.%m.%Y %H:%M:%S", localtime(&config->timeStamp));
+ strftime(timeString, TIMESTAMPLENGTH-1, "%a, %Y-%m-%d %H:%M:%S", localtime(&config->timeStamp));
strcpy(compileTimeString, __DATE__ );
strcat(compileTimeString, "-");
strcat(compileTimeString, __TIME__ );
@@ -295,6 +295,115 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) {
}
}
+ {
+ char * profilingMode = mcx_os_get_env_var("MC_PROFILING");
+ if (profilingMode) {
+ if (!is_off(profilingMode)) {
+ mcx_log(LOG_INFO, "Development mode turned on");
+ config->profilingMode = TRUE;
+ }
+
+ mcx_free(profilingMode);
+ }
+ }
+
+ {
+ char * str = mcx_os_get_env_var("MC_INTERPOLATION_BUFFER_SIZE");
+ if (str) {
+ int size = atoi(str);
+ if (size <= 0) {
+ mcx_log(LOG_WARNING, "Invalid interpolation filter buffer size (%d). Falling back to the default (%zu)",
+ size, config->interpolationBuffSize);
+ } else {
+ config->interpolationBuffSize = (size_t) size;
+ mcx_log(LOG_INFO, "Interpolation filter buffer size: %zu", config->interpolationBuffSize);
+ }
+ mcx_free(str);
+ }
+ }
+
+ {
+ char * str = mcx_os_get_env_var("MC_OVERRIDE_INTERPOLATION_BUFFER_SIZE");
+ if (str) {
+ int size = atoi(str);
+ if (size <= 0) {
+ mcx_log(LOG_WARNING, "Invalid interpolation filter override buffer size (%d)", size);
+ } else {
+ config->overrideInterpolationBuffSize = (size_t) size;
+ mcx_log(LOG_INFO, "Interpolation filter override buffer size: %zu", config->overrideInterpolationBuffSize);
+ }
+ mcx_free(str);
+ }
+ }
+
+ {
+ char * str = mcx_os_get_env_var("MC_INTERPOLATION_BUFFER_SIZE_LIMIT");
+ if (str) {
+ int size = atoi(str);
+ if (size <= 0) {
+ mcx_log(LOG_WARNING, "Invalid interpolation filter buffer size limit (%d)", size);
+ } else {
+ config->interpolationBuffSizeLimit = (size_t) size;
+ mcx_log(LOG_INFO, "Interpolation filter buffer size limit: %zu", config->interpolationBuffSizeLimit);
+ }
+ mcx_free(str);
+ }
+ }
+
+ {
+ char * str = mcx_os_get_env_var("MC_INTERPOLATION_BUFFER_SIZE_SAFE_EXT");
+ if (str) {
+ int size = atoi(str);
+ if (size <= 0) {
+ mcx_log(LOG_WARNING, "Invalid interpolation filter buffer size safety extension (%d)", size);
+ } else {
+ config->interpolationBuffSizeSafetyExt = (size_t) size;
+ mcx_log(LOG_INFO, "Interpolation filter buffer size safety extension: %zu", config->interpolationBuffSizeSafetyExt);
+ }
+ mcx_free(str);
+ }
+ }
+
+ {
+ char * disableMemFilter = NULL;
+
+ disableMemFilter = mcx_os_get_env_var("MC_DISABLE_MEM_FILTER");
+ if (disableMemFilter) {
+ if (is_on(disableMemFilter)) {
+ config->useMemFilter = FALSE;
+ }
+ mcx_free(disableMemFilter);
+ }
+ }
+
+ {
+ char * str = mcx_os_get_env_var("MC_MEM_FILTER_HISTORY_LIMIT");
+ if (str) {
+ int size = atoi(str);
+ if (size <= 0) {
+ mcx_log(LOG_WARNING, "Invalid memory filter history size limit (%s)", str);
+ } else {
+ config->memFilterHistoryLimit = (size_t) size;
+ mcx_log(LOG_INFO, "Memory filter history size limit: %zu", config->memFilterHistoryLimit);
+ }
+ mcx_free(str);
+ }
+ }
+
+ {
+ char * str = mcx_os_get_env_var("MC_MEM_FILTER_HISTORY_EXTRA");
+ if (str) {
+ int size = atoi(str);
+ if (size <= 0) {
+ mcx_log(LOG_WARNING, "Invalid memory filter extra history size (%s)", str);
+ } else {
+ config->memFilterHistoryExtra = (size_t) size;
+ mcx_log(LOG_INFO, "Memory filter extra history size: %zu", config->memFilterHistoryExtra);
+ }
+ mcx_free(str);
+ }
+ }
+
{
char * cosimInitEnabled = NULL;
@@ -456,7 +565,6 @@ static Config * ConfigCreate(Config * config) {
config->executable = NULL;
config->flushEveryStore = FALSE;
-
config->sumTimeDefined = FALSE;
config->sumTime = TRUE;
@@ -469,6 +577,17 @@ static Config * ConfigCreate(Config * config) {
config->nanCheck = NAN_CHECK_ALWAYS;
config->nanCheckNumMessages = MAX_NUM_MSGS;
+ config->interpolationBuffSize = 1000;
+ config->overrideInterpolationBuffSize = 0;
+ config->interpolationBuffSizeLimit = 100000;
+ config->interpolationBuffSizeSafetyExt = 1;
+
+ config->useMemFilter = TRUE;
+ config->memFilterHistoryLimit = 10000000;
+ config->memFilterHistoryExtra = 1;
+
+ config->profilingMode = FALSE;
+
return config;
}
diff --git a/src/core/Config.h b/src/core/Config.h
index 54e1cbe..7cd97eb 100644
--- a/src/core/Config.h
+++ b/src/core/Config.h
@@ -56,13 +56,25 @@ struct Config {
char * executable;
int flushEveryStore;
+
int sumTime;
int sumTimeDefined;
int writeAllLogFile;
+ size_t interpolationBuffSize;
+ size_t overrideInterpolationBuffSize;
+ size_t interpolationBuffSizeLimit;
+ size_t interpolationBuffSizeSafetyExt;
+
+ int useMemFilter;
+ size_t memFilterHistoryLimit;
+ size_t memFilterHistoryExtra;
+
int cosimInitEnabled;
+ int profilingMode;
+
size_t maxNumTimeSnapWarnings;
NaNCheckLevel nanCheck;
diff --git a/src/core/Conversion.c b/src/core/Conversion.c
index d11f48a..886def6 100644
--- a/src/core/Conversion.c
+++ b/src/core/Conversion.c
@@ -35,6 +35,73 @@ OBJECT_CLASS(Conversion, Object);
// ----------------------------------------------------------------------
// Range Conversion
+McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * value) {
+ RangeConversion * rangeConv = NULL;
+ ChannelValue * minToUse = NULL;
+ ChannelValue * maxToUse = NULL;
+
+ McxStatus retVal = RETURN_OK;
+
+ if (value->type != CHANNEL_DOUBLE && value->type != CHANNEL_INTEGER) {
+ return RETURN_OK;
+ }
+
+ rangeConv = (RangeConversion *) object_create(RangeConversion);
+ if (!rangeConv) {
+ mcx_log(LOG_ERROR, "ConvertRange: Not enough memory");
+ return RETURN_ERROR;
+ }
+
+ maxToUse = max ? ChannelValueClone(max) : NULL;
+ if (max && !maxToUse) {
+ mcx_log(LOG_ERROR, "ConvertRange: Not enough memory for max");
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
+
+ minToUse = min ? ChannelValueClone(min) : NULL;
+ if (min && !minToUse) {
+ mcx_log(LOG_ERROR, "ConvertRange: Not enough memory for min");
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
+
+ retVal = rangeConv->Setup(rangeConv, minToUse, maxToUse);
+ if (retVal == RETURN_ERROR) {
+ mcx_log(LOG_ERROR, "ConvertRange: Conversion setup failed");
+ goto cleanup;
+ }
+
+ minToUse = NULL;
+ maxToUse = NULL;
+
+ if (rangeConv->IsEmpty(rangeConv)) {
+ object_destroy(rangeConv);
+ }
+
+ if (rangeConv) {
+ Conversion * conversion = (Conversion *) rangeConv;
+ retVal = conversion->convert(conversion, value);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "ConvertRange: Conversion failed");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (minToUse) {
+ mcx_free(minToUse);
+ }
+
+ if (maxToUse) {
+ mcx_free(maxToUse);
+ }
+
+ object_destroy(rangeConv);
+
+ return retVal;
+}
+
static McxStatus RangeConversionConvert(Conversion * conversion, ChannelValue * value) {
RangeConversion * rangeConversion = (RangeConversion *) conversion;
@@ -89,8 +156,8 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue
return RETURN_ERROR;
}
- conversion->min = min;
- conversion->max = max;
+ conversion->min = min ? ChannelValueClone(min) : NULL;
+ conversion->max = max ? ChannelValueClone(max) : NULL;
return RETURN_OK;
}
@@ -141,6 +208,42 @@ OBJECT_CLASS(RangeConversion, Conversion);
// ----------------------------------------------------------------------
// Unit Conversion
+McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * value) {
+ UnitConversion * unitConv = NULL;
+
+ McxStatus retVal = RETURN_OK;
+
+ unitConv = (UnitConversion *) object_create(UnitConversion);
+ if (!unitConv) {
+ mcx_log(LOG_ERROR, "ConvertUnit: Not enough memory");
+ return RETURN_ERROR;
+ }
+
+ retVal = unitConv->Setup(unitConv, fromUnit, toUnit);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ConvertUnit: Conversion setup failed");
+ goto cleanup;
+ }
+
+ if (unitConv->IsEmpty(unitConv)) {
+ object_destroy(unitConv);
+ }
+
+ if (unitConv) {
+ Conversion * conv = (Conversion *) unitConv;
+ retVal = conv->convert(conv, value);
+ if (retVal == RETURN_ERROR) {
+ mcx_log(LOG_ERROR, "ConvertUnit: Conversion failed");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ object_destroy(unitConv);
+
+ return retVal;
+}
+
static void UnitConversionConvertVector(UnitConversion * unitConversion, double * vector, size_t vectorLength) {
size_t i;
if (!unitConversion->IsEmpty(unitConversion)) {
@@ -241,6 +344,73 @@ OBJECT_CLASS(UnitConversion, Conversion);
// ----------------------------------------------------------------------
// Linear Conversion
+McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelValue * value) {
+ LinearConversion * linearConv = NULL;
+ ChannelValue * factorToUse = NULL;
+ ChannelValue * offsetToUse = NULL;
+
+ McxStatus retVal = RETURN_OK;
+
+ if (value->type != CHANNEL_DOUBLE && value->type != CHANNEL_INTEGER) {
+ return RETURN_OK;
+ }
+
+ linearConv = (LinearConversion *) object_create(LinearConversion);
+ if (!linearConv) {
+ mcx_log(LOG_ERROR, "ConvertLinear: Not enough memory");
+ return RETURN_ERROR;
+ }
+
+ factorToUse = factor ? ChannelValueClone(factor) : NULL;
+ if (factor && !factorToUse) {
+ mcx_log(LOG_ERROR, "ConvertLinear: Not enough memory for factor");
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
+
+ offsetToUse = offset ? ChannelValueClone(offset) : NULL;
+ if (offset && !offsetToUse) {
+ mcx_log(LOG_ERROR, "ConvertLinear: Not enough memory for offset");
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
+
+ retVal = linearConv->Setup(linearConv, factorToUse, offsetToUse);
+ if (retVal == RETURN_ERROR) {
+ mcx_log(LOG_ERROR, "ConvertLinear: Conversion setup failed");
+ goto cleanup;
+ }
+
+ factorToUse = NULL;
+ offsetToUse = NULL;
+
+ if (linearConv->IsEmpty(linearConv)) {
+ object_destroy(linearConv);
+ }
+
+ if (linearConv) {
+ Conversion * conversion = (Conversion *) linearConv;
+ retVal = conversion->convert(conversion, value);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "ConvertLinear: Conversion failed");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ if (factorToUse) {
+ mcx_free(factorToUse);
+ }
+
+ if (offsetToUse) {
+ mcx_free(offsetToUse);
+ }
+
+ object_destroy(linearConv);
+
+ return retVal;
+}
+
static McxStatus LinearConversionConvert(Conversion * conversion, ChannelValue * value) {
LinearConversion * linearConversion = (LinearConversion *) conversion;
@@ -288,8 +458,8 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal
return RETURN_ERROR;
}
- conversion->factor = factor;
- conversion->offset = offset;
+ conversion->factor = factor ? ChannelValueClone(factor) : NULL;
+ conversion->offset = offset ? ChannelValueClone(offset) : NULL;
return RETURN_OK;
}
@@ -339,6 +509,38 @@ OBJECT_CLASS(LinearConversion, Conversion);
// ----------------------------------------------------------------------
// Type Conversion
+McxStatus ConvertType(ChannelType fromType, ChannelType toType, ChannelValue * value) {
+ TypeConversion * typeConv = NULL;
+ Conversion * conv = NULL;
+
+ McxStatus retVal = RETURN_OK;
+
+ typeConv = (TypeConversion *) object_create(TypeConversion);
+ if (!typeConv) {
+ mcx_log(LOG_ERROR, "ConvertType: Not enough memory");
+ return RETURN_ERROR;
+ }
+
+ conv = (Conversion *) typeConv;
+
+ retVal = typeConv->Setup(typeConv, fromType, toType);
+ if (retVal == RETURN_ERROR) {
+ mcx_log(LOG_ERROR, "ConvertType: Conversion setup failed");
+ goto cleanup;
+ }
+
+ retVal = conv->convert(conv, value);
+ if (retVal == RETURN_ERROR) {
+ mcx_log(LOG_ERROR, "Type conversion failed");
+ goto cleanup;
+ }
+
+cleanup:
+ object_destroy(typeConv);
+
+ return retVal;
+}
+
static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValue * value) {
if (ChannelValueType(value) != CHANNEL_INTEGER) {
mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(CHANNEL_INTEGER));
@@ -370,7 +572,7 @@ static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, Channe
}
value->type = CHANNEL_DOUBLE;
- value->value.d = (value->value.d != 0) ? 1. : 0.;
+ value->value.d = (value->value.i != 0) ? 1. : 0.;
return RETURN_OK;
}
diff --git a/src/core/Conversion.h b/src/core/Conversion.h
index 4b3a1d6..1f542f2 100644
--- a/src/core/Conversion.h
+++ b/src/core/Conversion.h
@@ -54,6 +54,8 @@ typedef struct RangeConversion {
} RangeConversion;
+McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * value);
+
// ----------------------------------------------------------------------
// Unit Conversion
@@ -78,6 +80,8 @@ struct UnitConversion {
fUnitConversionVector convertVector;
};
+McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * value);
+
// ----------------------------------------------------------------------
// Linear Conversion
@@ -102,6 +106,8 @@ typedef struct LinearConversion {
} LinearConversion;
+McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelValue * value);
+
// ----------------------------------------------------------------------
// Type Conversion
@@ -120,6 +126,9 @@ struct TypeConversion {
fTypeConversionIsEmpty IsEmpty;
};
+McxStatus ConvertType(ChannelType fromType, ChannelType toType, ChannelValue * value);
+
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif /* __cplusplus */
diff --git a/src/core/Databus.c b/src/core/Databus.c
index e08a004..74efc5b 100644
--- a/src/core/Databus.c
+++ b/src/core/Databus.c
@@ -22,6 +22,8 @@
#include "core/connections/FilteredConnection.h"
+#include "objects/Vector.h"
+
#include "util/stdlib.h"
// private headers, see "Object-oriented programming in ANSI-C", Hanser 1994
@@ -35,14 +37,14 @@ extern "C" {
// DatabusInfo
static void DatabusInfoDataDestructor(DatabusInfoData * data) {
- data->infos->DestroyObjects(data->infos);
object_destroy(data->infos);
data->origInfos->DestroyObjects(data->origInfos);
object_destroy(data->origInfos);
}
static DatabusInfoData * DatabusInfoDataCreate(DatabusInfoData * data) {
- data->infos = (ObjectContainer *) object_create(ObjectContainer);
+ data->infos = (Vector *) object_create(Vector);
+ data->infos->Setup(data->infos, sizeof(ChannelInfo), ChannelInfoInit, ChannelInfoSetFrom, ChannelInfoDestroy);
data->origInfos = (ObjectContainer *) object_create(ObjectContainer);
return data;
}
@@ -69,17 +71,19 @@ char * CreateIndexedName(const char * name, unsigned i) {
-static ObjectContainer * DatabusReadPortInput(PortInput * input) {
+static Vector * DatabusReadPortInput(PortInput * input) {
McxStatus retVal = RETURN_OK;
- ObjectContainer * list = NULL;
+ Vector * list = NULL;
VectorChannelInfo * vector = NULL;
- list = (ObjectContainer *) object_create(ObjectContainer);
+ list = (Vector *) object_create(Vector);
if (!list) {
retVal = RETURN_ERROR;
goto cleanup_0;
}
+ list->Setup(list, sizeof(ChannelInfo), ChannelInfoInit, ChannelInfoSetFrom, ChannelInfoDestroy);
+
vector = (VectorChannelInfo *)object_create(VectorChannelInfo);
if (!vector) {
retVal = RETURN_ERROR;
@@ -176,7 +180,7 @@ static ObjectContainer * DatabusReadPortInput(PortInput * input) {
char * nameInTool = NULL;
char * id = NULL;
- ChannelInfo * copy = NULL;
+ ChannelInfo copy = { 0 };
if (!(name = CreateIndexedName(vectorPortInput->name, i))) {
retVal = RETURN_ERROR;
@@ -195,60 +199,58 @@ static ObjectContainer * DatabusReadPortInput(PortInput * input) {
}
}
- copy = object_create(ChannelInfo);
- if (!copy) {
- retVal = RETURN_ERROR;
+ retVal = ChannelInfoInit(©);
+ if (RETURN_ERROR == retVal) {
goto cleanup_2;
}
- copy->SetName(copy, name);
- copy->SetNameInTool(copy, nameInTool);
- copy->SetID(copy, id);
+ ChannelInfoSetName(©, name);
+ ChannelInfoSetNameInTool(©, nameInTool);
+ ChannelInfoSetID(©, id);
- copy->SetDescription(copy, vectorPortInput->description);
- copy->SetType(copy, vectorPortInput->type);
+ ChannelInfoSetDescription(©, vectorPortInput->description);
+ ChannelInfoSetType(©, vectorPortInput->type);
- if (!copy->IsBinary(copy)) {
- copy->SetUnit(copy, vectorPortInput->unit);
+ if (!ChannelInfoIsBinary(©)) {
+ ChannelInfoSetUnit(©, vectorPortInput->unit);
} else {
- copy->SetUnit(copy, "-");
+ ChannelInfoSetUnit(©, "-");
}
- copy->SetVector(copy, (VectorChannelInfo *) object_strong_reference(vector));
+ ChannelInfoSetVector(©, (VectorChannelInfo *) object_strong_reference(vector));
if (mins) {
- copy->SetMin(copy, mins[i - startIndex]);
+ copy.min = mins[i - startIndex];
}
if (maxs) {
- copy->SetMax(copy, maxs[i - startIndex]);
+ copy.max = maxs[i - startIndex];
}
if (scales) {
- copy->SetScale(copy, scales[i - startIndex]);
+ copy.scale = scales[i - startIndex];
}
if (offsets) {
- copy->SetOffset(copy, offsets[i - startIndex]);
+ copy.offset = offsets[i - startIndex];
}
if (defaults) {
- copy->SetDefault(copy, defaults[i - startIndex]);
+ copy.defaultValue = defaults[i - startIndex];
}
if (initials) {
- copy->SetInitial(copy, initials[i - startIndex]);
+ copy.initialValue = initials[i - startIndex];
}
if (writeResults) {
- copy->SetWriteResult(copy, writeResults[i - startIndex]);
+ copy.writeResult = writeResults[i - startIndex];
}
- retVal = vector->AddElement(vector, copy, i);
+ list->PushBack(list, ©);
+
+ retVal = vector->AddElement(vector, list->At(list, list->Size(list) - 1), i);
if (RETURN_ERROR == retVal) {
goto cleanup_2;
}
- list->PushBack(list, (Object *) copy);
-
cleanup_2:
-
if (name) {
mcx_free(name);
}
@@ -295,25 +297,25 @@ static ObjectContainer * DatabusReadPortInput(PortInput * input) {
} else {
ScalarPortInput * scalarPortInput = input->port.scalarPort;
- ChannelInfo * info = object_create(ChannelInfo);
- if (!info) {
- retVal = RETURN_ERROR;
- goto cleanup_0;
+ ChannelInfo info = { 0 };
+ retVal = ChannelInfoInit(&info);
+ if (RETURN_ERROR == retVal) {
+ goto cleanup_else_1;
}
- info->SetName(info, scalarPortInput->name);
- info->SetNameInTool(info, scalarPortInput->nameInModel);
- info->SetDescription(info, scalarPortInput->description);
- info->SetID(info, scalarPortInput->id);
- info->SetType(info, scalarPortInput->type);
+ ChannelInfoSetName(&info, scalarPortInput->name);
+ ChannelInfoSetNameInTool(&info, scalarPortInput->nameInModel);
+ ChannelInfoSetDescription(&info, scalarPortInput->description);
+ ChannelInfoSetID(&info, scalarPortInput->id);
+ ChannelInfoSetType(&info, scalarPortInput->type);
- if (!info->IsBinary(info)) {
- info->SetUnit(info, scalarPortInput->unit);
+ if (!ChannelInfoIsBinary(&info)) {
+ ChannelInfoSetUnit(&info, scalarPortInput->unit);
} else {
- info->SetUnit(info, "-");
+ ChannelInfoSetUnit(&info, "-");
}
- ChannelType expectedType = info->GetType(info);
+ ChannelType expectedType = info.type;
ChannelValue value;
@@ -321,71 +323,71 @@ static ObjectContainer * DatabusReadPortInput(PortInput * input) {
if (scalarPortInput->min.defined) {
ChannelValueSetFromReference(&value, &scalarPortInput->min.value);
- info->SetMin(info, ChannelValueClone(&value));
- if (!info->GetMin(info)) {
+ info.min = ChannelValueClone(&value);
+ if (!info.min) {
goto cleanup_else_1;
}
}
if (scalarPortInput->max.defined) {
ChannelValueSetFromReference(&value, &scalarPortInput->max.value);
- info->SetMax(info, ChannelValueClone(&value));
- if (!info->GetMax(info)) {
+ info.max = ChannelValueClone(&value);
+ if (!info.max) {
goto cleanup_else_1;
}
}
if (scalarPortInput->scale.defined) {
ChannelValueSetFromReference(&value, &scalarPortInput->scale.value);
- info->SetScale(info, ChannelValueClone(&value));
- if (!info->GetScale(info)) {
+ info.scale = ChannelValueClone(&value);
+ if (!info.scale) {
goto cleanup_else_1;
}
}
if (scalarPortInput->offset.defined) {
ChannelValueSetFromReference(&value, &scalarPortInput->offset.value);
- info->SetOffset(info, ChannelValueClone(&value));
- if (!info->GetOffset(info)) {
+ info.offset = ChannelValueClone(&value);
+ if (!info.offset) {
goto cleanup_else_1;
}
}
if (scalarPortInput->default_.defined) {
ChannelValueSetFromReference(&value, &scalarPortInput->default_.value);
- info->SetDefault(info, ChannelValueClone(&value));
- if (!info->GetDefault(info)) {
+ info.defaultValue = ChannelValueClone(&value);
+ if (!info.defaultValue) {
goto cleanup_else_1;
}
}
if (scalarPortInput->initial.defined) {
ChannelValueSetFromReference(&value, &scalarPortInput->initial.value);
- info->SetInitial(info, ChannelValueClone(&value));
- if (!info->GetInitialValue(info)) {
+ info.initialValue = ChannelValueClone(&value);
+ if (!info.initialValue) {
goto cleanup_else_1;
}
}
if (scalarPortInput->writeResults.defined) {
- info->SetWriteResult(info, scalarPortInput->writeResults.value);
+ info.writeResult = scalarPortInput->writeResults.value;
}
- retVal = vector->Setup(vector, info->GetName(info), info->GetNameInTool(info), TRUE, -1, -1);
+ retVal = vector->Setup(vector, ChannelInfoGetName(&info), info.nameInTool, TRUE, -1, -1);
if (RETURN_ERROR == retVal) {
goto cleanup_else_1;
}
- info->SetVector(info, (VectorChannelInfo *) object_strong_reference(vector));
+ ChannelInfoSetVector(&info, (VectorChannelInfo *) object_strong_reference(vector));
+
+ list->PushBack(list, &info);
- retVal = vector->AddElement(vector, info, 0);
+ retVal = vector->AddElement(vector, list->At(list, list->Size(list) - 1), 0);
if (RETURN_ERROR == retVal) {
goto cleanup_else_1;
}
- list->PushBack(list, (Object *) object_strong_reference(info));
-
cleanup_else_1:
- object_destroy(info);
+ ChannelInfoDestroy(&info);
ChannelValueDestructor(&value);
goto cleanup_0;
}
@@ -400,9 +402,20 @@ static ObjectContainer * DatabusReadPortInput(PortInput * input) {
return list;
}
+static int ChannelInfoSameNamePred(void * elem, const char * name) {
+ ChannelInfo * info = (ChannelInfo *) elem;
+
+ return 0 == strcmp(ChannelInfoGetName(info), name);
+}
+
+static int ChannelInfosGetNameIdx(Vector * infos, const char * name) {
+ size_t idx = infos->FindIdx(infos, ChannelInfoSameNamePred, name);
+
+ return idx == SIZE_T_ERROR ? -1 : (int)idx;
+}
int DatabusInfoGetChannelID(DatabusInfo * info, const char * name) {
- return info->data->infos->GetNameIndex(info->data->infos, name);
+ return ChannelInfosGetNameIdx(info->data->infos, name);
}
McxStatus DatabusInfoRead(DatabusInfo * dbInfo,
@@ -417,6 +430,8 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo,
size_t numChildren = input->ports->Size(input->ports);
+ Vector * dbInfos = dbInfo->data->infos;
+ size_t requiredSize = 0;
ObjectContainer * allChannels = dbInfo->data->origInfos;
if (NULL == allChannels) {
mcx_log(LOG_ERROR, "Ports: Read port infos: Container of vector ports missing");
@@ -425,68 +440,93 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo,
for (i = 0; i < numChildren; i++) {
PortInput * portInput = (PortInput *) input->ports->At(input->ports, i);
+ if (portInput->type == PORT_SCALAR) {
+ requiredSize++;
+ } else {
+ requiredSize += portInput->port.vectorPort->endIndex - portInput->port.vectorPort->startIndex + 1;
+ }
+ }
- ObjectContainer * dbInfos = dbInfo->data->infos;
- ObjectContainer * infos = NULL;
+ if (requiredSize > 0) {
+ dbInfos->Reserve(dbInfos, requiredSize);
+ }
+
+ for (i = 0; i < numChildren; i++) {
+ PortInput * portInput = (PortInput *) input->ports->At(input->ports, i);
+ Vector * infos = NULL;
infos = DatabusReadPortInput(portInput);
if (!infos) {
- mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read info of port %d", i);
+ mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read info of port %zu", i);
return RETURN_ERROR;
}
- {
- ChannelInfo * chInfo = (ChannelInfo *) infos->At(infos, 0);
- allChannels->PushBack(allChannels, (Object *) object_strong_reference(chInfo->vector));
- }
-
for (j = 0; j < infos->Size(infos); j++) {
ChannelInfo * info = (ChannelInfo *) infos->At(infos, j);
- const char * name = info->GetName(info);
- int n = dbInfos->GetNameIndex(dbInfos, name);
+ const char * name = ChannelInfoGetName(info);
+ int n = ChannelInfosGetNameIdx(dbInfos, name);
if (n >= 0) { // key already exists
mcx_log(LOG_ERROR, "Ports: Duplicate port %s", name);
- infos->DestroyObjects(infos);
object_destroy(infos);
return RETURN_ERROR;
}
mcx_log(LOG_DEBUG, " Port: \"%s\"", name);
- infos->SetElementName(infos, j, name);
- info->SetMode(info, mode);
+ info->mode = mode;
}
- if (infos->Size(infos) == 1 && SpecificRead) {
- ChannelInfo * info = (ChannelInfo *) infos->At(infos, infos->Size(infos) - 1);
- retVal = SpecificRead(comp, info, portInput, i);
+ for (j = 0; j < infos->Size(infos); ++j) {
+ ChannelInfo * info = (ChannelInfo *) infos->At(infos, j);
+ VectorChannelInfo * vInfo = info->vector;
+ size_t startIdx = vInfo->GetStartIndex(vInfo);
+ size_t idx = startIdx == -1 ? 0 : (startIdx + j);
+ ChannelInfo * infoCpy = NULL;
+
+ retVal = dbInfos->PushBack(dbInfos, info);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %zu", i);
+ object_destroy(infos);
+ return RETURN_ERROR;
+ }
+
+ infoCpy = dbInfos->At(dbInfos, dbInfos->Size(dbInfos) - 1);
+ retVal = infoCpy->vector->AddElement(infoCpy->vector, infoCpy, idx);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read element specific data of port %d", i);
+ mcx_log(LOG_ERROR, "Ports: Read port infos: Could not add vector info of port %zu", i);
+ object_destroy(infos);
return RETURN_ERROR;
}
+
+ if (infos->Size(infos) == 1 && SpecificRead) {
+ retVal = SpecificRead(comp, infoCpy, portInput, i);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read element specific data of port %zu", i);
+ return RETURN_ERROR;
+ }
+ }
}
- retVal = dbInfos->Append(dbInfos, infos);
- if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i);
- object_destroy(infos);
- return RETURN_ERROR;
+ {
+ size_t dbInfosSize = dbInfos->Size(dbInfos);
+ ChannelInfo * chInfo = (ChannelInfo *)dbInfos->At(dbInfos, dbInfosSize - 1);
+ allChannels->PushBack(allChannels, (Object *) object_strong_reference(chInfo->vector));
}
+
object_destroy(infos);
}
return RETURN_OK;
}
-static int IsWriteResults(Object * obj) {
- ChannelInfo * info = (ChannelInfo *) obj;
+static int IsWriteResults(void * elem, void * ignore) {
+ ChannelInfo * info = (ChannelInfo *) elem;
- return info->GetWriteResultFlag(info);
+ return info->writeResult;
}
size_t DatabusInfoGetNumWriteChannels(DatabusInfo * dbInfo) {
- ObjectContainer * infos = dbInfo->data->infos;
-
- ObjectContainer * writeInfos = infos->Filter(infos, IsWriteResults);
+ Vector * infos = dbInfo->data->infos;
+ Vector * writeInfos = infos->FilterRef(infos, IsWriteResults, NULL);
size_t num = writeInfos->Size(writeInfos);
@@ -527,6 +567,9 @@ static void DatabusDataDestructor(DatabusData * data) {
}
mcx_free(data->in);
}
+ if (data->inConnected) {
+ mcx_free(data->inConnected);
+ }
if (data->out) {
size_t num = DatabusInfoGetChannelNum(data->outInfo);
@@ -570,6 +613,9 @@ static void DatabusDataDestructor(DatabusData * data) {
static DatabusData * DatabusDataCreate(DatabusData * data) {
data->in = NULL;
+ data->inConnected = NULL;
+ data->numInConnected = 0;
+
data->out = NULL;
data->local = NULL;
data->rtfactor = NULL;
@@ -599,6 +645,24 @@ static DatabusData * DatabusDataCreate(DatabusData * data) {
OBJECT_CLASS(DatabusData, Object);
+McxStatus DatabusUpdateInConnected(Databus * db) {
+ size_t i = 0;
+ size_t numIn = DatabusInfoGetChannelNum(DatabusGetInInfo(db));
+
+ db->data->numInConnected = 0;
+
+ for (i = 0; i < numIn; i++) {
+ ChannelIn * chIn = db->data->in[i];
+ Channel * ch = (Channel *) chIn;
+
+ if (ch->IsConnected(ch)) {
+ db->data->inConnected[db->data->numInConnected] = db->data->in[i];
+ db->data->numInConnected++;
+ }
+ }
+
+ return RETURN_OK;
+}
McxStatus DatabusSetup(Databus * db, DatabusInfo * in, DatabusInfo * out, Config * config) {
@@ -617,6 +681,13 @@ McxStatus DatabusSetup(Databus * db, DatabusInfo * in, DatabusInfo * out, Config
mcx_log(LOG_ERROR, "Ports: Memory allocation for inports failed");
return RETURN_ERROR;
}
+
+ db->data->inConnected = (ChannelIn **)mcx_calloc(numIn, sizeof(ChannelIn *));
+ if (db->data->inConnected == NULL) {
+ mcx_log(LOG_ERROR, "Ports: Memory allocation for connected inports failed");
+ return RETURN_ERROR;
+ }
+
for (i = 0; i < numIn; i++) {
db->data->in[i] = (ChannelIn *) object_create(ChannelIn);
if (!db->data->in[i]) {
@@ -686,8 +757,31 @@ McxStatus DatabusTriggerOutChannels(Databus *db, TimeInterval * time) {
out = (Channel *) db->data->out[i];
retVal = out->Update(out, time);
if (RETURN_OK != retVal) {
- ChannelInfo * info = out->GetInfo(out);
- mcx_log(LOG_ERROR, "Could not update outport %s", info->GetName(info));
+ ChannelInfo * info = &out->info;
+ mcx_log(LOG_ERROR, "Could not update outport %s", ChannelInfoGetName(info));
+ return RETURN_ERROR;
+ }
+ }
+
+ return RETURN_OK;
+}
+
+
+McxStatus DatabusTriggerConnectedInConnections(Databus * db, TimeInterval * consumerTime) {
+ if (!db) {
+ mcx_log(LOG_ERROR, "Ports: Trigger inports: Invalid structure");
+ return RETURN_ERROR;
+ }
+ size_t i = 0;
+
+ McxStatus retVal = RETURN_OK;
+
+ for (i = 0; i < db->data->numInConnected; i++) {
+ Channel * channel = (Channel *)db->data->inConnected[i];
+ retVal = channel->Update(channel, consumerTime);
+ if (RETURN_OK != retVal) {
+ ChannelInfo * info = &channel->info;
+ mcx_log(LOG_ERROR, "Could not update inport %s", ChannelInfoGetName(info));
return RETURN_ERROR;
}
}
@@ -695,6 +789,7 @@ McxStatus DatabusTriggerOutChannels(Databus *db, TimeInterval * time) {
return RETURN_OK;
}
+
McxStatus DatabusTriggerInConnections(Databus * db, TimeInterval * consumerTime) {
if (!db) {
mcx_log(LOG_ERROR, "Ports: Trigger inports: Invalid structure");
@@ -710,8 +805,8 @@ McxStatus DatabusTriggerInConnections(Databus * db, TimeInterval * consumerTime)
if (channel->IsValid(channel)) {
retVal = channel->Update(channel, consumerTime);
if (RETURN_OK != retVal) {
- ChannelInfo * info = channel->GetInfo(channel);
- mcx_log(LOG_ERROR, "Could not update inport %s", info->GetName(info));
+ ChannelInfo * info = &channel->info;
+ mcx_log(LOG_ERROR, "Could not update inport %s", ChannelInfoGetName(info));
return RETURN_ERROR;
}
}
@@ -735,8 +830,8 @@ Connection * DatabusCreateConnection(Databus * db, ConnectionInfo * info) {
ChannelOut * outChannel = NULL;
ChannelIn * inChannel = NULL;
- size_t outChannelID = info->GetSourceChannelID(info);
- size_t inChannelID = info->GetTargetChannelID(info);
+ size_t outChannelID = info->sourceChannel;
+ size_t inChannelID = info->targetChannel;
char * connStr = NULL;
@@ -750,7 +845,7 @@ Connection * DatabusCreateConnection(Databus * db, ConnectionInfo * info) {
outChannel = db->data->out[outChannelID];
- target = info->GetTargetComponent(info);
+ target = info->targetComponent;
// get inChannel
inDb = target->GetDatabus(target);
@@ -761,7 +856,7 @@ Connection * DatabusCreateConnection(Databus * db, ConnectionInfo * info) {
inChannel = inDb->data->in[inChannelID];
- connStr = info->ConnectionString(info);
+ connStr = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, " Connection: %s", connStr);
if (connStr) {
mcx_free(connStr);
@@ -777,7 +872,7 @@ Connection * DatabusCreateConnection(Databus * db, ConnectionInfo * info) {
retVal = connection->Setup(connection, outChannel, inChannel, info);
if (RETURN_OK != retVal) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
if (buffer) {
mcx_log(LOG_ERROR, "Create connection: Could not setup connection %s", buffer);
mcx_free(buffer);
@@ -878,6 +973,13 @@ static VectorChannelInfo * DatabusInfoGetVectorChannelInfo(DatabusInfo * info, s
return (VectorChannelInfo *) info->data->origInfos->At(info->data->origInfos, i);
}
+int DatabusInChannelsDefined(Databus * db) {
+ return db->data->in != NULL;
+}
+
+int DatabusOutChannelsDefined(Databus* db) {
+ return db->data->out != NULL;
+}
ChannelIn * DatabusGetInChannel(Databus * db, size_t i) {
DatabusInfo * info = NULL;
@@ -1043,13 +1145,13 @@ McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * refe
}
if (CHANNEL_UNKNOWN != type) {
- ChannelInfo * info = ((Channel *)out)->GetInfo((Channel *) out);
- if (info->GetType(info) != type) {
- if (info->IsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
+ ChannelInfo * info = &((Channel *)out)->info;
+ if (info->type != type) {
+ if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
// ok
} else {
mcx_log(LOG_ERROR, "Ports: Set out reference: Port %s has mismatching type %s, given: %s",
- info->GetName(info), ChannelTypeToString(info->GetType(info)), ChannelTypeToString(type));
+ ChannelInfoGetName(info), ChannelTypeToString(info->type), ChannelTypeToString(type));
return RETURN_ERROR;
}
}
@@ -1077,13 +1179,13 @@ McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const voi
return RETURN_ERROR;
}
- info = ((Channel *)out)->GetInfo((Channel *) out);
- if (info->GetType(info) != type) {
+ info = &((Channel *)out)->info;
+ if (info->type != type) {
mcx_log(LOG_ERROR, "Ports: Set out reference function: Port %s has mismatching type %s, given: %s",
- info->GetName(info), ChannelTypeToString(info->GetType(info)), ChannelTypeToString(type));
+ ChannelInfoGetName(info), ChannelTypeToString(info->type), ChannelTypeToString(type));
return RETURN_ERROR;
}
- if (info->IsBinary(info)) {
+ if (ChannelInfoIsBinary(info)) {
mcx_log(LOG_ERROR, "Ports: Set out reference function: Illegal type: Binary");
return RETURN_ERROR;
}
@@ -1227,13 +1329,13 @@ McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference,
}
if (CHANNEL_UNKNOWN != type) {
- info = ((Channel *)in)->GetInfo((Channel *)in);
- if (info->GetType(info) != type) {
- if (info->IsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
+ info = &((Channel *)in)->info;
+ if (info->type != type) {
+ if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
// ok
} else {
mcx_log(LOG_ERROR, "Ports: Set in-reference: Port %s has mismatching type %s, given: %s",
- info->GetName(info), ChannelTypeToString(info->GetType(info)), ChannelTypeToString(type));
+ ChannelInfoGetName(info), ChannelTypeToString(info->type), ChannelTypeToString(type));
return RETURN_ERROR;
}
}
@@ -1352,19 +1454,19 @@ static char * DatabusGetUniqueChannelName(Databus * db, const char * name) {
size_t suffix = 1;
char suffixStr[SUFFIX_LEN] = "";
- ObjectContainer * inInfos = db->data->inInfo->data->infos;
- ObjectContainer * outInfos = db->data->outInfo->data->infos;
- ObjectContainer * localInfos = db->data->localInfo->data->infos;
- ObjectContainer * rtfactorInfos = db->data->rtfactorInfo->data->infos;
+ Vector * inInfos = db->data->inInfo->data->infos;
+ Vector * outInfos = db->data->outInfo->data->infos;
+ Vector * localInfos = db->data->localInfo->data->infos;
+ Vector * rtfactorInfos = db->data->rtfactorInfo->data->infos;
/* Make name unique by adding " %d" suffix */
uniqueName = (char *) mcx_calloc(strlen(name) + SUFFIX_LEN + 1, sizeof(char));
strcpy(uniqueName, name);
strcat(uniqueName, suffixStr);
- while (inInfos->GetNameIndex(inInfos, uniqueName) > -1
- || outInfos->GetNameIndex(outInfos, uniqueName) > -1
- || localInfos->GetNameIndex(localInfos, uniqueName) > -1) {
+ while (ChannelInfosGetNameIdx(inInfos, uniqueName) > -1
+ || ChannelInfosGetNameIdx(outInfos, uniqueName) > -1
+ || ChannelInfosGetNameIdx(localInfos, uniqueName) > -1) {
int len = snprintf(suffixStr, SUFFIX_LEN," %zu", suffix);
strcpy(uniqueName, name);
strcat(uniqueName, suffixStr);
@@ -1382,61 +1484,70 @@ static McxStatus DatabusAddLocalChannelInternal(Databus * db,
const char * unit,
const void * reference,
ChannelType type) {
- ChannelInfo * chInfo = NULL;
+ ChannelInfo chInfo = { 0 };
ChannelLocal * local = NULL;
Channel * channel = NULL;
+ size_t infoDataSize = 0;
char * uniqueName = NULL;
McxStatus retVal = RETURN_OK;
- chInfo = (ChannelInfo *) object_create(ChannelInfo);
- if (!chInfo) {
+
+ retVal = ChannelInfoInit(&chInfo);
+ if (RETURN_ERROR == retVal) {
mcx_log(LOG_ERROR, "Ports: Set local-reference: Create port info for %s failed", name);
return RETURN_ERROR;
}
uniqueName = DatabusGetUniqueChannelName(db, name);
- retVal = chInfo->Init(chInfo, uniqueName, NULL, unit, type, id);
+ retVal = ChannelInfoSetup(&chInfo, uniqueName, NULL, unit, type, id);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Ports: Set local-reference: Initializing ChannelInfo for %s failed", chInfo->GetName(chInfo));
- return RETURN_ERROR;
+ mcx_log(LOG_ERROR, "Ports: Set local-reference: Setting up ChannelInfo for %s failed", ChannelInfoGetName(&chInfo));
+ goto cleanup;
}
mcx_free(uniqueName);
- retVal = infoData->infos->PushBack(infoData->infos, (Object *) chInfo);
+ retVal = infoData->infos->PushBack(infoData->infos, &chInfo);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Ports: Set local-reference: Storing ChannelInfo for %s failed", chInfo->GetName(chInfo));
- return RETURN_ERROR;
+ mcx_log(LOG_ERROR, "Ports: Set local-reference: Storing ChannelInfo for %s failed", ChannelInfoGetName(&chInfo));
+ goto cleanup;
}
+ infoDataSize = infoData->infos->Size(infoData->infos);
+
local = (ChannelLocal *) object_create(ChannelLocal);
if (!local) {
- mcx_log(LOG_ERROR, "Ports: Set local-reference: Create port %s failed", chInfo->GetName(chInfo));
- return RETURN_ERROR;
+ mcx_log(LOG_ERROR, "Ports: Set local-reference: Create port %s failed", ChannelInfoGetName(&chInfo));
+ retVal = RETURN_ERROR;
+ goto cleanup;
}
channel = (Channel *) local;
- retVal = channel->Setup(channel, chInfo);
+ retVal = channel->Setup(channel, infoData->infos->At(infoData->infos, infoDataSize - 1));
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Ports: Set local-reference: Could not setup port %s", chInfo->GetName(chInfo));
- return RETURN_ERROR;
+ mcx_log(LOG_ERROR, "Ports: Set local-reference: Could not setup port %s", ChannelInfoGetName(&chInfo));
+ goto cleanup;
}
retVal = local->SetReference(local, reference, type);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Ports: Set local-reference: Setting reference to %s failed", chInfo->GetName(chInfo));
- return RETURN_ERROR;
+ mcx_log(LOG_ERROR, "Ports: Set local-reference: Setting reference to %s failed", ChannelInfoGetName(&chInfo));
+ goto cleanup;
}
- *dbDataChannel = (ChannelLocal * *) mcx_realloc(*dbDataChannel, infoData->infos->Size(infoData->infos) * sizeof(Channel *));
+ *dbDataChannel = (ChannelLocal * *) mcx_realloc(*dbDataChannel, infoDataSize * sizeof(Channel *));
if (!*dbDataChannel) {
- mcx_log(LOG_ERROR, "Ports: Set local-reference: Memory reallocation for adding %s to ports failed", chInfo->GetName(chInfo));
- return RETURN_ERROR;
+ mcx_log(LOG_ERROR, "Ports: Set local-reference: Memory reallocation for adding %s to ports failed", ChannelInfoGetName(&chInfo));
+ retVal = RETURN_ERROR;
+ goto cleanup;
}
- (*dbDataChannel)[infoData->infos->Size(infoData->infos) - 1] = (ChannelLocal *) channel;
+ (*dbDataChannel)[infoDataSize - 1] = (ChannelLocal *) channel;
- return RETURN_OK;
+cleanup:
+ ChannelInfoDestroy(&chInfo);
+
+ return retVal;
}
McxStatus DatabusAddLocalChannel(Databus * db,
@@ -1675,63 +1786,80 @@ int DatabusChannelRTFactorIsValid(Databus * db, size_t channel) {
return rtfactor->IsValid(rtfactor);
}
-McxStatus DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) {
- size_t i = 0;
- size_t j = 0;
-
- McxStatus retVal = RETURN_OK;
-
- ObjectContainer * infos = db->data->outInfo->data->infos;
+McxStatus DatabusCollectModeSwitchData(Databus * db) {
+ Vector * infos = db->data->outInfo->data->infos;
size_t size = infos->Size(infos);
+ size_t i = 0, j = 0, idx = 0;
+ db->modeSwitchDataSize = 0;
+ // determine cache size
for (i = 0; i < size; i++) {
ChannelOut * out = db->data->out[i];
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
+ db->modeSwitchDataSize += conns->Size(conns);
+ }
+
+ // allocate cache
+ db->modeSwitchData = (ModeSwitchData *)mcx_calloc(db->modeSwitchDataSize, sizeof(ModeSwitchData));
+ if (!db->modeSwitchData) {
+ return RETURN_ERROR;
+ }
- for (j = 0; j < conns->Size(conns); j++) {
- Connection * connection = (Connection *) conns->At(conns, j);
+ // fill up the cache
+ for (i = 0, idx = 0; i < size; i++) {
+ ChannelOut * out = db->data->out[i];
+ ObjectList * conns = out->GetConnections(out);
+ size_t connSize = conns->Size(conns);
+
+ for (j = 0; j < connSize; j++, idx++) {
+ Connection * connection = (Connection*)conns->At(conns, j);
ConnectionInfo * info = connection->GetInfo(connection);
- Component * target = info->GetTargetComponent(info);
- Component * source = info->GetSourceComponent(info);
+ Component * target = info->targetComponent;
+ Component * source = info->sourceComponent;
double targetTimeStepSize = target->GetTimeStep(target);
double sourceTimeStepSize = source->GetTimeStep(source);
- retVal = connection->EnterCouplingStepMode(connection, timeStepSize, sourceTimeStepSize, targetTimeStepSize);
- if (RETURN_OK != retVal) {
- char * buffer = info->ConnectionString(info);
- mcx_log(LOG_ERROR, "Ports: Cannot enter coupling step mode of connection %s", buffer);
- mcx_free(buffer);
- return RETURN_ERROR;
- }
+
+ db->modeSwitchData[idx].connection = connection;
+ db->modeSwitchData[idx].sourceTimeStepSize = sourceTimeStepSize;
+ db->modeSwitchData[idx].targetTimeStepSize = targetTimeStepSize;
}
}
return RETURN_OK;
}
-McxStatus DatabusEnterCommunicationMode(Databus * db, double time) {
+McxStatus DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) {
size_t i = 0;
- size_t j = 0;
-
McxStatus retVal = RETURN_OK;
- ObjectContainer * infos = db->data->outInfo->data->infos;
- size_t size = infos->Size(infos);
+ for (i = 0; i < db->modeSwitchDataSize; i++) {
+ ModeSwitchData data = db->modeSwitchData[i];
+ retVal = data.connection->EnterCouplingStepMode(data.connection, timeStepSize, data.sourceTimeStepSize, data.targetTimeStepSize);
+ if (RETURN_OK != retVal) {
+ ConnectionInfo * info = data.connection->GetInfo(data.connection);
+ char * buffer = ConnectionInfoConnectionString(info);
+ mcx_log(LOG_ERROR, "Ports: Cannot enter coupling step mode of connection %s", buffer);
+ mcx_free(buffer);
+ return RETURN_ERROR;
+ }
+ }
- for (i = 0; i < size; i++) {
- ChannelOut * out = db->data->out[i];
- ObjectContainer * conns = out->GetConnections(out);
+ return RETURN_OK;
+}
- for (j = 0; j < conns->Size(conns); j++) {
- Connection * connection = (Connection *) conns->At(conns, j);
- ConnectionInfo * info = connection->GetInfo(connection);
+McxStatus DatabusEnterCommunicationMode(Databus * db, double time) {
+ size_t i = 0;
+ McxStatus retVal = RETURN_OK;
- retVal = connection->EnterCommunicationMode(connection, time);
- if (RETURN_OK != retVal) {
- char * buffer = info->ConnectionString(info);
- mcx_log(LOG_ERROR, "Ports: Cannot enter communication mode of connection %s", buffer);
- mcx_free(buffer);
- return RETURN_ERROR;
- }
+ for (i = 0; i < db->modeSwitchDataSize; i++) {
+ ModeSwitchData data = db->modeSwitchData[i];
+ retVal = data.connection->EnterCommunicationMode(data.connection, time);
+ if (RETURN_OK != retVal) {
+ ConnectionInfo * info = data.connection->GetInfo(data.connection);
+ char * buffer = ConnectionInfoConnectionString(info);
+ mcx_log(LOG_ERROR, "Ports: Cannot enter communication mode of connection %s", buffer);
+ mcx_free(buffer);
+ return RETURN_ERROR;
}
}
@@ -1739,13 +1867,15 @@ McxStatus DatabusEnterCommunicationMode(Databus * db, double time) {
}
/* The container connections may only contain connections outgoing from this db */
-McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectContainer * connections, double time) {
+McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectList * connections, double time) {
size_t i = 0;
- for (i = 0; i < connections->Size(connections); i++) {
+ size_t connSize = connections->Size(connections);
+
+ for (i = 0; i < connSize; i++) {
Connection * connection = (Connection *) connections->At(connections, i);
ConnectionInfo * info = connection->GetInfo(connection);
- Component * comp = info->GetSourceComponent(info);
+ Component * comp = info->sourceComponent;
Databus * connDb = comp->GetDatabus(comp);
McxStatus retVal = RETURN_OK;
@@ -1753,7 +1883,7 @@ McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectContai
if (db == connDb) {
retVal = connection->EnterCommunicationMode(connection, time);
if (RETURN_OK != retVal) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_ERROR, "Ports: Cannot enter communication mode of connection %s", buffer);
mcx_free(buffer);
return RETURN_ERROR;
diff --git a/src/core/Databus.h b/src/core/Databus.h
index b392150..70cda7e 100644
--- a/src/core/Databus.h
+++ b/src/core/Databus.h
@@ -246,10 +246,14 @@ struct Connection * DatabusCreateConnection(struct Databus * db, struct Connecti
* \return \c RETURN_OK on success, or \c RETURN_ERROR otherwise.
*/
McxStatus DatabusTriggerInConnections(struct Databus * db, TimeInterval * consumerTime);
+McxStatus DatabusTriggerConnectedInConnections(struct Databus * db, TimeInterval * consumerTime);
+McxStatus DatabusUpdateInConnected(Databus * db);
+
+McxStatus DatabusCollectModeSwitchData(Databus * db);
McxStatus DatabusEnterCouplingStepMode(struct Databus * db, double timeStepSize);
McxStatus DatabusEnterCommunicationMode(struct Databus * db, double time);
-McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectContainer * connections, double time);
+McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectList * connections, double time);
/* private interface for Component, Model, Task */
@@ -288,6 +292,9 @@ size_t DatabusInfoGetNumWriteChannels(DatabusInfo * dbInfo);
/* internal */
+int DatabusInChannelsDefined(Databus * db);
+int DatabusOutChannelsDefined(Databus * db);
+
/**
* Accessor function for the \a i-th in channel of \a db.
*
@@ -318,10 +325,20 @@ struct Channel * DatabusGetRTFactorChannel(Databus * db, size_t i);
extern const struct ObjectClass _Databus;
+
+typedef struct {
+ Connection * connection;
+ double sourceTimeStepSize;
+ double targetTimeStepSize;
+} ModeSwitchData;
+
typedef struct Databus {
Object _; // base class
struct DatabusData * data;
+
+ ModeSwitchData * modeSwitchData;
+ size_t modeSwitchDataSize;
} Databus;
char * CreateIndexedName(const char * name, unsigned i);
diff --git a/src/core/Databus_impl.h b/src/core/Databus_impl.h
index 40ef811..8527c27 100644
--- a/src/core/Databus_impl.h
+++ b/src/core/Databus_impl.h
@@ -11,6 +11,8 @@
#ifndef MCX_CORE_DATABUS_IMPL_H
#define MCX_CORE_DATABUS_IMPL_H
+#include "objects/Vector.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -27,7 +29,7 @@ extern const struct ObjectClass _DatabusInfoData;
typedef struct DatabusInfoData {
Object _; // base class
- ObjectContainer * infos;
+ Vector * infos;
ObjectContainer * origInfos;
} DatabusInfoData;
@@ -51,6 +53,8 @@ typedef struct DatabusData {
Object _; // base class
struct ChannelIn ** in; /**< input channels */
+ struct ChannelIn ** inConnected; /**< connected input channels */
+ size_t numInConnected;
struct ChannelOut ** out; /**< output channels */
struct ChannelLocal ** local; /**< local (non-connectable) channels */
struct ChannelLocal ** rtfactor; /**< rtfactor (non-connectable) channels */
diff --git a/src/core/Model.c b/src/core/Model.c
index 16d1a92..3c7246b 100644
--- a/src/core/Model.c
+++ b/src/core/Model.c
@@ -14,6 +14,7 @@
#include "steptypes/StepType.h"
#include "tarjan.h"
#include "components/ComponentFactory.h"
+#include "components/comp_constant.h"
#include "reader/model/ModelInput.h"
#include "reader/model/components/ComponentsInput.h"
#include "reader/model/components/ComponentInput.h"
@@ -23,8 +24,8 @@
#include "core/Databus.h"
#include "core/channels/Channel.h"
+#include "core/channels/ChannelInfo.h"
#include "core/connections/Connection.h"
-#include "core/connections/ConnectionInfo_impl.h"
#include "core/connections/FilteredConnection.h"
#include "core/SubModel.h"
@@ -42,43 +43,44 @@ extern "C" {
static ChannelInfo * GetTargetChannelInfo(ConnectionInfo * info) {
- Component * trg = info->GetTargetComponent(info);
+ Component * trg = info->targetComponent;
struct Databus * trgDb = trg->GetDatabus(trg);
- int trgId = info->GetTargetChannelID(info);
+ int trgId = info->targetChannel;
return DatabusGetInChannelInfo(trgDb, trgId);
}
static ChannelInfo * GetSourceChannelInfo(ConnectionInfo * info) {
- Component * src = info->GetSourceComponent(info);
+ Component * src = info->sourceComponent;
struct Databus * srcDb = src->GetDatabus(src);
- int srcId = info->GetSourceChannelID(info);
+ int srcId = info->sourceChannel;
return DatabusGetOutChannelInfo(srcDb, srcId);
}
-static int ConnInfoWithSrc(Object * obj, void * ctx) {
+static int ConnInfoWithSrc(void * elem, void * arg) {
/*
* TRUE if obj (ConnectionInfo) has ctx as its source ChannelInfo
*/
- ConnectionInfo * info = (ConnectionInfo *)obj;
+ ChannelInfo * chInfo = (ChannelInfo *) arg;
+ ConnectionInfo * info = *((ConnectionInfo **) elem);
ChannelInfo * srcInfo = GetSourceChannelInfo(info);
- return srcInfo == (ChannelInfo *)ctx;
+ return srcInfo == chInfo;
}
-static int IsBinaryConn(Object * obj) {
+static int IsBinaryConn(void * elem, void * args) {
/*
* TRUE if both source and target channel infos of obj (ConnectionInfo) are binary
*/
- ConnectionInfo * info = (ConnectionInfo *)obj;
+ ConnectionInfo * info = (ConnectionInfo *) elem;
ChannelInfo * srcInfo = GetSourceChannelInfo(info);
ChannelInfo * trgInfo = GetTargetChannelInfo(info);
- return srcInfo->IsBinary(srcInfo) && trgInfo->IsBinary(trgInfo);
+ return ChannelInfoIsBinary(srcInfo) && ChannelInfoIsBinary(trgInfo);
}
-static int CanMakeChannelsBinReferences(ObjectContainer * connInfos, Task * task) {
+static int CanMakeChannelsBinReferences(Vector * connInfos, Task * task) {
/*
* Checks whether all binary connections in connInfos satisfy the condition
* to use CHANNEL_BINARY_REFERENCE instead of CHANNEL_BINARY.
@@ -93,10 +95,10 @@ static int CanMakeChannelsBinReferences(ObjectContainer * connInfos, Task * task
size_t num = connInfos->Size(connInfos);
for (i = 0; i < num; i++) {
- ConnectionInfo * info = (ConnectionInfo *)connInfos->At(connInfos, i);
+ ConnectionInfo * info = *(ConnectionInfo **)connInfos->At(connInfos, i);
- Component * trg = info->GetTargetComponent(info);
- Component * src = info->GetSourceComponent(info);
+ Component * trg = info->targetComponent;
+ Component * src = info->sourceComponent;
ChannelInfo * trgInfo = GetTargetChannelInfo(info);
ChannelInfo * srcInfo = GetSourceChannelInfo(info);
@@ -114,7 +116,7 @@ static int CanMakeChannelsBinReferences(ObjectContainer * connInfos, Task * task
return TRUE;
}
-static void UpdateBinaryChannelTypes(ObjectContainer * connInfos, Task * task) {
+static void UpdateBinaryChannelTypes(Vector * connInfos, Task * task) {
/*
* Updates the channel types of binary connections in connInfos according to the
* result of `CanMakeChannelsBinReferences` (see function for more info)
@@ -124,20 +126,20 @@ static void UpdateBinaryChannelTypes(ObjectContainer * connInfos, Task * task) {
int canMakeReference = CanMakeChannelsBinReferences(connInfos, task);
for (i = 0; i < connInfos->Size(connInfos); i++) {
- ConnectionInfo * info = (ConnectionInfo *)connInfos->At(connInfos, i);
+ ConnectionInfo * info = *(ConnectionInfo **)connInfos->At(connInfos, i);
ChannelInfo * srcInfo = GetSourceChannelInfo(info);
ChannelInfo * trgInfo = GetTargetChannelInfo(info);
if (canMakeReference) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, "Fast binary channel requirements fulfilled for connection %s", buffer);
mcx_free(buffer);
trgInfo->type = CHANNEL_BINARY_REFERENCE;
srcInfo->type = CHANNEL_BINARY_REFERENCE;
} else {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, "Using binary channels for connection %s", buffer);
mcx_free(buffer);
@@ -147,12 +149,125 @@ static void UpdateBinaryChannelTypes(ObjectContainer * connInfos, Task * task) {
}
}
+/**
+ * Remove connections to Constant elements from the model
+ * For each such connection, the value of the Constant shall be taken
+ * and set as the default value of the corresponding input.
+ * Necessary value/type conversions are done as well.
+ */
+static McxStatus ModelPreprocessConstConnections(Model * model) {
+ Vector * conns = model->connections;
+ Vector * filteredConns = NULL;
+
+ size_t i = 0;
+ McxStatus retVal = RETURN_OK;
+
+ filteredConns = (Vector*)object_create(Vector);
+ if (!filteredConns) {
+ mcx_log(LOG_ERROR, "Not enough memory to filter out constant connections");
+ return RETURN_ERROR;
+ }
+ filteredConns->Setup(filteredConns, sizeof(ConnectionInfo), ConnectionInfoInit, NULL, NULL);
+
+ for (i = 0; i < conns->Size(conns); i++) {
+ ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i);
+ ChannelValue * src = NULL;
+
+ Component * srcComp = info->sourceComponent;
+ CompConstant * srcCompConst = NULL;
+ Databus * srcDb = srcComp->GetDatabus(srcComp);
+ ChannelInfo * srcChannelInfo = DatabusGetOutChannelInfo(srcDb, info->sourceChannel);
+
+ Component * trgComp = info->targetComponent;
+ Databus * trgDb = trgComp->GetDatabus(trgComp);
+ ChannelInfo * trgChannelInfo = DatabusGetInChannelInfo(trgDb, info->targetChannel);
+
+ // if not a const conn, add to the filtered conns
+ if (0 != strcmp(compConstantTypeString, srcComp->GetType(srcComp))) {
+ filteredConns->PushBack(filteredConns, info);
+ continue;
+ }
+
+ // else kick the connection and update the channel default value
+ srcCompConst = (CompConstant *) srcComp;
+ src = (ChannelValue *) mcx_calloc(1, sizeof(ChannelValue));
+
+ if (!src) {
+ mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Not enough memory");
+ goto cleanup_1;
+ }
+
+ ChannelValueInit(src, srcChannelInfo->type);
+ retVal = ChannelValueSet(src, srcCompConst->GetValue(srcCompConst, info->sourceChannel));
+ if (retVal == RETURN_ERROR) {
+ goto cleanup_1;
+ }
+
+ // out channel range and linear conversions
+ retVal = ConvertRange(srcChannelInfo->min, srcChannelInfo->max, src);
+ if (retVal == RETURN_ERROR) {
+ goto cleanup_1;
+ }
+
+ retVal = ConvertLinear(srcChannelInfo->scale, srcChannelInfo->offset, src);
+ if (retVal == RETURN_ERROR) {
+ goto cleanup_1;
+ }
+
+ // type conversion
+ retVal = ConvertType(srcChannelInfo->type, trgChannelInfo->type, src);
+ if (retVal == RETURN_ERROR) {
+ goto cleanup_1;
+ }
+
+ // unit conversion
+ retVal = ConvertUnit(srcChannelInfo->unitString, trgChannelInfo->unitString, src);
+ if (retVal == RETURN_ERROR) {
+ goto cleanup_1;
+ }
+
+ // set the default value
+ if (trgChannelInfo->defaultValue) {
+ ChannelValueDestructor(trgChannelInfo->defaultValue);
+ }
+ trgChannelInfo->defaultValue = src;
+
+ continue;
+
+cleanup_1:
+ if (src) {
+ ChannelValueDestructor(src);
+ mcx_free(src);
+ }
+
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
+
+cleanup:
+ if (retVal == RETURN_ERROR) {
+ object_destroy(filteredConns);
+
+ return RETURN_ERROR;
+ }
+
+ object_destroy(conns);
+ model->connections = filteredConns;
+
+ return RETURN_OK;
+}
+
+static int ConnInfoContained(void * elem, void * arg) {
+ ConnectionInfo * info = *(ConnectionInfo **) elem;
+ return info == (ConnectionInfo *) arg;
+}
+
static McxStatus ModelPreprocessBinaryConnections(Model * model) {
- ObjectContainer * conns = model->connections;
+ Vector * conns = model->connections;
size_t connsSize = conns->Size(conns);
- ObjectContainer * binConnInfos = NULL;
- ObjectContainer * processedConnInfos = NULL;
+ Vector * binConnInfos = NULL;
+ Vector * processedConnInfos = NULL;
size_t i = 0;
@@ -164,30 +279,32 @@ static McxStatus ModelPreprocessBinaryConnections(Model * model) {
return RETURN_OK;
}
- // filter all binary connection
- binConnInfos = conns->Filter(conns, IsBinaryConn);
+ binConnInfos = conns->FilterRef(conns, IsBinaryConn, NULL);
if (!binConnInfos) {
mcx_log(LOG_ERROR, "Not enough memory for binary connections");
retVal = RETURN_ERROR;
goto cleanup;
}
- processedConnInfos = (ObjectContainer *)object_create(ObjectContainer);
+ processedConnInfos = (Vector*)object_create(Vector);
if (!processedConnInfos) {
mcx_log(LOG_ERROR, "Not enough memory for processed binary connections");
retVal = RETURN_ERROR;
goto cleanup;
}
+ processedConnInfos->Setup(processedConnInfos, sizeof(ConnectionInfo*), NULL, NULL, NULL);
+
for (i = 0; i < binConnInfos->Size(binConnInfos); i++) {
- ConnectionInfo * info = (ConnectionInfo *)binConnInfos->At(binConnInfos, i);
+ ConnectionInfo * info = *(ConnectionInfo **)binConnInfos->At(binConnInfos, i);
+ ChannelInfo * srcInfo = GetSourceChannelInfo(info);
+ Vector* connInfos = NULL;
- if (processedConnInfos->Contains(processedConnInfos, (Object *)info)) {
+ if (processedConnInfos->FindIdx(processedConnInfos, ConnInfoContained, info) != SIZE_T_ERROR) {
continue;
}
- ChannelInfo * srcInfo = GetSourceChannelInfo(info);
- ObjectContainer * connInfos = binConnInfos->FilterCtx(binConnInfos, ConnInfoWithSrc, srcInfo);
+ connInfos = binConnInfos->Filter(binConnInfos, ConnInfoWithSrc, srcInfo);
if (!connInfos) {
mcx_log(LOG_ERROR, "Not enough memory for filtered binary connections");
retVal = RETURN_ERROR;
@@ -213,7 +330,7 @@ static McxStatus ModelPreprocessBinaryConnections(Model * model) {
}
static int ComponentIsBoundaryCondition(const Component * comp) {
- if (0 == strcmp("CONSTANT", comp->GetType(comp))
+ if (0 == strcmp(compConstantTypeString, comp->GetType(comp))
)
{
return TRUE;
@@ -221,18 +338,18 @@ static int ComponentIsBoundaryCondition(const Component * comp) {
return FALSE;
}
-static ObjectContainer * GetAllSourceConnInfos(Model * model, Component * comp) {
- ObjectContainer * conns = model->connections;
- ObjectContainer * comps = model->components;
+static Vector * GetAllSourceConnInfoRefs(Model * model, Component * comp) {
+ Vector * conns = model->connections;
size_t numConnections = conns->Size(conns);
- ObjectContainer * sources = (ObjectContainer *) object_create(ObjectContainer);
+ Vector * sources = (Vector*) object_create(Vector);
size_t i = 0;
+ sources->Setup(sources, sizeof(ConnectionInfo*), NULL, NULL, NULL);
for (i = 0; i < numConnections; i++) {
ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i);
- Component * target = info->GetTargetComponent(info);
+ Component * target = info->targetComponent;
if (target == comp) {
- sources->PushBack(sources, (Object *) info);
+ sources->PushBack(sources, &info);
}
}
@@ -240,17 +357,16 @@ static ObjectContainer * GetAllSourceConnInfos(Model * model, Component * comp)
}
static ObjectContainer * GetAllSourceElements(Model * model, Component * comp) {
- ObjectContainer * conns = model->connections;
- ObjectContainer * comps = model->components;
+ Vector * conns = model->connections;
size_t numConnections = conns->Size(conns);
ObjectContainer * sources = (ObjectContainer *) object_create(ObjectContainer);
size_t i = 0;
for (i = 0; i < numConnections; i++) {
ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i);
- Component * target = info->GetTargetComponent(info);
+ Component * target = info->targetComponent;
if (target == comp) {
- Component * source = info->GetSourceComponent(info);
+ Component * source = info->sourceComponent;
if (!sources->Contains(sources, (Object *) source)) {
sources->PushBack(sources, (Object *) source);
}
@@ -263,6 +379,12 @@ static ObjectContainer * GetAllSourceElements(Model * model, Component * comp) {
static McxStatus ModelPreprocess(Model * model) {
McxStatus retVal = RETURN_OK;
+ retVal = ModelPreprocessConstConnections(model);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Model: Preprocessing const connections failed");
+ return RETURN_ERROR;
+ }
+
retVal = ModelPreprocessBinaryConnections(model);
if (RETURN_ERROR == retVal) {
mcx_log(LOG_ERROR, "Model: Preprocessing binary connections failed");
@@ -287,13 +409,13 @@ static McxStatus ModelInsertAllFilters(Model * model) {
for (j = 0; j < numOutChannels; j++) {
ChannelOut * out = DatabusGetOutChannel(db, j);
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
for (k = 0; k < conns->Size(conns); k++) {
Connection * connection = (Connection *) conns->At(conns, k);
ConnectionInfo * info = connection->GetInfo(connection);
if (connection->AddFilter) {
- char * connStr = info->ConnectionString(info);
+ char * connStr = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, " Adding filter to connection: %s", connStr);
if (connStr) {
mcx_free(connStr);
@@ -355,6 +477,36 @@ static McxStatus ModelCreateInitSubModel(Model * model) {
return retVal;
}
+McxStatus ModelInitInConnectedList(ObjectContainer * comps) {
+ size_t i = 0;
+
+ for (i = 0; i < comps->Size(comps); i++) {
+ Component * comp = (Component *)comps->At(comps, i);
+ McxStatus retVal = DatabusUpdateInConnected(comp->GetDatabus(comp));
+ if (RETURN_ERROR == retVal) {
+ ComponentLog(comp, LOG_ERROR, "Could not initialize the In-Connection list");
+ return RETURN_ERROR;
+ }
+ }
+ return RETURN_OK;
+}
+
+static McxStatus ModelSignalConnectionsDone(ObjectContainer * comps) {
+ size_t i = 0;
+
+ for (i = 0; i < comps->Size(comps); i++) {
+ Component * comp = (Component *)comps->At(comps, i);
+ if (NULL != comp->OnConnectionsDone) {
+ if (RETURN_ERROR == comp->OnConnectionsDone(comp)) {
+ ComponentLog(comp, LOG_ERROR, "OnConnectionsDone callback failed");
+ return RETURN_ERROR;
+ }
+ }
+ }
+
+ return RETURN_OK;
+}
+
static McxStatus ModelConnectionsDone(Model * model) {
OrderedNodes * orderedNodes = NULL;
McxStatus retVal = RETURN_OK;
@@ -365,10 +517,23 @@ static McxStatus ModelConnectionsDone(Model * model) {
goto cleanup;
}
+ retVal = ModelInitInConnectedList(model->components);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Model: In-Connection lists could not be initialized");
+ goto cleanup;
+ }
+
+ retVal = ModelSignalConnectionsDone(model->components);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Model: Components could not be notified about connection completion");
+ goto cleanup;
+ }
+
// determine initialization evaluation order
if (model->config->cosimInitEnabled) {
retVal = ModelCreateInitSubModel(model);
- if (retVal != RETURN_OK) {
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Model: InitSubModel could not be created");
goto cleanup;
}
}
@@ -435,6 +600,11 @@ static McxStatus ModelConnectionsDone(Model * model) {
goto cleanup;
}
+ retVal = model->subModel->LoopComponents(model->subModel, CompCollectModeSwitchData, NULL);
+ if (RETURN_ERROR == retVal) {
+ return retVal;
+ }
+
cleanup:
if (orderedNodes) {
tarjan_ordered_nodes_cleanup(orderedNodes);
@@ -456,7 +626,7 @@ static Connection * ModelGetConnectionFromInfo(Model * model, ConnectionInfo * i
for (j = 0; j < numOutChannels; j++) {
ChannelOut * out = DatabusGetOutChannel(db, j);
- ObjectContainer * conns = out->GetConnections(out);
+ ObjectList * conns = out->GetConnections(out);
for (k = 0; k < conns->Size(conns); k++) {
Connection * connection = (Connection *) conns->At(conns, k);
@@ -549,13 +719,13 @@ static McxStatus ModelReadComponents(void * self, ComponentsInput * input) {
}
}
- mcx_log(LOG_INFO, "Read %d elements", numComps);
+ mcx_log(LOG_INFO, "Read %zu elements", numComps);
mcx_log(LOG_INFO, " ");
return RETURN_OK;
}
-McxStatus ReadConnections(ObjectContainer * connections,
+McxStatus ReadConnections(Vector * connections,
ConnectionsInput * connectionsInput,
ObjectContainer * components,
Component * sourceComp,
@@ -566,7 +736,7 @@ McxStatus ReadConnections(ObjectContainer * connections,
// loop over all connections here
for (i = 0; i < connInputs->Size(connInputs); i++) {
ConnectionInput * connInput = (ConnectionInput*)connInputs->At(connInputs, i);
- ObjectContainer * conns = NULL;
+ Vector * conns = NULL;
size_t connsSize = 0;
size_t j = 0;
@@ -581,7 +751,7 @@ McxStatus ReadConnections(ObjectContainer * connections,
ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, j);
char * connStr = NULL;
- connStr = info->ConnectionString(info);
+ connStr = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, " Connection: %s", connStr);
mcx_free(connStr);
}
@@ -590,7 +760,7 @@ McxStatus ReadConnections(ObjectContainer * connections,
object_destroy(conns);
}
- mcx_log(LOG_INFO, "Read %d connections", connections->Size(connections));
+ mcx_log(LOG_INFO, "Read %zu connections", connections->Size(connections));
mcx_log(LOG_INFO, " ");
return RETURN_OK;
@@ -609,13 +779,10 @@ static McxStatus ModelReadConnections(void * self, ConnectionsInput * input) {
}
static McxStatus ModelCheckConnectivity(Model * model) {
- ObjectContainer * connections = model->connections;
- McxStatus retVal = RETURN_OK;
-
- return CheckConnectivity(connections);
+ return CheckConnectivity(model->connections);
}
-McxStatus MakeConnections(ObjectContainer * connections, InterExtrapolatingType isInterExtrapolating) {
+McxStatus MakeConnections(Vector * connections, InterExtrapolatingType isInterExtrapolating) {
ConnectionInfo * info = NULL;
McxStatus retVal = RETURN_OK;
size_t i = 0;
@@ -648,7 +815,7 @@ static McxStatus ModelMakeConnections(Model * model) {
retVal = MakeConnections(model->connections, isInterExtrapolating);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Model: Creating connection %d failed", i);
+ mcx_log(LOG_ERROR, "Model: Creating connection %zu failed", i);
return RETURN_ERROR;
}
mcx_log(LOG_DEBUG, "Creating connections done");
@@ -689,7 +856,7 @@ static McxStatus ModelRead(void * self, ModelInput * input) {
static McxStatus ModelDoComponentNameCheck(Component * comp, void * param) {
Component * comp2 = (Component *) param;
if (! strcmp(comp->GetName(comp), comp2->GetName(comp2)) && (comp != comp2)) {
- mcx_log(LOG_ERROR, "Model: Elements %d and %d have the same name", comp->GetID(comp), comp2->GetID(comp2));
+ mcx_log(LOG_ERROR, "Model: Elements %zu and %zu have the same name", comp->GetID(comp), comp2->GetID(comp2));
return RETURN_ERROR;
}
@@ -715,24 +882,24 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para
for (i = 0; i < numInChannels; i++) {
Channel * channel = (Channel *)DatabusGetInChannel(db, i);
- ChannelInfo * info = channel->GetInfo(channel);
+ ChannelInfo * info = &channel->info;
- if ((info->GetMode(info) == CHANNEL_MANDATORY)
+ if ((info->mode == CHANNEL_MANDATORY)
&& !channel->IsValid(channel)) {
- mcx_log(LOG_ERROR, "Model: %d. inport (%s) of element %s not connected"
- , i+1, info->GetName(info), comp->GetName(comp));
+ mcx_log(LOG_ERROR, "Model: %zu. inport (%s) of element %s not connected"
+ , i+1, ChannelInfoGetName(info), comp->GetName(comp));
return RETURN_ERROR;
}
}
for (i = 0; i < numOutChannels; i++) {
Channel * channel = (Channel *)DatabusGetOutChannel(db, i);
- ChannelInfo * info = channel->GetInfo(channel);
+ ChannelInfo * info = &channel->info;
- if ((info->GetMode(info) == CHANNEL_MANDATORY)
+ if ((info->mode == CHANNEL_MANDATORY)
&& !channel->IsValid(channel)) {
- mcx_log(LOG_ERROR, "Model: %d. outport (%s) of element %s not connected"
- , i+1, info->GetName(info), comp->GetName(comp));
+ mcx_log(LOG_ERROR, "Model: %zu. outport (%s) of element %s not connected"
+ , i+1, ChannelInfoGetName(info), comp->GetName(comp));
return RETURN_ERROR;
}
}
@@ -743,7 +910,7 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para
static McxStatus ModelDoConsistencyChecks(Model * model) {
SubModel * subModel = model->subModel;
- ObjectContainer * conns = model->connections;
+ Vector * conns = model->connections;
ObjectContainer * comps = model->components;
Task * task = model->task;
@@ -760,8 +927,7 @@ static McxStatus ModelDoConsistencyChecks(Model * model) {
for (i = 0; i < conns->Size(conns); i++) {
ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i);
- if ((info->GetDecouplePriority(info) > 0)
- || (info->GetDecoupleType(info) != DECOUPLE_DEFAULT)) {
+ if (info->decouplePriority > 0 || info->decoupleType != DECOUPLE_DEFAULT) {
hasDecoupleInfos = 1;
}
}
@@ -1194,11 +1360,22 @@ static McxStatus ModelInitialize(Model * model) {
return RETURN_ERROR;
}
+ {
+ McxTime rtGlobalSimStart;
+ mcx_time_get(&rtGlobalSimStart);
+
+ retVal = subModel->LoopComponents(subModel, ComponentBeforeDoSteps, &rtGlobalSimStart);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Model: Initialization of elements failed");
+ return retVal;
+ }
+ }
+
return RETURN_OK;
}
static const char * GetComponentAbbrev(const char * type) {
- if (!strcmp(type, "CONSTANT")) {
+ if (!strcmp(type, compConstantTypeString)) {
return "C";
} else if (!strcmp(type, "INTEGRATOR")) {
return "INT";
@@ -1238,7 +1415,7 @@ McxStatus PrintComponentGraph(Component * comp,
mcx_os_fprintf(dotFile, "
\n", tableArgs);
for (j = 0; j < GetDependencyNumIn(A); j++) {
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, " | %d | \n", j, j);
+ mcx_os_fprintf(dotFile, " %zu | \n", j, j);
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, "
\n");
@@ -1256,7 +1433,7 @@ McxStatus PrintComponentGraph(Component * comp,
mcx_os_fprintf(dotFile, " \n", tableArgs);
for (j = 0; j < DatabusGetOutChannelsNum(db); j++) {
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, " | %d | \n", j, j);
+ mcx_os_fprintf(dotFile, " %zu | \n", j, j);
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, "
\n");
@@ -1280,7 +1457,7 @@ McxStatus PrintComponentGraph(Component * comp,
}
GetDependency(A, i, grp, &dep);
if (dep != DEP_INDEPENDENT) {
- mcx_os_fprintf(dotFile, "in:in%d -> out:out%d;\n", i, j);
+ mcx_os_fprintf(dotFile, "in:in%zu -> out:out%zu;\n", i, j);
}
}
}
@@ -1298,7 +1475,7 @@ McxStatus PrintComponentGraph(Component * comp,
return RETURN_OK;
}
-McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Component * inComp, Component * outComp, const char * title, const char * filename) {
+McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * inComp, Component * outComp, const char * title, const char * filename) {
size_t i = 0;
size_t j = 0;
@@ -1322,14 +1499,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp
mcx_os_fprintf(dotFile, " \n", tableArgs);
for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) {
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, " | %d | \n", j, j);
+ mcx_os_fprintf(dotFile, " %zu | \n", j, j);
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, " \n");
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, ">] comp%d;\n", comps->Size(comps));
+ mcx_os_fprintf(dotFile, ">] comp%zu;\n", comps->Size(comps));
}
for (i = 0; i < comps->Size(comps); i++) {
@@ -1345,7 +1522,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp
mcx_os_fprintf(dotFile, " \n", tableArgs);
for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) {
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, " | %d | \n", j, j);
+ mcx_os_fprintf(dotFile, " %zu | \n", j, j);
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, "
\n");
@@ -1359,14 +1536,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp
mcx_os_fprintf(dotFile, " \n", tableArgs);
for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) {
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, " | %d | \n", j, j);
+ mcx_os_fprintf(dotFile, " %zu | \n", j, j);
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, " \n");
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, ">] comp%d;\n", c->GetID(c));
+ mcx_os_fprintf(dotFile, ">] comp%zu;\n", c->GetID(c));
}
if (outComp) {
@@ -1381,7 +1558,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp
mcx_os_fprintf(dotFile, " \n", tableArgs);
for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) {
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, " | %d | \n", j, j);
+ mcx_os_fprintf(dotFile, " %zu | \n", j, j);
mcx_os_fprintf(dotFile, "
\n");
}
mcx_os_fprintf(dotFile, "
\n");
@@ -1389,21 +1566,21 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp
mcx_os_fprintf(dotFile, " \n");
mcx_os_fprintf(dotFile, " out | \n");
mcx_os_fprintf(dotFile, " \n");
- mcx_os_fprintf(dotFile, ">] comp%d;\n", comps->Size(comps) + 1);
+ mcx_os_fprintf(dotFile, ">] comp%zu;\n", comps->Size(comps) + 1);
}
mcx_os_fprintf(dotFile, "{\n");
if (inComp && outComp) {
- mcx_os_fprintf(dotFile, "comp%d -> comp%d [style=invis];\n",
+ mcx_os_fprintf(dotFile, "comp%zu -> comp%zu [style=invis];\n",
comps->Size(comps),
comps->Size(comps) + 1);
}
for (i = 0; i < conns->Size(conns); i++) {
ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i);
- Component * src = info->GetSourceComponent(info);
- Component * trg = info->GetTargetComponent(info);
+ Component * src = info->sourceComponent;
+ Component * trg = info->targetComponent;
size_t srcID = src->GetID(src);
size_t trgID = trg->GetID(trg);
@@ -1416,8 +1593,8 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp
}
mcx_os_fprintf(dotFile, "comp%zu:out%d -> comp%zu:in%d;\n",
- srcID, info->GetSourceChannelID(info),
- trgID, info->GetTargetChannelID(info));
+ srcID, info->sourceChannel,
+ trgID, info->targetChannel);
}
mcx_os_fprintf(dotFile, "}\n");
@@ -1468,7 +1645,8 @@ static Model * ModelCreate(Model * model) {
// set to default values
model->components = (ObjectContainer *) object_create(ObjectContainer);
- model->connections = (ObjectContainer *) object_create(ObjectContainer);
+ model->connections = (Vector *) object_create(Vector);
+ model->connections->Setup(model->connections, sizeof(ConnectionInfo), ConnectionInfoInit, NULL, NULL);
model->factory = NULL;
model->config = NULL;
diff --git a/src/core/Model.h b/src/core/Model.h
index 2f1cfab..5465ad7 100644
--- a/src/core/Model.h
+++ b/src/core/Model.h
@@ -19,6 +19,7 @@
#include "core/SubModel.h"
#include "reader/model/ModelInput.h"
#include "components/ComponentFactory.h"
+#include "objects/Vector.h"
#ifdef __cplusplus
extern "C" {
@@ -63,7 +64,7 @@ struct Model {
Config * config;
Task * task;
- ObjectContainer * connections;
+ Vector * connections;
ObjectContainer * components;
@@ -77,7 +78,7 @@ struct Model {
} ;
-McxStatus ReadConnections(ObjectContainer * connections,
+McxStatus ReadConnections(Vector * connections,
ConnectionsInput * connectionsInput,
ObjectContainer * components,
Component * sourceComp,
@@ -86,9 +87,9 @@ McxStatus ReadConnections(ObjectContainer * connections,
McxStatus SetupComponents(ObjectContainer * components, Component * leaveOutComponent);
McxStatus SetupDatabusComponents(ObjectContainer * components);
-McxStatus MakeConnections(ObjectContainer * connections, InterExtrapolatingType isInterExtrapolating);
+McxStatus MakeConnections(Vector * connections, InterExtrapolatingType isInterExtrapolating);
-McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Component * inComp, Component * outComp, const char * title, const char * filename);
+McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * inComp, Component * outComp, const char * title, const char * filename);
McxStatus PrintComponentGraph(Component * comp, const char * filename,
struct Dependencies * A, DependencyType depType);
diff --git a/src/core/SubModel.c b/src/core/SubModel.c
index 1e67fd5..87feb06 100644
--- a/src/core/SubModel.c
+++ b/src/core/SubModel.c
@@ -14,13 +14,15 @@
#include "core/SubModel.h"
#include "core/Component.h"
#include "core/connections/Connection.h"
+#include "core/channels/ChannelInfo.h"
#include "core/Databus.h"
#include "core/channels/Channel.h"
#ifdef __cplusplus
- extern "C" {
+extern "C" {
#endif /* __cplusplus */
+
static McxStatus SubModelGeneratorSetComponents(SubModelGenerator * subModelGenerator, ObjectContainer * comps,
DependencyType depType);
@@ -80,7 +82,7 @@ static McxStatus SubModelGeneratorPrintNodeMap(SubModelGenerator * subModelGener
}
if (comp->OneOutputOneGroup(comp)) {
ChannelInfo * info = DatabusGetOutChannelInfo(comp->GetDatabus(comp), compAndGroup->group);
- mcx_log(LOG_INFO, " %s (%s, %s)", enu, comp->GetName(comp), info->GetName(info));
+ mcx_log(LOG_INFO, " %s (%s, %s)", enu, comp->GetName(comp), ChannelInfoGetName(info));
mcx_log(LOG_DEBUG, " (%zu)", compAndGroup->group);
} else if(depType == INITIAL_DEPENDENCIES && comp->GetNumInitialOutGroups(comp) == 1 ||
depType == RUNTIME_DEPENDENCIES && comp->GetNumOutGroups(comp) == 1) {
@@ -89,7 +91,7 @@ static McxStatus SubModelGeneratorPrintNodeMap(SubModelGenerator * subModelGener
mcx_log(LOG_INFO, " %s (%s, -)", enu, comp->GetName(comp));
} else {
ChannelInfo * info = DatabusGetOutChannelInfo(comp->GetDatabus(comp), compAndGroup->group);
- mcx_log(LOG_INFO, " %s (%s, %s)", enu, comp->GetName(comp), info->GetName(info));
+ mcx_log(LOG_INFO, " %s (%s, %s)", enu, comp->GetName(comp), ChannelInfoGetName(info));
}
}
}
@@ -393,6 +395,27 @@ static int SubModelIsElement(SubModel * subModel, const Component * comp) {
return 0;
}
+static int SubModelContainsOrIsElement(SubModel * subModel, const Component * comp) {
+ ObjectContainer * comps = subModel->components;
+ size_t i = 0;
+
+ for (i = 0; i < comps->Size(comps); i++) {
+ Component * iComp = (Component *) comps->At(comps, i);
+ if (!iComp) {
+ mcx_log(LOG_DEBUG, "Model: nullptr in submodel at idx %zu", i);
+ continue;
+ }
+
+ if (comp == iComp) {
+ return TRUE;
+ } else if (iComp->ContainsComponent && iComp->ContainsComponent(iComp, comp)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
// only need to consider DECOUPLE_IFNEEDED since DECOUPLE_ALWAYS is handled at connection->Setup()
McxStatus OrderedNodesDecoupleConnections(OrderedNodes * orderedNodes, ObjectContainer * comps) {
size_t i; size_t k;
@@ -422,7 +445,7 @@ McxStatus OrderedNodesDecoupleConnections(OrderedNodes * orderedNodes, ObjectCon
for (ii = 0; ii < group->nodes.size && decouplePriority < INT_MAX; ii++) {
for (jj = 0; jj < group->nodes.size && decouplePriority < INT_MAX; jj++) {
int localDecouplePriority = -1;
- ObjectContainer * connections = NULL;
+ ObjectList * connections = NULL;
Component * fromComp = (Component *) comps->At(comps, group->nodes.values[ii]);
Component * toComp = (Component *) comps->At(comps, group->nodes.values[jj]);
@@ -445,18 +468,18 @@ McxStatus OrderedNodesDecoupleConnections(OrderedNodes * orderedNodes, ObjectCon
Connection * conn = (Connection *) connections->At(connections, k);
ConnectionInfo * info = conn->GetInfo(conn);
- if (info->IsDecoupled(info)) {
+ if (ConnectionInfoIsDecoupled(info)) {
continue;
}
if (fromComp->GetSequenceNumber(fromComp) > toComp->GetSequenceNumber(toComp)) {
localDecouplePriority = INT_MAX; // ordering by components takes priority
break;
- } else if (info->GetDecoupleType(info) == DECOUPLE_IFNEEDED) {
- if (info->GetDecouplePriority(info) > localDecouplePriority) {
- localDecouplePriority = info->GetDecouplePriority(info);
+ } else if (info->decoupleType == DECOUPLE_IFNEEDED) {
+ if (info->decouplePriority > localDecouplePriority) {
+ localDecouplePriority = info->decouplePriority;
}
- } else if (info->GetDecoupleType(info) == DECOUPLE_NEVER) {
+ } else if (info->decoupleType == DECOUPLE_NEVER) {
// if a connection in this bundle set to never decouple, discard this bundle
localDecouplePriority = -1;
break;
@@ -476,7 +499,7 @@ McxStatus OrderedNodesDecoupleConnections(OrderedNodes * orderedNodes, ObjectCon
// decouple connection with highest priority
if (decoupleFrom != SIZE_T_ERROR && decoupleTo != SIZE_T_ERROR) {
- ObjectContainer * connections = NULL;
+ ObjectList * connections = NULL;
Component * fromComp = (Component *) comps->At(comps, group->nodes.values[decoupleFrom]);
Component * toComp = (Component *) comps->At(comps, group->nodes.values[decoupleTo]);
@@ -501,11 +524,11 @@ McxStatus OrderedNodesDecoupleConnections(OrderedNodes * orderedNodes, ObjectCon
Connection * conn = (Connection *) connections->At(connections, k);
ConnectionInfo * info = conn->GetInfo(conn);
- char * connStr = info->ConnectionString(info);
+ char * connStr = ConnectionInfoConnectionString(info);
mcx_log(LOG_INFO, "Decoupling connection %s", connStr);
mcx_free(connStr);
- info->SetDecoupled(info);
+ ConnectionInfoSetDecoupled(info);
}
object_destroy(connections);
@@ -577,6 +600,7 @@ static SubModel * SubModelCreate(SubModel * subModel) {
subModel->LoopEvaluationList = SubModelLoopEvaluationList;
subModel->LoopComponents = SubModelLoopComponents;
subModel->IsElement = SubModelIsElement;
+ subModel->ContainsOrIsElement = SubModelContainsOrIsElement;
subModel->outConnections = (ObjectContainer *) object_create(ObjectContainer);
if (!subModel->outConnections) {
@@ -667,7 +691,7 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen
//check if connection exists (cosim init values are not deoupling connections, they only have lower priority than connection values)
ConnectionInfo * info = GetInConnectionInfo(targetComp, targetInChannelID);
if (NULL != info) {
- if (info->IsDecoupled(info)) {//decoupled connection
+ if (ConnectionInfoIsDecoupled(info)) {//decoupled connection
dependency = DEP_INDEPENDENT;
}
} else {//no connection
@@ -681,21 +705,21 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen
Connection * conn = GetInConnection(targetComp, targetInChannelID);
if (info
- && (info->GetDecoupleType(info) & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED))
- && (!info->IsDecoupled(info))
+ && (info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED))
+ && (!ConnectionInfoIsDecoupled(info))
&& conn
&& conn->IsActiveDependency(conn))
{
- Component * sourceComp = info->GetSourceComponent(info);
+ Component * sourceComp = info->sourceComponent;
size_t sourceOutGroup, sourceNode;
Databus * db = targetComp->GetDatabus(targetComp);
DatabusInfo * dbInfo = DatabusGetOutInfo(db);
size_t numOutChannels = DatabusInfoGetChannelNum(dbInfo);
if (INITIAL_DEPENDENCIES == depType) {
- sourceOutGroup = sourceComp->GetInitialOutGroup(sourceComp, info->GetSourceChannelID(info));
+ sourceOutGroup = sourceComp->GetInitialOutGroup(sourceComp, info->sourceChannel);
} else {
- sourceOutGroup = sourceComp->GetOutGroup(sourceComp, info->GetSourceChannelID(info));
+ sourceOutGroup = sourceComp->GetOutGroup(sourceComp, info->sourceChannel);
}
sourceNode = SubModelGeneratorGetNodeID(subModelGenerator, sourceComp, sourceOutGroup);
@@ -795,6 +819,39 @@ int OrderedNodesCheckIfLoopsExist(OrderedNodes * nodes) {
return FALSE;
}
+static size_t SubModelGetNumObservableChannels(const SubModel * subModel) {
+ size_t count = 0;
+ ObjectContainer * comps = subModel->components;
+ Component * comp = NULL;
+ size_t i = 0;
+
+ for (i = 0; i < comps->Size(comps); i++) {
+ comp = (Component *) comps->At(comps, i);
+ count += comp->GetNumObservableChannels(comp);
+ }
+
+ return count;
+}
+
+StringContainer * SubModelGetAllObservableChannelsContainer(SubModel * subModel) {
+ ObjectContainer * comps = subModel->components;
+ size_t numObservableChannels = SubModelGetNumObservableChannels(subModel);
+
+ StringContainer * container = StringContainerCreate(numObservableChannels);
+ size_t count = 0;
+ size_t i = 0, j = 0;
+
+ for (i = 0; i < comps->Size(comps); i++) {
+ Component * comp = (Component *) comps->At(comps, i);
+ // TODO: make composable
+ comp->AddObservableChannels(comp, container, &count);
+ }
+
+ StringContainerResize(container, count);
+
+ return container;
+}
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif /* __cplusplus */
\ No newline at end of file
diff --git a/src/core/SubModel.h b/src/core/SubModel.h
index 4ea4f66..1a962a1 100644
--- a/src/core/SubModel.h
+++ b/src/core/SubModel.h
@@ -19,6 +19,7 @@
extern "C" {
#endif /* __cplusplus */
+
typedef enum {
INITIAL_DEPENDENCIES,
RUNTIME_DEPENDENCIES
@@ -66,6 +67,7 @@ struct SubModel {
fSubModelLoopEvaluationList LoopEvaluationList;
fSubModelLoopComponents LoopComponents;
fSubModelIsElement IsElement;
+ fSubModelIsElement ContainsOrIsElement;
ObjectContainer * evaluationList; // contains CompAndGroup
ObjectContainer * components; // contains Component
@@ -74,6 +76,8 @@ struct SubModel {
};
+StringContainer * SubModelGetAllObservableChannelsContainer(SubModel * subModel);
+
extern const struct ObjectClass _SubModelGenerator;
struct SubModelGenerator {
diff --git a/src/core/Task.c b/src/core/Task.c
index b8d6bc0..33303dc 100644
--- a/src/core/Task.c
+++ b/src/core/Task.c
@@ -27,18 +27,25 @@ extern "C" {
static int TaskSubmodelIsFinished(SubModel * subModel) {
size_t i = 0;
-
ObjectContainer * eval = subModel->evaluationList;
+ size_t numComps = eval->Size(eval);
+ int modelContainsOnlyNeverFinishingComps = numComps ? TRUE : FALSE;
- for (i = 0; i < eval->Size(eval); i++) {
+ for (i = 0; i < numComps; i++) {
CompAndGroup * compAndGroup = (CompAndGroup *) eval->At(eval, i);
Component * comp = (Component *) compAndGroup->comp;
if (comp->GetFinishState(comp) == COMP_IS_NOT_FINISHED) {
return FALSE;
+ } else if (comp->GetFinishState(comp) != COMP_NEVER_FINISHES) {
+ modelContainsOnlyNeverFinishingComps = FALSE;
}
}
+ if (modelContainsOnlyNeverFinishingComps) {
+ return FALSE;
+ }
+
return TRUE;
}
@@ -112,7 +119,7 @@ static McxStatus TaskInitialize(Task * task, Model * model) {
return RETURN_ERROR;
}
- retVal = subModel->LoopComponents(subModel, CompPostDoUpdateState, (void *) task);
+ retVal = subModel->LoopComponents(subModel, CompPostDoUpdateState, (void *) stepParams);
if (RETURN_ERROR == retVal) {
mcx_log(LOG_ERROR, "Post update state of elements failed during initialization");
return RETURN_ERROR;
@@ -274,7 +281,7 @@ static McxStatus TaskRead(Task * task, TaskInput * taskInput) {
}
task->rtFactorEnabled = taskInput->timingOutput.defined ? taskInput->timingOutput.value : FALSE;
- retVal = task->storage->Read(task->storage, taskInput->results, task->config);
+ retVal = task->storage->Read(task->storage, taskInput->results, task->config, IsStepTypeMultiThreading(task->stepTypeType));
return retVal;
}
diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c
index be8f9e7..6d656d8 100644
--- a/src/core/channels/Channel.c
+++ b/src/core/channels/Channel.c
@@ -24,63 +24,42 @@ extern "C" {
// ----------------------------------------------------------------------
// Channel
-static ChannelData * ChannelDataCreate(ChannelData * data) {
- /* create dummy info*/
- data->info = (ChannelInfo *) object_create(ChannelInfo);
- if (!data->info) {
- return NULL;
- }
-
- data->isDefinedDuringInit = FALSE;
- data->internalValue = NULL;
- ChannelValueInit(&data->value, CHANNEL_UNKNOWN);
-
- return data;
-}
-
-static void ChannelDataDestructor(ChannelData * data) {
- // Note: This is done in Databus
- // object_destroy(data->info);
-
- ChannelValueDestructor(&data->value);
-}
-
-OBJECT_CLASS(ChannelData, Object);
-
static int ChannelIsDefinedDuringInit(Channel * channel) {
- return channel->data->isDefinedDuringInit;
+ return channel->isDefinedDuringInit;
}
static void ChannelSetDefinedDuringInit(Channel * channel) {
- channel->data->isDefinedDuringInit = TRUE;
-}
-
-static ChannelInfo * ChannelGetInfo(Channel * channel) {
- return channel->data->info;
+ channel->isDefinedDuringInit = TRUE;
}
static McxStatus ChannelSetup(Channel * channel, ChannelInfo * info) {
- if (channel->data->info) {
- object_destroy(channel->data->info);
- }
- channel->data->info = info;
+ McxStatus retVal = RETURN_OK;
+
info->channel = channel;
+ retVal = ChannelInfoSetFrom(&channel->info, info);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
return RETURN_OK;
}
static void ChannelDestructor(Channel * channel) {
- object_destroy(channel->data);
+ ChannelInfoDestroy(&channel->info);
+ ChannelValueDestructor(&channel->value);
}
static Channel * ChannelCreate(Channel * channel) {
- channel->data = (ChannelData *) object_create(ChannelData);
- if (!channel->data) {
+ if (RETURN_ERROR == ChannelInfoInit(&channel->info)) {
return NULL;
}
- channel->GetInfo = ChannelGetInfo;
+ channel->isDefinedDuringInit = FALSE;
+ channel->internalValue = NULL;
+ ChannelValueInit(&channel->value, CHANNEL_UNKNOWN);
+
channel->Setup = ChannelSetup;
channel->IsDefinedDuringInit = ChannelIsDefinedDuringInit;
channel->SetDefinedDuringInit = ChannelSetDefinedDuringInit;
@@ -138,27 +117,27 @@ OBJECT_CLASS(ChannelInData, Object);
static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, ChannelType type) {
Channel * ch = (Channel *) in;
- ChannelInfo * info = ch->GetInfo(ch);
+ ChannelInfo * info = &ch->info;
if (!in) {
mcx_log(LOG_ERROR, "Port: Set inport reference: Invalid port");
return RETURN_ERROR;
}
if (in->data->reference) {
- mcx_log(LOG_ERROR, "Port %s: Set inport reference: Reference already set", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set inport reference: Reference already set", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
if (CHANNEL_UNKNOWN != type) {
if (!info) {
- mcx_log(LOG_ERROR, "Port %s: Set inport reference: Port not set up", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set inport reference: Port not set up", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
- if (info->GetType(info) != type) {
- if (info->IsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
+ if (info->type != type) {
+ if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
// ok
} else {
- mcx_log(LOG_ERROR, "Port %s: Set inport reference: Mismatching types", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set inport reference: Mismatching types", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
@@ -175,22 +154,22 @@ static const void * ChannelInGetValueReference(Channel * channel) {
const static int maxCountError = 10;
static int i = 0;
if (i < maxCountError) {
- ChannelInfo * info = channel->GetInfo(channel);
+ ChannelInfo * info = &channel->info;
i++;
- mcx_log(LOG_ERROR, "Port %s: Get value reference: No value reference for inport", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Get value reference: No value reference for inport", ChannelInfoGetLogName(info));
if (i == maxCountError) {
- mcx_log(LOG_ERROR, "Port %s: Get value reference: No value reference for inport - truncated", info->GetLogName(info)) ;
+ mcx_log(LOG_ERROR, "Port %s: Get value reference: No value reference for inport - truncated", ChannelInfoGetLogName(info)) ;
}
}
return NULL;
}
- return ChannelValueReference(&channel->data->value);
+ return ChannelValueReference(&channel->value);
}
static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) {
ChannelIn * in = (ChannelIn *) channel;
- ChannelInfo * info = channel->GetInfo(channel);
+ ChannelInfo * info = &channel->info;
Connection * conn = in->data->connection;
McxStatus retVal = RETURN_OK;
@@ -198,12 +177,12 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) {
/* if no connection is present we have nothing to update*/
if (conn) {
ConnectionInfo * connInfo = NULL;
- ChannelValue * val = &channel->data->value;
+ ChannelValue * val = &channel->value;
- connInfo = conn->GetInfo(conn);
+ connInfo = &conn->info;
ChannelValueDestructor(val);
- ChannelValueInit(val, connInfo->GetType(connInfo));
+ ChannelValueInit(val, ConnectionInfoGetType(connInfo));
/* Update the connection for the current time */
conn->UpdateToOutput(conn, time);
@@ -214,47 +193,46 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) {
Conversion * conversion = (Conversion *) in->data->typeConversion;
retVal = conversion->convert(conversion, val);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute type conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute type conversion", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
- }
- if (info->GetType(info) == CHANNEL_DOUBLE) {
- ChannelValue * val = &channel->data->value;
- // unit
- if (in->data->unitConversion) {
- Conversion * conversion = (Conversion *) in->data->unitConversion;
- retVal = conversion->convert(conversion, val);
- if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute unit conversion", info->GetLogName(info));
- return RETURN_ERROR;
+ if (info->type == CHANNEL_DOUBLE) {
+ ChannelValue * val = &channel->value;
+ // unit
+ if (in->data->unitConversion) {
+ Conversion * conversion = (Conversion *) in->data->unitConversion;
+ retVal = conversion->convert(conversion, val);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute unit conversion", ChannelInfoGetLogName(info));
+ return RETURN_ERROR;
+ }
}
}
- }
- if (info->GetType(info) == CHANNEL_DOUBLE ||
- info->GetType(info) == CHANNEL_INTEGER) {
- ChannelValue * val = &channel->data->value;
+ if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) {
+ ChannelValue * val = &channel->value;
- // linear
- if (in->data->linearConversion) {
- Conversion * conversion = (Conversion *) in->data->linearConversion;
- retVal = conversion->convert(conversion, val);
- if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute linear conversion", info->GetLogName(info));
- return RETURN_ERROR;
+ // linear
+ if (in->data->linearConversion) {
+ Conversion * conversion = (Conversion *) in->data->linearConversion;
+ retVal = conversion->convert(conversion, val);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute linear conversion", ChannelInfoGetLogName(info));
+ return RETURN_ERROR;
+ }
}
- }
- // range
- if (in->data->rangeConversion) {
- Conversion * conversion = (Conversion *) in->data->rangeConversion;
- retVal = conversion->convert(conversion, val);
- if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute range conversion", info->GetLogName(info));
- return RETURN_ERROR;
+ // range
+ if (in->data->rangeConversion) {
+ Conversion * conversion = (Conversion *) in->data->rangeConversion;
+ retVal = conversion->convert(conversion, val);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute range conversion", ChannelInfoGetLogName(info));
+ return RETURN_ERROR;
+ }
}
}
}
@@ -265,11 +243,11 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) {
}
- switch (info->GetType(info)) {
+ switch (info->type) {
case CHANNEL_DOUBLE:
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, info->GetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel));
+ MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel));
}
#endif // MCX_DEBUG
* (double *) in->data->reference = * (double *) channel->GetValueReference(channel);
@@ -333,7 +311,7 @@ static int ChannelInIsValid(Channel * channel) {
if (channel->IsConnected(channel)) {
return TRUE;
} else {
- ChannelInfo * info = channel->GetInfo(channel);
+ ChannelInfo * info = &channel->info;
if (info && NULL != info->defaultValue) {
return TRUE;
}
@@ -350,7 +328,7 @@ static int ChannelInIsDiscrete(ChannelIn * in) {
}
static int ChannelInIsConnected(Channel * channel) {
- if (channel->data->info && channel->data->info->connected) {
+ if (channel->info.type != CHANNEL_UNKNOWN && channel->info.connected) {
return TRUE;
} else {
ChannelIn * in = (ChannelIn *) channel;
@@ -364,7 +342,7 @@ static int ChannelInIsConnected(Channel * channel) {
static ConnectionInfo * ChannelInGetConnectionInfo(ChannelIn * in) {
if (in->data->connection) {
- return in->data->connection->GetInfo(in->data->connection);
+ return &in->data->connection->info;
} else {
return NULL;
}
@@ -386,18 +364,18 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection,
McxStatus retVal;
in->data->connection = connection;
- channel->data->internalValue = connection->GetValueReference(connection);
+ channel->internalValue = connection->GetValueReference(connection);
// setup unit conversion
- inInfo = channel->GetInfo(channel);
+ inInfo = &channel->info;
- if (inInfo->GetType(inInfo) == CHANNEL_DOUBLE) {
+ if (inInfo->type == CHANNEL_DOUBLE) {
in->data->unitConversion = (UnitConversion *) object_create(UnitConversion);
retVal = in->data->unitConversion->Setup(in->data->unitConversion,
unit,
- inInfo->GetUnit(inInfo));
+ inInfo->unitString);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Port %s: Set inport connection: Could not setup unit conversion", inInfo->GetLogName(inInfo));
+ mcx_log(LOG_ERROR, "Port %s: Set inport connection: Could not setup unit conversion", ChannelInfoGetLogName(inInfo));
return RETURN_ERROR;
}
@@ -407,13 +385,13 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection,
}
// setup type conversion
- if (inInfo->GetType(inInfo) != type) {
+ if (inInfo->type != type) {
in->data->typeConversion = (TypeConversion *) object_create(TypeConversion);
retVal = in->data->typeConversion->Setup(in->data->typeConversion,
type,
- inInfo->GetType(inInfo));
+ inInfo->type);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Port %s: Set connection: Could not setup type conversion", inInfo->GetLogName(inInfo));
+ mcx_log(LOG_ERROR, "Port %s: Set connection: Could not setup type conversion", ChannelInfoGetLogName(inInfo));
return RETURN_ERROR;
}
}
@@ -430,34 +408,45 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) {
// types
if (info->type == CHANNEL_UNKNOWN) {
- mcx_log(LOG_ERROR, "Port %s: Setup inport: Unknown type", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Setup inport: Unknown type", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
- ChannelValueInit(&channel->data->value, info->type);
+ ChannelValueInit(&channel->value, info->type);
// default value
if (info->defaultValue) {
- ChannelValueSet(&channel->data->value, info->defaultValue);
+ ChannelValueSet(&channel->value, info->defaultValue);
+
+ // apply range and linear conversions immediately
+ retVal = ConvertRange(info->min, info->max, &channel->value);
+ if (retVal == RETURN_ERROR) {
+ return RETURN_ERROR;
+ }
+
+ retVal = ConvertLinear(info->scale, info->offset, &channel->value);
+ if (retVal == RETURN_ERROR) {
+ return RETURN_ERROR;
+ }
+
channel->SetDefinedDuringInit(channel);
- channel->data->internalValue = ChannelValueReference(&channel->data->value);
+ channel->internalValue = ChannelValueReference(&channel->value);
}
// unit conversion is setup when a connection is set
// min/max conversions are only used for double types
- if (info->GetType(info) == CHANNEL_DOUBLE
- || info->GetType(info) == CHANNEL_INTEGER)
+ if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER)
{
- ChannelValue * min = info->GetMin(info);
- ChannelValue * max = info->GetMax(info);
+ ChannelValue * min = info->min;
+ ChannelValue * max = info->max;
- ChannelValue * scale = info->GetScale(info);
- ChannelValue * offset = info->GetOffset(info);
+ ChannelValue * scale = info->scale;
+ ChannelValue * offset = info->offset;
in->data->rangeConversion = (RangeConversion *) object_create(RangeConversion);
retVal = in->data->rangeConversion->Setup(in->data->rangeConversion, min, max);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Port %s: Setup inport: Could not setup range conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Setup inport: Could not setup range conversion", ChannelInfoGetLogName(info));
object_destroy(in->data->rangeConversion);
return RETURN_ERROR;
} else {
@@ -469,7 +458,7 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) {
in->data->linearConversion = (LinearConversion *) object_create(LinearConversion);
retVal = in->data->linearConversion->Setup(in->data->linearConversion, scale, offset);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Port %s: Setup inport: Could not setup linear conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Setup inport: Could not setup linear conversion", ChannelInfoGetLogName(info));
object_destroy(in->data->linearConversion);
return RETURN_ERROR;
} else {
@@ -525,7 +514,7 @@ static ChannelOutData * ChannelOutDataCreate(ChannelOutData * data) {
data->rangeConversionIsActive = TRUE;
- data->connections = (ObjectContainer *) object_create(ObjectContainer);
+ data->connections = (ObjectList *) object_create(ObjectList);
data->nanCheck = NAN_CHECK_ALWAYS;
@@ -537,7 +526,7 @@ static ChannelOutData * ChannelOutDataCreate(ChannelOutData * data) {
}
static void ChannelOutDataDestructor(ChannelOutData * data) {
- ObjectContainer * conns = data->connections;
+ ObjectList * conns = data->connections;
size_t i = 0;
if (data->rangeConversion) {
@@ -560,11 +549,11 @@ OBJECT_CLASS(ChannelOutData, Object);
static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * config) {
Channel * channel = (Channel *) out;
- ChannelValue * min = info->GetMin(info);
- ChannelValue * max = info->GetMax(info);
+ ChannelValue * min = info->min;
+ ChannelValue * max = info->max;
- ChannelValue * scale = info->GetScale(info);
- ChannelValue * offset = info->GetOffset(info);
+ ChannelValue * scale = info->scale;
+ ChannelValue * offset = info->offset;
McxStatus retVal;
@@ -572,25 +561,24 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config *
// default value
if (info->type == CHANNEL_UNKNOWN) {
- mcx_log(LOG_ERROR, "Port %s: Setup outport: Unknown type", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Setup outport: Unknown type", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
- ChannelValueInit(&channel->data->value, info->type);
+ ChannelValueInit(&channel->value, info->type);
// default value
if (info->defaultValue) {
- channel->data->internalValue = ChannelValueReference(info->defaultValue);
+ channel->internalValue = ChannelValueReference(channel->info.defaultValue);
}
// min/max conversions are only used for double types
- if (info->GetType(info) == CHANNEL_DOUBLE
- || info->GetType(info) == CHANNEL_INTEGER)
+ if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER)
{
out->data->rangeConversion = (RangeConversion *) object_create(RangeConversion);
retVal = out->data->rangeConversion->Setup(out->data->rangeConversion, min, max);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Port %s: Setup outport: Could not setup range conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Setup outport: Could not setup range conversion", ChannelInfoGetLogName(info));
object_destroy(out->data->rangeConversion);
return RETURN_ERROR;
} else {
@@ -602,7 +590,7 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config *
out->data->linearConversion = (LinearConversion *) object_create(LinearConversion);
retVal = out->data->linearConversion->Setup(out->data->linearConversion, scale, offset);
if (RETURN_ERROR == retVal) {
- mcx_log(LOG_ERROR, "Port %s: Setup outport: Could not setup linear conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Setup outport: Could not setup linear conversion", ChannelInfoGetLogName(info));
object_destroy(out->data->linearConversion);
return RETURN_ERROR;
} else {
@@ -613,7 +601,7 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config *
}
if (!config) {
- mcx_log(LOG_DEBUG, "Port %s: Setup outport: No config available", info->GetLogName(info));
+ mcx_log(LOG_DEBUG, "Port %s: Setup outport: No config available", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
@@ -624,38 +612,38 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config *
}
static McxStatus ChannelOutRegisterConnection(ChannelOut * out, Connection * connection) {
- ObjectContainer * conns = out->data->connections;
+ ObjectList * conns = out->data->connections;
return conns->PushBack(conns, (Object *) connection);
}
static const void * ChannelOutGetValueReference(Channel * channel) {
ChannelOut * out = (ChannelOut *) channel;
- ChannelInfo * info = channel->GetInfo(channel);
+ ChannelInfo * info = &channel->info;
// check if out is initialized
if (!channel->IsValid(channel)) {
- mcx_log(LOG_ERROR, "Port %s: Get value reference: No Value Reference", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Get value reference: No Value Reference", ChannelInfoGetLogName(info));
return NULL;
}
- return ChannelValueReference(&channel->data->value);
+ return ChannelValueReference(&channel->value);
}
static const proc * ChannelOutGetFunction(ChannelOut * out) {
return out->data->valueFunction;
}
-static ObjectContainer * ChannelOutGetConnections(ChannelOut * out) {
+static ObjectList * ChannelOutGetConnections(ChannelOut * out) {
return out->data->connections;
}
static int ChannelOutIsValid(Channel * channel) {
- return (NULL != channel->data->internalValue);
+ return (NULL != channel->internalValue);
}
static int ChannelOutIsConnected(Channel * channel) {
- if (channel->data->info->connected) {
+ if (channel->info.connected) {
return TRUE;
} else {
ChannelOut * out = (ChannelOut *) channel;
@@ -677,28 +665,28 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference
mcx_log(LOG_ERROR, "Port: Set outport reference: Invalid port");
return RETURN_ERROR;
}
- info = channel->GetInfo(channel);
+ info = &channel->info;
if (!info) {
- mcx_log(LOG_ERROR, "Port %s: Set outport reference: Port not set up", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set outport reference: Port not set up", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
- if (channel->data->internalValue
- && !(info->defaultValue && channel->data->internalValue == ChannelValueReference(info->defaultValue))) {
- mcx_log(LOG_ERROR, "Port %s: Set outport reference: Reference already set", info->GetLogName(info));
+ if (channel->internalValue
+ && !(info->defaultValue && channel->internalValue == ChannelValueReference(info->defaultValue))) {
+ mcx_log(LOG_ERROR, "Port %s: Set outport reference: Reference already set", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
if (CHANNEL_UNKNOWN != type) {
- if (info->GetType(info) != type) {
- if (info->IsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
+ if (info->type != type) {
+ if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) {
// ok
} else {
- mcx_log(LOG_ERROR, "Port %s: Set outport reference: Mismatching types", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set outport reference: Mismatching types", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
}
- channel->data->internalValue = reference;
+ channel->internalValue = reference;
return RETURN_OK;
}
@@ -711,16 +699,16 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r
return RETURN_ERROR;
}
- info = channel->GetInfo(channel);
+ info = &channel->info;
if (CHANNEL_UNKNOWN != type) {
if (info->type != type) {
- mcx_log(LOG_ERROR, "Port %s: Set outport function: Mismatching types", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set outport function: Mismatching types", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
if (out->data->valueFunction) {
- mcx_log(LOG_ERROR, "Port %s: Set outport function: Reference already set", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Set outport function: Reference already set", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
@@ -728,7 +716,7 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r
out->data->valueFunction = (const proc *) reference;
// Setup value reference to point to internal value
- channel->data->internalValue = ChannelValueReference(&channel->data->value);
+ channel->internalValue = ChannelValueReference(&channel->value);
return RETURN_OK;
}
@@ -737,7 +725,7 @@ static void WarnAboutNaN(LogSeverity level, ChannelInfo * info, TimeInterval * t
if (*max > 0) {
if (*count < *max) {
mcx_log(level, "Outport %s at time %f is not a number (NaN)",
- info->GetName(info), time->startTime);
+ ChannelInfoGetName(info), time->startTime);
*count += 1;
if (*count == *max) {
mcx_log(level, "This warning will not be shown anymore");
@@ -745,15 +733,15 @@ static void WarnAboutNaN(LogSeverity level, ChannelInfo * info, TimeInterval * t
}
} else {
mcx_log(level, "Outport %s at time %f is not a number (NaN)",
- info->GetName(info), time->startTime);
+ ChannelInfoGetName(info), time->startTime);
}
}
static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) {
ChannelOut * out = (ChannelOut *)channel;
- ChannelInfo * info = ((Channel *)out)->GetInfo((Channel *)out);
+ ChannelInfo * info = &channel->info;
- ObjectContainer * conns = out->data->connections;
+ ObjectList * conns = out->data->connections;
McxStatus retVal = RETURN_OK;
@@ -768,31 +756,30 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) {
double val = p->fn(time, p->env);
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, info->GetLogName(info), time->startTime, val);
+ MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, val);
}
#endif // MCX_DEBUG
- ChannelValueSetFromReference(&channel->data->value, &val);
+ ChannelValueSetFromReference(&channel->value, &val);
} else {
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- if (CHANNEL_DOUBLE == info->GetType(info)) {
+ if (CHANNEL_DOUBLE == info->type) {
MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)",
time->startTime,
- info->GetLogName(info),
+ ChannelInfoGetLogName(info),
time->startTime,
- * (double *) channel->data->internalValue);
+ * (double *) channel->internalValue);
} else {
- MCX_DEBUG_LOG("[%f] CH OUT (%s)", time->startTime, info->GetLogName(info));
+ MCX_DEBUG_LOG("[%f] CH OUT (%s)", time->startTime, ChannelInfoGetLogName(info));
}
}
#endif // MCX_DEBUG
- ChannelValueSetFromReference(&channel->data->value, channel->data->internalValue);
+ ChannelValueSetFromReference(&channel->value, channel->internalValue);
}
// Apply conversion
- if (info->GetType(info) == CHANNEL_DOUBLE ||
- info->GetType(info) == CHANNEL_INTEGER) {
- ChannelValue * val = &channel->data->value;
+ if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) {
+ ChannelValue * val = &channel->value;
// range
if (out->data->rangeConversion) {
@@ -800,7 +787,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) {
Conversion * conversion = (Conversion *) out->data->rangeConversion;
retVal = conversion->convert(conversion, val);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Port %s: Update outport: Could not execute range conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Update outport: Could not execute range conversion", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
@@ -811,14 +798,15 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) {
Conversion * conversion = (Conversion *) out->data->linearConversion;
retVal = conversion->convert(conversion, val);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Port %s: Update outport: Could not execute linear conversion", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Update outport: Could not execute linear conversion", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
}
// Notify connections of new values
- for (j = 0; j < conns->Size(conns); j++) {
+ size_t connSize = conns->Size(conns);
+ for (j = 0; j < connSize; j++) {
Connection * connection = (Connection *) conns->At(conns, j);
channel->SetDefinedDuringInit(channel);
connection->UpdateFromInput(connection, time);
@@ -826,11 +814,11 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) {
}
- if (CHANNEL_DOUBLE == info->GetType(info)) {
+ if (CHANNEL_DOUBLE == info->type) {
const double * val = NULL;
{
- val = &channel->data->value.value.d;
+ val = &channel->value.value.d;
}
if (isnan(*val))
@@ -839,13 +827,13 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) {
case NAN_CHECK_ALWAYS:
mcx_log(LOG_ERROR, "Outport %s at time %f is not a number (NaN)",
- info->GetName(info), time->startTime);
+ ChannelInfoGetName(info), time->startTime);
return RETURN_ERROR;
case NAN_CHECK_CONNECTED:
if (conns->Size(conns) > 0) {
mcx_log(LOG_ERROR, "Outport %s at time %f is not a number (NaN)",
- info->GetName(info), time->startTime);
+ ChannelInfoGetName(info), time->startTime);
return RETURN_ERROR;
} else {
WarnAboutNaN(LOG_WARNING, info, time, &out->data->countNaNCheckWarning, &out->data->maxNumNaNCheckWarning);
@@ -913,7 +901,7 @@ static McxStatus ChannelLocalSetup(ChannelLocal * local, ChannelInfo * info) {
}
static const void * ChannelLocalGetValueReference(Channel * channel) {
- return channel->data->internalValue;
+ return channel->internalValue;
}
static McxStatus ChannelLocalUpdate(Channel * channel, TimeInterval * time) {
@@ -921,7 +909,7 @@ static McxStatus ChannelLocalUpdate(Channel * channel, TimeInterval * time) {
}
static int ChannelLocalIsValid(Channel * channel) {
- return (channel->data->internalValue != NULL);
+ return (channel->internalValue != NULL);
}
// TODO: Unify with ChannelOutsetReference (similar code)
@@ -931,24 +919,24 @@ static McxStatus ChannelLocalSetReference(ChannelLocal * local,
Channel * channel = (Channel *) local;
ChannelInfo * info = NULL;
- info = channel->GetInfo(channel);
+ info = &channel->info;
if (!info) {
mcx_log(LOG_ERROR, "Port: Set local value reference: Port not set up");
return RETURN_ERROR;
}
- if (channel->data->internalValue
- && !(info->defaultValue && channel->data->internalValue == ChannelValueReference(info->defaultValue))) {
- mcx_log(LOG_ERROR, "Port %s: Set local value reference: Reference already set", info->GetLogName(info));
+ if (channel->internalValue
+ && !(info->defaultValue && channel->internalValue == ChannelValueReference(info->defaultValue))) {
+ mcx_log(LOG_ERROR, "Port %s: Set local value reference: Reference already set", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
if (CHANNEL_UNKNOWN != type) {
- if (info->GetType(info) != type) {
- mcx_log(LOG_ERROR, "Port %s: Set local value reference: Mismatching types", info->GetLogName(info));
+ if (info->type != type) {
+ mcx_log(LOG_ERROR, "Port %s: Set local value reference: Mismatching types", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
- channel->data->internalValue = reference;
+ channel->internalValue = reference;
return RETURN_OK;
}
diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h
index 2b394f8..9847dc1 100644
--- a/src/core/channels/Channel.h
+++ b/src/core/channels/Channel.h
@@ -12,6 +12,7 @@
#define MCX_CORE_CHANNELS_CHANNEL_H
#include "CentralParts.h"
+#include "core/channels/ChannelInfo.h"
#ifdef __cplusplus
extern "C" {
@@ -19,9 +20,7 @@ extern "C" {
struct Config;
struct Component;
-struct ChannelInfo;
-struct ChannelData;
struct ChannelInData;
struct ChannelOutData;
struct Connection;
@@ -42,8 +41,6 @@ typedef int (* fChannelIsDefinedDuringInit)(Channel * channel);
typedef void (* fChannelSetDefinedDuringInit)(Channel * channel);
-typedef struct ChannelInfo * (* fChannelGetInfo)(Channel * channel);
-
typedef McxStatus (* fChannelSetup)(Channel * channel, struct ChannelInfo * info);
typedef McxStatus (* fChannelUpdate)(Channel * channel, TimeInterval * time);
@@ -53,6 +50,18 @@ extern const struct ObjectClass _Channel;
struct Channel {
Object _; // base class
+ ChannelInfo info;
+
+ // ----------------------------------------------------------------------
+ // Value
+
+ // NOTE: This flag gets set if there is a defined value for the
+ // channel during initialization.
+ int isDefinedDuringInit;
+
+ const void * internalValue;
+ ChannelValue value;
+
/**
* Virtual method.
*
@@ -68,11 +77,6 @@ struct Channel {
*/
fChannelUpdate Update;
- /**
- * Return info struct of channel.
- */
- fChannelGetInfo GetInfo;
-
/**
* Virtual method.
*
@@ -98,8 +102,6 @@ struct Channel {
* Initialize channel with info struct.
*/
fChannelSetup Setup;
-
- struct ChannelData * data;
};
// ----------------------------------------------------------------------
@@ -192,7 +194,7 @@ typedef McxStatus (* fChannelOutRegisterConnection)(struct ChannelOut * out,
typedef const proc * (* fChannelOutGetFunction)(ChannelOut * out);
-typedef ObjectContainer * (* fChannelOutGetConnections)(ChannelOut * out);
+typedef ObjectList * (* fChannelOutGetConnections)(ChannelOut * out);
extern const struct ObjectClass _ChannelOut;
diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c
index 95e5631..41e4baf 100644
--- a/src/core/channels/ChannelInfo.c
+++ b/src/core/channels/ChannelInfo.c
@@ -18,10 +18,8 @@
extern "C" {
#endif /* __cplusplus */
-// ----------------------------------------------------------------------
-// ChannelInfo
-static const char * ChannelInfoGetLogName(const ChannelInfo * info) {
+const char * ChannelInfoGetLogName(const ChannelInfo * info) {
if (info->id) {
return info->id;
} else {
@@ -29,15 +27,7 @@ static const char * ChannelInfoGetLogName(const ChannelInfo * info) {
}
}
-static ChannelType ChannelInfoType(const ChannelInfo * info) {
- return info->type;
-}
-
-static ChannelMode ChannelInfoMode(const ChannelInfo * info) {
- return info->mode;
-}
-
-static const char * ChannelInfoName(const ChannelInfo * info) {
+const char * ChannelInfoGetName(const ChannelInfo * info) {
if (info->name) {
return info->name;
} else {
@@ -45,57 +35,11 @@ static const char * ChannelInfoName(const ChannelInfo * info) {
}
}
-static const char * ChannelInfoNameInTool(const ChannelInfo * info) {
- return info->nameInTool;
-}
-
-static const char * ChannelInfoDescription(const ChannelInfo * info) {
- return info->description;
-}
-
-static const char * ChannelInfoID(const ChannelInfo * info) {
- return info->id;
-}
-
-static const char * ChannelInfoUnit(const ChannelInfo * info) {
- return info->unitString;
-}
-
-static ChannelValue * ChannelGetMin(const ChannelInfo * info) {
- return info->min;
-}
-
-static ChannelValue * ChannelGetMax(const ChannelInfo * info) {
- return info->max;
-}
-
-static ChannelValue * ChannelInfoGetInitialValue(const ChannelInfo * info) {
- return info->initialValue;
+int ChannelInfoIsBinary(const ChannelInfo * info) {
+ return info->type == CHANNEL_BINARY || info->type == CHANNEL_BINARY_REFERENCE;
}
-static ChannelValue * ChannelInfoScale(const ChannelInfo * info) {
- return info->scale;
-}
-
-static ChannelValue * ChannelInfoOffset(const ChannelInfo * info) {
- return info->offset;
-}
-
-static ChannelValue * ChannelInfoDefault(const ChannelInfo * info) {
- return info->defaultValue;
-}
-
-static int ChannelInfoIsBinary(const ChannelInfo * info) {
- return info->type == CHANNEL_BINARY
- || info->type == CHANNEL_BINARY_REFERENCE;
-}
-
-static int ChannelInfoGetWriteResultFlag(const ChannelInfo * info) {
- return info->writeResult;
-}
-
-
-static McxStatus ChannelInfoSetString(char * * dst, const char * src) {
+static McxStatus ChannelInfoSetString(char ** dst, const char * src) {
if (*dst) {
mcx_free(*dst);
}
@@ -110,256 +54,197 @@ static McxStatus ChannelInfoSetString(char * * dst, const char * src) {
return RETURN_OK;
}
-static McxStatus ChannelInfoSetVector(ChannelInfo * info, VectorChannelInfo * vector) {
- if (info->vector) {
- object_destroy(info->vector);
- }
-
- info->vector = vector;
-
- return RETURN_OK;
-}
-
-static McxStatus ChannelInfoSetName(ChannelInfo * info, const char * name) {
+McxStatus ChannelInfoSetName(ChannelInfo * info, const char * name) {
return ChannelInfoSetString(&info->name, name);
}
-static McxStatus ChannelInfoSetNameInTool(ChannelInfo * info, const char * name) {
+McxStatus ChannelInfoSetNameInTool(ChannelInfo * info, const char * name) {
return ChannelInfoSetString(&info->nameInTool, name);
}
-static McxStatus ChannelInfoSetID(ChannelInfo * info, const char * name) {
+McxStatus ChannelInfoSetID(ChannelInfo * info, const char * name) {
return ChannelInfoSetString(&info->id, name);
}
-static McxStatus ChannelInfoSetDescription(ChannelInfo * info, const char * name) {
+McxStatus ChannelInfoSetDescription(ChannelInfo * info, const char * name) {
return ChannelInfoSetString(&info->description, name);
}
-static McxStatus ChannelInfoSetUnit(ChannelInfo * info, const char * name) {
+McxStatus ChannelInfoSetUnit(ChannelInfo * info, const char * name) {
return ChannelInfoSetString(&info->unitString, name);
}
-static McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType type) {
+McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType type) {
if (info->type != CHANNEL_UNKNOWN) {
- mcx_log(LOG_ERROR, "Port %s: Type already set", info->GetLogName(info));
+ mcx_log(LOG_ERROR, "Port %s: Type already set", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
info->type = type;
- if (info->IsBinary(info)) {
+ if (ChannelInfoIsBinary(info)) {
// the default for binary is off
- info->SetWriteResult(info, FALSE);
+ info->writeResult = FALSE;
}
return RETURN_OK;
}
-static McxStatus ChannelInfoSetMode(ChannelInfo * info, ChannelMode mode) {
- info->mode = mode;
-
- return RETURN_OK;
-}
-
-static McxStatus ChannelInfoSetMin(ChannelInfo * info, ChannelValue * min) {
- info->min = min;
- return RETURN_OK;
-}
-
-static McxStatus ChannelInfoSetMax(ChannelInfo * info, ChannelValue * max) {
- info->max = max;
- return RETURN_OK;
-}
-
-static McxStatus ChannelInfoSetScale(ChannelInfo * info, ChannelValue * scale) {
- info->scale = scale;
- return RETURN_OK;
-}
+McxStatus ChannelInfoSetVector(ChannelInfo * info, VectorChannelInfo * vector) {
+ if (info->vector) {
+ object_destroy(info->vector);
+ }
-static McxStatus ChannelInfoSetOffset(ChannelInfo * info, ChannelValue * offset) {
- info->offset = offset;
- return RETURN_OK;
-}
+ info->vector = vector;
-static McxStatus ChannelInfoSetDefault(ChannelInfo * info, ChannelValue * defaultValue) {
- info->defaultValue = defaultValue;
return RETURN_OK;
}
-static McxStatus ChannelInfoSetInitial(ChannelInfo * info, ChannelValue * initialValue) {
- info->initialValue = initialValue;
- return RETURN_OK;
-}
+McxStatus ChannelInfoSetup(ChannelInfo * info,
+ const char * name,
+ const char * descr,
+ const char * unit,
+ ChannelType type,
+ const char * id) {
+ if (name && RETURN_OK != ChannelInfoSetName(info, name)) {
+ mcx_log(LOG_DEBUG, "Port %s: Could not set name", name);
+ return RETURN_ERROR;
+ }
+ if (descr && RETURN_OK != ChannelInfoSetDescription(info, descr)) {
+ mcx_log(LOG_DEBUG, "Port %s: Could not set description", name);
+ return RETURN_ERROR;
+ }
+ if (unit && RETURN_OK != ChannelInfoSetUnit(info, unit)) {
+ mcx_log(LOG_DEBUG, "Port %s: Could not set unit", name);
+ return RETURN_ERROR;
+ }
+ if (id && RETURN_OK != ChannelInfoSetID(info, id)) {
+ mcx_log(LOG_DEBUG, "Port %s: Could not set ID", name);
+ return RETURN_ERROR;
+ }
+ if (RETURN_OK != ChannelInfoSetType(info, type)) {
+ mcx_log(LOG_DEBUG, "Port %s: Could not set type", name);
+ return RETURN_ERROR;
+ }
-static McxStatus ChannelInfoSetWriteResult(ChannelInfo * info, int writeResult) {
- info->writeResult = writeResult;
return RETURN_OK;
}
-
-static void ChannelInfoSet(
- ChannelInfo * info,
- VectorChannelInfo * vector,
- char * name,
- char * nameInTool,
- char * description,
- char * unit,
- ChannelType type,
- ChannelMode mode,
- char * id,
- ChannelValue * min,
- ChannelValue * max,
- ChannelValue * scale,
- ChannelValue * offset,
- ChannelValue * defaultValue,
- ChannelValue * initialValue,
- int writeResult)
-{
- info->vector = vector;
- info->name = name;
- info->nameInTool = nameInTool;
- info->description = description;
- info->unitString = unit;
- info->type = type;
- info->mode = mode;
- info->id = id;
- info->min = min;
- info->max = max;
- info->scale = scale;
- info->offset = offset;
- info->defaultValue = defaultValue;
- info->initialValue = initialValue;
- info->writeResult = writeResult;
-}
-
-static void ChannelInfoGet(
- const ChannelInfo * info,
- VectorChannelInfo ** vector,
- char ** name,
- char ** nameInTool,
- char ** description,
- char ** unit,
- ChannelType * type,
- ChannelMode * mode,
- char ** id,
- ChannelValue ** min,
- ChannelValue ** max,
- ChannelValue ** scale,
- ChannelValue ** offset,
- ChannelValue ** defaultValue,
- ChannelValue ** initialValue,
- int * writeResult)
-{
- * vector = info->vector;
- * name = info->name;
- * nameInTool = info->nameInTool;
- * description = info->description;
- * unit = info->unitString;
- * type = info->type;
- * mode = info->mode;
- * id = info->id;
- * min = info->min;
- * max = info->max;
- * scale = info->scale;
- * offset = info->offset;
- * defaultValue = info->defaultValue;
- * initialValue = info->initialValue;
- * writeResult = info->writeResult;
+static void FreeChannelValue(ChannelValue ** value) {
+ if (*value) {
+ ChannelValueDestructor(*value);
+ mcx_free(*value);
+ *value = NULL;
+ }
}
-static ChannelInfo * ChannelInfoClone(const ChannelInfo * info) {
- ChannelInfo * clone = (ChannelInfo *) object_create(ChannelInfo);
+McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other) {
+ McxStatus retVal = RETURN_OK;
- if (!clone) {
- return NULL;
+ retVal = ChannelInfoSetName(info, other->name);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set name");
+ return RETURN_ERROR;
}
- if (info->name && !(clone->name = mcx_string_copy(info->name))) { return NULL; }
- if (info->nameInTool && !(clone->nameInTool = mcx_string_copy(info->nameInTool))) { return NULL; }
- if (info->description && !(clone->description = mcx_string_copy(info->description))) { return NULL; }
- if (info->unitString && !(clone->unitString = mcx_string_copy(info->unitString))) { return NULL; }
- if (info->id && !(clone->id = mcx_string_copy(info->id))) { return NULL; }
-
- clone->type = info->type;
- clone->mode = info->mode;
-
- if (info->min) {
- if (!(clone->min = ChannelValueClone(info->min))) { return NULL; }
- }
- if (info->max) {
- if (!(clone->max = ChannelValueClone(info->max))) { return NULL; }
- }
- if (info->scale) {
- if (!(clone->scale = ChannelValueClone(info->scale))) { return NULL; }
- }
- if (info->offset) {
- if (!(clone->offset = ChannelValueClone(info->offset))) { return NULL; }
- }
- if (info->defaultValue) {
- if (!(clone->defaultValue = ChannelValueClone(info->defaultValue))) { return NULL; }
- }
- if (info->initialValue) {
- if (!(clone->initialValue = ChannelValueClone(info->initialValue))) { return NULL; }
+ retVal = ChannelInfoSetNameInTool(info, other->nameInTool);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set name in model");
+ return RETURN_ERROR;
}
- clone->writeResult = info->writeResult;
-
- return clone;
-}
-
-static ChannelInfo * ChannelInfoCopy(
- const ChannelInfo * info,
- char * name,
- char * nameInTool,
- char * id) {
-
- ChannelInfo * copy = info->Clone(info);
+ retVal = ChannelInfoSetDescription(info, other->description);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set description");
+ return RETURN_ERROR;
+ }
- if (!copy) {
- return NULL;
+ retVal = ChannelInfoSetUnit(info, other->unitString);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set unit");
+ return RETURN_ERROR;
}
- copy->SetName(copy, name);
- copy->SetNameInTool(copy, nameInTool);
- copy->SetID(copy, id);
+ retVal = ChannelInfoSetID(info, other->id);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set name");
+ return RETURN_ERROR;
+ }
- return copy;
-}
+ info->type = other->type;
+ info->mode = other->mode;
+ info->writeResult = other->writeResult;
+ info->connected = other->connected;
+ info->initialValueIsExact = other->initialValueIsExact;
+
+ info->channel = other->channel; // weak reference
+
+ FreeChannelValue(&info->min);
+ FreeChannelValue(&info->max);
+ FreeChannelValue(&info->scale);
+ FreeChannelValue(&info->offset);
+ FreeChannelValue(&info->defaultValue);
+ FreeChannelValue(&info->initialValue);
+
+ if (other->min) {
+ info->min = ChannelValueClone(other->min);
+ if (!info->min) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set min");
+ return RETURN_ERROR;
+ }
+ }
-static McxStatus ChannelInfoInit(ChannelInfo * info,
- const char * name,
- const char * descr,
- const char * unit,
- ChannelType type,
- const char * id) {
+ if (other->max) {
+ info->max = ChannelValueClone(other->max);
+ if (!info->max) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set max");
+ return RETURN_ERROR;
+ }
+ }
+ if (other->scale) {
+ info->scale = ChannelValueClone(other->scale);
+ if (!info->scale) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set scale");
+ return RETURN_ERROR;
+ }
+ }
- if (name && RETURN_OK != info->SetName(info, name)) {
- mcx_log(LOG_DEBUG, "Port %s: Could not set name", name);
- return RETURN_ERROR;
+ if (other->offset) {
+ info->offset = ChannelValueClone(other->offset);
+ if (!info->offset) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set offset");
+ return RETURN_ERROR;
+ }
}
- if (descr && RETURN_OK != info->SetDescription(info, descr)) {
- mcx_log(LOG_DEBUG, "Port %s: Could not set description", name);
- return RETURN_ERROR;
+
+ if (other->defaultValue) {
+ info->defaultValue = ChannelValueClone(other->defaultValue);
+ if (!info->defaultValue) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set default value");
+ return RETURN_ERROR;
+ }
}
- if (unit && RETURN_OK != info->SetUnit(info, unit)) {
- mcx_log(LOG_DEBUG, "Port %s: Could not set unit", name);
- return RETURN_ERROR;
+
+ if (other->initialValue) {
+ info->initialValue = ChannelValueClone(other->initialValue);
+ if (!info->initialValue) {
+ mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set initial value");
+ return RETURN_ERROR;
+ }
}
- if (id && RETURN_OK != info->SetID(info, id)) {
- mcx_log(LOG_DEBUG, "Port %s: Could not set ID", name);
- return RETURN_ERROR;
+
+ if (info->vector) {
+ object_destroy(info->vector);
}
- if (RETURN_OK != info->SetType(info, type)) {
- mcx_log(LOG_DEBUG, "Port %s: Could not set type", name);
- return RETURN_ERROR;
+
+ if (other->vector) {
+ info->vector = (VectorChannelInfo *) object_strong_reference(other->vector);
}
return RETURN_OK;
}
-
static void FreeStr(char ** str) {
if (*str) {
mcx_free(*str);
@@ -367,75 +252,32 @@ static void FreeStr(char ** str) {
}
}
-static void ChannelInfoDestructor(ChannelInfo * info) {
+void ChannelInfoDestroy(ChannelInfo * info) {
FreeStr(&info->name);
FreeStr(&info->nameInTool);
FreeStr(&info->description);
FreeStr(&info->unitString);
FreeStr(&info->id);
- if (info->defaultValue) {
- ChannelValueDestructor(info->defaultValue);
- mcx_free(info->defaultValue);
- info->defaultValue = NULL;
- }
- if (info->initialValue) {
- ChannelValueDestructor(info->initialValue);
- mcx_free(info->initialValue);
- info->initialValue = NULL;
- }
+ FreeChannelValue(&info->min);
+ FreeChannelValue(&info->max);
+ FreeChannelValue(&info->scale);
+ FreeChannelValue(&info->offset);
+ FreeChannelValue(&info->defaultValue);
+ FreeChannelValue(&info->initialValue);
+
if (info->vector) {
object_destroy(info->vector);
}
-}
-static ChannelInfo * ChannelInfoCreate(ChannelInfo * info) {
- info->Set = ChannelInfoSet;
- info->Get = ChannelInfoGet;
- info->Clone = ChannelInfoClone;
- info->Copy = ChannelInfoCopy;
-
- info->Init = ChannelInfoInit;
-
- info->SetVector = ChannelInfoSetVector;
- info->SetName = ChannelInfoSetName;
- info->SetNameInTool = ChannelInfoSetNameInTool;
- info->SetID = ChannelInfoSetID;
- info->SetDescription = ChannelInfoSetDescription;
- info->SetUnit = ChannelInfoSetUnit;
- info->SetType = ChannelInfoSetType;
- info->SetMode = ChannelInfoSetMode;
-
- info->SetMin = ChannelInfoSetMin;
- info->SetMax = ChannelInfoSetMax;
- info->SetScale = ChannelInfoSetScale;
- info->SetOffset = ChannelInfoSetOffset;
- info->SetDefault = ChannelInfoSetDefault;
- info->SetInitial = ChannelInfoSetInitial;
- info->SetWriteResult = ChannelInfoSetWriteResult;
-
- info->GetType = ChannelInfoType;
- info->GetMode = ChannelInfoMode;
- info->GetName = ChannelInfoName;
- info->GetNameInTool = ChannelInfoNameInTool;
- info->GetDescription = ChannelInfoDescription;
- info->GetID = ChannelInfoID;
- info->GetUnit = ChannelInfoUnit;
- info->GetMin = ChannelGetMin;
- info->GetMax = ChannelGetMax;
-
- info->GetInitialValue = ChannelInfoGetInitialValue;
-
- info->GetScale = ChannelInfoScale;
- info->GetOffset = ChannelInfoOffset;
- info->GetDefault = ChannelInfoDefault;
-
- info->IsBinary = ChannelInfoIsBinary;
-
- info->GetWriteResultFlag = ChannelInfoGetWriteResultFlag;
-
- info->GetLogName = ChannelInfoGetLogName;
+ info->channel = NULL;
+ info->initialValueIsExact = FALSE;
+ info->type = CHANNEL_UNKNOWN;
+ info->connected = FALSE;
+ info->writeResult = TRUE;
+}
+McxStatus ChannelInfoInit(ChannelInfo * info) {
info->vector = NULL;
info->name = NULL;
@@ -461,10 +303,9 @@ static ChannelInfo * ChannelInfoCreate(ChannelInfo * info) {
info->channel = NULL;
- return info;
+ return RETURN_OK;
}
-OBJECT_CLASS(ChannelInfo, Object);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/core/channels/ChannelInfo.h b/src/core/channels/ChannelInfo.h
index 1980034..9f8c0a0 100644
--- a/src/core/channels/ChannelInfo.h
+++ b/src/core/channels/ChannelInfo.h
@@ -11,174 +11,76 @@
#ifndef MCX_CORE_CHANNELS_CHANNELINFO_H
#define MCX_CORE_CHANNELS_CHANNELINFO_H
-#include "CentralParts.h"
+#include "core/channels/ChannelValue.h"
#include "core/channels/VectorChannelInfo.h"
+#include "common/status.h"
+
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-// ----------------------------------------------------------------------
-// ChannelInfo
-typedef struct ChannelInfo ChannelInfo;
-typedef struct VectorChannelInfo VectorChannelInfo;
-typedef struct Channel Channel;
-
-extern const struct ObjectClass _ChannelInfo;
-
-typedef void (* fChannelInfoSet)(
- ChannelInfo * info,
- struct VectorChannelInfo * vector,
- char * name,
- char * nameInTool,
- char * description,
- char * unit,
- ChannelType type,
- ChannelMode mode,
- char * id,
- ChannelValue * min,
- ChannelValue * max,
- ChannelValue * scale,
- ChannelValue * offset,
- ChannelValue * defaultValue,
- ChannelValue * initialValue,
- int writeResult);
-
-typedef void (* fChannelInfoGet)(
- const ChannelInfo * info,
- struct VectorChannelInfo ** vector,
- char ** name,
- char ** nameInTool,
- char ** description,
- char ** unit,
- ChannelType * type,
- ChannelMode * mode,
- char ** id,
- ChannelValue ** min,
- ChannelValue ** max,
- ChannelValue ** scale,
- ChannelValue ** offset,
- ChannelValue ** defaultValue,
- ChannelValue ** initialValue,
- int * writeResult);
-
-typedef ChannelInfo * (* fChannelInfoCopy)(
- const ChannelInfo * info,
- char * name,
- char * nameInTool,
- char * id);
-
-typedef McxStatus (* fChannelInfoInit)(
- ChannelInfo * info,
- const char * name,
- const char * descr,
- const char * unit,
- ChannelType type,
- const char * id);
-
-typedef ChannelInfo * (* fChannelInfoClone)(const ChannelInfo * info);
-
-typedef ChannelType (* fChannelInfoGetType)(const ChannelInfo * info);
-typedef ChannelMode (* fChannelInfoGetMode)(const ChannelInfo * info);
-
-typedef McxStatus (* fChannelInfoSetDouble)(ChannelInfo * info, double val);
-typedef McxStatus (* fChannelInfoSetInt)(ChannelInfo * info, int val);
-typedef McxStatus (* fChannelInfoSetBool)(ChannelInfo * info, int val);
-typedef McxStatus (* fChannelInfoSetChannelValue)(ChannelInfo * info, ChannelValue * val);
-typedef ChannelValue * (* fChannelInfoGetChannelValue)(const ChannelInfo * info);
-
-typedef const char * (* fChannelInfoGetString)(const ChannelInfo * info);
-typedef McxStatus (* fChannelInfoSetString)(ChannelInfo * info, const char * str);
-typedef McxStatus (* fChannelInfoSetChannelType)(ChannelInfo * info, ChannelType type);
-typedef McxStatus (* fChannelInfoSetChannelMode)(ChannelInfo * info, ChannelMode mode);
-typedef McxStatus (* fChannelInfoSetVector)(ChannelInfo * info, VectorChannelInfo * vector);
-
-typedef ChannelValue * (* fChannelInfoGetInitialValue)(const ChannelInfo * info);
-
-typedef int (* fChannelInfoGetInt)(const ChannelInfo * info);
-
-struct ChannelInfo {
- Object _; // base class
-
- fChannelInfoSet Set;
- fChannelInfoGet Get;
- fChannelInfoClone Clone;
- fChannelInfoCopy Copy;
-
- fChannelInfoInit Init;
-
- fChannelInfoSetVector SetVector;
- fChannelInfoSetString SetName;
- fChannelInfoSetString SetNameInTool;
- fChannelInfoSetString SetID;
- fChannelInfoSetString SetDescription;
- fChannelInfoSetString SetUnit;
-
- fChannelInfoSetChannelValue SetMin;
- fChannelInfoSetChannelValue SetMax;
- fChannelInfoSetChannelValue SetScale;
- fChannelInfoSetChannelValue SetOffset;
-
- fChannelInfoSetChannelValue SetDefault;
- fChannelInfoSetChannelValue SetInitial;
-
- fChannelInfoSetBool SetWriteResult;
-
- fChannelInfoSetChannelType SetType;
- fChannelInfoSetChannelMode SetMode;
-
- fChannelInfoGetType GetType;
- fChannelInfoGetMode GetMode;
- fChannelInfoGetString GetName;
- fChannelInfoGetString GetNameInTool;
- fChannelInfoGetString GetDescription;
- fChannelInfoGetString GetID;
- fChannelInfoGetString GetUnit;
-
- fChannelInfoGetInt IsBinary;
-
- fChannelInfoGetInt GetWriteResultFlag;
-
- fChannelInfoGetInitialValue GetInitialValue;
-
- fChannelInfoGetChannelValue GetMin;
- fChannelInfoGetChannelValue GetMax;
- fChannelInfoGetChannelValue GetScale;
- fChannelInfoGetChannelValue GetOffset;
- fChannelInfoGetChannelValue GetDefault;
-
- fChannelInfoGetString GetLogName;
+
+typedef struct ChannelInfo {
/* vector must be NULL if this is a scalar. It is the *only* way
* to distinguish between vectors of size 1 and scalar values.
*/
- struct VectorChannelInfo * vector;
+ VectorChannelInfo * vector;
+
+ struct Channel * channel;
char * name;
+ char * nameInTool;
char * description;
char * unitString;
- ChannelMode mode;
char * id;
- ChannelValue * min;
- ChannelValue * max;
+ ChannelMode mode;
int writeResult;
- char * nameInTool;
-
- int connected;
-
- ChannelType type;
+ ChannelValue * min;
+ ChannelValue * max;
+ ChannelValue * scale;
+ ChannelValue * offset;
ChannelValue * defaultValue;
ChannelValue * initialValue;
+ ChannelType type;
+
+ int connected;
int initialValueIsExact;
+} ChannelInfo;
+
+
+McxStatus ChannelInfoInit(ChannelInfo * info);
+void ChannelInfoDestroy(ChannelInfo * info);
+
+
+const char * ChannelInfoGetLogName(const ChannelInfo * info);
+const char * ChannelInfoGetName(const ChannelInfo * info);
+
+McxStatus ChannelInfoSetName(ChannelInfo * info, const char * name);
+McxStatus ChannelInfoSetNameInTool(ChannelInfo * info, const char * name);
+McxStatus ChannelInfoSetID(ChannelInfo * info, const char * name);
+McxStatus ChannelInfoSetDescription(ChannelInfo * info, const char * name);
+McxStatus ChannelInfoSetUnit(ChannelInfo * info, const char * name);
+McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType type);
+McxStatus ChannelInfoSetVector(ChannelInfo * info, VectorChannelInfo * vector);
+
+int ChannelInfoIsBinary(const ChannelInfo * info);
+
+McxStatus ChannelInfoSetup(ChannelInfo * info,
+ const char * name,
+ const char * descr,
+ const char * unit,
+ ChannelType type,
+ const char * id);
+
+McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other);
- ChannelValue * scale;
- ChannelValue * offset;
- struct Channel * channel;
-};
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c
index e172227..2c4cc8c 100644
--- a/src/core/channels/ChannelValue.c
+++ b/src/core/channels/ChannelValue.c
@@ -118,7 +118,7 @@ char * ChannelValueToString(ChannelValue * value) {
return buffer;
}
-McxStatus ChannelValueDataToStringBuffer(ChannelValueData * value, ChannelType type, char * buffer, size_t len) {
+McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, ChannelType type, char * buffer, size_t len) {
size_t i = 0;
size_t length = 0;
const size_t precision = 13;
@@ -192,7 +192,7 @@ McxStatus ChannelValueDataToStringBuffer(ChannelValueData * value, ChannelType t
return RETURN_OK;
}
-McxStatus ChannelValueToStringBuffer(ChannelValue * value, char * buffer, size_t len) {
+McxStatus ChannelValueToStringBuffer(const ChannelValue * value, char * buffer, size_t len) {
return ChannelValueDataToStringBuffer(&value->value, value->type, buffer, len);
}
diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h
index b177593..7cbdf2a 100644
--- a/src/core/channels/ChannelValue.h
+++ b/src/core/channels/ChannelValue.h
@@ -59,8 +59,8 @@ typedef struct ChannelValue {
void ChannelValueInit(ChannelValue * value, ChannelType type);
void ChannelValueDestructor(ChannelValue * value);
char * ChannelValueToString(ChannelValue * value);
-McxStatus ChannelValueDataToStringBuffer(ChannelValueData * value, ChannelType type, char * buffer, size_t len);
-McxStatus ChannelValueToStringBuffer(ChannelValue * value, char * buffer, size_t len);
+McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, ChannelType type, char * buffer, size_t len);
+McxStatus ChannelValueToStringBuffer(const ChannelValue * value, char * buffer, size_t len);
ChannelType ChannelValueType(ChannelValue * value);
void * ChannelValueReference(ChannelValue * value);
diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h
index 60ef770..af2a837 100644
--- a/src/core/channels/Channel_impl.h
+++ b/src/core/channels/Channel_impl.h
@@ -13,32 +13,13 @@
#include "CentralParts.h"
#include "objects/ObjectContainer.h"
+#include "core/channels/ChannelInfo.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-// ----------------------------------------------------------------------
-// Channel
-
-typedef struct ChannelData {
- Object _; // base class
-
- // ----------------------------------------------------------------------
- // General Information
-
- ChannelInfo * info;
-
- // ----------------------------------------------------------------------
- // Value
-
- // NOTE: This flag gets set if there is a defined value for the
- // channel during initialization.
- int isDefinedDuringInit;
- const void * internalValue;
- ChannelValue value;
-} ChannelData;
// ----------------------------------------------------------------------
// ChannelIn
@@ -95,7 +76,7 @@ typedef struct ChannelOutData {
// Connections to Consumers
// A list of all input channels that are connected to this output channel
- ObjectContainer * connections;
+ ObjectList * connections;
} ChannelOutData;
diff --git a/src/core/channels/VectorChannelInfo.c b/src/core/channels/VectorChannelInfo.c
index ee6fbe9..10492b3 100644
--- a/src/core/channels/VectorChannelInfo.c
+++ b/src/core/channels/VectorChannelInfo.c
@@ -9,6 +9,7 @@
********************************************************************************/
#include "core/channels/VectorChannelInfo.h"
+#include "core/channels/ChannelInfo.h"
#include "util/string.h"
#include "objects/ObjectContainer.h"
@@ -61,9 +62,8 @@ static McxStatus VectorChannelInfoSetup(
static McxStatus VectorChannelInfoAddElement(
VectorChannelInfo * info,
ChannelInfo * channel,
- size_t index) {
-
- ChannelInfo * oldChannel = NULL;
+ size_t index)
+{
McxStatus retVal = RETURN_OK;
if (index < info->startIndex || index > info->endIndex) {
@@ -71,14 +71,9 @@ static McxStatus VectorChannelInfoAddElement(
return RETURN_ERROR;
}
- oldChannel = (ChannelInfo *) info->channels->At(info->channels, index - info->startIndex);
- if (oldChannel) {
- object_destroy(oldChannel);
- }
-
- retVal = info->channels->SetAt(info->channels, index - info->startIndex, (Object *) channel);
+ retVal = info->channels->SetAt(info->channels, index - info->startIndex, &channel);
if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Vector port: %s: Could not add port info with index %d", info->GetName(info));
+ mcx_log(LOG_ERROR, "Vector port: %s: Could not add port info with index %zu", info->GetName(info), index);
return RETURN_ERROR;
}
@@ -102,7 +97,7 @@ static const char * VectorChannelInfoGetNameInTool(VectorChannelInfo * info) {
}
static ChannelInfo * VectorChannelInfoGetElement(VectorChannelInfo * info, size_t index) {
- return (ChannelInfo *) info->channels->At(info->channels, index - info->startIndex);
+ return *(ChannelInfo **) info->channels->At(info->channels, index - info->startIndex);
}
static int VectorChannelInfoIsScalar(VectorChannelInfo * info) {
@@ -139,11 +134,13 @@ static VectorChannelInfo * VectorChannelInfoCreate(VectorChannelInfo * info) {
info->startIndex = SIZE_T_ERROR;
info->endIndex = SIZE_T_ERROR;
- info->channels = (ObjectContainer *) object_create(ObjectContainer);
+ info->channels = (Vector *) object_create(Vector);
if (!info->channels) {
return NULL;
}
+ info->channels->Setup(info->channels, sizeof(ChannelInfo *), NULL, NULL, NULL);
+
return info;
}
diff --git a/src/core/channels/VectorChannelInfo.h b/src/core/channels/VectorChannelInfo.h
index 0a9b24e..118a71f 100644
--- a/src/core/channels/VectorChannelInfo.h
+++ b/src/core/channels/VectorChannelInfo.h
@@ -12,7 +12,7 @@
#define MCX_CORE_CHANNELS_VECTORCHANNELINFO_H
#include "CentralParts.h"
-#include "core/channels/ChannelInfo.h"
+#include "objects/Vector.h"
#ifdef __cplusplus
extern "C" {
@@ -53,7 +53,7 @@ struct VectorChannelInfo {
size_t startIndex;
size_t endIndex;
- ObjectContainer * channels; // of ChannelInfo, the elements of the vector
+ Vector * channels; // of ChannelInfo, the elements of the vector
};
#ifdef __cplusplus
diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c
index 2f3edad..67622d2 100644
--- a/src/core/connections/Connection.c
+++ b/src/core/connections/Connection.c
@@ -10,8 +10,8 @@
#include "CentralParts.h"
#include "core/connections/Connection.h"
-#include "core/connections/Connection_impl.h"
#include "core/channels/Channel.h"
+#include "core/channels/ChannelInfo.h"
#include "core/connections/ConnectionInfo.h"
#include "core/Conversion.h"
@@ -21,34 +21,64 @@
// Filter
#include "core/connections/filters/DiscreteFilter.h"
+#include "core/connections/filters/MemoryFilter.h"
#include "core/connections/filters/IntExtFilter.h"
#include "core/connections/filters/ExtFilter.h"
#include "core/connections/filters/IntFilter.h"
+#include "util/compare.h"
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-McxStatus CheckConnectivity(ObjectContainer * connections) {
+
+static void UpdateInChannelInfo(Component * comp, size_t idx) {
+ Databus * db = comp->GetDatabus(comp);
+
+ if (DatabusInChannelsDefined(db)) {
+ Channel * channel = (Channel *) DatabusGetInChannel(db, idx);
+ if (channel) {
+ channel->info.connected = 1;
+ }
+ }
+}
+
+static void UpdateOutChannelInfo(Component * comp, size_t idx) {
+ Databus * db = comp->GetDatabus(comp);
+
+ if (DatabusOutChannelsDefined(db)) {
+ Channel * channel = (Channel *) DatabusGetOutChannel(db, idx);
+ if (channel) {
+ channel->info.connected = 1;
+ }
+ }
+}
+
+McxStatus CheckConnectivity(Vector * connections) {
size_t i = 0;
- for (i = 0; i < connections->Size(connections); i++) {
+ size_t connSize = connections->Size(connections);
+
+ for (i = 0; i < connSize; i++) {
ConnectionInfo * connInfo = (ConnectionInfo *) connections->At(connections, i);
ChannelInfo * info = NULL;
- Component * target = connInfo->GetTargetComponent(connInfo);
- int targetId = connInfo->GetTargetChannelID(connInfo);
+ Component * target = connInfo->targetComponent;
+ int targetId = connInfo->targetChannel;
- Component * source = connInfo->GetSourceComponent(connInfo);
- int sourceId = connInfo->GetSourceChannelID(connInfo);
+ Component * source = connInfo->sourceComponent;
+ int sourceId = connInfo->sourceChannel;
info = DatabusInfoGetChannel(DatabusGetInInfo(target->GetDatabus(target)), targetId);
if (info) {
info->connected = 1;
+ UpdateInChannelInfo(target, targetId);
}
info = DatabusInfoGetChannel(DatabusGetOutInfo(source->GetDatabus(source)), sourceId);
if (info) {
info->connected = 1;
+ UpdateOutChannelInfo(source, sourceId);
}
}
@@ -64,22 +94,19 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte
ChannelInfo * outInfo = NULL;
ChannelInfo * inInfo = NULL;
- source = info->GetSourceComponent(info);
- target = info->GetTargetComponent(info);
+ source = info->sourceComponent;
+ target = info->targetComponent;
// Get data types of involved channels
- outInfo = DatabusInfoGetChannel(DatabusGetOutInfo(source->GetDatabus(source)),
- info->GetSourceChannelID(info));
-
- inInfo = DatabusInfoGetChannel(DatabusGetInInfo(target->GetDatabus(target)),
- info->GetTargetChannelID(info));
+ outInfo = DatabusInfoGetChannel(DatabusGetOutInfo(source->GetDatabus(source)), info->sourceChannel);
+ inInfo = DatabusInfoGetChannel(DatabusGetInInfo(target->GetDatabus(target)), info->targetChannel);
if (!outInfo || !inInfo) {
mcx_log(LOG_ERROR, "Connection: Make connection: Invalid arguments");
return RETURN_ERROR;
}
- InterExtrapolationParams * params = info->GetInterExtraParams(info);
+ InterExtrapolationParams * params = &info->interExtrapolationParams;
if (EXTRAPOLATING == isInterExtrapolating) {
if (params->extrapolationOrder != params->interpolationOrder) {
@@ -89,7 +116,7 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte
isInterExtrapolating = INTEREXTRAPOLATING;
}
- info->SetInterExtrapolating(info, isInterExtrapolating);
+ info->isInterExtrapolating = isInterExtrapolating;
connection = DatabusCreateConnection(source->GetDatabus(source), info);
if (!connection) {
@@ -100,35 +127,882 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte
return RETURN_OK;
}
+static void LogStepRatios(double sourceStep, double targetStep, double synchStep, ConnectionInfo * info) {
+ char * connString = ConnectionInfoConnectionString(info);
+
+ if (sourceStep <= synchStep && targetStep <= synchStep) {
+ MCX_DEBUG_LOG("CONN %s: source <= synch && target <= synch", connString);
+ } else if (sourceStep <= synchStep && targetStep > synchStep) {
+ MCX_DEBUG_LOG("CONN %s: source <= synch && target > synch", connString);
+ } else if (sourceStep > synchStep && targetStep <= synchStep) {
+ MCX_DEBUG_LOG("CONN %s: source > synch && target <= synch", connString);
+ } else {
+ MCX_DEBUG_LOG("CONN %s: source > synch && target > synch", connString);
+ }
+
+ mcx_free(connString);
+}
+
+static int ComponentMightNotRespectStepSize(Component * comp) {
+ return FALSE;
+}
+
+static size_t DetermineFilterBufferSize(ConnectionInfo * info) {
+ Component * source = info->sourceComponent;
+ Component * target = info->targetComponent;
+
+ Model * model = source->GetModel(source);
+ Task * task = model->GetTask(model);
+
+ double synchStep = task->GetTimeStep(task);
+ double sourceStep = source->GetTimeStep(source) > 0 ? source->GetTimeStep(source) : synchStep;
+ double targetStep = target->GetTimeStep(target) > 0 ? target->GetTimeStep(target) : synchStep;
+
+ size_t buffSize = 0;
+
+ if (model->config->overrideInterpolationBuffSize > 0) {
+ buffSize = model->config->overrideInterpolationBuffSize;
+ }
+ else if (ComponentMightNotRespectStepSize(source) || ComponentMightNotRespectStepSize(target)) {
+ buffSize = model->config->interpolationBuffSize;
+ }
+ else {
+ buffSize = (size_t) ceil(synchStep / sourceStep) + 1;
+ }
+
+ buffSize += model->config->interpolationBuffSizeSafetyExt;
+
+ if (buffSize > model->config->interpolationBuffSizeLimit) {
+ char * connString = ConnectionInfoConnectionString(info);
+ mcx_log(LOG_WARNING, "%s: buffer limit exceeded (%zu > &zu). Limit can be changed via MC_INTERPOLATION_BUFFER_SIZE_LIMIT.",
+ connString, buffSize, model->config->interpolationBuffSizeLimit);
+ mcx_free(connString);
+
+ buffSize = model->config->interpolationBuffSizeLimit;
+ }
+
+ return buffSize;
+}
+
+static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) {
+ size_t size = 0;
+
+ Component * sourceComp = info->sourceComponent;
+ Component * targetComp = info->targetComponent;
+
+ Model * model = sourceComp->GetModel(sourceComp);
+ Task * task = model->GetTask(model);
+
+ size_t limit = model->config->memFilterHistoryLimit;
+
+ double syncStep = task->GetTimeStep(task);
+
+ double sourceStep = sourceComp->GetTimeStep(sourceComp) ? sourceComp->GetTimeStep(sourceComp) : syncStep;
+ double targetStep = targetComp->GetTimeStep(targetComp) ? targetComp->GetTimeStep(targetComp) : syncStep;
+
+ double syncToSrcRatio = syncStep / sourceStep;
+ double syncToTrgRatio = syncStep / targetStep;
+
+ double trgToSyncRatio = targetStep / syncStep;
+ double trgToSrcRatio = targetStep / sourceStep;
+
+ double srcToSyncRatio = sourceStep / syncStep;
+ double srcToTrgRatio = sourceStep / targetStep;
+
+ double syncToSrc = round(syncToSrcRatio);
+ double syncToTrg = round(syncToTrgRatio);
+
+ double trgToSync = round(trgToSyncRatio);
+ double trgToSrc = round(trgToSrcRatio);
+
+ double srcToSync = round(srcToSyncRatio);
+ double srcToTrg = round(srcToTrgRatio);
+
+ int useInputsAtEndTime = task->useInputsAtEndTime;
+
+ StepTypeType stepType = task->GetStepTypeType(task);
+
+ if (!model->config->useMemFilter) {
+ return 0;
+ }
+
+ if (ComponentMightNotRespectStepSize(sourceComp) || ComponentMightNotRespectStepSize(targetComp)) {
+ return 0;
+ }
+
+ if (STEP_TYPE_PARALLEL_MT == stepType) {
+ if (useInputsAtEndTime && extDegree == 0) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 2: T = t_a && t_a > t_b && t_a = n * t_b
+ else if (double_eq(syncStep, sourceStep) && srcToTrgRatio > 1.0 && double_eq(srcToTrgRatio, srcToTrg)) {
+ size = 2;
+ }
+ // CASE 3: T = t_a && t_a > t_b && t_a = m * t_b
+ else if (double_eq(syncStep, sourceStep) && srcToTrgRatio > 1.0 && !double_eq(srcToTrgRatio, srcToTrg)) {
+ size = 2;
+ }
+ // CASE 4: T > t_a && T = n * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 5: T > t_a && T = n * t_a && t_a > t_b && t_a = k * t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && srcToTrgRatio > 1.0 && double_eq(srcToTrgRatio, srcToTrg)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 6: T > t_a && T = n * t_a && t_a > t_b && t_a = m * t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && srcToTrgRatio > 1.0 && !double_eq(srcToTrgRatio, srcToTrg)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 7: T > t_a && T = m * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ // CASE 10: T < t_a && T = t_b && n * T = t_a && n = 2
+ else if (double_eq(syncStep, targetStep) && double_eq(srcToSyncRatio, 2.0)) {
+ size = 2;
+ }
+ // CASE 12: T < t_a && T = t_b && m * T = t_a && m <= 1.5
+ else if (double_eq(syncStep, targetStep) && srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && (double_eq(srcToSyncRatio, 1.5) || srcToSyncRatio < 1.5)) {
+ size = 2;
+ }
+ // CASE 14: T < t_a && T < t_b && n * T = t_b && k * T = t_a && k / n = 2
+ else if (trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSync / trgToSync;
+ if (double_eq(factor, 2.0)) {
+ size = 2;
+ }
+ }
+ // CASE 16: T < t_a && T < t_b && n * T = t_b && k * T = t_a && k / n in (1,2)
+ else if (trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSync / trgToSync;
+ if (!double_eq(factor, round(factor)) && factor > 1.0 && factor < 2.0) {
+ size = 2;
+ }
+ }
+ // CASE 18: T < t_a && T < t_b && n * T = t_b && p * T = t_a && p / n in (1,2)
+ else if (trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSyncRatio / trgToSync;
+ if (!double_eq(factor, round(factor)) && factor > 1.0 && factor < 2.0) {
+ size = 2;
+ }
+ }
+ // CASE 20: T < t_a && T < t_b && m * T = t_b && k * T = t_a && k / m in (1,2)
+ else if (trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSync / trgToSyncRatio;
+ if (!double_eq(factor, round(factor)) && factor > 1.0 && factor < 2.0) {
+ size = 2;
+ }
+ }
+ // CASE 22: T < t_a && T < t_b && m * T = t_b && k * T = t_a && k / m = 2
+ else if (trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSync / trgToSyncRatio;
+ if (double_eq(factor, 2.0)) {
+ size = 2;
+ }
+ }
+ // CASE 24: T < t_a && T < t_b && m * T = t_b && p * T = t_a && p / m = 2
+ else if (trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSyncRatio / trgToSyncRatio;
+ if (double_eq(factor, 2.0)) {
+ size = 2;
+ }
+ }
+ // CASE 26: T < t_a && T < t_b && m * T = t_b && p * T = t_a && p / m in (1,2)
+ else if (trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync)) {
+ double factor = srcToSyncRatio / trgToSyncRatio;
+ if (!double_eq(factor, round(factor)) && factor > 1.0 && factor < 2.0) {
+ size = 2;
+ }
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 37: T = t_b && t_b > t_a && t_b = m * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && !double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(trgToSrcRatio) + 1;
+ }
+ // CASE 38: T > t_b && T = n * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) syncToTrg * (size_t) trgToSrc + 1;
+ }
+ // CASE 39: T > t_b && T = n * t_b && t_b > t_a && t_b = m * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && !double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) syncToTrg * (size_t) ceil(trgToSrcRatio) + 1;
+ }
+ // CASE 40: T > t_b && t = m * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) trgToSrc + 1;
+ }
+ // CASE 41: T > t_b && t = m * t_b && t_b > t_a && t_b = p * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && !double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) ceil(trgToSrcRatio) + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 43: T < t_b && T = t_a && m * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 44: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 45: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n not in {2,3,...} && k > n
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 46: T < t_b && T < t_a && n * T = t_a && p * T = t_b && p > n
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ size = 2;
+ }
+ // CASE 47: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m not in {2,3,...} && k > m
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 48: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 49: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 50: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m not in {2,3,...} && p > m
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 51: T < t_b && T > t_a && T = n * t_a && k * T = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 52: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 53: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p not in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 54: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m not in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 55: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 56: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 57: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m < 2
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor < 2.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 58: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m > 2 && p * m not in {3,4,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 2.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ }
+ else if (!useInputsAtEndTime && extDegree == 0) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 2: T = t_a && t_a > t_b && t_a = n * t_b
+ else if (double_eq(syncStep, sourceStep) && srcToTrgRatio > 1.0 && double_eq(srcToTrgRatio, srcToTrg)) {
+ size = 2;
+ }
+ // CASE 3: T = t_a && t_a > t_b && t_a = m * t_b
+ else if (double_eq(syncStep, sourceStep) && srcToTrgRatio > 1.0 && !double_eq(srcToTrgRatio, srcToTrg)) {
+ size = 2;
+ }
+ // CASE 4: T > t_a && T = n * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 5: T > t_a && T = n * t_a && t_a > t_b && t_a = k * t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && srcToTrgRatio > 1.0 && double_eq(srcToTrgRatio, srcToTrg)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 6: T > t_a && T = n * t_a && t_a > t_b && t_a = m * t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && srcToTrgRatio > 1.0 && !double_eq(srcToTrgRatio, srcToTrg)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 7: T > t_a && T = m * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ // CASE 12: T < t_a && T = t_b && m * T = t_a && m <= 1.5
+ else if (double_eq(syncStep, targetStep) && srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && (double_eq(srcToSyncRatio, 1.5) || srcToSyncRatio < 1.5)) {
+ size = 2;
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 38: T > t_b && T = n * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) syncToTrg * (size_t) trgToSrc + 1;
+ }
+ // CASE 40: T > t_b && t = m * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) trgToSrc + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 43: T < t_b && T = t_a && m * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 44: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 48: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 49: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 51: T < t_b && T > t_a && T = n * t_a && k * T = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 52: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 53: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p not in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 55: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 56: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ }
+ else if (useInputsAtEndTime) {
+ // not applicable
+ }
+ else if (!useInputsAtEndTime) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 44: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 48: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 49: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 51: T < t_b && T > t_a && T = n * t_a && k * T = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 55: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ }
+ } else if (STEP_TYPE_SEQUENTIAL == stepType) {
+ if (useInputsAtEndTime && extDegree == 0) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 4: T > t_a && T = n * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 7: T > t_a && T = m * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 38: T > t_b && T = n * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) syncToTrg * (size_t) trgToSrc + 1;
+ }
+ // CASE 40: T > t_b && t = m * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) trgToSrc + 1;
+ }
+ // CASE 41: T > t_b && t = m * t_b && t_b > t_a && t_b = p * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && !double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) ceil(trgToSrcRatio) + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 43: T < t_b && T = t_a && m * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 44: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 45: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n not in {2,3,...} && k > n
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 46: T < t_b && T < t_a && n * T = t_a && p * T = t_b && p > n
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ size = 2;
+ }
+ // CASE 47: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m not in {2,3,...} && k > m
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 48: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 49: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 50: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m not in {2,3,...} && p > m
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync) && trgToSyncRatio > srcToSyncRatio) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 51: T < t_b && T > t_a && T = n * t_a && k * T = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = (size_t)syncToSrc + 1;
+ }
+ // CASE 52: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 53: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p not in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 54: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m not in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 55: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 56: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 58: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m > 2 && p * m not in {3,4,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 2.0 && !double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ }
+ else if (!useInputsAtEndTime && extDegree == 0) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 4: T > t_a && T = n * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 7: T > t_a && T = m * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 38: T > t_b && T = n * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t)syncToTrg * (size_t)trgToSrc + 1;
+ }
+ // CASE 40: T > t_b && t = m * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) trgToSrc + 1;
+ }
+ // CASE 41: T > t_b && t = m * t_b && t_b > t_a && t_b = p * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && !double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) ceil(trgToSrcRatio) + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 44: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 48: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 49: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 51: T < t_b && T > t_a && T = n * t_a && k * T = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = (size_t)syncToSrc + 1;
+ }
+ // CASE 52: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 55: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 56: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ }
+ else if (useInputsAtEndTime) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 4: T > t_a && T = n * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 7: T > t_a && T = m * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 38: T > t_b && T = n * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) syncToTrg * (size_t) trgToSrc + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ }
+ else if (!useInputsAtEndTime) {
+ // CASE 1: T = t_a && t_a = t_b
+ if (double_eq(syncStep, sourceStep) && double_eq(sourceStep, targetStep)) {
+ size = 2;
+ }
+ // CASE 4: T > t_a && T = n * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) syncToSrc + 1;
+ }
+ // CASE 7: T > t_a && T = m * t_a && t_a = t_b
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && double_eq(sourceStep, targetStep)) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ // CASE 36: T = t_b && t_b > t_a && t_b = n * t_a
+ else if (double_eq(syncStep, targetStep) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) trgToSrc + 1;
+ }
+ // CASE 38: T > t_b && T = n * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) syncToTrg * (size_t) trgToSrc + 1;
+ }
+ // CASE 40: T > t_b && t = m * t_b && t_b > t_a && t_b = k * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) trgToSrc + 1;
+ }
+ // CASE 41: T > t_b && t = m * t_b && t_b > t_a && t_b = p * t_a
+ else if (syncToTrgRatio > 1.0 && !double_eq(syncToTrgRatio, syncToTrg) && trgToSrcRatio > 1.0 && !double_eq(trgToSrcRatio, trgToSrc)) {
+ size = (size_t) ceil(syncToTrgRatio) * (size_t) ceil(trgToSrcRatio) + 1;
+ }
+ // CASE 42: T < t_b && T = t_a && n * T = t_b
+ else if (double_eq(syncStep, sourceStep) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = 2;
+ }
+ // CASE 44: T < t_b && T < t_a &&& n * T = t_a && k * T = t_b && k / n in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSync;
+ if (factor > 1 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 48: T < t_b && T < t_a &&& m * T = t_a && k * T = t_b && k / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSync / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 49: T < t_b && T < t_a &&& m * T = t_a && p * T = t_b && p / m in {2,3,...}
+ else if (srcToSyncRatio > 1.0 && !double_eq(srcToSyncRatio, srcToSync) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = trgToSyncRatio / srcToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = 2;
+ }
+ }
+ // CASE 51: T < t_b && T > t_a && T = n * t_a && k * T = t_b
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ size = (size_t)syncToSrc + 1;
+ }
+ // CASE 52: T < t_b && T > t_a && T = n * t_a && p * T = t_b && n * p in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrc * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) syncToSrc + 1;
+ }
+ }
+ // CASE 55: T < t_b && T > t_a && T = m * t_a && k * T = t_b && k * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSync;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ // CASE 56: T < t_b && T > t_a && T = m * t_a && p * T = t_b && p * m in {2,3,...}
+ else if (syncToSrcRatio > 1.0 && !double_eq(syncToSrcRatio, syncToSrc) && trgToSyncRatio > 1.0 && !double_eq(trgToSyncRatio, trgToSync)) {
+ double factor = syncToSrcRatio * trgToSyncRatio;
+ if (factor > 1.0 && double_eq(factor, round(factor))) {
+ size = (size_t) ceil(syncToSrcRatio) + 1;
+ }
+ }
+ }
+ }
+
+ if (size == 0) {
+ return 0;
+ }
+
+ if (size + model->config->memFilterHistoryExtra > limit) {
+ char * connString = ConnectionInfoConnectionString(info);
+ mcx_log(LOG_WARNING, "%s: history size limit exceeded (%zu > &zu). Limit can be changed via MC_MEM_FILTER_HISTORY_LIMIT. "
+ "Disabling memory filter",
+ connString, size + model->config->memFilterHistoryExtra, limit);
+ mcx_free(connString);
+
+ return 0;
+ }
+
+ return size + model->config->memFilterHistoryExtra;
+}
+
+static MemoryFilter * SetMemoryFilter(int reverseSearch, ChannelType sourceType, size_t historySize) {
+ McxStatus retVal = RETURN_OK;
+
+ MemoryFilter * filter = (MemoryFilter *)object_create(MemoryFilter);
+ if (!filter) {
+ mcx_log(LOG_ERROR, "Memory filter creation failed");
+ return NULL;
+ }
+
+ mcx_log(LOG_DEBUG, " Setting up memory filter. (%p)", filter);
+ mcx_log(LOG_DEBUG, " History size: %zu", historySize);
+
+ retVal = filter->Setup(filter, sourceType, historySize, reverseSearch);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Memory filter setup failed");
+ object_destroy(filter);
+ return NULL;
+ }
+
+ return filter;
+}
ChannelFilter * FilterFactory(Connection * connection) {
ChannelFilter * filter = NULL;
McxStatus retVal;
ConnectionInfo * info = connection->GetInfo(connection);
- InterExtrapolationType extrapolType = info->GetInterExtraType(info);
- InterExtrapolationParams * params = info->GetInterExtraParams(info);
+ InterExtrapolationType extrapolType = info->interExtrapolationType;
+ InterExtrapolationParams * params = &info->interExtrapolationParams;
+
+ Component * sourceComp = info->sourceComponent;
+ Model * model = sourceComp->GetModel(sourceComp);
+ Task * task = model->GetTask(model);
+ int useInputsAtEndTime = task->useInputsAtEndTime;
- if (info->GetType(info) == CHANNEL_DOUBLE) {
+ if (ConnectionInfoGetType(info) == CHANNEL_DOUBLE) {
if (!(INTERVAL_COUPLING == params->interpolationInterval && INTERVAL_SYNCHRONIZATION == params->extrapolationInterval)) {
mcx_log(LOG_WARNING, "The use of inter/extrapolation interval settings for double is not supported");
}
if (extrapolType == INTEREXTRAPOLATION_POLYNOMIAL) {
- InterExtrapolatingType isInterExtrapol = info->GetInterExtrapolating(info);
- if (INTERPOLATING == isInterExtrapol && info->IsDecoupled(info)) {
+ InterExtrapolatingType isInterExtrapol = info->isInterExtrapolating;
+ if (INTERPOLATING == isInterExtrapol && ConnectionInfoIsDecoupled(info)) {
isInterExtrapol = INTEREXTRAPOLATING;
}
int degree = (INTERPOLATING == isInterExtrapol) ? params->interpolationOrder : params->extrapolationOrder;
if (EXTRAPOLATING == isInterExtrapol || INTEREXTRAPOLATING == isInterExtrapol) {
- if (INTEREXTRAPOLATING == isInterExtrapol) {
+ size_t memFilterHist = MemoryFilterHistorySize(info, params->extrapolationOrder);
+ if (0 != memFilterHist) {
+ filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist);
+ if (!filter) {
+ return NULL;
+ }
+ } else if (INTEREXTRAPOLATING == isInterExtrapol) {
IntExtFilter * intExtFilter = (IntExtFilter *)object_create(IntExtFilter);
filter = (ChannelFilter *)intExtFilter;
mcx_log(LOG_DEBUG, " Setting up dynamic filter. (%p)", filter);
mcx_log(LOG_DEBUG, " Interpolation order: %d, extrapolation order: %d", params->interpolationOrder, params->extrapolationOrder);
- retVal = intExtFilter->Setup(intExtFilter, params->extrapolationOrder, params->interpolationOrder);
+ size_t buffSize = DetermineFilterBufferSize(info);
+ retVal = intExtFilter->Setup(intExtFilter, params->extrapolationOrder, params->interpolationOrder, buffSize);
if (RETURN_OK != retVal) {
return NULL;
}
@@ -143,14 +1017,23 @@ ChannelFilter * FilterFactory(Connection * connection) {
}
}
} else {
- IntFilter * intFilter = (IntFilter *) object_create(IntFilter);
- filter = (ChannelFilter *) intFilter;
- mcx_log(LOG_DEBUG, " Setting up coupling step interpolation filter. (%p)", filter);
- mcx_log(LOG_DEBUG, " Interpolation order: %d", degree);
- retVal = intFilter->Setup(intFilter, degree);
- if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Connection: Filter: Could not setup");
- return NULL;
+ size_t memFilterHist = MemoryFilterHistorySize(info, degree);
+ if (0 != memFilterHist) {
+ filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist);
+ if (!filter) {
+ return NULL;
+ }
+ } else {
+ IntFilter* intFilter = (IntFilter*)object_create(IntFilter);
+ filter = (ChannelFilter*)intFilter;
+ mcx_log(LOG_DEBUG, " Setting up coupling step interpolation filter. (%p)", filter);
+ mcx_log(LOG_DEBUG, " Interpolation order: %d", degree);
+ size_t buffSize = DetermineFilterBufferSize(info);
+ retVal = intFilter->Setup(intFilter, degree, buffSize);
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "Connection: Filter: Could not setup");
+ return NULL;
+ }
}
}
@@ -172,82 +1055,59 @@ ChannelFilter * FilterFactory(Connection * connection) {
mcx_log(LOG_DEBUG, "Using constant synchronization step extrapolation for non-double connection");
discreteFilter = (DiscreteFilter *) object_create(DiscreteFilter);
- discreteFilter->Setup(discreteFilter, info->GetType(info));
+ discreteFilter->Setup(discreteFilter, ConnectionInfoGetType(info));
filter = (ChannelFilter *) discreteFilter;
}
- if (NULL == filter && info->GetType(info) == CHANNEL_DOUBLE) {
+ if (NULL == filter && ConnectionInfoGetType(info) == CHANNEL_DOUBLE) {
// TODO: add a check to avoid filters for non-multirate cases
- ExtFilter * extFilter = (ExtFilter *) object_create(ExtFilter);
- extFilter->Setup(extFilter, 0);
- filter = (ChannelFilter *) extFilter;
+ size_t memFilterHist = MemoryFilterHistorySize(info, 0);
+ if (0 != memFilterHist) {
+ filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist);
+ if (!filter) {
+ return NULL;
+ }
+ } else {
+ ExtFilter * extFilter = (ExtFilter *) object_create(ExtFilter);
+ extFilter->Setup(extFilter, 0);
+ filter = (ChannelFilter *) extFilter;
+ }
}
- filter->AssignState(filter, &connection->data->state);
+ filter->AssignState(filter, &connection->state_);
return filter;
}
-
-static ConnectionData * ConnectionDataCreate(ConnectionData * data) {
- data->out = NULL;
- data->in = NULL;
-
- data->info = NULL;
-
- data->value = NULL;
- data->useInitialValue = FALSE;
-
- data->isActiveDependency = TRUE;
-
- ChannelValueInit(&data->store, CHANNEL_UNKNOWN);
-
- data->state = InCommunicationMode;
-
- data->NormalUpdateFrom = NULL;
- data->NormalUpdateTo = NULL;
- data->normalValue = NULL;
-
- return data;
-}
-
-
-static void ConnectionDataDestructor(ConnectionData * data) {
- object_destroy(data->info);
-
- ChannelValueDestructor(&data->store);
-}
-
-OBJECT_CLASS(ConnectionData, Object);
-
-
static void * ConnectionGetValueReference(Connection * connection) {
- return (void *)connection->data->value;
+ return (void *)connection->value_;
}
+static void ConnectionSetValueReference(Connection * connection, void * reference) {
+ connection->value_ = reference;
+}
static void ConnectionDestructor(Connection * connection) {
- object_destroy(connection->data);
+ ChannelValueDestructor(&connection->store_);
}
static ChannelOut * ConnectionGetSource(Connection * connection) {
- return connection->data->out;
+ return connection->out_;
}
static ChannelIn * ConnectionGetTarget(Connection * connection) {
- return connection->data->in;
+ return connection->in_;
}
static ConnectionInfo * ConnectionGetInfo(Connection * connection) {
- return connection->data->info;
+ return &connection->info;
}
static int ConnectionIsDecoupled(Connection * connection) {
- ConnectionInfo * info = connection->GetInfo(connection);
- return info->IsDecoupled(info);
+ return ConnectionInfoIsDecoupled(&connection->info);
}
static int ConnectionIsDefinedDuringInit(Connection * connection) {
@@ -262,11 +1122,11 @@ static void ConnectionSetDefinedDuringInit(Connection * connection) {
static int ConnectionIsActiveDependency(Connection * conn) {
- return conn->data->isActiveDependency;
+ return conn->isActiveDependency_;
}
static void ConnectionSetActiveDependency(Connection * conn, int active) {
- conn->data->isActiveDependency = active;
+ conn->isActiveDependency_ = active;
}
static void ConnectionUpdateFromInput(Connection * connection, TimeInterval * time) {
@@ -275,30 +1135,30 @@ static void ConnectionUpdateFromInput(Connection * connection, TimeInterval * ti
static McxStatus ConnectionUpdateInitialValue(Connection * connection) {
ConnectionInfo * info = connection->GetInfo(connection);
- Channel * in = (Channel *) connection->data->in;
- Channel * out = (Channel *) connection->data->out;
+ Channel * in = (Channel *) connection->in_;
+ Channel * out = (Channel *) connection->out_;
- ChannelInfo * inInfo = in->GetInfo(in);
- ChannelInfo * outInfo = out->GetInfo(out);
+ ChannelInfo * inInfo = &in->info;
+ ChannelInfo * outInfo = &out->info;
- if (connection->data->state != InInitializationMode) {
- char * buffer = info->ConnectionString(info);
+ if (connection->state_ != InInitializationMode) {
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_ERROR, "Connection %s: Update initial value: Cannot update initial value outside of initialization mode", buffer);
mcx_free(buffer);
return RETURN_ERROR;
}
if (!out || !in) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_ERROR, "Connection %s: Update initial value: Cannot update initial value for unconnected connection", buffer);
mcx_free(buffer);
return RETURN_ERROR;
}
- if (inInfo->GetInitialValue(inInfo)) {
+ if (inInfo->initialValue) {
McxStatus retVal = RETURN_OK;
- ChannelValue * store = &connection->data->store;
- ChannelValue * inChannelValue = inInfo->GetInitialValue(inInfo);
+ ChannelValue * store = &connection->store_;
+ ChannelValue * inChannelValue = inInfo->initialValue;
ChannelValue * inValue = ChannelValueClone(inChannelValue);
if (NULL == inValue) {
@@ -338,17 +1198,17 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) {
}
mcx_free(inValue);
- connection->data->useInitialValue = TRUE;
- } else if (outInfo->GetInitialValue(outInfo)) {
- ChannelValueSet(&connection->data->store, outInfo->GetInitialValue(outInfo));
- connection->data->useInitialValue = TRUE;
+ connection->useInitialValue_ = TRUE;
+ } else if (outInfo->initialValue) {
+ ChannelValueSet(&connection->store_, outInfo->initialValue);
+ connection->useInitialValue_ = TRUE;
} else {
{
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_WARNING, "Connection %s: No initial values are specified for the ports of the connection", buffer);
mcx_free(buffer);
}
- ChannelValueInit(&connection->data->store, info->GetType(info));
+ ChannelValueInit(&connection->store_, ConnectionInfoGetType(info));
}
return RETURN_OK;
@@ -357,26 +1217,26 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) {
static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * time) {
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- Channel * channel = (Channel *) connection->data->out;
- ChannelInfo * info = channel->GetInfo(channel);
- MCX_DEBUG_LOG("[%f] CONN (%s) UpdateFromInput", time->startTime, info->GetName(info));
+ Channel * channel = (Channel *) connection->out_;
+ ChannelInfo * info = &channel->info;
+ MCX_DEBUG_LOG("[%f] CONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info));
}
#endif
// Do nothing
}
static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) {
- Channel * channel = (Channel *) connection->data->out;
+ Channel * channel = (Channel *) connection->out_;
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- ChannelInfo * info = channel->GetInfo(channel);
- MCX_DEBUG_LOG("[%f] CONN (%s) UpdateToOutput", time->startTime, info->GetName(info));
+ ChannelInfo * info = &channel->info;
+ MCX_DEBUG_LOG("[%f] CONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info));
}
#endif
- if (!connection->data->useInitialValue) {
- ChannelValueSetFromReference(&connection->data->store, channel->GetValueReference(channel));
+ if (!connection->useInitialValue_) {
+ ChannelValueSetFromReference(&connection->store_, channel->GetValueReference(channel));
if (channel->IsDefinedDuringInit(channel)) {
connection->SetDefinedDuringInit(connection);
}
@@ -387,27 +1247,27 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time)
static McxStatus ConnectionEnterInitializationMode(Connection * connection) {
#ifdef MCX_DEBUG
- Channel * channel = (Channel *) connection->data->out;
- ChannelInfo * info = channel->GetInfo(channel);
- MCX_DEBUG_LOG("[%f] CONN (%s) EnterInit", 0.0, info->GetName(info));
+ Channel * channel = (Channel *) connection->out_;
+ ChannelInfo * info = &channel->info;
+ MCX_DEBUG_LOG("[%f] CONN (%s) EnterInit", 0.0, ChannelInfoGetName(info));
#endif
- if (connection->data->state == InInitializationMode) {
+ if (connection->state_ == InInitializationMode) {
mcx_log(LOG_ERROR, "Connection: Enter initialization mode: Called multiple times");
return RETURN_ERROR;
}
- connection->data->state = InInitializationMode;
+ connection->state_ = InInitializationMode;
// save functions for normal mode
- connection->data->NormalUpdateFrom = connection->UpdateFromInput;
- connection->data->NormalUpdateTo = connection->UpdateToOutput;
- connection->data->normalValue = connection->data->value;
+ connection->NormalUpdateFrom_ = connection->UpdateFromInput;
+ connection->NormalUpdateTo_ = connection->UpdateToOutput;
+ connection->normalValue_ = connection->value_;
// set functions for initialization mode
connection->UpdateFromInput = ConnectionInitUpdateFrom;
connection->UpdateToOutput = ConnectionInitUpdateTo;
- connection->data->value = ChannelValueReference(&connection->data->store);
+ connection->value_ = ChannelValueReference(&connection->store_);
connection->IsDefinedDuringInit = ConnectionIsDefinedDuringInit;
connection->SetDefinedDuringInit = ConnectionSetDefinedDuringInit;
@@ -421,21 +1281,21 @@ static McxStatus ConnectionExitInitializationMode(Connection * connection, doubl
#ifdef MCX_DEBUG
if (time < MCX_DEBUG_LOG_TIME) {
- Channel * channel = (Channel *) connection->data->out;
- ChannelInfo * info = channel->GetInfo(channel);
- MCX_DEBUG_LOG("[%f] CONN (%s) ExitInit", time, info->GetName(info));
+ Channel * channel = (Channel *) connection->out_;
+ ChannelInfo * info = &channel->info;
+ MCX_DEBUG_LOG("[%f] CONN (%s) ExitInit", time, ChannelInfoGetName(info));
}
#endif
- if (connection->data->state != InInitializationMode) {
+ if (connection->state_ != InInitializationMode) {
mcx_log(LOG_ERROR, "Connection: Exit initialization mode: Called multiple times");
return RETURN_ERROR;
}
// restore functions for normal mode
- connection->UpdateFromInput = connection->data->NormalUpdateFrom;
- connection->UpdateToOutput = connection->data->NormalUpdateTo;
- connection->data->value = connection->data->normalValue;
+ connection->UpdateFromInput = connection->NormalUpdateFrom_;
+ connection->UpdateToOutput = connection->NormalUpdateTo_;
+ connection->value_ = connection->normalValue_;
connection->IsDefinedDuringInit = NULL;
connection->SetDefinedDuringInit(connection); // After initialization all values are defined
connection->SetDefinedDuringInit = NULL;
@@ -451,7 +1311,7 @@ static McxStatus ConnectionExitInitializationMode(Connection * connection, doubl
}
static McxStatus ConnectionEnterCommunicationMode(Connection * connection, double time) {
- connection->data->state = InCommunicationMode;
+ connection->state_ = InCommunicationMode;
return RETURN_OK;
}
@@ -459,7 +1319,7 @@ static McxStatus ConnectionEnterCommunicationMode(Connection * connection, doubl
static McxStatus ConnectionEnterCouplingStepMode(Connection * connection
, double communicationTimeStepSize, double sourceTimeStepSize, double targetTimeStepSize)
{
- connection->data->state = InCouplingStepMode;
+ connection->state_ = InCouplingStepMode;
return RETURN_OK;
}
@@ -468,30 +1328,31 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn *
McxStatus retVal = RETURN_OK;
Channel * chOut = (Channel *) out;
- ChannelInfo * outInfo = chOut->GetInfo(chOut);
+ ChannelInfo * outInfo = &chOut->info;
- connection->data->out = out;
- connection->data->in = in;
- connection->data->info = info;
+ connection->out_ = out;
+ connection->in_ = in;
if (in->IsDiscrete(in)) {
- info->SetDiscreteTarget(info);
+ info->hasDiscreteTarget = TRUE;
}
- ChannelValueInit(&connection->data->store, outInfo->GetType(outInfo));
+ connection->info = *info;
+
+ ChannelValueInit(&connection->store_, outInfo->type);
// Add connection to channel out
retVal = out->RegisterConnection(out, connection);
if (RETURN_OK != retVal) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_ERROR, "Connection %s: Setup connection: Could not register with outport", buffer);
mcx_free(buffer);
return RETURN_ERROR;
}
- retVal = in->SetConnection(in, connection, outInfo->GetUnit(outInfo), outInfo->GetType(outInfo));
+ retVal = in->SetConnection(in, connection, outInfo->unitString, outInfo->type);
if (RETURN_OK != retVal) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_ERROR, "Connection %s: Setup connection: Could not register with inport", buffer);
mcx_free(buffer);
return RETURN_ERROR;
@@ -501,11 +1362,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn *
}
static Connection * ConnectionCreate(Connection * connection) {
- connection->data = (ConnectionData *) object_create(ConnectionData);
-
- if (!connection->data) {
- return NULL;
- }
+ McxStatus retVal = RETURN_OK;
connection->Setup = NULL;
@@ -513,6 +1370,7 @@ static Connection * ConnectionCreate(Connection * connection) {
connection->GetTarget = ConnectionGetTarget;
connection->GetValueReference = ConnectionGetValueReference;
+ connection->SetValueReference = ConnectionSetValueReference;
connection->GetInfo = ConnectionGetInfo;
@@ -535,6 +1393,27 @@ static Connection * ConnectionCreate(Connection * connection) {
connection->AddFilter = NULL;
+ connection->out_ = NULL;
+ connection->in_ = NULL;
+
+ retVal = ConnectionInfoInit(&connection->info);
+ if (RETURN_ERROR == retVal) {
+ return NULL;
+ }
+
+ connection->value_ = NULL;
+ connection->useInitialValue_ = FALSE;
+
+ connection->isActiveDependency_ = TRUE;
+
+ ChannelValueInit(&connection->store_, CHANNEL_UNKNOWN);
+
+ connection->state_ = InCommunicationMode;
+
+ connection->NormalUpdateFrom_ = NULL;
+ connection->NormalUpdateTo_ = NULL;
+ connection->normalValue_ = NULL;
+
return connection;
}
diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h
index f90ea6c..f4736b9 100644
--- a/src/core/connections/Connection.h
+++ b/src/core/connections/Connection.h
@@ -13,6 +13,7 @@
#include "CentralParts.h"
#include "core/connections/ConnectionInfo.h"
+#include "objects/Vector.h"
#ifdef __cplusplus
extern "C" {
@@ -30,7 +31,7 @@ typedef enum {
InInitializationMode
} ConnectionState;
-McxStatus CheckConnectivity(ObjectContainer * connections);
+McxStatus CheckConnectivity(Vector * connections);
McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInterExtrapolating);
@@ -49,6 +50,7 @@ typedef struct ChannelOut * (* fConnectionGetSource)(Connection * connection);
typedef struct ChannelIn * (* fConnectionGetTarget)(Connection * connection);
typedef void * (* fConnectionGetValueReference)(Connection * connection);
+typedef void (* fConnectionSetValueReference)(Connection * connection, void * reference);
typedef ConnectionInfo * (* fConnectionGetInfo)(Connection * connection);
@@ -74,9 +76,38 @@ typedef McxStatus (* fConnectionAddFilter)(Connection * connection);
extern const struct ObjectClass _Connection;
+
struct Connection {
Object _; // base class
+ // source
+ struct ChannelOut * out_;
+
+ // target
+ struct ChannelIn * in_;
+
+
+ // ----------------------------------------------------------------------
+ // Value on channel
+
+ const void * value_;
+ int useInitialValue_;
+
+ ChannelValue store_;
+
+ int isActiveDependency_;
+
+ // Meta Data
+ ConnectionInfo info;
+
+ // Current state of the connection in state machine
+ ConnectionState state_;
+
+ // Temporary save functions during initialization mode
+ fConnectionUpdateFromInput NormalUpdateFrom_;
+ fConnectionUpdateToOutput NormalUpdateTo_;
+ const void * normalValue_;
+
/**
* Virtual Method.
*
@@ -101,6 +132,12 @@ struct Connection {
*/
fConnectionGetValueReference GetValueReference;
+ /**
+ * Set the reference to the value of the connection. This value will be
+ * updated on each call to UpdateToOutput().
+ */
+ fConnectionSetValueReference SetValueReference;
+
/**
* Returns the connection info struct.
*/
@@ -168,8 +205,6 @@ struct Connection {
fConnectionUpdateInitialValue UpdateInitialValue;
fConnectionAddFilter AddFilter;
-
- struct ConnectionData * data;
} ;
//------------------------------------------------------------------------------
diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c
index ba5ebda..c5e7fba 100644
--- a/src/core/connections/ConnectionInfo.c
+++ b/src/core/connections/ConnectionInfo.c
@@ -9,7 +9,7 @@
********************************************************************************/
#include "core/connections/ConnectionInfo.h"
-#include "core/connections/ConnectionInfo_impl.h"
+#include "core/channels/ChannelInfo.h"
#include "core/Model.h"
#include "core/Databus.h"
@@ -18,215 +18,57 @@
extern "C" {
#endif /* __cplusplus */
-static ConnectionInfoData * ConnectionInfoDataCreate(ConnectionInfoData * data) {
- data->sourceComponent = NULL;
- data->targetComponent = NULL;
- data->sourceChannel = -1;
- data->targetChannel = -1;
- data->isDecoupled = FALSE;
- data->isInterExtrapolating = INTERPOLATING;
-
- data->interExtrapolationType = INTEREXTRAPOLATION_NONE;
- data->interExtrapolationParams = (InterExtrapolationParams *) mcx_malloc(sizeof(InterExtrapolationParams));
- if (!data->interExtrapolationParams) {
- return NULL;
- }
- data->interExtrapolationParams->extrapolationInterval = INTERVAL_SYNCHRONIZATION;
- data->interExtrapolationParams->extrapolationOrder = POLY_CONSTANT;
- data->interExtrapolationParams->interpolationInterval = INTERVAL_COUPLING;
- data->interExtrapolationParams->interpolationOrder = POLY_CONSTANT;
-
- data->decoupleType = DECOUPLE_DEFAULT;
- data->decouplePriority = 0;
-
- data->hasDiscreteTarget = FALSE;
-
- return data;
-}
-
-static void ConnectionInfoDataDestructor(ConnectionInfoData * data) {
- if (data->interExtrapolationParams) {
- mcx_free(data->interExtrapolationParams);
- data->interExtrapolationParams = NULL;
- }
-}
-
-OBJECT_CLASS(ConnectionInfoData, Object);
-
-
-static void ConnectionInfoSet(
- ConnectionInfo * info,
- Component * sourceComponent,
- Component * targetComponent,
- int sourceChannel,
- int targetChannel,
- int isDecoupled,
- InterExtrapolatingType isInterExtrapolating,
- InterExtrapolationType interExtrapolationType,
- InterExtrapolationParams * interExtrapolationParams,
- DecoupleType decoupleType,
- int decouplePriority
-) {
-
- info->data->sourceComponent = sourceComponent;
- info->data->targetComponent = targetComponent;
- info->data->sourceChannel = sourceChannel;
- info->data->targetChannel = targetChannel;
- info->data->isDecoupled = isDecoupled;
- info->data->isInterExtrapolating = isInterExtrapolating;
- info->data->interExtrapolationType = interExtrapolationType;
- info->data->interExtrapolationParams = interExtrapolationParams;
- info->data->decoupleType = decoupleType;
- info->data->decouplePriority = decouplePriority;
-}
-
-static void ConnectionInfoGet(
- ConnectionInfo * info,
- Component ** sourceComponent,
- Component ** targetComponent,
- int * sourceChannel,
- int * targetChannel,
- int * isDecoupled,
- InterExtrapolatingType * isInterExtrapolating,
- InterExtrapolationType * interExtrapolationType,
- InterExtrapolationParams ** interExtrapolationParams,
- DecoupleType * decoupleType,
- int * decouplePriority
-) {
-
- * sourceComponent = info->data->sourceComponent;
- * targetComponent = info->data->targetComponent;
- * sourceChannel = info->data->sourceChannel;
- * targetChannel = info->data->targetChannel;
- * isDecoupled = info->data->isDecoupled;
- * isInterExtrapolating = info->data->isInterExtrapolating;
- * interExtrapolationType = info->data->interExtrapolationType;
- * interExtrapolationParams = info->data->interExtrapolationParams;
- * decoupleType = info->data->decoupleType;
- * decouplePriority = info->data->decouplePriority;
-}
-
-static ConnectionInfo * ConnectionInfoClone(ConnectionInfo * info) {
- ConnectionInfo * clone = (ConnectionInfo *) object_create(ConnectionInfo);
-
- if (!clone) {
- return NULL;
- }
-
- clone->data->sourceComponent = info->data->sourceComponent;
- clone->data->targetComponent = info->data->targetComponent;
-
- clone->data->sourceChannel = info->data->sourceChannel;
- clone->data->targetChannel = info->data->targetChannel;
-
- clone->data->isDecoupled = info->data->isDecoupled;
- clone->data->isInterExtrapolating = info->data->isInterExtrapolating;
-
- clone->data->interExtrapolationType = info->data->interExtrapolationType;
-
- clone->data->interExtrapolationParams->extrapolationInterval = info->data->interExtrapolationParams->extrapolationInterval;
- clone->data->interExtrapolationParams->extrapolationOrder = info->data->interExtrapolationParams->extrapolationOrder;
- clone->data->interExtrapolationParams->interpolationInterval = info->data->interExtrapolationParams->interpolationInterval;
- clone->data->interExtrapolationParams->interpolationOrder = info->data->interExtrapolationParams->interpolationOrder;
-
- clone->data->decoupleType = info->data->decoupleType;
- clone->data->decouplePriority = info->data->decouplePriority;
-
- clone->data->hasDiscreteTarget = info->data->hasDiscreteTarget;
-
- return clone;
-}
-
-static ConnectionInfo * ConnectionInfoCopy(
- ConnectionInfo * info,
- int sourceChannel,
- int targetChannel) {
-
- ConnectionInfo * copy = info->Clone(info);
-
- copy->data->sourceChannel = sourceChannel;
- copy->data->targetChannel = targetChannel;
-
- return copy;
-}
-
-static int ConnectionInfoGetDecouplePriority(ConnectionInfo * info) {
- return info->data->decouplePriority;
-}
-
-static int ConnectionInfoGetSourceChannelID(ConnectionInfo * info) {
- return info->data->sourceChannel;
-}
-
-static int ConnectionInfoGetTargetChannelID(ConnectionInfo * info) {
- return info->data->targetChannel;
+int ConnectionInfoIsDecoupled(ConnectionInfo * info) {
+ return info->isDecoupled_;
}
-static Component * ConnectionInfoGetSourceComponent(ConnectionInfo * info) {
- return info->data->sourceComponent;
+void ConnectionInfoSetDecoupled(ConnectionInfo * info) {
+ info->isDecoupled_ = TRUE;
}
-static Component * ConnectionInfoGetTargetComponent(ConnectionInfo * info) {
- return info->data->targetComponent;
-}
-
-static DecoupleType ConnectionInfoGetDecoupleType(ConnectionInfo * info) {
- return info->data->decoupleType;
-}
-
-static int ConnectionInfoIsDecoupled(ConnectionInfo * info) {
- return info->data->isDecoupled;
-}
-
-static void ConnectionInfoSetDecoupled(ConnectionInfo * info) {
- info->data->isDecoupled = TRUE;
-}
-
-static InterExtrapolatingType ConnectionInfoGetInterExtrapolating(ConnectionInfo * info) {
- return info->data->isInterExtrapolating;
-}
-
-static void ConnectionInfoSetInterExtrapolating(ConnectionInfo * info, InterExtrapolatingType isInterExtrapolating) {
- info->data->isInterExtrapolating = isInterExtrapolating;
-}
-
-static ChannelType ConnectionInfoGetType(ConnectionInfo * info) {
+ChannelType ConnectionInfoGetType(ConnectionInfo * info) {
//Return the data type of the corresponding outport of the source component
Component * source = NULL;
Databus * db = NULL;
ChannelInfo * outInfo = NULL;
+ if (CHANNEL_UNKNOWN != info->connType_) {
+ return info->connType_;
+ }
+
if (NULL == info) {
mcx_log(LOG_DEBUG, "ConnectionInfo: GetType: no info available");
return CHANNEL_UNKNOWN;
}
- source = info->GetSourceComponent(info);
+ source = info->sourceComponent;
if (NULL == source) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no source available", buffer);
mcx_free(buffer);
return CHANNEL_UNKNOWN;
}
db = source->GetDatabus(source);
if (NULL == db) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no databus available", buffer);
mcx_free(buffer);
return CHANNEL_UNKNOWN;
}
- outInfo = DatabusInfoGetChannel(DatabusGetOutInfo(db), info->GetSourceChannelID(info));
+ outInfo = DatabusInfoGetChannel(DatabusGetOutInfo(db), info->sourceChannel);
if (!outInfo) {
- char * buffer = info->ConnectionString(info);
+ char * buffer = ConnectionInfoConnectionString(info);
mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no outinfo available", buffer);
mcx_free(buffer);
return CHANNEL_UNKNOWN;
}
- return outInfo->GetType(outInfo);
+
+ info->connType_ = outInfo->type;
+ return info->connType_;
}
-static char * ConnectionInfoConnectionString(ConnectionInfo * info) {
+char * ConnectionInfoConnectionString(ConnectionInfo * info) {
Component * src = NULL;
Component * trg = NULL;
@@ -250,11 +92,11 @@ static char * ConnectionInfoConnectionString(ConnectionInfo * info) {
return NULL;
}
- src = info->GetSourceComponent(info);
- trg = info->GetTargetComponent(info);
+ src = info->sourceComponent;
+ trg = info->targetComponent;
- srcID = info->GetSourceChannelID(info);
- trgID = info->GetTargetChannelID(info);
+ srcID = info->sourceChannel;
+ trgID = info->targetChannel;
if (!src || !trg) {
@@ -276,9 +118,9 @@ static char * ConnectionInfoConnectionString(ConnectionInfo * info) {
len = strlen("(, ) - (, )")
+ strlen(src->GetName(src))
- + strlen(srcInfo->GetName(srcInfo))
+ + strlen(ChannelInfoGetName(srcInfo))
+ strlen(trg->GetName(trg))
- + strlen(trgInfo->GetName(trgInfo))
+ + strlen(ChannelInfoGetName(trgInfo))
+ 1 /* terminator */;
buffer = (char *) mcx_malloc(len * sizeof(char));
@@ -288,81 +130,39 @@ static char * ConnectionInfoConnectionString(ConnectionInfo * info) {
sprintf(buffer, "(%s, %s) - (%s, %s)",
src->GetName(src),
- srcInfo->GetName(srcInfo),
+ ChannelInfoGetName(srcInfo),
trg->GetName(trg),
- trgInfo->GetName(trgInfo));
+ ChannelInfoGetName(trgInfo));
return buffer;
}
-static InterExtrapolationType ConnectionInfoGetInterExtraType(ConnectionInfo * info) {
- return info->data->interExtrapolationType;
-}
-
-static InterExtrapolationParams * ConnectionInfoGetInterExtraParams(ConnectionInfo * info) {
- return info->data->interExtrapolationParams;
-}
-
-static void ConnectionInfoSetInterExtraType(ConnectionInfo * info, InterExtrapolationType type) {
- info->data->interExtrapolationType = type;
-}
-
-static void ConnectionInfoDestructor(ConnectionInfo * info) {
- object_destroy(info->data);
-}
-
-static int ConnectionHasDiscreteTarget(ConnectionInfo * info) {
- return info->data->hasDiscreteTarget;
-}
-
-static void ConnectionSetDiscreteTarget(ConnectionInfo * info) {
- info->data->hasDiscreteTarget = TRUE;
-}
-
-static ConnectionInfo * ConnectionInfoCreate(ConnectionInfo * info) {
- info->data = (ConnectionInfoData *) object_create(ConnectionInfoData);
-
- if (!info->data) {
- return NULL;
- }
-
- info->Set = ConnectionInfoSet;
- info->Get = ConnectionInfoGet;
-
- info->Clone = ConnectionInfoClone;
- info->Copy = ConnectionInfoCopy;
-
- info->GetSourceChannelID = ConnectionInfoGetSourceChannelID;
- info->GetTargetChannelID = ConnectionInfoGetTargetChannelID;
-
- info->GetSourceComponent = ConnectionInfoGetSourceComponent;
- info->GetTargetComponent = ConnectionInfoGetTargetComponent;
-
- info->GetDecoupleType = ConnectionInfoGetDecoupleType;
- info->GetDecouplePriority = ConnectionInfoGetDecouplePriority;
-
- info->IsDecoupled = ConnectionInfoIsDecoupled;
- info->SetDecoupled = ConnectionInfoSetDecoupled;
+McxStatus ConnectionInfoInit(ConnectionInfo * info) {
+ info->sourceComponent = NULL;
+ info->targetComponent = NULL;
- info->GetInterExtrapolating = ConnectionInfoGetInterExtrapolating;
- info->SetInterExtrapolating = ConnectionInfoSetInterExtrapolating;
+ info->sourceChannel = -1;
+ info->targetChannel = -1;
- info->HasDiscreteTarget = ConnectionHasDiscreteTarget;
- info->SetDiscreteTarget = ConnectionSetDiscreteTarget;
+ info->isDecoupled_ = FALSE;
+ info->isInterExtrapolating = INTERPOLATING;
- info->GetType = ConnectionInfoGetType;
+ info->interExtrapolationType = INTEREXTRAPOLATION_NONE;
+ info->interExtrapolationParams.extrapolationInterval = INTERVAL_SYNCHRONIZATION;
+ info->interExtrapolationParams.extrapolationOrder = POLY_CONSTANT;
+ info->interExtrapolationParams.interpolationInterval = INTERVAL_COUPLING;
+ info->interExtrapolationParams.interpolationOrder = POLY_CONSTANT;
- info->ConnectionString = ConnectionInfoConnectionString;
+ info->decoupleType = DECOUPLE_DEFAULT;
+ info->decouplePriority = 0;
- info->GetInterExtraType = ConnectionInfoGetInterExtraType;
- info->GetInterExtraParams = ConnectionInfoGetInterExtraParams;
+ info->hasDiscreteTarget = FALSE;
- info->SetInterExtraType = ConnectionInfoSetInterExtraType;
+ info->connType_ = CHANNEL_UNKNOWN;
- return info;
+ return RETURN_OK;
}
-OBJECT_CLASS(ConnectionInfo, Object);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/core/connections/ConnectionInfo.h b/src/core/connections/ConnectionInfo.h
index 2c5f492..ec262c9 100644
--- a/src/core/connections/ConnectionInfo.h
+++ b/src/core/connections/ConnectionInfo.h
@@ -1,5 +1,5 @@
/********************************************************************************
- * Copyright (c) 2020 AVL List GmbH and others
+ * Copyright (c) 2022 AVL List GmbH and others
*
* This program and the accompanying materials are made available under the
* terms of the Apache Software License 2.0 which is available at
@@ -11,8 +11,6 @@
#ifndef MCX_CORE_CONNECTIONS_CONNECTIONINFO_H
#define MCX_CORE_CONNECTIONS_CONNECTIONINFO_H
-#include "core/channels/ChannelInfo.h"
-#include "objects/ObjectContainer.h"
#include "CentralParts.h"
#include "core/Component_interface.h"
@@ -22,113 +20,46 @@
extern "C" {
#endif /* __cplusplus */
-// ----------------------------------------------------------------------
-// ConnectionInfo
-struct ConnectionInfo;
-typedef struct ConnectionInfo ConnectionInfo;
+typedef struct Component Component;
-typedef void (*fConnectionInfoSet)(
- ConnectionInfo * info
- , Component * sourceComponent
- , Component * targetComponent
- , int sourceChannel
- , int targetChannel
- , int isDecoupled
- , InterExtrapolatingType isInterExtrapolating
- , InterExtrapolationType interExtrapolationType
- , InterExtrapolationParams * interExtrapolationParams
- , DecoupleType decoupleType
- , int decouplePriority
-);
-typedef void (* fConnectionInfoGet)(
- ConnectionInfo * info
- , Component ** sourceComponent
- , Component ** targetComponent
- , int * sourceChannel
- , int * targetChannel
- , int * isDecoupled
- , InterExtrapolatingType * isInterExtrapolating
- , InterExtrapolationType * interExtrapolationType
- , InterExtrapolationParams ** interExtrapolationParams
- , DecoupleType * decoupleType
- , int * decouplePriority
-);
+typedef struct ConnectionInfo {
+ Component * sourceComponent;
+ Component * targetComponent;
-typedef ConnectionInfo * (* fConnectionInfoClone)(
- ConnectionInfo * info);
+ int sourceChannel;
+ int targetChannel;
-typedef ConnectionInfo * (* fConnectionInfoCopy)(
- ConnectionInfo * info,
- int sourceChannel,
- int targetChannel);
+ // Decouple Info: If this connection is decoupled because of an algebraic loop
+ // in the model (this means that the value of the source for the target is
+ // behind one timestep)
+ int isDecoupled_;
-typedef int (* fConnectionInfoGetChannelID)(ConnectionInfo * info);
+ int hasDiscreteTarget;
-typedef Component * (* fConnectionInfoGetSourceComponent)(ConnectionInfo * info);
-typedef Component * (* fConnectionInfoGetTargetComponent)(ConnectionInfo * info);
+ ChannelType connType_;
-typedef DecoupleType (* fConnectionInfoGetDecoupleType)(ConnectionInfo * info);
+ InterExtrapolatingType isInterExtrapolating;
-typedef ChannelType (* fConnectionInfoGetType)(ConnectionInfo * info);
+ InterExtrapolationType interExtrapolationType;
+ InterExtrapolationParams interExtrapolationParams;
-typedef int (* fConnectionInfoGetBool)(ConnectionInfo * info);
-typedef int (* fConnectionInfoGetInt)(ConnectionInfo * info);
-typedef InterExtrapolatingType (* fConnectionInfoGetInterExtrapolating)(ConnectionInfo * info);
+ DecoupleType decoupleType;
+ int decouplePriority;
-typedef void (* fConnectionInfoSetVoid)(ConnectionInfo * info);
-typedef void (* fConnectionInfoSetInterExtrapolating)(ConnectionInfo * info, InterExtrapolatingType isInterExtrapolating);
-typedef char * (* fConnectionInfoConnectionString)(ConnectionInfo * info);
+} ConnectionInfo;
-typedef InterExtrapolationType (* fConnectionInfoGetInterExtraType)(ConnectionInfo * info);
-typedef InterExtrapolationParams * (* fConnectionInfoGetInterExtraParams)(ConnectionInfo * info);
-typedef void (* fConnectionInfoSetInterExtraType)(ConnectionInfo * info, InterExtrapolationType type);
+McxStatus ConnectionInfoInit(ConnectionInfo * info);
-typedef int (*fConnectionHasDiscreteTarget)(ConnectionInfo * info);
-typedef void (*fConnectionSetDiscreteTarget)(ConnectionInfo * info);
-extern const struct ObjectClass _ConnectionInfo;
+ChannelType ConnectionInfoGetType(ConnectionInfo * info);
-struct ConnectionInfo {
- Object _; // base class
+int ConnectionInfoIsDecoupled(ConnectionInfo * info);
+void ConnectionInfoSetDecoupled(ConnectionInfo * info);
- fConnectionInfoSet Set;
- fConnectionInfoGet Get;
-
- fConnectionInfoClone Clone;
- fConnectionInfoCopy Copy;
-
- fConnectionInfoGetChannelID GetSourceChannelID;
- fConnectionInfoGetChannelID GetTargetChannelID;
-
- fConnectionInfoGetSourceComponent GetSourceComponent;
- fConnectionInfoGetTargetComponent GetTargetComponent;
-
- fConnectionInfoGetDecoupleType GetDecoupleType;
- fConnectionInfoGetInt GetDecouplePriority;
-
- fConnectionInfoGetBool IsDecoupled;
- fConnectionInfoSetVoid SetDecoupled;
-
- fConnectionInfoGetInterExtrapolating GetInterExtrapolating;
- fConnectionInfoSetInterExtrapolating SetInterExtrapolating;
-
- fConnectionHasDiscreteTarget HasDiscreteTarget;
- fConnectionSetDiscreteTarget SetDiscreteTarget;
-
- fConnectionInfoGetType GetType;
-
- fConnectionInfoConnectionString ConnectionString;
-
- fConnectionInfoGetInterExtraType GetInterExtraType;
- fConnectionInfoGetInterExtraParams GetInterExtraParams;
-
- fConnectionInfoSetInterExtraType SetInterExtraType;
-
- struct ConnectionInfoData * data;
-} ;
+char * ConnectionInfoConnectionString(ConnectionInfo * info);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c
index c963d10..6de46c3 100644
--- a/src/core/connections/ConnectionInfoFactory.c
+++ b/src/core/connections/ConnectionInfoFactory.c
@@ -11,6 +11,7 @@
#include "core/connections/ConnectionInfoFactory.h"
#include "core/connections/ConnectionInfo.h"
#include "core/Databus.h"
+#include "objects/Vector.h"
#include "util/string.h"
@@ -18,214 +19,190 @@
extern "C" {
#endif /* __cplusplus */
-static ConnectionInfo * ConnectionInfoFactoryCreateConnectionInfo(ObjectContainer * components,
- ConnectionInput * connInput,
- Component * sourceCompOverride,
- Component * targetCompOverride) {
- McxStatus retVal = RETURN_OK;
- ConnectionInfo * info = NULL;
- Component * sourceComp = NULL;
- Component * targetComp = NULL;
+static McxStatus ConnectionInfoFactoryInitConnectionInfo(
+ ConnectionInfo * info,
+ ObjectContainer * components,
+ ConnectionInput * connInput,
+ Component * sourceCompOverride,
+ Component * targetCompOverride)
+{
+ McxStatus retVal = RETURN_OK;
- int sourceChannel = 0;
- int targetChannel = 0;
int id = 0;
-
int connectionInverted = 0;
+ char * strToChannel = NULL;
+ char * strFromChannel = NULL;
- int isDecoupled = FALSE;
- InterExtrapolatingType isInterExtrapolating = INTERPOLATING;
-
- InterExtrapolationType interExtrapolationType;
- InterExtrapolationParams * interExtrapolationParams = NULL;
-
- DecoupleType decoupleType;
- int decouplePriority = 0;
+ retVal = ConnectionInfoInit(info);
+ if (retVal == RETURN_ERROR) {
+ mcx_log(LOG_ERROR, "Initializing the ConnectionInfo object failed");
+ goto cleanup;
+ }
- // temporary data for reading not used in info->Set()
- char * strFromChannel = NULL;
- char * strToChannel = NULL;
+ // source component
+ {
+ // use conn endpoints from caller if they are not in components
+ info->sourceComponent = sourceCompOverride;
+
+ if (info->sourceComponent == NULL) {
+ char * inputFromComponent = connInput->fromType == ENDPOINT_SCALAR ? connInput->from.scalarEndpoint->component :
+ connInput->from.vectorEndpoint->component;
+ if (inputFromComponent == NULL) {
+ retVal = input_element_error((InputElement*)connInput, "Source element is not specified");
+ goto cleanup;
+ }
- // weak pointers to endpoint data
- char * inputToChannel = NULL;
- char * inputToComponent = NULL;
- char * inputFromChannel = NULL;
- char * inputFromComponent = NULL;
+ if (0 == strlen(inputFromComponent)) {
+ retVal = input_element_error((InputElement*)connInput, "Source element name is empty");
+ goto cleanup;
+ }
- Databus * databus = NULL;
- DatabusInfo * databusInfo = NULL;
+ id = components->GetNameIndex(components, inputFromComponent);
+ if (id < 0) {
+ retVal = input_element_error((InputElement*)connInput, "Source element %s does not exist",
+ inputFromComponent);
+ goto cleanup;
+ }
- info = (ConnectionInfo *)object_create(ConnectionInfo);
- if (NULL == info) {
- return NULL;
+ info->sourceComponent = (Component *) components->elements[id];
+ }
}
- // get default values
- info->Get(
- info,
- &sourceComp,
- &targetComp,
- &sourceChannel,
- &targetChannel,
- &isDecoupled,
- &isInterExtrapolating,
- &interExtrapolationType,
- &interExtrapolationParams,
- &decoupleType,
- &decouplePriority
- );
-
- // use conn endpoints from caller if they are not in components
- sourceComp = sourceCompOverride;
- targetComp = targetCompOverride;
+ // target component
+ {
+ // use conn endpoints from caller if they are not in components
+ info->targetComponent = targetCompOverride;
+
+ if (info->targetComponent == NULL) {
+ char * inputToComponent = connInput->toType == ENDPOINT_SCALAR ? connInput->to.scalarEndpoint->component :
+ connInput->to.vectorEndpoint->component;
+ if (inputToComponent == NULL) {
+ retVal = input_element_error((InputElement*)connInput, "Target element is not specified");
+ goto cleanup;
+ }
- // source component
- if (sourceComp == NULL) {
- inputFromComponent = connInput->fromType == ENDPOINT_SCALAR ? connInput->from.scalarEndpoint->component :
- connInput->from.vectorEndpoint->component;
- if (inputFromComponent == NULL) {
- retVal = input_element_error((InputElement*)connInput, "Source element is not specified");
- goto cleanup;
- }
+ if (0 == strlen(inputToComponent)) {
+ retVal = input_element_error((InputElement*)connInput, "Target element name is empty");
+ goto cleanup;
+ }
- if (0 == strlen(inputFromComponent)) {
- retVal = input_element_error((InputElement*)connInput, "Source element name is empty");
- goto cleanup;
- }
+ id = components->GetNameIndex(components, inputToComponent);
+ if (id < 0) {
+ retVal = input_element_error((InputElement*)connInput, "Target element %s does not exist",
+ inputToComponent);
+ goto cleanup;
+ }
- id = components->GetNameIndex(components, inputFromComponent);
- if (id < 0) {
- retVal = input_element_error((InputElement*)connInput, "Source element %s does not exist",
- inputFromComponent);
- goto cleanup;
+ info->targetComponent = (Component *) components->elements[id];
}
-
- sourceComp = (Component *) components->elements[id];
}
// source channel
- inputFromChannel = connInput->fromType == ENDPOINT_SCALAR ? connInput->from.scalarEndpoint->channel :
- connInput->from.vectorEndpoint->channel;
- strFromChannel = mcx_string_copy(inputFromChannel);
- if (0 == strlen(strFromChannel)) {
- retVal = input_element_error((InputElement*)connInput, "Source port name is empty");
- goto cleanup;
- }
-
- if (connInput->fromType == ENDPOINT_VECTOR) {
- mcx_free(strFromChannel);
- strFromChannel = CreateIndexedName(inputFromChannel, connInput->from.vectorEndpoint->startIndex);
- if (!strFromChannel) {
- retVal = RETURN_ERROR;
+ {
+ Databus * databus = info->sourceComponent->GetDatabus(info->sourceComponent);
+ DatabusInfo * databusInfo = DatabusGetOutInfo(databus);
+
+ char * inputFromChannel = connInput->fromType == ENDPOINT_SCALAR ? connInput->from.scalarEndpoint->channel :
+ connInput->from.vectorEndpoint->channel;
+ strFromChannel = mcx_string_copy(inputFromChannel);
+ if (0 == strlen(strFromChannel)) {
+ retVal = input_element_error((InputElement*)connInput, "Source port name is empty");
goto cleanup;
}
- }
- // target component
- if (targetComp == NULL) {
- inputToComponent = connInput->toType == ENDPOINT_SCALAR ? connInput->to.scalarEndpoint->component :
- connInput->to.vectorEndpoint->component;
- if (inputToComponent == NULL) {
- retVal = input_element_error((InputElement*)connInput, "Target element is not specified");
- goto cleanup;
+ if (connInput->fromType == ENDPOINT_VECTOR) {
+ mcx_free(strFromChannel);
+ strFromChannel = CreateIndexedName(inputFromChannel, connInput->from.vectorEndpoint->startIndex);
+ if (!strFromChannel) {
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
}
- if (0 == strlen(inputToComponent)) {
- retVal = input_element_error((InputElement*)connInput, "Target element name is empty");
- goto cleanup;
- }
+ info->sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel);
+ if (info->sourceChannel < 0) {
+ // the connection might be inverted, see SSP 1.0 specification (section 5.3.2.1, page 47)
- id = components->GetNameIndex(components, inputToComponent);
- if (id < 0) {
- retVal = input_element_error((InputElement*)connInput, "Target element %s does not exist",
- inputToComponent);
- goto cleanup;
- }
+ databusInfo = DatabusGetInInfo(databus);
+ info->sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel);
- targetComp = (Component *) components->elements[id];
+ if (info->sourceChannel < 0) {
+ mcx_log(LOG_ERROR, "Connection: Source port %s of element %s does not exist",
+ strFromChannel, info->sourceComponent->GetName(info->sourceComponent));
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ } else {
+ connectionInverted = 1;
+ }
+ }
}
// target channel
- inputToChannel = connInput->toType == ENDPOINT_SCALAR ? connInput->to.scalarEndpoint->channel :
- connInput->to.vectorEndpoint->channel;
- strToChannel = mcx_string_copy(inputToChannel);
- if (0 == strlen(strToChannel)) {
- retVal = input_element_error((InputElement*)connInput, "Target port name is empty");
- goto cleanup;
- }
-
- if (connInput->toType == ENDPOINT_VECTOR) {
- mcx_free(strToChannel);
- strToChannel = CreateIndexedName(inputToChannel, connInput->to.vectorEndpoint->startIndex);
- if (!strToChannel) {
- retVal = RETURN_ERROR;
+ {
+ Databus * databus = info->targetComponent->GetDatabus(info->targetComponent);
+ DatabusInfo * databusInfo = NULL;
+
+ char * inputToChannel = connInput->toType == ENDPOINT_SCALAR ? connInput->to.scalarEndpoint->channel :
+ connInput->to.vectorEndpoint->channel;
+ strToChannel = mcx_string_copy(inputToChannel);
+ if (0 == strlen(strToChannel)) {
+ retVal = input_element_error((InputElement*)connInput, "Target port name is empty");
goto cleanup;
}
- }
-
- databus = sourceComp->GetDatabus(sourceComp);
- databusInfo = DatabusGetOutInfo(databus);
- sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel);
- if (sourceChannel < 0) {
- // the connection might be inverted, see SSP 1.0 specification (section 5.3.2.1, page 47)
-
- databusInfo = DatabusGetInInfo(databus);
- sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel);
- if (sourceChannel < 0) {
- mcx_log(LOG_ERROR, "Connection: Source port %s of element %s does not exist",
- strFromChannel, sourceComp->GetName(sourceComp));
- retVal = RETURN_ERROR;
- goto cleanup;
- } else {
- connectionInverted = 1;
+ if (connInput->toType == ENDPOINT_VECTOR) {
+ mcx_free(strToChannel);
+ strToChannel = CreateIndexedName(inputToChannel, connInput->to.vectorEndpoint->startIndex);
+ if (!strToChannel) {
+ retVal = RETURN_ERROR;
+ goto cleanup;
+ }
}
- }
-
- databus = targetComp->GetDatabus(targetComp);
-
- if (0 == connectionInverted) {
- databusInfo = DatabusGetInInfo(databus);
- } else {
- databusInfo = DatabusGetOutInfo(databus);
- }
- targetChannel = DatabusInfoGetChannelID(databusInfo, strToChannel);
- if (targetChannel < 0) {
if (0 == connectionInverted) {
- mcx_log(LOG_ERROR, "Connection: Target port %s of element %s does not exist",
- strToChannel, targetComp->GetName(targetComp));
+ databusInfo = DatabusGetInInfo(databus);
} else {
- mcx_log(LOG_ERROR, "Connection: Source port %s of element %s does not exist",
- strToChannel, targetComp->GetName(targetComp));
+ databusInfo = DatabusGetOutInfo(databus);
+ }
+
+ info->targetChannel = DatabusInfoGetChannelID(databusInfo, strToChannel);
+ if (info->targetChannel < 0) {
+ if (0 == connectionInverted) {
+ mcx_log(LOG_ERROR, "Connection: Target port %s of element %s does not exist",
+ strToChannel, info->targetComponent->GetName(info->targetComponent));
+ } else {
+ mcx_log(LOG_ERROR, "Connection: Source port %s of element %s does not exist",
+ strToChannel, info->targetComponent->GetName(info->targetComponent));
+ }
+ retVal = RETURN_ERROR;
+ goto cleanup;
}
- retVal = RETURN_ERROR;
- goto cleanup;
}
+ // swap endpoints if connection is inverted
if (connectionInverted) {
- int tmp = sourceChannel;
- Component * tmpCmp = sourceComp;
+ int tmp = info->sourceChannel;
+ Component * tmpCmp = info->sourceComponent;
- sourceChannel = targetChannel;
- targetChannel = tmp;
+ info->sourceChannel = info->targetChannel;
+ info->targetChannel = tmp;
- sourceComp = targetComp;
- targetComp = tmpCmp;
+ info->sourceComponent = info->targetComponent;
+ info->targetComponent = tmpCmp;
mcx_log(LOG_DEBUG, "Connection: Inverted connection (%s, %s) -- (%s, %s)",
- targetComp->GetName(targetComp), strFromChannel, sourceComp->GetName(sourceComp), strToChannel);
+ info->targetComponent->GetName(info->targetComponent), strFromChannel, info->sourceComponent->GetName(info->sourceComponent), strToChannel);
}
// extrapolation
if (connInput->interExtrapolationType.defined) {
- interExtrapolationType = connInput->interExtrapolationType.value;
+ info->interExtrapolationType = connInput->interExtrapolationType.value;
}
- if (INTEREXTRAPOLATION_POLYNOMIAL == interExtrapolationType) {
+ if (INTEREXTRAPOLATION_POLYNOMIAL == info->interExtrapolationType) {
// read the parameters of poly inter-/extrapolation
- InterExtrapolationParams * params = interExtrapolationParams;
+ InterExtrapolationParams * params = &info->interExtrapolationParams;
InterExtrapolationInput * paramsInput = connInput->interExtrapolation;
params->extrapolationInterval = paramsInput->extrapolationType;
@@ -236,59 +213,49 @@ static ConnectionInfo * ConnectionInfoFactoryCreateConnectionInfo(ObjectContaine
// decouple
if (connInput->decoupleType.defined) {
- decoupleType = connInput->decoupleType.value;
+ info->decoupleType = connInput->decoupleType.value;
// decouple priority
- if (DECOUPLE_IFNEEDED == decoupleType) {
+ if (DECOUPLE_IFNEEDED == info->decoupleType) {
DecoupleIfNeededInput * decoupleInput = (DecoupleIfNeededInput*)connInput->decoupleSettings;
if (decoupleInput->priority.defined) {
- decouplePriority = decoupleInput->priority.value;
+ info->decouplePriority = decoupleInput->priority.value;
}
- if (decouplePriority < 0) {
+ if (info->decouplePriority < 0) {
retVal = input_element_error((InputElement*)decoupleInput, "Invalid decouple priority");
goto cleanup;
}
}
}
- info->Set(
- info,
- sourceComp,
- targetComp,
- sourceChannel,
- targetChannel,
- isDecoupled,
- isInterExtrapolating,
- interExtrapolationType,
- interExtrapolationParams,
- decoupleType,
- decouplePriority
- );
-
cleanup:
- if (RETURN_ERROR == retVal) { object_destroy(info); }
if (NULL != strFromChannel) { mcx_free(strFromChannel); }
if (NULL != strToChannel) { mcx_free(strToChannel); }
- return info;
+ return retVal;
}
-ObjectContainer * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * components,
- ConnectionInput * connInput,
- Component * sourceCompOverride,
- Component * targetCompOverride) {
- ConnectionInfo * info = NULL;
- ObjectContainer * list = NULL;
+Vector * ConnectionInfoFactoryCreateConnectionInfos(
+ ObjectContainer * components,
+ ConnectionInput * connInput,
+ Component * sourceCompOverride,
+ Component * targetCompOverride)
+{
+ McxStatus retVal = RETURN_OK;
- list = (ObjectContainer *) object_create(ObjectContainer);
+ ConnectionInfo info = { 0 };
+ Vector * list = NULL;
+
+ list = (Vector *) object_create(Vector);
if (!list) {
goto cleanup;
}
- info = ConnectionInfoFactoryCreateConnectionInfo(components, connInput,
- sourceCompOverride, targetCompOverride);
- if (!info) {
+ list->Setup(list, sizeof(ConnectionInfo), ConnectionInfoInit, NULL, NULL);
+
+ retVal = ConnectionInfoFactoryInitConnectionInfo(&info, components, connInput, sourceCompOverride, targetCompOverride);
+ if (RETURN_ERROR == retVal) {
goto cleanup;
}
@@ -301,8 +268,8 @@ ObjectContainer * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * c
int toEndIndex = connInput->toType == ENDPOINT_VECTOR ? connInput->to.vectorEndpoint->endIndex : 0;
int i = 0;
- int fromStart = info->GetSourceChannelID(info);
- int toStart = info->GetTargetChannelID(info);
+ int fromStart = info.sourceChannel;
+ int toStart = info.targetChannel;
if (fromEndIndex - fromStartIndex != toEndIndex - toStartIndex) {
/* the lenghts of both sides do not match */
@@ -311,27 +278,25 @@ ObjectContainer * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * c
}
for (i = 0; fromStartIndex + i <= fromEndIndex; i++) {
- ConnectionInfo * copy = info->Copy(info, fromStart + i, toStart + i);
- if (!copy) {
- goto cleanup;
- }
- list->PushBack(list, (Object *) copy);
- }
+ ConnectionInfo * copy = NULL;
- object_destroy(info);
+ list->PushBack(list, &info);
+ copy = (ConnectionInfo *) list->At(list, list->Size(list) - 1);
+ copy->sourceChannel = fromStart + i;
+ copy->targetChannel = toStart + i;
+ }
} else {
/* info is the only connection: leave as is */
- list->PushBack(list, (Object *) info);
+ list->PushBack(list, &info);
}
return list;
cleanup:
if (list) {
- list->DestroyObjects(list);
object_destroy(list);
}
- if (info) { object_destroy(info); }
+
return NULL;
}
diff --git a/src/core/connections/ConnectionInfoFactory.h b/src/core/connections/ConnectionInfoFactory.h
index 2c3e22b..5881b14 100644
--- a/src/core/connections/ConnectionInfoFactory.h
+++ b/src/core/connections/ConnectionInfoFactory.h
@@ -14,15 +14,18 @@
#include "objects/ObjectContainer.h"
#include "reader/model/connections/ConnectionInput.h"
#include "core/Component_interface.h"
+#include "objects/Vector.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-ObjectContainer * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * components,
- ConnectionInput * connInput,
- Component * sourceCompOverride,
- Component * targetCompOverride);
+
+Vector * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * components,
+ ConnectionInput * connInput,
+ Component * sourceCompOverride,
+ Component * targetCompOverride);
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/core/connections/ConnectionInfo_impl.h b/src/core/connections/ConnectionInfo_impl.h
deleted file mode 100644
index e2a35c9..0000000
--- a/src/core/connections/ConnectionInfo_impl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/********************************************************************************
- * Copyright (c) 2020 AVL List GmbH and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Apache Software License 2.0 which is available at
- * https://www.apache.org/licenses/LICENSE-2.0.
- *
- * SPDX-License-Identifier: Apache-2.0
- ********************************************************************************/
-
-#ifndef MCX_CORE_CONNECTIONS_CONNECTIONINFO_IMPL_H
-#define MCX_CORE_CONNECTIONS_CONNECTIONINFO_IMPL_H
-
-/* for interExtrapolation, DecoupleType */
-#include "CentralParts.h"
-
-/* for ChannelType */
-#include "core/channels/ChannelValue.h"
-
-/* for Component */
-#include "core/Component.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-// ----------------------------------------------------------------------
-// ConnectionInfo
-
-extern const struct ObjectClass _ConnectionInfoData;
-
-typedef struct ConnectionInfoData {
- Object _;
-
- struct Component * sourceComponent;
- struct Component * targetComponent;
-
- int sourceChannel;
- int targetChannel;
-
- // Decouple Info: If this connection is decoupled because of an algebraic loop
- // in the model (this means that the value of the source for the target is
- // behind one timestep)
- int isDecoupled;
-
- InterExtrapolatingType isInterExtrapolating;
-
- InterExtrapolationType interExtrapolationType;
- InterExtrapolationParams * interExtrapolationParams;
-
- DecoupleType decoupleType;
- int decouplePriority;
-
- int hasDiscreteTarget;
-
-} ConnectionInfoData;
-
-#ifdef __cplusplus
-} /* closing brace for extern "C" */
-#endif /* __cplusplus */
-
-#endif /* MCX_CORE_CONNECTIONS_CONNECTIONINFO_IMPL_H */
\ No newline at end of file
diff --git a/src/core/connections/Connection_impl.h b/src/core/connections/Connection_impl.h
deleted file mode 100644
index 9facd50..0000000
--- a/src/core/connections/Connection_impl.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/********************************************************************************
- * Copyright (c) 2020 AVL List GmbH and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Apache Software License 2.0 which is available at
- * https://www.apache.org/licenses/LICENSE-2.0.
- *
- * SPDX-License-Identifier: Apache-2.0
- ********************************************************************************/
-
-#ifndef MCX_CORE_CONNECTIONS_CONNECTION_IMPL_H
-#define MCX_CORE_CONNECTIONS_CONNECTION_IMPL_H
-
-// for ExtrapolType
-#include "core/connections/filters/Filter.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-// ----------------------------------------------------------------------
-// Connection
-
-// provides information about the connection between
-// the input channel it is stored in and the output channel
-// that the input channel is connected to
-
-extern const struct ObjectClass _ConnectionData;
-
-typedef struct ConnectionData {
- Object _; // base class
-
- // ----------------------------------------------------------------------
- // Structural Information
-
- // source
- struct ChannelOut * out;
-
- // target
- struct ChannelIn * in;
-
-
- // ----------------------------------------------------------------------
- // Value on channel
-
- const void * value;
- int useInitialValue;
-
- ChannelValue store;
-
- int isActiveDependency;
-
- // Meta Data
- ConnectionInfo * info;
-
- // Current state of the connection in state machine
- ConnectionState state;
-
- // Temporary save functions during initialization mode
- fConnectionUpdateFromInput NormalUpdateFrom;
- fConnectionUpdateToOutput NormalUpdateTo;
- const void * normalValue;
-} ConnectionData;
-
-#ifdef __cplusplus
-} /* closing brace for extern "C" */
-#endif /* __cplusplus */
-
-#endif /* MCX_CORE_CONNECTIONS_CONNECTION_IMPL_H */
\ No newline at end of file
diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c
index 57cd8a3..79aa80a 100644
--- a/src/core/connections/FilteredConnection.c
+++ b/src/core/connections/FilteredConnection.c
@@ -11,9 +11,9 @@
#include "core/connections/FilteredConnection.h"
#include "core/connections/FilteredConnection_impl.h"
#include "core/connections/Connection.h"
-#include "core/connections/Connection_impl.h"
#include "core/connections/ConnectionInfo.h"
#include "core/channels/Channel.h"
+#include "core/channels/ChannelInfo.h"
#include "core/connections/filters/DiscreteFilter.h"
#ifdef __cplusplus
@@ -40,14 +40,14 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o
ChannelIn * in, ConnectionInfo * info) {
FilteredConnection * filteredConnection = (FilteredConnection *) connection;
- ChannelInfo * sourceInfo = ((Channel *)out)->GetInfo((Channel *) out);
- ChannelInfo * targetInfo = ((Channel *)in)->GetInfo((Channel *) in);
+ ChannelInfo * sourceInfo = &((Channel *)out)->info;
+ ChannelInfo * targetInfo = &((Channel *)in)->info;
McxStatus retVal = RETURN_OK;
// Decoupling
- if (DECOUPLE_ALWAYS == info->GetDecoupleType(info)) {
- info->SetDecoupled(info);
+ if (DECOUPLE_ALWAYS == info->decoupleType) {
+ ConnectionInfoSetDecoupled(info);
}
// filter will be added after model is connected
@@ -57,7 +57,7 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o
ChannelValueInit(&filteredConnection->data->store, sourceInfo->type);
// value reference
- connection->data->value = ChannelValueReference(&filteredConnection->data->store);
+ connection->value_ = ChannelValueReference(&filteredConnection->data->store);
// Connection::Setup()
@@ -85,7 +85,7 @@ static McxStatus FilteredConnectionEnterCommunicationMode(Connection * connectio
}
}
- connection->data->state = InCommunicationMode;
+ connection->state_ = InCommunicationMode;
return RETURN_OK;
}
@@ -106,7 +106,7 @@ static McxStatus FilteredConnectionEnterCouplingStepMode(Connection * connection
}
}
- connection->data->state = InCouplingStepMode;
+ connection->state_ = InCouplingStepMode;
return RETURN_OK;
}
@@ -122,12 +122,11 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter
FilteredConnection * filteredConnection = (FilteredConnection *) connection;
ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection);
Channel * channel = (Channel *) connection->GetSource(connection);
- ChannelInfo * info = channel->GetInfo(channel);
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- ChannelInfo * info = channel->GetInfo(channel);
- MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateFromInput", time->startTime, info->GetName(info));
+ ChannelInfo * info = &channel->info;
+ MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info));
}
#endif
@@ -145,12 +144,10 @@ static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterv
Channel * channel = (Channel *) connection->GetSource(connection);
ChannelOut * out = (ChannelOut *) channel;
- ChannelInfo * info = channel->GetInfo(channel);
-
#ifdef MCX_DEBUG
if (time->startTime < MCX_DEBUG_LOG_TIME) {
- ChannelInfo * info = channel->GetInfo(channel);
- MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateToOutput", time->startTime, info->GetName(info));
+ ChannelInfo * info = &channel->info;
+ MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info));
}
#endif
diff --git a/src/core/connections/filters/IntExtFilter.c b/src/core/connections/filters/IntExtFilter.c
index 00ee864..37d61d9 100644
--- a/src/core/connections/filters/IntExtFilter.c
+++ b/src/core/connections/filters/IntExtFilter.c
@@ -104,8 +104,8 @@ static McxStatus IntExtFilterEnterCommunicationMode(ChannelFilter * filter, doub
return RETURN_OK;
}
-static McxStatus IntExtFilterSetup(IntExtFilter * intExtFilter, int degreeExtrapolation, int degreeInterpolation) {
- if (RETURN_ERROR == intExtFilter->filterInt->Setup(intExtFilter->filterInt, degreeInterpolation)) {
+static McxStatus IntExtFilterSetup(IntExtFilter * intExtFilter, int degreeExtrapolation, int degreeInterpolation, size_t buffSize) {
+ if (RETURN_ERROR == intExtFilter->filterInt->Setup(intExtFilter->filterInt, degreeInterpolation, buffSize)) {
mcx_log(LOG_ERROR, "Connection: IntExtFilter: Setup of interpolation filter failed");
return RETURN_ERROR;
}
diff --git a/src/core/connections/filters/IntExtFilter.h b/src/core/connections/filters/IntExtFilter.h
index 571d956..3b9e758 100644
--- a/src/core/connections/filters/IntExtFilter.h
+++ b/src/core/connections/filters/IntExtFilter.h
@@ -22,7 +22,7 @@ extern "C" {
typedef struct IntExtFilter IntExtFilter;
-typedef McxStatus (* fIntExtFilterSetup)(IntExtFilter * intExtFilter, int degreeExtrapolation, int degreeInterpolation);
+typedef McxStatus (* fIntExtFilterSetup)(IntExtFilter * intExtFilter, int degreeExtrapolation, int degreeInterpolation, size_t buffSize);
extern const struct ObjectClass _IntExtFilter;
diff --git a/src/core/connections/filters/IntFilter.c b/src/core/connections/filters/IntFilter.c
index 1b399a3..08de7c2 100644
--- a/src/core/connections/filters/IntFilter.c
+++ b/src/core/connections/filters/IntFilter.c
@@ -165,7 +165,7 @@ static McxStatus IntFilterEnterCommunicationMode(ChannelFilter * filter, double
return RETURN_OK;
}
-static McxStatus IntFilterSetup(IntFilter * intFilter, int degree){
+static McxStatus IntFilterSetup(IntFilter * intFilter, int degree, size_t buffSize){
ChannelFilter * filter = (ChannelFilter *) intFilter;
mcx_table_interp_type intType = MCX_TABLE_INTERP_NOT_SET;
@@ -173,6 +173,28 @@ static McxStatus IntFilterSetup(IntFilter * intFilter, int degree){
int ret = 0;
+ if (buffSize == 0) {
+ mcx_log(LOG_ERROR, "IntFilter: Buffer size %zu not supported", buffSize);
+ return RETURN_ERROR;
+ }
+
+ intFilter->dataLen = buffSize;
+
+ intFilter->read_x_data = (double*)mcx_malloc(intFilter->dataLen * sizeof(double));
+ intFilter->read_y_data = (double*)mcx_malloc(intFilter->dataLen * sizeof(double));
+
+ intFilter->write_x_data = (double*)mcx_malloc(intFilter->dataLen * sizeof(double));
+ intFilter->write_y_data = (double*)mcx_malloc(intFilter->dataLen * sizeof(double));
+
+ if (!intFilter->read_x_data ||
+ !intFilter->read_y_data ||
+ !intFilter->write_x_data ||
+ !intFilter->write_y_data)
+ {
+ mcx_log(LOG_ERROR, "IntFilter: Buffer allocation failed");
+ return RETURN_ERROR;
+ }
+
intFilter->couplingPolyDegree = degree;
switch (degree) {
@@ -201,11 +223,11 @@ static McxStatus IntFilterSetup(IntFilter * intFilter, int degree){
static void IntFilterDestructor(IntFilter * filter){
mcx_interp_free_table(filter->T);
- mcx_free(filter->read_x_data);
- mcx_free(filter->read_y_data);
+ if (filter->read_x_data) { mcx_free(filter->read_x_data); }
+ if (filter->read_y_data) { mcx_free(filter->read_y_data); }
- mcx_free(filter->write_x_data);
- mcx_free(filter->write_y_data);
+ if (filter->write_x_data) { mcx_free(filter->write_x_data); }
+ if (filter->write_y_data) { mcx_free(filter->write_y_data); }
}
static IntFilter * IntFilterCreate(IntFilter * intFilter){
@@ -226,14 +248,13 @@ static IntFilter * IntFilterCreate(IntFilter * intFilter){
intFilter->T = mcx_interp_new_table();
- /* this is just a generous heuristic value */
- intFilter->dataLen = 1000;
+ intFilter->dataLen = 0;
- intFilter->read_x_data = (double *) mcx_malloc(intFilter->dataLen * sizeof(double));
- intFilter->read_y_data = (double *) mcx_malloc(intFilter->dataLen * sizeof(double));
+ intFilter->read_x_data = NULL;
+ intFilter->read_y_data = NULL;
- intFilter->write_x_data = (double *) mcx_malloc(intFilter->dataLen * sizeof(double));
- intFilter->write_y_data = (double *) mcx_malloc(intFilter->dataLen * sizeof(double));
+ intFilter->write_x_data = NULL;
+ intFilter->write_y_data = NULL;
return intFilter;
}
diff --git a/src/core/connections/filters/IntFilter.h b/src/core/connections/filters/IntFilter.h
index 74d5052..d847a5c 100644
--- a/src/core/connections/filters/IntFilter.h
+++ b/src/core/connections/filters/IntFilter.h
@@ -22,7 +22,7 @@ extern "C" {
typedef struct IntFilter IntFilter;
-typedef McxStatus (* fIntFilterSetup)(IntFilter * filter, int degree);
+typedef McxStatus (* fIntFilterSetup)(IntFilter * filter, int degree, size_t buffSize);
extern const struct ObjectClass _IntFilter;
diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c
new file mode 100644
index 0000000..b4fddd0
--- /dev/null
+++ b/src/core/connections/filters/MemoryFilter.c
@@ -0,0 +1,331 @@
+/********************************************************************************
+ * Copyright (c) 2022 AVL List GmbH and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Apache Software License 2.0 which is available at
+ * https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ********************************************************************************/
+
+#include "core/connections/filters/MemoryFilter.h"
+
+#include "util/compare.h"
+
+#include
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t) (-1))
+#endif // !SIZE_MAX
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+static McxStatus MemoryFilterSetValue(ChannelFilter * filter, double time, ChannelValueData value) {
+ MemoryFilter * memoryFilter = (MemoryFilter *) filter;
+
+ if (InCommunicationMode != * filter->state) {
+ if (memoryFilter->numEntriesWrite >= memoryFilter->historySize) {
+ mcx_log(LOG_ERROR, "MemoryFilter: History buffer too small");
+ return RETURN_ERROR;
+ }
+
+ ChannelValueSetFromReference(memoryFilter->valueHistoryWrite + memoryFilter->numEntriesWrite, &value);
+ memoryFilter->timeHistoryWrite[memoryFilter->numEntriesWrite] = time;
+ memoryFilter->numEntriesWrite++;
+
+#ifdef MCX_DEBUG
+ if (time < MCX_DEBUG_LOG_TIME) {
+ if (memoryFilter->valueHistoryWrite[0].type == CHANNEL_DOUBLE) {
+ MCX_DEBUG_LOG("MemoryFilter: F SET (%x) (%f, %f)", filter, time, value.d);
+ } else {
+ MCX_DEBUG_LOG("MemoryFilter: F SET (%x) (%f, -)", filter, time);
+ }
+ MCX_DEBUG_LOG("MemoryFilter: NumEntriesWrite: %zu", memoryFilter->numEntriesWrite);
+ }
+#endif // MCX_DEBUG
+ }
+
+ return RETURN_OK;
+}
+
+static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, double time) {
+ MemoryFilter * memoryFilter = (MemoryFilter *) filter;
+ size_t i = 0;
+ size_t smallerIdx = SIZE_MAX;
+ size_t biggerIdx = SIZE_MAX;
+
+ for (i = memoryFilter->numEntriesRead - 1 ; i >= 0; --i) {
+ if (double_eq(memoryFilter->timeHistoryRead[i], time)) {
+#ifdef MCX_DEBUG
+ if (time < MCX_DEBUG_LOG_TIME) {
+ if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) {
+ MCX_DEBUG_LOG("MemoryFilter: F GET (%x) (%f, %f)", filter, time, memoryFilter->valueHistoryRead[i].value.d);
+ } else {
+ MCX_DEBUG_LOG("MemoryFilter: F GET (%x) (%f, -)", filter, time);
+ }
+ }
+#endif // MCX_DEBUG
+
+ return memoryFilter->valueHistoryRead[i].value;
+ }
+
+ // find out closest stored time points
+ if (time < memoryFilter->timeHistoryRead[i]) {
+ biggerIdx = i;
+ } else if (smallerIdx == SIZE_MAX) {
+ smallerIdx = i;
+ } else {
+ break;
+ }
+ }
+
+ if (smallerIdx == SIZE_MAX) {
+ i = biggerIdx;
+ } else if (biggerIdx == SIZE_MAX) {
+ i = smallerIdx;
+ } else if ((time - memoryFilter->timeHistoryRead[smallerIdx]) < (memoryFilter->timeHistoryRead[biggerIdx] - time)) {
+ i = smallerIdx;
+ } else {
+ i = biggerIdx;
+ }
+
+#ifdef MCX_DEBUG
+ if (time < MCX_DEBUG_LOG_TIME) {
+ if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) {
+ MCX_DEBUG_LOG("MemoryFilter: F GET CLOSEST (%x) (%f, %f)", filter, time, memoryFilter->valueHistoryRead[i].value.d);
+ } else {
+ MCX_DEBUG_LOG("MemoryFilter: F GET CLOSEST (%x) (%f, -)", filter, time);
+ }
+ }
+#endif // MCX_DEBUG
+
+ return memoryFilter->valueHistoryRead[i].value;
+}
+
+static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time) {
+ MemoryFilter * memoryFilter = (MemoryFilter *) filter;
+ size_t i = 0;
+ size_t smallerIdx = SIZE_MAX;
+ size_t biggerIdx = SIZE_MAX;
+
+ for (i = 0; i < memoryFilter->numEntriesRead; ++i) {
+ if (double_eq(memoryFilter->timeHistoryRead[i], time)) {
+#ifdef MCX_DEBUG
+ if (time < MCX_DEBUG_LOG_TIME) {
+ if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) {
+ MCX_DEBUG_LOG("MemoryFilter: F GET (%x) (%f, %f)", filter, time, memoryFilter->valueHistoryRead[i].value.d);
+ } else {
+ MCX_DEBUG_LOG("MemoryFilter: F GET (%x) (%f, -)", filter, time);
+ }
+ }
+#endif // MCX_DEBUG
+
+ return memoryFilter->valueHistoryRead[i].value;
+ }
+
+ // find out closest stored time points
+ if (time > memoryFilter->timeHistoryRead[i]) {
+ smallerIdx = i;
+ } else if (biggerIdx == SIZE_MAX) {
+ biggerIdx = i;
+ } else {
+ break;
+ }
+ }
+
+ if (smallerIdx == SIZE_MAX) {
+ i = biggerIdx;
+ } else if (biggerIdx == SIZE_MAX) {
+ i = smallerIdx;
+ } else if ((time - memoryFilter->timeHistoryRead[smallerIdx]) < (memoryFilter->timeHistoryRead[biggerIdx] - time)) {
+ i = smallerIdx;
+ } else {
+ i = biggerIdx;
+ }
+
+#ifdef MCX_DEBUG
+ if (time < MCX_DEBUG_LOG_TIME) {
+ if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) {
+ MCX_DEBUG_LOG("MemoryFilter: F GET CLOSEST (%x) (%f, %f)", filter, time, memoryFilter->valueHistoryRead[i].value.d);
+ } else {
+ MCX_DEBUG_LOG("MemoryFilter: F GET CLOSEST (%x) (%f, -)", filter, time);
+ }
+ }
+#endif // MCX_DEBUG
+
+ return memoryFilter->valueHistoryRead[i].value;
+}
+
+static McxStatus MemoryFilterEnterCouplingStepMode(ChannelFilter * filter,
+ double communicationTimeStepSize,
+ double sourceTimeStepSize,
+ double targetTimeStepSize) {
+ MemoryFilter * memoryFilter = (MemoryFilter *) filter;
+
+ MCX_DEBUG_LOG("MemoryFilter: Enter coupling mode (%x): NumEntriesRead: %d, NumEntriesWrite: %d",
+ filter, memoryFilter->numEntriesRead, memoryFilter->numEntriesWrite);
+
+ return RETURN_OK;
+}
+
+static McxStatus MemoryFilterEnterCommunicationMode(ChannelFilter * filter, double _time) {
+ MemoryFilter* memoryFilter = (MemoryFilter*)filter;
+
+ MCX_DEBUG_LOG("MemoryFilter: Enter synchronization mode (%x): NumEntriesRead: %d, NumEntriesWrite: %d",
+ filter, memoryFilter->numEntriesRead, memoryFilter->numEntriesWrite);
+
+ if (memoryFilter->numEntriesWrite > 0) {
+ size_t i = 0;
+ if (memoryFilter->numEntriesRead > 1) {
+ ChannelValueSetFromReference(&memoryFilter->valueHistoryRead[0], &memoryFilter->valueHistoryRead[memoryFilter->numEntriesRead - 1].value);
+ memoryFilter->timeHistoryRead[0] = memoryFilter->timeHistoryRead[memoryFilter->numEntriesRead - 1];
+ memoryFilter->numEntriesRead = 1;
+ }
+
+ for (i = 0; i < memoryFilter->numEntriesWrite; i++) {
+#ifdef MCX_DEBUG
+ if (i + memoryFilter->numEntriesRead >= memoryFilter->historySize) {
+ mcx_log(LOG_ERROR, "MemoryFilter: Trying to write outside of allocated buffer "
+ "(HistorySize: %zu, NumEntriesRead: %zu, NumEntriesWrite: %zu",
+ memoryFilter->historySize, memoryFilter->numEntriesRead, memoryFilter->numEntriesWrite);
+ return RETURN_ERROR;
+ }
+#endif // MCX_DEBUG
+ ChannelValueSetFromReference(&memoryFilter->valueHistoryRead[i + memoryFilter->numEntriesRead], &memoryFilter->valueHistoryWrite[i].value);
+ memoryFilter->timeHistoryRead[i + memoryFilter->numEntriesRead] = memoryFilter->timeHistoryWrite[i];
+ }
+
+ memoryFilter->numEntriesRead += memoryFilter->numEntriesWrite;
+ memoryFilter->numEntriesWrite = 0;
+ }
+
+ return RETURN_OK;
+}
+
+static McxStatus MemoryFilterSetup(MemoryFilter * filter, ChannelType type, size_t historySize, int reverseSearch) {
+ ChannelFilter * channelFilter = (ChannelFilter *)filter;
+ size_t i = 0;
+
+ channelFilter->GetValue = reverseSearch ? MemoryFilterGetValueReverse : MemoryFilterGetValue;
+
+ filter->historySize = historySize;
+ filter->numEntriesRead = 0;
+ filter->numEntriesWrite = 0;
+
+ filter->valueHistoryRead = (ChannelValue *) mcx_malloc(filter->historySize * sizeof(ChannelValue));
+ if (!filter->valueHistoryRead) {
+ mcx_log(LOG_ERROR, "MemoryFilterSetup: No memory for value buffer (read)");
+ goto cleanup;
+ }
+
+ filter->valueHistoryWrite = (ChannelValue*)mcx_malloc(filter->historySize * sizeof(ChannelValue));
+ if (!filter->valueHistoryWrite) {
+ mcx_log(LOG_ERROR, "MemoryFilterSetup: No memory for value buffer (write)");
+ goto cleanup;
+ }
+
+ filter->timeHistoryRead = (double *) mcx_calloc(filter->historySize, sizeof(double));
+ if (!filter->timeHistoryRead) {
+ mcx_log(LOG_ERROR, "MemoryFilterSetup: No memory for time buffer (read)");
+ goto cleanup;
+ }
+
+ filter->timeHistoryWrite = (double*)mcx_calloc(filter->historySize, sizeof(double));
+ if (!filter->timeHistoryWrite) {
+ mcx_log(LOG_ERROR, "MemoryFilterSetup: No memory for time buffer (write)");
+ goto cleanup;
+ }
+
+ for (i = 0; i < filter->historySize; i++) {
+ ChannelValueInit(filter->valueHistoryRead + i, type);
+ }
+
+ for (i = 0; i < filter->historySize; i++) {
+ ChannelValueInit(filter->valueHistoryWrite + i, type);
+ }
+
+ return RETURN_OK;
+
+cleanup:
+ if (filter->valueHistoryRead) {
+ mcx_free(filter->valueHistoryRead);
+ }
+
+ if (filter->valueHistoryWrite) {
+ mcx_free(filter->valueHistoryWrite);
+ }
+
+ if (filter->timeHistoryRead) {
+ mcx_free(filter->timeHistoryRead);
+ }
+
+ if (filter->timeHistoryWrite) {
+ mcx_free(filter->timeHistoryWrite);
+ }
+
+ return RETURN_ERROR;
+}
+
+static void MemoryFilterDestructor(MemoryFilter * filter) {
+ if (filter->valueHistoryRead) {
+ size_t i = 0;
+
+ for (i = 0; i < filter->numEntriesRead; i++) {
+ ChannelValueDestructor(&filter->valueHistoryRead[i]);
+ }
+
+ mcx_free(filter->valueHistoryRead);
+ }
+
+ if (filter->timeHistoryRead) {
+ mcx_free(filter->timeHistoryRead);
+ }
+
+ if (filter->valueHistoryWrite) {
+ size_t i = 0;
+
+ for (i = 0; i < filter->numEntriesWrite; i++) {
+ ChannelValueDestructor(&filter->valueHistoryWrite[i]);
+ }
+
+ mcx_free(filter->valueHistoryWrite);
+ }
+
+ if (filter->timeHistoryWrite) {
+ mcx_free(filter->timeHistoryWrite);
+ }
+}
+
+static MemoryFilter * MemoryFilterCreate(MemoryFilter * memoryFilter) {
+ ChannelFilter * filter = (ChannelFilter *) memoryFilter;
+
+ filter->SetValue = MemoryFilterSetValue;
+ filter->GetValue = NULL;
+
+ filter->EnterCommunicationMode = MemoryFilterEnterCommunicationMode;
+ filter->EnterCouplingStepMode = MemoryFilterEnterCouplingStepMode;
+
+ memoryFilter->Setup = MemoryFilterSetup;
+
+ memoryFilter->valueHistoryRead = NULL;
+ memoryFilter->valueHistoryWrite = NULL;
+ memoryFilter->timeHistoryRead = NULL;
+ memoryFilter->timeHistoryWrite = NULL;
+
+ memoryFilter->numEntriesRead = 0;
+ memoryFilter->numEntriesWrite = 0;
+
+ memoryFilter->historySize = 0;
+
+ return memoryFilter;
+}
+
+OBJECT_CLASS(MemoryFilter, ChannelFilter);
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif /* __cplusplus */
\ No newline at end of file
diff --git a/src/core/connections/filters/MemoryFilter.h b/src/core/connections/filters/MemoryFilter.h
new file mode 100644
index 0000000..7b97d4a
--- /dev/null
+++ b/src/core/connections/filters/MemoryFilter.h
@@ -0,0 +1,45 @@
+/********************************************************************************
+ * Copyright (c) 2022 AVL List GmbH and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Apache Software License 2.0 which is available at
+ * https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ********************************************************************************/
+
+#ifndef MCX_CORE_CONNECTIONS_FILTERS_MEMORY_FILTER_H
+#define MCX_CORE_CONNECTIONS_FILTERS_MEMORY_FILTER_H
+
+#include "core/connections/filters/Filter.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct MemoryFilter MemoryFilter;
+
+typedef McxStatus (* fMemoryFilterSetup)(MemoryFilter * filter, ChannelType type, size_t historySize, int reverseSearch);
+
+extern const struct ObjectClass _MemoryFilter;
+
+struct MemoryFilter {
+ ChannelFilter _;
+
+ fMemoryFilterSetup Setup;
+
+ ChannelValue * valueHistoryRead;
+ ChannelValue * valueHistoryWrite;
+ double * timeHistoryRead;
+ double * timeHistoryWrite;
+
+ size_t numEntriesRead;
+ size_t numEntriesWrite;
+ size_t historySize;
+} ;
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif /* __cplusplus */
+
+#endif /* MCX_CORE_CONNECTIONS_FILTERS_MEMORY_FILTER_H */
\ No newline at end of file
diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c
index 1f1913a..21c1040 100644
--- a/src/fmu/common_fmu2.c
+++ b/src/fmu/common_fmu2.c
@@ -13,6 +13,8 @@
#include "fmu/Fmu2Value.h"
+#include "core/channels/ChannelInfo.h"
+
#include "reader/model/parameters/ArrayParameterDimensionInput.h"
#include "reader/model/parameters/ParameterInput.h"
#include "reader/model/parameters/ParametersInput.h"
@@ -59,6 +61,23 @@ ChannelType Fmi2TypeToChannelType(fmi2_base_type_enu_t type) {
}
}
+const char * Fmi2TypeToString(fmi2_base_type_enu_t type) {
+ switch (type) {
+ case fmi2_base_type_real:
+ return "fmi2Real";
+ case fmi2_base_type_int:
+ return "fmi2Integer";
+ case fmi2_base_type_bool:
+ return "fmi2Bool";
+ case fmi2_base_type_str:
+ return "fmi2String";
+ case fmi2_base_type_enum:
+ return "fmi2Enum";
+ }
+ return "fmi2Unknown";
+}
+
+
McxStatus Fmu2CommonStructInit(Fmu2CommonStruct * fmu) {
fmu->fmiImport = NULL;
@@ -73,6 +92,8 @@ McxStatus Fmu2CommonStructInit(Fmu2CommonStruct * fmu) {
fmu->tunableParams = (ObjectContainer *) object_create(ObjectContainer);
fmu->initialValues = (ObjectContainer *) object_create(ObjectContainer);
+ fmu->connectedIn = (ObjectContainer *) object_create(ObjectContainer);
+
fmu->numLogCategories = 0;
fmu->logCategories = NULL;
@@ -234,6 +255,10 @@ void Fmu2CommonStructDestructor(Fmu2CommonStruct * fmu) {
object_destroy(fmu->tunableParams);
}
+ if (fmu->connectedIn) {
+ object_destroy(fmu->connectedIn);
+ }
+
if (fmu->fmiImport) {
fmi2_import_free(fmu->fmiImport);
fmu->fmiImport = NULL;
@@ -1030,8 +1055,8 @@ void Fmu2MarkTunableParamsAsInputAsDiscrete(ObjectContainer * in) {
if (fmi2_causality_enu_input != causality) {
ChannelIn * in = (ChannelIn *) val->channel;
- ChannelInfo * info = ((Channel*)in)->GetInfo((Channel*)in);
- mcx_log(LOG_DEBUG, "Setting input \"%s\" as discrete", info->GetLogName(info));
+ ChannelInfo * info = &((Channel*)in)->info;
+ mcx_log(LOG_DEBUG, "Setting input \"%s\" as discrete", ChannelInfoGetLogName(info));
in->SetDiscrete(in);
}
}
diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h
index d4c2764..0f61179 100644
--- a/src/fmu/common_fmu2.h
+++ b/src/fmu/common_fmu2.h
@@ -24,6 +24,7 @@ extern "C" {
#endif /* __cplusplus */
ChannelType Fmi2TypeToChannelType(fmi2_base_type_enu_t type);
+const char * Fmi2TypeToString(fmi2_base_type_enu_t type);
struct Fmu2CommonStruct;
@@ -52,6 +53,8 @@ struct Fmu2CommonStruct {
ObjectContainer * params;
ObjectContainer * initialValues;
+ ObjectContainer * connectedIn;
+
ObjectContainer * localValues;
ObjectContainer * tunableParams;
diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c
index 610d724..6e451a7 100644
--- a/src/objects/ObjectContainer.c
+++ b/src/objects/ObjectContainer.c
@@ -23,6 +23,268 @@ typedef struct ObjectContainerElement {
void * value;
} ObjectContainerElement;
+typedef struct {
+ int (*cmp)(const void *, const void *, void *);
+ void * arg;
+} StrCmpCtx;
+
+static int ObjectContainerElementCmp(const void * first, const void * second, void * ctx) {
+ StrCmpCtx * data = (StrCmpCtx *)ctx;
+
+ ObjectContainerElement * firstElement = (ObjectContainerElement *)first;
+ ObjectContainerElement * secondElement = (ObjectContainerElement *)second;
+
+ return data->cmp(&(firstElement->object), &(secondElement->object), data->arg);
+}
+
+
+
+static size_t ObjectListSize(const ObjectList * container) {
+ return container->size;
+}
+
+static McxStatus ObjectListResize(ObjectList * container, size_t size) {
+ size_t oldSize = container->size;
+ size_t oldCapacity = container->capacity;
+ size_t i = 0;
+
+ container->size = size;
+ if (oldCapacity < size) {
+ container->capacity = size + container->increment;
+ container->elements = (Object * *)mcx_realloc(container->elements, container->capacity * sizeof(Object *));
+ if (!container->elements) {
+ mcx_log(LOG_ERROR, "ObjectList: Resize: Memory allocation failed");
+ return RETURN_ERROR;
+ }
+ }
+
+ // if we make the container larger, init new elements with NULL
+ for (i = oldSize; i < size; i++) {
+ container->elements[i] = NULL;
+ }
+
+ return RETURN_OK;
+}
+
+
+static McxStatus ObjectListPushBack(ObjectList * container, Object * obj) {
+ McxStatus retVal = container->Resize(container, container->size + 1);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ObjectList: PushBack: Resize failed");
+ return RETURN_ERROR;
+ }
+ container->elements[container->size - 1] = obj;
+
+ return RETURN_OK;
+}
+
+static McxStatus ObjectListSort(ObjectList * container, int (*cmp)(const void *, const void *, void *), void * arg) {
+ size_t i = 0;
+ size_t n = container->size;
+
+ StrCmpCtx ctx;
+ ctx.cmp = cmp;
+ ctx.arg = arg;
+
+ ObjectContainerElement * elements = mcx_malloc(n * sizeof(ObjectContainerElement));
+ if (!elements) {
+ return RETURN_ERROR;
+ }
+
+ for (i = 0; i < n; i++) {
+ elements[i].object = container->elements[i];
+ }
+
+ mcx_sort(elements, n, sizeof(ObjectContainerElement), ObjectContainerElementCmp, &ctx);
+
+ for (i = 0; i < n; i++) {
+ container->elements[i] = elements[i].object;
+ }
+
+ mcx_free(elements);
+
+ return RETURN_OK;
+}
+
+static Object * ObjectListAt(const ObjectList * container, size_t pos) {
+ if (pos < container->size) {
+ return container->elements[pos];
+ } else {
+ return NULL;
+ }
+}
+
+static McxStatus ObjectListSetAt(ObjectList * container, size_t pos, Object * obj) {
+ if (pos >= container->size) {
+ container->Resize(container, pos + 1);
+ }
+
+ container->elements[pos] = obj;
+
+ return RETURN_OK;
+}
+
+static ObjectList * ObjectListCopy(ObjectList * container) {
+ McxStatus retVal;
+ size_t i = 0;
+
+ ObjectList * newContainer = (ObjectList *) object_create(ObjectList);
+
+ if (!newContainer) {
+ mcx_log(LOG_ERROR, "ObjectContainer: Copy: Memory allocation failed");
+ return NULL;
+ }
+
+ retVal = newContainer->Resize(newContainer, container->Size(container));
+ if (RETURN_OK != retVal) {
+ object_destroy(newContainer);
+ return NULL;
+ }
+
+ for (i = 0; i < newContainer->Size(newContainer); i++) {
+ newContainer->elements[i] = container->elements[i];
+ }
+
+ return newContainer;
+}
+
+static McxStatus ObjectListAppend(ObjectList * container, ObjectList * appendee) {
+ size_t appendeeSize = 0;
+ size_t size = 0;
+ size_t i = 0;
+
+ McxStatus retVal = RETURN_OK;
+
+ if (!appendee) {
+ mcx_log(LOG_ERROR, "ObjectContainer: Append: Appendee missing");
+ return RETURN_ERROR;
+ }
+
+ appendeeSize = appendee->Size(appendee);
+ for (i = 0; i < appendeeSize; i++) {
+ retVal = container->PushBack(container, appendee->At(appendee, i));
+ if (RETURN_OK != retVal) {
+ return RETURN_ERROR;
+ }
+ }
+
+ return RETURN_OK;
+}
+
+static Object ** ObjectListData(ObjectList * container) {
+ return container->elements;
+}
+
+static void ObjectListAssignArray(ObjectList * container, size_t size, Object ** objs) {
+ container->size = size;
+
+ if (container->elements) {
+ mcx_free(container->elements);
+ }
+ container->elements = objs;
+}
+
+static void ObjectListDestroyObjects(ObjectList * container) {
+ size_t i = 0;
+
+ for (i = 0; i < container->size; i++) {
+ Object * obj = container->At(container, i);
+ object_destroy(obj);
+ }
+
+ container->Resize(container, 0);
+}
+
+static int ObjectListContains(ObjectList * container, Object * obj) {
+ size_t i = 0;
+ for (i = 0; i < container->size; i++) {
+ if (container->At(container, i) == obj) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static ObjectList * ObjectListFilter(ObjectList * container, fObjectPredicate predicate) {
+ ObjectList * filtered = (ObjectList *) object_create(ObjectList);
+
+ size_t i = 0;
+
+ for (i = 0; i < container->size; i++) {
+ Object * obj = container->At(container, i);
+ if (predicate(obj)) {
+ filtered->PushBack(filtered, obj);
+ }
+ }
+
+ return filtered;
+}
+
+static ObjectList * ObjectListFilterCtx(ObjectList * container, fObjectPredicateCtx predicate, void * ctx) {
+ ObjectList * filtered = (ObjectList *) object_create(ObjectList);
+
+ size_t i = 0;
+
+ for (i = 0; i < container->size; i++) {
+ Object * obj = container->At(container, i);
+ if (predicate(obj, ctx)) {
+ filtered->PushBack(filtered, obj);
+ }
+ }
+
+ return filtered;
+}
+
+static void ObjectListIterate(ObjectList * container, fObjectIter iter) {
+ size_t i = 0;
+ for (i = 0; i < container->size; i++) {
+ Object * obj = container->At(container, i);
+ iter(obj);
+ }
+}
+
+static void ObjectListDestructor(ObjectList * container) {
+ if (container->elements) {
+ mcx_free(container->elements);
+ }
+}
+
+static ObjectList * ObjectListCreate(ObjectList * container) {
+ container->Size = ObjectListSize;
+ container->Resize = ObjectListResize;
+ container->PushBack = ObjectListPushBack;
+ container->At = ObjectListAt;
+ container->SetAt = ObjectListSetAt;
+ container->Copy = ObjectListCopy;
+ container->Append = ObjectListAppend;
+ container->Data = ObjectListData;
+ container->AssignArray = ObjectListAssignArray;
+
+ container->DestroyObjects = ObjectListDestroyObjects;
+
+ container->Contains = ObjectListContains;
+ container->Filter = ObjectListFilter;
+ container->FilterCtx = ObjectListFilterCtx;
+
+ container->Iterate = ObjectListIterate;
+ container->Sort = ObjectListSort;
+
+ container->elements = NULL;
+ container->size = 0;
+ container->capacity = 0;
+ container->increment = 10;
+
+ return container;
+}
+
+OBJECT_CLASS(ObjectList, Object);
+
+
+
+
+
+
+/////////////////
static size_t ObjectContainerSize(const ObjectContainer * container) {
return container->size;
@@ -30,14 +292,17 @@ static size_t ObjectContainerSize(const ObjectContainer * container) {
static McxStatus ObjectContainerResize(ObjectContainer * container, size_t size) {
size_t oldSize = container->size;
+ size_t oldCapacity = container->capacity;
size_t i = 0;
- container->size = size;
- container->elements = (Object * *) mcx_realloc(container->elements,
- size * sizeof(Object *));
- if (!container->elements && 0 < size) {
- mcx_log(LOG_ERROR, "ObjectContainer: Resize: Memory allocation failed");
- return RETURN_ERROR;
+ container->size = size;
+ if (oldCapacity < size) {
+ container->capacity = size + container->increment;
+ container->elements = (Object * *)mcx_realloc(container->elements, container->capacity * sizeof(Object *));
+ if (!container->elements) {
+ mcx_log(LOG_ERROR, "ObjectContainer: Resize: Memory allocation failed");
+ return RETURN_ERROR;
+ }
}
/* if we make the container larger, init new elements with NULL */
@@ -49,14 +314,11 @@ static McxStatus ObjectContainerResize(ObjectContainer * container, size_t size)
}
static McxStatus ObjectContainerPushBack(ObjectContainer * container, Object * obj) {
- container->size += 1;
- container->elements = (Object * *) mcx_realloc(container->elements,
- container->size * sizeof(Object *));
- if (!container->elements) {
- mcx_log(LOG_ERROR, "ObjectContainer: PushBack: Memory allocation failed");
+ McxStatus retVal = container->Resize(container, container->size + 1);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "ObjectContainer: PushBack: Resize failed");
return RETURN_ERROR;
}
-
container->elements[container->size - 1] = obj;
return StringContainerResize(container->strToIdx, container->size);
@@ -77,19 +339,6 @@ static McxStatus ObjectContainerPushBackNamed(ObjectContainer * container, Obje
return RETURN_OK;
}
-typedef struct {
- int (*cmp)(const void *, const void *, void *);
- void * arg;
-} StrCmpCtx;
-
-static int ObjectContainerElementCmp(const void * first, const void * second, void * ctx) {
- StrCmpCtx * data = (StrCmpCtx *)ctx;
-
- ObjectContainerElement * firstElement = (ObjectContainerElement *) first;
- ObjectContainerElement * secondElement = (ObjectContainerElement *) second;
-
- return data->cmp(&(firstElement->object), &(secondElement->object), data->arg);
-}
static McxStatus ObjectContainerSort(ObjectContainer * container, int (*cmp)(const void *, const void *, void *), void * arg) {
size_t i = 0;
@@ -145,7 +394,7 @@ static ObjectContainer * ObjectContainerCopy(ObjectContainer * container) {
McxStatus retVal;
size_t i = 0;
- ObjectContainer * newContainer = (ObjectContainer *) object_create(ObjectContainer);
+ ObjectContainer * newContainer = (ObjectContainer *)object_create(ObjectContainer);
if (!newContainer) {
mcx_log(LOG_ERROR, "ObjectContainer: Copy: Memory allocation failed");
@@ -161,7 +410,7 @@ static ObjectContainer * ObjectContainerCopy(ObjectContainer * container) {
for (i = 0; i < newContainer->Size(newContainer); i++) {
newContainer->elements[i] = container->elements[i];
retVal = StringContainerSetString(newContainer->strToIdx, i,
- StringContainerGetString(container->strToIdx, i));
+ StringContainerGetString(container->strToIdx, i));
if (retVal != RETURN_OK) {
return NULL;
}
@@ -170,9 +419,7 @@ static ObjectContainer * ObjectContainerCopy(ObjectContainer * container) {
return newContainer;
}
-static McxStatus ObjectContainerAppend(
- ObjectContainer * container,
- ObjectContainer * appendee) {
+static McxStatus ObjectContainerAppend(ObjectContainer * container, ObjectContainer * appendee) {
size_t appendeeSize = 0;
size_t size = 0;
size_t i = 0;
@@ -192,7 +439,7 @@ static McxStatus ObjectContainerAppend(
}
retVal = container->SetElementName(container, container->Size(container) - 1,
- appendee->GetElementName(appendee, i));
+ appendee->GetElementName(appendee, i));
if (RETURN_OK != retVal) {
return RETURN_ERROR;
}
@@ -205,9 +452,7 @@ static Object ** ObjectContainerData(ObjectContainer * container) {
return container->elements;
}
-static void ObjectContainerAssignArray(ObjectContainer * container,
- size_t size,
- Object ** objs) {
+static void ObjectContainerAssignArray(ObjectContainer * container, size_t size, Object ** objs) {
container->size = size;
if (container->elements) {
@@ -228,8 +473,8 @@ static void ObjectContainerDestroyObjects(ObjectContainer * container) {
}
static McxStatus ObjectContainerSetElementName(ObjectContainer * container,
- size_t pos,
- const char * name) {
+ size_t pos,
+ const char * name) {
if (pos >= container->size) {
mcx_log(LOG_ERROR, "ObjectContainer: SetElementName: Position %u out of bounds, max is %u", pos, container->size);
return RETURN_ERROR;
@@ -238,23 +483,20 @@ static McxStatus ObjectContainerSetElementName(ObjectContainer * container,
return StringContainerSetString(container->strToIdx, pos, name);
}
-static const char * ObjectContainerGetElementName(ObjectContainer * container,
- size_t pos) {
+static const char * ObjectContainerGetElementName(ObjectContainer * container, size_t pos) {
return StringContainerGetString(container->strToIdx, pos);
}
-static int ObjectContainerGetNameIndex(ObjectContainer * container,
- const char * name) {
+static int ObjectContainerGetNameIndex(ObjectContainer * container, const char * name) {
return StringContainerGetIndex(container->strToIdx, name);
}
static Object * ObjectContainerGetByName(const ObjectContainer * container, const char * name) {
return container->At(container, container->GetNameIndex((ObjectContainer *)container, name));
}
-static int ObjectContainerContains(ObjectContainer * container,
- Object * obj) {
+static int ObjectContainerContains(ObjectContainer * container, Object * obj) {
size_t i = 0;
- for (i = 0; i < container->Size(container); i++) {
+ for (i = 0; i < container->size; i++) {
if (container->At(container, i) == obj) {
return TRUE;
}
@@ -263,11 +505,10 @@ static int ObjectContainerContains(ObjectContainer * container,
}
static ObjectContainer * ObjectContainerFilter(ObjectContainer * container, fObjectPredicate predicate) {
- ObjectContainer * filtered = (ObjectContainer *) object_create(ObjectContainer);
-
+ ObjectContainer * filtered = (ObjectContainer *)object_create(ObjectContainer);
size_t i = 0;
- for (i = 0; i < container->Size(container); i++) {
+ for (i = 0; i < container->size; i++) {
Object * obj = container->At(container, i);
if (predicate(obj)) {
filtered->PushBack(filtered, obj);
@@ -278,11 +519,11 @@ static ObjectContainer * ObjectContainerFilter(ObjectContainer * container, fObj
}
static ObjectContainer * ObjectContainerFilterCtx(ObjectContainer * container, fObjectPredicateCtx predicate, void * ctx) {
- ObjectContainer * filtered = (ObjectContainer *) object_create(ObjectContainer);
+ ObjectContainer * filtered = (ObjectContainer *)object_create(ObjectContainer);
size_t i = 0;
- for (i = 0; i < container->Size(container); i++) {
+ for (i = 0; i < container->size; i++) {
Object * obj = container->At(container, i);
if (predicate(obj, ctx)) {
filtered->PushBack(filtered, obj);
@@ -294,7 +535,7 @@ static ObjectContainer * ObjectContainerFilterCtx(ObjectContainer * container, f
static void ObjectContainerIterate(ObjectContainer * container, fObjectIter iter) {
size_t i = 0;
- for (i = 0; i < container->Size(container); i++) {
+ for (i = 0; i < container->size; i++) {
Object * obj = container->At(container, i);
iter(obj);
}
@@ -337,8 +578,10 @@ static ObjectContainer * ObjectContainerCreate(ObjectContainer * container) {
container->elements = NULL;
container->size = 0;
+ container->capacity = 0;
+ container->increment = 10;
- container->strToIdx = (StringContainer *) mcx_malloc(sizeof(StringContainer));
+ container->strToIdx = (StringContainer *)mcx_malloc(sizeof(StringContainer));
if (!container->strToIdx) { return NULL; }
StringContainerInit(container->strToIdx, 0);
@@ -348,6 +591,7 @@ static ObjectContainer * ObjectContainerCreate(ObjectContainer * container) {
OBJECT_CLASS(ObjectContainer, Object);
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif /* __cplusplus */
\ No newline at end of file
diff --git a/src/objects/ObjectContainer.h b/src/objects/ObjectContainer.h
index a9fbf00..30c948c 100644
--- a/src/objects/ObjectContainer.h
+++ b/src/objects/ObjectContainer.h
@@ -17,44 +17,86 @@
extern "C" {
#endif /* __cplusplus */
-typedef struct ObjectContainer ObjectContainer;
-struct StringContainer;
+typedef struct ObjectList ObjectList;
typedef int (* fObjectPredicate)(Object * obj);
typedef int (* fObjectPredicateCtx)(Object * obj, void * ctx);
typedef void (* fObjectIter)(Object * obj);
-typedef size_t (* fObjectContainerSize)(const ObjectContainer * container);
-typedef McxStatus (* fObjectContainerResize)(ObjectContainer * container, size_t size);
-typedef McxStatus (* fObjectContainerPushBack)(ObjectContainer * container, Object * obj);
-typedef McxStatus (* fObjectContainerPushBackNamed)(ObjectContainer * container, Object * obj, const char * name);
-typedef Object * (* fObjectContainerAt)(const ObjectContainer * container, size_t pos);
-typedef Object * (* fObjectContainerGetByName)(const ObjectContainer * container, const char * name);
-typedef McxStatus (* fObjectContainerSetAt)(ObjectContainer * container, size_t pos, Object * obj);
-typedef ObjectContainer * (* fObjectContainerCopy)(ObjectContainer * container);
-typedef McxStatus (* fObjectContainerAppend)(
- ObjectContainer * container,
- ObjectContainer * appendee);
-typedef Object ** (* fObjectContainerData)(ObjectContainer * container);
-typedef void (* fObjectContainerAssignArray)(ObjectContainer * container,
- size_t size,
- Object ** objs);
-typedef void (* fObjectContainerDestroyObjects)(ObjectContainer * container);
-typedef McxStatus (* fObjectContainerSetElementName)(ObjectContainer * container,
- size_t pos,
- const char * name);
-typedef const char * (* fObjectContainerGetElementName)(ObjectContainer * container, size_t pos);
-typedef int (* fObjectContainerGetNameIndex)(ObjectContainer * container,
- const char * name);
-typedef int (* fObjectContainerContains)(ObjectContainer * container,
- Object * obj);
-typedef ObjectContainer * (* fObjectContainerFilter)(ObjectContainer * container, fObjectPredicate predicate);
-typedef ObjectContainer * (* fObjectContainerFilterCtx)(ObjectContainer * container, fObjectPredicateCtx predicate, void * ctx);
-
-typedef McxStatus (*fObjectContainerSort)(ObjectContainer * container, int (*cmp)(const void *, const void *, void *), void * arg);
-
-
-typedef void (* fObjectContainerIterate)(ObjectContainer * container, fObjectIter iter);
+typedef size_t(*fObjectListSize)(const ObjectList * container);
+typedef McxStatus(*fObjectListResize)(ObjectList * container, size_t size);
+typedef McxStatus(*fObjectListPushBack)(ObjectList * container, Object * obj);
+typedef Object * (*fObjectListAt)(const ObjectList * container, size_t pos);
+typedef McxStatus(*fObjectListSetAt)(ObjectList * container, size_t pos, Object * obj);
+typedef ObjectList * (*fObjectListCopy)(ObjectList * container);
+typedef McxStatus(*fObjectListAppend)(ObjectList * container, ObjectList * appendee);
+typedef Object ** (*fObjectListData)(ObjectList * container);
+typedef void (*fObjectListAssignArray)(ObjectList * container, size_t size, Object** objs);
+typedef void (*fObjectListDestroyObjects)(ObjectList * container);
+typedef int (*fObjectListContains)(ObjectList * container, Object * obj);
+typedef ObjectList * (*fObjectListFilter)(ObjectList * container, fObjectPredicate predicate);
+typedef ObjectList * (*fObjectListFilterCtx)(ObjectList * container, fObjectPredicateCtx predicate, void * ctx);
+
+typedef McxStatus(*fObjectListSort)(ObjectList * container, int (*cmp)(const void *, const void *, void *), void * arg);
+typedef void (*fObjectListIterate)(ObjectList * container, fObjectIter iter);
+
+extern const struct ObjectClass _ObjectList;
+
+typedef struct ObjectList {
+ Object _; /* super class first */
+
+ fObjectListSize Size;
+ fObjectListResize Resize;
+ fObjectListPushBack PushBack;
+ fObjectListAt At;
+ fObjectListSetAt SetAt;
+ fObjectListCopy Copy;
+ fObjectListAppend Append;
+ fObjectListData Data;
+ fObjectListAssignArray AssignArray;
+
+ fObjectListDestroyObjects DestroyObjects;
+
+ fObjectListContains Contains;
+ fObjectListFilter Filter;
+ fObjectListFilterCtx FilterCtx;
+
+ fObjectListSort Sort;
+ fObjectListIterate Iterate;
+
+ struct Object ** elements;
+ size_t size;
+ size_t capacity;
+ size_t increment;
+} ObjectList;
+
+typedef struct ObjectContainer ObjectContainer;
+struct StringContainer;
+
+typedef size_t(*fObjectContainerSize)(const ObjectContainer * container);
+typedef McxStatus(*fObjectContainerResize)(ObjectContainer * container, size_t size);
+typedef McxStatus(*fObjectContainerPushBack)(ObjectContainer * container, Object * obj);
+typedef Object * (*fObjectContainerAt)(const ObjectContainer * container, size_t pos);
+typedef McxStatus(*fObjectContainerSetAt)(ObjectContainer * container, size_t pos, Object * obj);
+typedef ObjectContainer * (*fObjectContainerCopy)(ObjectContainer * container);
+typedef McxStatus(*fObjectContainerAppend)(ObjectContainer * container, ObjectContainer * appendee);
+typedef Object ** (*fObjectContainerData)(ObjectContainer * container);
+typedef void (*fObjectContainerAssignArray)(ObjectContainer * container, size_t size, Object** objs);
+typedef void (*fObjectContainerDestroyObjects)(ObjectContainer * container);
+typedef int (*fObjectContainerContains)(ObjectContainer * container, Object * obj);
+typedef ObjectContainer * (*fObjectContainerFilter)(ObjectContainer * container, fObjectPredicate predicate);
+typedef ObjectContainer * (*fObjectContainerFilterCtx)(ObjectContainer * container, fObjectPredicateCtx predicate, void * ctx);
+
+typedef McxStatus(*fObjectContainerSort)(ObjectContainer * container, int (*cmp)(const void *, const void *, void *), void * arg);
+typedef void (*fObjectContainerIterate)(ObjectContainer * container, fObjectIter iter);
+
+
+typedef McxStatus(*fObjectContainerSetElementName)(ObjectContainer * container, size_t pos, const char * name);
+typedef int (*fObjectContainerGetNameIndex)(ObjectContainer * container, const char * name);
+typedef McxStatus(*fObjectContainerPushBackNamed)(ObjectContainer * container, Object * obj, const char * name);
+typedef Object * (*fObjectContainerGetByName)(const ObjectContainer * container, const char * name);
+typedef const char * (*fObjectContainerGetElementName)(ObjectContainer * container, size_t pos);
+
extern const struct ObjectClass _ObjectContainer;
@@ -89,6 +131,8 @@ typedef struct ObjectContainer {
struct Object ** elements;
size_t size;
+ size_t capacity;
+ size_t increment;
struct StringContainer * strToIdx;
} ObjectContainer;
diff --git a/src/objects/Vector.c b/src/objects/Vector.c
new file mode 100644
index 0000000..49915e3
--- /dev/null
+++ b/src/objects/Vector.c
@@ -0,0 +1,290 @@
+/********************************************************************************
+ * Copyright (c) 2022 AVL List GmbH and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Apache Software License 2.0 which is available at
+ * https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ********************************************************************************/
+
+#include "objects/Vector.h"
+
+#include "common/logging.h"
+#include "common/memory.h"
+
+#include
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+static size_t VectorSize(const Vector * vector) {
+ return vector->size_;
+}
+
+static void * VectorAt(const Vector * vector, size_t idx) {
+ if (idx < vector->size_) {
+ char * it = (char *) vector->elements_;
+ return (void *) (it + idx * vector->elemSize_);
+ } else {
+ return NULL;
+ }
+}
+
+static McxStatus VectorResize(Vector * vector, size_t size) {
+ size_t oldSize = vector->size_;
+ size_t oldCapacity = vector->capacity_;
+ size_t i = 0;
+ McxStatus retVal = RETURN_OK;
+
+ vector->size_ = size;
+ if (oldCapacity < size) {
+ vector->capacity_ = size + vector->increment_;
+ vector->elements_ = mcx_realloc(vector->elements_, vector->capacity_ * vector->elemSize_);
+ if (!vector->elements_) {
+ mcx_log(LOG_ERROR, "Vector: Resize: Memory allocation failed");
+ return RETURN_ERROR;
+ }
+ }
+
+ // if we make the vector larger, init new elements
+ if (vector->elemInitializer_) {
+ for (i = oldSize; i < size; ++i) {
+ retVal = vector->elemInitializer_(vector->At(vector, i));
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Vector: Resize: Element initialization failed");
+ return RETURN_ERROR;
+ }
+ }
+ }
+
+ return RETURN_OK;
+}
+
+static McxStatus VectorSetAt(Vector * vector, size_t pos, void * elem) {
+ McxStatus retVal = RETURN_OK;
+
+ if (pos >= vector->size_) {
+ VectorResize(vector, pos + 1);
+ }
+
+ if (vector->elemSetter_) {
+ retVal = vector->elemSetter_(vector->At(vector, pos), elem);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Vector: SetAt: Element setting failed");
+ return RETURN_ERROR;
+ }
+ } else {
+ memcpy(vector->At(vector, pos), elem, vector->elemSize_);
+ }
+
+ return RETURN_OK;
+}
+
+static size_t VectorFindIdx(const Vector * vector, fVectorElemPredicate pred, void * args) {
+ size_t i = 0;
+ char * it = NULL;
+
+ for (i = 0, it = (char*) vector->elements_; i < vector->size_; ++i, it += vector->elemSize_) {
+ if (pred((void *) it, args)) {
+ return i;
+ }
+ }
+
+ return SIZE_T_ERROR;
+}
+
+static void * VectorFind(const Vector * vector, fVectorElemPredicate pred, void * args) {
+ size_t idx = vector->FindIdx(vector, pred, args);
+
+ if (idx == SIZE_T_ERROR) {
+ return NULL;
+ }
+
+ return vector->At(vector, idx);
+}
+
+static McxStatus VectorReserve(Vector * vector, size_t newCapacity) {
+ size_t oldCapacity = vector->capacity_;
+
+ if (oldCapacity < newCapacity) {
+ vector->capacity_ = oldCapacity + newCapacity;
+ vector->elements_ = mcx_realloc(vector->elements_, vector->capacity_ * vector->elemSize_);
+ if (!vector->elements_) {
+ mcx_log(LOG_ERROR, "Vector: Reserve: Memory allocation failed");
+ return RETURN_ERROR;
+ }
+ }
+
+ return RETURN_OK;
+}
+
+static McxStatus VectorPushBack(Vector * vector, void * elem) {
+ McxStatus retVal = VectorResize(vector, vector->size_ + 1);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Vector: PushBack: Resize failed");
+ return RETURN_ERROR;
+ }
+
+ if (vector->elemSetter_) {
+ retVal = vector->elemSetter_(vector->At(vector, vector->size_ - 1), elem);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Vector: PushBack: Element setting failed");
+ return RETURN_ERROR;
+ }
+ } else {
+ memcpy(vector->At(vector, vector->size_ - 1), elem, vector->elemSize_);
+ }
+
+ return RETURN_OK;
+}
+
+static McxStatus VectorAppend(Vector * vector, Vector * appendee) {
+ size_t appendeeSize = 0;
+ size_t i = 0;
+
+ McxStatus retVal = RETURN_OK;
+
+ if (!appendee) {
+ mcx_log(LOG_ERROR, "Vector: Append: Appendee missing");
+ return RETURN_ERROR;
+ }
+
+ appendeeSize = appendee->Size(appendee);
+ retVal = VectorReserve(vector, vector->size_ + appendeeSize);
+ if (RETURN_ERROR == retVal) {
+ return RETURN_ERROR;
+ }
+
+ for (i = 0; i < appendeeSize; i++) {
+ retVal = vector->PushBack(vector, appendee->At(appendee, i));
+ if (RETURN_OK != retVal) {
+ return RETURN_ERROR;
+ }
+ }
+
+ return RETURN_OK;
+}
+
+static Vector * VectorFilter(const Vector * vector, fVectorElemPredicate predicate, void * args) {
+ Vector * filtered = (Vector *) object_create(Vector);
+ size_t i = 0;
+ char * it = NULL;
+
+ if (!filtered) {
+ mcx_log(LOG_ERROR, "Vector: Filter: Not enough memory");
+ return NULL;
+ }
+
+ filtered->Setup(filtered, vector->elemSize_, vector->elemInitializer_, vector->elemSetter_, vector->elemDestructor_);
+
+ for (i = 0, it = (char*)vector->elements_; i < vector->size_; ++i, it += vector->elemSize_) {
+ if (predicate((void *) it, args)) {
+ filtered->PushBack(filtered, (void *) it);
+ }
+ }
+
+ return filtered;
+}
+
+static Vector * VectorFilterRef(const Vector * vector, fVectorElemPredicate predicate, void * args) {
+ Vector * filtered = (Vector *) object_create(Vector);
+ size_t i = 0;
+ char * it = NULL;
+
+ if (!filtered) {
+ mcx_log(LOG_ERROR, "Vector: FilterReferences: Not enough memory");
+ return NULL;
+ }
+
+ filtered->Setup(filtered, sizeof(void *), NULL, NULL, NULL);
+
+ for (i = 0, it = (char*)vector->elements_; i < vector->size_; ++i, it += vector->elemSize_) {
+ if (predicate((void *) it, args)) {
+ filtered->PushBack(filtered, (void *) &it);
+ }
+ }
+
+ return filtered;
+}
+
+
+static int VectorContains(Vector * vector, void * elem) {
+ size_t i = 0;
+
+ for (i = 0; i < vector->size_; i++) {
+ if (vector->At(vector, i) == elem) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void VectorSetup(
+ Vector * vector,
+ size_t elemSize,
+ fVectorElemInitializer elemInitializer,
+ fVectorElemSetter elemSetter,
+ fVectorElemDestructor elemDestructor)
+{
+ vector->elemSize_ = elemSize;
+ vector->elemInitializer_ = elemInitializer;
+ vector->elemSetter_ = elemSetter;
+ vector->elemDestructor_ = elemDestructor;
+}
+
+static void VectorDestructor(Vector * vector) {
+ if (vector->elements_) {
+ if (vector->elemDestructor_) {
+ size_t i = 0;
+ char * it = (char *)vector->elements_;
+
+ for (i = 0; i < vector->size_; ++i) {
+ vector->elemDestructor_((void *) (it + i * vector->elemSize_));
+ }
+ }
+
+ mcx_free(vector->elements_);
+ }
+}
+
+static Vector * VectorCreate(Vector * vector) {
+ vector->Setup = VectorSetup;
+ vector->Size = VectorSize;
+ vector->At = VectorAt;
+ vector->SetAt = VectorSetAt;
+ vector->Reserve = VectorReserve;
+ vector->PushBack = VectorPushBack;
+ vector->Append = VectorAppend;
+ vector->Filter = VectorFilter;
+ vector->FilterRef = VectorFilterRef;
+ vector->Find = VectorFind;
+ vector->FindIdx = VectorFindIdx;
+ vector->Contains = VectorContains;
+
+ vector->elements_ = NULL;
+
+ vector->elemSize_ = 0;
+ vector->elemDestructor_ = NULL;
+ vector->elemInitializer_ = NULL;
+ vector->elemSetter_ = NULL;
+
+ vector->size_ = 0;
+ vector->capacity_ = 0;
+ vector->increment_ = 10;
+
+ return vector;
+}
+
+OBJECT_CLASS(Vector, Object);
+
+
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif /* __cplusplus */
\ No newline at end of file
diff --git a/src/objects/Vector.h b/src/objects/Vector.h
new file mode 100644
index 0000000..5572555
--- /dev/null
+++ b/src/objects/Vector.h
@@ -0,0 +1,82 @@
+/********************************************************************************
+ * Copyright (c) 2022 AVL List GmbH and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Apache Software License 2.0 which is available at
+ * https://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ********************************************************************************/
+
+#ifndef MCX_OBJECTS_VECTOR_H
+#define MCX_OBJECTS_VECTOR_H
+
+#include "common/status.h"
+#include "objects/Object.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+
+typedef struct Vector Vector;
+
+typedef McxStatus (*fVectorElemInitializer)(void * elem);
+typedef McxStatus (*fVectorElemSetter)(void * elem, void * other);
+typedef void (*fVectorElemDestructor)(void * elem);
+typedef void (*fVectorSetup)(Vector * vector, size_t elemSize, fVectorElemInitializer elemInitializer,
+ fVectorElemSetter elemSetter, fVectorElemDestructor elemDestructor);
+typedef size_t (*fVectorSize)(const Vector * vector);
+typedef int (*fVectorElemPredicate)(void * elem, void * args);
+typedef void * (*fVectorFind)(const Vector * vector, fVectorElemPredicate pred, void * args);
+typedef size_t (*fVectorFindIdx)(const Vector * vector, fVectorElemPredicate pred, void * args);
+typedef void * (*fVectorAt)(const Vector * vector, size_t idx);
+typedef McxStatus (*fVectorSetAt)(Vector * vector, size_t pos, void * elem);
+typedef McxStatus (*fVectorReserve)(Vector * vector, size_t newCapacity);
+typedef McxStatus (*fVectorPushBack)(Vector * vector, void * elem);
+typedef McxStatus (*fVectorAppend)(Vector * vector, Vector * appendee);
+typedef Vector * (*fVectorFilter)(const Vector * vector, fVectorElemPredicate predicate, void * args);
+typedef Vector * (*fVectorFilterRef)(const Vector * vector, fVectorElemPredicate predicate, void * args);
+typedef int (*fVectorContains)(Vector * vector, void * elem);
+
+extern const struct ObjectClass _Vector;
+
+
+typedef struct Vector {
+ Object _;
+
+ fVectorSetup Setup;
+ fVectorSize Size;
+ fVectorAt At;
+ fVectorSetAt SetAt;
+ fVectorReserve Reserve;
+ fVectorPushBack PushBack;
+ fVectorAppend Append;
+ fVectorFilter Filter;
+ fVectorFilterRef FilterRef;
+ fVectorFind Find;
+ fVectorFindIdx FindIdx;
+ fVectorContains Contains;
+
+
+ void * elements_;
+
+ size_t elemSize_;
+ fVectorElemInitializer elemInitializer_;
+ fVectorElemSetter elemSetter_;
+ fVectorElemDestructor elemDestructor_;
+
+ size_t size_;
+ size_t capacity_;
+ size_t increment_;
+} Vector;
+
+
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif /* __cplusplus */
+
+#endif /* MCX_OBJECTS_VECTOR_H */
\ No newline at end of file
diff --git a/src/reader/EnumMapping.c b/src/reader/EnumMapping.c
index dc11b01..be08854 100644
--- a/src/reader/EnumMapping.c
+++ b/src/reader/EnumMapping.c
@@ -20,7 +20,7 @@ extern "C" {
MapStringInt storeLevelMapping[] = {
{"none", STORE_NONE},
- {"micro", STORE_COUPLING}, // fall back to COUPLING for now
+ {"micro", STORE_MICRO},
{"coupling", STORE_COUPLING},
{"synchronization", STORE_SYNCHRONIZATION},
{NULL, 0}
diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c
index e653d50..d675c97 100644
--- a/src/steptypes/StepType.c
+++ b/src/steptypes/StepType.c
@@ -9,6 +9,7 @@
********************************************************************************/
#include "core/Component.h"
+#include "core/Component_impl.h"
#include "core/SubModel.h"
#include "core/Databus.h"
#include "storage/ComponentStorage.h"
@@ -60,12 +61,13 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
}
}
+ TimeSnapshotStart(&comp->data->rtData.funcTimings.rtTriggerIn);
// TODO: Rename this to UpdateInChannels
if (TRUE == ComponentGetUseInputsAtCouplingStepEndTime(comp)) {
tmpTime = interval.startTime;
interval.startTime = interval.endTime;
- retVal = DatabusTriggerInConnections(comp->GetDatabus(comp), &interval);
+ retVal = DatabusTriggerConnectedInConnections(comp->GetDatabus(comp), &interval);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "%s: Update inports failed", comp->GetName(comp));
return RETURN_ERROR;
@@ -73,12 +75,13 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
interval.startTime = tmpTime;
} else {
- retVal = DatabusTriggerInConnections(comp->GetDatabus(comp), &interval);
+ retVal = DatabusTriggerConnectedInConnections(comp->GetDatabus(comp), &interval);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "%s: Update inports failed", comp->GetName(comp));
return RETURN_ERROR;
}
}
+ TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtTriggerIn);
#ifdef MCX_DEBUG
if (time < MCX_DEBUG_LOG_TIME) {
@@ -86,6 +89,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
}
#endif // MCX_DEBUG
+ TimeSnapshotStart((TimeSnapshot *) &comp->data->rtData.funcTimings.rtStoreIn);
if (TRUE == ComponentGetStoreInputsAtCouplingStepEndTime(comp)) {
retVal = comp->Store(comp, CHANNEL_STORE_IN, interval.endTime, level);
} else if (FALSE == ComponentGetStoreInputsAtCouplingStepEndTime(comp)) {
@@ -98,6 +102,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
mcx_log(LOG_ERROR, "%s: Storing inport failed", comp->GetName(comp));
return RETURN_ERROR;
}
+ TimeSnapshotEnd((TimeSnapshot *) &comp->data->rtData.funcTimings.rtStoreIn);
#ifdef MCX_DEBUG
if (time < MCX_DEBUG_LOG_TIME) {
@@ -121,6 +126,14 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
return RETURN_ERROR;
}
+ if (comp->PostDoStep) {
+ retVal = comp->PostDoStep(comp);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "%s: PostDoStep failed", comp->GetName(comp));
+ return RETURN_ERROR;
+ }
+ }
+
/* the last coupling step is the new synchronization step */
if (double_geq(comp->GetTime(comp), stepEndTime)) {
level = STORE_SYNCHRONIZATION;
@@ -134,6 +147,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
}
#endif // MCX_DEBUG
+ TimeSnapshotStart((TimeSnapshot *) &comp->data->rtData.funcTimings.rtStore);
retVal = comp->Store(comp, CHANNEL_STORE_OUT, comp->GetTime(comp), level);
if (RETURN_ERROR == retVal) {
mcx_log(LOG_ERROR, "%s: Storing outport failed", comp->GetName(comp));
@@ -149,6 +163,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP
mcx_log(LOG_ERROR, "%s: Storing real time factors failed", comp->GetName(comp));
return RETURN_ERROR;
}
+ TimeSnapshotEnd((TimeSnapshot *) &comp->data->rtData.funcTimings.rtStore);
}
if (comp->GetFinishState(comp) == COMP_IS_FINISHED) {
@@ -184,7 +199,7 @@ static McxStatus CompTriggerInputs(CompAndGroup * compGroup, void * param) {
return RETURN_ERROR;
}
- retVal = DatabusTriggerInConnections(comp->GetDatabus(comp), &interval);
+ retVal = DatabusTriggerConnectedInConnections(comp->GetDatabus(comp), &interval);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "%s: Updating inports failed", comp->GetName(comp));
return RETURN_ERROR;
@@ -236,6 +251,18 @@ McxStatus CompEnterCouplingStepMode(Component * comp, void * param) {
return RETURN_OK;
}
+McxStatus CompCollectModeSwitchData(Component * comp, void * param) {
+ McxStatus retVal = RETURN_OK;
+
+ retVal = DatabusCollectModeSwitchData(comp->GetDatabus(comp));
+ if (RETURN_OK != retVal) {
+ mcx_log(LOG_ERROR, "%s: Collecting mode switch data failed", comp->GetName(comp));
+ return RETURN_ERROR;
+ }
+
+ return RETURN_OK;
+}
+
McxStatus CompEnterCommunicationPoint(CompAndGroup * compGroup, void * param) {
const StepTypeParams * params = (const StepTypeParams *) param;
@@ -249,6 +276,11 @@ McxStatus CompEnterCommunicationPoint(CompAndGroup * compGroup, void * param) {
// ----------------------------------------------------------------------
// Step Type
+int IsStepTypeMultiThreading(StepTypeType type) {
+ return (type == STEP_TYPE_PARALLEL_MT
+ );
+}
+
static McxStatus StepTypeConfigure(StepType * stepType, StepTypeParams * params, SubModel * subModel) {
return RETURN_OK;
}
diff --git a/src/steptypes/StepType.h b/src/steptypes/StepType.h
index f555b11..b5eac5d 100644
--- a/src/steptypes/StepType.h
+++ b/src/steptypes/StepType.h
@@ -32,6 +32,9 @@ typedef enum StepTypeType {
} StepTypeType;
+int IsStepTypeMultiThreading(StepTypeType type);
+
+
typedef McxStatus (* fStepTypeDoStep)(StepType * stepType, StepTypeParams * params, SubModel * subModel);
typedef McxStatus (* fStepTypeFinish)(StepType * stepType, StepTypeParams * params, SubModel * subModel, FinishState * finishState);
typedef McxStatus (* fStepTypeConfigure)(StepType * stepType, StepTypeParams * params, SubModel * subModel);
@@ -56,6 +59,7 @@ struct StepTypeParams {
/* shared functionality between step types */
McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeParams * params);
McxStatus CompEnterCouplingStepMode(Component * comp, void * param);
+McxStatus CompCollectModeSwitchData(Component * comp, void * param);
McxStatus CompEnterCommunicationPoint(CompAndGroup * compGroup, void * param);
McxStatus CompDoStep(CompAndGroup * compGroup, void * param);
diff --git a/src/steptypes/StepTypeSequential.c b/src/steptypes/StepTypeSequential.c
index bbd6cc9..3e26842 100644
--- a/src/steptypes/StepTypeSequential.c
+++ b/src/steptypes/StepTypeSequential.c
@@ -61,7 +61,7 @@ McxStatus CompPreDoUpdateState(Component * comp, void * param) {
}
}
- retVal = DatabusTriggerInConnections(comp->GetDatabus(comp), &interval);
+ retVal = DatabusTriggerConnectedInConnections(comp->GetDatabus(comp), &interval);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "Simulation: Update inports for element PreDoUpdateState failed");
return RETURN_ERROR;
@@ -96,7 +96,7 @@ McxStatus CompPostDoUpdateState(Component * comp, void * param) {
}
}
- retVal = DatabusTriggerInConnections(comp->GetDatabus(comp), &interval);
+ retVal = DatabusTriggerConnectedInConnections(comp->GetDatabus(comp), &interval);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "Simulation: Update inports for element PostDoUpdateState failed");
return RETURN_ERROR;
diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c
index 4aa3807..7cf8f14 100644
--- a/src/storage/ChannelStorage.c
+++ b/src/storage/ChannelStorage.c
@@ -36,16 +36,16 @@ static McxStatus ChannelStorageRegisterChannelInternal(ChannelStorage * channelS
/* if values have already been written, do not allow registering additional channels */
if (channelStore->values) {
- info = channel->GetInfo(channel);
- mcx_log(LOG_ERROR, "Results: Register port %s: Cannot register ports to storage after values have been stored", info->GetLogName(info));
+ info = &channel->info;
+ mcx_log(LOG_ERROR, "Results: Register port %s: Cannot register ports to storage after values have been stored", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
/* add channel */
retVal = channels->PushBack(channels, (Object *)object_strong_reference(channel));
if (RETURN_OK != retVal) {
- info = channel->GetInfo(channel);
- mcx_log(LOG_DEBUG, "Results: Register port %s: Pushback of port failed", info->GetLogName(info));
+ info = &channel->info;
+ mcx_log(LOG_DEBUG, "Results: Register port %s: Pushback of port failed", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
@@ -56,8 +56,8 @@ static McxStatus ChannelStorageRegisterChannel(ChannelStorage * channelStore, Ch
ObjectContainer * channels = channelStore->channels;
if (0 == channels->Size(channels)) {
- ChannelInfo *info = channel->GetInfo(channel);
- mcx_log(LOG_ERROR, "Results: Register port %s: Port storage not yet setup", info->GetLogName(info));
+ ChannelInfo *info = &channel->info;
+ mcx_log(LOG_ERROR, "Results: Register port %s: Port storage not yet setup", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
@@ -65,7 +65,7 @@ static McxStatus ChannelStorageRegisterChannel(ChannelStorage * channelStore, Ch
}
static McxStatus ChannelStorageSetup(ChannelStorage * channelStore, int fullStorage) {
- ChannelInfo * timeInfo = NULL;
+ ChannelInfo timeInfo = { 0 };
Channel * timeChannel = NULL;
McxStatus retVal = RETURN_OK;
@@ -77,38 +77,35 @@ static McxStatus ChannelStorageSetup(ChannelStorage * channelStore, int fullStor
}
/* add time channel */
- timeInfo = (ChannelInfo *) object_create(ChannelInfo);
- if (!timeInfo) { /* this can only fail because of no memory */
- mcx_log(LOG_DEBUG, "Results: Setup port storage: No memory for time port data");
- return RETURN_ERROR;
+ retVal = ChannelInfoInit(&timeInfo);
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Results: Setup port storage: Initialization of time port data failed");
+ goto cleanup;
}
- retVal = timeInfo->Init(
- timeInfo,
- "Time", /* name */
- "", /* description */
- GetTimeUnitString(), /* unit */
- CHANNEL_DOUBLE, /* type */
- "" /* id*/ );
- if (RETURN_OK != retVal) {
- mcx_log(LOG_ERROR, "Results: Setup port storage: Could not setup time port data");
- return RETURN_ERROR;
+ retVal = ChannelInfoSetup(&timeInfo, "Time", "", GetTimeUnitString(), CHANNEL_DOUBLE, "");
+ if (RETURN_ERROR == retVal) {
+ mcx_log(LOG_ERROR, "Results: Setup port storage: Could not set up time port data");
+ goto cleanup;
}
timeChannel = (Channel *) object_create(Channel);
if (!timeChannel) { /* this can only fail because of no memory */
mcx_log(LOG_DEBUG, "Results: Setup port storage: No memory for time port");
- return RETURN_ERROR;
+ retVal = RETURN_ERROR;
+ goto cleanup;
}
- retVal = timeChannel->Setup(timeChannel, timeInfo);
+ retVal = timeChannel->Setup(timeChannel, &timeInfo);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "Results: Setup port storage: Could not setup time port");
- return RETURN_ERROR;
+ goto cleanup;
}
retVal = ChannelStorageRegisterChannelInternal(channelStore, timeChannel);
+cleanup:
+ ChannelInfoDestroy(&timeInfo);
object_destroy(timeChannel);
return retVal;
@@ -155,8 +152,8 @@ static McxStatus ChannelStorageSetValueFromReferenceAt(ChannelStorage * channelS
}
if (row >= channelStore->numValues) {
- ChannelInfo * info = channel->GetInfo(channel);
- ChannelValueInit(&channelStore->values[row * colNum + col], info->GetType(info));
+ ChannelInfo * info = &channel->info;
+ ChannelValueInit(&channelStore->values[row * colNum + col], info->type);
}
ChannelValueSetFromReference(&channelStore->values[row * colNum + col], reference);
@@ -207,8 +204,8 @@ static McxStatus ChannelStorageStoreFull(ChannelStorage * channelStore, double t
retVal = ChannelStorageSetValueFromReferenceAt(channelStore,
channelStore->numValues, i, channel->GetValueReference(channel));
if (RETURN_OK != retVal) { /* error msg in ChannelStorageSetValueFromReferenceAt */
- ChannelInfo *info = channel->GetInfo(channel);
- mcx_log(LOG_DEBUG, "Results: Error in store port %s", info->GetLogName(info));
+ ChannelInfo *info = &channel->info;
+ mcx_log(LOG_DEBUG, "Results: Error in store port %s", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
@@ -249,8 +246,8 @@ static McxStatus ChannelStorageStoreNonFull(ChannelStorage * channelStore, doubl
Channel * channel = (Channel *) channels->At(channels, i);
retVal = ChannelStorageSetValueFromReferenceAt(channelStore, 0, i, channel->GetValueReference(channel));
if (RETURN_OK != retVal) { /* error msg in ChannelStorageSetValueFromReferenceAt */
- ChannelInfo *info = channel->GetInfo(channel);
- mcx_log(LOG_DEBUG, "Results: Error in store port %s", info->GetLogName(info));
+ ChannelInfo *info = &channel->info;
+ mcx_log(LOG_DEBUG, "Results: Error in store port %s", ChannelInfoGetLogName(info));
return RETURN_ERROR;
}
}
@@ -267,6 +264,11 @@ static ChannelValue ChannelStorageGetValueAt(ChannelStorage * channelStore, size
return channelStore->values[row * colNum + col];
}
+static ChannelValue * ChannelStorageGetValuesAtRow(ChannelStorage * channelStore, size_t row) {
+ size_t colNum = channelStore->channels->Size(channelStore->channels);
+ return channelStore->values + row * colNum;
+}
+
static size_t ChannelStorageLength(ChannelStorage * channelStore) {
return channelStore->numValues;
@@ -277,7 +279,7 @@ static ChannelInfo * ChannelStorageGetChannelInfo(ChannelStorage * channelStore,
Channel * channel = (Channel *) channels->At(channels, idx);
if (channel) {
- return channel->GetInfo(channel);
+ return &channel->info;
} else {
return NULL;
}
@@ -304,7 +306,7 @@ static void ChannelStorageDestructor(ChannelStorage * channelStore) {
size_t i = 0;
if (channels->Size(channels) > 0) {
Channel * channel = (Channel *) channels->At(channels, 0);
- ChannelInfo * timeInfo = channel->GetInfo(channel);
+ ChannelInfo * timeInfo = &channel->info;
object_destroy(timeInfo);
}
for (i = 0; i < channels->Size(channels); i++) {
@@ -324,6 +326,7 @@ static ChannelStorage * ChannelStorageCreate(ChannelStorage * channelStore) {
channelStore->GetChannelNum = ChannelStorageGetChannelNum;
channelStore->GetValueAt = ChannelStorageGetValueAt;
+ channelStore->GetValuesAtRow = ChannelStorageGetValuesAtRow;
channelStore->Length = ChannelStorageLength;
channelStore->GetChannelInfo = ChannelStorageGetChannelInfo;
diff --git a/src/storage/ChannelStorage.h b/src/storage/ChannelStorage.h
index 0702875..481700a 100644
--- a/src/storage/ChannelStorage.h
+++ b/src/storage/ChannelStorage.h
@@ -26,6 +26,7 @@ typedef McxStatus (* fChannelStorageRegisterChannel)(ChannelStorage * channelSto
typedef McxStatus (* fChannelStorageStore)(ChannelStorage * channelStore, double time);
typedef size_t (* fChannelStorageGetChannelNum)(ChannelStorage * channelStore);
typedef ChannelValue (* fChannelStorageGetValueAt)(ChannelStorage * channelStore, size_t row, size_t col);
+typedef ChannelValue * (* fChannelStorageGetValuesAtRow)(ChannelStorage * channelStore, size_t row);
typedef size_t (* fChannelStorageLength)(ChannelStorage * channelStore);
typedef struct ChannelInfo * (* fChannelStorageGetChannelInfo)(ChannelStorage * channelStore, size_t idx);
@@ -40,6 +41,7 @@ typedef struct ChannelStorage {
fChannelStorageGetChannelNum GetChannelNum;
fChannelStorageGetValueAt GetValueAt;
+ fChannelStorageGetValuesAtRow GetValuesAtRow;
fChannelStorageLength Length;
diff --git a/src/storage/ComponentStorage.c b/src/storage/ComponentStorage.c
index f9b8008..a6ce392 100644
--- a/src/storage/ComponentStorage.c
+++ b/src/storage/ComponentStorage.c
@@ -50,9 +50,8 @@ static McxStatus ComponentStorageRegisterChannel(ComponentStorage * compStore, C
ChannelStorage * channels = compStore->channels[chType];
if (compStore->storeLevel > STORE_NONE) {
- ChannelInfo * info = channel->GetInfo(channel);
- if (compStore->storage->channelStoreEnabled[chType]
- && info->GetWriteResultFlag(info)) {
+ ChannelInfo * info = &channel->info;
+ if (compStore->storage->channelStoreEnabled[chType] && info->writeResult) {
return channels->RegisterChannel(channels, channel);
}
}
diff --git a/src/storage/ResultsStorage.c b/src/storage/ResultsStorage.c
index 41146ba..2b9858e 100644
--- a/src/storage/ResultsStorage.c
+++ b/src/storage/ResultsStorage.c
@@ -38,6 +38,7 @@ static StorageBackend * StorageBackendCreate(StorageBackend * backend) {
backend->Configure = NULL;
backend->Setup = NULL;
backend->Store = NULL;
+ backend->StoreChannelValues = NULL;
backend->Finished = NULL;
backend->id = 0;
@@ -168,7 +169,7 @@ static McxStatus StorageFinishModel(ResultsStorage * storage, SubModel * subMode
// Get values from Components
for (i = 0; i < storage->numComponents; i++) {
ComponentStorage * compStore = storage->componentStorage[i];
- if (subModel->IsElement(subModel, compStore->comp)) {
+ if (subModel->ContainsOrIsElement(subModel, compStore->comp)) {
compStore->Finished(compStore);
}
}
@@ -241,9 +242,13 @@ static McxStatus StorageAddBackend(ResultsStorage * storage, BackendType type, i
StorageBackend * storeBackend = NULL;
switch (type) {
case BACKEND_CSV:
- storeBackend = (StorageBackend *)object_create(StorageBackendCsv);
+ {
+ {
+ storeBackend = (StorageBackend *)object_create(StorageBackendCsv);
+ }
break;
}
+ }
if (NULL == storeBackend) {
mcx_log(LOG_ERROR, "The %s result storage backend could not be created", GetBackendTypeString(type));
return RETURN_ERROR;
@@ -396,7 +401,7 @@ static McxStatus ResultsStorageSetChannelStoreEnabled(ResultsStorage * storage,
return RETURN_OK;
}
-static McxStatus StorageRead(ResultsStorage * storage, ResultsInput * resultsInput, const Config * config) {
+static McxStatus StorageRead(ResultsStorage * storage, ResultsInput * resultsInput, const Config * config, int multiThreaded) {
BackendsInput * backendsInput = resultsInput->backends;
size_t i = 0;
McxStatus retVal = RETURN_OK;
diff --git a/src/storage/ResultsStorage.h b/src/storage/ResultsStorage.h
index 2a0e78e..47ff582 100644
--- a/src/storage/ResultsStorage.h
+++ b/src/storage/ResultsStorage.h
@@ -35,6 +35,7 @@ typedef struct StorageBackend StorageBackend;
typedef McxStatus (* fStorageBackendConfigure)(StorageBackend * backend, ResultsStorage * storage, const char * path, int flushEveryStore, int storeAtRuntime);
typedef McxStatus (* fStorageBackendSetup)(StorageBackend * backend);
typedef McxStatus (* fStorageBackendStore)(StorageBackend * backend, ChannelStoreType chType, size_t comp, size_t row);
+typedef McxStatus (* fStorageBackendStoreChannelValues)(StorageBackend * backend, ChannelStoreType chType, size_t comp, ChannelValue * channels, size_t num);
typedef McxStatus (* fStorageBackendFinished)(StorageBackend * backend);
extern const struct ObjectClass _StorageBackend;
@@ -42,10 +43,11 @@ extern const struct ObjectClass _StorageBackend;
struct StorageBackend {
Object _; // super class first
- fStorageBackendConfigure Configure;
- fStorageBackendSetup Setup;
- fStorageBackendStore Store;
- fStorageBackendFinished Finished;
+ fStorageBackendConfigure Configure;
+ fStorageBackendSetup Setup;
+ fStorageBackendStore Store;
+ fStorageBackendStoreChannelValues StoreChannelValues;
+ fStorageBackendFinished Finished;
int id;
@@ -56,7 +58,7 @@ struct StorageBackend {
struct ResultsStorage * storage;
};
-typedef McxStatus (* fResultsStorageRead)(ResultsStorage * storage, ResultsInput * resultsInput, const Config * config);
+typedef McxStatus (* fResultsStorageRead)(ResultsStorage * storage, ResultsInput * resultsInput, const Config * config, int multiThreaded);
typedef McxStatus (* fResultsStorageSetup)(ResultsStorage * storage, double startTime);
typedef McxStatus (* fResultsStorageFinished)(ResultsStorage * storage);
diff --git a/src/storage/StorageBackendCsv.c b/src/storage/StorageBackendCsv.c
index e467a7c..61eaf26 100644
--- a/src/storage/StorageBackendCsv.c
+++ b/src/storage/StorageBackendCsv.c
@@ -251,7 +251,7 @@ static McxStatus SetupComponentFilesCsv(StorageBackend * backend) {
for (chIdx = 0; chIdx < chNum; chIdx++) {
ChannelInfo * info = chStore->GetChannelInfo(chStore, chIdx);
- const char * channelName = info->GetName(info);
+ const char * channelName = ChannelInfoGetName(info);
char * quotedChannelName = QuoteString(channelName);
const char * sep = textBackend->separator;
@@ -270,7 +270,7 @@ static McxStatus SetupComponentFilesCsv(StorageBackend * backend) {
for (chIdx = 0; chIdx < chNum; chIdx++) {
ChannelInfo * info = chStore->GetChannelInfo(chStore, chIdx);
- const char * channelUnit = info->GetUnit(info);
+ const char * channelUnit = info->unitString;
const char * sep = textBackend->separator;
if (chIdx == 0) {
sep = "";
diff --git a/src/storage/StorageBackendText.c b/src/storage/StorageBackendText.c
index a951aad..56c38b0 100644
--- a/src/storage/StorageBackendText.c
+++ b/src/storage/StorageBackendText.c
@@ -25,6 +25,7 @@ extern "C" {
//declare storage functions
+static McxStatus StoreChannelValues(StorageBackend * backend, ChannelStoreType chType, size_t comp, ChannelValue * values, size_t num);
static McxStatus Store(StorageBackend * backend, ChannelStoreType chType, size_t comp, size_t row);
static McxStatus Finished(StorageBackend * backend);
static McxStatus StoreFull(StorageBackend * backend, ChannelStoreType chType, size_t comp, size_t row);
@@ -91,6 +92,7 @@ static McxStatus Configure(StorageBackend * backend, ResultsStorage * storage, c
} else {
backend->needsFullStorage = 0;
backend->Store = Store;
+ backend->StoreChannelValues = StoreChannelValues;
backend->Finished = Finished;
}
@@ -196,9 +198,8 @@ static char * QuoteString(const char * _str) {
return newStr;
}
-static McxStatus WriteRow(FILE * file, ChannelStorage * chStore, size_t row, const char * separator) {
+static McxStatus WriteRow(FILE * file, ChannelValue * values, size_t numChannels, const char * separator) {
size_t channel = 0;
- const size_t numChannels = chStore->GetChannelNum(chStore);
char staticBuffer[32];
int storedLen = 0;
@@ -209,7 +210,7 @@ static McxStatus WriteRow(FILE * file, ChannelStorage * chStore, size_t row, con
for (channel = 0; channel < numChannels; channel++) {
McxStatus retVal = RETURN_OK;
- ChannelValue val = chStore->GetValueAt(chStore, row, channel);
+ ChannelValue val = values[channel];
const char * sep = separator;
if (channel == 0) { // leave out separator at the beginning
sep = "";
@@ -259,8 +260,7 @@ static McxStatus WriteRow(FILE * file, ChannelStorage * chStore, size_t row, con
return RETURN_OK;
}
-
-static McxStatus Store(StorageBackend * backend, ChannelStoreType chType, size_t comp, size_t row) {
+static McxStatus StoreChannelValues(StorageBackend * backend, ChannelStoreType chType, size_t comp, ChannelValue * values, size_t num) {
StorageBackendText * textBackend = (StorageBackendText *) backend;
ResultsStorage * storage = backend->storage;
ComponentStorage * compStore = storage->componentStorage[comp];
@@ -271,10 +271,10 @@ static McxStatus Store(StorageBackend * backend, ChannelStoreType chType, size_t
mcx_log(LOG_ERROR, "Results: No result file for element %d", comp);
return RETURN_ERROR;
}
+
textFile = &(textBackend->comps[comp].files[chType]);
- MCX_DEBUG_LOG("STORE WRITE (%d) chtype %d row %d", comp, chType, row);
- retVal = WriteRow(textFile->fp, compStore->channels[chType], row, textBackend->separator);
+ retVal = WriteRow(textFile->fp, values, num, textBackend->separator);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "Results: Could not write result row for \"%s\"", textFile->name);
return RETURN_ERROR;
@@ -285,6 +285,16 @@ static McxStatus Store(StorageBackend * backend, ChannelStoreType chType, size_t
}
}
return RETURN_OK;
+
+}
+
+
+static McxStatus Store(StorageBackend * backend, ChannelStoreType chType, size_t comp, size_t row) {
+ ResultsStorage * storage = backend->storage;
+ ComponentStorage * compStore = storage->componentStorage[comp];
+ ChannelStorage * chStore = compStore->channels[chType];
+
+ return backend->StoreChannelValues(backend, chType, comp, chStore->GetValuesAtRow(chStore, row), chStore->GetChannelNum(chStore));
}
@@ -336,7 +346,7 @@ static McxStatus FinishedFull(StorageBackend * backend) {
if (storage->channelStoreEnabled[chType] && textFile) {
for (chIdx = 0; chIdx < chStore->Length(chStore); chIdx++) {
- McxStatus retVal = WriteRow(textFile->fp, chStore, chIdx, textBackend->separator);
+ McxStatus retVal = WriteRow(textFile->fp, chStore->GetValuesAtRow(chStore, chIdx), chStore->GetChannelNum(chStore), textBackend->separator);
if (RETURN_OK != retVal) {
mcx_log(LOG_ERROR, "Results: Could not write result row for %s", textFile->name);
finishedStatus = RETURN_ERROR;
diff --git a/src/util/common/time.c b/src/util/common/time.c
index 3cff9f2..c2951c3 100644
--- a/src/util/common/time.c
+++ b/src/util/common/time.c
@@ -20,6 +20,13 @@ void mcx_time_init(McxTime * time) {
mcx_time_diff(&now, &now, time);
}
+double mcx_time_to_milli_s(McxTime * time) {
+ return mcx_time_to_micro_s(time) / 1000.0;
+}
+double mcx_time_to_seconds(McxTime * time) {
+ return mcx_time_to_micro_s(time) / 1000000.0;
+}
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif /* __cplusplus */
\ No newline at end of file
diff --git a/src/util/linux/time.c b/src/util/linux/time.c
index 082200b..cc86196 100644
--- a/src/util/linux/time.c
+++ b/src/util/linux/time.c
@@ -66,8 +66,8 @@ void mcx_time_diff(McxTime * start, McxTime * end, McxTime * result) {
timersub(end, start, result);
}
-double mcx_time_to_seconds(McxTime * time) {
- return time->tv_sec + time->tv_usec / 1000000.0;
+double mcx_time_to_micro_s(McxTime * time) {
+ return time->tv_sec*1000000.0 + time->tv_usec;
}
McxTime mcx_seconds_to_time(int seconds) {
diff --git a/src/util/time.h b/src/util/time.h
index a8dfecd..c6a88f0 100644
--- a/src/util/time.h
+++ b/src/util/time.h
@@ -32,6 +32,8 @@ void mcx_cpu_time_get(McxTime * time);
void mcx_time_add(McxTime * a, McxTime * b, McxTime * result);
void mcx_time_diff(McxTime * start, McxTime * end, McxTime * result);
double mcx_time_to_seconds(McxTime * time);
+double mcx_time_to_micro_s(McxTime * time);
+double mcx_time_to_milli_s(McxTime * time);
McxTime mcx_seconds_to_time(int seconds);
long mcx_time_get_clock();
diff --git a/src/util/win/time.c b/src/util/win/time.c
index 3a9a191..990c9af 100644
--- a/src/util/win/time.c
+++ b/src/util/win/time.c
@@ -50,7 +50,7 @@ void mcx_time_diff(McxTime * start, McxTime * end, McxTime * result) {
result->QuadPart = end->QuadPart - start->QuadPart;
}
-double mcx_time_to_seconds(McxTime * time) {
+double mcx_time_to_micro_s(McxTime * time) {
McxTime freq;
McxTime micro_secs;
@@ -58,7 +58,7 @@ double mcx_time_to_seconds(McxTime * time) {
micro_secs.QuadPart = time->QuadPart * 1000000;
micro_secs.QuadPart /= freq.QuadPart;
- return micro_secs.QuadPart / 1000000.0;
+ return micro_secs.QuadPart;
}
McxTime mcx_seconds_to_time(int seconds) {