From ef1963722825c82af98c6a0b074590dc6edc5d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 22 Oct 2021 14:45:10 +0200 Subject: [PATCH 001/295] Fix whitespaces --- src/core/Component.h | 1 - src/core/SubModel.c | 3 ++- src/core/SubModel.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/Component.h b/src/core/Component.h index 406dfd2..01f9775 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -22,7 +22,6 @@ extern "C" { #endif /* __cplusplus */ - typedef enum ComponentFinishState { COMP_IS_FINISHED, COMP_IS_NOT_FINISHED, diff --git a/src/core/SubModel.c b/src/core/SubModel.c index 1e67fd5..c32232e 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -18,9 +18,10 @@ #include "core/channels/Channel.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* __cplusplus */ + static McxStatus SubModelGeneratorSetComponents(SubModelGenerator * subModelGenerator, ObjectContainer * comps, DependencyType depType); diff --git a/src/core/SubModel.h b/src/core/SubModel.h index 4ea4f66..bf7b221 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 From 0666de93ec2e70a8424aeab9fda3955acba83481 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:19:49 +0100 Subject: [PATCH 002/295] Add capacity to ObjectContainer --- src/objects/ObjectContainer.c | 17 +++++++++++------ src/objects/ObjectContainer.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index 610d724..5c96d25 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -30,14 +30,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 && 0 < size) { + mcx_log(LOG_ERROR, "ObjectContainer: Resize: Memory allocation failed"); + return RETURN_ERROR; + } } /* if we make the container larger, init new elements with NULL */ @@ -337,6 +340,8 @@ static ObjectContainer * ObjectContainerCreate(ObjectContainer * container) { container->elements = NULL; container->size = 0; + container->capacity = 0; + container->increment = 10; container->strToIdx = (StringContainer *) mcx_malloc(sizeof(StringContainer)); if (!container->strToIdx) { return NULL; } diff --git a/src/objects/ObjectContainer.h b/src/objects/ObjectContainer.h index a9fbf00..f7994c3 100644 --- a/src/objects/ObjectContainer.h +++ b/src/objects/ObjectContainer.h @@ -89,6 +89,8 @@ typedef struct ObjectContainer { struct Object ** elements; size_t size; + size_t capacity; + size_t increment; struct StringContainer * strToIdx; } ObjectContainer; From b15a6e8975340aa5d9dc294ed75b22416ba8d4e3 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:25:37 +0100 Subject: [PATCH 003/295] Use ObjectContainerResize in ObjectContainerPushBack --- src/objects/ObjectContainer.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index 5c96d25..b22b2a1 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -52,14 +52,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); From 6cf11739dc2d4eb09465a5d8d6e09165392016bc Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:28:12 +0100 Subject: [PATCH 004/295] Use size within ObjectContainer directly --- src/objects/ObjectContainer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index b22b2a1..afe990a 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -254,7 +254,7 @@ static Object * ObjectContainerGetByName(const ObjectContainer * container, cons 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; } @@ -267,7 +267,7 @@ static ObjectContainer * ObjectContainerFilter(ObjectContainer * container, fObj 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); @@ -282,7 +282,7 @@ static ObjectContainer * ObjectContainerFilterCtx(ObjectContainer * container, f 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 +294,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); } From ef60f7b6f0cedaf43fee81a19e54f4d986a9959b Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:30:36 +0100 Subject: [PATCH 005/295] Add ObjectList --- src/objects/ObjectContainer.c | 275 ++++++++++++++++++++++++++++++++-- src/objects/ObjectContainer.h | 108 +++++++++---- 2 files changed, 337 insertions(+), 46 deletions(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index afe990a..6450ad4 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 && 0 < size) { + 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; @@ -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; diff --git a/src/objects/ObjectContainer.h b/src/objects/ObjectContainer.h index f7994c3..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; From 03a2379a21ea6a9d962b989b7573e894cbdcb4a0 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:40:54 +0100 Subject: [PATCH 006/295] Use ObjectList instead of ObjectContainer --- src/core/Component.c | 14 +++++++------- src/core/Component.h | 4 ++-- src/core/Databus.c | 6 +++--- src/core/Databus.h | 2 +- src/core/Model.c | 4 ++-- src/core/SubModel.c | 4 ++-- src/core/channels/Channel.c | 10 +++++----- src/core/channels/Channel.h | 2 +- src/core/channels/Channel_impl.h | 2 +- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index ef09db6..70ec225 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -684,7 +684,7 @@ McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time return RETURN_OK; } -McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectContainer * connections, TimeInterval * time) { +McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time) { McxStatus retVal = RETURN_OK; mcx_time_init(&comp->data->rtData.stepClock); @@ -826,13 +826,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,7 +840,7 @@ 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); for (j = 0; j < conns->Size(conns); j++) { Connection * conn = (Connection *) conns->At(conns, j); @@ -881,7 +881,7 @@ 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); for (j = 0; j < conns->Size(conns); j++) { Connection * connection = (Connection *) conns->At(conns, j); @@ -901,7 +901,7 @@ 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); for (j = 0; j < conns->Size(conns); j++) { Connection * connection = (Connection *) conns->At(conns, j); @@ -928,7 +928,7 @@ 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); for (j = 0; j < conns->Size(conns); j++) { Connection * connection = (Connection *) conns->At(conns, j); diff --git a/src/core/Component.h b/src/core/Component.h index 01f9775..df865ee 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -77,7 +77,7 @@ 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); @@ -232,7 +232,7 @@ 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); struct Connection * GetInConnection(const Component * comp, size_t channelID); diff --git a/src/core/Databus.c b/src/core/Databus.c index e08a004..5bfbe38 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1686,7 +1686,7 @@ McxStatus DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) { for (i = 0; i < size; i++) { ChannelOut * out = db->data->out[i]; - ObjectContainer * conns = out->GetConnections(out); + ObjectList * conns = out->GetConnections(out); for (j = 0; j < conns->Size(conns); j++) { Connection * connection = (Connection *) conns->At(conns, j); @@ -1719,7 +1719,7 @@ McxStatus DatabusEnterCommunicationMode(Databus * db, double time) { for (i = 0; i < size; i++) { ChannelOut * out = db->data->out[i]; - ObjectContainer * conns = out->GetConnections(out); + ObjectList * conns = out->GetConnections(out); for (j = 0; j < conns->Size(conns); j++) { Connection * connection = (Connection *) conns->At(conns, j); @@ -1739,7 +1739,7 @@ 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++) { diff --git a/src/core/Databus.h b/src/core/Databus.h index b392150..aef2950 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -249,7 +249,7 @@ McxStatus DatabusTriggerInConnections(struct Databus * db, TimeInterval * consum 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 */ diff --git a/src/core/Model.c b/src/core/Model.c index 16d1a92..ecd59b6 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -287,7 +287,7 @@ 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); @@ -456,7 +456,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); diff --git a/src/core/SubModel.c b/src/core/SubModel.c index c32232e..4978637 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -423,7 +423,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]); @@ -477,7 +477,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]); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index be8f9e7..fcef4e8 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -525,7 +525,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 +537,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) { @@ -624,7 +624,7 @@ 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); } @@ -646,7 +646,7 @@ static const proc * ChannelOutGetFunction(ChannelOut * out) { return out->data->valueFunction; } -static ObjectContainer * ChannelOutGetConnections(ChannelOut * out) { +static ObjectList * ChannelOutGetConnections(ChannelOut * out) { return out->data->connections; } @@ -753,7 +753,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ChannelOut * out = (ChannelOut *)channel; ChannelInfo * info = ((Channel *)out)->GetInfo((Channel *)out); - ObjectContainer * conns = out->data->connections; + ObjectList * conns = out->data->connections; McxStatus retVal = RETURN_OK; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index 2b394f8..5dd16b6 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -192,7 +192,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/Channel_impl.h b/src/core/channels/Channel_impl.h index 60ef770..7066f89 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -95,7 +95,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; From 5ebc0bdb0d8e08445999c80b671f947a057c93c1 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:46:17 +0100 Subject: [PATCH 007/295] Use size variable --- src/core/Component.c | 12 ++++++++---- src/core/Databus.c | 10 +++++++--- src/core/channels/Channel.c | 3 ++- src/core/connections/Connection.c | 4 +++- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 70ec225..82c8296 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -841,8 +841,9 @@ static ObjectList * ComponentGetConnections(Component * fromComp, Component * to for (i = 0; i < DatabusGetOutChannelsNum(db); i++) { ChannelOut * out = DatabusGetOutChannel(db, i); 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); @@ -882,8 +883,9 @@ McxStatus ComponentOutConnectionsEnterInitMode(Component * comp) { for (i = 0; i < numOutChannels; i++) { ChannelOut * out = DatabusGetOutChannel(db, i); 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 @@ -902,8 +904,9 @@ McxStatus ComponentDoOutConnectionsInitialization(Component * comp, int onlyIfDe for (i = 0; i < numOutChannels; i++) { ChannelOut * out = DatabusGetOutChannel(db, i); 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)) { @@ -929,8 +932,9 @@ McxStatus ComponentOutConnectionsExitInitMode(Component * comp, double time) { for (i = 0; i < numOutChannels; i++) { ChannelOut * out = DatabusGetOutChannel(db, i); 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 diff --git a/src/core/Databus.c b/src/core/Databus.c index 5bfbe38..e20ebbb 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1687,8 +1687,9 @@ McxStatus DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) { for (i = 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 < conns->Size(conns); j++) { + for (j = 0; j < connSize; j++) { Connection * connection = (Connection *) conns->At(conns, j); ConnectionInfo * info = connection->GetInfo(connection); Component * target = info->GetTargetComponent(info); @@ -1720,8 +1721,9 @@ McxStatus DatabusEnterCommunicationMode(Databus * db, double time) { for (i = 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 < conns->Size(conns); j++) { + for (j = 0; j < connSize; j++) { Connection * connection = (Connection *) conns->At(conns, j); ConnectionInfo * info = connection->GetInfo(connection); @@ -1742,7 +1744,9 @@ McxStatus DatabusEnterCommunicationMode(Databus * db, 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); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index fcef4e8..667f761 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -818,7 +818,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // 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); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 2f3edad..eb6a51d 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -32,7 +32,9 @@ extern "C" { McxStatus CheckConnectivity(ObjectContainer * 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); From 6cd90ebaebd870ab21b49d765acc527422a59571 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:46:56 +0100 Subject: [PATCH 008/295] Cache ConnectionInfo type --- src/core/connections/ConnectionInfo.c | 9 ++++++++- src/core/connections/ConnectionInfo.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index ba5ebda..a2d68d5 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -198,6 +198,10 @@ static ChannelType ConnectionInfoGetType(ConnectionInfo * info) { 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; @@ -223,7 +227,9 @@ static ChannelType ConnectionInfoGetType(ConnectionInfo * info) { mcx_free(buffer); return CHANNEL_UNKNOWN; } - return outInfo->GetType(outInfo); + + info->connType = outInfo->GetType(outInfo); + return info->connType; } static char * ConnectionInfoConnectionString(ConnectionInfo * info) { @@ -359,6 +365,7 @@ static ConnectionInfo * ConnectionInfoCreate(ConnectionInfo * info) { info->SetInterExtraType = ConnectionInfoSetInterExtraType; + info->connType = CHANNEL_UNKNOWN; return info; } diff --git a/src/core/connections/ConnectionInfo.h b/src/core/connections/ConnectionInfo.h index 2c5f492..bd153e5 100644 --- a/src/core/connections/ConnectionInfo.h +++ b/src/core/connections/ConnectionInfo.h @@ -128,6 +128,8 @@ struct ConnectionInfo { fConnectionInfoSetInterExtraType SetInterExtraType; struct ConnectionInfoData * data; + + ChannelType connType; } ; #ifdef __cplusplus From 8b5cc36652caf499287d57ba5c01781bd3d6c89b Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 13 Nov 2021 20:47:38 +0100 Subject: [PATCH 009/295] Adapt coding style --- src/objects/ObjectContainer.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index 6450ad4..c3954b4 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -394,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"); @@ -410,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; } @@ -419,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; @@ -441,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; } @@ -454,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) { @@ -477,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; @@ -487,21 +483,18 @@ 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; i++) { if (container->At(container, i) == obj) { @@ -512,8 +505,7 @@ 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; i++) { @@ -527,7 +519,7 @@ 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; @@ -589,7 +581,7 @@ static ObjectContainer * ObjectContainerCreate(ObjectContainer * container) { 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); @@ -599,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 From a80e917dbe8f47b1c8faeb379da6693c1de961cd Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 15 Nov 2021 16:48:34 +0100 Subject: [PATCH 010/295] Remove size check in ObjectList/Container Resize --- src/objects/ObjectContainer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index c3954b4..6e451a7 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -52,7 +52,7 @@ static McxStatus ObjectListResize(ObjectList * container, size_t size) { if (oldCapacity < size) { container->capacity = size + container->increment; container->elements = (Object * *)mcx_realloc(container->elements, container->capacity * sizeof(Object *)); - if (!container->elements && 0 < size) { + if (!container->elements) { mcx_log(LOG_ERROR, "ObjectList: Resize: Memory allocation failed"); return RETURN_ERROR; } @@ -299,7 +299,7 @@ static McxStatus ObjectContainerResize(ObjectContainer * container, size_t size) if (oldCapacity < size) { container->capacity = size + container->increment; container->elements = (Object * *)mcx_realloc(container->elements, container->capacity * sizeof(Object *)); - if (!container->elements && 0 < size) { + if (!container->elements) { mcx_log(LOG_ERROR, "ObjectContainer: Resize: Memory allocation failed"); return RETURN_ERROR; } From 1433851a8d1a6656499423315732d4e2eded32c1 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 18 Nov 2021 10:29:59 +0100 Subject: [PATCH 011/295] Fix TypeConversionConvertBoolDouble --- src/core/Conversion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index d11f48a..fcff9e6 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -370,7 +370,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; } From 9acf45b1d921dd2ab60d0c4995ebab811c78ec56 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 23 Nov 2021 08:42:09 +0100 Subject: [PATCH 012/295] time: Add mcx_time_to_micro_s function --- src/util/common/time.c | 7 +++++++ src/util/linux/time.c | 4 ++-- src/util/time.h | 2 ++ src/util/win/time.c | 4 ++-- 4 files changed, 13 insertions(+), 4 deletions(-) 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) { From 7ea9280f1085224c179e7935aa418f28837818b4 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 23 Nov 2021 08:43:23 +0100 Subject: [PATCH 013/295] Add calcStart/EndWallClockTime to rt factor results --- src/core/Component.c | 35 +++++++++++++++++++++++++++++++++++ src/core/Component_impl.h | 6 ++++++ 2 files changed, 41 insertions(+) diff --git a/src/core/Component.c b/src/core/Component.c index 82c8296..5cb6136 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -282,6 +282,32 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { return RETURN_ERROR; } mcx_free(id); + + + id = CreateChannelID(comp->GetName(comp), "CalcStartWallClockTime"); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "CalcStartWallClockTime"); + return RETURN_ERROR; + } + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcStartWallClockTime", id, "time~mys", &comp->data->rtData.calcStartWallClockTime, CHANNEL_DOUBLE)) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "CalcStartWallClockTime"); + mcx_free(id); + return RETURN_ERROR; + } + mcx_free(id); + + + id = CreateChannelID(comp->GetName(comp), "CalcEndWallClockTime"); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "CalcEndWallClockTime"); + return RETURN_ERROR; + } + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcEndWallClockTime", id, "time~mys", &comp->data->rtData.calcEndWallClockTime, CHANNEL_DOUBLE)) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "CalcEndWallClockTime"); + mcx_free(id); + return RETURN_ERROR; + } + mcx_free(id); } return RETURN_OK; @@ -521,6 +547,12 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de /* total (all components + framework) rt factor */ rtData->totalRtFactor = mcx_time_to_seconds(&totalDiff) / rtData->commTime; rtData->totalRtFactorAvg = mcx_time_to_seconds(&totalDiffAvg) / timeDiff; + + mcx_time_diff(&rtData->startClock, &start, &rtData->lastDoStepStartClock); + mcx_time_diff(&rtData->startClock, &end, &rtData->lastDoStepEndClock); + + rtData->calcStartWallClockTime = mcx_time_to_micro_s(&rtData->lastDoStepStartClock); + rtData->calcEndWallClockTime = mcx_time_to_micro_s(&rtData->lastDoStepEndClock); } return RETURN_OK; @@ -1220,6 +1252,9 @@ static ComponentData * ComponentDataCreate(ComponentData * data) { mcx_time_init(&rtData->lastDoStepClock); mcx_time_init(&rtData->lastCommDoStepClock); + mcx_time_init(&rtData->lastDoStepStartClock); + mcx_time_init(&rtData->lastDoStepEndClock); + rtData->totalRtFactor = 0.; rtData->totalRtFactorAvg = 0.; diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index f680118..db3cfb2 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -54,6 +54,12 @@ struct ComponentRTFactorData { double totalRtFactor; double totalRtFactorAvg; + + McxTime lastDoStepStartClock; /* wall clock of last DoStep Start*/ + McxTime lastDoStepEndClock; /* wall clock of last DoStep End */ + + double calcStartWallClockTime; + double calcEndWallClockTime; }; From 34c8beea7b1ed62df728e62a78a69f5fa711c57a Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 23 Nov 2021 23:59:30 +0100 Subject: [PATCH 014/295] rtFactor: Use a more consistent naming --- src/core/Component.c | 133 +++++++++++++++++++------------------- src/core/Component_impl.h | 40 ++++++------ 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 5cb6136..7135ac5 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -216,7 +216,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { 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)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock", id, GetTimeUnitString(), &comp->data->rtData.rtTotalSum_s, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock"); mcx_free(id); return RETURN_ERROR; @@ -228,7 +228,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock Calc"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock Calc", id, GetTimeUnitString(), &comp->data->rtData.simTime, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock Calc", id, GetTimeUnitString(), &comp->data->rtData.rtCalcSum_s, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock Calc"); mcx_free(id); return RETURN_ERROR; @@ -240,7 +240,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor Calc"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc", id, "-", &comp->data->rtData.rtFactor, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc", id, "-", &comp->data->rtData.rtFactorCalc, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor Calc"); mcx_free(id); return RETURN_ERROR; @@ -252,7 +252,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor Calc (Avg)"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc (Avg)", id, "-", &comp->data->rtData.rtFactorAvg, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc (Avg)", id, "-", &comp->data->rtData.rtFactorCalcAvg, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor Calc (Avg)"); mcx_free(id); return RETURN_ERROR; @@ -264,7 +264,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor", id, "-", &comp->data->rtData.totalRtFactor, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor", id, "-", &comp->data->rtData.rtFactorTotal, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor"); mcx_free(id); return RETURN_ERROR; @@ -276,7 +276,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock Calc"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor (Avg)", id, "-", &comp->data->rtData.totalRtFactorAvg, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor (Avg)", id, "-", &comp->data->rtData.rtFactorTotalAvg, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock Calc"); mcx_free(id); return RETURN_ERROR; @@ -284,12 +284,14 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { mcx_free(id); + + id = CreateChannelID(comp->GetName(comp), "CalcStartWallClockTime"); if (!id) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "CalcStartWallClockTime"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcStartWallClockTime", id, "time~mys", &comp->data->rtData.calcStartWallClockTime, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcStartWallClockTime", id, "time~mys", &comp->data->rtData.rtCalcStart_mys, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "CalcStartWallClockTime"); mcx_free(id); return RETURN_ERROR; @@ -302,7 +304,7 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "CalcEndWallClockTime"); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcEndWallClockTime", id, "time~mys", &comp->data->rtData.calcEndWallClockTime, CHANNEL_DOUBLE)) { + if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcEndWallClockTime", id, "time~mys", &comp->data->rtData.rtCalcEnd_mys, CHANNEL_DOUBLE)) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "CalcEndWallClockTime"); mcx_free(id); return RETURN_ERROR; @@ -412,10 +414,10 @@ 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; + 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; } @@ -456,14 +458,14 @@ 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 */ + McxTime rtStartCalc, rtEndCalc, rtDeltaCalc; 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); + mcx_time_get(&rtStartCalc); } MCX_DEBUG_LOG("DoStep: %.16f -> %.16f", time, endTime); @@ -511,48 +513,41 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de if (comp->data->rtData.enabled) { ComponentRTFactorData * rtData = &comp->data->rtData; - double timeDiff = endTime - rtData->startTime; + double simCalcSum = endTime - rtData->simStartTime; - /* wall time of this DoStep */ - mcx_time_get(&end); + mcx_time_get(&rtEndCalc); // wall time of this DoStep + mcx_time_diff(&rtStartCalc, &rtEndCalc, &rtDeltaCalc); // data for local rt factor - /* data for local rt factor */ - mcx_time_diff(&start, &end, &diff); + mcx_time_diff(&rtData->rtLastCompEnd, &rtEndCalc, &rtTotal); // data for total rt factor and avg rt factor + mcx_time_diff(&rtData->rtCompStart, &rtEndCalc, &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 = rtEndCalc; // 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 = mcx_time_to_seconds(&rtTotalSum) / simCalcSum; - mcx_time_diff(&rtData->startClock, &start, &rtData->lastDoStepStartClock); - mcx_time_diff(&rtData->startClock, &end, &rtData->lastDoStepEndClock); + mcx_time_diff(&rtData->rtCompStart, &rtStartCalc, &rtData->rtCalcStart); + mcx_time_diff(&rtData->rtCompStart, &rtEndCalc, &rtData->rtCalcEnd); - rtData->calcStartWallClockTime = mcx_time_to_micro_s(&rtData->lastDoStepStartClock); - rtData->calcEndWallClockTime = mcx_time_to_micro_s(&rtData->lastDoStepEndClock); + rtData->rtCalcStart_mys = mcx_time_to_micro_s(&rtData->rtCalcStart); + rtData->rtCalcEnd_mys = mcx_time_to_micro_s(&rtData->rtCalcEnd); } return RETURN_OK; @@ -703,9 +698,10 @@ struct Dependencies * ComponentGetInOutGroupsNoDependency(const Component * comp McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time) { McxStatus retVal = RETURN_OK; - mcx_time_init(&comp->data->rtData.stepClock); - comp->data->rtData.commTime = 0; - comp->data->rtData.lastCommDoStepClock = comp->data->rtData.lastDoStepClock; + mcx_time_init(&comp->data->rtData.rtCommStepTime); + comp->data->rtData.simCommStepTime = 0; + comp->data->rtData.rtLastCompEnd = comp->data->rtData.rtLastEndCalc; + 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); @@ -719,9 +715,10 @@ McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time) { McxStatus retVal = RETURN_OK; - mcx_time_init(&comp->data->rtData.stepClock); - comp->data->rtData.commTime = 0; - comp->data->rtData.lastCommDoStepClock = comp->data->rtData.lastDoStepClock; + mcx_time_init(&comp->data->rtData.rtCommStepTime); + comp->data->rtData.simCommStepTime = 0; + comp->data->rtData.rtLastCompEnd = comp->data->rtData.rtLastEndCalc; + 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); @@ -1236,27 +1233,29 @@ 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->simTime = 0.; - rtData->simTimeTotal = 0.; - rtData->stepTime = 0.; - rtData->startTime = 0.; - rtData->commTime = 0.; + rtData->simStartTime = 0.; + rtData->simCommStepTime = 0.; - rtData->rtFactor = 0.; - rtData->rtFactorAvg = 0.; + rtData->rtFactorCalc = 0.; + rtData->rtFactorCalcAvg = 0.; - mcx_time_init(&rtData->startClock); - mcx_time_init(&rtData->lastDoStepClock); - mcx_time_init(&rtData->lastCommDoStepClock); + mcx_time_init(&rtData->rtCompStart); + mcx_time_init(&rtData->rtLastEndCalc); + mcx_time_init(&rtData->rtLastCompEnd); - mcx_time_init(&rtData->lastDoStepStartClock); - mcx_time_init(&rtData->lastDoStepEndClock); + mcx_time_init(&rtData->rtCalcStart); + mcx_time_init(&rtData->rtCalcEnd); - rtData->totalRtFactor = 0.; - rtData->totalRtFactorAvg = 0.; + rtData->rtFactorTotal = 0.; + rtData->rtFactorTotalAvg = 0.; data->hasOwnInputEvaluationTime = FALSE; data->useInputsAtCouplingStepEndTime = FALSE; diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index db3cfb2..b85e443 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -33,33 +33,35 @@ 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 - double simTime; /* time in doStep since simulation start */ - double simTimeTotal; /* time since initialize */ - double stepTime; /* time in the current communication step */ + McxTime rtCommStepTime; // ticks in the current communication step + double rtCommStepTime_s; // time in the current communication step - double startTime; /* start time of simulation */ - double commTime; /* simulated time in current communication step */ + double simCommStepTime; // simulated time in current communication step - double rtFactor; - double rtFactorAvg; + double rtTotalSum_s; // time since initialize - McxTime startClock; /* wall clock of start of simulation */ - McxTime lastDoStepClock; /* wall clock of last DoStep */ + double simStartTime; // start time of simulation - /* wall clock of last DoStep before entering communication mode */ - McxTime lastCommDoStepClock; + double rtFactorCalc; + double rtFactorCalcAvg; - double totalRtFactor; - double totalRtFactorAvg; + double rtFactorTotal; + double rtFactorTotalAvg; - McxTime lastDoStepStartClock; /* wall clock of last DoStep Start*/ - McxTime lastDoStepEndClock; /* wall clock of last DoStep End */ + McxTime rtCompStart; // wall clock of start of simulation - double calcStartWallClockTime; - double calcEndWallClockTime; + McxTime rtLastEndCalc; // wall clock of last Calc End + + McxTime rtLastCompEnd; // wall clock of last DoStep before entering communication mode + + McxTime rtCalcStart; // wall clock of last DoStep Start + double rtCalcStart_mys; + + McxTime rtCalcEnd; // wall clock of last DoStep End + double rtCalcEnd_mys; }; From e121150ae0c7c4e4846e5c2bbc32b5468f100f57 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 24 Nov 2021 12:20:28 +0100 Subject: [PATCH 015/295] Add ComponentBeforeDoSteps() --- src/core/Component.c | 3 +++ src/core/Component.h | 1 + src/core/Model.c | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/src/core/Component.c b/src/core/Component.c index 7135ac5..8084d6e 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -418,7 +418,10 @@ McxStatus ComponentInitialize(Component * comp, size_t group, double startTime) 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; +} +McxStatus ComponentBeforeDoSteps(Component * comp, void * param) { return RETURN_OK; } diff --git a/src/core/Component.h b/src/core/Component.h index df865ee..b68477c 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -224,6 +224,7 @@ McxStatus ComponentRegisterStorage(Component* comp, struct ResultsStorage* stora 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); diff --git a/src/core/Model.c b/src/core/Model.c index ecd59b6..98bf8a9 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -1194,6 +1194,13 @@ static McxStatus ModelInitialize(Model * model) { return RETURN_ERROR; } + + retVal = subModel->LoopComponents(subModel, ComponentBeforeDoSteps, NULL); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Initialization of elements failed"); + return retVal; + } + return RETURN_OK; } From fc70701ff76abdb6a6c494b5fb8b2914cc5c56b6 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 24 Nov 2021 12:26:15 +0100 Subject: [PATCH 016/295] Use rtGlobalSimStart as reference for rtCalcStart and rtCalcEnd --- src/core/Component.c | 7 +++++-- src/core/Component_impl.h | 3 ++- src/core/Model.c | 12 ++++++++---- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 8084d6e..f53ae3d 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -422,6 +422,9 @@ McxStatus ComponentInitialize(Component * comp, size_t group, double startTime) } McxStatus ComponentBeforeDoSteps(Component * comp, void * param) { + McxTime * rtGlobalSimStart = (McxTime *)param; + comp->data->rtData.rtGlobalSimStart = *rtGlobalSimStart; + return RETURN_OK; } @@ -546,8 +549,8 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de rtData->rtFactorTotal = mcx_time_to_seconds(&rtTotal) / rtData->simCommStepTime; rtData->rtFactorTotalAvg = mcx_time_to_seconds(&rtTotalSum) / simCalcSum; - mcx_time_diff(&rtData->rtCompStart, &rtStartCalc, &rtData->rtCalcStart); - mcx_time_diff(&rtData->rtCompStart, &rtEndCalc, &rtData->rtCalcEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtStartCalc, &rtData->rtCalcStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtEndCalc, &rtData->rtCalcEnd); rtData->rtCalcStart_mys = mcx_time_to_micro_s(&rtData->rtCalcStart); rtData->rtCalcEnd_mys = mcx_time_to_micro_s(&rtData->rtCalcEnd); diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index b85e443..146474c 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -51,7 +51,8 @@ struct ComponentRTFactorData { double rtFactorTotal; double rtFactorTotalAvg; - McxTime rtCompStart; // wall clock of start of simulation + McxTime rtCompStart; // wall clock of start of component + McxTime rtGlobalSimStart; // wall clock of start of simulation McxTime rtLastEndCalc; // wall clock of last Calc End diff --git a/src/core/Model.c b/src/core/Model.c index 98bf8a9..926aa66 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -1194,11 +1194,15 @@ static McxStatus ModelInitialize(Model * model) { return RETURN_ERROR; } + { + McxTime rtGlobalSimStart; + mcx_time_get(&rtGlobalSimStart); - retVal = subModel->LoopComponents(subModel, ComponentBeforeDoSteps, NULL); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Model: Initialization of elements failed"); - return retVal; + retVal = subModel->LoopComponents(subModel, ComponentBeforeDoSteps, &rtGlobalSimStart); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Initialization of elements failed"); + return retVal; + } } return RETURN_OK; From 48c2dbb6543c9bd7ef19df6420b2eb706fc884bf Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 25 Nov 2021 13:56:35 +0100 Subject: [PATCH 017/295] component: Restructue ComponentSetupRTFactor --- src/core/Component.c | 111 ++++++++++++++++++++++--------------------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index f53ae3d..a13d32f 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -207,109 +207,114 @@ McxStatus ComponentSetup(Component * comp) { } static McxStatus ComponentSetupRTFactor(Component * comp) { - // Add rt factor if (comp->data->rtData.enabled) { char * id = NULL; + const char * chName = NULL; + McxStatus retVal = RETURN_OK; - id = CreateChannelID(comp->GetName(comp), "RealTime Clock"); + chName = "RealTime Clock"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock", id, GetTimeUnitString(), &comp->data->rtData.rtTotalSum_s, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, GetTimeUnitString(), &comp->data->rtData.rtTotalSum_s, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - id = CreateChannelID(comp->GetName(comp), "RealTime Clock Calc"); + chName = "RealTime Clock Calc"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock Calc"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Clock Calc", id, GetTimeUnitString(), &comp->data->rtData.rtCalcSum_s, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock Calc"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, GetTimeUnitString(), &comp->data->rtData.rtCalcSum_s, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - id = CreateChannelID(comp->GetName(comp), "RealTime Factor Calc"); + chName = "RealTime Factor Calc"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor Calc"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc", id, "-", &comp->data->rtData.rtFactorCalc, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor Calc"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorCalc, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - id = CreateChannelID(comp->GetName(comp), "RealTime Factor Calc (Avg)"); + chName = "RealTime Factor Calc (Avg)"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor Calc (Avg)"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor Calc (Avg)", id, "-", &comp->data->rtData.rtFactorCalcAvg, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor Calc (Avg)"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorCalcAvg, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - id = CreateChannelID(comp->GetName(comp), "RealTime Factor"); + chName = "RealTime Factor"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Factor"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor", id, "-", &comp->data->rtData.rtFactorTotal, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Factor"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorTotal, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - id = CreateChannelID(comp->GetName(comp), "RealTime Factor (Avg)"); + chName = "RealTime Factor (Avg)"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "RealTime Clock Calc"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "RealTime Factor (Avg)", id, "-", &comp->data->rtData.rtFactorTotalAvg, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "RealTime Clock Calc"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorTotalAvg, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - - - - id = CreateChannelID(comp->GetName(comp), "CalcStartWallClockTime"); + chName = "CalcStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "CalcStartWallClockTime"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcStartWallClockTime", id, "time~mys", &comp->data->rtData.rtCalcStart_mys, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "CalcStartWallClockTime"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtCalcStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); - - id = CreateChannelID(comp->GetName(comp), "CalcEndWallClockTime"); + chName = "CalcEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", "CalcEndWallClockTime"); + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); return RETURN_ERROR; } - if (RETURN_ERROR == DatabusAddRTFactorChannel(comp->data->databus, "CalcEndWallClockTime", id, "time~mys", &comp->data->rtData.rtCalcEnd_mys, CHANNEL_DOUBLE)) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", "CalcEndWallClockTime"); - mcx_free(id); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtCalcEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } - mcx_free(id); } return RETURN_OK; From dd5da10230a8ad1dec06330330af688c3a89ffc1 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 25 Nov 2021 15:24:00 +0100 Subject: [PATCH 018/295] component: Reuse rtData->rtTotalSum_s --- src/core/Component.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Component.c b/src/core/Component.c index a13d32f..be0b5dd 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -552,7 +552,7 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de // Sum = from simulation begin rtData->rtFactorTotal = mcx_time_to_seconds(&rtTotal) / rtData->simCommStepTime; - rtData->rtFactorTotalAvg = mcx_time_to_seconds(&rtTotalSum) / simCalcSum; + rtData->rtFactorTotalAvg = rtData->rtTotalSum_s / simCalcSum; mcx_time_diff(&rtData->rtGlobalSimStart, &rtStartCalc, &rtData->rtCalcStart); mcx_time_diff(&rtData->rtGlobalSimStart, &rtEndCalc, &rtData->rtCalcEnd); From 0cac58a8ac1b8e346f82eafea02fe721734db166 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 24 Nov 2021 12:32:38 +0100 Subject: [PATCH 019/295] Set rtData.rtCompStart in ComponentBeforeDoSteps() --- src/core/Component.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index be0b5dd..90b264f 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -420,9 +420,7 @@ McxStatus ComponentInitialize(Component * comp, size_t group, double startTime) comp->data->time = startTime; comp->data->rtData.simStartTime = startTime; - 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,6 +428,10 @@ McxStatus ComponentBeforeDoSteps(Component * comp, void * param) { McxTime * rtGlobalSimStart = (McxTime *)param; comp->data->rtData.rtGlobalSimStart = *rtGlobalSimStart; + 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; } From 4c34594914b804529bac899dc75f1231e9002d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 29 Nov 2021 15:19:03 +0100 Subject: [PATCH 020/295] Component post do-step hook The callback will be called after a component do-step, AFTER the out channels were updated via ComponentUpdateOutChannels (and implicitly via comp->UpdateOutChannels) --- src/core/Component.c | 1 + src/core/Component.h | 2 ++ src/steptypes/StepType.c | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/src/core/Component.c b/src/core/Component.c index 90b264f..04f4eb9 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -1119,6 +1119,7 @@ static Component * ComponentCreate(Component * comp) { comp->Store = ComponentStore; comp->DoStep = NULL; + comp->PostDoStep = NULL; comp->Finish = NULL; comp->GetNumInChannels = ComponentGetNumInChannels; diff --git a/src/core/Component.h b/src/core/Component.h index b68477c..e816d15 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -51,6 +51,7 @@ typedef McxStatus (* fComponentUpdateInChannels)(Component * comp); 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); @@ -135,6 +136,7 @@ struct Component { fComponentStore Store; fComponentDoStep DoStep; + fComponentPostDoStep PostDoStep; fComponentFinish Finish; // Read and Setup Channels diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index e653d50..688f69e 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -121,6 +121,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; From 11052c69e9fd47c8a99cb8b95d814fef3b476319 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 16 Nov 2021 00:42:00 +0100 Subject: [PATCH 021/295] Do not get FMU values in Fmu2DoStep() --- src/components/comp_fmu.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 4b3fee0..3582c52 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -1008,22 +1008,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; } From 5839809a877f5df7574f7b97443621eec1442fc8 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 16 Nov 2021 22:30:21 +0100 Subject: [PATCH 022/295] Add retrieval of observables to components (+submodels) --- src/core/Component.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ src/core/Component.h | 5 ++++ src/core/SubModel.c | 33 +++++++++++++++++++++ src/core/SubModel.h | 2 ++ 4 files changed, 110 insertions(+) diff --git a/src/core/Component.c b/src/core/Component.c index 04f4eb9..8fc4cc6 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -598,6 +598,73 @@ static size_t ComponentGetNumWriteRTFactorChannels(const Component * comp) { return DatabusInfoGetNumWriteChannels(DatabusGetRTFactorInfo(comp->data->databus)); } +static size_t ComponentGetNumMonitoringChannels(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 AddMonitoringChannels(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->GetInfo(channel)->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->GetInfo(channel)->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->GetInfo(channel)->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->GetInfo(channel)->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; @@ -1200,6 +1267,9 @@ static Component * ComponentCreate(Component * comp) { comp->data->typeString = NULL; + comp->GetNumMonitoringChannels = ComponentGetNumMonitoringChannels; + comp->AddMonitoringChannels = AddMonitoringChannels; + return comp; } diff --git a/src/core/Component.h b/src/core/Component.h index e816d15..a6e7a89 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -100,6 +100,8 @@ typedef McxStatus (*fComponentSetDouble)(Component * comp, double offset); typedef void (*fComponentSetIsPartOfInitCalculation)(Component * comp, int isPartOfInitCalculation); +typedef McxStatus (* fAddMonitoringChannels)(const Component * comp, StringContainer * container, size_t * count); + extern const struct ObjectClass _Component; struct Component { @@ -213,6 +215,9 @@ struct Component { fComponentSetDouble SetResultTimeOffset; + fComponentGetNumber GetNumMonitoringChannels; + fAddMonitoringChannels AddMonitoringChannels; + struct ComponentData * data; }; diff --git a/src/core/SubModel.c b/src/core/SubModel.c index 4978637..8b5ceff 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -796,6 +796,39 @@ int OrderedNodesCheckIfLoopsExist(OrderedNodes * nodes) { return FALSE; } +static size_t SubModelGetNumMonitoringChannels(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->GetNumMonitoringChannels(comp); + } + + return count; +} + +StringContainer * SubModelGetAllMonitoringChannelsContainer(SubModel * subModel) { + ObjectContainer * comps = subModel->components; + size_t numMonitoringChannels = SubModelGetNumMonitoringChannels(subModel); + + StringContainer * container = StringContainerCreate(numMonitoringChannels); + 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->AddMonitoringChannels(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 bf7b221..12ba479 100644 --- a/src/core/SubModel.h +++ b/src/core/SubModel.h @@ -75,6 +75,8 @@ struct SubModel { }; +StringContainer * SubModelGetAllMonitoringChannelsContainer(SubModel * subModel); + extern const struct ObjectClass _SubModelGenerator; struct SubModelGenerator { From 129f788d71e91abe0faa6b7f925681e0f82c57ff Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 17 Nov 2021 12:49:03 +0100 Subject: [PATCH 023/295] Rename Monitoring to Observable --- src/core/Component.c | 9 +++++---- src/core/Component.h | 6 +++--- src/core/SubModel.c | 12 ++++++------ src/core/SubModel.h | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 8fc4cc6..0ae8071 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -598,7 +598,7 @@ static size_t ComponentGetNumWriteRTFactorChannels(const Component * comp) { return DatabusInfoGetNumWriteChannels(DatabusGetRTFactorInfo(comp->data->databus)); } -static size_t ComponentGetNumMonitoringChannels(const Component * comp) { +static size_t ComponentGetNumObservableChannels(const Component * comp) { size_t num = 0; num += DatabusGetOutChannelsNum(comp->data->databus); @@ -609,7 +609,7 @@ static size_t ComponentGetNumMonitoringChannels(const Component * comp) { return num; } -static McxStatus AddMonitoringChannels(const Component * comp, StringContainer * container, size_t * count) { +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); @@ -1267,8 +1267,9 @@ static Component * ComponentCreate(Component * comp) { comp->data->typeString = NULL; - comp->GetNumMonitoringChannels = ComponentGetNumMonitoringChannels; - comp->AddMonitoringChannels = AddMonitoringChannels; + + comp->GetNumObservableChannels = ComponentGetNumObservableChannels; + comp->AddObservableChannels = AddObservableChannels; return comp; } diff --git a/src/core/Component.h b/src/core/Component.h index a6e7a89..325cb11 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -100,7 +100,7 @@ typedef McxStatus (*fComponentSetDouble)(Component * comp, double offset); typedef void (*fComponentSetIsPartOfInitCalculation)(Component * comp, int isPartOfInitCalculation); -typedef McxStatus (* fAddMonitoringChannels)(const Component * comp, StringContainer * container, size_t * count); +typedef McxStatus (* fAddObservableChannels)(const Component * comp, StringContainer * container, size_t * count); extern const struct ObjectClass _Component; @@ -215,8 +215,8 @@ struct Component { fComponentSetDouble SetResultTimeOffset; - fComponentGetNumber GetNumMonitoringChannels; - fAddMonitoringChannels AddMonitoringChannels; + fComponentGetNumber GetNumObservableChannels; + fAddObservableChannels AddObservableChannels; struct ComponentData * data; }; diff --git a/src/core/SubModel.c b/src/core/SubModel.c index 8b5ceff..1f940c5 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -796,7 +796,7 @@ int OrderedNodesCheckIfLoopsExist(OrderedNodes * nodes) { return FALSE; } -static size_t SubModelGetNumMonitoringChannels(const SubModel * subModel) { +static size_t SubModelGetNumObservableChannels(const SubModel * subModel) { size_t count = 0; ObjectContainer * comps = subModel->components; Component * comp = NULL; @@ -804,24 +804,24 @@ static size_t SubModelGetNumMonitoringChannels(const SubModel * subModel) { for (i = 0; i < comps->Size(comps); i++) { comp = (Component *) comps->At(comps, i); - count += comp->GetNumMonitoringChannels(comp); + count += comp->GetNumObservableChannels(comp); } return count; } -StringContainer * SubModelGetAllMonitoringChannelsContainer(SubModel * subModel) { +StringContainer * SubModelGetAllObservableChannelsContainer(SubModel * subModel) { ObjectContainer * comps = subModel->components; - size_t numMonitoringChannels = SubModelGetNumMonitoringChannels(subModel); + size_t numObservableChannels = SubModelGetNumObservableChannels(subModel); - StringContainer * container = StringContainerCreate(numMonitoringChannels); + 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->AddMonitoringChannels(comp, container, &count); + comp->AddObservableChannels(comp, container, &count); } StringContainerResize(container, count); diff --git a/src/core/SubModel.h b/src/core/SubModel.h index 12ba479..63ffa49 100644 --- a/src/core/SubModel.h +++ b/src/core/SubModel.h @@ -75,7 +75,7 @@ struct SubModel { }; -StringContainer * SubModelGetAllMonitoringChannelsContainer(SubModel * subModel); +StringContainer * SubModelGetAllObservableChannelsContainer(SubModel * subModel); extern const struct ObjectClass _SubModelGenerator; From 53eeda6d8c5202946cf9174468a4143f3273c21e Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 2 Oct 2021 04:16:59 +0200 Subject: [PATCH 024/295] Add STORE_MICRO store level --- src/CentralParts.h | 1 + src/reader/EnumMapping.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CentralParts.h b/src/CentralParts.h index 7740e94..5cae1a4 100644 --- a/src/CentralParts.h +++ b/src/CentralParts.h @@ -150,6 +150,7 @@ typedef enum StoreLevel { STORE_NONE = 1, STORE_SYNCHRONIZATION = 2, STORE_COUPLING = 3, + STORE_MICRO = 4, } StoreLevel; typedef enum { 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} From f0f3b71cb8eaa95faafc2c10ebd7b34a03e3c3c3 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 15 Nov 2021 02:07:07 +0100 Subject: [PATCH 025/295] Databus: Track connected inputs --- src/core/Databus.c | 31 +++++++++++++++++++++++++++++++ src/core/Databus.h | 2 ++ src/core/Databus_impl.h | 2 ++ 3 files changed, 35 insertions(+) diff --git a/src/core/Databus.c b/src/core/Databus.c index e20ebbb..ee7268f 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -527,6 +527,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 +573,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 +605,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 +641,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]) { diff --git a/src/core/Databus.h b/src/core/Databus.h index aef2950..2fe1f83 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -247,6 +247,8 @@ struct Connection * DatabusCreateConnection(struct Databus * db, struct Connecti */ McxStatus DatabusTriggerInConnections(struct Databus * db, TimeInterval * consumerTime); +McxStatus DatabusUpdateInConnected(Databus * db); + McxStatus DatabusEnterCouplingStepMode(struct Databus * db, double timeStepSize); McxStatus DatabusEnterCommunicationMode(struct Databus * db, double time); McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectList * connections, double time); diff --git a/src/core/Databus_impl.h b/src/core/Databus_impl.h index 40ef811..147985a 100644 --- a/src/core/Databus_impl.h +++ b/src/core/Databus_impl.h @@ -51,6 +51,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 */ From a1e57a2e139a0223909d9a57c85ad5f49d5b5a51 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 15 Nov 2021 02:08:10 +0100 Subject: [PATCH 026/295] Update connected inputs --- src/core/Component.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/Component.c b/src/core/Component.c index 0ae8071..0c5020a 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -201,7 +201,13 @@ McxStatus ComponentSetup(Component * comp) { if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not setup real time factor"); return RETURN_ERROR; - } + } + + retVal = DatabusUpdateInConnected(comp->data->databus); + if (RETURN_OK != retVal) { + ComponentLog(comp, LOG_ERROR, "Could not update in connections"); + return RETURN_ERROR; + } return RETURN_OK; } From 4d00f1586c1994de2bab676303b719cd3cff6334 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 15 Nov 2021 02:08:46 +0100 Subject: [PATCH 027/295] Add function to trigger only connected inputs --- src/core/Databus.c | 24 ++++++++++++++++++++++++ src/core/Databus.h | 1 + 2 files changed, 25 insertions(+) diff --git a/src/core/Databus.c b/src/core/Databus.c index ee7268f..4635392 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -726,6 +726,30 @@ McxStatus DatabusTriggerOutChannels(Databus *db, TimeInterval * time) { 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->GetInfo(channel); + mcx_log(LOG_ERROR, "Could not update inport %s", info->GetName(info)); + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + + McxStatus DatabusTriggerInConnections(Databus * db, TimeInterval * consumerTime) { if (!db) { mcx_log(LOG_ERROR, "Ports: Trigger inports: Invalid structure"); diff --git a/src/core/Databus.h b/src/core/Databus.h index 2fe1f83..f45491f 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -246,6 +246,7 @@ 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); From 5653e8c20029335a7a3d315b180e86bce050b167 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 15 Nov 2021 02:11:13 +0100 Subject: [PATCH 028/295] Trigger only connected inputs in steptypes --- src/steptypes/StepType.c | 6 +++--- src/steptypes/StepTypeSequential.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index 688f69e..6bb993d 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -65,7 +65,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP 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,7 +73,7 @@ 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; @@ -192,7 +192,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; 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; From 0dc4ac7a890f36341918bb7c4aa321754780a1e1 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 15 Dec 2021 16:11:07 +0100 Subject: [PATCH 029/295] Component: Remove redundant ComponentUpdateOutChannels() call --- src/core/Component.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 0c5020a..7621120 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -793,7 +793,6 @@ McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time ComponentLog(comp, LOG_ERROR, "Cannot enter communication mode at time %.17g s", time->startTime); return RETURN_ERROR; } - ComponentUpdateOutChannels(comp, time); return RETURN_OK; } @@ -810,7 +809,6 @@ McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, Objec ComponentLog(comp, LOG_ERROR, "Cannot enter communication mode for connections at time %.17g s", time->startTime); return RETURN_ERROR; } - ComponentUpdateOutChannels(comp, time); return RETURN_OK; } From ca44ee0231269d22f7f2eb73abf65a29e62fb84d Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 11 Jan 2022 15:58:10 +0100 Subject: [PATCH 030/295] Move DatabusUpdateInConnected() call to ModelConnectionsDone() --- src/core/Component.c | 6 ------ src/core/Model.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 7621120..801bb62 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -203,12 +203,6 @@ McxStatus ComponentSetup(Component * comp) { return RETURN_ERROR; } - retVal = DatabusUpdateInConnected(comp->data->databus); - if (RETURN_OK != retVal) { - ComponentLog(comp, LOG_ERROR, "Could not update in connections"); - return RETURN_ERROR; - } - return RETURN_OK; } diff --git a/src/core/Model.c b/src/core/Model.c index 926aa66..ed926ee 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -355,6 +355,20 @@ 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 ModelConnectionsDone(Model * model) { OrderedNodes * orderedNodes = NULL; McxStatus retVal = RETURN_OK; @@ -365,6 +379,12 @@ 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; + } + // determine initialization evaluation order if (model->config->cosimInitEnabled) { retVal = ModelCreateInitSubModel(model); From dde5cc1233c82d0d97e4443e30977ea457915ae3 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 11 Jan 2022 16:00:26 +0100 Subject: [PATCH 031/295] Model: Improve error handling in ModelConnectionsDone --- src/core/Model.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/Model.c b/src/core/Model.c index ed926ee..23bcb2c 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -388,7 +388,8 @@ static McxStatus ModelConnectionsDone(Model * model) { // 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; } } From 4fa9c4f694e34dc11dc6ed409248a646cf82abae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 23 Dec 2021 14:50:13 +0100 Subject: [PATCH 032/295] Expose a getter to values of constants --- src/components/comp_constant.c | 47 +++++++++++++++++++++++++++++----- src/components/comp_constant.h | 15 +++++++++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index 5e1f472..0cdff42 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 (%d) 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 */ From 67467e42e76d3083c032fd2b397a72dcaca3813c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 23 Dec 2021 16:22:09 +0100 Subject: [PATCH 033/295] Add explicit conversion functions --- src/core/Conversion.c | 202 ++++++++++++++++++++++++++++++++++++++++++ src/core/Conversion.h | 9 ++ 2 files changed, 211 insertions(+) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index fcff9e6..81c9ee8 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; @@ -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; @@ -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)); 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 */ From 51534113238e15b4ca5e2fd6bd51eb94d2407bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 23 Dec 2021 16:25:03 +0100 Subject: [PATCH 034/295] Preprocess connections to constant elements --- src/core/Model.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/src/core/Model.c b/src/core/Model.c index 23bcb2c..14a4491 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" @@ -147,6 +148,114 @@ 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) { + ObjectContainer * conns = model->connections; + ObjectContainer * filteredConns = (ObjectContainer *) object_create(ObjectContainer); + + size_t i = 0; + McxStatus retVal = RETURN_OK; + + if (!filteredConns) { + mcx_log(LOG_ERROR, "Not enough memory to filter out constant connections"); + return RETURN_ERROR; + } + + for (i = 0; i < conns->Size(conns); i++) { + ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i); + ChannelValue * src = NULL; + + Component * srcComp = info->GetSourceComponent(info); + CompConstant * srcCompConst = NULL; + Databus * srcDb = srcComp->GetDatabus(srcComp); + ChannelInfo * srcChannelInfo = DatabusGetOutChannelInfo(srcDb, info->GetSourceChannelID(info)); + + Component * trgComp = info->GetTargetComponent(info); + Databus * trgDb = trgComp->GetDatabus(trgComp); + ChannelInfo * trgChannelInfo = DatabusGetInChannelInfo(trgDb, info->GetTargetChannelID(info)); + + // if not a const conn, add to the filtered conns + if (0 != strcmp("CONSTANT", srcComp->GetType(srcComp))) { + filteredConns->PushBack(filteredConns, (Object *) 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->GetType(srcChannelInfo)); + retVal = ChannelValueSet(src, srcCompConst->GetValue(srcCompConst, info->GetSourceChannelID(info))); + if (retVal == RETURN_ERROR) { + goto cleanup_1; + } + + // out channel range and linear conversions + retVal = ConvertRange(srcChannelInfo->GetMin(srcChannelInfo), srcChannelInfo->GetMax(srcChannelInfo), src); + if (retVal == RETURN_ERROR) { + goto cleanup_1; + } + + retVal = ConvertLinear(srcChannelInfo->GetScale(srcChannelInfo), srcChannelInfo->GetOffset(srcChannelInfo), src); + if (retVal == RETURN_ERROR) { + goto cleanup_1; + } + + // type conversion + retVal = ConvertType(srcChannelInfo->GetType(srcChannelInfo), trgChannelInfo->GetType(trgChannelInfo), src); + if (retVal == RETURN_ERROR) { + goto cleanup_1; + } + + // unit conversion + retVal = ConvertUnit(srcChannelInfo->GetUnit(srcChannelInfo), trgChannelInfo->GetUnit(trgChannelInfo), src); + if (retVal == RETURN_ERROR) { + goto cleanup_1; + } + + // set the default value + if (trgChannelInfo->defaultValue) { + ChannelValueDestructor(trgChannelInfo->defaultValue); + } + trgChannelInfo->defaultValue = src; + + object_destroy(info); + + 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 McxStatus ModelPreprocessBinaryConnections(Model * model) { ObjectContainer * conns = model->connections; size_t connsSize = conns->Size(conns); @@ -263,6 +372,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"); From 6973a60dce0a49ea7fdedb5b1b7cabce0ad7b1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 23 Dec 2021 16:28:15 +0100 Subject: [PATCH 035/295] ChannelInUpdate: Trigger conversion only if channel is connected --- src/core/channels/Channel.c | 57 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 667f761..8e4127f 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -218,43 +218,42 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { 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->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->GetType(info) == CHANNEL_DOUBLE || - info->GetType(info) == CHANNEL_INTEGER) { - ChannelValue * val = &channel->data->value; + if (info->GetType(info) == CHANNEL_DOUBLE || info->GetType(info) == CHANNEL_INTEGER) { + ChannelValue * val = &channel->data->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", 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", 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", info->GetLogName(info)); + return RETURN_ERROR; + } } } } From d2c46a85d653002ce0ddc4f387bc6c7c197613a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 23 Dec 2021 16:31:10 +0100 Subject: [PATCH 036/295] Apply range/linear conversions immediately when setting a default value --- src/core/channels/Channel.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 8e4127f..b2f59fa 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -437,6 +437,18 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { // default value if (info->defaultValue) { ChannelValueSet(&channel->data->value, info->defaultValue); + + // apply range and linear conversions immediately + retVal = ConvertRange(info->GetMin(info), info->GetMax(info), &channel->data->value); + if (retVal == RETURN_ERROR) { + return RETURN_ERROR; + } + + retVal = ConvertLinear(info->GetScale(info), info->GetOffset(info), &channel->data->value); + if (retVal == RETURN_ERROR) { + return RETURN_ERROR; + } + channel->SetDefinedDuringInit(channel); channel->data->internalValue = ChannelValueReference(&channel->data->value); } From eac058b22d18de90ba837f0d24da679e9308c9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 13 Jan 2022 11:03:46 +0100 Subject: [PATCH 037/295] Avoid using magic values --- src/components/ComponentTypes.c | 4 +++- src/components/ComponentTypes.h | 1 + src/core/Model.c | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) 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/core/Model.c b/src/core/Model.c index 14a4491..4d53725 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -180,7 +180,7 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { ChannelInfo * trgChannelInfo = DatabusGetInChannelInfo(trgDb, info->GetTargetChannelID(info)); // if not a const conn, add to the filtered conns - if (0 != strcmp("CONSTANT", srcComp->GetType(srcComp))) { + if (0 != strcmp(compConstantTypeString, srcComp->GetType(srcComp))) { filteredConns->PushBack(filteredConns, (Object *) info); continue; } @@ -322,7 +322,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; @@ -1345,7 +1345,7 @@ static McxStatus ModelInitialize(Model * model) { } static const char * GetComponentAbbrev(const char * type) { - if (!strcmp(type, "CONSTANT")) { + if (!strcmp(type, compConstantTypeString)) { return "C"; } else if (!strcmp(type, "INTEGRATOR")) { return "INT"; From 48e22826bdffbcc89fb3e7e61ff7678baf5c1a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 13 Jan 2022 11:06:23 +0100 Subject: [PATCH 038/295] Group object creation and failure check --- src/core/Model.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/Model.c b/src/core/Model.c index 4d53725..dd2da25 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -156,11 +156,12 @@ static void UpdateBinaryChannelTypes(ObjectContainer * connInfos, Task * task) { */ static McxStatus ModelPreprocessConstConnections(Model * model) { ObjectContainer * conns = model->connections; - ObjectContainer * filteredConns = (ObjectContainer *) object_create(ObjectContainer); + ObjectContainer * filteredConns = NULL; size_t i = 0; McxStatus retVal = RETURN_OK; + filteredConns = (ObjectContainer*)object_create(ObjectContainer); if (!filteredConns) { mcx_log(LOG_ERROR, "Not enough memory to filter out constant connections"); return RETURN_ERROR; From 83445f5e6107823105d698c2b3248c3e304f9f92 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 22 Jan 2022 13:42:41 +0100 Subject: [PATCH 039/295] Remove obsolete comment --- src/CentralParts.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CentralParts.h b/src/CentralParts.h index 5cae1a4..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 From a8b032179afae5ad7ce446e29318975316c21031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 20 Jan 2022 13:49:24 +0100 Subject: [PATCH 040/295] Avoid cache misses during coupling step mode switches --- src/core/Databus.c | 57 +++++++++++++++++++++++++++++----------- src/core/Databus.h | 11 ++++++++ src/core/Model.c | 5 ++++ src/steptypes/StepType.c | 12 +++++++++ src/steptypes/StepType.h | 1 + 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 4635392..43b3e85 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1730,34 +1730,61 @@ 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; - +McxStatus DatabusCollectModeSwitchData(Databus * db) { ObjectContainer * 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]; + 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; + } + + // 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++) { - Connection * connection = (Connection *) conns->At(conns, j); + 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); 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 DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) { + size_t i = 0; + McxStatus retVal = RETURN_OK; + + 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 = info->ConnectionString(info); + mcx_log(LOG_ERROR, "Ports: Cannot enter coupling step mode of connection %s", buffer); + mcx_free(buffer); + return RETURN_ERROR; } } diff --git a/src/core/Databus.h b/src/core/Databus.h index f45491f..d55290a 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -250,6 +250,7 @@ McxStatus DatabusTriggerConnectedInConnections(struct Databus * db, TimeInterval 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, ObjectList * connections, double time); @@ -321,10 +322,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/Model.c b/src/core/Model.c index dd2da25..8e0471c 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -572,6 +572,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); diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index 6bb993d..a530281 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -244,6 +244,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; diff --git a/src/steptypes/StepType.h b/src/steptypes/StepType.h index f555b11..0cacd6c 100644 --- a/src/steptypes/StepType.h +++ b/src/steptypes/StepType.h @@ -56,6 +56,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); From 9e6c479489a077f659bb42483c3731e309bd0e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 27 Jan 2022 15:29:12 +0100 Subject: [PATCH 041/295] Avoid cache misses during synch mode switches --- src/core/Databus.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 43b3e85..c97e915 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1793,29 +1793,17 @@ McxStatus DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) { McxStatus DatabusEnterCommunicationMode(Databus * db, double time) { 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 < 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++) { - Connection * connection = (Connection *) conns->At(conns, j); - ConnectionInfo * info = connection->GetInfo(connection); - - 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 = info->ConnectionString(info); + mcx_log(LOG_ERROR, "Ports: Cannot enter communication mode of connection %s", buffer); + mcx_free(buffer); + return RETURN_ERROR; } } From bee00ab4584fd37c29ad6ef7a9516877d35d9d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 26 Jan 2022 13:47:58 +0100 Subject: [PATCH 042/295] Make IntFilter buffer size configurable --- src/core/Config.c | 17 ++++++++ src/core/Config.h | 2 + src/core/connections/Connection.c | 15 ++++++- src/core/connections/filters/IntExtFilter.c | 4 +- src/core/connections/filters/IntExtFilter.h | 2 +- src/core/connections/filters/IntFilter.c | 43 +++++++++++++++------ src/core/connections/filters/IntFilter.h | 2 +- 7 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/core/Config.c b/src/core/Config.c index ecd81e5..96ab213 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -295,6 +295,21 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + 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 * cosimInitEnabled = NULL; @@ -469,6 +484,8 @@ static Config * ConfigCreate(Config * config) { config->nanCheck = NAN_CHECK_ALWAYS; config->nanCheckNumMessages = MAX_NUM_MSGS; + config->interpolationBuffSize = 1000; + return config; } diff --git a/src/core/Config.h b/src/core/Config.h index 54e1cbe..f5122d0 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -61,6 +61,8 @@ struct Config { int writeAllLogFile; + size_t interpolationBuffSize; + int cosimInitEnabled; size_t maxNumTimeSnapWarnings; diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index eb6a51d..8978288 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -103,6 +103,15 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte } +static size_t DetermineFilterBufferSize(ConnectionInfo * info) { + Component * source = info->GetSourceComponent(info); + + Model * model = source->GetModel(source); + + return model->config->interpolationBuffSize; +} + + ChannelFilter * FilterFactory(Connection * connection) { ChannelFilter * filter = NULL; McxStatus retVal; @@ -130,7 +139,8 @@ ChannelFilter * FilterFactory(Connection * connection) { 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; } @@ -149,7 +159,8 @@ ChannelFilter * FilterFactory(Connection * connection) { 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); + 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; 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; From f93c77e372f4141ab438617785e84c7c48795df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 26 Jan 2022 14:57:50 +0100 Subject: [PATCH 043/295] Calculate required size of the IntFilter buffer --- src/core/Config.c | 15 ++++++++++++ src/core/Config.h | 1 + src/core/connections/Connection.c | 39 ++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/core/Config.c b/src/core/Config.c index 96ab213..b09364e 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -310,6 +310,20 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + 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 * cosimInitEnabled = NULL; @@ -485,6 +499,7 @@ static Config * ConfigCreate(Config * config) { config->nanCheckNumMessages = MAX_NUM_MSGS; config->interpolationBuffSize = 1000; + config->overrideInterpolationBuffSize = 0; return config; } diff --git a/src/core/Config.h b/src/core/Config.h index f5122d0..c75e499 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -62,6 +62,7 @@ struct Config { int writeAllLogFile; size_t interpolationBuffSize; + size_t overrideInterpolationBuffSize; int cosimInitEnabled; diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 8978288..6655b1f 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -102,13 +102,50 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte return RETURN_OK; } +static void LogStepRatios(double sourceStep, double targetStep, double synchStep, ConnectionInfo * info) { + char * connString = info->ConnectionString(info); + + if (sourceStep <= synchStep && targetStep <= synchStep) { + mcx_log(LOG_DEBUG, "%s: source <= synch && target <= synch", connString); + } else if (sourceStep <= synchStep && targetStep > synchStep) { + mcx_log(LOG_INFO, "CONN %s: source <= synch && target > synch", connString); + } else if (sourceStep > synchStep && targetStep <= synchStep) { + mcx_log(LOG_INFO, "CONN %s: source > synch && target <= synch", connString); + } else { + mcx_log(LOG_INFO, "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->GetSourceComponent(info); + Component * target = info->GetTargetComponent(info); 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 = ceil(synchStep / sourceStep) + 1; + } - return model->config->interpolationBuffSize; + return buffSize; } From 557c71db43a6dd236c3270099d3952b4459d2064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 26 Jan 2022 15:17:16 +0100 Subject: [PATCH 044/295] Add buffer limit and 'safety zone' --- src/core/Config.c | 30 ++++++++++++++++++++++++++++++ src/core/Config.h | 2 ++ src/core/connections/Connection.c | 11 +++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/core/Config.c b/src/core/Config.c index b09364e..953c6d1 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -324,6 +324,34 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + 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 * cosimInitEnabled = NULL; @@ -500,6 +528,8 @@ static Config * ConfigCreate(Config * config) { config->interpolationBuffSize = 1000; config->overrideInterpolationBuffSize = 0; + config->interpolationBuffSizeLimit = 100000; + config->interpolationBuffSizeSafetyExt = 1; return config; } diff --git a/src/core/Config.h b/src/core/Config.h index c75e499..487805c 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -63,6 +63,8 @@ struct Config { size_t interpolationBuffSize; size_t overrideInterpolationBuffSize; + size_t interpolationBuffSizeLimit; + size_t interpolationBuffSizeSafetyExt; int cosimInitEnabled; diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 6655b1f..c2fab2b 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -145,6 +145,17 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { buffSize = ceil(synchStep / sourceStep) + 1; } + buffSize += model->config->interpolationBuffSizeSafetyExt; + + if (buffSize > model->config->interpolationBuffSizeLimit) { + char * connString = info->ConnectionString(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; } From 6f89ec7e703d9cbce8d5b45a578bd098c1b3275b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 28 Jan 2022 09:41:40 +0100 Subject: [PATCH 045/295] Change log levels --- src/core/connections/Connection.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index c2fab2b..7f613f5 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -106,13 +106,13 @@ static void LogStepRatios(double sourceStep, double targetStep, double synchStep char * connString = info->ConnectionString(info); if (sourceStep <= synchStep && targetStep <= synchStep) { - mcx_log(LOG_DEBUG, "%s: source <= synch && target <= synch", connString); + MCX_DEBUG_LOG("CONN %s: source <= synch && target <= synch", connString); } else if (sourceStep <= synchStep && targetStep > synchStep) { - mcx_log(LOG_INFO, "CONN %s: source <= synch && target > synch", connString); + MCX_DEBUG_LOG("CONN %s: source <= synch && target > synch", connString); } else if (sourceStep > synchStep && targetStep <= synchStep) { - mcx_log(LOG_INFO, "CONN %s: source > synch && target <= synch", connString); + MCX_DEBUG_LOG("CONN %s: source > synch && target <= synch", connString); } else { - mcx_log(LOG_INFO, "CONN %s: source > synch && target > synch", connString); + MCX_DEBUG_LOG("CONN %s: source > synch && target > synch", connString); } mcx_free(connString); From 24d96260312f36aa7df1120ad5c0802ea51c8053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 1 Feb 2022 10:22:28 +0100 Subject: [PATCH 046/295] fmu2: Filter out connected inputs --- src/components/comp_fmu.c | 21 ++++++++++++++++++++- src/core/Component.c | 2 ++ src/core/Component.h | 4 ++++ src/core/Model.c | 22 ++++++++++++++++++++++ src/fmu/common_fmu2.c | 6 ++++++ src/fmu/common_fmu2.h | 2 ++ 6 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 3582c52..9fa18a1 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -852,6 +852,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 +881,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) { @@ -1343,6 +1360,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 801bb62..548bc1c 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -1269,6 +1269,8 @@ static Component * ComponentCreate(Component * comp) { comp->GetNumObservableChannels = ComponentGetNumObservableChannels; comp->AddObservableChannels = AddObservableChannels; + comp->OnConnectionsDone = NULL; + return comp; } diff --git a/src/core/Component.h b/src/core/Component.h index 325cb11..d22f795 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -72,6 +72,8 @@ 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); @@ -218,6 +220,8 @@ struct Component { fComponentGetNumber GetNumObservableChannels; fAddObservableChannels AddObservableChannels; + fOnConnectionsDone OnConnectionsDone; + struct ComponentData * data; }; diff --git a/src/core/Model.c b/src/core/Model.c index 8e0471c..fb55af2 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -485,6 +485,22 @@ McxStatus ModelInitInConnectedList(ObjectContainer * comps) { 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; @@ -501,6 +517,12 @@ static McxStatus ModelConnectionsDone(Model * model) { 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); diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 1f1913a..1fa6e6f 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -73,6 +73,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 +236,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; diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h index d4c2764..23b5291 100644 --- a/src/fmu/common_fmu2.h +++ b/src/fmu/common_fmu2.h @@ -52,6 +52,8 @@ struct Fmu2CommonStruct { ObjectContainer * params; ObjectContainer * initialValues; + ObjectContainer * connectedIn; + ObjectContainer * localValues; ObjectContainer * tunableParams; From 98be11514e2fa69261b565ce56f5010522ec885f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 1 Feb 2022 10:23:09 +0100 Subject: [PATCH 047/295] Do not set unconnected variables in every DoStep --- src/components/comp_fmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 9fa18a1..7ec833f 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -976,7 +976,7 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double fmi2_status_t status = fmi2_status_ok; // 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; From eba29f2e5691fb212a931da2b8a7b7a84f5a8c40 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 16 Dec 2021 20:56:05 +0100 Subject: [PATCH 048/295] component: Add SyncStart/EndWallClockTime timing results --- src/core/Component.c | 60 +++++++++++++++++++++++++++++++++++---- src/core/Component_impl.h | 6 ++++ 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 548bc1c..2cc9b06 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -315,6 +315,32 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } + + chName = "SyncStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtSyncStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + chName = "SyncEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtSyncEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } } return RETURN_OK; @@ -561,6 +587,9 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de rtData->rtCalcStart_mys = mcx_time_to_micro_s(&rtData->rtCalcStart); rtData->rtCalcEnd_mys = mcx_time_to_micro_s(&rtData->rtCalcEnd); + + rtData->rtSyncStart_mys = mcx_time_to_micro_s(&rtData->rtSyncStart); + rtData->rtSyncEnd_mys = mcx_time_to_micro_s(&rtData->rtSyncEnd); } return RETURN_OK; @@ -777,10 +806,15 @@ struct Dependencies * ComponentGetInOutGroupsNoDependency(const Component * comp McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time) { McxStatus retVal = RETURN_OK; + ComponentRTFactorData * rtData = &comp->data->rtData; + McxTime rtSyncStart, rtSyncEnd; - mcx_time_init(&comp->data->rtData.rtCommStepTime); - comp->data->rtData.simCommStepTime = 0; - comp->data->rtData.rtLastCompEnd = comp->data->rtData.rtLastEndCalc; + mcx_time_init(&rtData->rtCommStepTime); + rtData->simCommStepTime = 0; + rtData->rtLastCompEnd = rtData->rtLastEndCalc; + + mcx_time_get(&rtSyncStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncStart, &rtData->rtSyncStart); retVal = DatabusEnterCommunicationMode(comp->data->databus, time->startTime); if (RETURN_OK != retVal) { @@ -788,15 +822,23 @@ McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time return RETURN_ERROR; } + mcx_time_get(&rtSyncEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncEnd, &rtData->rtSyncEnd); + return RETURN_OK; } McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time) { McxStatus retVal = RETURN_OK; + ComponentRTFactorData * rtData = &comp->data->rtData; + McxTime rtSyncStart, rtSyncEnd; - mcx_time_init(&comp->data->rtData.rtCommStepTime); - comp->data->rtData.simCommStepTime = 0; - comp->data->rtData.rtLastCompEnd = comp->data->rtData.rtLastEndCalc; + mcx_time_init(&rtData->rtCommStepTime); + rtData->simCommStepTime = 0; + rtData->rtLastCompEnd = rtData->rtLastEndCalc; + + mcx_time_get(&rtSyncStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncStart, &rtData->rtSyncStart); retVal = DatabusEnterCommunicationModeForConnections(comp->data->databus, connections, time->startTime); if (RETURN_OK != retVal) { @@ -804,6 +846,9 @@ McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, Objec return RETURN_ERROR; } + mcx_time_get(&rtSyncEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncEnd, &rtData->rtSyncEnd); + return RETURN_OK; } @@ -1339,6 +1384,9 @@ static ComponentData * ComponentDataCreate(ComponentData * data) { mcx_time_init(&rtData->rtCalcStart); mcx_time_init(&rtData->rtCalcEnd); + mcx_time_init(&rtData->rtSyncStart); + mcx_time_init(&rtData->rtSyncEnd); + rtData->rtFactorTotal = 0.; rtData->rtFactorTotalAvg = 0.; diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index 146474c..336d19a 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -63,6 +63,12 @@ struct ComponentRTFactorData { McxTime rtCalcEnd; // wall clock of last DoStep End double rtCalcEnd_mys; + + McxTime rtSyncStart; // wall clock of sync start + double rtSyncStart_mys; + + McxTime rtSyncEnd; // wall clock of sync end + double rtSyncEnd_mys; }; From 381c2d7ed27b5fc95183a1250c54d9790879db3f Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 31 Jan 2022 09:05:11 +0100 Subject: [PATCH 049/295] component: Measure additional times --- src/components/comp_fmu.c | 17 ++++ src/core/Component.c | 188 ++++++++++++++++++++++++++++++++++++++ src/core/Component_impl.h | 31 +++++++ src/steptypes/StepType.c | 20 ++++ 4 files changed, 256 insertions(+) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 7ec833f..b27d766 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -13,6 +13,7 @@ #include "FMI/fmi_import_context.h" #include "components/comp_fmu_impl.h" #include "core/Databus.h" +#include "core/Component_impl.h" #include "fmilib.h" #include "fmu/Fmu1Value.h" #include "fmu/Fmu2Value.h" @@ -975,6 +976,11 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double McxStatus retVal; fmi2_status_t status = fmi2_status_ok; + ComponentRTFactorData * rtData = &comp->data->rtData; + McxTime rtInputStart, rtInputEnd; + mcx_time_get(&rtInputStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtInputStart, &rtData->rtInputStart); + // Set variables retVal = Fmu2SetVariableArray(fmu2, fmu2->connectedIn); if (RETURN_OK != retVal) { @@ -982,6 +988,9 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double return RETURN_ERROR; } + mcx_time_get(&rtInputEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtInputEnd, &rtData->rtInputEnd); + // Do calculations status = fmi2_import_do_step(fmu2->fmiImport, compFmu->lastCommunicationTimePoint, deltaTime, fmi2_true); if (fmi2_status_ok == status) { @@ -1288,6 +1297,11 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) { Fmu2CommonStruct * fmu2 = &comp_fmu->fmu2; McxStatus retVal; + ComponentRTFactorData * rtData = &comp->data->rtData; + McxTime rtOutputStart, rtOutputEnd; + mcx_time_get(&rtOutputStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputStart, &rtData->rtOutputStart); + retVal = Fmu2GetVariableArray(fmu2, fmu2->out); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Initialization computation failed"); @@ -1300,6 +1314,9 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) { return RETURN_ERROR; } + mcx_time_get(&rtOutputEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputEnd, &rtData->rtOutputEnd); + return RETURN_OK; } diff --git a/src/core/Component.c b/src/core/Component.c index 2cc9b06..8c5b459 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -341,6 +341,145 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); return RETURN_ERROR; } + + + + chName = "InputStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtInputStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + chName = "InputEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtInputEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "OutputStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtOutputStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + chName = "OutputEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtOutputEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "StoreStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "StoreEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "StoreInStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreInStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "StoreInEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreInEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "TriggerInStartWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtTriggerInStart_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } + + + chName = "TriggerInEndWallClockTime"; + id = CreateChannelID(comp->GetName(comp), chName); + if (!id) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); + return RETURN_ERROR; + } + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtTriggerInEnd_mys, CHANNEL_DOUBLE); + mcx_free(id); + if (retVal == RETURN_ERROR) { + ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + return RETURN_ERROR; + } } return RETURN_OK; @@ -590,6 +729,27 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de rtData->rtSyncStart_mys = mcx_time_to_micro_s(&rtData->rtSyncStart); rtData->rtSyncEnd_mys = mcx_time_to_micro_s(&rtData->rtSyncEnd); + + rtData->rtInputStart_mys = mcx_time_to_micro_s(&rtData->rtInputStart); + rtData->rtInputEnd_mys = mcx_time_to_micro_s(&rtData->rtInputEnd); + + rtData->rtOutputStart_mys = mcx_time_to_micro_s(&rtData->rtOutputStart); + rtData->rtOutputEnd_mys = mcx_time_to_micro_s(&rtData->rtOutputEnd); + + rtData->rtStoreStart_mys = rtData->rtStoreStartPre_mys; + rtData->rtStoreEnd_mys = rtData->rtStoreEndPre_mys; + + rtData->rtStoreStartPre_mys = mcx_time_to_micro_s(&rtData->rtStoreStart); + rtData->rtStoreEndPre_mys = mcx_time_to_micro_s(&rtData->rtStoreEnd); + + rtData->rtStoreInStart_mys = rtData->rtStoreInStartPre_mys; + rtData->rtStoreInEnd_mys = rtData->rtStoreInEndPre_mys; + + rtData->rtStoreInStartPre_mys = mcx_time_to_micro_s(&rtData->rtStoreInStart); + rtData->rtStoreInEndPre_mys = mcx_time_to_micro_s(&rtData->rtStoreInEnd); + + rtData->rtTriggerInStart_mys = mcx_time_to_micro_s(&rtData->rtTriggerInStart); + rtData->rtTriggerInEnd_mys = mcx_time_to_micro_s(&rtData->rtTriggerInEnd); } return RETURN_OK; @@ -1387,6 +1547,34 @@ static ComponentData * ComponentDataCreate(ComponentData * data) { mcx_time_init(&rtData->rtSyncStart); mcx_time_init(&rtData->rtSyncEnd); + mcx_time_init(&rtData->rtStoreStart); + mcx_time_init(&rtData->rtStoreEnd); + mcx_time_init(&rtData->rtStoreInStart); + mcx_time_init(&rtData->rtStoreInEnd); + mcx_time_init(&rtData->rtInputStart); + mcx_time_init(&rtData->rtInputEnd); + mcx_time_init(&rtData->rtOutputStart); + mcx_time_init(&rtData->rtOutputEnd); + mcx_time_init(&rtData->rtTriggerInStart); + mcx_time_init(&rtData->rtTriggerInEnd); + + rtData->rtInputStart_mys = 0.; + rtData->rtInputEnd_mys = 0.; + rtData->rtOutputStart_mys = 0.; + rtData->rtOutputEnd_mys = 0.; + rtData->rtStoreStart_mys = 0.; + rtData->rtStoreEnd_mys = 0.; + rtData->rtStoreStartPre_mys = 0.; + rtData->rtStoreEndPre_mys = 0.; + + rtData->rtStoreInStart_mys = 0.; + rtData->rtStoreInEnd_mys = 0.; + rtData->rtStoreInStartPre_mys = 0.; + rtData->rtStoreInEndPre_mys = 0.; + + rtData->rtTriggerInStart_mys = 0.; + rtData->rtTriggerInEnd_mys = 0.; + rtData->rtFactorTotal = 0.; rtData->rtFactorTotalAvg = 0.; diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index 336d19a..9b9bccb 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -69,6 +69,37 @@ struct ComponentRTFactorData { McxTime rtSyncEnd; // wall clock of sync end double rtSyncEnd_mys; + + McxTime rtInputStart; + double rtInputStart_mys; + McxTime rtInputEnd; + double rtInputEnd_mys; + + McxTime rtOutputStart; + double rtOutputStart_mys; + McxTime rtOutputEnd; + double rtOutputEnd_mys; + + McxTime rtStoreStart; + double rtStoreStart_mys; + double rtStoreStartPre_mys; + + McxTime rtStoreEnd; + double rtStoreEnd_mys; + double rtStoreEndPre_mys; + + McxTime rtStoreInStart; + double rtStoreInStart_mys; + double rtStoreInStartPre_mys; + + McxTime rtStoreInEnd; + double rtStoreInEnd_mys; + double rtStoreInEndPre_mys; + + McxTime rtTriggerInStart; + double rtTriggerInStart_mys; + McxTime rtTriggerInEnd; + double rtTriggerInEnd_mys; }; diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index a530281..2bf439a 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,6 +61,11 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } } + ComponentRTFactorData * rtData = &comp->data->rtData; + McxTime rtTriggerInStart, rtTriggerInEnd; + mcx_time_get(&rtTriggerInStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtTriggerInStart, &rtData->rtTriggerInStart); + // TODO: Rename this to UpdateInChannels if (TRUE == ComponentGetUseInputsAtCouplingStepEndTime(comp)) { tmpTime = interval.startTime; @@ -79,6 +85,8 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP return RETURN_ERROR; } } + mcx_time_get(&rtTriggerInEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtTriggerInEnd, &rtData->rtTriggerInEnd); #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { @@ -86,6 +94,10 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } #endif // MCX_DEBUG + McxTime rtStoreInStart, rtStoreInEnd; + mcx_time_get(&rtStoreInStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreInStart, &rtData->rtStoreInStart); + if (TRUE == ComponentGetStoreInputsAtCouplingStepEndTime(comp)) { retVal = comp->Store(comp, CHANNEL_STORE_IN, interval.endTime, level); } else if (FALSE == ComponentGetStoreInputsAtCouplingStepEndTime(comp)) { @@ -98,6 +110,8 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP mcx_log(LOG_ERROR, "%s: Storing inport failed", comp->GetName(comp)); return RETURN_ERROR; } + mcx_time_get(&rtStoreInEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreInEnd, &rtData->rtStoreInEnd); #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { @@ -142,6 +156,10 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } #endif // MCX_DEBUG + McxTime rtStoreStart, rtStoreEnd; + mcx_time_get(&rtStoreStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreStart, &rtData->rtStoreStart); + 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)); @@ -157,6 +175,8 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP mcx_log(LOG_ERROR, "%s: Storing real time factors failed", comp->GetName(comp)); return RETURN_ERROR; } + mcx_time_get(&rtStoreEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreEnd, &rtData->rtStoreEnd); } if (comp->GetFinishState(comp) == COMP_IS_FINISHED) { From 639c44adaec5ceb3a30e255ab129aca6d72f41f9 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Tue, 1 Feb 2022 22:47:22 +0100 Subject: [PATCH 050/295] Do not use uninitialized rtGlobalSimStart --- src/components/comp_fmu.c | 12 ++++++++---- src/core/Component.c | 3 +++ src/core/Component_impl.h | 2 ++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index b27d766..43dc586 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -1299,8 +1299,10 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) { ComponentRTFactorData * rtData = &comp->data->rtData; McxTime rtOutputStart, rtOutputEnd; - mcx_time_get(&rtOutputStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputStart, &rtData->rtOutputStart); + if (rtData->rtGlobalSimStartDefined) { + mcx_time_get(&rtOutputStart); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputStart, &rtData->rtOutputStart); + } retVal = Fmu2GetVariableArray(fmu2, fmu2->out); if (RETURN_OK != retVal) { @@ -1314,8 +1316,10 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) { return RETURN_ERROR; } - mcx_time_get(&rtOutputEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputEnd, &rtData->rtOutputEnd); + if (rtData->rtGlobalSimStartDefined) { + mcx_time_get(&rtOutputEnd); + mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputEnd, &rtData->rtOutputEnd); + } return RETURN_OK; } diff --git a/src/core/Component.c b/src/core/Component.c index 8c5b459..4e40d76 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -592,6 +592,7 @@ McxStatus ComponentInitialize(Component * comp, size_t group, double startTime) McxStatus ComponentBeforeDoSteps(Component * comp, void * param) { McxTime * rtGlobalSimStart = (McxTime *)param; comp->data->rtData.rtGlobalSimStart = *rtGlobalSimStart; + comp->data->rtData.rtGlobalSimStartDefined = TRUE; mcx_time_get(&comp->data->rtData.rtCompStart); comp->data->rtData.rtLastEndCalc = comp->data->rtData.rtCompStart; @@ -1575,6 +1576,8 @@ static ComponentData * ComponentDataCreate(ComponentData * data) { rtData->rtTriggerInStart_mys = 0.; rtData->rtTriggerInEnd_mys = 0.; + rtData->rtGlobalSimStartDefined = FALSE; + rtData->rtFactorTotal = 0.; rtData->rtFactorTotalAvg = 0.; diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index 9b9bccb..8b2cf41 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -54,6 +54,8 @@ struct ComponentRTFactorData { McxTime rtCompStart; // wall clock of start of component McxTime rtGlobalSimStart; // wall clock of start of simulation + int rtGlobalSimStartDefined; + McxTime rtLastEndCalc; // wall clock of last Calc End McxTime rtLastCompEnd; // wall clock of last DoStep before entering communication mode From e5da00e27b57429ec5304c5546733a9b488c3c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 4 Feb 2022 15:27:26 +0100 Subject: [PATCH 051/295] Extract common code into a function --- src/core/Component.c | 274 ++++++++++--------------------------------- 1 file changed, 63 insertions(+), 211 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 4e40d76..e735b46 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -206,278 +206,130 @@ McxStatus ComponentSetup(Component * comp) { 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) { if (comp->data->rtData.enabled) { - char * id = NULL; - const char * chName = NULL; McxStatus retVal = RETURN_OK; - chName = "RealTime Clock"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, GetTimeUnitString(), &comp->data->rtData.rtTotalSum_s, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + // RealTime channels + retVal = DefineTimingChannel(comp, "RealTime Clock", GetTimeUnitString(), &comp->data->rtData.rtTotalSum_s); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "RealTime Clock Calc"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, GetTimeUnitString(), &comp->data->rtData.rtCalcSum_s, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "RealTime Clock Calc", GetTimeUnitString(), &comp->data->rtData.rtCalcSum_s); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "RealTime Factor Calc"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorCalc, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "RealTime Factor Calc", "-", &comp->data->rtData.rtFactorCalc); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "RealTime Factor Calc (Avg)"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorCalcAvg, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "RealTime Factor Calc (Avg)", "-", &comp->data->rtData.rtFactorCalcAvg); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "RealTime Factor"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorTotal, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "RealTime Factor", "-", &comp->data->rtData.rtFactorTotal); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "RealTime Factor (Avg)"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "-", &comp->data->rtData.rtFactorTotalAvg, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "RealTime Factor (Avg)", "-", &comp->data->rtData.rtFactorTotalAvg); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "CalcStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtCalcStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + // Scheduling channels + retVal = DefineTimingChannel(comp, "CalcStartWallClockTime", "time~mys", &comp->data->rtData.rtCalcStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "CalcEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtCalcEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "CalcEndWallClockTime", "time~mys", &comp->data->rtData.rtCalcEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "SyncStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtSyncStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "SyncStartWallClockTime", "time~mys", &comp->data->rtData.rtSyncStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "SyncEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtSyncEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "SyncEndWallClockTime", "time~mys", &comp->data->rtData.rtSyncEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - - chName = "InputStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtInputStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "InputStartWallClockTime", "time~mys", &comp->data->rtData.rtInputStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "InputEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtInputEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "InputEndWallClockTime", "time~mys", &comp->data->rtData.rtInputEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "OutputStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtOutputStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "OutputStartWallClockTime", "time~mys", &comp->data->rtData.rtOutputStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - chName = "OutputEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtOutputEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "OutputEndWallClockTime", "time~mys", &comp->data->rtData.rtOutputEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "StoreStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "StoreStartWallClockTime", "time~mys", &comp->data->rtData.rtStoreStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "StoreEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "StoreEndWallClockTime", "time~mys", &comp->data->rtData.rtStoreEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "StoreInStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreInStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "StoreInStartWallClockTime", "time~mys", &comp->data->rtData.rtStoreInStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "StoreInEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtStoreInEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "StoreInEndWallClockTime", "time~mys", &comp->data->rtData.rtStoreInEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "TriggerInStartWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtTriggerInStart_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "TriggerInStartWallClockTime", "time~mys", &comp->data->rtData.rtTriggerInStart_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - - chName = "TriggerInEndWallClockTime"; - id = CreateChannelID(comp->GetName(comp), chName); - if (!id) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not create ID for port %s", chName); - return RETURN_ERROR; - } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, "time~mys", &comp->data->rtData.rtTriggerInEnd_mys, CHANNEL_DOUBLE); - mcx_free(id); - if (retVal == RETURN_ERROR) { - ComponentLog(comp, LOG_ERROR, "Setup real time factor: Could not add port %s", chName); + retVal = DefineTimingChannel(comp, "TriggerInEndWallClockTime", "time~mys", &comp->data->rtData.rtTriggerInEnd_mys); + if (RETURN_ERROR == retVal) { return RETURN_ERROR; } } From 15f54447be5abe439f8d96309a6252d6c77fd913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 4 Feb 2022 15:46:06 +0100 Subject: [PATCH 052/295] Enable profiling times with a development flag --- src/core/Component.c | 88 +++++++++++++++++++++------------------ src/core/Component.h | 2 +- src/core/Component_impl.h | 2 + src/core/Config.c | 14 +++++++ src/core/Config.h | 2 + 5 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index e735b46..a68c63a 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -57,7 +57,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 +149,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.profilingTimesEnabled = config->profilingMode; } retVal = comp->data->storage->Read(comp->data->storage, input->results); @@ -180,6 +181,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.profilingTimesEnabled = comp->data->model->config->profilingMode; } if (comp->data->model->task->params) { @@ -283,54 +285,56 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { return RETURN_ERROR; } - retVal = DefineTimingChannel(comp, "InputStartWallClockTime", "time~mys", &comp->data->rtData.rtInputStart_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + if (comp->data->rtData.profilingTimesEnabled) { + retVal = DefineTimingChannel(comp, "InputStartWallClockTime", "time~mys", &comp->data->rtData.rtInputStart_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "InputEndWallClockTime", "time~mys", &comp->data->rtData.rtInputEnd_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "InputEndWallClockTime", "time~mys", &comp->data->rtData.rtInputEnd_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "OutputStartWallClockTime", "time~mys", &comp->data->rtData.rtOutputStart_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "OutputStartWallClockTime", "time~mys", &comp->data->rtData.rtOutputStart_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "OutputEndWallClockTime", "time~mys", &comp->data->rtData.rtOutputEnd_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "OutputEndWallClockTime", "time~mys", &comp->data->rtData.rtOutputEnd_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "StoreStartWallClockTime", "time~mys", &comp->data->rtData.rtStoreStart_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "StoreStartWallClockTime", "time~mys", &comp->data->rtData.rtStoreStart_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "StoreEndWallClockTime", "time~mys", &comp->data->rtData.rtStoreEnd_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "StoreEndWallClockTime", "time~mys", &comp->data->rtData.rtStoreEnd_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "StoreInStartWallClockTime", "time~mys", &comp->data->rtData.rtStoreInStart_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "StoreInStartWallClockTime", "time~mys", &comp->data->rtData.rtStoreInStart_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "StoreInEndWallClockTime", "time~mys", &comp->data->rtData.rtStoreInEnd_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "StoreInEndWallClockTime", "time~mys", &comp->data->rtData.rtStoreInEnd_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "TriggerInStartWallClockTime", "time~mys", &comp->data->rtData.rtTriggerInStart_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; - } + retVal = DefineTimingChannel(comp, "TriggerInStartWallClockTime", "time~mys", &comp->data->rtData.rtTriggerInStart_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } - retVal = DefineTimingChannel(comp, "TriggerInEndWallClockTime", "time~mys", &comp->data->rtData.rtTriggerInEnd_mys); - if (RETURN_ERROR == retVal) { - return RETURN_ERROR; + retVal = DefineTimingChannel(comp, "TriggerInEndWallClockTime", "time~mys", &comp->data->rtData.rtTriggerInEnd_mys); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } } } @@ -1184,7 +1188,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); @@ -1390,6 +1394,8 @@ static ComponentData * ComponentDataCreate(ComponentData * data) { rtData->rtFactorCalc = 0.; rtData->rtFactorCalcAvg = 0.; + rtData->profilingTimesEnabled = FALSE; + mcx_time_init(&rtData->rtCompStart); mcx_time_init(&rtData->rtLastEndCalc); mcx_time_init(&rtData->rtLastCompEnd); diff --git a/src/core/Component.h b/src/core/Component.h index d22f795..80ab6ed 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -228,7 +228,7 @@ struct Component { /* 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); diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index 8b2cf41..6aa259d 100644 --- a/src/core/Component_impl.h +++ b/src/core/Component_impl.h @@ -72,6 +72,8 @@ struct ComponentRTFactorData { McxTime rtSyncEnd; // wall clock of sync end double rtSyncEnd_mys; + int profilingTimesEnabled; + McxTime rtInputStart; double rtInputStart_mys; McxTime rtInputEnd; diff --git a/src/core/Config.c b/src/core/Config.c index 953c6d1..66c5af2 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -295,6 +295,18 @@ 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) { @@ -531,6 +543,8 @@ static Config * ConfigCreate(Config * config) { config->interpolationBuffSizeLimit = 100000; config->interpolationBuffSizeSafetyExt = 1; + config->profilingMode = FALSE; + return config; } diff --git a/src/core/Config.h b/src/core/Config.h index 487805c..425ec23 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -68,6 +68,8 @@ struct Config { int cosimInitEnabled; + int profilingMode; + size_t maxNumTimeSnapWarnings; NaNCheckLevel nanCheck; From b0680ad47cb423f38950e9d79e93fb943017ba51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 8 Feb 2022 15:24:27 +0100 Subject: [PATCH 053/295] Restructure timings --- src/components/comp_fmu.c | 24 +--- src/core/Component.c | 241 +++++++++++++++++++++----------------- src/core/Component_impl.h | 92 +++++++-------- src/steptypes/StepType.c | 25 +--- 4 files changed, 189 insertions(+), 193 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 43dc586..8b305d6 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -976,20 +976,14 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double McxStatus retVal; fmi2_status_t status = fmi2_status_ok; - ComponentRTFactorData * rtData = &comp->data->rtData; - McxTime rtInputStart, rtInputEnd; - mcx_time_get(&rtInputStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtInputStart, &rtData->rtInputStart); - + TimeSnapshotStart(&comp->data->rtData.funcTimings.rtInput); // Set variables retVal = Fmu2SetVariableArray(fmu2, fmu2->connectedIn); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Setting inChannels failed"); return RETURN_ERROR; } - - mcx_time_get(&rtInputEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtInputEnd, &rtData->rtInputEnd); + TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtInput); // Do calculations status = fmi2_import_do_step(fmu2->fmiImport, compFmu->lastCommunicationTimePoint, deltaTime, fmi2_true); @@ -1297,13 +1291,7 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) { Fmu2CommonStruct * fmu2 = &comp_fmu->fmu2; McxStatus retVal; - ComponentRTFactorData * rtData = &comp->data->rtData; - McxTime rtOutputStart, rtOutputEnd; - if (rtData->rtGlobalSimStartDefined) { - mcx_time_get(&rtOutputStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputStart, &rtData->rtOutputStart); - } - + TimeSnapshotStart(&comp->data->rtData.funcTimings.rtOutput); retVal = Fmu2GetVariableArray(fmu2, fmu2->out); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Initialization computation failed"); @@ -1315,11 +1303,7 @@ static McxStatus Fmu2UpdateOutChannels(Component * comp) { ComponentLog(comp, LOG_ERROR, "Initialization computation failed"); return RETURN_ERROR; } - - if (rtData->rtGlobalSimStartDefined) { - mcx_time_get(&rtOutputEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtOutputEnd, &rtData->rtOutputEnd); - } + TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtOutput); return RETURN_OK; } diff --git a/src/core/Component.c b/src/core/Component.c index a68c63a..e694d78 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -149,7 +149,7 @@ McxStatus ComponentRead(Component * comp, ComponentInput * input, const struct C if (input->results->rtFactor.defined) { comp->data->rtData.defined = TRUE; comp->data->rtData.enabled = input->results->rtFactor.value; - comp->data->rtData.profilingTimesEnabled = config->profilingMode; + comp->data->rtData.funcTimings.profilingTimesEnabled = config->profilingMode; } retVal = comp->data->storage->Read(comp->data->storage, input->results); @@ -181,7 +181,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.profilingTimesEnabled = comp->data->model->config->profilingMode; + comp->data->rtData.funcTimings.profilingTimesEnabled = comp->data->model->config->profilingMode; } if (comp->data->model->task->params) { @@ -265,73 +265,73 @@ static McxStatus ComponentSetupRTFactor(Component * comp) { } // Scheduling channels - retVal = DefineTimingChannel(comp, "CalcStartWallClockTime", "time~mys", &comp->data->rtData.rtCalcStart_mys); + retVal = DefineTimingChannel(comp, "CalcStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtCalc.startTime); if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - retVal = DefineTimingChannel(comp, "CalcEndWallClockTime", "time~mys", &comp->data->rtData.rtCalcEnd_mys); + retVal = DefineTimingChannel(comp, "CalcEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtCalc.endTime); if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - retVal = DefineTimingChannel(comp, "SyncStartWallClockTime", "time~mys", &comp->data->rtData.rtSyncStart_mys); + retVal = DefineTimingChannel(comp, "SyncStartWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtSync.startTime); if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - retVal = DefineTimingChannel(comp, "SyncEndWallClockTime", "time~mys", &comp->data->rtData.rtSyncEnd_mys); + retVal = DefineTimingChannel(comp, "SyncEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtSync.endTime); if (RETURN_ERROR == retVal) { return RETURN_ERROR; } - if (comp->data->rtData.profilingTimesEnabled) { - retVal = DefineTimingChannel(comp, "InputStartWallClockTime", "time~mys", &comp->data->rtData.rtInputStart_mys); + 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.rtInputEnd_mys); + 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.rtOutputStart_mys); + 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.rtOutputEnd_mys); + 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.rtStoreStart_mys); + 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.rtStoreEnd_mys); + 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.rtStoreInStart_mys); + 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.rtStoreInEnd_mys); + 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.rtTriggerInStart_mys); + 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.rtTriggerInEnd_mys); + retVal = DefineTimingChannel(comp, "TriggerInEndWallClockTime", "time~mys", &comp->data->rtData.funcTimings.rtTriggerIn.endTime); if (RETURN_ERROR == retVal) { return RETURN_ERROR; } @@ -446,9 +446,7 @@ McxStatus ComponentInitialize(Component * comp, size_t group, double startTime) } McxStatus ComponentBeforeDoSteps(Component * comp, void * param) { - McxTime * rtGlobalSimStart = (McxTime *)param; - comp->data->rtData.rtGlobalSimStart = *rtGlobalSimStart; - comp->data->rtData.rtGlobalSimStartDefined = TRUE; + FunctionTimingsSetGlobalSimStart(&comp->data->rtData.funcTimings, (McxTime *)param); mcx_time_get(&comp->data->rtData.rtCompStart); comp->data->rtData.rtLastEndCalc = comp->data->rtData.rtCompStart; @@ -493,14 +491,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 rtStartCalc, rtEndCalc, rtDeltaCalc; double startTime; McxTime rtTotal, rtTotalSum; if (comp->data->rtData.enabled) { /* data for local rt factor */ startTime = comp->GetTime(comp); - mcx_time_get(&rtStartCalc); + TimeSnapshotStart(&comp->data->rtData.funcTimings.rtCalc); } MCX_DEBUG_LOG("DoStep: %.16f -> %.16f", time, endTime); @@ -547,16 +544,17 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de } if (comp->data->rtData.enabled) { + McxTime rtDeltaCalc; ComponentRTFactorData * rtData = &comp->data->rtData; double simCalcSum = endTime - rtData->simStartTime; - mcx_time_get(&rtEndCalc); // wall time of this DoStep - mcx_time_diff(&rtStartCalc, &rtEndCalc, &rtDeltaCalc); // data for local rt factor + TimeSnapshotEnd(&rtData->funcTimings.rtCalc); + mcx_time_diff(&rtData->funcTimings.rtCalc.start, &rtData->funcTimings.rtCalc.end, &rtDeltaCalc); // data for local rt factor - mcx_time_diff(&rtData->rtLastCompEnd, &rtEndCalc, &rtTotal); // data for total rt factor and avg rt factor - mcx_time_diff(&rtData->rtCompStart, &rtEndCalc, &rtTotalSum); + 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); - rtData->rtLastEndCalc = rtEndCalc; // udpate wall clock for next dostep + rtData->rtLastEndCalc = rtData->funcTimings.rtCalc.end; // udpate wall clock for next dostep 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 @@ -578,35 +576,7 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de rtData->rtFactorTotal = mcx_time_to_seconds(&rtTotal) / rtData->simCommStepTime; rtData->rtFactorTotalAvg = rtData->rtTotalSum_s / simCalcSum; - mcx_time_diff(&rtData->rtGlobalSimStart, &rtStartCalc, &rtData->rtCalcStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtEndCalc, &rtData->rtCalcEnd); - - rtData->rtCalcStart_mys = mcx_time_to_micro_s(&rtData->rtCalcStart); - rtData->rtCalcEnd_mys = mcx_time_to_micro_s(&rtData->rtCalcEnd); - - rtData->rtSyncStart_mys = mcx_time_to_micro_s(&rtData->rtSyncStart); - rtData->rtSyncEnd_mys = mcx_time_to_micro_s(&rtData->rtSyncEnd); - - rtData->rtInputStart_mys = mcx_time_to_micro_s(&rtData->rtInputStart); - rtData->rtInputEnd_mys = mcx_time_to_micro_s(&rtData->rtInputEnd); - - rtData->rtOutputStart_mys = mcx_time_to_micro_s(&rtData->rtOutputStart); - rtData->rtOutputEnd_mys = mcx_time_to_micro_s(&rtData->rtOutputEnd); - - rtData->rtStoreStart_mys = rtData->rtStoreStartPre_mys; - rtData->rtStoreEnd_mys = rtData->rtStoreEndPre_mys; - - rtData->rtStoreStartPre_mys = mcx_time_to_micro_s(&rtData->rtStoreStart); - rtData->rtStoreEndPre_mys = mcx_time_to_micro_s(&rtData->rtStoreEnd); - - rtData->rtStoreInStart_mys = rtData->rtStoreInStartPre_mys; - rtData->rtStoreInEnd_mys = rtData->rtStoreInEndPre_mys; - - rtData->rtStoreInStartPre_mys = mcx_time_to_micro_s(&rtData->rtStoreInStart); - rtData->rtStoreInEndPre_mys = mcx_time_to_micro_s(&rtData->rtStoreInEnd); - - rtData->rtTriggerInStart_mys = mcx_time_to_micro_s(&rtData->rtTriggerInStart); - rtData->rtTriggerInEnd_mys = mcx_time_to_micro_s(&rtData->rtTriggerInEnd); + FunctionTimingsCalculateTimeDiffs(&rtData->funcTimings); } return RETURN_OK; @@ -824,23 +794,18 @@ struct Dependencies * ComponentGetInOutGroupsNoDependency(const Component * comp McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time) { McxStatus retVal = RETURN_OK; ComponentRTFactorData * rtData = &comp->data->rtData; - McxTime rtSyncStart, rtSyncEnd; mcx_time_init(&rtData->rtCommStepTime); rtData->simCommStepTime = 0; rtData->rtLastCompEnd = rtData->rtLastEndCalc; - mcx_time_get(&rtSyncStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncStart, &rtData->rtSyncStart); - + 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; } - - mcx_time_get(&rtSyncEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncEnd, &rtData->rtSyncEnd); + TimeSnapshotEnd(&rtData->funcTimings.rtSync); return RETURN_OK; } @@ -848,23 +813,18 @@ McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time) { McxStatus retVal = RETURN_OK; ComponentRTFactorData * rtData = &comp->data->rtData; - McxTime rtSyncStart, rtSyncEnd; mcx_time_init(&rtData->rtCommStepTime); rtData->simCommStepTime = 0; rtData->rtLastCompEnd = rtData->rtLastEndCalc; - mcx_time_get(&rtSyncStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncStart, &rtData->rtSyncStart); - + 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; } - - mcx_time_get(&rtSyncEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtSyncEnd, &rtData->rtSyncEnd); + TimeSnapshotEnd(&rtData->funcTimings.rtSync); return RETURN_OK; } @@ -1336,6 +1296,109 @@ static Component * ComponentCreate(Component * comp) { 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); @@ -1394,47 +1457,11 @@ static ComponentData * ComponentDataCreate(ComponentData * data) { rtData->rtFactorCalc = 0.; rtData->rtFactorCalcAvg = 0.; - rtData->profilingTimesEnabled = FALSE; - mcx_time_init(&rtData->rtCompStart); mcx_time_init(&rtData->rtLastEndCalc); mcx_time_init(&rtData->rtLastCompEnd); - mcx_time_init(&rtData->rtCalcStart); - mcx_time_init(&rtData->rtCalcEnd); - - mcx_time_init(&rtData->rtSyncStart); - mcx_time_init(&rtData->rtSyncEnd); - - mcx_time_init(&rtData->rtStoreStart); - mcx_time_init(&rtData->rtStoreEnd); - mcx_time_init(&rtData->rtStoreInStart); - mcx_time_init(&rtData->rtStoreInEnd); - mcx_time_init(&rtData->rtInputStart); - mcx_time_init(&rtData->rtInputEnd); - mcx_time_init(&rtData->rtOutputStart); - mcx_time_init(&rtData->rtOutputEnd); - mcx_time_init(&rtData->rtTriggerInStart); - mcx_time_init(&rtData->rtTriggerInEnd); - - rtData->rtInputStart_mys = 0.; - rtData->rtInputEnd_mys = 0.; - rtData->rtOutputStart_mys = 0.; - rtData->rtOutputEnd_mys = 0.; - rtData->rtStoreStart_mys = 0.; - rtData->rtStoreEnd_mys = 0.; - rtData->rtStoreStartPre_mys = 0.; - rtData->rtStoreEndPre_mys = 0.; - - rtData->rtStoreInStart_mys = 0.; - rtData->rtStoreInEnd_mys = 0.; - rtData->rtStoreInStartPre_mys = 0.; - rtData->rtStoreInEndPre_mys = 0.; - - rtData->rtTriggerInStart_mys = 0.; - rtData->rtTriggerInEnd_mys = 0.; - - rtData->rtGlobalSimStartDefined = FALSE; + FunctionTimingsInit(&rtData->funcTimings); rtData->rtFactorTotal = 0.; rtData->rtFactorTotalAvg = 0.; diff --git a/src/core/Component_impl.h b/src/core/Component_impl.h index 6aa259d..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 { @@ -52,58 +96,12 @@ struct ComponentRTFactorData { double rtFactorTotalAvg; McxTime rtCompStart; // wall clock of start of component - McxTime rtGlobalSimStart; // wall clock of start of simulation - - int rtGlobalSimStartDefined; McxTime rtLastEndCalc; // wall clock of last Calc End McxTime rtLastCompEnd; // wall clock of last DoStep before entering communication mode - McxTime rtCalcStart; // wall clock of last DoStep Start - double rtCalcStart_mys; - - McxTime rtCalcEnd; // wall clock of last DoStep End - double rtCalcEnd_mys; - - McxTime rtSyncStart; // wall clock of sync start - double rtSyncStart_mys; - - McxTime rtSyncEnd; // wall clock of sync end - double rtSyncEnd_mys; - - int profilingTimesEnabled; - - McxTime rtInputStart; - double rtInputStart_mys; - McxTime rtInputEnd; - double rtInputEnd_mys; - - McxTime rtOutputStart; - double rtOutputStart_mys; - McxTime rtOutputEnd; - double rtOutputEnd_mys; - - McxTime rtStoreStart; - double rtStoreStart_mys; - double rtStoreStartPre_mys; - - McxTime rtStoreEnd; - double rtStoreEnd_mys; - double rtStoreEndPre_mys; - - McxTime rtStoreInStart; - double rtStoreInStart_mys; - double rtStoreInStartPre_mys; - - McxTime rtStoreInEnd; - double rtStoreInEnd_mys; - double rtStoreInEndPre_mys; - - McxTime rtTriggerInStart; - double rtTriggerInStart_mys; - McxTime rtTriggerInEnd; - double rtTriggerInEnd_mys; + FunctionTimings funcTimings; }; diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index 2bf439a..0208a64 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -61,11 +61,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } } - ComponentRTFactorData * rtData = &comp->data->rtData; - McxTime rtTriggerInStart, rtTriggerInEnd; - mcx_time_get(&rtTriggerInStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtTriggerInStart, &rtData->rtTriggerInStart); - + TimeSnapshotStart(&comp->data->rtData.funcTimings.rtTriggerIn); // TODO: Rename this to UpdateInChannels if (TRUE == ComponentGetUseInputsAtCouplingStepEndTime(comp)) { tmpTime = interval.startTime; @@ -85,8 +81,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP return RETURN_ERROR; } } - mcx_time_get(&rtTriggerInEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtTriggerInEnd, &rtData->rtTriggerInEnd); + TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtTriggerIn); #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { @@ -94,10 +89,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } #endif // MCX_DEBUG - McxTime rtStoreInStart, rtStoreInEnd; - mcx_time_get(&rtStoreInStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreInStart, &rtData->rtStoreInStart); - + TimeSnapshotStart(&comp->data->rtData.funcTimings.rtStoreIn); if (TRUE == ComponentGetStoreInputsAtCouplingStepEndTime(comp)) { retVal = comp->Store(comp, CHANNEL_STORE_IN, interval.endTime, level); } else if (FALSE == ComponentGetStoreInputsAtCouplingStepEndTime(comp)) { @@ -110,8 +102,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP mcx_log(LOG_ERROR, "%s: Storing inport failed", comp->GetName(comp)); return RETURN_ERROR; } - mcx_time_get(&rtStoreInEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreInEnd, &rtData->rtStoreInEnd); + TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtStoreIn); #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { @@ -156,10 +147,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } #endif // MCX_DEBUG - McxTime rtStoreStart, rtStoreEnd; - mcx_time_get(&rtStoreStart); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreStart, &rtData->rtStoreStart); - + TimeSnapshotStart(&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)); @@ -175,8 +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; } - mcx_time_get(&rtStoreEnd); - mcx_time_diff(&rtData->rtGlobalSimStart, &rtStoreEnd, &rtData->rtStoreEnd); + TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtStore); } if (comp->GetFinishState(comp) == COMP_IS_FINISHED) { From 69f1e8e68b475de1ab190675a9b78ab5135744b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 4 Mar 2022 12:25:54 +0100 Subject: [PATCH 054/295] Avoid premature simulation end in case of only NeverFinishing components Those are boundary condition components like (e.g. Signal Table, File, Constant, Monitor) --- src/core/Task.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/Task.c b/src/core/Task.c index b8d6bc0..fe7338d 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; } From a63defcea3c322035cd3c24f60f0a2bfe9aa9bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 7 Mar 2022 10:02:34 +0100 Subject: [PATCH 055/295] Ignore FLUSH_STORE in case of parallel --- src/core/Task.c | 2 +- src/steptypes/StepType.c | 5 +++++ src/steptypes/StepType.h | 3 +++ src/storage/ResultsStorage.c | 2 +- src/storage/ResultsStorage.h | 2 +- 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/core/Task.c b/src/core/Task.c index fe7338d..a6b55e7 100644 --- a/src/core/Task.c +++ b/src/core/Task.c @@ -281,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/steptypes/StepType.c b/src/steptypes/StepType.c index 0208a64..bdbd565 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -276,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 0cacd6c..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); diff --git a/src/storage/ResultsStorage.c b/src/storage/ResultsStorage.c index 41146ba..1837d65 100644 --- a/src/storage/ResultsStorage.c +++ b/src/storage/ResultsStorage.c @@ -396,7 +396,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..67bef97 100644 --- a/src/storage/ResultsStorage.h +++ b/src/storage/ResultsStorage.h @@ -56,7 +56,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); From 7ea746b8ca852cdf56d1073b503fa51da0936069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 7 Mar 2022 10:34:14 +0100 Subject: [PATCH 056/295] Change time format in log file header --- src/core/Config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Config.c b/src/core/Config.c index 66c5af2..d9146b8 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__ ); From cae9ce6796edcb891ca6e6fd469f5252826db20e Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Mon, 24 Jan 2022 12:14:04 +0100 Subject: [PATCH 057/295] Fix const warnings regarding ChannelValue --- src/core/channels/ChannelValue.c | 4 ++-- src/core/channels/ChannelValue.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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); From 1630ee53e2156da5973e2d9c90c5035bc3187d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Mar 2022 14:45:02 +0100 Subject: [PATCH 058/295] Convert path to a normalized absolute path prior to _waccess call --- libs/util/src/win/os.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) 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; } From 118cb9627c4cc79a36fab4bd167ef91fc0954975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 15 Feb 2022 11:06:18 +0100 Subject: [PATCH 059/295] Implement a memory filter --- src/core/connections/filters/MemoryFilter.c | 327 ++++++++++++++++++++ src/core/connections/filters/MemoryFilter.h | 45 +++ 2 files changed, 372 insertions(+) create mode 100644 src/core/connections/filters/MemoryFilter.c create mode 100644 src/core/connections/filters/MemoryFilter.h diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c new file mode 100644 index 0000000..6bab691 --- /dev/null +++ b/src/core/connections/filters/MemoryFilter.c @@ -0,0 +1,327 @@ +/******************************************************************************** + * 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" + +#define MEM_FILTER_IDX_FLAG ((size_t) (-1)) + + +#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; + int i = 0; + size_t smallerIdx = MEM_FILTER_IDX_FLAG; + size_t biggerIdx = MEM_FILTER_IDX_FLAG; + + 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 == MEM_FILTER_IDX_FLAG) { + smallerIdx = i; + } else { + break; + } + } + + if (smallerIdx == MEM_FILTER_IDX_FLAG) { + i = biggerIdx; + } else if (biggerIdx == MEM_FILTER_IDX_FLAG) { + 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; + int i = 0; + size_t smallerIdx = MEM_FILTER_IDX_FLAG; + size_t biggerIdx = MEM_FILTER_IDX_FLAG; + + 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 == MEM_FILTER_IDX_FLAG) { + biggerIdx = i; + } else { + break; + } + } + + if (smallerIdx == MEM_FILTER_IDX_FLAG) { + i = biggerIdx; + } else if (biggerIdx == MEM_FILTER_IDX_FLAG) { + 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 From be4a159fd66ff3aa25e5a88505f838cacc5e0e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 15 Feb 2022 11:07:33 +0100 Subject: [PATCH 060/295] Forward correct argument to CompPostDoUpdateState --- src/core/Task.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Task.c b/src/core/Task.c index a6b55e7..33303dc 100644 --- a/src/core/Task.c +++ b/src/core/Task.c @@ -119,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; From 0224c679d1e232e7ca22d753c4336236a9910ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 15 Feb 2022 11:41:39 +0100 Subject: [PATCH 061/295] Use the MemoryFilter when possible --- src/core/Config.c | 16 + src/core/Config.h | 2 + src/core/connections/Connection.c | 814 +++++++++++++++++++++++++++++- 3 files changed, 819 insertions(+), 13 deletions(-) diff --git a/src/core/Config.c b/src/core/Config.c index d9146b8..d09e5db 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -364,6 +364,20 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + 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 (%d)", size); + } else { + config->memFilterHistoryExtra = (size_t) size; + mcx_log(LOG_INFO, "Memory filter extra history size: %zu", config->memFilterHistoryExtra); + } + mcx_free(str); + } + } + { char * cosimInitEnabled = NULL; @@ -543,6 +557,8 @@ static Config * ConfigCreate(Config * config) { config->interpolationBuffSizeLimit = 100000; config->interpolationBuffSizeSafetyExt = 1; + config->memFilterHistoryExtra = 1; + config->profilingMode = FALSE; return config; diff --git a/src/core/Config.h b/src/core/Config.h index 425ec23..ac46a6c 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -66,6 +66,8 @@ struct Config { size_t interpolationBuffSizeLimit; size_t interpolationBuffSizeSafetyExt; + size_t memFilterHistoryExtra; + int cosimInitEnabled; int profilingMode; diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 7f613f5..662145b 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -21,10 +21,13 @@ // 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 */ @@ -159,6 +162,764 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { return buffSize; } +static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { + size_t size = 0; + + Component * sourceComp = info->GetSourceComponent(info); + Component * targetComp = info->GetTargetComponent(info); + + Model * model = sourceComp->GetModel(sourceComp); + Task * task = model->GetTask(model); + + 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 (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; + } + } + } + } + + return size ? size + model->config->memFilterHistoryExtra : 0; +} + +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; @@ -168,6 +929,11 @@ ChannelFilter * FilterFactory(Connection * connection) { InterExtrapolationType extrapolType = info->GetInterExtraType(info); InterExtrapolationParams * params = info->GetInterExtraParams(info); + Component * sourceComp = info->GetSourceComponent(info); + Model * model = sourceComp->GetModel(sourceComp); + Task * task = model->GetTask(model); + int useInputsAtEndTime = task->useInputsAtEndTime; + if (info->GetType(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"); @@ -182,7 +948,13 @@ ChannelFilter * FilterFactory(Connection * connection) { 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 = SetMemoryFilter(useInputsAtEndTime, info->GetType(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); @@ -203,15 +975,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); - 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; + size_t memFilterHist = MemoryFilterHistorySize(info, degree); + if (0 != memFilterHist) { + filter = SetMemoryFilter(useInputsAtEndTime, info->GetType(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; + } } } @@ -242,9 +1022,17 @@ ChannelFilter * FilterFactory(Connection * connection) { if (NULL == filter && info->GetType(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 = SetMemoryFilter(useInputsAtEndTime, info->GetType(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); From e2917998fd2b6f344510663bbea896e3246d9f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 21 Feb 2022 20:18:44 +0100 Subject: [PATCH 062/295] Add a switch to disable the MemoryFilter on demand --- src/core/Config.c | 13 +++++++++++++ src/core/Config.h | 1 + src/core/connections/Connection.c | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/src/core/Config.c b/src/core/Config.c index d09e5db..15e97d7 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -364,6 +364,18 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + 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_EXTRA"); if (str) { @@ -557,6 +569,7 @@ static Config * ConfigCreate(Config * config) { config->interpolationBuffSizeLimit = 100000; config->interpolationBuffSizeSafetyExt = 1; + config->useMemFilter = TRUE; config->memFilterHistoryExtra = 1; config->profilingMode = FALSE; diff --git a/src/core/Config.h b/src/core/Config.h index ac46a6c..832615d 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -66,6 +66,7 @@ struct Config { size_t interpolationBuffSizeLimit; size_t interpolationBuffSizeSafetyExt; + int useMemFilter; size_t memFilterHistoryExtra; int cosimInitEnabled; diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 662145b..8fb4f4d 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -198,6 +198,10 @@ static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { StepTypeType stepType = task->GetStepTypeType(task); + if (!model->config->useMemFilter) { + return 0; + } + if (ComponentMightNotRespectStepSize(sourceComp) || ComponentMightNotRespectStepSize(targetComp)) { return 0; } From 89d3a9cb58020acaf884872a609ad7eae3c78a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 21 Feb 2022 21:18:16 +0100 Subject: [PATCH 063/295] Check for cycles when determining the buffer size --- src/core/Config.c | 15 +++++++++++++++ src/core/Config.h | 1 + src/core/connections/Connection.c | 18 +++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/core/Config.c b/src/core/Config.c index 15e97d7..c799a19 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -376,6 +376,20 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + 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 (%d)", size); + } 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) { @@ -570,6 +584,7 @@ static Config * ConfigCreate(Config * config) { config->interpolationBuffSizeSafetyExt = 1; config->useMemFilter = TRUE; + config->memFilterHistoryLimit = 10000000; config->memFilterHistoryExtra = 1; config->profilingMode = FALSE; diff --git a/src/core/Config.h b/src/core/Config.h index 832615d..e520d6f 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -67,6 +67,7 @@ struct Config { size_t interpolationBuffSizeSafetyExt; int useMemFilter; + size_t memFilterHistoryLimit; size_t memFilterHistoryExtra; int cosimInitEnabled; diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 8fb4f4d..4005a98 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -171,6 +171,8 @@ static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { 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; @@ -900,7 +902,21 @@ static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { } } - return size ? size + model->config->memFilterHistoryExtra : 0; + if (size == 0) { + return 0; + } + + if (size + model->config->memFilterHistoryExtra > limit) { + char * connString = info->ConnectionString(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) { From 51d02a2acb6664ded7a8ffd9ec0e0aa9d46e870b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 14:05:14 +0100 Subject: [PATCH 064/295] Use >= to check for buffer overflow --- src/core/connections/filters/MemoryFilter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c index 6bab691..a172b54 100644 --- a/src/core/connections/filters/MemoryFilter.c +++ b/src/core/connections/filters/MemoryFilter.c @@ -24,7 +24,7 @@ static McxStatus MemoryFilterSetValue(ChannelFilter * filter, double time, Chann MemoryFilter * memoryFilter = (MemoryFilter *) filter; if (InCommunicationMode != * filter->state) { - if (memoryFilter->numEntriesWrite == memoryFilter->historySize) { + if (memoryFilter->numEntriesWrite >= memoryFilter->historySize) { mcx_log(LOG_ERROR, "MemoryFilter: History buffer too small"); return RETURN_ERROR; } From 1c957046a22ba193b91147160a3347904ebd195c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 14:05:40 +0100 Subject: [PATCH 065/295] Use SIZE_MAX instead of MEM_FILTER_IDX_FLAG --- src/core/connections/filters/MemoryFilter.c | 26 ++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c index a172b54..05383ce 100644 --- a/src/core/connections/filters/MemoryFilter.c +++ b/src/core/connections/filters/MemoryFilter.c @@ -12,7 +12,11 @@ #include "util/compare.h" -#define MEM_FILTER_IDX_FLAG ((size_t) (-1)) +#include + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) (-1)) +#endif // !SIZE_MAX #ifdef __cplusplus @@ -51,8 +55,8 @@ static McxStatus MemoryFilterSetValue(ChannelFilter * filter, double time, Chann static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, double time) { MemoryFilter * memoryFilter = (MemoryFilter *) filter; int i = 0; - size_t smallerIdx = MEM_FILTER_IDX_FLAG; - size_t biggerIdx = MEM_FILTER_IDX_FLAG; + 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)) { @@ -72,16 +76,16 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub // find out closest stored time points if (time < memoryFilter->timeHistoryRead[i]) { biggerIdx = i; - } else if (smallerIdx == MEM_FILTER_IDX_FLAG) { + } else if (smallerIdx == SIZE_MAX) { smallerIdx = i; } else { break; } } - if (smallerIdx == MEM_FILTER_IDX_FLAG) { + if (smallerIdx == SIZE_MAX) { i = biggerIdx; - } else if (biggerIdx == MEM_FILTER_IDX_FLAG) { + } else if (biggerIdx == SIZE_MAX) { i = smallerIdx; } else if ((time - memoryFilter->timeHistoryRead[smallerIdx]) < (memoryFilter->timeHistoryRead[biggerIdx] - time)) { i = smallerIdx; @@ -105,8 +109,8 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time) { MemoryFilter * memoryFilter = (MemoryFilter *) filter; int i = 0; - size_t smallerIdx = MEM_FILTER_IDX_FLAG; - size_t biggerIdx = MEM_FILTER_IDX_FLAG; + size_t smallerIdx = SIZE_MAX; + size_t biggerIdx = SIZE_MAX; for (i = 0; i < memoryFilter->numEntriesRead; ++i) { if (double_eq(memoryFilter->timeHistoryRead[i], time)) { @@ -126,16 +130,16 @@ static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time // find out closest stored time points if (time > memoryFilter->timeHistoryRead[i]) { smallerIdx = i; - } else if (biggerIdx == MEM_FILTER_IDX_FLAG) { + } else if (biggerIdx == SIZE_MAX) { biggerIdx = i; } else { break; } } - if (smallerIdx == MEM_FILTER_IDX_FLAG) { + if (smallerIdx == SIZE_MAX) { i = biggerIdx; - } else if (biggerIdx == MEM_FILTER_IDX_FLAG) { + } else if (biggerIdx == SIZE_MAX) { i = smallerIdx; } else if ((time - memoryFilter->timeHistoryRead[smallerIdx]) < (memoryFilter->timeHistoryRead[biggerIdx] - time)) { i = smallerIdx; From a7631c1e5f775a6e430ce3081979207d650d5c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 14:14:16 +0100 Subject: [PATCH 066/295] Print user's input as a string instead of the converted int value --- src/core/Config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/Config.c b/src/core/Config.c index c799a19..6798666 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -381,7 +381,7 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { if (str) { int size = atoi(str); if (size <= 0) { - mcx_log(LOG_WARNING, "Invalid memory filter history size limit (%d)", size); + 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); @@ -395,7 +395,7 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { if (str) { int size = atoi(str); if (size <= 0) { - mcx_log(LOG_WARNING, "Invalid memory filter extra history size (%d)", size); + 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); From 80aa0c381ab10fdf00212182b8c60efbbcc68b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 14:37:07 +0100 Subject: [PATCH 067/295] Fix compiler warnings --- src/core/connections/Connection.c | 8 ++++---- src/core/connections/filters/MemoryFilter.c | 4 ++-- src/steptypes/StepType.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 4005a98..5f6b822 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -145,7 +145,7 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { buffSize = model->config->interpolationBuffSize; } else { - buffSize = ceil(synchStep / sourceStep) + 1; + buffSize = (size_t) ceil(synchStep / sourceStep) + 1; } buffSize += model->config->interpolationBuffSizeSafetyExt; @@ -970,7 +970,7 @@ ChannelFilter * FilterFactory(Connection * connection) { if (EXTRAPOLATING == isInterExtrapol || INTEREXTRAPOLATING == isInterExtrapol) { size_t memFilterHist = MemoryFilterHistorySize(info, params->extrapolationOrder); if (0 != memFilterHist) { - filter = SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); if (!filter) { return NULL; } @@ -997,7 +997,7 @@ ChannelFilter * FilterFactory(Connection * connection) { } else { size_t memFilterHist = MemoryFilterHistorySize(info, degree); if (0 != memFilterHist) { - filter = SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); if (!filter) { return NULL; } @@ -1044,7 +1044,7 @@ ChannelFilter * FilterFactory(Connection * connection) { size_t memFilterHist = MemoryFilterHistorySize(info, 0); if (0 != memFilterHist) { - filter = SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); if (!filter) { return NULL; } diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c index 05383ce..b4fddd0 100644 --- a/src/core/connections/filters/MemoryFilter.c +++ b/src/core/connections/filters/MemoryFilter.c @@ -54,7 +54,7 @@ static McxStatus MemoryFilterSetValue(ChannelFilter * filter, double time, Chann static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, double time) { MemoryFilter * memoryFilter = (MemoryFilter *) filter; - int i = 0; + size_t i = 0; size_t smallerIdx = SIZE_MAX; size_t biggerIdx = SIZE_MAX; @@ -108,7 +108,7 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time) { MemoryFilter * memoryFilter = (MemoryFilter *) filter; - int i = 0; + size_t i = 0; size_t smallerIdx = SIZE_MAX; size_t biggerIdx = SIZE_MAX; diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index bdbd565..d675c97 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -89,7 +89,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } #endif // MCX_DEBUG - TimeSnapshotStart(&comp->data->rtData.funcTimings.rtStoreIn); + 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)) { @@ -102,7 +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(&comp->data->rtData.funcTimings.rtStoreIn); + TimeSnapshotEnd((TimeSnapshot *) &comp->data->rtData.funcTimings.rtStoreIn); #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { @@ -147,7 +147,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP } #endif // MCX_DEBUG - TimeSnapshotStart(&comp->data->rtData.funcTimings.rtStore); + 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)); @@ -163,7 +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(&comp->data->rtData.funcTimings.rtStore); + TimeSnapshotEnd((TimeSnapshot *) &comp->data->rtData.funcTimings.rtStore); } if (comp->GetFinishState(comp) == COMP_IS_FINISHED) { From 254d5218e433f038abd63152961f6ed90123e0b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 24 Feb 2022 13:21:14 +0100 Subject: [PATCH 068/295] Define a Vector of pure C objects --- src/objects/Vector.c | 249 +++++++++++++++++++++++++++++++++++++++++++ src/objects/Vector.h | 80 ++++++++++++++ 2 files changed, 329 insertions(+) create mode 100644 src/objects/Vector.c create mode 100644 src/objects/Vector.h diff --git a/src/objects/Vector.c b/src/objects/Vector.c new file mode 100644 index 0000000..fe6f1f0 --- /dev/null +++ b/src/objects/Vector.c @@ -0,0 +1,249 @@ +/******************************************************************************** + * 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 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 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 VectorPushBack(Vector * vector, void * elem) { + McxStatus retVal = vector->Resize(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); + 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->Resize = VectorResize; + 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..43c9bef --- /dev/null +++ b/src/objects/Vector.h @@ -0,0 +1,80 @@ +/******************************************************************************** + * 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 (*fVectorResize)(Vector * vector, size_t size); +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; + fVectorResize Resize; + 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 From 2702ae283fd906234577d5c4c7cea636e9270610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 25 Feb 2022 15:28:03 +0100 Subject: [PATCH 069/295] Inline ConnectionInfo into the Connection --- src/core/Component.c | 2 +- src/core/Component.h | 4 +- src/core/Databus.c | 22 +- src/core/Model.c | 136 +++---- src/core/Model.h | 9 +- src/core/SubModel.c | 26 +- src/core/channels/Channel.c | 2 +- src/core/connections/Connection.c | 87 +++-- src/core/connections/Connection.h | 3 +- src/core/connections/ConnectionInfo.c | 280 ++------------ src/core/connections/ConnectionInfo.h | 119 ++---- src/core/connections/ConnectionInfoFactory.c | 365 +++++++++---------- src/core/connections/ConnectionInfoFactory.h | 11 +- src/core/connections/ConnectionInfo_impl.h | 62 ---- src/core/connections/Connection_impl.h | 2 +- src/core/connections/FilteredConnection.c | 5 +- 16 files changed, 381 insertions(+), 754 deletions(-) delete mode 100644 src/core/connections/ConnectionInfo_impl.h diff --git a/src/core/Component.c b/src/core/Component.c index e694d78..658e353 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -976,7 +976,7 @@ static ObjectList * ComponentGetConnections(Component * fromComp, Component * to 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"); diff --git a/src/core/Component.h b/src/core/Component.h index 80ab6ed..0878259 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -17,6 +17,7 @@ #include "core/Dependency.h" #include "objects/StringContainer.h" #include "reader/model/components/ComponentInput.h" +#include "core/connections/ConnectionInfo.h" #ifdef __cplusplus extern "C" { @@ -33,7 +34,6 @@ struct Model; struct ComponentData; struct ChannelInfo; struct Connection; -struct ConnectionInfo; struct StepTypeParams; struct ResultsStorage; struct ComponentStorage; @@ -246,7 +246,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, struct St McxStatus ComponentEnterCommunicationPoint(Component * comp, 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/Databus.c b/src/core/Databus.c index c97e915..a14cb85 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -790,8 +790,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; @@ -805,7 +805,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); @@ -816,7 +816,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); @@ -832,7 +832,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); @@ -1758,8 +1758,8 @@ McxStatus DatabusCollectModeSwitchData(Databus * db) { 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); @@ -1781,7 +1781,7 @@ McxStatus DatabusEnterCouplingStepMode(Databus * db, double timeStepSize) { retVal = data.connection->EnterCouplingStepMode(data.connection, timeStepSize, data.sourceTimeStepSize, data.targetTimeStepSize); if (RETURN_OK != retVal) { ConnectionInfo * info = data.connection->GetInfo(data.connection); - char * buffer = info->ConnectionString(info); + char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_ERROR, "Ports: Cannot enter coupling step mode of connection %s", buffer); mcx_free(buffer); return RETURN_ERROR; @@ -1800,7 +1800,7 @@ McxStatus DatabusEnterCommunicationMode(Databus * db, double time) { retVal = data.connection->EnterCommunicationMode(data.connection, time); if (RETURN_OK != retVal) { ConnectionInfo * info = data.connection->GetInfo(data.connection); - 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; @@ -1819,7 +1819,7 @@ McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectList * 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; @@ -1827,7 +1827,7 @@ McxStatus DatabusEnterCommunicationModeForConnections(Databus * db, ObjectList * 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/Model.c b/src/core/Model.c index fb55af2..5200f65 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -25,7 +25,6 @@ #include "core/Databus.h" #include "core/channels/Channel.h" #include "core/connections/Connection.h" -#include "core/connections/ConnectionInfo_impl.h" #include "core/connections/FilteredConnection.h" #include "core/SubModel.h" @@ -43,43 +42,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); } -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. @@ -94,10 +94,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); @@ -115,7 +115,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) @@ -125,20 +125,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); @@ -155,34 +155,35 @@ static void UpdateBinaryChannelTypes(ObjectContainer * connInfos, Task * task) { * Necessary value/type conversions are done as well. */ static McxStatus ModelPreprocessConstConnections(Model * model) { - ObjectContainer * conns = model->connections; - ObjectContainer * filteredConns = NULL; + Vector * conns = model->connections; + Vector * filteredConns = NULL; size_t i = 0; McxStatus retVal = RETURN_OK; - filteredConns = (ObjectContainer*)object_create(ObjectContainer); + 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->GetSourceComponent(info); + Component * srcComp = info->sourceComponent; CompConstant * srcCompConst = NULL; Databus * srcDb = srcComp->GetDatabus(srcComp); - ChannelInfo * srcChannelInfo = DatabusGetOutChannelInfo(srcDb, info->GetSourceChannelID(info)); + ChannelInfo * srcChannelInfo = DatabusGetOutChannelInfo(srcDb, info->sourceChannel); - Component * trgComp = info->GetTargetComponent(info); + Component * trgComp = info->targetComponent; Databus * trgDb = trgComp->GetDatabus(trgComp); - ChannelInfo * trgChannelInfo = DatabusGetInChannelInfo(trgDb, info->GetTargetChannelID(info)); + 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, (Object *) info); + filteredConns->PushBack(filteredConns, info); continue; } @@ -196,7 +197,7 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { } ChannelValueInit(src, srcChannelInfo->GetType(srcChannelInfo)); - retVal = ChannelValueSet(src, srcCompConst->GetValue(srcCompConst, info->GetSourceChannelID(info))); + retVal = ChannelValueSet(src, srcCompConst->GetValue(srcCompConst, info->sourceChannel)); if (retVal == RETURN_ERROR) { goto cleanup_1; } @@ -230,8 +231,6 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { } trgChannelInfo->defaultValue = src; - object_destroy(info); - continue; cleanup_1: @@ -257,12 +256,17 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { 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; @@ -274,30 +278,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; @@ -331,18 +337,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); } } @@ -350,17 +356,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); } @@ -409,7 +414,7 @@ static McxStatus ModelInsertAllFilters(Model * model) { 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); @@ -719,7 +724,7 @@ static McxStatus ModelReadComponents(void * self, ComponentsInput * input) { return RETURN_OK; } -McxStatus ReadConnections(ObjectContainer * connections, +McxStatus ReadConnections(Vector * connections, ConnectionsInput * connectionsInput, ObjectContainer * components, Component * sourceComp, @@ -730,7 +735,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; @@ -745,7 +750,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); } @@ -773,13 +778,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; @@ -907,7 +909,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; @@ -924,8 +926,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; } } @@ -1473,7 +1474,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; @@ -1577,8 +1578,8 @@ McxStatus PrintModelGraph(ObjectContainer * comps, ObjectContainer * conns, Comp 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); @@ -1591,8 +1592,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"); @@ -1643,7 +1644,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 1f940c5..e23dbf7 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -446,18 +446,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; @@ -502,11 +502,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); @@ -668,7 +668,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 @@ -682,21 +682,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); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index b2f59fa..5c4f2d8 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -203,7 +203,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { connInfo = conn->GetInfo(conn); ChannelValueDestructor(val); - ChannelValueInit(val, connInfo->GetType(connInfo)); + ChannelValueInit(val, ConnectionInfoGetType(connInfo)); /* Update the connection for the current time */ conn->UpdateToOutput(conn, time); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 5f6b822..9d78700 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -32,7 +32,7 @@ extern "C" { #endif /* __cplusplus */ -McxStatus CheckConnectivity(ObjectContainer * connections) { +McxStatus CheckConnectivity(Vector * connections) { size_t i = 0; size_t connSize = connections->Size(connections); @@ -40,11 +40,11 @@ McxStatus CheckConnectivity(ObjectContainer * 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) { @@ -69,22 +69,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) { @@ -94,7 +91,7 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte isInterExtrapolating = INTEREXTRAPOLATING; } - info->SetInterExtrapolating(info, isInterExtrapolating); + info->isInterExtrapolating = isInterExtrapolating; connection = DatabusCreateConnection(source->GetDatabus(source), info); if (!connection) { @@ -106,7 +103,7 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte } static void LogStepRatios(double sourceStep, double targetStep, double synchStep, ConnectionInfo * info) { - char * connString = info->ConnectionString(info); + char * connString = ConnectionInfoConnectionString(info); if (sourceStep <= synchStep && targetStep <= synchStep) { MCX_DEBUG_LOG("CONN %s: source <= synch && target <= synch", connString); @@ -126,8 +123,8 @@ static int ComponentMightNotRespectStepSize(Component * comp) { } static size_t DetermineFilterBufferSize(ConnectionInfo * info) { - Component * source = info->GetSourceComponent(info); - Component * target = info->GetTargetComponent(info); + Component * source = info->sourceComponent; + Component * target = info->targetComponent; Model * model = source->GetModel(source); Task * task = model->GetTask(model); @@ -151,7 +148,7 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { buffSize += model->config->interpolationBuffSizeSafetyExt; if (buffSize > model->config->interpolationBuffSizeLimit) { - char * connString = info->ConnectionString(info); + 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); @@ -165,8 +162,8 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { size_t size = 0; - Component * sourceComp = info->GetSourceComponent(info); - Component * targetComp = info->GetTargetComponent(info); + Component * sourceComp = info->sourceComponent; + Component * targetComp = info->targetComponent; Model * model = sourceComp->GetModel(sourceComp); Task * task = model->GetTask(model); @@ -907,7 +904,7 @@ static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { } if (size + model->config->memFilterHistoryExtra > limit) { - char * connString = info->ConnectionString(info); + 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); @@ -946,22 +943,22 @@ ChannelFilter * FilterFactory(Connection * connection) { 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->GetSourceComponent(info); + 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; } @@ -970,7 +967,7 @@ ChannelFilter * FilterFactory(Connection * connection) { if (EXTRAPOLATING == isInterExtrapol || INTEREXTRAPOLATING == isInterExtrapol) { size_t memFilterHist = MemoryFilterHistorySize(info, params->extrapolationOrder); if (0 != memFilterHist) { - filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist); if (!filter) { return NULL; } @@ -997,7 +994,7 @@ ChannelFilter * FilterFactory(Connection * connection) { } else { size_t memFilterHist = MemoryFilterHistorySize(info, degree); if (0 != memFilterHist) { - filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist); if (!filter) { return NULL; } @@ -1033,18 +1030,18 @@ 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 size_t memFilterHist = MemoryFilterHistorySize(info, 0); if (0 != memFilterHist) { - filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, info->GetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist); if (!filter) { return NULL; } @@ -1065,7 +1062,7 @@ static ConnectionData * ConnectionDataCreate(ConnectionData * data) { data->out = NULL; data->in = NULL; - data->info = NULL; + ConnectionInfoInit(&data->info); data->value = NULL; data->useInitialValue = FALSE; @@ -1085,8 +1082,6 @@ static ConnectionData * ConnectionDataCreate(ConnectionData * data) { static void ConnectionDataDestructor(ConnectionData * data) { - object_destroy(data->info); - ChannelValueDestructor(&data->store); } @@ -1111,12 +1106,11 @@ static ChannelIn * ConnectionGetTarget(Connection * connection) { } static ConnectionInfo * ConnectionGetInfo(Connection * connection) { - return connection->data->info; + return &connection->data->info; } static int ConnectionIsDecoupled(Connection * connection) { - ConnectionInfo * info = connection->GetInfo(connection); - return info->IsDecoupled(info); + return ConnectionInfoIsDecoupled(&connection->data->info); } static int ConnectionIsDefinedDuringInit(Connection * connection) { @@ -1151,14 +1145,14 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { ChannelInfo * outInfo = out->GetInfo(out); if (connection->data->state != InInitializationMode) { - char * buffer = info->ConnectionString(info); + 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; @@ -1213,11 +1207,11 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { connection->data->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->data->store, ConnectionInfoGetType(info)); } return RETURN_OK; @@ -1341,18 +1335,19 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * connection->data->out = out; connection->data->in = in; - connection->data->info = info; if (in->IsDiscrete(in)) { - info->SetDiscreteTarget(info); + info->hasDiscreteTarget = TRUE; } + connection->data->info = *info; + ChannelValueInit(&connection->data->store, outInfo->GetType(outInfo)); // 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; @@ -1360,7 +1355,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * retVal = in->SetConnection(in, connection, outInfo->GetUnit(outInfo), outInfo->GetType(outInfo)); 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; diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h index f90ea6c..74e0e23 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); diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index a2d68d5..8c6cc82 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -9,7 +9,6 @@ ********************************************************************************/ #include "core/connections/ConnectionInfo.h" -#include "core/connections/ConnectionInfo_impl.h" #include "core/Model.h" #include "core/Databus.h" @@ -18,221 +17,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; +int ConnectionInfoIsDecoupled(ConnectionInfo * info) { + return info->isDecoupled_; } -static int ConnectionInfoGetTargetChannelID(ConnectionInfo * info) { - return info->data->targetChannel; +void ConnectionInfoSetDecoupled(ConnectionInfo * info) { + info->isDecoupled_ = TRUE; } -static Component * ConnectionInfoGetSourceComponent(ConnectionInfo * info) { - return info->data->sourceComponent; -} - -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 (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; } - info->connType = outInfo->GetType(outInfo); - return info->connType; + info->connType_ = outInfo->GetType(outInfo); + return info->connType_; } -static char * ConnectionInfoConnectionString(ConnectionInfo * info) { +char * ConnectionInfoConnectionString(ConnectionInfo * info) { Component * src = NULL; Component * trg = NULL; @@ -256,11 +91,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) { @@ -301,75 +136,32 @@ static char * ConnectionInfoConnectionString(ConnectionInfo * info) { 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; - 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 bd153e5..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,115 +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; - - ChannelType connType; -} ; +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 index 9facd50..b599fd2 100644 --- a/src/core/connections/Connection_impl.h +++ b/src/core/connections/Connection_impl.h @@ -51,7 +51,7 @@ typedef struct ConnectionData { int isActiveDependency; // Meta Data - ConnectionInfo * info; + ConnectionInfo info; // Current state of the connection in state machine ConnectionState state; diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 57cd8a3..eaf3917 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -14,6 +14,7 @@ #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 @@ -46,8 +47,8 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o 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 From a84098a28444efd18accb816d0f7eb0da56957d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 23 Feb 2022 16:54:49 +0100 Subject: [PATCH 070/295] Remove ConnectionData --- src/core/Component.c | 1 - src/core/channels/Channel.c | 2 +- src/core/connections/Connection.c | 141 ++++++++++------------ src/core/connections/Connection.h | 38 +++++- src/core/connections/Connection_impl.h | 69 ----------- src/core/connections/FilteredConnection.c | 7 +- 6 files changed, 105 insertions(+), 153 deletions(-) delete mode 100644 src/core/connections/Connection_impl.h diff --git a/src/core/Component.c b/src/core/Component.c index 658e353..5c1812a 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" diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 5c4f2d8..32aca03 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -200,7 +200,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ConnectionInfo * connInfo = NULL; ChannelValue * val = &channel->data->value; - connInfo = conn->GetInfo(conn); + connInfo = &conn->info; ChannelValueDestructor(val); ChannelValueInit(val, ConnectionInfoGetType(connInfo)); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 9d78700..607d21d 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -10,7 +10,6 @@ #include "CentralParts.h" #include "core/connections/Connection.h" -#include "core/connections/Connection_impl.h" #include "core/channels/Channel.h" #include "core/connections/ConnectionInfo.h" #include "core/Conversion.h" @@ -1052,65 +1051,37 @@ ChannelFilter * FilterFactory(Connection * connection) { } } - filter->AssignState(filter, &connection->data->state); + filter->AssignState(filter, &connection->state_); return filter; } - -static ConnectionData * ConnectionDataCreate(ConnectionData * data) { - data->out = NULL; - data->in = NULL; - - ConnectionInfoInit(&data->info); - - 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) { - 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) { - return ConnectionInfoIsDecoupled(&connection->data->info); + return ConnectionInfoIsDecoupled(&connection->info); } static int ConnectionIsDefinedDuringInit(Connection * connection) { @@ -1125,11 +1096,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) { @@ -1138,13 +1109,13 @@ 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); - if (connection->data->state != InInitializationMode) { + 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); @@ -1160,7 +1131,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { if (inInfo->GetInitialValue(inInfo)) { McxStatus retVal = RETURN_OK; - ChannelValue * store = &connection->data->store; + ChannelValue * store = &connection->store_; ChannelValue * inChannelValue = inInfo->GetInitialValue(inInfo); ChannelValue * inValue = ChannelValueClone(inChannelValue); @@ -1201,17 +1172,17 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { } mcx_free(inValue); - connection->data->useInitialValue = TRUE; + connection->useInitialValue_ = TRUE; } else if (outInfo->GetInitialValue(outInfo)) { - ChannelValueSet(&connection->data->store, outInfo->GetInitialValue(outInfo)); - connection->data->useInitialValue = TRUE; + ChannelValueSet(&connection->store_, outInfo->GetInitialValue(outInfo)); + connection->useInitialValue_ = TRUE; } else { { 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, ConnectionInfoGetType(info)); + ChannelValueInit(&connection->store_, ConnectionInfoGetType(info)); } return RETURN_OK; @@ -1220,7 +1191,7 @@ 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; + Channel * channel = (Channel *) connection->out_; ChannelInfo * info = channel->GetInfo(channel); MCX_DEBUG_LOG("[%f] CONN (%s) UpdateFromInput", time->startTime, info->GetName(info)); } @@ -1229,7 +1200,7 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim } 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) { @@ -1238,8 +1209,8 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) } #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); } @@ -1250,27 +1221,27 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) static McxStatus ConnectionEnterInitializationMode(Connection * connection) { #ifdef MCX_DEBUG - Channel * channel = (Channel *) connection->data->out; + Channel * channel = (Channel *) connection->out_; ChannelInfo * info = channel->GetInfo(channel); MCX_DEBUG_LOG("[%f] CONN (%s) EnterInit", 0.0, info->GetName(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; @@ -1284,21 +1255,21 @@ static McxStatus ConnectionExitInitializationMode(Connection * connection, doubl #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - Channel * channel = (Channel *) connection->data->out; + Channel * channel = (Channel *) connection->out_; ChannelInfo * info = channel->GetInfo(channel); MCX_DEBUG_LOG("[%f] CONN (%s) ExitInit", time, info->GetName(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; @@ -1314,7 +1285,7 @@ static McxStatus ConnectionExitInitializationMode(Connection * connection, doubl } static McxStatus ConnectionEnterCommunicationMode(Connection * connection, double time) { - connection->data->state = InCommunicationMode; + connection->state_ = InCommunicationMode; return RETURN_OK; } @@ -1322,7 +1293,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; } @@ -1333,16 +1304,16 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * Channel * chOut = (Channel *) out; ChannelInfo * outInfo = chOut->GetInfo(chOut); - connection->data->out = out; - connection->data->in = in; + connection->out_ = out; + connection->in_ = in; if (in->IsDiscrete(in)) { info->hasDiscreteTarget = TRUE; } - connection->data->info = *info; + connection->info = *info; - ChannelValueInit(&connection->data->store, outInfo->GetType(outInfo)); + ChannelValueInit(&connection->store_, outInfo->GetType(outInfo)); // Add connection to channel out retVal = out->RegisterConnection(out, connection); @@ -1365,11 +1336,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; @@ -1377,6 +1344,7 @@ static Connection * ConnectionCreate(Connection * connection) { connection->GetTarget = ConnectionGetTarget; connection->GetValueReference = ConnectionGetValueReference; + connection->SetValueReference = ConnectionSetValueReference; connection->GetInfo = ConnectionGetInfo; @@ -1399,6 +1367,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 74e0e23..f4736b9 100644 --- a/src/core/connections/Connection.h +++ b/src/core/connections/Connection.h @@ -50,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); @@ -75,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. * @@ -102,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. */ @@ -169,8 +205,6 @@ struct Connection { fConnectionUpdateInitialValue UpdateInitialValue; fConnectionAddFilter AddFilter; - - struct ConnectionData * data; } ; //------------------------------------------------------------------------------ diff --git a/src/core/connections/Connection_impl.h b/src/core/connections/Connection_impl.h deleted file mode 100644 index b599fd2..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 eaf3917..f025cb0 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -11,7 +11,6 @@ #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" @@ -58,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() @@ -86,7 +85,7 @@ static McxStatus FilteredConnectionEnterCommunicationMode(Connection * connectio } } - connection->data->state = InCommunicationMode; + connection->state_ = InCommunicationMode; return RETURN_OK; } @@ -107,7 +106,7 @@ static McxStatus FilteredConnectionEnterCouplingStepMode(Connection * connection } } - connection->data->state = InCouplingStepMode; + connection->state_ = InCouplingStepMode; return RETURN_OK; } From 836e97d4ff4db7e7a6b602f26efc3f2ec51cc7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 28 Feb 2022 11:55:10 +0100 Subject: [PATCH 071/295] Vector: Add SetAt method --- src/objects/Vector.c | 21 +++++++++++++++++++++ src/objects/Vector.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/src/objects/Vector.c b/src/objects/Vector.c index fe6f1f0..62f00ec 100644 --- a/src/objects/Vector.c +++ b/src/objects/Vector.c @@ -35,6 +35,26 @@ static void * VectorAt(const Vector * vector, size_t idx) { } } +static McxStatus VectorSetAt(Vector * vector, size_t pos, void * elem) { + McxStatus retVal = RETURN_OK; + + if (pos >= vector->size_) { + vector->Resize(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; @@ -217,6 +237,7 @@ static Vector * VectorCreate(Vector * vector) { vector->Setup = VectorSetup; vector->Size = VectorSize; vector->At = VectorAt; + vector->SetAt = VectorSetAt; vector->Resize = VectorResize; vector->PushBack = VectorPushBack; vector->Append = VectorAppend; diff --git a/src/objects/Vector.h b/src/objects/Vector.h index 43c9bef..36b7a35 100644 --- a/src/objects/Vector.h +++ b/src/objects/Vector.h @@ -33,6 +33,7 @@ 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 (*fVectorResize)(Vector * vector, size_t size); typedef McxStatus (*fVectorPushBack)(Vector * vector, void * elem); typedef McxStatus (*fVectorAppend)(Vector * vector, Vector * appendee); @@ -49,6 +50,7 @@ typedef struct Vector { fVectorSetup Setup; fVectorSize Size; fVectorAt At; + fVectorSetAt SetAt; fVectorResize Resize; fVectorPushBack PushBack; fVectorAppend Append; From 563936eeab0e9e4fd3590a1fdde95dd336bfeba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 2 Mar 2022 16:06:42 +0100 Subject: [PATCH 072/295] Vector: Hide Resize and expose a Reserve method --- src/objects/Vector.c | 59 +++++++++++++++++++++++++++----------------- src/objects/Vector.h | 4 +-- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/objects/Vector.c b/src/objects/Vector.c index 62f00ec..d26f695 100644 --- a/src/objects/Vector.c +++ b/src/objects/Vector.c @@ -35,11 +35,41 @@ static void * VectorAt(const Vector * vector, size_t idx) { } } +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_) { - vector->Resize(vector, pos + 1); + VectorResize(vector, pos + 1); } if (vector->elemSetter_) { @@ -78,38 +108,23 @@ static void * VectorFind(const Vector * vector, fVectorElemPredicate pred, void return vector->At(vector, idx); } -static McxStatus VectorResize(Vector * vector, size_t size) { - size_t oldSize = vector->size_; +static McxStatus VectorReserve(Vector * vector, size_t newCapacity) { size_t oldCapacity = vector->capacity_; - size_t i = 0; - McxStatus retVal = RETURN_OK; - vector->size_ = size; - if (oldCapacity < size) { - vector->capacity_ = size + vector->increment_; + 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: Resize: Memory allocation failed"); + mcx_log(LOG_ERROR, "Vector: Reserve: 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 VectorPushBack(Vector * vector, void * elem) { - McxStatus retVal = vector->Resize(vector, vector->size_ + 1); + McxStatus retVal = VectorResize(vector, vector->size_ + 1); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Vector: PushBack: Resize failed"); return RETURN_ERROR; @@ -238,7 +253,7 @@ static Vector * VectorCreate(Vector * vector) { vector->Size = VectorSize; vector->At = VectorAt; vector->SetAt = VectorSetAt; - vector->Resize = VectorResize; + vector->Reserve = VectorReserve; vector->PushBack = VectorPushBack; vector->Append = VectorAppend; vector->Filter = VectorFilter; diff --git a/src/objects/Vector.h b/src/objects/Vector.h index 36b7a35..5572555 100644 --- a/src/objects/Vector.h +++ b/src/objects/Vector.h @@ -34,7 +34,7 @@ typedef void * (*fVectorFind)(const Vector * vector, fVectorElemPredicate pred, 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 (*fVectorResize)(Vector * vector, size_t size); +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); @@ -51,7 +51,7 @@ typedef struct Vector { fVectorSize Size; fVectorAt At; fVectorSetAt SetAt; - fVectorResize Resize; + fVectorReserve Reserve; fVectorPushBack PushBack; fVectorAppend Append; fVectorFilter Filter; From edd73e66eb89772c93f3fac73c92f514f0ed0046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 28 Feb 2022 11:55:18 +0100 Subject: [PATCH 073/295] Inline ChannelInfo into the Channel --- src/components/comp_fmu.c | 53 +-- src/core/Conversion.c | 8 +- src/core/Databus.c | 309 ++++++++------ src/core/Databus_impl.h | 4 +- src/core/Model.c | 21 +- src/core/SubModel.c | 5 +- src/core/channels/Channel.c | 159 ++++---- src/core/channels/ChannelInfo.c | 465 +++++++--------------- src/core/channels/ChannelInfo.h | 190 +++------ src/core/channels/Channel_impl.h | 3 +- src/core/channels/VectorChannelInfo.c | 21 +- src/core/channels/VectorChannelInfo.h | 4 +- src/core/connections/Connection.c | 46 ++- src/core/connections/ConnectionInfo.c | 11 +- src/core/connections/FilteredConnection.c | 4 +- src/fmu/common_fmu2.c | 4 +- src/storage/ChannelStorage.c | 45 +-- src/storage/ComponentStorage.c | 3 +- src/storage/StorageBackendCsv.c | 4 +- 19 files changed, 589 insertions(+), 770 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 8b305d6..8dd698c 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -14,6 +14,7 @@ #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" @@ -55,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); @@ -66,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; } @@ -104,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); @@ -115,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; } @@ -386,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), @@ -424,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), @@ -510,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"); @@ -581,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; } @@ -621,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"); @@ -690,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; } diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 81c9ee8..886def6 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -156,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; } @@ -458,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; } diff --git a/src/core/Databus.c b/src/core/Databus.c index a14cb85..5808840 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,9 +440,20 @@ 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) { @@ -435,58 +461,72 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, 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 %d", 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 %d", 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 %d", 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); @@ -718,7 +758,7 @@ McxStatus DatabusTriggerOutChannels(Databus *db, TimeInterval * time) { 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)); + mcx_log(LOG_ERROR, "Could not update outport %s", ChannelInfoGetName(info)); return RETURN_ERROR; } } @@ -741,7 +781,7 @@ McxStatus DatabusTriggerConnectedInConnections(Databus * db, TimeInterval * cons 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)); + mcx_log(LOG_ERROR, "Could not update inport %s", ChannelInfoGetName(info)); return RETURN_ERROR; } } @@ -766,7 +806,7 @@ McxStatus DatabusTriggerInConnections(Databus * db, TimeInterval * consumerTime) 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)); + mcx_log(LOG_ERROR, "Could not update inport %s", ChannelInfoGetName(info)); return RETURN_ERROR; } } @@ -1099,12 +1139,12 @@ 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)) { + 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; } } @@ -1133,12 +1173,12 @@ McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const voi } info = ((Channel *)out)->GetInfo((Channel *) out); - if (info->GetType(info) != type) { + 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; } @@ -1283,12 +1323,12 @@ 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)) { + 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; } } @@ -1407,19 +1447,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); @@ -1437,61 +1477,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, @@ -1731,7 +1780,7 @@ int DatabusChannelRTFactorIsValid(Databus * db, size_t channel) { } McxStatus DatabusCollectModeSwitchData(Databus * db) { - ObjectContainer * infos = db->data->outInfo->data->infos; + Vector * infos = db->data->outInfo->data->infos; size_t size = infos->Size(infos); size_t i = 0, j = 0, idx = 0; db->modeSwitchDataSize = 0; diff --git a/src/core/Databus_impl.h b/src/core/Databus_impl.h index 147985a..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; diff --git a/src/core/Model.c b/src/core/Model.c index 5200f65..bb789a8 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -24,6 +24,7 @@ #include "core/Databus.h" #include "core/channels/Channel.h" +#include "core/channels/ChannelInfo.h" #include "core/connections/Connection.h" #include "core/connections/FilteredConnection.h" #include "core/SubModel.h" @@ -76,7 +77,7 @@ static int IsBinaryConn(void * elem, void * args) { ChannelInfo * srcInfo = GetSourceChannelInfo(info); ChannelInfo * trgInfo = GetTargetChannelInfo(info); - return srcInfo->IsBinary(srcInfo) && trgInfo->IsBinary(trgInfo); + return ChannelInfoIsBinary(srcInfo) && ChannelInfoIsBinary(trgInfo); } static int CanMakeChannelsBinReferences(Vector * connInfos, Task * task) { @@ -196,31 +197,31 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { goto cleanup_1; } - ChannelValueInit(src, srcChannelInfo->GetType(srcChannelInfo)); + 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->GetMin(srcChannelInfo), srcChannelInfo->GetMax(srcChannelInfo), src); + retVal = ConvertRange(srcChannelInfo->min, srcChannelInfo->max, src); if (retVal == RETURN_ERROR) { goto cleanup_1; } - retVal = ConvertLinear(srcChannelInfo->GetScale(srcChannelInfo), srcChannelInfo->GetOffset(srcChannelInfo), src); + retVal = ConvertLinear(srcChannelInfo->scale, srcChannelInfo->offset, src); if (retVal == RETURN_ERROR) { goto cleanup_1; } // type conversion - retVal = ConvertType(srcChannelInfo->GetType(srcChannelInfo), trgChannelInfo->GetType(trgChannelInfo), src); + retVal = ConvertType(srcChannelInfo->type, trgChannelInfo->type, src); if (retVal == RETURN_ERROR) { goto cleanup_1; } // unit conversion - retVal = ConvertUnit(srcChannelInfo->GetUnit(srcChannelInfo), trgChannelInfo->GetUnit(trgChannelInfo), src); + retVal = ConvertUnit(srcChannelInfo->unitString, trgChannelInfo->unitString, src); if (retVal == RETURN_ERROR) { goto cleanup_1; } @@ -883,10 +884,10 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para Channel * channel = (Channel *)DatabusGetInChannel(db, i); ChannelInfo * info = channel->GetInfo(channel); - 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)); + , i+1, ChannelInfoGetName(info), comp->GetName(comp)); return RETURN_ERROR; } } @@ -895,10 +896,10 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para Channel * channel = (Channel *)DatabusGetOutChannel(db, i); ChannelInfo * info = channel->GetInfo(channel); - 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)); + , i+1, ChannelInfoGetName(info), comp->GetName(comp)); return RETURN_ERROR; } } diff --git a/src/core/SubModel.c b/src/core/SubModel.c index e23dbf7..8d3b13c 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -14,6 +14,7 @@ #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" @@ -81,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) { @@ -90,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)); } } } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 32aca03..2f344c3 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -25,9 +25,10 @@ extern "C" { // Channel static ChannelData * ChannelDataCreate(ChannelData * data) { - /* create dummy info*/ - data->info = (ChannelInfo *) object_create(ChannelInfo); - if (!data->info) { + McxStatus retVal = RETURN_OK; + + retVal = ChannelInfoInit(&data->info); + if (RETURN_ERROR == retVal) { return NULL; } @@ -39,9 +40,7 @@ static ChannelData * ChannelDataCreate(ChannelData * data) { } static void ChannelDataDestructor(ChannelData * data) { - // Note: This is done in Databus - // object_destroy(data->info); - + ChannelInfoDestroy(&data->info); ChannelValueDestructor(&data->value); } @@ -57,16 +56,19 @@ static void ChannelSetDefinedDuringInit(Channel * channel) { } static ChannelInfo * ChannelGetInfo(Channel * channel) { - return channel->data->info; + return &channel->data->info; } 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->data->info, info); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } + return RETURN_OK; } @@ -145,20 +147,20 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel 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; } } @@ -177,9 +179,9 @@ static const void * ChannelInGetValueReference(Channel * channel) { if (i < maxCountError) { ChannelInfo * info = channel->GetInfo(channel); 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; @@ -214,26 +216,26 @@ 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) { + if (info->type == 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)); + 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) { + if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) { ChannelValue * val = &channel->data->value; // linear @@ -241,7 +243,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { 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)); + mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute linear conversion", ChannelInfoGetLogName(info)); return RETURN_ERROR; } } @@ -251,7 +253,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { 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)); + mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute range conversion", ChannelInfoGetLogName(info)); return RETURN_ERROR; } } @@ -264,11 +266,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); @@ -349,7 +351,7 @@ static int ChannelInIsDiscrete(ChannelIn * in) { } static int ChannelInIsConnected(Channel * channel) { - if (channel->data->info && channel->data->info->connected) { + if (channel->data->info.type != CHANNEL_UNKNOWN && channel->data->info.connected) { return TRUE; } else { ChannelIn * in = (ChannelIn *) channel; @@ -390,13 +392,13 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, // setup unit conversion inInfo = channel->GetInfo(channel); - 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; } @@ -406,13 +408,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; } } @@ -429,7 +431,7 @@ 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); @@ -439,12 +441,12 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { ChannelValueSet(&channel->data->value, info->defaultValue); // apply range and linear conversions immediately - retVal = ConvertRange(info->GetMin(info), info->GetMax(info), &channel->data->value); + retVal = ConvertRange(info->min, info->max, &channel->data->value); if (retVal == RETURN_ERROR) { return RETURN_ERROR; } - retVal = ConvertLinear(info->GetScale(info), info->GetOffset(info), &channel->data->value); + retVal = ConvertLinear(info->scale, info->offset, &channel->data->value); if (retVal == RETURN_ERROR) { return RETURN_ERROR; } @@ -456,19 +458,18 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { // 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 { @@ -480,7 +481,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 { @@ -571,11 +572,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; @@ -583,25 +584,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); // default value if (info->defaultValue) { - channel->data->internalValue = ChannelValueReference(info->defaultValue); + channel->data->internalValue = ChannelValueReference(channel->data->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 { @@ -613,7 +613,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 { @@ -624,7 +624,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; } @@ -646,7 +646,7 @@ static const void * ChannelOutGetValueReference(Channel * channel) { // 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; } @@ -666,7 +666,7 @@ static int ChannelOutIsValid(Channel * channel) { } static int ChannelOutIsConnected(Channel * channel) { - if (channel->data->info->connected) { + if (channel->data->info.connected) { return TRUE; } else { ChannelOut * out = (ChannelOut *) channel; @@ -690,20 +690,20 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference } info = channel->GetInfo(channel); 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)); + 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; } } @@ -725,13 +725,13 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r info = channel->GetInfo(channel); 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; } @@ -748,7 +748,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"); @@ -756,7 +756,7 @@ 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); } } @@ -779,21 +779,21 @@ 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); } 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); } 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 @@ -801,8 +801,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // Apply conversion - if (info->GetType(info) == CHANNEL_DOUBLE || - info->GetType(info) == CHANNEL_INTEGER) { + if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) { ChannelValue * val = &channel->data->value; // range @@ -811,7 +810,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; } } @@ -822,7 +821,7 @@ 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; } } @@ -838,7 +837,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } - if (CHANNEL_DOUBLE == info->GetType(info)) { + if (CHANNEL_DOUBLE == info->type) { const double * val = NULL; { @@ -851,13 +850,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); @@ -950,12 +949,12 @@ static McxStatus ChannelLocalSetReference(ChannelLocal * local, } 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)); + 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; } } 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/Channel_impl.h b/src/core/channels/Channel_impl.h index 7066f89..4d38142 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -13,6 +13,7 @@ #include "CentralParts.h" #include "objects/ObjectContainer.h" +#include "core/channels/ChannelInfo.h" #ifdef __cplusplus extern "C" { @@ -27,7 +28,7 @@ typedef struct ChannelData { // ---------------------------------------------------------------------- // General Information - ChannelInfo * info; + ChannelInfo info; // ---------------------------------------------------------------------- // Value 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 607d21d..cac2393 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -11,6 +11,7 @@ #include "CentralParts.h" #include "core/connections/Connection.h" #include "core/channels/Channel.h" +#include "core/channels/ChannelInfo.h" #include "core/connections/ConnectionInfo.h" #include "core/Conversion.h" @@ -31,6 +32,29 @@ extern "C" { #endif /* __cplusplus */ + +static void UpdateInChannelInfo(Component * comp, size_t idx) { + Databus * db = comp->GetDatabus(comp); + ChannelInfo * src = DatabusGetInChannelInfo(db, idx); + + Channel * channel = (Channel *) DatabusGetInChannel(db, idx); + + if (channel) { + channel->GetInfo(channel)->connected = 1; + } +} + +static void UpdateOutChannelInfo(Component * comp, size_t idx) { + Databus * db = comp->GetDatabus(comp); + ChannelInfo * src = DatabusGetOutChannelInfo(db, idx); + + Channel * channel = (Channel *) DatabusGetOutChannel(db, idx); + + if (channel) { + channel->GetInfo(channel)->connected = 1; + } +} + McxStatus CheckConnectivity(Vector * connections) { size_t i = 0; @@ -48,11 +72,13 @@ McxStatus CheckConnectivity(Vector * connections) { 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); } } @@ -1129,10 +1155,10 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { return RETURN_ERROR; } - if (inInfo->GetInitialValue(inInfo)) { + if (inInfo->initialValue) { McxStatus retVal = RETURN_OK; ChannelValue * store = &connection->store_; - ChannelValue * inChannelValue = inInfo->GetInitialValue(inInfo); + ChannelValue * inChannelValue = inInfo->initialValue; ChannelValue * inValue = ChannelValueClone(inChannelValue); if (NULL == inValue) { @@ -1173,8 +1199,8 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { mcx_free(inValue); connection->useInitialValue_ = TRUE; - } else if (outInfo->GetInitialValue(outInfo)) { - ChannelValueSet(&connection->store_, outInfo->GetInitialValue(outInfo)); + } else if (outInfo->initialValue) { + ChannelValueSet(&connection->store_, outInfo->initialValue); connection->useInitialValue_ = TRUE; } else { { @@ -1193,7 +1219,7 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim if (time->startTime < MCX_DEBUG_LOG_TIME) { Channel * channel = (Channel *) connection->out_; ChannelInfo * info = channel->GetInfo(channel); - MCX_DEBUG_LOG("[%f] CONN (%s) UpdateFromInput", time->startTime, info->GetName(info)); + MCX_DEBUG_LOG("[%f] CONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info)); } #endif // Do nothing @@ -1205,7 +1231,7 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) #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)); + MCX_DEBUG_LOG("[%f] CONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -1223,7 +1249,7 @@ static McxStatus ConnectionEnterInitializationMode(Connection * connection) { #ifdef MCX_DEBUG Channel * channel = (Channel *) connection->out_; ChannelInfo * info = channel->GetInfo(channel); - MCX_DEBUG_LOG("[%f] CONN (%s) EnterInit", 0.0, info->GetName(info)); + MCX_DEBUG_LOG("[%f] CONN (%s) EnterInit", 0.0, ChannelInfoGetName(info)); #endif if (connection->state_ == InInitializationMode) { @@ -1257,7 +1283,7 @@ static McxStatus ConnectionExitInitializationMode(Connection * connection, doubl if (time < MCX_DEBUG_LOG_TIME) { Channel * channel = (Channel *) connection->out_; ChannelInfo * info = channel->GetInfo(channel); - MCX_DEBUG_LOG("[%f] CONN (%s) ExitInit", time, info->GetName(info)); + MCX_DEBUG_LOG("[%f] CONN (%s) ExitInit", time, ChannelInfoGetName(info)); } #endif @@ -1313,7 +1339,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * connection->info = *info; - ChannelValueInit(&connection->store_, outInfo->GetType(outInfo)); + ChannelValueInit(&connection->store_, outInfo->type); // Add connection to channel out retVal = out->RegisterConnection(out, connection); @@ -1324,7 +1350,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * 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 = ConnectionInfoConnectionString(info); mcx_log(LOG_ERROR, "Connection %s: Setup connection: Could not register with inport", buffer); diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index 8c6cc82..c5e7fba 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -9,6 +9,7 @@ ********************************************************************************/ #include "core/connections/ConnectionInfo.h" +#include "core/channels/ChannelInfo.h" #include "core/Model.h" #include "core/Databus.h" @@ -63,7 +64,7 @@ ChannelType ConnectionInfoGetType(ConnectionInfo * info) { return CHANNEL_UNKNOWN; } - info->connType_ = outInfo->GetType(outInfo); + info->connType_ = outInfo->type; return info->connType_; } @@ -117,9 +118,9 @@ 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)); @@ -129,9 +130,9 @@ 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; } diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index f025cb0..01e2be5 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -127,7 +127,7 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter #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)); + MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -150,7 +150,7 @@ static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterv #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)); + MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info)); } #endif diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 1fa6e6f..7d1c0c6 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" @@ -1037,7 +1039,7 @@ 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)); + mcx_log(LOG_DEBUG, "Setting input \"%s\" as discrete", ChannelInfoGetLogName(info)); in->SetDiscrete(in); } } diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 4aa3807..b483050 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -37,7 +37,7 @@ 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)); + mcx_log(LOG_ERROR, "Results: Register port %s: Cannot register ports to storage after values have been stored", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -45,7 +45,7 @@ static McxStatus ChannelStorageRegisterChannelInternal(ChannelStorage * channelS 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)); + mcx_log(LOG_DEBUG, "Results: Register port %s: Pushback of port failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -57,7 +57,7 @@ static McxStatus ChannelStorageRegisterChannel(ChannelStorage * channelStore, Ch 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)); + 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; @@ -156,7 +153,7 @@ static McxStatus ChannelStorageSetValueFromReferenceAt(ChannelStorage * channelS if (row >= channelStore->numValues) { ChannelInfo * info = channel->GetInfo(channel); - ChannelValueInit(&channelStore->values[row * colNum + col], info->GetType(info)); + ChannelValueInit(&channelStore->values[row * colNum + col], info->type); } ChannelValueSetFromReference(&channelStore->values[row * colNum + col], reference); @@ -208,7 +205,7 @@ static McxStatus ChannelStorageStoreFull(ChannelStorage * channelStore, double t 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)); + mcx_log(LOG_DEBUG, "Results: Error in store port %s", ChannelInfoGetLogName(info)); return RETURN_ERROR; } } @@ -250,7 +247,7 @@ static McxStatus ChannelStorageStoreNonFull(ChannelStorage * channelStore, doubl 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)); + mcx_log(LOG_DEBUG, "Results: Error in store port %s", ChannelInfoGetLogName(info)); return RETURN_ERROR; } } diff --git a/src/storage/ComponentStorage.c b/src/storage/ComponentStorage.c index f9b8008..315194b 100644 --- a/src/storage/ComponentStorage.c +++ b/src/storage/ComponentStorage.c @@ -51,8 +51,7 @@ static McxStatus ComponentStorageRegisterChannel(ComponentStorage * compStore, C if (compStore->storeLevel > STORE_NONE) { ChannelInfo * info = channel->GetInfo(channel); - if (compStore->storage->channelStoreEnabled[chType] - && info->GetWriteResultFlag(info)) { + if (compStore->storage->channelStoreEnabled[chType] && info->writeResult) { return channels->RegisterChannel(channels, channel); } } 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 = ""; From 8dc290f338a00557283f042fe1976d8affcb920c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 2 Mar 2022 16:46:13 +0100 Subject: [PATCH 074/295] Drop ChannelData --- src/core/channels/Channel.c | 100 +++++++++++++------------------ src/core/channels/Channel.h | 17 ++++-- src/core/channels/Channel_impl.h | 20 ------- 3 files changed, 54 insertions(+), 83 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 2f344c3..0e1c3e7 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -24,39 +24,17 @@ extern "C" { // ---------------------------------------------------------------------- // Channel -static ChannelData * ChannelDataCreate(ChannelData * data) { - McxStatus retVal = RETURN_OK; - - retVal = ChannelInfoInit(&data->info); - if (RETURN_ERROR == retVal) { - return NULL; - } - - data->isDefinedDuringInit = FALSE; - data->internalValue = NULL; - ChannelValueInit(&data->value, CHANNEL_UNKNOWN); - - return data; -} - -static void ChannelDataDestructor(ChannelData * data) { - ChannelInfoDestroy(&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; + channel->isDefinedDuringInit = TRUE; } static ChannelInfo * ChannelGetInfo(Channel * channel) { - return &channel->data->info; + return &channel->info; } static McxStatus ChannelSetup(Channel * channel, ChannelInfo * info) { @@ -64,7 +42,7 @@ static McxStatus ChannelSetup(Channel * channel, ChannelInfo * info) { info->channel = channel; - retVal = ChannelInfoSetFrom(&channel->data->info, info); + retVal = ChannelInfoSetFrom(&channel->info, info); if (RETURN_ERROR == retVal) { return RETURN_ERROR; } @@ -73,15 +51,19 @@ static McxStatus ChannelSetup(Channel * channel, ChannelInfo * info) { } 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->isDefinedDuringInit = FALSE; + channel->internalValue = NULL; + ChannelValueInit(&channel->value, CHANNEL_UNKNOWN); + channel->GetInfo = ChannelGetInfo; channel->Setup = ChannelSetup; channel->IsDefinedDuringInit = ChannelIsDefinedDuringInit; @@ -187,7 +169,7 @@ static const void * ChannelInGetValueReference(Channel * channel) { return NULL; } - return ChannelValueReference(&channel->data->value); + return ChannelValueReference(&channel->value); } static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { @@ -200,7 +182,7 @@ 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->info; @@ -223,7 +205,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { if (info->type == CHANNEL_DOUBLE) { - ChannelValue * val = &channel->data->value; + ChannelValue * val = &channel->value; // unit if (in->data->unitConversion) { Conversion * conversion = (Conversion *) in->data->unitConversion; @@ -236,7 +218,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { } if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) { - ChannelValue * val = &channel->data->value; + ChannelValue * val = &channel->value; // linear if (in->data->linearConversion) { @@ -351,7 +333,7 @@ static int ChannelInIsDiscrete(ChannelIn * in) { } static int ChannelInIsConnected(Channel * channel) { - if (channel->data->info.type != CHANNEL_UNKNOWN && channel->data->info.connected) { + if (channel->info.type != CHANNEL_UNKNOWN && channel->info.connected) { return TRUE; } else { ChannelIn * in = (ChannelIn *) channel; @@ -387,7 +369,7 @@ 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); @@ -434,25 +416,25 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * 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->data->value); + retVal = ConvertRange(info->min, info->max, &channel->value); if (retVal == RETURN_ERROR) { return RETURN_ERROR; } - retVal = ConvertLinear(info->scale, info->offset, &channel->data->value); + 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 @@ -587,11 +569,11 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * 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(channel->data->info.defaultValue); + channel->internalValue = ChannelValueReference(channel->info.defaultValue); } @@ -650,7 +632,7 @@ static const void * ChannelOutGetValueReference(Channel * channel) { return NULL; } - return ChannelValueReference(&channel->data->value); + return ChannelValueReference(&channel->value); } static const proc * ChannelOutGetFunction(ChannelOut * out) { @@ -662,11 +644,11 @@ static ObjectList * ChannelOutGetConnections(ChannelOut * out) { } 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; @@ -693,8 +675,8 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference 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))) { + 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; } @@ -709,7 +691,7 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference } } - channel->data->internalValue = reference; + channel->internalValue = reference; return RETURN_OK; } @@ -739,7 +721,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; } @@ -782,7 +764,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { 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) { @@ -791,18 +773,18 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { time->startTime, ChannelInfoGetLogName(info), time->startTime, - * (double *) channel->data->internalValue); + * (double *) channel->internalValue); } else { 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->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) { - ChannelValue * val = &channel->data->value; + ChannelValue * val = &channel->value; // range if (out->data->rangeConversion) { @@ -841,7 +823,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { const double * val = NULL; { - val = &channel->data->value.value.d; + val = &channel->value.value.d; } if (isnan(*val)) @@ -924,7 +906,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) { @@ -932,7 +914,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) @@ -947,8 +929,8 @@ static McxStatus ChannelLocalSetReference(ChannelLocal * local, 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))) { + 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; } @@ -959,7 +941,7 @@ static McxStatus ChannelLocalSetReference(ChannelLocal * local, } } - 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 5dd16b6..ea8de5c 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; @@ -53,6 +52,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. * @@ -98,8 +109,6 @@ struct Channel { * Initialize channel with info struct. */ fChannelSetup Setup; - - struct ChannelData * data; }; // ---------------------------------------------------------------------- diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index 4d38142..af2a837 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -19,27 +19,7 @@ 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 From 544824723657c45bc2e0b539df720443de5d0990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 2 Mar 2022 17:07:08 +0100 Subject: [PATCH 075/295] Inline Channel::GetInfo --- src/core/Component.c | 8 +++---- src/core/Databus.c | 12 +++++----- src/core/Model.c | 4 ++-- src/core/channels/Channel.c | 27 +++++++++-------------- src/core/channels/Channel.h | 7 ------ src/core/connections/Connection.c | 18 +++++++-------- src/core/connections/FilteredConnection.c | 10 ++++----- src/fmu/common_fmu2.c | 2 +- src/storage/ChannelStorage.c | 16 +++++++------- src/storage/ComponentStorage.c | 2 +- 10 files changed, 46 insertions(+), 60 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 5c1812a..e9fb4e2 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -635,7 +635,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numOut; i++) { Channel * channel = (Channel *) DatabusGetOutChannel(db, i); - char * id = channel->GetInfo(channel)->id; + char * id = channel->info.id; if (NULL != id) { StringContainerSetKeyValue(container, *count, id, channel); @@ -645,7 +645,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numIn; i++) { Channel * channel = (Channel *) DatabusGetInChannel(db, i); - char * id = channel->GetInfo(channel)->id; + char * id = channel->info.id; int isValid = DatabusChannelInIsValid(db, i); if (NULL != id && isValid) { @@ -656,7 +656,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numLocal; i++) { Channel * channel = (Channel *) DatabusGetLocalChannel(db, i); - char * id = channel->GetInfo(channel)->id; + char * id = channel->info.id; int isValid = DatabusChannelLocalIsValid(db, i); if (NULL != id && isValid) { @@ -667,7 +667,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numRTFactor; i++) { Channel * channel = (Channel *) DatabusGetRTFactorChannel(db, i); - char * id = channel->GetInfo(channel)->id; + char * id = channel->info.id; int isValid = DatabusChannelRTFactorIsValid(db, i); if (NULL != id && isValid) { diff --git a/src/core/Databus.c b/src/core/Databus.c index 5808840..2cbb700 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -757,7 +757,7 @@ 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); + ChannelInfo * info = &out->info; mcx_log(LOG_ERROR, "Could not update outport %s", ChannelInfoGetName(info)); return RETURN_ERROR; } @@ -780,7 +780,7 @@ McxStatus DatabusTriggerConnectedInConnections(Databus * db, TimeInterval * cons Channel * channel = (Channel *)db->data->inConnected[i]; retVal = channel->Update(channel, consumerTime); if (RETURN_OK != retVal) { - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; mcx_log(LOG_ERROR, "Could not update inport %s", ChannelInfoGetName(info)); return RETURN_ERROR; } @@ -805,7 +805,7 @@ McxStatus DatabusTriggerInConnections(Databus * db, TimeInterval * consumerTime) if (channel->IsValid(channel)) { retVal = channel->Update(channel, consumerTime); if (RETURN_OK != retVal) { - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; mcx_log(LOG_ERROR, "Could not update inport %s", ChannelInfoGetName(info)); return RETURN_ERROR; } @@ -1138,7 +1138,7 @@ McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * refe } if (CHANNEL_UNKNOWN != type) { - ChannelInfo * info = ((Channel *)out)->GetInfo((Channel *) out); + ChannelInfo * info = &((Channel *)out)->info; if (info->type != type) { if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) { // ok @@ -1172,7 +1172,7 @@ McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const voi return RETURN_ERROR; } - info = ((Channel *)out)->GetInfo((Channel *) out); + 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", ChannelInfoGetName(info), ChannelTypeToString(info->type), ChannelTypeToString(type)); @@ -1322,7 +1322,7 @@ McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, } if (CHANNEL_UNKNOWN != type) { - info = ((Channel *)in)->GetInfo((Channel *)in); + info = &((Channel *)in)->info; if (info->type != type) { if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) { // ok diff --git a/src/core/Model.c b/src/core/Model.c index bb789a8..5364439 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -882,7 +882,7 @@ 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->mode == CHANNEL_MANDATORY) && !channel->IsValid(channel)) { @@ -894,7 +894,7 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para for (i = 0; i < numOutChannels; i++) { Channel * channel = (Channel *)DatabusGetOutChannel(db, i); - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; if ((info->mode == CHANNEL_MANDATORY) && !channel->IsValid(channel)) { diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 0e1c3e7..6d656d8 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -33,10 +33,6 @@ static void ChannelSetDefinedDuringInit(Channel * channel) { channel->isDefinedDuringInit = TRUE; } -static ChannelInfo * ChannelGetInfo(Channel * channel) { - return &channel->info; -} - static McxStatus ChannelSetup(Channel * channel, ChannelInfo * info) { McxStatus retVal = RETURN_OK; @@ -64,7 +60,6 @@ static Channel * ChannelCreate(Channel * channel) { channel->internalValue = NULL; ChannelValueInit(&channel->value, CHANNEL_UNKNOWN); - channel->GetInfo = ChannelGetInfo; channel->Setup = ChannelSetup; channel->IsDefinedDuringInit = ChannelIsDefinedDuringInit; channel->SetDefinedDuringInit = ChannelSetDefinedDuringInit; @@ -122,7 +117,7 @@ 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"); @@ -159,7 +154,7 @@ 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", ChannelInfoGetLogName(info)); if (i == maxCountError) { @@ -174,7 +169,7 @@ static const void * ChannelInGetValueReference(Channel * channel) { 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; @@ -316,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; } @@ -347,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; } @@ -372,7 +367,7 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, channel->internalValue = connection->GetValueReference(connection); // setup unit conversion - inInfo = channel->GetInfo(channel); + inInfo = &channel->info; if (inInfo->type == CHANNEL_DOUBLE) { in->data->unitConversion = (UnitConversion *) object_create(UnitConversion); @@ -624,7 +619,7 @@ static McxStatus ChannelOutRegisterConnection(ChannelOut * out, Connection * con 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)) { @@ -670,7 +665,7 @@ 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", ChannelInfoGetLogName(info)); return RETURN_ERROR; @@ -704,7 +699,7 @@ 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", ChannelInfoGetLogName(info)); @@ -744,7 +739,7 @@ static void WarnAboutNaN(LogSeverity level, ChannelInfo * info, TimeInterval * t static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ChannelOut * out = (ChannelOut *)channel; - ChannelInfo * info = ((Channel *)out)->GetInfo((Channel *)out); + ChannelInfo * info = &channel->info; ObjectList * conns = out->data->connections; @@ -924,7 +919,7 @@ 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; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index ea8de5c..9847dc1 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -41,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); @@ -79,11 +77,6 @@ struct Channel { */ fChannelUpdate Update; - /** - * Return info struct of channel. - */ - fChannelGetInfo GetInfo; - /** * Virtual method. * diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index cac2393..a25d76e 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -40,7 +40,7 @@ static void UpdateInChannelInfo(Component * comp, size_t idx) { Channel * channel = (Channel *) DatabusGetInChannel(db, idx); if (channel) { - channel->GetInfo(channel)->connected = 1; + channel->info.connected = 1; } } @@ -51,7 +51,7 @@ static void UpdateOutChannelInfo(Component * comp, size_t idx) { Channel * channel = (Channel *) DatabusGetOutChannel(db, idx); if (channel) { - channel->GetInfo(channel)->connected = 1; + channel->info.connected = 1; } } @@ -1138,8 +1138,8 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { 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->state_ != InInitializationMode) { char * buffer = ConnectionInfoConnectionString(info); @@ -1218,7 +1218,7 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { Channel * channel = (Channel *) connection->out_; - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] CONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -1230,7 +1230,7 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] CONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -1248,7 +1248,7 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) static McxStatus ConnectionEnterInitializationMode(Connection * connection) { #ifdef MCX_DEBUG Channel * channel = (Channel *) connection->out_; - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] CONN (%s) EnterInit", 0.0, ChannelInfoGetName(info)); #endif @@ -1282,7 +1282,7 @@ static McxStatus ConnectionExitInitializationMode(Connection * connection, doubl #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { Channel * channel = (Channel *) connection->out_; - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] CONN (%s) ExitInit", time, ChannelInfoGetName(info)); } #endif @@ -1328,7 +1328,7 @@ 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->out_ = out; connection->in_ = in; diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 01e2be5..9f6e0d8 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -40,8 +40,8 @@ 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; @@ -122,11 +122,10 @@ 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); + ChannelInfo * info = &channel->info; #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - ChannelInfo * info = channel->GetInfo(channel); MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -145,11 +144,10 @@ static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterv Channel * channel = (Channel *) connection->GetSource(connection); ChannelOut * out = (ChannelOut *) channel; - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - ChannelInfo * info = channel->GetInfo(channel); MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info)); } #endif diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 7d1c0c6..ffe2488 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -1038,7 +1038,7 @@ void Fmu2MarkTunableParamsAsInputAsDiscrete(ObjectContainer * in) { if (fmi2_causality_enu_input != causality) { ChannelIn * in = (ChannelIn *) val->channel; - ChannelInfo * info = ((Channel*)in)->GetInfo((Channel*)in); + ChannelInfo * info = &((Channel*)in)->info; mcx_log(LOG_DEBUG, "Setting input \"%s\" as discrete", ChannelInfoGetLogName(info)); in->SetDiscrete(in); } diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index b483050..80b6903 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -36,7 +36,7 @@ static McxStatus ChannelStorageRegisterChannelInternal(ChannelStorage * channelS /* if values have already been written, do not allow registering additional channels */ if (channelStore->values) { - info = channel->GetInfo(channel); + 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; } @@ -44,7 +44,7 @@ static McxStatus ChannelStorageRegisterChannelInternal(ChannelStorage * channelS /* add channel */ retVal = channels->PushBack(channels, (Object *)object_strong_reference(channel)); if (RETURN_OK != retVal) { - info = channel->GetInfo(channel); + info = &channel->info; mcx_log(LOG_DEBUG, "Results: Register port %s: Pushback of port failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -56,7 +56,7 @@ static McxStatus ChannelStorageRegisterChannel(ChannelStorage * channelStore, Ch ObjectContainer * channels = channelStore->channels; if (0 == channels->Size(channels)) { - ChannelInfo *info = channel->GetInfo(channel); + ChannelInfo *info = &channel->info; mcx_log(LOG_ERROR, "Results: Register port %s: Port storage not yet setup", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -152,7 +152,7 @@ static McxStatus ChannelStorageSetValueFromReferenceAt(ChannelStorage * channelS } if (row >= channelStore->numValues) { - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; ChannelValueInit(&channelStore->values[row * colNum + col], info->type); } @@ -204,7 +204,7 @@ 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); + ChannelInfo *info = &channel->info; mcx_log(LOG_DEBUG, "Results: Error in store port %s", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -246,7 +246,7 @@ 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); + ChannelInfo *info = &channel->info; mcx_log(LOG_DEBUG, "Results: Error in store port %s", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -274,7 +274,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; } @@ -301,7 +301,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++) { diff --git a/src/storage/ComponentStorage.c b/src/storage/ComponentStorage.c index 315194b..a6ce392 100644 --- a/src/storage/ComponentStorage.c +++ b/src/storage/ComponentStorage.c @@ -50,7 +50,7 @@ static McxStatus ComponentStorageRegisterChannel(ComponentStorage * compStore, C ChannelStorage * channels = compStore->channels[chType]; if (compStore->storeLevel > STORE_NONE) { - ChannelInfo * info = channel->GetInfo(channel); + ChannelInfo * info = &channel->info; if (compStore->storage->channelStoreEnabled[chType] && info->writeResult) { return channels->RegisterChannel(channels, channel); } From 27a29e0616ee0bf420b81ef37d5c38c66139c93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 14:56:05 +0100 Subject: [PATCH 076/295] Vector optimizations --- src/objects/Vector.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/objects/Vector.c b/src/objects/Vector.c index d26f695..49915e3 100644 --- a/src/objects/Vector.c +++ b/src/objects/Vector.c @@ -155,6 +155,11 @@ static McxStatus VectorAppend(Vector * vector, Vector * appendee) { } 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) { From b5c256bb62e02b1b7747f1273afe002fe85057f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 15:11:50 +0100 Subject: [PATCH 077/295] Remove unused variables --- src/core/connections/Connection.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index a25d76e..8b75a5c 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -35,8 +35,6 @@ extern "C" { static void UpdateInChannelInfo(Component * comp, size_t idx) { Databus * db = comp->GetDatabus(comp); - ChannelInfo * src = DatabusGetInChannelInfo(db, idx); - Channel * channel = (Channel *) DatabusGetInChannel(db, idx); if (channel) { @@ -46,8 +44,6 @@ static void UpdateInChannelInfo(Component * comp, size_t idx) { static void UpdateOutChannelInfo(Component * comp, size_t idx) { Databus * db = comp->GetDatabus(comp); - ChannelInfo * src = DatabusGetOutChannelInfo(db, idx); - Channel * channel = (Channel *) DatabusGetOutChannel(db, idx); if (channel) { From f8bb70f286331b63fbac47bf8d503cbb927eb2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 22 Mar 2022 15:12:26 +0100 Subject: [PATCH 078/295] Move variables closer to the place where they are used --- src/core/connections/FilteredConnection.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 9f6e0d8..79aa80a 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -122,10 +122,10 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter FilteredConnection * filteredConnection = (FilteredConnection *) connection; ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection); Channel * channel = (Channel *) connection->GetSource(connection); - ChannelInfo * info = &channel->info; #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { + ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -144,10 +144,9 @@ static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterv Channel * channel = (Channel *) connection->GetSource(connection); ChannelOut * out = (ChannelOut *) channel; - ChannelInfo * info = &channel->info; - #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { + ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info)); } #endif From 5854fa6df666169a857cf3ab4ff01e937df7bcf3 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 9 Mar 2024 14:48:39 +0100 Subject: [PATCH 079/295] Simplify ResultStorage --- src/core/Config.c | 1 - src/core/Config.h | 1 + src/storage/ChannelStorage.c | 6 ++++++ src/storage/ChannelStorage.h | 2 ++ src/storage/ResultsStorage.c | 7 ++++++- src/storage/ResultsStorage.h | 10 ++++++---- src/storage/StorageBackendText.c | 26 ++++++++++++++++++-------- 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/core/Config.c b/src/core/Config.c index 6798666..6842a0b 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -565,7 +565,6 @@ static Config * ConfigCreate(Config * config) { config->executable = NULL; config->flushEveryStore = FALSE; - config->sumTimeDefined = FALSE; config->sumTime = TRUE; diff --git a/src/core/Config.h b/src/core/Config.h index e520d6f..7cd97eb 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -56,6 +56,7 @@ struct Config { char * executable; int flushEveryStore; + int sumTime; int sumTimeDefined; diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 80b6903..7cf8f14 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -264,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; @@ -321,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/ResultsStorage.c b/src/storage/ResultsStorage.c index 1837d65..ecefdc4 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; @@ -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; diff --git a/src/storage/ResultsStorage.h b/src/storage/ResultsStorage.h index 67bef97..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; 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; From 1ef31f47571d15810a09f6a878cfbcc50159bfca Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 9 Mar 2024 14:49:12 +0100 Subject: [PATCH 080/295] Check that the Databus channels were set before trying to update their infos --- src/core/Databus.c | 7 +++++++ src/core/Databus.h | 3 +++ src/core/connections/Connection.c | 16 ++++++++++------ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 2cbb700..cfe4680 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -973,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; diff --git a/src/core/Databus.h b/src/core/Databus.h index d55290a..70cda7e 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -292,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. * diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 8b75a5c..67622d2 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -35,19 +35,23 @@ extern "C" { static void UpdateInChannelInfo(Component * comp, size_t idx) { Databus * db = comp->GetDatabus(comp); - Channel * channel = (Channel *) DatabusGetInChannel(db, idx); - if (channel) { - channel->info.connected = 1; + 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); - Channel * channel = (Channel *) DatabusGetOutChannel(db, idx); - if (channel) { - channel->info.connected = 1; + if (DatabusOutChannelsDefined(db)) { + Channel * channel = (Channel *) DatabusGetOutChannel(db, idx); + if (channel) { + channel->info.connected = 1; + } } } From bdb8500abcf6e2211d8a301fd86e27319fbc14bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 6 Apr 2022 12:19:32 +0200 Subject: [PATCH 081/295] Define a ContainsComponent method --- src/core/Component.c | 2 ++ src/core/Component.h | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/core/Component.c b/src/core/Component.c index e9fb4e2..eb05b1c 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -1239,6 +1239,8 @@ static Component * ComponentCreate(Component * comp) { comp->SetModel = ComponentSetModel; + comp->ContainsComponent = NULL; + comp->GetDatabus = ComponentGetDatabus; comp->GetName = ComponentGetName; comp->GetModel = ComponentGetModel; diff --git a/src/core/Component.h b/src/core/Component.h index 0878259..9d6f1cc 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -48,6 +48,8 @@ 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); @@ -194,6 +196,8 @@ struct Component { fComponentSetModel SetModel; + fComponentContainsComponent ContainsComponent; + fComponentGetDatabus GetDatabus; fComponentGetName GetName; fComponentGetName GetType; From 35259ba6c9aa026eb5470183c373d3f7d605e9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 6 Apr 2022 12:20:08 +0200 Subject: [PATCH 082/295] Submodel utility to properly check container-like components --- src/core/SubModel.c | 22 ++++++++++++++++++++++ src/core/SubModel.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/core/SubModel.c b/src/core/SubModel.c index 8d3b13c..b95df9d 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -395,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 %d", 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; @@ -579,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) { diff --git a/src/core/SubModel.h b/src/core/SubModel.h index 63ffa49..1a962a1 100644 --- a/src/core/SubModel.h +++ b/src/core/SubModel.h @@ -67,6 +67,7 @@ struct SubModel { fSubModelLoopEvaluationList LoopEvaluationList; fSubModelLoopComponents LoopComponents; fSubModelIsElement IsElement; + fSubModelIsElement ContainsOrIsElement; ObjectContainer * evaluationList; // contains CompAndGroup ObjectContainer * components; // contains Component From 072797701bea3765bcf72bdb1001b7a18ba47e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 6 Apr 2022 10:49:12 +0200 Subject: [PATCH 083/295] Make sure ComponentStorage->Finished is called for comp_solver components --- src/storage/ResultsStorage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/ResultsStorage.c b/src/storage/ResultsStorage.c index ecefdc4..2b9858e 100644 --- a/src/storage/ResultsStorage.c +++ b/src/storage/ResultsStorage.c @@ -169,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); } } From e08d0dd1a2e2e611eed4d6bf03dc88a3a4d90367 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 30 Sep 2021 23:41:37 +0200 Subject: [PATCH 084/295] common_fmu2: Add Fmi2TypeToString() function --- src/fmu/common_fmu2.c | 17 +++++++++++++++++ src/fmu/common_fmu2.h | 1 + 2 files changed, 18 insertions(+) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index ffe2488..21c1040 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -61,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; diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h index 23b5291..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; From 08f298a99188d35054f0d02960076fc01a9b39ec Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Fri, 28 Feb 2025 10:49:24 +0100 Subject: [PATCH 085/295] Use %zu for size_t prints --- src/components/comp_constant.c | 2 +- src/core/Databus.c | 8 ++++---- src/core/Model.c | 34 +++++++++++++++++----------------- src/core/SubModel.c | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index 0cdff42..95daef9 100644 --- a/src/components/comp_constant.c +++ b/src/components/comp_constant.c @@ -81,7 +81,7 @@ static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) { } if (i >= numVecOut) { - ComponentLog(comp, LOG_ERROR, "GetValue: Invalid index (%d) provided", idx); + ComponentLog(comp, LOG_ERROR, "GetValue: Invalid index (%zu) provided", idx); return NULL; } diff --git a/src/core/Databus.c b/src/core/Databus.c index cfe4680..74efc5b 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -457,7 +457,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, 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; } @@ -485,7 +485,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, retVal = dbInfos->PushBack(dbInfos, info); if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %zu", i); object_destroy(infos); return RETURN_ERROR; } @@ -493,7 +493,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, 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 add vector info 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; } @@ -501,7 +501,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, 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 %d", i); + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read element specific data of port %zu", i); return RETURN_ERROR; } } diff --git a/src/core/Model.c b/src/core/Model.c index 5364439..3c7246b 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -719,7 +719,7 @@ 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; @@ -760,7 +760,7 @@ McxStatus ReadConnections(Vector * 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; @@ -815,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"); @@ -856,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; } @@ -886,7 +886,7 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para if ((info->mode == CHANNEL_MANDATORY) && !channel->IsValid(channel)) { - mcx_log(LOG_ERROR, "Model: %d. inport (%s) of element %s not connected" + mcx_log(LOG_ERROR, "Model: %zu. inport (%s) of element %s not connected" , i+1, ChannelInfoGetName(info), comp->GetName(comp)); return RETURN_ERROR; } @@ -898,7 +898,7 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para if ((info->mode == CHANNEL_MANDATORY) && !channel->IsValid(channel)) { - mcx_log(LOG_ERROR, "Model: %d. outport (%s) of element %s not connected" + mcx_log(LOG_ERROR, "Model: %zu. outport (%s) of element %s not connected" , i+1, ChannelInfoGetName(info), comp->GetName(comp)); return RETURN_ERROR; } @@ -1415,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, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1433,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, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1457,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); } } } @@ -1499,14 +1499,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\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++) { @@ -1522,7 +1522,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1536,14 +1536,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\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) { @@ -1558,7 +1558,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1566,13 +1566,13 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i 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); } diff --git a/src/core/SubModel.c b/src/core/SubModel.c index b95df9d..87feb06 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -402,7 +402,7 @@ static int SubModelContainsOrIsElement(SubModel * subModel, const Component * co 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 %d", i); + mcx_log(LOG_DEBUG, "Model: nullptr in submodel at idx %zu", i); continue; } From dc0cf49d9858841c58c1cde41ad299e5d3a386ed Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Mon, 18 Oct 2021 18:03:31 +0200 Subject: [PATCH 086/295] signals: Add framework for printing function on signal --- src/util/signals.h | 3 +++ src/util/win/signals.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/util/signals.h b/src/util/signals.h index f468ca7..744aa54 100644 --- a/src/util/signals.h +++ b/src/util/signals.h @@ -23,6 +23,9 @@ void mcx_signal_handler_enable(void); void mcx_signal_handler_set_name(const char * threadName); void mcx_signal_handler_unset_name(void); +void mcx_signal_handler_set_function(const char * functionName); +void mcx_signal_handler_unset_function(void); + /** * Deletes the handler for SIGSEGV */ diff --git a/src/util/win/signals.c b/src/util/win/signals.c index e584175..3a652d1 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -21,6 +21,7 @@ /* Thread local variable to store the name of the element which is * running inside the signal-handled block. */ __declspec( thread ) static const char * _signalThreadName = NULL; +__declspec( thread ) static const char * _signalFunctionName = NULL; #ifdef __cplusplus extern "C" { @@ -28,7 +29,11 @@ extern "C" { static LONG WINAPI HandleException(PEXCEPTION_POINTERS exception) { if (_signalThreadName) { - mcx_log(LOG_ERROR, "The element %s caused an unrecoverable error.", _signalThreadName); + if (_signalFunctionName) { + mcx_log(LOG_ERROR, "The element %s caused an unrecoverable error in %s.", _signalThreadName, _signalFunctionName); + } else { + mcx_log(LOG_ERROR, "The element %s caused an unrecoverable error.", _signalThreadName); + } } else { mcx_log(LOG_ERROR, "An element caused an unrecoverable error."); } @@ -112,6 +117,14 @@ void mcx_signal_handler_unset_name(void) { _signalThreadName = NULL; } +void mcx_signal_handler_set_function(const char * functionName) { + _signalFunctionName = functionName; +} + +void mcx_signal_handler_unset_function(void) { + _signalFunctionName = NULL; +} + void mcx_signal_handler_enable(void) { _signalThreadName = NULL; SetUnhandledExceptionFilter(HandleException); From 3a5774275f5d011b002056cbe04179143e558a4f Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Mon, 18 Oct 2021 18:04:26 +0200 Subject: [PATCH 087/295] signals: Upgrade current function storage to stack --- src/util/win/signals.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/util/win/signals.c b/src/util/win/signals.c index 3a652d1..833d4cf 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -22,6 +22,8 @@ * running inside the signal-handled block. */ __declspec( thread ) static const char * _signalThreadName = NULL; __declspec( thread ) static const char * _signalFunctionName = NULL; +__declspec( thread ) static const char * _signalFunctionNameStack1 = NULL; +__declspec( thread ) static const char * _signalFunctionNameStack2 = NULL; #ifdef __cplusplus extern "C" { @@ -118,11 +120,31 @@ void mcx_signal_handler_unset_name(void) { } void mcx_signal_handler_set_function(const char * functionName) { + if (_signalFunctionNameStack2 != NULL) { + mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); + exit(1); // I guess there is a better way to handle this + } + if (_signalFunctionNameStack1 != NULL) { + _signalFunctionNameStack2 = _signalFunctionNameStack1; + } + if (_signalFunctionName != NULL) { + _signalFunctionNameStack1 = _signalFunctionName; + } _signalFunctionName = functionName; } void mcx_signal_handler_unset_function(void) { - _signalFunctionName = NULL; + if (_signalFunctionName == NULL) { + mcx_log(LOG_WARNING, "Signal handler function callstack empty. Cannot pop non-existing element."); + } + if (_signalFunctionNameStack1 != NULL) { + _signalFunctionName = _signalFunctionNameStack1; + if (_signalFunctionNameStack2 != NULL) { + _signalFunctionNameStack1 = _signalFunctionNameStack2; + } + } else { + _signalFunctionName = NULL; + } } void mcx_signal_handler_enable(void) { From 31a96326623ab835da6b640c32a596f924babf89 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 19 Oct 2021 14:15:09 +0200 Subject: [PATCH 088/295] signals: Add possibility to omit redundant argument --- src/util/signals.h | 8 +++++++- src/util/win/signals.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/util/signals.h b/src/util/signals.h index 744aa54..e7fb6d2 100644 --- a/src/util/signals.h +++ b/src/util/signals.h @@ -23,7 +23,13 @@ void mcx_signal_handler_enable(void); void mcx_signal_handler_set_name(const char * threadName); void mcx_signal_handler_unset_name(void); -void mcx_signal_handler_set_function(const char * functionName); +/** + * Sets and unsets the current functions name for usage in signal handler messages + * + * Note: __func__ is part of C99 standard (ISO/IEC 9899:1999), section 6.4.2.2 + */ +#define mcx_signal_handler_set_function() mcx_signal_handler_set_function_internal(__func__) +void mcx_signal_handler_set_function_internal(const char * functionName); void mcx_signal_handler_unset_function(void); /** diff --git a/src/util/win/signals.c b/src/util/win/signals.c index 833d4cf..0930867 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -119,7 +119,7 @@ void mcx_signal_handler_unset_name(void) { _signalThreadName = NULL; } -void mcx_signal_handler_set_function(const char * functionName) { +void mcx_signal_handler_set_function_internal(const char * functionName) { if (_signalFunctionNameStack2 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this From 2fffc22e2e3cab29abef7ac762b085976ddc1ed0 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 19 Oct 2021 14:16:05 +0200 Subject: [PATCH 089/295] signals: Add get for function name --- src/util/signals.h | 1 + src/util/win/signals.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/util/signals.h b/src/util/signals.h index e7fb6d2..a537be1 100644 --- a/src/util/signals.h +++ b/src/util/signals.h @@ -47,6 +47,7 @@ void mcx_signal_handler_sigint(int param); */ int mcx_signal_handler_is_interrupted(void); +const char * mcx_signal_handler_get_function_name(void); #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/util/win/signals.c b/src/util/win/signals.c index 0930867..52d8757 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -159,6 +159,10 @@ void mcx_signal_handler_disable(void) { _signalThreadName = NULL; } +const char * mcx_signal_handler_get_function_name(void) { + return _signalFunctionName; +} + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file From b6fb3eddaa19c12d20efcd60d8495c37d90d2031 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 19 Oct 2021 14:46:22 +0200 Subject: [PATCH 090/295] signals: Add function name to error message on linux --- src/util/linux/signals.c | 41 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/util/linux/signals.c b/src/util/linux/signals.c index aecd9de..d6735b0 100644 --- a/src/util/linux/signals.c +++ b/src/util/linux/signals.c @@ -18,6 +18,9 @@ /* Thread local variable to store the name of the element which is * running inside the signal-handled block. */ static __thread const char * _signalThreadName = NULL; +static __thread const char * _signalFunctionName = NULL; +static __thread const char * _signalFunctionNameStack1 = NULL; +static __thread const char * _signalFunctionNameStack2 = NULL; #ifdef __cplusplus extern "C" { @@ -25,7 +28,11 @@ extern "C" { static void sigHandlerParam(int param) { if (_signalThreadName) { - mcx_log(LOG_ERROR, "The element %s caused an unrecoverable error. Shutting down.", _signalThreadName); + if (_signalFunctionName) { + mcx_log(LOG_ERROR, "The element %s caused an unrecoverable error in %s. Shutting down.", _signalThreadName, _signalFunctionName); + } else { + mcx_log(LOG_ERROR, "The element %s caused an unrecoverable error. Shutting down.", _signalThreadName); + } } else { mcx_log(LOG_ERROR, "An element caused an unrecoverable error. Shutting down."); } @@ -48,6 +55,34 @@ void mcx_signal_handler_unset_name(void) { _signalThreadName = NULL; } +void mcx_signal_handler_set_function_internal(const char * functionName) { + if (_signalFunctionNameStack2 != NULL) { + mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); + exit(1); // I guess there is a better way to handle this + } + if (_signalFunctionNameStack1 != NULL) { + _signalFunctionNameStack2 = _signalFunctionNameStack1; + } + if (_signalFunctionName != NULL) { + _signalFunctionNameStack1 = _signalFunctionName; + } + _signalFunctionName = functionName; +} + +void mcx_signal_handler_unset_function(void) { + if (_signalFunctionName == NULL) { + mcx_log(LOG_WARNING, "Signal handler function callstack empty. Cannot pop non-existing element."); + } + if (_signalFunctionNameStack1 != NULL) { + _signalFunctionName = _signalFunctionNameStack1; + if (_signalFunctionNameStack2 != NULL) { + _signalFunctionNameStack1 = _signalFunctionNameStack2; + } + } else { + _signalFunctionName = NULL; + } +} + void mcx_signal_handler_enable(void) { static struct sigaction sigHandlerSEGV; @@ -71,6 +106,10 @@ void mcx_signal_handler_disable(void) { _signalThreadName = NULL; } +const char * mcx_signal_handler_get_function_name(void) { + return _signalFunctionName; +} + #ifdef __cplusplus } /* closing brace for extern "C" */ From 195f272409660e17ff0814dbb9af36002543d3cb Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Wed, 27 Oct 2021 15:44:14 +0200 Subject: [PATCH 091/295] signals: Log function on error in component dosteps --- src/components/comp_fmu.c | 3 +++ src/core/Component.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 8dd698c..56ab7b1 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -21,6 +21,7 @@ #include "objects/Map.h" #include "reader/model/components/specific_data/FmuInput.h" #include "util/string.h" +#include "util/signals.h" #ifdef __cplusplus extern "C" { @@ -987,7 +988,9 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double TimeSnapshotEnd(&comp->data->rtData.funcTimings.rtInput); // Do calculations + mcx_signal_handler_set_function("fmi2_import_do_step"); status = fmi2_import_do_step(fmu2->fmiImport, compFmu->lastCommunicationTimePoint, deltaTime, fmi2_true); + mcx_signal_handler_unset_function(); if (fmi2_status_ok == status) { // fine } else if (fmi2_status_discard == status) { diff --git a/src/core/Component.c b/src/core/Component.c index eb05b1c..a533d95 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -503,7 +503,9 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de if (comp->DoStep) { mcx_signal_handler_set_name(comp->GetName(comp)); + mcx_signal_handler_set_this_function(); retVal = comp->DoStep(comp, group, time, deltaTime, endTime, isNewStep); + mcx_signal_handler_unset_function(); mcx_signal_handler_unset_name(); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_DEBUG, "Component specific DoStep failed"); From 0d789f32515eb1750aa98053e10c6d7ed7a3911d Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Wed, 27 Oct 2021 15:47:43 +0200 Subject: [PATCH 092/295] signals: Improve naming of functions --- src/util/linux/signals.c | 2 +- src/util/signals.h | 4 ++-- src/util/win/signals.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/linux/signals.c b/src/util/linux/signals.c index d6735b0..1e84ea0 100644 --- a/src/util/linux/signals.c +++ b/src/util/linux/signals.c @@ -55,7 +55,7 @@ void mcx_signal_handler_unset_name(void) { _signalThreadName = NULL; } -void mcx_signal_handler_set_function_internal(const char * functionName) { +void mcx_signal_handler_set_function(const char * functionName) { if (_signalFunctionNameStack2 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this diff --git a/src/util/signals.h b/src/util/signals.h index a537be1..b1a3ee0 100644 --- a/src/util/signals.h +++ b/src/util/signals.h @@ -28,8 +28,8 @@ void mcx_signal_handler_unset_name(void); * * Note: __func__ is part of C99 standard (ISO/IEC 9899:1999), section 6.4.2.2 */ -#define mcx_signal_handler_set_function() mcx_signal_handler_set_function_internal(__func__) -void mcx_signal_handler_set_function_internal(const char * functionName); +#define mcx_signal_handler_set_this_function() mcx_signal_handler_set_function(__func__) +void mcx_signal_handler_set_function(const char * functionName); void mcx_signal_handler_unset_function(void); /** diff --git a/src/util/win/signals.c b/src/util/win/signals.c index 52d8757..fba8149 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -119,7 +119,7 @@ void mcx_signal_handler_unset_name(void) { _signalThreadName = NULL; } -void mcx_signal_handler_set_function_internal(const char * functionName) { +void mcx_signal_handler_set_function(const char * functionName) { if (_signalFunctionNameStack2 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this From 72d3a5515bcc0b894a0b9856e752069bca1f3987 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Wed, 27 Oct 2021 15:48:31 +0200 Subject: [PATCH 093/295] signals: Make callstack handling faster and more straight forward --- src/util/linux/signals.c | 19 +++++-------------- src/util/win/signals.c | 21 ++++++--------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/src/util/linux/signals.c b/src/util/linux/signals.c index 1e84ea0..a5fa976 100644 --- a/src/util/linux/signals.c +++ b/src/util/linux/signals.c @@ -60,12 +60,8 @@ void mcx_signal_handler_set_function(const char * functionName) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this } - if (_signalFunctionNameStack1 != NULL) { - _signalFunctionNameStack2 = _signalFunctionNameStack1; - } - if (_signalFunctionName != NULL) { - _signalFunctionNameStack1 = _signalFunctionName; - } + _signalFunctionNameStack2 = _signalFunctionNameStack1; + _signalFunctionNameStack1 = _signalFunctionName; _signalFunctionName = functionName; } @@ -73,14 +69,9 @@ void mcx_signal_handler_unset_function(void) { if (_signalFunctionName == NULL) { mcx_log(LOG_WARNING, "Signal handler function callstack empty. Cannot pop non-existing element."); } - if (_signalFunctionNameStack1 != NULL) { - _signalFunctionName = _signalFunctionNameStack1; - if (_signalFunctionNameStack2 != NULL) { - _signalFunctionNameStack1 = _signalFunctionNameStack2; - } - } else { - _signalFunctionName = NULL; - } + _signalFunctionName = _signalFunctionNameStack1; + _signalFunctionNameStack1 = _signalFunctionNameStack2; + _signalFunctionNameStack2 = NULL; } void mcx_signal_handler_enable(void) { diff --git a/src/util/win/signals.c b/src/util/win/signals.c index fba8149..f434af1 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -124,27 +124,18 @@ void mcx_signal_handler_set_function(const char * functionName) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this } - if (_signalFunctionNameStack1 != NULL) { - _signalFunctionNameStack2 = _signalFunctionNameStack1; - } - if (_signalFunctionName != NULL) { - _signalFunctionNameStack1 = _signalFunctionName; - } + _signalFunctionNameStack2 = _signalFunctionNameStack1; + _signalFunctionNameStack1 = _signalFunctionName; _signalFunctionName = functionName; } void mcx_signal_handler_unset_function(void) { if (_signalFunctionName == NULL) { - mcx_log(LOG_WARNING, "Signal handler function callstack empty. Cannot pop non-existing element."); - } - if (_signalFunctionNameStack1 != NULL) { - _signalFunctionName = _signalFunctionNameStack1; - if (_signalFunctionNameStack2 != NULL) { - _signalFunctionNameStack1 = _signalFunctionNameStack2; - } - } else { - _signalFunctionName = NULL; + mcx_log(LOG_WARNING, "Signal handler function callstack in element %s empty. Cannot pop non-existing element.", _signalThreadName); } + _signalFunctionName = _signalFunctionNameStack1; + _signalFunctionNameStack1 = _signalFunctionNameStack2; + _signalFunctionNameStack2 = NULL; } void mcx_signal_handler_enable(void) { From 6633767498def1ed24fdc112580669608c7cdf4c Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Wed, 16 Feb 2022 11:55:24 +0100 Subject: [PATCH 094/295] signals: Check stack integrity only on Debug --- src/util/linux/signals.c | 4 ++++ src/util/win/signals.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/util/linux/signals.c b/src/util/linux/signals.c index a5fa976..aede221 100644 --- a/src/util/linux/signals.c +++ b/src/util/linux/signals.c @@ -56,19 +56,23 @@ void mcx_signal_handler_unset_name(void) { } void mcx_signal_handler_set_function(const char * functionName) { +#if defined(MCX_DEBUG) if (_signalFunctionNameStack2 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this } +#endif _signalFunctionNameStack2 = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionName; _signalFunctionName = functionName; } void mcx_signal_handler_unset_function(void) { +#if defined(MCX_DEBUG) if (_signalFunctionName == NULL) { mcx_log(LOG_WARNING, "Signal handler function callstack empty. Cannot pop non-existing element."); } +#endif _signalFunctionName = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionNameStack2; _signalFunctionNameStack2 = NULL; diff --git a/src/util/win/signals.c b/src/util/win/signals.c index f434af1..f6c83ec 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -120,19 +120,23 @@ void mcx_signal_handler_unset_name(void) { } void mcx_signal_handler_set_function(const char * functionName) { +#if defined(MCX_DEBUG) if (_signalFunctionNameStack2 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this } +#endif _signalFunctionNameStack2 = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionName; _signalFunctionName = functionName; } void mcx_signal_handler_unset_function(void) { +#if defined(MCX_DEBUG) if (_signalFunctionName == NULL) { mcx_log(LOG_WARNING, "Signal handler function callstack in element %s empty. Cannot pop non-existing element.", _signalThreadName); } +#endif _signalFunctionName = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionNameStack2; _signalFunctionNameStack2 = NULL; From 7c867320b696ca57cc9e2dc147736a04914693c7 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 8 Mar 2022 15:05:20 +0100 Subject: [PATCH 095/295] signals: Populate call stack more often --- mcx/mcx.c | 24 ++++++++++++++++++++++++ src/core/Task.c | 6 ++++++ 2 files changed, 30 insertions(+) diff --git a/mcx/mcx.c b/mcx/mcx.c index c5c0f43..fa5749c 100644 --- a/mcx/mcx.c +++ b/mcx/mcx.c @@ -316,14 +316,20 @@ McxStatus RunMCX(int argc, char *argv[]) { goto cleanup; } + mcx_signal_handler_set_function("ConfigSetupFromCmdLine"); retVal = config->SetupFromCmdLine(config, argc, argv); + mcx_signal_handler_unset_function(); if (retVal == RETURN_ERROR) { goto cleanup; } + mcx_signal_handler_set_function("SetupLogFiles"); SetupLogFiles(config->logFile, config->writeAllLogFile); + mcx_signal_handler_unset_function(); logInitialized = 1; + mcx_signal_handler_set_function("ConfigSetupFromEnvironment"); retVal = config->SetupFromEnvironment(config); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { mcx_log(LOG_INFO, "Setting up configuration from environment failed"); retVal = RETURN_ERROR; @@ -337,14 +343,18 @@ McxStatus RunMCX(int argc, char *argv[]) { goto cleanup; } + mcx_signal_handler_set_function("ReaderSetup"); retVal = reader->Setup(reader, config->modelFile, config); + mcx_signal_handler_unset_function(); if (retVal == RETURN_ERROR) { mcx_log(LOG_ERROR, "Input reader setup failed"); retVal = RETURN_ERROR; goto cleanup; } + mcx_signal_handler_set_function("ReaderRead"); mcxInput = reader->Read(reader, config->modelFile); + mcx_signal_handler_unset_function(); if (!mcxInput) { mcx_log(LOG_ERROR, "Parsing of input file failed"); retVal = RETURN_ERROR; @@ -352,7 +362,9 @@ McxStatus RunMCX(int argc, char *argv[]) { } element = (InputElement *) mcxInput; + mcx_signal_handler_set_function("ConfigSetupFromInput"); retVal = config->SetupFromInput(config, mcxInput->config); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Setting up configuration from input file failed"); retVal = RETURN_ERROR; @@ -387,20 +399,26 @@ McxStatus RunMCX(int argc, char *argv[]) { mcx_cpu_time_get(&clock_read_begin); mcx_time_get(&time_read_begin); + mcx_signal_handler_set_function("TaskRead"); retVal = task->Read(task, mcxInput->task); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; } + mcx_signal_handler_set_function("ModelRead"); retVal = model->Read(model, mcxInput->model); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; } object_destroy(mcxInput); + mcx_signal_handler_set_function("ReaderCleanup"); reader->Cleanup(reader); + mcx_signal_handler_unset_function(); object_destroy(reader); mcx_cpu_time_get(&clock_read_end); @@ -421,19 +439,25 @@ McxStatus RunMCX(int argc, char *argv[]) { mcx_cpu_time_get(&clock_setup_begin); mcx_time_get(&time_setup_begin); + mcx_signal_handler_set_function("TaskSetup"); retVal = task->Setup(task, model); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; } + mcx_signal_handler_set_function("ModelSetup"); retVal = model->Setup(model); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; } + mcx_signal_handler_set_function("TaskPrepareRun"); retVal = task->PrepareRun(task, model); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; diff --git a/src/core/Task.c b/src/core/Task.c index 33303dc..b9eb6f8 100644 --- a/src/core/Task.c +++ b/src/core/Task.c @@ -84,19 +84,25 @@ static McxStatus TaskPrepareRun(Task * task, Model * model) { McxStatus retVal = RETURN_OK; #if defined (ENABLE_STORAGE) + mcx_signal_handler_set_function("ResultsStorageSetup"); retVal = task->storage->Setup(task->storage, task->timeStart); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Could not setup storage"); return RETURN_ERROR; } + mcx_signal_handler_set_function("ResultsStorageAddModelComponents"); retVal = task->storage->AddModelComponents(task->storage, model->subModel); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Could not setup component storage"); return RETURN_ERROR; } + mcx_signal_handler_set_function("ResultsStorageSetupBackends"); retVal = task->storage->SetupBackends(task->storage); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Could not setup storage backends"); return RETURN_ERROR; From 2983350ff4840229d178850b5459ddbf2ffd5897 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 15 Mar 2022 15:08:27 +0100 Subject: [PATCH 096/295] signals: Populate call stack on important blocks --- mcx/mcx.c | 4 ++++ src/core/Task.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/mcx/mcx.c b/mcx/mcx.c index fa5749c..4d19356 100644 --- a/mcx/mcx.c +++ b/mcx/mcx.c @@ -481,7 +481,9 @@ McxStatus RunMCX(int argc, char *argv[]) { mcx_cpu_time_get(&clock_init_begin); mcx_time_get(&time_init_begin); + mcx_signal_handler_set_function("TaskInitialize"); retVal = task->Initialize(task, model); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; @@ -505,7 +507,9 @@ McxStatus RunMCX(int argc, char *argv[]) { mcx_log(LOG_INFO, " "); mcx_cpu_time_get(&clock_sim_begin); mcx_time_get(&time_sim_begin); + mcx_signal_handler_set_function("TaskRun"); retVal = task->Run(task, model); + mcx_signal_handler_unset_function(); if (RETURN_OK != retVal) { retVal = RETURN_ERROR; goto cleanup; diff --git a/src/core/Task.c b/src/core/Task.c index b9eb6f8..4882a82 100644 --- a/src/core/Task.c +++ b/src/core/Task.c @@ -160,7 +160,9 @@ static McxStatus TaskRun(Task * task, Model * model) { stepParams->timeEndStep += task->params->timeStepSize; } + mcx_signal_handler_set_function("StepTypeDoStep"); status = task->stepType->DoStep(task->stepType, stepParams, subModel); + mcx_signal_handler_unset_function(); if (status != RETURN_OK) { break; } From 9ccabe880abf043a48ad61c2360b99499eba15f9 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Fri, 18 Mar 2022 10:56:49 +0100 Subject: [PATCH 097/295] signals: Populate call stack around cleanup --- mcx/mcx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mcx/mcx.c b/mcx/mcx.c index 4d19356..c180997 100644 --- a/mcx/mcx.c +++ b/mcx/mcx.c @@ -540,6 +540,7 @@ McxStatus RunMCX(int argc, char *argv[]) { mcx_cpu_time_get(&clock_cleanup_begin); mcx_time_get(&time_cleanup_begin); + mcx_signal_handler_set_function("RunMCX:Cleanup"); object_destroy(task); object_destroy(model); object_destroy(config); @@ -582,6 +583,7 @@ McxStatus RunMCX(int argc, char *argv[]) { mcx_log(LOG_INFO, "**********************************************************************"); } + mcx_signal_handler_unset_function(); // RunMCX:Cleanup return retVal; } From 57483aa91f69b99150d97d8228043561aa599e48 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 22 Mar 2022 13:20:52 +0100 Subject: [PATCH 098/295] signals: Populate call stack on fmu calls --- src/components/comp_fmu.c | 20 ++++++++++++++++++++ src/fmu/common_fmu2.c | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 56ab7b1..8496501 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -230,10 +230,12 @@ static McxStatus Fmu1Initialize(Component * comp, size_t group, double startTime // Initialization Mode ComponentLog(comp, LOG_DEBUG, "fmiInitializeSlave"); + mcx_signal_handler_set_function("fmi1_import_initialize_slave"); status = fmi1_import_initialize_slave(fmu1->fmiImport, startTime, fmi1_false, 0.0); + mcx_signal_handler_unset_function(); if (fmi1_status_ok != status) { ComponentLog(comp, LOG_ERROR, "fmiInitializeSlave failed"); return RETURN_ERROR; @@ -289,7 +291,9 @@ static McxStatus Fmu1DoStep(Component * comp, size_t group, double time, double } // Do calculations + mcx_signal_handler_set_function("fmi1_import_do_step"); status = fmi1_import_do_step(fmu1->fmiImport, compFmu->lastCommunicationTimePoint, deltaTime, fmi1_true); + mcx_signal_handler_unset_function(); if (fmi1_status_ok == status) { // fine } else if (fmi1_status_discard == status) { @@ -906,12 +910,14 @@ static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime defaultTolerance = fmi2_import_get_default_experiment_tolerance(fmu2->fmiImport); compFmu->lastCommunicationTimePoint = startTime; + mcx_signal_handler_set_function("fmi2_import_setup_experiment"); status = fmi2_import_setup_experiment(fmu2->fmiImport, fmi2_false, /* toleranceDefine */ defaultTolerance, startTime, /* startTime */ fmi2_false, /* stopTimeDefined */ 0.0 /* stopTime */); + mcx_signal_handler_unset_function(); if (fmi2_status_ok != status) { ComponentLog(comp, LOG_ERROR, "SetupExperiment failed"); @@ -919,7 +925,9 @@ static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime } // Initialization Mode + mcx_signal_handler_set_function("fmi2_import_enter_initialization_mode"); status = fmi2_import_enter_initialization_mode(fmu2->fmiImport); + mcx_signal_handler_unset_function(); if (fmi2_status_ok != status) { ComponentLog(comp, LOG_ERROR, "Could not enter Initialization Mode"); return RETURN_ERROR; @@ -962,7 +970,9 @@ static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime static McxStatus Fmu2ExitInitializationMode(Component *comp) { CompFMU *compFmu = (CompFMU*)comp; + mcx_signal_handler_set_function("fmi2_import_exit_initialization_mode"); fmi2_status_t status = fmi2_import_exit_initialization_mode(compFmu->fmu2.fmiImport); + mcx_signal_handler_unset_function(); if (fmi2_status_ok != status) { ComponentLog(comp, LOG_ERROR, "Could not exit Initialization Mode"); return RETURN_ERROR; @@ -997,7 +1007,9 @@ static McxStatus Fmu2DoStep(Component * comp, size_t group, double time, double fmi2_status_t fmi2status; fmi2_boolean_t isTerminated = fmi2_false; + mcx_signal_handler_set_function("fmi2_import_get_boolean_status"); fmi2status = fmi2_import_get_boolean_status(fmu2->fmiImport, fmi2_terminated, &isTerminated); + mcx_signal_handler_unset_function(); if (fmi2_status_ok == fmi2status) { if (fmi2_true == isTerminated) { comp->SetIsFinished(comp); @@ -1333,21 +1345,29 @@ static void CompFMUDestructor(CompFMU * compFmu) { // TOOD: Move this to the common struct destructors if (fmu1->fmiImport) { if (fmi1_true == fmu1->runOk) { + mcx_signal_handler_set_function("fmi1_import_terminate_slave"); fmi1_import_terminate_slave(fmu1->fmiImport); + mcx_signal_handler_unset_function(); } if (fmi1_true == fmu1->instantiateOk) { + mcx_signal_handler_set_function("fmi1_import_free_slave_instance"); fmi1_import_free_slave_instance(fmu1->fmiImport); + mcx_signal_handler_unset_function(); } } if (fmu2->fmiImport) { if (fmi2_true == fmu2->runOk) { + mcx_signal_handler_set_function("fmi2_import_terminate"); fmi2_import_terminate(fmu2->fmiImport); + mcx_signal_handler_unset_function(); } if (fmi2_true == fmu2->instantiateOk) { + mcx_signal_handler_set_function("fmi2_import_free_instance"); fmi2_import_free_instance(fmu2->fmiImport); + mcx_signal_handler_unset_function(); } } diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 21c1040..27c75b2 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -21,6 +21,7 @@ #include "util/string.h" #include "util/stdlib.h" +#include "util/signals.h" #include "fmilib.h" @@ -191,11 +192,13 @@ McxStatus Fmu2CommonStructSetup(FmuCommon * common, Fmu2CommonStruct * fmu2, fmi } mcx_log(LOG_DEBUG, "%s: instantiatefn: %x", common->instanceName, fmi2_import_instantiate); + mcx_signal_handler_set_function("fmi2_import_instantiate"), jmStatus = fmi2_import_instantiate(fmu2->fmiImport, common->instanceName, fmu_type, NULL, fmi2_false /* visible */); + mcx_signal_handler_unset_function(); if (jm_status_error == jmStatus) { mcx_log(LOG_ERROR, "%s: Instantiate failed", common->instanceName); return RETURN_ERROR; @@ -634,7 +637,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = {fmuVal->data->vr.scalar}; + mcx_signal_handler_set_function("fmi2_import_set_real"); status = fmi2_import_set_real(fmu->fmiImport, vr, 1, (const fmi2_real_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); MCX_DEBUG_LOG("Set %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueReference(chVal)); @@ -644,7 +649,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; + mcx_signal_handler_set_function("fmi2_import_set_integer"); status = fmi2_import_set_integer(fmu->fmiImport, vr, 1, (const fmi2_integer_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); MCX_DEBUG_LOG("Set %s(%d)=%d", fmuVal->name, vr[0], *(int*)ChannelValueReference(chVal)); @@ -654,7 +661,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; + mcx_signal_handler_set_function("fmi2_import_set_boolean"); status = fmi2_import_set_boolean(fmu->fmiImport, vr, 1, (const fmi2_boolean_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); break; } @@ -662,7 +671,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; + mcx_signal_handler_set_function("fmi2_import_set_string"); status = fmi2_import_set_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); break; } @@ -681,7 +692,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { , (fmi2_integer_t) binary->len }; + mcx_signal_handler_set_function("fmi2_import_set_integer"); status = fmi2_import_set_integer(fmu->fmiImport, vrs, 3, vals); + mcx_signal_handler_unset_function(); break; } @@ -738,7 +751,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; + mcx_signal_handler_set_function("fmi2_import_get_real"); status = fmi2_import_get_real(fmu->fmiImport, vr, 1, (fmi2_real_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); MCX_DEBUG_LOG("Get %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueReference(chVal)); @@ -748,7 +763,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; + mcx_signal_handler_set_function("fmi2_import_get_integer"); status = fmi2_import_get_integer(fmu->fmiImport, vr, 1, (fmi2_integer_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); break; } @@ -756,7 +773,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; + mcx_signal_handler_set_function("fmi2_import_get_boolean"); status = fmi2_import_get_boolean(fmu->fmiImport, vr, 1, (fmi2_boolean_t *) ChannelValueReference(chVal)); + mcx_signal_handler_unset_function(); break; } @@ -766,7 +785,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { char * buffer = NULL; + mcx_signal_handler_set_function("fmi2_import_get_string"); status = fmi2_import_get_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) &buffer); + mcx_signal_handler_unset_function(); ChannelValueSetFromReference(chVal, &buffer); break; @@ -783,7 +804,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { binary_string binary; + mcx_signal_handler_set_function("fmi2_import_get_integer"); status = fmi2_import_get_integer(fmu->fmiImport, vrs, 3, vs); + mcx_signal_handler_unset_function(); binary.len = vs[2]; binary.data = (char *) ((((long long)vs[1] & 0xffffffff) << 32) | (vs[0] & 0xffffffff)); From 229dd4d2bfa75b2b88c7cbdbfcd5009589914a02 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Thu, 24 Mar 2022 11:24:19 +0100 Subject: [PATCH 099/295] signals: Increase call stack size 3->5 --- src/util/linux/signals.c | 10 ++++++++-- src/util/win/signals.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/util/linux/signals.c b/src/util/linux/signals.c index aede221..101e510 100644 --- a/src/util/linux/signals.c +++ b/src/util/linux/signals.c @@ -21,6 +21,8 @@ static __thread const char * _signalThreadName = NULL; static __thread const char * _signalFunctionName = NULL; static __thread const char * _signalFunctionNameStack1 = NULL; static __thread const char * _signalFunctionNameStack2 = NULL; +static __thread const char * _signalFunctionNameStack3 = NULL; +static __thread const char * _signalFunctionNameStack4 = NULL; #ifdef __cplusplus extern "C" { @@ -57,11 +59,13 @@ void mcx_signal_handler_unset_name(void) { void mcx_signal_handler_set_function(const char * functionName) { #if defined(MCX_DEBUG) - if (_signalFunctionNameStack2 != NULL) { + if (_signalFunctionNameStack4 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this } #endif + _signalFunctionNameStack4 = _signalFunctionNameStack3; + _signalFunctionNameStack3 = _signalFunctionNameStack2; _signalFunctionNameStack2 = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionName; _signalFunctionName = functionName; @@ -75,7 +79,9 @@ void mcx_signal_handler_unset_function(void) { #endif _signalFunctionName = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionNameStack2; - _signalFunctionNameStack2 = NULL; + _signalFunctionNameStack2 = _signalFunctionNameStack3; + _signalFunctionNameStack3 = _signalFunctionNameStack4; + _signalFunctionNameStack4 = NULL; } void mcx_signal_handler_enable(void) { diff --git a/src/util/win/signals.c b/src/util/win/signals.c index f6c83ec..156b3b5 100644 --- a/src/util/win/signals.c +++ b/src/util/win/signals.c @@ -24,6 +24,8 @@ __declspec( thread ) static const char * _signalThreadName = NULL; __declspec( thread ) static const char * _signalFunctionName = NULL; __declspec( thread ) static const char * _signalFunctionNameStack1 = NULL; __declspec( thread ) static const char * _signalFunctionNameStack2 = NULL; +__declspec( thread ) static const char * _signalFunctionNameStack3 = NULL; +__declspec( thread ) static const char * _signalFunctionNameStack4 = NULL; #ifdef __cplusplus extern "C" { @@ -121,11 +123,13 @@ void mcx_signal_handler_unset_name(void) { void mcx_signal_handler_set_function(const char * functionName) { #if defined(MCX_DEBUG) - if (_signalFunctionNameStack2 != NULL) { + if (_signalFunctionNameStack4 != NULL) { mcx_log(LOG_ERROR, "Signal handler function callstack overflow!"); exit(1); // I guess there is a better way to handle this } #endif + _signalFunctionNameStack4 = _signalFunctionNameStack3; + _signalFunctionNameStack3 = _signalFunctionNameStack2; _signalFunctionNameStack2 = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionName; _signalFunctionName = functionName; @@ -139,7 +143,9 @@ void mcx_signal_handler_unset_function(void) { #endif _signalFunctionName = _signalFunctionNameStack1; _signalFunctionNameStack1 = _signalFunctionNameStack2; - _signalFunctionNameStack2 = NULL; + _signalFunctionNameStack2 = _signalFunctionNameStack3; + _signalFunctionNameStack3 = _signalFunctionNameStack4; + _signalFunctionNameStack4 = NULL; } void mcx_signal_handler_enable(void) { From 73dbc2167575039c024746c1a65c9255caa7d1e7 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 7 Apr 2022 22:23:27 +0200 Subject: [PATCH 100/295] signals: Remove individual fmu set/get calls --- src/fmu/common_fmu2.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 27c75b2..dd20a66 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -637,9 +637,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = {fmuVal->data->vr.scalar}; - mcx_signal_handler_set_function("fmi2_import_set_real"); status = fmi2_import_set_real(fmu->fmiImport, vr, 1, (const fmi2_real_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); MCX_DEBUG_LOG("Set %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueReference(chVal)); @@ -649,9 +647,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - mcx_signal_handler_set_function("fmi2_import_set_integer"); status = fmi2_import_set_integer(fmu->fmiImport, vr, 1, (const fmi2_integer_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); MCX_DEBUG_LOG("Set %s(%d)=%d", fmuVal->name, vr[0], *(int*)ChannelValueReference(chVal)); @@ -661,9 +657,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - mcx_signal_handler_set_function("fmi2_import_set_boolean"); status = fmi2_import_set_boolean(fmu->fmiImport, vr, 1, (const fmi2_boolean_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); break; } @@ -671,9 +665,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - mcx_signal_handler_set_function("fmi2_import_set_string"); status = fmi2_import_set_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); break; } @@ -692,9 +684,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { , (fmi2_integer_t) binary->len }; - mcx_signal_handler_set_function("fmi2_import_set_integer"); status = fmi2_import_set_integer(fmu->fmiImport, vrs, 3, vals); - mcx_signal_handler_unset_function(); break; } @@ -751,9 +741,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - mcx_signal_handler_set_function("fmi2_import_get_real"); status = fmi2_import_get_real(fmu->fmiImport, vr, 1, (fmi2_real_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); MCX_DEBUG_LOG("Get %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueReference(chVal)); @@ -763,9 +751,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - mcx_signal_handler_set_function("fmi2_import_get_integer"); status = fmi2_import_get_integer(fmu->fmiImport, vr, 1, (fmi2_integer_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); break; } @@ -773,9 +759,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - mcx_signal_handler_set_function("fmi2_import_get_boolean"); status = fmi2_import_get_boolean(fmu->fmiImport, vr, 1, (fmi2_boolean_t *) ChannelValueReference(chVal)); - mcx_signal_handler_unset_function(); break; } @@ -785,9 +769,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { char * buffer = NULL; - mcx_signal_handler_set_function("fmi2_import_get_string"); status = fmi2_import_get_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) &buffer); - mcx_signal_handler_unset_function(); ChannelValueSetFromReference(chVal, &buffer); break; @@ -804,12 +786,10 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { binary_string binary; - mcx_signal_handler_set_function("fmi2_import_get_integer"); status = fmi2_import_get_integer(fmu->fmiImport, vrs, 3, vs); - mcx_signal_handler_unset_function(); - binary.len = vs[2]; - binary.data = (char *) ((((long long)vs[1] & 0xffffffff) << 32) | (vs[0] & 0xffffffff)); + binary.len = vs[2]; + binary.data = (char *) ((((long long)vs[1] & 0xffffffff) << 32) | (vs[0] & 0xffffffff)); ChannelValueSetFromReference(chVal, &binary); From 98c143101b6ed4575b93f8ad0c3688efe7de24e4 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Thu, 7 Apr 2022 22:28:18 +0200 Subject: [PATCH 101/295] signals: Add fmi batch functions --- src/fmu/common_fmu1.c | 11 +++++++++++ src/fmu/common_fmu2.c | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index 446599d..dc72d00 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -15,6 +15,7 @@ #include "reader/model/parameters/ParameterInput.h" #include "util/string.h" +#include "util/signals.h" #include "fmilib.h" @@ -601,14 +602,19 @@ McxStatus Fmu1SetVariableArray(Fmu1CommonStruct * fmu, ObjectContainer * vals) { size_t i = 0; size_t numVars = vals->Size(vals); + mcx_signal_handler_set_this_function(); + for (i = 0; i < numVars; i++) { Fmu1Value * fmuVal = (Fmu1Value *) vals->At(vals, i); if (RETURN_ERROR == Fmu1SetVariable(fmu, fmuVal)) { + mcx_signal_handler_unset_function(); return RETURN_ERROR; } } + mcx_signal_handler_unset_function(); + return RETURN_OK; } @@ -672,15 +678,20 @@ McxStatus Fmu1GetVariableArray(Fmu1CommonStruct * fmu, ObjectContainer * vals) { size_t i = 0; size_t numVars = vals->Size(vals); + mcx_signal_handler_set_this_function(); + for (i = 0; i < numVars; i++) { McxStatus retVal = RETURN_OK; Fmu1Value * fmuVal = (Fmu1Value *) vals->At(vals, i); retVal = Fmu1GetVariable(fmu, fmuVal); if (RETURN_ERROR == retVal) { + mcx_signal_handler_unset_function(); return RETURN_ERROR; } } + mcx_signal_handler_unset_function(); + return RETURN_OK; } diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index dd20a66..2aaf9d7 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -716,15 +716,20 @@ McxStatus Fmu2SetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals) { McxStatus retVal = RETURN_OK; + mcx_signal_handler_set_this_function(); + for (i = 0; i < numVars; i++) { Fmu2Value * const fmuVal = (Fmu2Value *) vals->At(vals, i); retVal = Fmu2SetVariable(fmu, fmuVal); if (RETURN_ERROR == retVal) { + mcx_signal_handler_unset_function(); return RETURN_ERROR; } } + mcx_signal_handler_unset_function(); + return RETURN_OK; } @@ -823,16 +828,21 @@ McxStatus Fmu2GetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals) { McxStatus retVal = RETURN_OK; + mcx_signal_handler_set_this_function(); + for (i = 0; i < numVars; i++) { Fmu2Value * const fmuVal = (Fmu2Value *) vals->At(vals, i); retVal = Fmu2GetVariable(fmu, fmuVal); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "FMU: Getting of variable array failed at element %u", i); + mcx_signal_handler_unset_function(); return RETURN_ERROR; } } + mcx_signal_handler_unset_function(); + return RETURN_OK; } From 631acec7ac7e6cd3934d3d6aa0063dc939b30f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 15 Mar 2022 11:04:49 +0100 Subject: [PATCH 102/295] Set channel reference for outputs as well --- src/components/comp_fmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 8496501..56ef4d2 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -435,6 +435,8 @@ static McxStatus Fmu2SetupChannelOut(ObjectContainer /* Fmu2Values */ * vals, Da channelName = ChannelInfoGetName(info); } + val->SetChannel(val, info->channel); + if (val->val.type != info->type) { ChannelValueInit(&val->val, info->type); } From 493d8f6b5c2dd855276677abb7139c9480b2a178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 15 Mar 2022 11:09:02 +0100 Subject: [PATCH 103/295] Define info object for storing variable data from the model description --- src/fmu/Fmu2Value.c | 105 ++++++++++++++++++++++++++++++++++++++++++++ src/fmu/Fmu2Value.h | 16 +++++++ 2 files changed, 121 insertions(+) diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 68b2779..aa15aaf 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -34,6 +34,106 @@ static Fmu2ValueData * Fmu2ValueDataCreate(Fmu2ValueData * data) { OBJECT_CLASS(Fmu2ValueData, Object); +Fmu2VariableInfo * Fmu2VariableInfoMake(fmi2_import_variable_t * var) { + Fmu2VariableInfo * info = (Fmu2VariableInfo *)object_create(Fmu2VariableInfo); + + if (info) { + fmi2_base_type_enu_t type = fmi2_import_get_variable_base_type(var); + ChannelValueData min = { 0 }; + int minDefined = FALSE; + ChannelValueData max = { 0 }; + int maxDefined = FALSE; + + char * xmlDesc = fmi2_import_get_variable_description(var); + info->desc = mcx_string_copy(xmlDesc); + if (xmlDesc && !info->desc) { + goto cleanup; + } + + switch (type) { + case fmi2_base_type_real: + info->type = CHANNEL_DOUBLE; + min.d = fmi2_import_get_real_variable_min(fmi2_import_get_variable_as_real(var)); + minDefined = min.d != -DBL_MAX; + max.d = fmi2_import_get_real_variable_max(fmi2_import_get_variable_as_real(var)); + maxDefined = max.d != DBL_MAX; + break; + case fmi2_base_type_int: + info->type = CHANNEL_INTEGER; + min.i = fmi2_import_get_integer_variable_min(fmi2_import_get_variable_as_integer(var)); + minDefined = min.i != -INT_MIN; + max.i = fmi2_import_get_integer_variable_max(fmi2_import_get_variable_as_integer(var)); + maxDefined = max.i != INT_MAX; + break; + case fmi2_base_type_enum: + info->type = CHANNEL_INTEGER; + min.i = fmi2_import_get_enum_variable_min(fmi2_import_get_variable_as_enum(var)); + minDefined = min.i != -INT_MIN; + max.i = fmi2_import_get_enum_variable_max(fmi2_import_get_variable_as_enum(var)); + maxDefined = max.i != INT_MAX; + break; + case fmi2_base_type_str: + info->type = CHANNEL_STRING; + break; + case fmi2_base_type_bool: + info->type = CHANNEL_BOOL; + break; + default: + info->type = CHANNEL_UNKNOWN; + break; + } + + if (minDefined) { + info->min = (ChannelValueData *)mcx_calloc(1, sizeof(ChannelValueData)); + if (!info->min) { + goto cleanup; + } + ChannelValueDataSetFromReference(info->min, info->type, &min); + } + + if (maxDefined) { + info->max = (ChannelValueData*)mcx_calloc(1, sizeof(ChannelValueData)); + if (!info->max) { + goto cleanup; + } + ChannelValueDataSetFromReference(info->max, info->type, &max); + } + } + + return info; + +cleanup: + object_destroy(info); + return NULL; +} + +static void Fmu2VariableInfoDestructor(Fmu2VariableInfo * info) { + if (info->min) { + ChannelValueDataDestructor(info->min, info->type); + mcx_free(info->min); + } + if (info->max) { + ChannelValueDataDestructor(info->max, info->type); + mcx_free(info->max); + } + + if (info->desc) { mcx_free(info->desc); } +} + +static Fmu2VariableInfo * Fmu2VariableInfoCreate(Fmu2VariableInfo * info) { + info->type = CHANNEL_UNKNOWN; + + info->min = NULL; + info->max = NULL; + + info->desc = NULL; + + return info; +} + +OBJECT_CLASS(Fmu2VariableInfo, Object); + + Fmu2ValueData * Fmu2ValueDataScalarMake(fmi2_import_variable_t * scalar) { Fmu2ValueData * data = (Fmu2ValueData *) object_create(Fmu2ValueData); @@ -136,6 +236,7 @@ static void Fmu2ValueDestructor(Fmu2Value * v) { v->unit = NULL; } object_destroy(v->data); + object_destroy(v->info); ChannelValueDestructor(&v->val); } @@ -148,6 +249,8 @@ static Fmu2Value * Fmu2ValueCreate(Fmu2Value * v) { v->unit = NULL; v->data = NULL; v->channel = NULL; + v->info = NULL; + ChannelValueInit(&v->val, CHANNEL_UNKNOWN); return v; @@ -174,6 +277,8 @@ Fmu2Value * Fmu2ValueScalarMake(const char * name, fmi2_import_variable_t * scal Fmu2ValueData * data = Fmu2ValueDataScalarMake(scalar); Fmu2Value * value = Fmu2ValueMake(name, data, unit, channel); + value->info = Fmu2VariableInfoMake(scalar); + return value; } diff --git a/src/fmu/Fmu2Value.h b/src/fmu/Fmu2Value.h index 7664554..004b277 100644 --- a/src/fmu/Fmu2Value.h +++ b/src/fmu/Fmu2Value.h @@ -56,6 +56,21 @@ struct Fmu2ValueData { Fmu2ValueData * Fmu2ValueDataScalarMake(fmi2_import_variable_t * scalar); Fmu2ValueData * Fmu2ValueDataBinaryMake(fmi2_import_variable_t * hi, fmi2_import_variable_t * lo, fmi2_import_variable_t * size); + +extern const struct ObjectClass _Fmu2VariableInfo; + +typedef struct Fmu2VariableInfo { + Object _; + + ChannelType type; + + ChannelValueData * min; + ChannelValueData * max; + + char * desc; +} Fmu2VariableInfo; + + struct Fmu2Value; typedef struct Fmu2Value Fmu2Value; @@ -78,6 +93,7 @@ struct Fmu2Value { Channel * channel; Fmu2ValueData * data; + Fmu2VariableInfo * info; ChannelValue val; }; From 056e751207a1cd67d7dae07919ae1eb618ea004c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 8 Apr 2022 14:38:51 +0200 Subject: [PATCH 104/295] Construct proxies to array parameters during read --- src/components/comp_fmu.c | 27 +++----- src/fmu/common_fmu2.c | 136 +++++++++++++++++++++++++------------- src/fmu/common_fmu2.h | 4 +- 3 files changed, 101 insertions(+), 66 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 56ef4d2..f58fc66 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -804,20 +804,17 @@ static McxStatus Fmu2Read(Component * comp, ComponentInput * input, const struct ParametersInput * parametersInput = input->parameters; if (parametersInput) { - vals = Fmu2ReadParams(parametersInput, - compFmu->fmu2.fmiImport, - NULL + retVal = Fmu2ReadParams( + fmu2->params, + fmu2->arrayParams, + parametersInput, + compFmu->fmu2.fmiImport, + NULL ); - if (!vals) { - ComponentLog(comp, LOG_ERROR, "Could not read parameters"); - return RETURN_ERROR; - } - retVal = fmu2->params->Append(fmu2->params, vals); if (RETURN_OK != retVal) { - ComponentLog(comp, LOG_ERROR, "Could not add parameters"); + ComponentLog(comp, LOG_ERROR, "Could not read parameters"); return RETURN_ERROR; } - object_destroy(vals); } } @@ -826,17 +823,11 @@ static McxStatus Fmu2Read(Component * comp, ComponentInput * input, const struct ParametersInput * parametersInput = input->initialValues; if (parametersInput) { - vals = Fmu2ReadParams(parametersInput, compFmu->fmu2.fmiImport, NULL); - if (!vals) { - ComponentLog(comp, LOG_ERROR, "Could not read initial values"); - return RETURN_ERROR; - } - retVal = fmu2->initialValues->Append(fmu2->initialValues, vals); + retVal = Fmu2ReadParams(fmu2->initialValues, NULL, parametersInput, compFmu->fmu2.fmiImport, NULL); if (RETURN_OK != retVal) { - ComponentLog(comp, LOG_ERROR, "Could not add initial values"); + ComponentLog(comp, LOG_ERROR, "Could not read initial values"); return RETURN_ERROR; } - object_destroy(vals); } } diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 2aaf9d7..181294e 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -93,6 +93,8 @@ McxStatus Fmu2CommonStructInit(Fmu2CommonStruct * fmu) { fmu->tunableParams = (ObjectContainer *) object_create(ObjectContainer); fmu->initialValues = (ObjectContainer *) object_create(ObjectContainer); + fmu->arrayParams = (ObjectContainer *) object_create(ObjectContainer); + fmu->connectedIn = (ObjectContainer *) object_create(ObjectContainer); fmu->numLogCategories = 0; @@ -243,6 +245,11 @@ void Fmu2CommonStructDestructor(Fmu2CommonStruct * fmu) { object_destroy(fmu->params); } + if (fmu->arrayParams) { + fmu->arrayParams->DestroyObjects(fmu->arrayParams); + object_destroy(fmu->arrayParams); + } + if (fmu->initialValues) { fmu->initialValues->DestroyObjects(fmu->initialValues); object_destroy(fmu->initialValues); @@ -451,98 +458,141 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, } // Reads parameters from the input file (both scalar and array). -// +// If arrayParams is given, creates proxy views to array elements. // Ignores parameters provided via the `ignore` argument. -ObjectContainer * Fmu2ReadParams(ParametersInput * input, fmi2_import_t * import, ObjectContainer * ignore) { - ObjectContainer * params = (ObjectContainer *) object_create(ObjectContainer); - ObjectContainer * ret = params; // used for unified cleanup via goto +McxStatus Fmu2ReadParams(ObjectContainer * params, ObjectContainer * arrayParams, ParametersInput * input, fmi2_import_t * import, ObjectContainer * ignore) { + McxStatus retVal = RETURN_OK; size_t i = 0; size_t num = 0; - McxStatus retVal = RETURN_OK; if (!params) { - return NULL; + return RETURN_ERROR; } num = input->parameters->Size(input->parameters); for (i = 0; i < num; i++) { ParameterInput * parameterInput = (ParameterInput *) input->parameters->At(input->parameters, i); - char * name = NULL; - Fmu2Value * val = NULL; - ObjectContainer * vals = NULL; - name = mcx_string_copy(parameterInput->parameter.arrayParameter->name); if (!name) { - ret = NULL; - goto fmu2_read_params_for_cleanup; + retVal = RETURN_ERROR; + goto cleanup_0; } // ignore the parameter if it is in the `ignore` container if (ignore && ignore->GetNameIndex(ignore, name) >= 0) { - goto fmu2_read_params_for_cleanup; + goto cleanup_0; } if (parameterInput->type == PARAMETER_ARRAY) { + ObjectContainer * vals = NULL; + ArrayParameterProxy * proxy = NULL; + size_t j = 0; + // read parameter dimensions (if any) - should only be defined for array parameters if (parameterInput->parameter.arrayParameter->numDims >=2 && parameterInput->parameter.arrayParameter->dims[1] && !parameterInput->parameter.arrayParameter->dims[0]) { mcx_log(LOG_ERROR, "FMU: Array parameter %s: Missing definition for the first dimension " "while the second dimension is defined.", parameterInput->parameter.arrayParameter->name); - ret = NULL; - goto fmu2_read_params_for_cleanup; + retVal = RETURN_ERROR; + goto cleanup_1; } // array - split it into scalars vals = Fmu2ReadArrayParamValues(name, parameterInput->parameter.arrayParameter, import, params); if (vals == NULL) { mcx_log(LOG_ERROR, "FMU: Could not read array parameter %s", name); - ret = NULL; - goto fmu2_read_params_for_cleanup; + retVal = RETURN_ERROR; + goto cleanup_1; + } + + if (arrayParams) { + // set up a proxy that will reference the individual scalars + proxy = (ArrayParameterProxy *) object_create(ArrayParameterProxy); + if (!proxy) { + mcx_log(LOG_ERROR, "FMU: Creating an array proxy failed: No memory"); + retVal = RETURN_ERROR; + goto cleanup_1; + } + + retVal = proxy->Setup(proxy, name, parameterInput->parameter.arrayParameter->numDims, parameterInput->parameter.arrayParameter->dims); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "FMU Array parameter %s: Array proxy setup failed", name); + goto cleanup_1; + } } // store the scalar values - size_t j = 0; for (j = 0; j < vals->Size(vals); j++) { - Object * v = vals->At(vals, j); - retVal = params->PushBackNamed(params, v, ((Fmu2Value*)v)->name); + Fmu2Value * v = (Fmu2Value *) vals->At(vals, j); + retVal = params->PushBackNamed(params, (Object *) v, v->name); if (RETURN_OK != retVal) { - ret = NULL; - goto fmu2_read_params_for_cleanup; + mcx_log(LOG_ERROR, "FMU: Adding element #%zu of parameter %s failed", j, name); + goto cleanup_1; + } + + vals->SetAt(vals, j, NULL); + + if (arrayParams) { + retVal = proxy->AddValue(proxy, v); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "FMU: Adding proxy to element #%zu of parameter %s failed", j, name); + goto cleanup_1; + } + } + } + + if (arrayParams) { + retVal = arrayParams->PushBackNamed(arrayParams, (Object *) proxy, proxy->GetName(proxy)); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "FMU: Adding proxy for %s failed", name); + goto cleanup_1; + } + } + +cleanup_1: + if (RETURN_ERROR == retVal) { + object_destroy(proxy); + if (vals) { + vals->DestroyObjects(vals); } } object_destroy(vals); + + if (RETURN_ERROR == retVal) { + goto cleanup_0; + } } else { + Fmu2Value * val = NULL; + // read the scalar value val = Fmu2ReadParamValue(parameterInput->parameter.scalarParameter, import); if (val == NULL) { mcx_log(LOG_ERROR, "FMU: Could not read parameter value of parameter %s", name); - ret = NULL; - goto fmu2_read_params_for_cleanup; + retVal = RETURN_ERROR; + goto cleanup_2; } // store the read value retVal = params->PushBackNamed(params, (Object * ) val, name); if (RETURN_OK != retVal) { - ret = NULL; - goto fmu2_read_params_for_cleanup; + goto cleanup_2; } - } -fmu2_read_params_for_cleanup: - if (name) { mcx_free(name); } - if (ret == NULL) { - if (val) { object_destroy(val); } - if (vals) { - vals->DestroyObjects(vals); - object_destroy(vals); +cleanup_2: + if (RETURN_ERROR == retVal) { + object_destroy(val); } + } - goto cleanup; +cleanup_0: + if (name) { mcx_free(name); } + if (retVal == RETURN_ERROR) { + return RETURN_ERROR; } } @@ -555,30 +605,22 @@ ObjectContainer * Fmu2ReadParams(ParametersInput * input, fmi2_import_t * import status = params->Sort(params, NaturalComp, NULL); if (RETURN_OK != status) { mcx_log(LOG_ERROR, "FMU: Unable to sort parameters"); - ret = NULL; - goto cleanup; + return RETURN_ERROR; } for (i = 0; i < n - 1; i++) { Fmu2Value * a = (Fmu2Value *) params->At(params, i); Fmu2Value * b = (Fmu2Value *) params->At(params, i + 1); - if (! strcmp(a->name, b->name)) { + if (!strcmp(a->name, b->name)) { mcx_log(LOG_ERROR, "FMU: Duplicate definition of parameter %s", a->name); - ret = NULL; - goto cleanup; + return RETURN_ERROR; } } } } -cleanup: - if (ret == NULL) { - params->DestroyObjects(params); - object_destroy(params); - } - - return ret; + return retVal; } diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h index 0f61179..024d2ee 100644 --- a/src/fmu/common_fmu2.h +++ b/src/fmu/common_fmu2.h @@ -30,7 +30,7 @@ struct Fmu2CommonStruct; typedef struct Fmu2CommonStruct Fmu2CommonStruct; -ObjectContainer * Fmu2ReadParams(ParametersInput * input, fmi2_import_t * import, ObjectContainer * ignore); +McxStatus Fmu2ReadParams(ObjectContainer * params, ObjectContainer * arrayParams, ParametersInput * input, fmi2_import_t * import, ObjectContainer * ignore); // TODO: rename all variablearrays to something better McxStatus Fmu2SetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals); @@ -53,6 +53,8 @@ struct Fmu2CommonStruct { ObjectContainer * params; ObjectContainer * initialValues; + ObjectContainer * arrayParams; // proxy views to array parameter elements (from params) (type: ArrayParameterProxy) + ObjectContainer * connectedIn; ObjectContainer * localValues; From 5c6e07d5c43aae9c816974e6ea2ecdc00a1cea3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 9 May 2022 15:11:05 +0200 Subject: [PATCH 105/295] Only take into account fully tunable maps/curves --- src/fmu/common_fmu2.c | 2 +- src/objects/ObjectContainer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 181294e..a6cb9ba 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -965,7 +965,7 @@ ObjectContainer * Fmu2ValueScalarListFromVarList(fmi2_import_variable_list_t * v Fmu2Value * value = Fmu2ValueScalarMake(name, var, NULL, NULL); if (value) { - list->PushBack(list, (Object *) value); + list->PushBackNamed(list, (Object *) value, name); } else { list->DestroyObjects(list); object_destroy(list); diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index 6e451a7..c7c9cdc 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -526,7 +526,7 @@ static ObjectContainer * ObjectContainerFilterCtx(ObjectContainer * container, f for (i = 0; i < container->size; i++) { Object * obj = container->At(container, i); if (predicate(obj, ctx)) { - filtered->PushBack(filtered, obj); + filtered->PushBackNamed(filtered, obj, container->GetElementName(container, i)); } } From bd270ab12d0b11a32196a8628090e2c24b44a390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 10 May 2022 08:36:48 +0200 Subject: [PATCH 106/295] Add ParameterProxies --- src/CMakeLists.txt | 1 + src/core/parameters/ParameterProxies.c | 217 +++++++++++++++++++++++++ src/core/parameters/ParameterProxies.h | 92 +++++++++++ src/fmu/common_fmu2.c | 1 + 4 files changed, 311 insertions(+) create mode 100644 src/core/parameters/ParameterProxies.c create mode 100644 src/core/parameters/ParameterProxies.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2de6bcc..5808f1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,7 @@ file(GLOB MCX_SRC_COMMON "core/channels/*.c" "core/channels/*.cpp" "core/connections/*.c" "core/connections/*.cpp" "core/connections/filters/*.c" "core/connections/filters/*.cpp" + "core/parameters/*.c" "core/parameters/*.cpp" "components/*.c" "components/*.cpp" "fmu/*.c" "fmu/*.cpp" "objects/*.c" "objects/*.cpp" diff --git a/src/core/parameters/ParameterProxies.c b/src/core/parameters/ParameterProxies.c new file mode 100644 index 0000000..107daae --- /dev/null +++ b/src/core/parameters/ParameterProxies.c @@ -0,0 +1,217 @@ +/******************************************************************************** + * Copyright (c) 2021 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/parameters/ParameterProxies.h" +#include "util/string.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +static void ScalarParameterProxySetValue(ScalarParameterProxy * proxy, Fmu2Value * value) { + proxy->value_ = value; +} + +static ChannelType ScalarParameterProxyGetType(ScalarParameterProxy * proxy) { + if (proxy->value_) { + return ChannelValueType(&proxy->value_->val); + } + + return CHANNEL_UNKNOWN; +} + +static Fmu2Value * ScalarParameterProxyGetValue(ScalarParameterProxy * proxy) { + return proxy->value_; +} + +static void ScalarParameterProxyDestructor(ScalarParameterProxy * proxy) { + // don't destroy value as it is just a weak reference +} + +static ScalarParameterProxy * ScalarParameterProxyCreate(ScalarParameterProxy * proxy) { + proxy->SetValue = ScalarParameterProxySetValue; + proxy->GetType = ScalarParameterProxyGetType; + proxy->GetValue = ScalarParameterProxyGetValue; + + proxy->value_ = NULL; + + return proxy; +} + +OBJECT_CLASS(ScalarParameterProxy, Object); + + + +static McxStatus ArrayParameterProxyAddValue(ArrayParameterProxy * proxy, Fmu2Value * value) { + McxStatus retVal = RETURN_OK; + + if (proxy->values_->Size(proxy->values_) > 0) { + Fmu2Value * val = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); + + // check that data types match + if (ChannelValueType(&val->val) != ChannelValueType(&value->val)) { + mcx_log(LOG_ERROR, "Adding value of '%s' to array proxy '%s' failed: Data type mismatch", value->name, proxy->name_); + return RETURN_ERROR; + } + + // check that units match + if (!val->unit && value->unit || val->unit && !value->unit || val->unit && value->unit && strcmp(val->unit, value->unit) != 0) { + mcx_log(LOG_ERROR, "Adding value of '%s' to array proxy '%s' failed: Unit mismatch", value->name, proxy->name_); + return RETURN_ERROR; + } + } + + // add the value to the internal container + retVal = proxy->values_->PushBackNamed(proxy->values_, (Object *)value, value->name); + if (retVal == RETURN_ERROR) { + mcx_log(LOG_ERROR, "Adding value of '%s' to array proxy '%s' failed", value->name, proxy->name_); + return RETURN_ERROR; + } + + return RETURN_OK; +} + +static McxStatus ArrayParameterProxySetup(ArrayParameterProxy * proxy, const char * name, size_t numDims, size_t * dims) { + proxy->name_ = mcx_string_copy(name); + if (name && !proxy->name_) { + mcx_log(LOG_ERROR, "Array proxy setup failed: Not enough memory"); + return RETURN_ERROR; + } + + proxy->numDims_ = numDims; + proxy->dims_ = (size_t *)mcx_calloc(numDims, sizeof(size_t)); + if (!proxy->dims_) { + mcx_log(LOG_ERROR, "Array proxy setup failed: Not enough memory"); + return RETURN_ERROR; + } + + memcpy((void *)proxy->dims_, (void *)dims, numDims * sizeof(size_t)); + + return RETURN_OK; +} + +static const char * ArrayParameterProxyGetName(ArrayParameterProxy * proxy) { + return proxy->name_; +} + +static const char * ArrayParameterProxyGetDesc(ArrayParameterProxy * proxy) { + if (proxy->values_->Size(proxy->values_) > 0) { + Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); + return value->info->desc; + } + + return NULL; +} + +static const char * ArrayParameterProxyGetUnit(ArrayParameterProxy * proxy) { + if (proxy->values_->Size(proxy->values_) > 0) { + Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); + return value->unit; + } + + return NULL; +} + +static ObjectContainer * ArrayParameterProxyGetValues(ArrayParameterProxy * proxy) { + return proxy->values_; +} + +static size_t ArrayParameterProxyGetNumDims(ArrayParameterProxy * proxy) { + return proxy->numDims_; +} + +static size_t ArrayParameterProxyGetDim(ArrayParameterProxy * proxy, size_t idx) { + if (idx >= proxy->numDims_) { + return (size_t)(-1); + } + + return proxy->dims_[idx]; +} + +static ChannelType ArrayParameterProxyGetType(ArrayParameterProxy * proxy) { + if (proxy->values_->Size(proxy->values_) > 0) { + Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); + return ChannelValueType(&value->val); + } + + return CHANNEL_UNKNOWN; +} + +static void ArrayParameterProxyDestructor(ArrayParameterProxy * proxy) { + if (proxy->name_) { mcx_free(proxy->name_); } + if (proxy->dims_) { mcx_free(proxy->dims_); } + + proxy->numDims_ = 0; + + // don't destroy the contained objects as they are just weak references + object_destroy(proxy->values_); +} + +static fmi2_value_reference_t ArrayParameterProxyGetValueReference(ArrayParameterProxy * proxy, size_t idx) { + if (idx < proxy->values_->Size(proxy->values_)) { + Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, idx); + return value->data->vr.scalar; + } + + return (fmi2_value_reference_t)(-1);; +} + +static ChannelValueData * ArrayParameterProxyGetMin(ArrayParameterProxy * proxy) { + if (proxy->values_->Size(proxy->values_) > 0) { + Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); + return value->info->min; + } + + return NULL; +} + +static ChannelValueData * ArrayParameterProxyGetMax(ArrayParameterProxy * proxy) { + if (proxy->values_->Size(proxy->values_) > 0) { + Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); + return value->info->max; + } + + return NULL; +} + +static ArrayParameterProxy * ArrayParameterProxyCreate(ArrayParameterProxy * proxy) { + proxy->Setup = ArrayParameterProxySetup; + proxy->AddValue = ArrayParameterProxyAddValue; + + proxy->GetName = ArrayParameterProxyGetName; + proxy->GetDesc = ArrayParameterProxyGetDesc; + proxy->GetUnit = ArrayParameterProxyGetUnit; + proxy->GetValues = ArrayParameterProxyGetValues; + proxy->GetDim = ArrayParameterProxyGetDim; + proxy->GetNumDims = ArrayParameterProxyGetNumDims; + proxy->GetType = ArrayParameterProxyGetType; + proxy->GetValueReference = ArrayParameterProxyGetValueReference; + proxy->GetMin = ArrayParameterProxyGetMin; + proxy->GetMax = ArrayParameterProxyGetMax; + + proxy->values_ = (ObjectContainer *)object_create(ObjectContainer); + if (!proxy->values_) { + return NULL; + } + + proxy->name_ = NULL; + proxy->dims_ = NULL; + proxy->numDims_ = 0; + + return proxy; +} + +OBJECT_CLASS(ArrayParameterProxy, Object); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/parameters/ParameterProxies.h b/src/core/parameters/ParameterProxies.h new file mode 100644 index 0000000..3d96aec --- /dev/null +++ b/src/core/parameters/ParameterProxies.h @@ -0,0 +1,92 @@ +/******************************************************************************** + * Copyright (c) 2021 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_PARAMETERS_PARAMETER_PROXIES_H +#define MCX_CORE_PARAMETERS_PARAMETER_PROXIES_H + +#include "CentralParts.h" + +#include "fmu/Fmu2Value.h" +#include "objects/ObjectContainer.h" + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +struct ScalarParameterProxy; +typedef struct ScalarParameterProxy ScalarParameterProxy; + +typedef void (*fScalarParameterProxySetValue)(ScalarParameterProxy * proxy, Fmu2Value * value); +typedef ChannelType (*fScalarParameterProxyGetType)(ScalarParameterProxy * proxy); +typedef Fmu2Value * (*fScalarParameterProxyGetValue)(ScalarParameterProxy * proxy); + +extern const struct ObjectClass _ScalarParameterProxy; + +struct ScalarParameterProxy { + Object _; + + fScalarParameterProxySetValue SetValue; + fScalarParameterProxyGetType GetType; + fScalarParameterProxyGetValue GetValue; + + Fmu2Value * value_; +}; + + +struct ArrayParameterProxy; +typedef struct ArrayParameterProxy ArrayParameterProxy; + +typedef McxStatus(*fArrayParameterProxyAddValue)(ArrayParameterProxy * proxy, Fmu2Value * value); +typedef McxStatus(*fArrayParameterProxySetup)(ArrayParameterProxy * proxy, const char * name, size_t numDims, size_t * dims); +typedef const char * (*fArrayParameterProxyGetName)(ArrayParameterProxy * proxy); +typedef const char * (*fArrayParameterProxyGetDesc)(ArrayParameterProxy * proxy); +typedef const char * (*fArrayParameterProxyGetUnit)(ArrayParameterProxy * proxy); +typedef size_t (*fArrayParameterProxyGetNumDims)(ArrayParameterProxy * proxy); +typedef size_t (*fArrayParameterProxyGetDim)(ArrayParameterProxy * proxy, size_t idx); +typedef ObjectContainer * (*fArrayParameterProxyGetValues)(ArrayParameterProxy * proxy); +typedef ChannelType (*fArrayParameterProxyGetType)(ArrayParameterProxy * proxy); +typedef fmi2_value_reference_t (*fArrayParameterProxyGetValueReference)(ArrayParameterProxy * proxy, size_t idx); +typedef ChannelValueData * (*fArrayParameterProxyGetMin)(ArrayParameterProxy * proxy); +typedef ChannelValueData * (*fArrayParameterProxyGetMax)(ArrayParameterProxy * proxy); + +extern const struct ObjectClass _ArrayParameterProxy; + +struct ArrayParameterProxy { + Object _; + + fArrayParameterProxySetup Setup; + fArrayParameterProxyAddValue AddValue; + fArrayParameterProxyGetValues GetValues; + fArrayParameterProxyGetName GetName; + fArrayParameterProxyGetDesc GetDesc; + fArrayParameterProxyGetUnit GetUnit; + fArrayParameterProxyGetNumDims GetNumDims; + fArrayParameterProxyGetDim GetDim; + fArrayParameterProxyGetType GetType; + fArrayParameterProxyGetValueReference GetValueReference; + fArrayParameterProxyGetMin GetMin; + fArrayParameterProxyGetMax GetMax; + + size_t numDims_; + size_t * dims_; + + char * name_; + + ObjectContainer * values_; // of Fmu2Value +}; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MCX_CORE_PARAMETERS_PARAMETER_PROXIES_H */ \ No newline at end of file diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index a6cb9ba..f0c39d4 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -14,6 +14,7 @@ #include "fmu/Fmu2Value.h" #include "core/channels/ChannelInfo.h" +#include "core/parameters/ParameterProxies.h" #include "reader/model/parameters/ArrayParameterDimensionInput.h" #include "reader/model/parameters/ParameterInput.h" From 2d03c7aa78d0d367e253683343b1dca53c4e59bd Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Fri, 3 Jun 2022 17:33:33 +0200 Subject: [PATCH 107/295] Component: Distinguish error/warning in DoStep --- src/core/Component.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index a533d95..5c595ac 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -507,9 +507,11 @@ McxStatus ComponentDoStep(Component * comp, size_t group, double time, double de retVal = comp->DoStep(comp, group, time, deltaTime, endTime, isNewStep); mcx_signal_handler_unset_function(); mcx_signal_handler_unset_name(); - if (RETURN_OK != retVal) { - ComponentLog(comp, LOG_DEBUG, "Component specific DoStep failed"); + if (RETURN_ERROR == retVal) { + ComponentLog(comp, LOG_ERROR, "Component specific DoStep failed"); return RETURN_ERROR; + } else if (RETURN_WARNING == retVal) { + ComponentLog(comp, LOG_DEBUG, "Component specific DoStep returned with a warning"); } } From 08da9f98c0b081195bc25ca3bd02c5ee32a5530c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 4 Jul 2022 09:21:09 +0200 Subject: [PATCH 108/295] results: Make CSV component files resettable --- src/storage/StorageBackendCsv.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/storage/StorageBackendCsv.c b/src/storage/StorageBackendCsv.c index 61eaf26..f5bdef4 100644 --- a/src/storage/StorageBackendCsv.c +++ b/src/storage/StorageBackendCsv.c @@ -185,19 +185,21 @@ static char * QuoteString(const char * _str) { static McxStatus SetupComponentFilesCsv(StorageBackend * backend) { StorageBackendText * textBackend = (StorageBackendText *) backend; ResultsStorage * storage = backend->storage; - char * buffer = NULL; size_t compIdx = 0; + size_t numCompsOld = textBackend->numComponents; - if (textBackend->numComponents > 0) { - mcx_log(LOG_ERROR, "Results: Re-setting up backend"); + MCX_DEBUG_LOG("Setting up component CSV files (%zu -> %zu)", numCompsOld, storage->numComponents); + textBackend->numComponents = storage->numComponents; + textBackend->comps = (TextComponent *) mcx_realloc(textBackend->comps, textBackend->numComponents * sizeof(TextComponent)); + if (textBackend->numComponents && !textBackend->comps) { + mcx_log(LOG_ERROR, "SetupComponentFilesCsv: TextComponents: Not enough memory"); return RETURN_ERROR; } - /* calloc is used for implicit initialization of textBackend->comps */ - textBackend->numComponents = storage->numComponents; - textBackend->comps = (TextComponent *) mcx_calloc(textBackend->numComponents, sizeof(TextComponent)); + // initialize new TextComponents to 0 + memset(textBackend->comps + numCompsOld, 0, (textBackend->numComponents - numCompsOld) * sizeof(TextComponent)); - for (compIdx = 0; compIdx < textBackend->numComponents; compIdx++) { + for (compIdx = numCompsOld; compIdx < textBackend->numComponents; compIdx++) { ComponentStorage * compStore = storage->componentStorage[compIdx]; Component * comp = (Component *) compStore->comp; TextComponent * textComponent = &(textBackend->comps[compIdx]); @@ -216,6 +218,7 @@ static McxStatus SetupComponentFilesCsv(StorageBackend * backend) { ChannelStorage * chStore = compStore->channels[j]; size_t chNum = chStore->GetChannelNum(chStore); size_t chIdx = 0; + char * buffer = NULL; const size_t nameLen = strlen(localName) + strlen(ChannelStoreSuffix[j]) + 6; /* do not create a file if channel store is not enabled */ @@ -281,6 +284,7 @@ static McxStatus SetupComponentFilesCsv(StorageBackend * backend) { } mcx_free(localName); } + return RETURN_OK; } From d777f0b35cd66acba3ef0fa94c5fc1463deb05ed Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 5 Jul 2021 12:21:51 +0200 Subject: [PATCH 109/295] channel: Add return value to SetFromReference --- src/components/comp_constant.c | 12 +++++++--- src/core/Conversion.c | 4 +++- src/core/Databus.c | 24 ++++++++++++++----- src/core/channels/Channel.c | 16 +++++++++---- src/core/channels/ChannelValue.c | 20 +++++++++------- src/core/channels/ChannelValue.h | 4 ++-- src/core/connections/Connection.c | 8 +++++-- src/core/connections/Connection.h | 2 +- src/core/connections/FilteredConnection.c | 16 +++++++++---- src/core/connections/FilteredConnection.h | 2 +- src/core/connections/filters/DiscreteFilter.c | 4 +++- src/fmu/Fmu2Value.c | 4 +++- src/fmu/common_fmu1.c | 16 +++++++++---- src/fmu/common_fmu2.c | 22 +++++++++++++---- src/reader/model/ports/ScalarPortInput.c | 24 ++++++++++++++----- src/storage/ChannelStorage.c | 4 +++- 16 files changed, 131 insertions(+), 51 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index 95daef9..1825b67 100644 --- a/src/components/comp_constant.c +++ b/src/components/comp_constant.c @@ -38,7 +38,10 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con if (value->type == CONSTANT_VALUE_SCALAR) { compConstant->values[i] = (ChannelValue *)mcx_calloc(1, sizeof(ChannelValue)); ChannelValueInit(compConstant->values[i], value->value.scalar->type); - ChannelValueSetFromReference(compConstant->values[i], &value->value.scalar->value); + if (RETURN_OK != ChannelValueSetFromReference(compConstant->values[i], &value->value.scalar->value)) { + ComponentLog(comp, LOG_ERROR, "Could not set channel value"); + return RETURN_ERROR; + } } else { size_t j = 0; size_t size = ChannelValueTypeSize(value->value.array->type); @@ -46,8 +49,11 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con sizeof(ChannelValue)); for (j = 0; j < value->value.array->numValues; j++) { ChannelValueInit(compConstant->values[i] + j, value->value.array->type); - ChannelValueSetFromReference(compConstant->values[i] + j, - (char *)value->value.array->values + j * size); + if (RETURN_OK != ChannelValueSetFromReference(compConstant->values[i] + j, + (char *)value->value.array->values + j * size)) { + ComponentLog(comp, LOG_ERROR, "Could not set channel value"); + return RETURN_ERROR; + } } } } diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 886def6..a684987 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -273,7 +273,9 @@ static McxStatus UnitConversionConvert(Conversion * conversion, ChannelValue * v val = (val + unitConversion->source.offset) * unitConversion->source.factor; val = (val / unitConversion->target.factor) - unitConversion->target.offset; - ChannelValueSetFromReference(value, &val); + if (RETURN_OK != ChannelValueSetFromReference(value, &val)) { + return RETURN_ERROR; + } return RETURN_OK; } diff --git a/src/core/Databus.c b/src/core/Databus.c index 74efc5b..d3901a9 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -322,7 +322,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { ChannelValueInit(&value, expectedType); if (scalarPortInput->min.defined) { - ChannelValueSetFromReference(&value, &scalarPortInput->min.value); + if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->min.value)) { + goto cleanup_else_1; + } info.min = ChannelValueClone(&value); if (!info.min) { goto cleanup_else_1; @@ -330,7 +332,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { } if (scalarPortInput->max.defined) { - ChannelValueSetFromReference(&value, &scalarPortInput->max.value); + if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->max.value)) { + goto cleanup_else_1; + } info.max = ChannelValueClone(&value); if (!info.max) { goto cleanup_else_1; @@ -338,7 +342,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { } if (scalarPortInput->scale.defined) { - ChannelValueSetFromReference(&value, &scalarPortInput->scale.value); + if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->scale.value)) { + goto cleanup_else_1; + } info.scale = ChannelValueClone(&value); if (!info.scale) { goto cleanup_else_1; @@ -346,7 +352,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { } if (scalarPortInput->offset.defined) { - ChannelValueSetFromReference(&value, &scalarPortInput->offset.value); + if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->offset.value)) { + goto cleanup_else_1; + } info.offset = ChannelValueClone(&value); if (!info.offset) { goto cleanup_else_1; @@ -354,7 +362,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { } if (scalarPortInput->default_.defined) { - ChannelValueSetFromReference(&value, &scalarPortInput->default_.value); + if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->default_.value)) { + goto cleanup_else_1; + } info.defaultValue = ChannelValueClone(&value); if (!info.defaultValue) { goto cleanup_else_1; @@ -362,7 +372,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { } if (scalarPortInput->initial.defined) { - ChannelValueSetFromReference(&value, &scalarPortInput->initial.value); + if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->initial.value)) { + goto cleanup_else_1; + } info.initialValue = ChannelValueClone(&value); if (!info.initialValue) { goto cleanup_else_1; diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 6d656d8..a17b147 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -185,8 +185,12 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ChannelValueInit(val, ConnectionInfoGetType(connInfo)); /* Update the connection for the current time */ - conn->UpdateToOutput(conn, time); - ChannelValueSetFromReference(val, conn->GetValueReference(conn)); + if (RETURN_OK != conn->UpdateToOutput(conn, time)) { + return RETURN_ERROR; + } + if (RETURN_OK != ChannelValueSetFromReference(val, conn->GetValueReference(conn))) { + return RETURN_ERROR; + } //type if (in->data->typeConversion) { @@ -759,7 +763,9 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, val); } #endif // MCX_DEBUG - ChannelValueSetFromReference(&channel->value, &val); + if (RETURN_OK != ChannelValueSetFromReference(&channel->value, &val)) { + return RETURN_ERROR; + } } else { #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { @@ -774,7 +780,9 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } } #endif // MCX_DEBUG - ChannelValueSetFromReference(&channel->value, channel->internalValue); + if (RETURN_OK != ChannelValueSetFromReference(&channel->value, channel->internalValue)) { + return RETURN_ERROR; + } } // Apply conversion diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 2c4cc8c..7ec6d04 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -233,8 +233,8 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType type) { } } -void ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference) { - if (!reference) { return; } +McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference) { + if (!reference) { return RETURN_OK; } // TODO: change to ERROR switch (type) { case CHANNEL_DOUBLE: @@ -279,12 +279,12 @@ void ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, default: break; } -} -void ChannelValueSetFromReference(ChannelValue * value, const void * reference) { - if (!reference) { return; } + return RETURN_OK; +} - ChannelValueDataSetFromReference(&value->value, value->type, reference); +McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * reference) { + return ChannelValueDataSetFromReference(&value->value, value->type, reference); } McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { @@ -294,7 +294,9 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { return RETURN_ERROR; } - ChannelValueSetFromReference(value, ChannelValueReference((ChannelValue *) source)); + if (RETURN_OK != ChannelValueSetFromReference(value, ChannelValueReference((ChannelValue *) source))) { + return RETURN_ERROR; + } return RETURN_OK; } @@ -527,7 +529,9 @@ ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType } ChannelValueInit(array[i], type); - ChannelValueSetFromReference(array[i], (char *) values + i*size); + if (RETURN_OK != ChannelValueSetFromReference(array[i], (char *) values + i*size)) { + return RETURN_ERROR; + } } return array; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 7cbdf2a..bc280c6 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -67,9 +67,9 @@ void * ChannelValueReference(ChannelValue * value); void ChannelValueDataDestructor(ChannelValueData * data, ChannelType type); void ChannelValueDataInit(ChannelValueData * data, ChannelType type); -void ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference); +McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference); -void ChannelValueSetFromReference(ChannelValue * value, const void * reference); +McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * reference); void ChannelValueSetToReference(ChannelValue * value, void * reference); McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 67622d2..3787984 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1225,7 +1225,7 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim // Do nothing } -static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) { +static McxStatus ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) { Channel * channel = (Channel *) connection->out_; #ifdef MCX_DEBUG @@ -1236,13 +1236,17 @@ static void ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) #endif if (!connection->useInitialValue_) { - ChannelValueSetFromReference(&connection->store_, channel->GetValueReference(channel)); + if (RETURN_OK != ChannelValueSetFromReference(&connection->store_, channel->GetValueReference(channel))) { + return RETURN_ERROR; + } if (channel->IsDefinedDuringInit(channel)) { connection->SetDefinedDuringInit(connection); } } else { connection->SetDefinedDuringInit(connection); } + + return RETURN_OK; } static McxStatus ConnectionEnterInitializationMode(Connection * connection) { diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h index f4736b9..648ed86 100644 --- a/src/core/connections/Connection.h +++ b/src/core/connections/Connection.h @@ -62,7 +62,7 @@ typedef void (* fConnectionSetVoid)(Connection * connection); typedef void (* fConnectionUpdateFromInput)(Connection * connection, TimeInterval * time); -typedef void (* fConnectionUpdateToOutput)(Connection * connection, TimeInterval * time); +typedef McxStatus (* fConnectionUpdateToOutput)(Connection * connection, TimeInterval * time); typedef McxStatus (* fConnectionUpdateInitialValue)(Connection * connection); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 79aa80a..3d8a1d3 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -114,8 +114,8 @@ static ChannelFilter * FilteredConnectionGetFilter(FilteredConnection * connecti return connection->data->filter; } -static void FilteredConnectionSetResult(FilteredConnection * connection, const void * value) { - ChannelValueSetFromReference(&connection->data->store, value); +static McxStatus FilteredConnectionSetResult(FilteredConnection * connection, const void * value) { + return ChannelValueSetFromReference(&connection->data->store, value); } static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInterval * time) { @@ -136,7 +136,7 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter } } -static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterval * time) { +static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeInterval * time) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; ChannelFilter * filter = NULL; @@ -156,7 +156,9 @@ static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterv double value = 0.0; value = p->fn(time, p->env); - filteredConnection->SetResult(filteredConnection, &value); + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { + return RETURN_ERROR; + } } else { // only filter if time is not negative (negative time means filter disabled) if (filteredConnection->GetReadFilter(filteredConnection) && time->startTime >= 0) { @@ -165,9 +167,13 @@ static void FilteredConnectionUpdateToOutput(Connection * connection, TimeInterv filter = filteredConnection->GetReadFilter(filteredConnection); value = filter->GetValue(filter, time->startTime); - filteredConnection->SetResult(filteredConnection, &value); + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { + return RETURN_ERROR; + } } } + + return RETURN_OK; } static McxStatus AddFilter(Connection * connection) { diff --git a/src/core/connections/FilteredConnection.h b/src/core/connections/FilteredConnection.h index ef2f335..00dc94a 100644 --- a/src/core/connections/FilteredConnection.h +++ b/src/core/connections/FilteredConnection.h @@ -22,7 +22,7 @@ typedef struct FilteredConnection FilteredConnection; typedef struct ChannelFilter * (* fConnectionGetFilter)(FilteredConnection * connection); -typedef void (* fFilteredConnectionSetResult)(FilteredConnection * connection, const void * value); +typedef McxStatus (* fFilteredConnectionSetResult)(FilteredConnection * connection, const void * value); extern const struct ObjectClass _FilteredConnection; diff --git a/src/core/connections/filters/DiscreteFilter.c b/src/core/connections/filters/DiscreteFilter.c index ad80218..279ca3a 100644 --- a/src/core/connections/filters/DiscreteFilter.c +++ b/src/core/connections/filters/DiscreteFilter.c @@ -18,7 +18,9 @@ static McxStatus DiscreteFilterSetValue(ChannelFilter * filter, double time, Cha DiscreteFilter * discreteFilter = (DiscreteFilter *) filter; if (InCommunicationMode != * filter->state) { - ChannelValueSetFromReference(&discreteFilter->lastCouplingStepValue, &value); + if (RETURN_OK != ChannelValueSetFromReference(&discreteFilter->lastCouplingStepValue, &value)) { + return RETURN_ERROR; + } } return RETURN_OK; diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index aa15aaf..dc5c8ab 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -208,7 +208,9 @@ static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData break; case fmi2_base_type_str: { const char * buffer = fmi2_import_get_string_variable_start(fmi2_import_get_variable_as_string(data->data.scalar)); - ChannelValueSetFromReference(&v->val, &buffer); + if (RETURN_OK != ChannelValueSetFromReference(&v->val, &buffer)) { + return RETURN_ERROR; + } break; } case fmi2_base_type_enum: diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index dc72d00..94bbf97 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -283,7 +283,9 @@ Fmu1Value * Fmu1ReadParamValue(ScalarParameterInput * input, fmi1_import_t * imp } ChannelValueInit(&chVal, input->type); - ChannelValueSetFromReference(&chVal, &input->value.value); + if (RETURN_OK != ChannelValueSetFromReference(&chVal, &input->value.value)) { + return NULL; + } var = fmi1_import_get_variable_by_name(import, input->name); if (!var) { @@ -381,11 +383,15 @@ static ObjectContainer * Fmu1ReadArrayParamValues(const char * name, if (input->type == CHANNEL_DOUBLE) { ChannelValueInit(&chVal, CHANNEL_DOUBLE); - ChannelValueSetFromReference(&chVal, &((double *)input->values)[index]); + if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { + return RETURN_ERROR; + } } else { // integer ChannelValueInit(&chVal, CHANNEL_INTEGER); - ChannelValueSetFromReference(&chVal, &((int *)input->values)[index]); + if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { + return RETURN_ERROR; + } } retVal = val->SetFromChannelValue(val, &chVal); @@ -652,7 +658,9 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { char * buffer = NULL; status = fmi1_import_get_string(fmu->fmiImport, vr, 1, (fmi1_string_t *)&buffer); - ChannelValueSetFromReference(chVal, &buffer); + if (RETURN_OK != ChannelValueSetFromReference(chVal, &buffer)) { + return RETURN_ERROR; + } break; } default: diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index f0c39d4..c6c7e3f 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -299,7 +299,9 @@ Fmu2Value * Fmu2ReadParamValue(ScalarParameterInput * input, } ChannelValueInit(&chVal, input->type); - ChannelValueSetFromReference(&chVal, &input->value.value); + if (RETURN_OK != ChannelValueSetFromReference(&chVal, &input->value.value)) { + return NULL; + } var = fmi2_import_get_variable_by_name(import, input->name); if (!var) { @@ -389,10 +391,16 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, if (input->type == CHANNEL_DOUBLE) { ChannelValueInit(&chVal, CHANNEL_DOUBLE); - ChannelValueSetFromReference(&chVal, &((double *)input->values)[index]); + if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { + retVal = RETURN_ERROR; + goto fmu2_read_array_param_values_for_cleanup; + } } else { // integer ChannelValueInit(&chVal, CHANNEL_INTEGER); - ChannelValueSetFromReference(&chVal, &((int *)input->values)[index]); + if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { + retVal = RETURN_ERROR; + goto fmu2_read_array_param_values_for_cleanup; + } } retVal = val->SetFromChannelValue(val, &chVal); @@ -818,7 +826,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { char * buffer = NULL; status = fmi2_import_get_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) &buffer); - ChannelValueSetFromReference(chVal, &buffer); + if (RETURN_OK != ChannelValueSetFromReference(chVal, &buffer)) { + return RETURN_ERROR; + } break; } @@ -839,7 +849,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { binary.len = vs[2]; binary.data = (char *) ((((long long)vs[1] & 0xffffffff) << 32) | (vs[0] & 0xffffffff)); - ChannelValueSetFromReference(chVal, &binary); + if (RETURN_OK != ChannelValueSetFromReference(chVal, &binary)) { + return RETURN_ERROR; + } break; } diff --git a/src/reader/model/ports/ScalarPortInput.c b/src/reader/model/ports/ScalarPortInput.c index 50be17d..38d4b18 100644 --- a/src/reader/model/ports/ScalarPortInput.c +++ b/src/reader/model/ports/ScalarPortInput.c @@ -81,37 +81,49 @@ static McxStatus CopyFrom(ScalarPortInput * self, ScalarPortInput * src) { self->min.defined = src->min.defined; if (self->min.defined) { ChannelValueDataInit(&self->min.value, self->type); - ChannelValueDataSetFromReference(&self->min.value, self->type, &src->min.value); + if (RETURN_OK != ChannelValueDataSetFromReference(&self->min.value, self->type, &src->min.value)) { + return RETURN_ERROR; + } } self->max.defined = src->max.defined; if (self->max.defined) { ChannelValueDataInit(&self->max.value, self->type); - ChannelValueDataSetFromReference(&self->max.value, self->type, &src->max.value); + if (RETURN_OK != ChannelValueDataSetFromReference(&self->max.value, self->type, &src->max.value)) { + return RETURN_ERROR; + } } self->scale.defined = src->scale.defined; if (self->scale.defined) { ChannelValueDataInit(&self->scale.value, self->type); - ChannelValueDataSetFromReference(&self->scale.value, self->type, &src->scale.value); + if (RETURN_OK != ChannelValueDataSetFromReference(&self->scale.value, self->type, &src->scale.value)) { + return RETURN_ERROR; + } } self->offset.defined = src->offset.defined; if (self->offset.defined) { ChannelValueDataInit(&self->offset.value, self->type); - ChannelValueDataSetFromReference(&self->offset.value, self->type, &src->offset.value); + if (RETURN_OK != ChannelValueDataSetFromReference(&self->offset.value, self->type, &src->offset.value)) { + return RETURN_ERROR; + } } self->default_.defined = src->default_.defined; if (self->default_.defined) { ChannelValueDataInit(&self->default_.value, self->type); - ChannelValueDataSetFromReference(&self->default_.value, self->type, &src->default_.value); + if (RETURN_OK != ChannelValueDataSetFromReference(&self->default_.value, self->type, &src->default_.value)) { + return RETURN_ERROR; + } } self->initial.defined = src->initial.defined; if (self->initial.defined) { ChannelValueDataInit(&self->initial.value, self->type); - ChannelValueDataSetFromReference(&self->initial.value, self->type, &src->initial.value); + if (RETURN_OK != ChannelValueDataSetFromReference(&self->initial.value, self->type, &src->initial.value)) { + return RETURN_ERROR; + } } self->writeResults = src->writeResults; diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 7cf8f14..538e86b 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -156,7 +156,9 @@ static McxStatus ChannelStorageSetValueFromReferenceAt(ChannelStorage * channelS ChannelValueInit(&channelStore->values[row * colNum + col], info->type); } - ChannelValueSetFromReference(&channelStore->values[row * colNum + col], reference); + if (RETURN_OK != ChannelValueSetFromReference(&channelStore->values[row * colNum + col], reference)) { + return RETURN_ERROR; + } return RETURN_OK; } From 677217527ad7cd9e9c3a3fee2657d10d38329f9e Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 5 Jul 2021 13:40:53 +0200 Subject: [PATCH 110/295] channel: Add return value to SetToReference --- src/core/channels/ChannelValue.c | 4 +++- src/core/channels/ChannelValue.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 7ec6d04..1685e7f 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -301,7 +301,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { return RETURN_OK; } -void ChannelValueSetToReference(ChannelValue * value, void * reference) { +McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { switch (value->type) { case CHANNEL_DOUBLE: * (double *) reference = value->value.d; @@ -347,6 +347,8 @@ void ChannelValueSetToReference(ChannelValue * value, void * reference) { default: break; } + + return RETURN_OK; } #ifdef __cplusplus size_t ChannelValueTypeSize(ChannelType type) { diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index bc280c6..2b40d11 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -70,7 +70,7 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType type); McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference); McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * reference); -void ChannelValueSetToReference(ChannelValue * value, void * reference); +McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference); McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); From 06e75558f5acc9efd53201b854cf772ec3d05d9b Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 5 Jul 2021 08:42:12 +0200 Subject: [PATCH 111/295] channel: Add CHANNEL_ARRAY --- src/core/channels/ChannelValue.c | 155 +++++++++++++++++++++++++++++++ src/core/channels/ChannelValue.h | 33 +++++-- 2 files changed, 178 insertions(+), 10 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 1685e7f..5411d42 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -15,6 +15,58 @@ extern "C" { #endif /* __cplusplus */ + +McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType type) { + a->numDims = numDims; + a->dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); + if (!a->dims) { + return RETURN_ERROR; + } + memcpy(a->dims, dims, sizeof(size_t) * numDims); + + a->type = type; + a->data = (void *) mcx_calloc(ChannelValueTypeSize(type), array_num_elements(a)); + if (!a->data) { + return RETURN_ERROR; + } + + return RETURN_OK; +} + +int array_dims_match(array * a, array * b) { + size_t i = 0; + + if (a->numDims != b->numDims) { + return 0; + } + if (a->dims == NULL || b->dims == NULL) { + return 0; + } + + for (i = 0; i < a->numDims; i++) { + if (a->dims[i] != b->dims[i]) { + return 0; + } + } + + return 1; +} + +size_t array_num_elements(array * a) { + size_t i = 0; + size_t n = 1; + + if (a->numDims == 0) { + return 0; + } + + for (i = 0; i < a->numDims; i++) { + n *= a->dims[i]; + } + + return n; +} + void ChannelValueInit(ChannelValue * value, ChannelType type) { value->type = type; ChannelValueDataInit(&value->value, type); @@ -33,6 +85,15 @@ void ChannelValueDataDestructor(ChannelValueData * data, ChannelType type) { } } else if (type == CHANNEL_BINARY_REFERENCE) { // do not free references to binary, they are not owned by the ChannelValueData + } else if (type == CHANNEL_ARRAY) { + if (data->a.dims) { + mcx_free(data->a.dims); + data->a.dims = NULL; + } + if (data->a.data) { + mcx_free(data->a.data); + data->a.data = NULL; + } } } @@ -111,6 +172,9 @@ char * ChannelValueToString(ChannelValue * value) { } } break; + case CHANNEL_ARRAY: + mcx_log(LOG_ERROR, "TODO: ChannelValueToString unimplemented for CHANNEL_ARRAY"); + return NULL; default: return NULL; } @@ -184,6 +248,9 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel } } break; + case CHANNEL_ARRAY: + mcx_log(LOG_ERROR, "TODO: ChannelValueToString unimplemented for CHANNEL_ARRAY"); + return RETURN_ERROR; default: mcx_log(LOG_DEBUG, "Port value to string: Unknown type"); return RETURN_ERROR; @@ -227,6 +294,11 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType type) { data->b.len = 0; data->b.data = NULL; break; + case CHANNEL_ARRAY: + data->a.numDims = 0; + data->a.dims = NULL; + data->a.data = NULL; + break; case CHANNEL_UNKNOWN: default: break; @@ -275,6 +347,28 @@ McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType data->b.data = ((binary_string *) reference)->data; } break; + case CHANNEL_ARRAY: + if (NULL != reference) { + array * a = (array *) reference; + + // The first call to SetFromReference fixes the dimensions + if (!data->a.numDims && a->numDims) { + if (RETURN_OK != array_init(&data->a, a->numDims, a->dims, a->type)) { + return RETURN_ERROR; + } + } + + // Arrays do not support multiplexing (yet) + if (!array_dims_match(&data->a, a)) { + return RETURN_ERROR; + } + + if (a->data == NULL || data->a.data == NULL) { + return RETURN_ERROR; + } + + memcpy(data->a.data, a->data, ChannelValueTypeSize(a->type) * array_num_elements(a)); + } case CHANNEL_UNKNOWN: default: break; @@ -343,6 +437,29 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { ((binary_string *) reference)->data = value->value.b.data; } break; + case CHANNEL_ARRAY: + if (NULL != reference) { + array * a = (array *) reference; + + // First Set fixes the dimensions + if (value->value.a.numDims && !a->numDims) { + if (RETURN_OK != array_init(a, value->value.a.numDims, value->value.a.dims, value->value.a.type)) { + return RETURN_ERROR; + } + } + + // Arrays do not support multiplexing (yet) + if (!array_dims_match(a, &value->value.a)) { + return RETURN_ERROR; + } + + if (value->value.a.data == NULL || a->data == NULL) { + return RETURN_ERROR; + } + + memcpy(a->data, value->value.a.data, ChannelValueTypeSize(a->type) * array_num_elements(a)); + } + break; case CHANNEL_UNKNOWN: default: break; @@ -350,6 +467,8 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { return RETURN_OK; } + +// TODO: invalid size should be (-1) #ifdef __cplusplus size_t ChannelValueTypeSize(ChannelType type) { switch (type) { @@ -361,6 +480,11 @@ size_t ChannelValueTypeSize(ChannelType type) { return sizeof(ChannelValueData::i); case CHANNEL_STRING: return sizeof(ChannelValueData::s); + case CHANNEL_BINARY: + case CHANNEL_BINARY_REFERENCE: + return sizeof(ChannelValueData::b); + case CHANNEL_ARRAY: + return sizeof(ChannelValueData::a); } return 0; } @@ -376,6 +500,11 @@ size_t ChannelValueTypeSize(ChannelType type) { return sizeof(value.i); case CHANNEL_STRING: return sizeof(value.s); + case CHANNEL_BINARY: + case CHANNEL_BINARY_REFERENCE: + return sizeof(value.b); + case CHANNEL_ARRAY: + return sizeof(value.a); } return 0; } @@ -396,6 +525,8 @@ const char * ChannelTypeToString(ChannelType type) { case CHANNEL_BINARY: case CHANNEL_BINARY_REFERENCE: return "Binary"; + case CHANNEL_ARRAY: + return "Array"; default: return ""; } @@ -427,6 +558,10 @@ int ChannelValueLeq(ChannelValue * val1, ChannelValue * val2) { return val1->value.d <= val2->value.d; case CHANNEL_INTEGER: return val1->value.i <= val2->value.i; + case CHANNEL_ARRAY: + // TODO: val1 <= val1 <=> val1[i,j] <= val2[i,j] \forall i,j? + mcx_log(LOG_ERROR, "TODO: ChannelValueLeq unimplemented for CHANNEL_ARRAY"); + exit(-1); default: return 0; } @@ -442,6 +577,10 @@ int ChannelValueGeq(ChannelValue * val1, ChannelValue * val2) { return val1->value.d >= val2->value.d; case CHANNEL_INTEGER: return val1->value.i >= val2->value.i; + case CHANNEL_ARRAY: + // TODO: val1 >= val1 <=> val1[i,j] >= val2[i,j] \forall i,j? + mcx_log(LOG_ERROR, "TODO: ChannelValueGeq unimplemented for CHANNEL_ARRAY"); + exit(-1); default: return 0; } @@ -460,6 +599,10 @@ int ChannelValueEq(ChannelValue * val1, ChannelValue * val2) { return val1->value.i == val2->value.i; case CHANNEL_STRING: return !strcmp(val1->value.s, val2->value.s); + case CHANNEL_ARRAY: + // TODO: val1 == val1 <=> val1[i,j] == val2[i,j] \forall i,j? + mcx_log(LOG_ERROR, "TODO: ChannelValueEq unimplemented for CHANNEL_ARRAY"); + exit(-1); default: return 0; } @@ -479,6 +622,12 @@ McxStatus ChannelValueAddOffset(ChannelValue * val, ChannelValue * offset) { case CHANNEL_INTEGER: val->value.i += offset->value.i; return RETURN_OK; + case CHANNEL_ARRAY: + // TODO: val matrix, offset matrix + // val matrix, offset scalar + // needs check above relaxed + mcx_log(LOG_ERROR, "TODO: ChannelValueAddOffset unimplemented for CHANNEL_ARRAY"); + exit(-1); default: mcx_log(LOG_ERROR, "Port: Add offset: Type %s not allowed", ChannelTypeToString(ChannelValueType(val))); return RETURN_ERROR; @@ -499,6 +648,12 @@ McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { case CHANNEL_INTEGER: val->value.i *= factor->value.i; return RETURN_OK; + case CHANNEL_ARRAY: + // TODO: val matrix, offset scalar + // val matrix, offset matrix: matrix multiplication? + // needs check above relaxed + mcx_log(LOG_ERROR, "TODO: ChannelValueScale unimplemented for CHANNEL_ARRAY"); + exit(-1); default: mcx_log(LOG_ERROR, "Port: Scale: Type %s not allowed", ChannelTypeToString(ChannelValueType(val))); return RETURN_ERROR; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 2b40d11..7b4cccc 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -17,6 +17,18 @@ extern "C" { #endif /* __cplusplus */ +// possible types of values that can be put on channels +typedef enum ChannelType { + CHANNEL_UNKNOWN = 0, + CHANNEL_DOUBLE = 1, + CHANNEL_INTEGER = 2, + CHANNEL_BOOL = 3, + CHANNEL_STRING = 4, + CHANNEL_BINARY = 5, + CHANNEL_BINARY_REFERENCE = 6, + CHANNEL_ARRAY = 7, +} ChannelType; + typedef struct { double startTime; double endTime; @@ -32,23 +44,24 @@ typedef struct { char * data; } binary_string; -// possible types of values that can be put on channels -typedef enum ChannelType { - CHANNEL_UNKNOWN = 0, - CHANNEL_DOUBLE = 1, - CHANNEL_INTEGER = 2, - CHANNEL_BOOL = 3, - CHANNEL_STRING = 4, - CHANNEL_BINARY = 5, - CHANNEL_BINARY_REFERENCE = 6, -} ChannelType; +typedef struct { + size_t numDims; + size_t * dims; + ChannelType type; + void * data; +} array; + +int array_dims_match(array * a, array * b); +size_t array_num_elements(array * a); +// TODO: change concrete types to McxDouble, McxInteger, etc typedef union ChannelValueData { /* the order is significant. double needs to be the first entry for union initialization to work */ double d; int i; char * s; binary_string b; + array a; } ChannelValueData; typedef struct ChannelValue { From d2e4b57a87cab84956ad44822dfa6c9e5baf3655 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 6 Jul 2021 10:10:36 +0200 Subject: [PATCH 112/295] Add ChannelTypeMatch --- src/core/channels/ChannelValue.c | 10 ++++++++++ src/core/channels/ChannelValue.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 5411d42..a25f20a 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -510,6 +510,16 @@ size_t ChannelValueTypeSize(ChannelType type) { } #endif //__cplusplus +int ChannelTypeMatch(ChannelType a, ChannelType b) { + if ((CHANNEL_BINARY == a || CHANNEL_BINARY_REFERENCE == a) && + (CHANNEL_BINARY == b || CHANNEL_BINARY_REFERENCE == b)) { + return 1; + } else { + return a == b; + } + // TODO: Ignores array dimensions +} + const char * ChannelTypeToString(ChannelType type) { switch (type) { case CHANNEL_UNKNOWN: diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 7b4cccc..30a6d25 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -88,6 +88,8 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference); McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); size_t ChannelValueTypeSize(ChannelType type); +int ChannelTypeMatch(ChannelType a, ChannelType b); + ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType type); From d848a9e54b8cabe39235878d7bac9044efe407ec Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 6 Jul 2021 10:11:10 +0200 Subject: [PATCH 113/295] channel: Use ChannelTypeMatch in ChannelInSetReference --- src/core/channels/Channel.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index a17b147..7bcde53 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -133,13 +133,9 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel mcx_log(LOG_ERROR, "Port %s: Set inport reference: Port not set up", ChannelInfoGetLogName(info)); return RETURN_ERROR; } - 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", ChannelInfoGetLogName(info)); - return RETURN_ERROR; - } + if (!ChannelTypeMatch(info->type, type)) { + mcx_log(LOG_ERROR, "Port %s: Set inport reference: Mismatching types", ChannelInfoGetLogName(info)); + return RETURN_ERROR; } } From 133ae5675245fcac109b0f1ce80ce819d249016a Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 6 Jul 2021 10:11:43 +0200 Subject: [PATCH 114/295] channel: Use ChannelValueDataSetFromReference in ChannelInUpdate --- src/core/channels/Channel.c | 61 +++---------------------------------- 1 file changed, 4 insertions(+), 57 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 7bcde53..6fde510 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -242,65 +242,12 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } - - 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, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); - } -#endif // MCX_DEBUG - * (double *) in->data->reference = * (double *) channel->GetValueReference(channel); - break; - case CHANNEL_INTEGER: - * (int *) in->data->reference = * (int *) channel->GetValueReference(channel); - break; - case CHANNEL_BOOL: - * (int *) in->data->reference = * (int *) channel->GetValueReference(channel); - break; - case CHANNEL_STRING: - { - const void * reference = channel->GetValueReference(channel); - - if (NULL != reference && NULL != * (const char * *) reference ) { - if (* (char * *) in->data->reference) { - mcx_free(* (char * *) in->data->reference); - } - * (char * *) in->data->reference = (char *) mcx_calloc(strlen(* (const char **) reference) + 1, sizeof(char)); - if (* (char * *) in->data->reference) { - strncpy(* (char * *) in->data->reference, * (const char **)reference, strlen(* (const char **)reference) + 1); - } - } - break; + if (time->startTime < MCX_DEBUG_LOG_TIME && info->type == CHANNEL_DOUBLE) { + MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); } - case CHANNEL_BINARY: - { - const void * reference = channel->GetValueReference(channel); - if (NULL != reference && NULL != ((const binary_string *) reference)->data) { - if (((binary_string *) in->data->reference)->data) { - mcx_free(((binary_string *) in->data->reference)->data); - } - ((binary_string *) in->data->reference)->len = ((const binary_string *) reference)->len; - ((binary_string *) in->data->reference)->data = (char *) mcx_malloc(((binary_string *) in->data->reference)->len); - if (((binary_string *) in->data->reference)->data) { - memcpy(((binary_string *) in->data->reference)->data, ((const binary_string *) reference)->data, ((binary_string *) in->data->reference)->len); - } - } - break; - } - case CHANNEL_BINARY_REFERENCE: - { - const void * reference = channel->GetValueReference(channel); - - if (NULL != reference && NULL != ((binary_string *) reference)->data) { - ((binary_string *) in->data->reference)->len = ((binary_string *) reference)->len; - ((binary_string *) in->data->reference)->data = ((binary_string *) reference)->data; - } - break; - } - default: - break; + if (RETURN_OK != ChannelValueDataSetFromReference(in->data->reference, info->type, channel->GetValueReference(channel))) { + return RETURN_ERROR; } return RETURN_OK; From d1c5545e2bfffb486693a202030764144dc37fd6 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 6 Jul 2021 11:40:18 +0200 Subject: [PATCH 115/295] channel: Add error messages --- src/core/channels/Channel.c | 2 ++ src/core/connections/FilteredConnection.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 6fde510..95a89b8 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -182,9 +182,11 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { + mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection failed", info->GetLogName(info)); return RETURN_ERROR; } if (RETURN_OK != ChannelValueSetFromReference(val, conn->GetValueReference(conn))) { + mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueSetFromReference failed", info->GetLogName(info)); return RETURN_ERROR; } diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 3d8a1d3..cbf73ed 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -157,6 +157,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI value = p->fn(time, p->env); if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { + mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } } else { @@ -168,6 +169,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI value = filter->GetValue(filter, time->startTime); if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { + mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } } From 92ccb83bdef99ef67e5da0dbd75768ef930cee0f Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 6 Jul 2021 11:47:33 +0200 Subject: [PATCH 116/295] channel: Remove unnecessary type checks --- src/core/channels/Channel.c | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 95a89b8..9643db5 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -182,11 +182,11 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { - mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection failed", info->GetLogName(info)); + mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } if (RETURN_OK != ChannelValueSetFromReference(val, conn->GetValueReference(conn))) { - mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueSetFromReference failed", info->GetLogName(info)); + mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueSetFromReference failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -199,42 +199,42 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { 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; - } + // Conversions + { + 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->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", ChannelInfoGetLogName(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", 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", ChannelInfoGetLogName(info)); + return RETURN_ERROR; } } } From 36065ec07d58742d2bf88dd3f2d2becfca20d372 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 6 Jul 2021 14:05:25 +0200 Subject: [PATCH 117/295] channel: Add nameInModel to ChannelInfoInit --- src/core/Databus.c | 2 +- src/core/channels/ChannelInfo.c | 5 +++++ src/core/channels/ChannelInfo.h | 1 + src/storage/ChannelStorage.c | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index d3901a9..327de97 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1513,7 +1513,7 @@ static McxStatus DatabusAddLocalChannelInternal(Databus * db, } uniqueName = DatabusGetUniqueChannelName(db, name); - retVal = ChannelInfoSetup(&chInfo, uniqueName, NULL, unit, type, id); + retVal = ChannelInfoSetup(&chInfo, uniqueName, uniqueName, NULL, unit, type, id); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Ports: Set local-reference: Setting up ChannelInfo for %s failed", ChannelInfoGetName(&chInfo)); goto cleanup; diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index 41e4baf..7db9b5f 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -102,6 +102,7 @@ McxStatus ChannelInfoSetVector(ChannelInfo * info, VectorChannelInfo * vector) { McxStatus ChannelInfoSetup(ChannelInfo * info, const char * name, + const char * nameInModel, const char * descr, const char * unit, ChannelType type, @@ -110,6 +111,10 @@ McxStatus ChannelInfoSetup(ChannelInfo * info, mcx_log(LOG_DEBUG, "Port %s: Could not set name", name); return RETURN_ERROR; } + if (nameInModel && RETURN_OK != ChannelInfoSetNameInTool(info, nameInModel)) { + mcx_log(LOG_DEBUG, "Port %s: Could not set name in tool", 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; diff --git a/src/core/channels/ChannelInfo.h b/src/core/channels/ChannelInfo.h index 9f8c0a0..a995413 100644 --- a/src/core/channels/ChannelInfo.h +++ b/src/core/channels/ChannelInfo.h @@ -73,6 +73,7 @@ int ChannelInfoIsBinary(const ChannelInfo * info); McxStatus ChannelInfoSetup(ChannelInfo * info, const char * name, + const char * nameInModel, const char * descr, const char * unit, ChannelType type, diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 538e86b..cfda2e6 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -83,7 +83,7 @@ static McxStatus ChannelStorageSetup(ChannelStorage * channelStore, int fullStor goto cleanup; } - retVal = ChannelInfoSetup(&timeInfo, "Time", "", GetTimeUnitString(), CHANNEL_DOUBLE, ""); + retVal = ChannelInfoSetup(&timeInfo, "Time", "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; From b43a7e9e6ff985b79be96cb8ee992168d62e0e54 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Wed, 7 Jul 2021 09:14:40 +0200 Subject: [PATCH 118/295] Add ChannelValueDestroy to free ChannelValues on heap --- src/core/channels/ChannelValue.c | 6 ++++++ src/core/channels/ChannelValue.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index a25f20a..b227785 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -670,6 +670,12 @@ McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { } } +void ChannelValueDestroy(ChannelValue ** value) { + ChannelValueDestructor(*value); + mcx_free(*value); + *value = NULL; +} + ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType type) { ChannelValue ** array = NULL; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 30a6d25..e1b21c0 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -90,6 +90,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); size_t ChannelValueTypeSize(ChannelType type); int ChannelTypeMatch(ChannelType a, ChannelType b); +void ChannelValueDestroy(ChannelValue ** value); ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType type); From 56e5bb5d62a125c60d4bef7900c42c005c8c87ab Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Wed, 7 Jul 2021 10:05:38 +0200 Subject: [PATCH 119/295] channel: Use writeResults as scalar for vectors --- src/core/Databus.c | 11 +++-------- src/reader/model/ports/VectorPortInput.c | 23 +++++++++++------------ src/reader/model/ports/VectorPortInput.h | 2 +- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 327de97..3e1882a 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -98,7 +98,6 @@ static Vector * DatabusReadPortInput(PortInput * input) { ChannelValue ** offsets = NULL; ChannelValue ** defaults = NULL; ChannelValue ** initials = NULL; - int * writeResults = NULL; int startIndex = 0; int endIndex = 0; @@ -173,8 +172,6 @@ static Vector * DatabusReadPortInput(PortInput * input) { goto cleanup_1; } - writeResults = vectorPortInput->writeResults; - for (i = startIndex; i <= endIndex; i++) { char * name = NULL; char * nameInTool = NULL; @@ -239,8 +236,9 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (initials) { copy.initialValue = initials[i - startIndex]; } - if (writeResults) { - copy.writeResult = writeResults[i - startIndex]; + + if (vectorPortInput->writeResults.defined) { + copy.writeResult = vectorPortInput->writeResults.value; } list->PushBack(list, ©); @@ -287,9 +285,6 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (initials) { mcx_free(initials); } - if (writeResults) { - // writeResults was taken from vectorPortInput - } if (RETURN_ERROR == retVal) { goto cleanup_0; diff --git a/src/reader/model/ports/VectorPortInput.c b/src/reader/model/ports/VectorPortInput.c index bd74ebc..5461096 100644 --- a/src/reader/model/ports/VectorPortInput.c +++ b/src/reader/model/ports/VectorPortInput.c @@ -144,15 +144,7 @@ static McxStatus CopyFrom(VectorPortInput * self, VectorPortInput * src) { self->default_ = NULL; } - if (src->writeResults) { - self->writeResults = (int *) mcx_calloc(len, sizeof(int)); - if (!self->writeResults) { - return RETURN_ERROR; - } - memcpy(self->writeResults, src->writeResults, len * sizeof(int)); - } else { - self->writeResults = NULL; - } + self->writeResults = src->writeResults; return RETURN_OK; } @@ -187,6 +179,14 @@ static void PrintVec(char * prefix, ChannelType type, size_t len, void * value) mcx_log(LOG_DEBUG, "%s", buffer); } +static void PrintOptionalInt(char * prefix, OPTIONAL_VALUE(int) value) { + if (value.defined) { + mcx_log(LOG_DEBUG, "%s%d,", prefix, value.value); + } else { + mcx_log(LOG_DEBUG, "%s-,", prefix); + } +} + void VectorPortInputPrint(VectorPortInput * input) { size_t len = input->endIndex - input->startIndex + 1; @@ -205,7 +205,7 @@ void VectorPortInputPrint(VectorPortInput * input) { PrintVec(" .default: ", input->type, len, input->default_); PrintVec(" .initial: ", input->type, len, input->initial); - PrintVec(" .writeResults: ", input->type, len, input->writeResults); + PrintOptionalInt(" .writeResults: ", input->writeResults); mcx_log(LOG_DEBUG, "}"); } @@ -221,7 +221,6 @@ static void VectorPortInputDestructor(VectorPortInput * input) { if (input->offset) { mcx_free(input->offset); } if (input->default_) { mcx_free(input->default_); } if (input->initial) { mcx_free(input->initial); } - if (input->writeResults) { mcx_free(input->writeResults); } } static VectorPortInput * VectorPortInputCreate(VectorPortInput * input) { @@ -247,7 +246,7 @@ static VectorPortInput * VectorPortInputCreate(VectorPortInput * input) { input->default_ = NULL; input->initial = NULL; - input->writeResults = NULL; + OPTIONAL_UNSET(input->writeResults); inputElement->Clone = Clone; input->CopyFrom = CopyFrom; diff --git a/src/reader/model/ports/VectorPortInput.h b/src/reader/model/ports/VectorPortInput.h index 417767b..9516e31 100644 --- a/src/reader/model/ports/VectorPortInput.h +++ b/src/reader/model/ports/VectorPortInput.h @@ -46,7 +46,7 @@ struct VectorPortInput { void * default_; void * initial; - int * writeResults; + OPTIONAL_VALUE(int) writeResults; fVectorPortInputCopyFrom CopyFrom; }; From 75a4c3a36e87bf62a04cfee4847760cd36521d6c Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 12 Jul 2021 10:28:25 +0200 Subject: [PATCH 120/295] channel: Make ChannelType a struct --- src/components/comp_fmu.c | 36 ++-- src/components/comp_integrator.c | 4 +- src/components/comp_vector_integrator.c | 4 +- src/core/Component.c | 2 +- src/core/Conversion.c | 80 ++++----- src/core/Databus.c | 31 ++-- src/core/Model.c | 8 +- src/core/channels/Channel.c | 44 ++--- src/core/channels/ChannelInfo.c | 8 +- src/core/channels/ChannelValue.c | 155 ++++++++++-------- src/core/channels/ChannelValue.h | 40 ++++- src/core/connections/Connection.c | 8 +- src/core/connections/ConnectionInfo.c | 12 +- src/core/connections/FilteredConnection.c | 2 +- src/core/connections/filters/DiscreteFilter.c | 4 +- src/core/connections/filters/MemoryFilter.c | 10 +- src/core/parameters/ParameterProxies.c | 6 +- src/fmu/Fmu1Value.c | 2 +- src/fmu/Fmu2Value.c | 16 +- src/fmu/common_fmu1.c | 22 +-- src/fmu/common_fmu2.c | 26 +-- .../components/specific_data/ConstantInput.c | 4 +- .../model/parameters/ArrayParameterInput.c | 4 +- .../model/parameters/ScalarParameterInput.c | 4 +- src/reader/model/ports/ScalarPortInput.c | 4 +- src/reader/model/ports/VectorPortInput.c | 4 +- src/reader/ssp/Parameters.c | 37 +++-- src/reader/ssp/Ports.c | 37 +++-- src/reader/ssp/SpecificData.c | 31 ++-- src/reader/ssp/Util.c | 4 +- src/storage/ChannelStorage.c | 2 +- src/storage/StorageBackendText.c | 2 +- 32 files changed, 363 insertions(+), 290 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index f58fc66..eedea53 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -68,7 +68,7 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { return RETURN_ERROR; } - if (info->type != Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))) { + if (!ChannelTypeEq(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->type), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))); @@ -117,7 +117,7 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { return RETURN_ERROR; } - if (info->type != Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var))) { + if (!ChannelTypeEq(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->type), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))); @@ -399,7 +399,7 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat val->SetChannel(val, info->channel); - if (val->val.type != info->type) { + if (!ChannelTypeEq(val->val.type, info->type)) { ChannelValueInit(&val->val, info->type); } retVal = DatabusSetInReference(db, i, @@ -437,7 +437,7 @@ static McxStatus Fmu2SetupChannelOut(ObjectContainer /* Fmu2Values */ * vals, Da val->SetChannel(val, info->channel); - if (val->val.type != info->type) { + if (!ChannelTypeEq(val->val.type, info->type)) { ChannelValueInit(&val->val, info->type); } retVal = DatabusSetOutReference(db, i, @@ -552,24 +552,24 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab return RETURN_ERROR; } - if (CHANNEL_INTEGER != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo))) { + if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelNameLo); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(CHANNEL_INTEGER), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); + ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); return RETURN_ERROR; } - if (CHANNEL_INTEGER != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi))) { + if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelNameHi); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(CHANNEL_INTEGER), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); + ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); return RETURN_ERROR; } - if (CHANNEL_INTEGER != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize))) { + if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelNameSize); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(CHANNEL_INTEGER), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); + ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); return RETURN_ERROR; } @@ -589,7 +589,7 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab return RETURN_ERROR; } - if (info->type != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))) { + if (!ChannelTypeEq(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->type), @@ -661,24 +661,24 @@ static McxStatus Fmu2ReadChannelOut(ObjectContainer /* Fmu2Value */ * vals, Data return RETURN_ERROR; } - if (CHANNEL_INTEGER != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo))) { + if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelNameLo); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", - ChannelTypeToString(CHANNEL_INTEGER), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); + ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); return RETURN_ERROR; } - if (CHANNEL_INTEGER != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi))) { + if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelNameHi); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", - ChannelTypeToString(CHANNEL_INTEGER), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); + ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); return RETURN_ERROR; } - if (CHANNEL_INTEGER != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize))) { + if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelNameSize); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", - ChannelTypeToString(CHANNEL_INTEGER), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); + ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); return RETURN_ERROR; } @@ -698,7 +698,7 @@ static McxStatus Fmu2ReadChannelOut(ObjectContainer /* Fmu2Value */ * vals, Data return RETURN_ERROR; } - if (info->type != Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var))) { + if (!ChannelTypeEq(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->type), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); diff --git a/src/components/comp_integrator.c b/src/components/comp_integrator.c index 968c261..82fcc8f 100644 --- a/src/components/comp_integrator.c +++ b/src/components/comp_integrator.c @@ -56,13 +56,13 @@ static McxStatus Setup(Component * comp) { CompIntegrator * integrator = (CompIntegrator *) comp; McxStatus retVal = RETURN_OK; - retVal = DatabusSetInReference(comp->GetDatabus(comp), 0, &integrator->deriv, CHANNEL_DOUBLE); + retVal = DatabusSetInReference(comp->GetDatabus(comp), 0, &integrator->deriv, ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; } - retVal = DatabusSetOutReference(comp->GetDatabus(comp), 0, &integrator->state, CHANNEL_DOUBLE); + retVal = DatabusSetOutReference(comp->GetDatabus(comp), 0, &integrator->state, ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 57b6bc1..9002ee3 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -80,7 +80,7 @@ static McxStatus Setup(Component * comp) { size_t startIdx = vInfo->GetStartIndex(vInfo); size_t endIdx = vInfo->GetEndIndex(vInfo); size_t numCh = endIdx - startIdx; - retVal = DatabusSetInRefVector(db, i, startIdx, endIdx, integrator->deriv + nextIdx, CHANNEL_DOUBLE); + retVal = DatabusSetInRefVector(db, i, startIdx, endIdx, integrator->deriv + nextIdx, ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; @@ -94,7 +94,7 @@ static McxStatus Setup(Component * comp) { size_t startIdx = vInfo->GetStartIndex(vInfo); size_t endIdx = vInfo->GetEndIndex(vInfo); size_t numCh = endIdx - startIdx; - retVal = DatabusSetOutRefVector(db, i, startIdx, endIdx, integrator->state + nextIdx, CHANNEL_DOUBLE); + retVal = DatabusSetOutRefVector(db, i, startIdx, endIdx, integrator->state + nextIdx, ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; diff --git a/src/core/Component.c b/src/core/Component.c index 5c595ac..25d188c 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -216,7 +216,7 @@ static McxStatus DefineTimingChannel(Component * comp, const char * chName, cons return RETURN_ERROR; } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, unit, reference, CHANNEL_DOUBLE); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, unit, reference, ChannelTypeDouble); mcx_free(id); diff --git a/src/core/Conversion.c b/src/core/Conversion.c index a684987..18714be 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -42,7 +42,7 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va McxStatus retVal = RETURN_OK; - if (value->type != CHANNEL_DOUBLE && value->type != CHANNEL_INTEGER) { + if (!ChannelTypeEq(value->type, ChannelTypeDouble) && !ChannelTypeEq(value->type, ChannelTypeInteger)) { return RETURN_OK; } @@ -107,7 +107,7 @@ static McxStatus RangeConversionConvert(Conversion * conversion, ChannelValue * McxStatus retVal = RETURN_OK; - if (ChannelValueType(value) != rangeConversion->type) { + if (!ChannelTypeEq(ChannelValueType(value), rangeConversion->type)) { mcx_log(LOG_ERROR, "Range conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(rangeConversion->type)); return RETURN_ERROR; } @@ -134,7 +134,7 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue return RETURN_OK; } - if (min && max && ChannelValueType(min) != ChannelValueType(max)) { + if (min && max && !ChannelTypeEq(ChannelValueType(min), ChannelValueType(max))) { mcx_log(LOG_ERROR, "Range conversion: Types of max value and min value do not match"); return RETURN_ERROR; } @@ -150,8 +150,8 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue conversion->type = ChannelValueType(max); } - if (!(conversion->type == CHANNEL_DOUBLE - || conversion->type == CHANNEL_INTEGER)) { + if (!(ChannelTypeEq(conversion->type, ChannelTypeDouble) + || ChannelTypeEq(conversion->type, ChannelTypeInteger))) { mcx_log(LOG_ERROR, "Range conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -163,7 +163,7 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue } static int RangeConversionIsEmpty(RangeConversion * conversion) { - switch (conversion->type) { + switch (conversion->type.con) { case CHANNEL_DOUBLE: return (!conversion->min || * (double *) ChannelValueReference(conversion->min) == (-DBL_MAX)) && @@ -194,7 +194,7 @@ static RangeConversion * RangeConversionCreate(RangeConversion * rangeConversion rangeConversion->Setup = RangeConversionSetup; rangeConversion->IsEmpty = RangeConversionIsEmpty; - rangeConversion->type = CHANNEL_UNKNOWN; + rangeConversion->type = ChannelTypeUnknown; rangeConversion->min = NULL; rangeConversion->max = NULL; @@ -263,8 +263,8 @@ static McxStatus UnitConversionConvert(Conversion * conversion, ChannelValue * v double val = 0.0; - if (ChannelValueType(value) != CHANNEL_DOUBLE) { - mcx_log(LOG_ERROR, "Unit conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(CHANNEL_DOUBLE)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeDouble)) { + mcx_log(LOG_ERROR, "Unit conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeDouble)); return RETURN_ERROR; } @@ -353,7 +353,7 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal McxStatus retVal = RETURN_OK; - if (value->type != CHANNEL_DOUBLE && value->type != CHANNEL_INTEGER) { + if (!ChannelTypeEq(value->type, ChannelTypeDouble) && !ChannelTypeEq(value->type, ChannelTypeInteger)) { return RETURN_OK; } @@ -442,7 +442,7 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal return RETURN_OK; } - if (factor && offset && ChannelValueType(factor) != ChannelValueType(offset)) { + if (factor && offset && !ChannelTypeEq(ChannelValueType(factor), ChannelValueType(offset))) { mcx_log(LOG_WARNING, "Linear conversion: Types of factor value (%s) and offset value (%s) do not match", ChannelTypeToString(ChannelValueType(factor)), ChannelTypeToString(ChannelValueType(offset))); return RETURN_ERROR; @@ -454,8 +454,8 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal conversion->type = ChannelValueType(offset); } - if (!(conversion->type == CHANNEL_DOUBLE - || conversion->type == CHANNEL_INTEGER)) { + if (!(ChannelTypeEq(conversion->type, ChannelTypeDouble) + || ChannelTypeEq(conversion->type, ChannelTypeInteger))) { mcx_log(LOG_WARNING, "Linear conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -467,7 +467,7 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal } static int LinearConversionIsEmpty(LinearConversion * conversion) { - switch (conversion->type) { + switch (conversion->type.con) { case CHANNEL_DOUBLE: return (!conversion->factor || * (double *) ChannelValueReference(conversion->factor) == 1.0) && @@ -497,7 +497,7 @@ static LinearConversion * LinearConversionCreate(LinearConversion * linearConver linearConversion->Setup = LinearConversionSetup; linearConversion->IsEmpty = LinearConversionIsEmpty; - linearConversion->type = CHANNEL_UNKNOWN; + linearConversion->type = ChannelTypeUnknown; linearConversion->factor = NULL; linearConversion->offset = NULL; @@ -544,72 +544,72 @@ McxStatus ConvertType(ChannelType fromType, ChannelType toType, ChannelValue * v } 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)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeInteger)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeInteger)); return RETURN_ERROR; } - value->type = CHANNEL_DOUBLE; + value->type = ChannelTypeDouble; value->value.d = (double)value->value.i; return RETURN_OK; } static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, ChannelValue * value) { - if (ChannelValueType(value) != CHANNEL_DOUBLE) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(CHANNEL_DOUBLE)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeDouble)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeDouble)); return RETURN_ERROR; } - value->type = CHANNEL_INTEGER; + value->type = ChannelTypeInteger; value->value.i = (int)floor(value->value.d + 0.5); return RETURN_OK; } static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, ChannelValue * value) { - if (ChannelValueType(value) != CHANNEL_BOOL) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(CHANNEL_BOOL)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeBool)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeBool)); return RETURN_ERROR; } - value->type = CHANNEL_DOUBLE; + value->type = ChannelTypeDouble; value->value.d = (value->value.i != 0) ? 1. : 0.; return RETURN_OK; } static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, ChannelValue * value) { - if (ChannelValueType(value) != CHANNEL_DOUBLE) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(CHANNEL_DOUBLE)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeDouble)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeDouble)); return RETURN_ERROR; } - value->type = CHANNEL_BOOL; + value->type = ChannelTypeBool; value->value.i = (value->value.d > 0) ? 1 : 0; return RETURN_OK; } static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, ChannelValue * value) { - if (ChannelValueType(value) != CHANNEL_BOOL) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(CHANNEL_BOOL)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeBool)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeBool)); return RETURN_ERROR; } - value->type = CHANNEL_INTEGER; + value->type = ChannelTypeInteger; value->value.i = (value->value.i != 0) ? 1 : 0; return RETURN_OK; } static McxStatus TypeConversionConvertIntegerBool(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)); + if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeInteger)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeInteger)); return RETURN_ERROR; } - value->type = CHANNEL_BOOL; + value->type = ChannelTypeBool; value->value.i = (value->value.i != 0) ? 1 : 0; return RETURN_OK; @@ -624,19 +624,19 @@ static McxStatus TypeConversionSetup(TypeConversion * typeConversion, ChannelType toType) { Conversion * conversion = (Conversion *) typeConversion; - if (fromType == toType) { + if (ChannelTypeEq(fromType, toType)) { conversion->convert = TypeConversionConvertId; - } else if (fromType == CHANNEL_INTEGER && toType == CHANNEL_DOUBLE) { + } else if (ChannelTypeEq(fromType, ChannelTypeInteger) && ChannelTypeEq(toType, ChannelTypeDouble)) { conversion->convert = TypeConversionConvertIntDouble; - } else if (fromType == CHANNEL_DOUBLE && toType == CHANNEL_INTEGER) { + } else if (ChannelTypeEq(fromType, ChannelTypeDouble) && ChannelTypeEq(toType, ChannelTypeInteger)) { conversion->convert = TypeConversionConvertDoubleInt; - } else if (fromType == CHANNEL_BOOL && toType == CHANNEL_DOUBLE) { + } else if (ChannelTypeEq(fromType, ChannelTypeBool) && ChannelTypeEq(toType, ChannelTypeDouble)) { conversion->convert = TypeConversionConvertBoolDouble; - } else if (fromType == CHANNEL_DOUBLE && toType == CHANNEL_BOOL) { + } else if (ChannelTypeEq(fromType, ChannelTypeDouble) && ChannelTypeEq(toType, ChannelTypeBool)) { conversion->convert = TypeConversionConvertDoubleBool; - } else if (fromType == CHANNEL_BOOL && toType == CHANNEL_INTEGER) { + } else if (ChannelTypeEq(fromType, ChannelTypeBool) && ChannelTypeEq(toType, ChannelTypeInteger)) { conversion->convert = TypeConversionConvertBoolInteger; - } else if (fromType == CHANNEL_INTEGER && toType == CHANNEL_BOOL) { + } else if (ChannelTypeEq(fromType, ChannelTypeInteger) && ChannelTypeEq(toType, ChannelTypeBool)) { conversion->convert = TypeConversionConvertIntegerBool; } else { mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion selected"); diff --git a/src/core/Databus.c b/src/core/Databus.c index 3e1882a..121aaf6 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1151,10 +1151,10 @@ McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * refe return RETURN_ERROR; } - if (CHANNEL_UNKNOWN != type) { + if (ChannelTypeIsValid(type)) { ChannelInfo * info = &((Channel *)out)->info; - if (info->type != type) { - if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) { + if (!ChannelTypeEq(info->type, type)) { + if (ChannelInfoIsBinary(info) && ChannelTypeIsBinary(type)) { // ok } else { mcx_log(LOG_ERROR, "Ports: Set out reference: Port %s has mismatching type %s, given: %s", @@ -1187,7 +1187,7 @@ McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const voi } info = &((Channel *)out)->info; - if (info->type != type) { + if (!ChannelTypeEq(info->type, type)) { mcx_log(LOG_ERROR, "Ports: Set out reference function: Port %s has mismatching type %s, given: %s", ChannelInfoGetName(info), ChannelTypeToString(info->type), ChannelTypeToString(type)); return RETURN_ERROR; @@ -1212,7 +1212,7 @@ McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, mcx_log(LOG_ERROR, "Ports: Set out reference vector: Start index %d bigger than end index %d", startIdx, endIdx); return RETURN_ERROR; } - if (CHANNEL_UNKNOWN == type) { + if (!ChannelTypeIsValid(type)) { mcx_log(LOG_ERROR, "Ports: Set out reference vector: Type of vector needs to be specified"); return RETURN_ERROR; } @@ -1261,7 +1261,7 @@ McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, mcx_log(LOG_ERROR, "Ports: Set out reference vector: Start index %d bigger than end index %d", startIdx, endIdx); return RETURN_ERROR; } - if (CHANNEL_UNKNOWN == type) { + if (!ChannelTypeIsValid(type)) { mcx_log(LOG_ERROR, "Ports: Set out reference vector: Type of vector needs to be specified"); return RETURN_ERROR; } @@ -1287,7 +1287,7 @@ McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, return RETURN_ERROR; } ii = i - startIdx; - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: ref = (const void *) (((double *) reference) + ii); break; @@ -1335,10 +1335,11 @@ McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, return RETURN_ERROR; } - if (CHANNEL_UNKNOWN != type) { + if (ChannelTypeIsValid(type)) { info = &((Channel *)in)->info; - if (info->type != type) { - if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) { + if (!ChannelTypeEq(info->type, type)) { + // TODO: Remove ChannelInfoIsBinary, use ChannelTypeIsBinary instead? + if (ChannelInfoIsBinary(info) && ChannelTypeIsBinary(type)) { // ok } else { mcx_log(LOG_ERROR, "Ports: Set in-reference: Port %s has mismatching type %s, given: %s", @@ -1360,7 +1361,7 @@ McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, s mcx_log(LOG_ERROR, "Ports: Set in reference vector: Start index %d bigger than end index %d", startIdx, endIdx); return RETURN_ERROR; } - if (CHANNEL_UNKNOWN == type) { + if (!ChannelTypeIsValid(type)) { mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector needs to be specified"); return RETURN_ERROR; } @@ -1385,11 +1386,11 @@ McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, s return RETURN_ERROR; } ii = i - startIdx; - if (CHANNEL_DOUBLE == type) { + if (ChannelTypeEq(ChannelTypeDouble, type)) { ref = (void *) (((double *) reference) + ii); - } else if (CHANNEL_INTEGER == type) { + } else if (ChannelTypeEq(ChannelTypeInteger, type)) { ref = (void *) (((int *) reference) + ii); - } else if (CHANNEL_BOOL == type) { + } else if (ChannelTypeEq(ChannelTypeBool, type)) { ref = (void *) (((int *) reference) + ii); } else { mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector not allowed"); @@ -1417,7 +1418,7 @@ McxStatus DatabusSetInRefVectorChannel(Databus * db, size_t channel, mcx_log(LOG_ERROR, "Ports: Set in reference vector: Start index %d bigger than end index %d", startIdx, endIdx); return RETURN_ERROR; } - if (CHANNEL_UNKNOWN == type) { + if (!ChannelTypeIsValid(type)) { mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector needs to be specified"); return RETURN_ERROR; } diff --git a/src/core/Model.c b/src/core/Model.c index 3c7246b..5894488 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -136,15 +136,15 @@ static void UpdateBinaryChannelTypes(Vector * connInfos, Task * task) { 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; + trgInfo->type = ChannelTypeBinaryReference; + srcInfo->type = ChannelTypeBinaryReference; } else { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "Using binary channels for connection %s", buffer); mcx_free(buffer); - trgInfo->type = CHANNEL_BINARY; - srcInfo->type = CHANNEL_BINARY; + trgInfo->type = ChannelTypeBinary; + srcInfo->type = ChannelTypeBinary; } } } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 9643db5..56223fa 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -15,6 +15,7 @@ #include "core/channels/ChannelInfo.h" #include "core/channels/Channel.h" +#include "core/channels/ChannelValue.h" #include "core/channels/Channel_impl.h" #ifdef __cplusplus @@ -58,7 +59,7 @@ static Channel * ChannelCreate(Channel * channel) { channel->isDefinedDuringInit = FALSE; channel->internalValue = NULL; - ChannelValueInit(&channel->value, CHANNEL_UNKNOWN); + ChannelValueInit(&channel->value, ChannelTypeUnknown); channel->Setup = ChannelSetup; channel->IsDefinedDuringInit = ChannelIsDefinedDuringInit; @@ -128,7 +129,7 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel return RETURN_ERROR; } - if (CHANNEL_UNKNOWN != type) { + if (ChannelTypeIsValid(type)) { if (!info) { mcx_log(LOG_ERROR, "Port %s: Set inport reference: Port not set up", ChannelInfoGetLogName(info)); return RETURN_ERROR; @@ -244,7 +245,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } - if (time->startTime < MCX_DEBUG_LOG_TIME && info->type == CHANNEL_DOUBLE) { + if (time->startTime < MCX_DEBUG_LOG_TIME && ChannelTypeEq(info->type, ChannelTypeDouble)) { MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); } @@ -277,7 +278,7 @@ static int ChannelInIsDiscrete(ChannelIn * in) { } static int ChannelInIsConnected(Channel * channel) { - if (channel->info.type != CHANNEL_UNKNOWN && channel->info.connected) { + if (ChannelTypeIsValid(channel->info.type) && channel->info.connected) { return TRUE; } else { ChannelIn * in = (ChannelIn *) channel; @@ -318,7 +319,7 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, // setup unit conversion inInfo = &channel->info; - if (inInfo->type == CHANNEL_DOUBLE) { + if (ChannelTypeEq(inInfo->type, ChannelTypeDouble)) { in->data->unitConversion = (UnitConversion *) object_create(UnitConversion); retVal = in->data->unitConversion->Setup(in->data->unitConversion, unit, @@ -334,7 +335,7 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, } // setup type conversion - if (inInfo->type != type) { + if (!ChannelTypeEq(inInfo->type, type)) { in->data->typeConversion = (TypeConversion *) object_create(TypeConversion); retVal = in->data->typeConversion->Setup(in->data->typeConversion, type, @@ -356,7 +357,7 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { retVal = channel->Setup(channel, info); // call base-class function // types - if (info->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(info->type)) { mcx_log(LOG_ERROR, "Port %s: Setup inport: Unknown type", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -384,7 +385,8 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { // unit conversion is setup when a connection is set // min/max conversions are only used for double types - if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) + if (ChannelTypeEq(info->type, ChannelTypeDouble) + || ChannelTypeEq(info->type, ChannelTypeInteger)) { ChannelValue * min = info->min; ChannelValue * max = info->max; @@ -509,7 +511,7 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * retVal = channel->Setup(channel, info); // call base-class function // default value - if (info->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(info->type)) { mcx_log(LOG_ERROR, "Port %s: Setup outport: Unknown type", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -522,7 +524,8 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * // min/max conversions are only used for double types - if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) + if (ChannelTypeEq(info->type, ChannelTypeDouble) + || ChannelTypeEq(info->type, ChannelTypeInteger)) { out->data->rangeConversion = (RangeConversion *) object_create(RangeConversion); retVal = out->data->rangeConversion->Setup(out->data->rangeConversion, min, max); @@ -624,9 +627,9 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference mcx_log(LOG_ERROR, "Port %s: Set outport reference: Reference already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } - if (CHANNEL_UNKNOWN != type) { - if (info->type != type) { - if (ChannelInfoIsBinary(info) && (type == CHANNEL_BINARY || type == CHANNEL_BINARY_REFERENCE)) { + if (ChannelTypeIsValid(type)) { + if (!ChannelTypeEq(info->type, type)) { + if (ChannelInfoIsBinary(info) && ChannelTypeIsBinary(type)) { // ok } else { mcx_log(LOG_ERROR, "Port %s: Set outport reference: Mismatching types", ChannelInfoGetLogName(info)); @@ -649,8 +652,8 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r } info = &channel->info; - if (CHANNEL_UNKNOWN != type) { - if (info->type != type) { + if (ChannelTypeIsValid(type)) { + if (!ChannelTypeEq(info->type, type)) { mcx_log(LOG_ERROR, "Port %s: Set outport function: Mismatching types", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -714,7 +717,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } else { #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - if (CHANNEL_DOUBLE == info->type) { + if (ChannelTypeEq(ChannelTypeDouble, info->type)) { MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), @@ -731,7 +734,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // Apply conversion - if (info->type == CHANNEL_DOUBLE || info->type == CHANNEL_INTEGER) { + if (ChannelTypeEq(info->type, ChannelTypeDouble) || + ChannelTypeEq(info->type, ChannelTypeInteger)) { ChannelValue * val = &channel->value; // range @@ -767,7 +771,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } - if (CHANNEL_DOUBLE == info->type) { + if (ChannelTypeEq(ChannelTypeDouble, info->type)) { const double * val = NULL; { @@ -882,8 +886,8 @@ static McxStatus ChannelLocalSetReference(ChannelLocal * local, mcx_log(LOG_ERROR, "Port %s: Set local value reference: Reference already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } - if (CHANNEL_UNKNOWN != type) { - if (info->type != type) { + if (ChannelTypeIsValid(type)) { + if (!ChannelTypeEq(info->type, type)) { mcx_log(LOG_ERROR, "Port %s: Set local value reference: Mismatching types", ChannelInfoGetLogName(info)); return RETURN_ERROR; } diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index 7db9b5f..e8c72ab 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -36,7 +36,7 @@ const char * ChannelInfoGetName(const ChannelInfo * info) { } int ChannelInfoIsBinary(const ChannelInfo * info) { - return info->type == CHANNEL_BINARY || info->type == CHANNEL_BINARY_REFERENCE; + return ChannelTypeIsBinary(info->type); } static McxStatus ChannelInfoSetString(char ** dst, const char * src) { @@ -75,7 +75,7 @@ McxStatus ChannelInfoSetUnit(ChannelInfo * info, const char * name) { } McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType type) { - if (info->type != CHANNEL_UNKNOWN) { + if (ChannelTypeIsValid(info->type)) { mcx_log(LOG_ERROR, "Port %s: Type already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -277,7 +277,7 @@ void ChannelInfoDestroy(ChannelInfo * info) { info->channel = NULL; info->initialValueIsExact = FALSE; - info->type = CHANNEL_UNKNOWN; + info->type = ChannelTypeUnknown; info->connected = FALSE; info->writeResult = TRUE; } @@ -300,7 +300,7 @@ McxStatus ChannelInfoInit(ChannelInfo * info) { info->scale = NULL; info->offset = NULL; - info->type = CHANNEL_UNKNOWN; + info->type = ChannelTypeUnknown; info->defaultValue = NULL; info->initialValue = NULL; diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index b227785..cecaf9c 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -16,7 +16,70 @@ extern "C" { #endif /* __cplusplus */ -McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType type) { +ChannelType ChannelTypeUnknown = { CHANNEL_UNKNOWN, NULL}; +ChannelType ChannelTypeInteger = { CHANNEL_INTEGER, NULL}; +ChannelType ChannelTypeDouble = { CHANNEL_DOUBLE, NULL}; +ChannelType ChannelTypeBool = { CHANNEL_BOOL, NULL}; +ChannelType ChannelTypeString = { CHANNEL_STRING, NULL}; +ChannelType ChannelTypeBinary = { CHANNEL_BINARY, NULL}; +ChannelType ChannelTypeBinaryReference = { CHANNEL_BINARY_REFERENCE, NULL}; + +ChannelType ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims) { + ChannelType array; + + if (!inner) { + return ChannelTypeUnknown; + } + + array.con = CHANNEL_ARRAY; + array.ty.a.inner = inner; + array.ty.a.numDims = numDims; + array.ty.a.dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); + if (!array.ty.a.dims) { + return ChannelTypeUnknown; + } + + memcpy(array.ty.a.dims, dims, sizeof(size_t)*numDims); + + return array; +} + +int ChannelTypeIsValid(ChannelType a) { + return a.con != CHANNEL_UNKNOWN; +} + +int ChannelTypeIsScalar(ChannelType a) { + return a.con != CHANNEL_ARRAY; +} + +int ChannelTypeIsArray(ChannelType a) { + return a.con == CHANNEL_ARRAY; +} + +int ChannelTypeIsBinary(ChannelType a) { + return a.con == CHANNEL_BINARY || a.con == CHANNEL_BINARY_REFERENCE; +} + +int ChannelTypeEq(ChannelType a, ChannelType b) { + if (a.con == CHANNEL_ARRAY && b.con == CHANNEL_ARRAY) { + size_t i = 0; + if (a.ty.a.numDims != b.ty.a.numDims) { + return 0; + } + for (i = 0; i < a.ty.a.numDims; i++) { + if (a.ty.a.dims[i] != b.ty.a.dims[i]) { + return 0; + } + } + return 1; + } else if ((a.con == CHANNEL_BINARY || a.con == CHANNEL_BINARY_REFERENCE) && + (b.con == CHANNEL_BINARY || b.con == CHANNEL_BINARY_REFERENCE)) { + } else { + return a.con == b.con; + } +} + +McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType inner) { a->numDims = numDims; a->dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); if (!a->dims) { @@ -24,8 +87,8 @@ McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType type) } memcpy(a->dims, dims, sizeof(size_t) * numDims); - a->type = type; - a->data = (void *) mcx_calloc(ChannelValueTypeSize(type), array_num_elements(a)); + a->type = inner; + a->data = (void *) mcx_calloc(ChannelValueTypeSize(inner), array_num_elements(a)); if (!a->data) { return RETURN_ERROR; } @@ -73,19 +136,19 @@ void ChannelValueInit(ChannelValue * value, ChannelType type) { } void ChannelValueDataDestructor(ChannelValueData * data, ChannelType type) { - if (type == CHANNEL_STRING) { + if (type.con == CHANNEL_STRING) { if (data->s) { mcx_free(data->s); data->s = NULL; } - } else if (type == CHANNEL_BINARY) { + } else if (type.con == CHANNEL_BINARY) { if (data->b.data) { mcx_free(data->b.data); data->b.data = NULL; } - } else if (type == CHANNEL_BINARY_REFERENCE) { + } else if (type.con == CHANNEL_BINARY_REFERENCE) { // do not free references to binary, they are not owned by the ChannelValueData - } else if (type == CHANNEL_ARRAY) { + } else if (type.con == CHANNEL_ARRAY) { if (data->a.dims) { mcx_free(data->a.dims); data->a.dims = NULL; @@ -113,7 +176,7 @@ char * ChannelValueToString(ChannelValue * value) { const uint32_t digits_of_exp = 4; // = (mcx_digits10(DBL_MAX_10_EXP) + 1 /* sign */ char * buffer = NULL; - switch (value->type) { + switch (value->type.con) { case CHANNEL_DOUBLE: length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; buffer = (char *) mcx_malloc(sizeof(char) * length); @@ -172,9 +235,6 @@ char * ChannelValueToString(ChannelValue * value) { } } break; - case CHANNEL_ARRAY: - mcx_log(LOG_ERROR, "TODO: ChannelValueToString unimplemented for CHANNEL_ARRAY"); - return NULL; default: return NULL; } @@ -189,7 +249,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel const uint32_t digits_of_exp = 4; // = (mcx_digits10(DBL_MAX_10_EXP) + 1 /* sign */ const char * doubleFmt = "%*.*E"; - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; if (len < length) { @@ -248,9 +308,6 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel } } break; - case CHANNEL_ARRAY: - mcx_log(LOG_ERROR, "TODO: ChannelValueToString unimplemented for CHANNEL_ARRAY"); - return RETURN_ERROR; default: mcx_log(LOG_DEBUG, "Port value to string: Unknown type"); return RETURN_ERROR; @@ -268,7 +325,7 @@ ChannelType ChannelValueType(ChannelValue * value) { } void * ChannelValueReference(ChannelValue * value) { - if (value->type == CHANNEL_UNKNOWN) { + if (value->type.con == CHANNEL_UNKNOWN) { return NULL; } else { return &value->value; @@ -276,7 +333,7 @@ void * ChannelValueReference(ChannelValue * value) { } void ChannelValueDataInit(ChannelValueData * data, ChannelType type) { - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: data->d = 0.0; break; @@ -308,7 +365,7 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType type) { McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference) { if (!reference) { return RETURN_OK; } // TODO: change to ERROR - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: data->d = * (double *) reference; break; @@ -382,7 +439,7 @@ McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * refere } McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { - if (value->type != source->type) { + if (!ChannelTypeEq(value->type, source->type)) { mcx_log(LOG_ERROR, "Port: Set: Mismatching types. Source type: %s, target type: %s", ChannelTypeToString(source->type), ChannelTypeToString(value->type)); return RETURN_ERROR; @@ -396,7 +453,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { } McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { - switch (value->type) { + switch (value->type.con) { case CHANNEL_DOUBLE: * (double *) reference = value->value.d; break; @@ -471,7 +528,7 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { // TODO: invalid size should be (-1) #ifdef __cplusplus size_t ChannelValueTypeSize(ChannelType type) { - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: return sizeof(ChannelValueData::d); case CHANNEL_INTEGER: @@ -491,7 +548,7 @@ size_t ChannelValueTypeSize(ChannelType type) { #else //__cplusplus size_t ChannelValueTypeSize(ChannelType type) { ChannelValueData value; - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: return sizeof(value.d); case CHANNEL_INTEGER: @@ -511,17 +568,11 @@ size_t ChannelValueTypeSize(ChannelType type) { #endif //__cplusplus int ChannelTypeMatch(ChannelType a, ChannelType b) { - if ((CHANNEL_BINARY == a || CHANNEL_BINARY_REFERENCE == a) && - (CHANNEL_BINARY == b || CHANNEL_BINARY_REFERENCE == b)) { - return 1; - } else { - return a == b; - } - // TODO: Ignores array dimensions + return ChannelTypeEq(a, b); } const char * ChannelTypeToString(ChannelType type) { - switch (type) { + switch (type.con) { case CHANNEL_UNKNOWN: return "Unknown"; case CHANNEL_DOUBLE: @@ -559,49 +610,41 @@ ChannelValue * ChannelValueClone(ChannelValue * value) { int ChannelValueLeq(ChannelValue * val1, ChannelValue * val2) { - if (ChannelValueType(val1) != ChannelValueType(val2)) { + if (!ChannelTypeEq(val1->type, val2->type)) { return 0; } - switch (ChannelValueType(val1)) { + switch (ChannelValueType(val1).con) { case CHANNEL_DOUBLE: return val1->value.d <= val2->value.d; case CHANNEL_INTEGER: return val1->value.i <= val2->value.i; - case CHANNEL_ARRAY: - // TODO: val1 <= val1 <=> val1[i,j] <= val2[i,j] \forall i,j? - mcx_log(LOG_ERROR, "TODO: ChannelValueLeq unimplemented for CHANNEL_ARRAY"); - exit(-1); default: return 0; } } int ChannelValueGeq(ChannelValue * val1, ChannelValue * val2) { - if (ChannelValueType(val1) != ChannelValueType(val2)) { + if (!ChannelTypeEq(val1->type, val2->type)) { return 0; } - switch (ChannelValueType(val1)) { + switch (ChannelValueType(val1).con) { case CHANNEL_DOUBLE: return val1->value.d >= val2->value.d; case CHANNEL_INTEGER: return val1->value.i >= val2->value.i; - case CHANNEL_ARRAY: - // TODO: val1 >= val1 <=> val1[i,j] >= val2[i,j] \forall i,j? - mcx_log(LOG_ERROR, "TODO: ChannelValueGeq unimplemented for CHANNEL_ARRAY"); - exit(-1); default: return 0; } } int ChannelValueEq(ChannelValue * val1, ChannelValue * val2) { - if (ChannelValueType(val1) != ChannelValueType(val2)) { + if (!ChannelTypeEq(val1->type, val2->type)) { return 0; } - switch (ChannelValueType(val1)) { + switch (ChannelValueType(val1).con) { case CHANNEL_DOUBLE: return val1->value.d == val2->value.d; case CHANNEL_BOOL: @@ -609,35 +652,25 @@ int ChannelValueEq(ChannelValue * val1, ChannelValue * val2) { return val1->value.i == val2->value.i; case CHANNEL_STRING: return !strcmp(val1->value.s, val2->value.s); - case CHANNEL_ARRAY: - // TODO: val1 == val1 <=> val1[i,j] == val2[i,j] \forall i,j? - mcx_log(LOG_ERROR, "TODO: ChannelValueEq unimplemented for CHANNEL_ARRAY"); - exit(-1); default: return 0; } } McxStatus ChannelValueAddOffset(ChannelValue * val, ChannelValue * offset) { - if (ChannelValueType(val) != ChannelValueType(offset)) { + if (!ChannelTypeEq(val->type, offset->type)) { mcx_log(LOG_ERROR, "Port: Add offset: Mismatching types. Value type: %s, offset type: %s", ChannelTypeToString(ChannelValueType(val)), ChannelTypeToString(ChannelValueType(offset))); return RETURN_ERROR; } - switch (ChannelValueType(val)) { + switch (ChannelValueType(val).con) { case CHANNEL_DOUBLE: val->value.d += offset->value.d; return RETURN_OK; case CHANNEL_INTEGER: val->value.i += offset->value.i; return RETURN_OK; - case CHANNEL_ARRAY: - // TODO: val matrix, offset matrix - // val matrix, offset scalar - // needs check above relaxed - mcx_log(LOG_ERROR, "TODO: ChannelValueAddOffset unimplemented for CHANNEL_ARRAY"); - exit(-1); default: mcx_log(LOG_ERROR, "Port: Add offset: Type %s not allowed", ChannelTypeToString(ChannelValueType(val))); return RETURN_ERROR; @@ -645,25 +678,19 @@ McxStatus ChannelValueAddOffset(ChannelValue * val, ChannelValue * offset) { } McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { - if (ChannelValueType(val) != ChannelValueType(factor)) { + if (!ChannelTypeEq(val->type, factor->type)) { mcx_log(LOG_ERROR, "Port: Scale: Mismatching types. Value type: %s, factor type: %s", ChannelTypeToString(ChannelValueType(val)), ChannelTypeToString(ChannelValueType(factor))); return RETURN_ERROR; } - switch (ChannelValueType(val)) { + switch (ChannelValueType(val).con) { case CHANNEL_DOUBLE: val->value.d *= factor->value.d; return RETURN_OK; case CHANNEL_INTEGER: val->value.i *= factor->value.i; return RETURN_OK; - case CHANNEL_ARRAY: - // TODO: val matrix, offset scalar - // val matrix, offset matrix: matrix multiplication? - // needs check above relaxed - mcx_log(LOG_ERROR, "TODO: ChannelValueScale unimplemented for CHANNEL_ARRAY"); - exit(-1); default: mcx_log(LOG_ERROR, "Port: Scale: Type %s not allowed", ChannelTypeToString(ChannelValueType(val))); return RETURN_ERROR; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index e1b21c0..c0ba1aa 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -12,13 +12,14 @@ #define MCX_CORE_CHANNELS_CHANNEL_VALUE_H #include "CentralParts.h" +#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ // possible types of values that can be put on channels -typedef enum ChannelType { +typedef enum ChannelTypeConstructor { CHANNEL_UNKNOWN = 0, CHANNEL_DOUBLE = 1, CHANNEL_INTEGER = 2, @@ -27,8 +28,44 @@ typedef enum ChannelType { CHANNEL_BINARY = 5, CHANNEL_BINARY_REFERENCE = 6, CHANNEL_ARRAY = 7, +} ChannelTypeConstructor; + +typedef struct ChannelTypeArrayType { + struct ChannelType * inner; + size_t numDims; + size_t * dims; +} ChannelTypeArrayType; + +typedef struct ChannelType { + ChannelTypeConstructor con; + union { + ChannelTypeArrayType a; + } ty; } ChannelType; +// pre-defined types +extern ChannelType ChannelTypeUnknown; +extern ChannelType ChannelTypeInteger; +extern ChannelType ChannelTypeDouble; +extern ChannelType ChannelTypeBool; +extern ChannelType ChannelTypeString; +extern ChannelType ChannelTypeBinary; +extern ChannelType ChannelTypeBinaryReference; +ChannelType ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims); + +int ChannelTypeIsValid(ChannelType a); +int ChannelTypeIsScalar(ChannelType a); +int ChannelTypeIsArray(ChannelType a); +int ChannelTypeIsBinary(ChannelType a); + +int ChannelTypeEq(ChannelType a, ChannelType b); + +typedef struct MapStringChannelType { + const char * key; + ChannelType * value; +} MapStringChannelType; + + typedef struct { double startTime; double endTime; @@ -51,6 +88,7 @@ typedef struct { void * data; } array; +McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType type); int array_dims_match(array * a, array * b); size_t array_num_elements(array * a); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 3787984..1e6e0d3 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -976,7 +976,7 @@ ChannelFilter * FilterFactory(Connection * connection) { Task * task = model->GetTask(model); int useInputsAtEndTime = task->useInputsAtEndTime; - if (ConnectionInfoGetType(info) == CHANNEL_DOUBLE) { + if (ChannelTypeEq(ConnectionInfoGetType(info), ChannelTypeDouble)) { 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"); } @@ -1061,7 +1061,7 @@ ChannelFilter * FilterFactory(Connection * connection) { filter = (ChannelFilter *) discreteFilter; } - if (NULL == filter && ConnectionInfoGetType(info) == CHANNEL_DOUBLE) { + if (NULL == filter && ChannelTypeEq(ConnectionInfoGetType(info), ChannelTypeDouble)) { // TODO: add a check to avoid filters for non-multirate cases size_t memFilterHist = MemoryFilterHistorySize(info, 0); @@ -1170,7 +1170,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { // If the value is taken from the in channel, the value must be converted. // TODO: It might be a better idea to use the type of the in channel as type of the connection. // Such a change might be more complex to implement. - if (inValue->type != store->type) { + if (!ChannelTypeEq(inValue->type, store->type)) { TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); Conversion * conv = (Conversion *) typeConv; retVal = typeConv->Setup(typeConv, inValue->type, store->type); @@ -1410,7 +1410,7 @@ static Connection * ConnectionCreate(Connection * connection) { connection->isActiveDependency_ = TRUE; - ChannelValueInit(&connection->store_, CHANNEL_UNKNOWN); + ChannelValueInit(&connection->store_, ChannelTypeUnknown); connection->state_ = InCommunicationMode; diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index c5e7fba..298091e 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -34,34 +34,34 @@ ChannelType ConnectionInfoGetType(ConnectionInfo * info) { Databus * db = NULL; ChannelInfo * outInfo = NULL; - if (CHANNEL_UNKNOWN != info->connType_) { + if (ChannelTypeIsValid(info->connType_)) { return info->connType_; } if (NULL == info) { mcx_log(LOG_DEBUG, "ConnectionInfo: GetType: no info available"); - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } source = info->sourceComponent; if (NULL == source) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no source available", buffer); mcx_free(buffer); - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } db = source->GetDatabus(source); if (NULL == db) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no databus available", buffer); mcx_free(buffer); - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } outInfo = DatabusInfoGetChannel(DatabusGetOutInfo(db), info->sourceChannel); if (!outInfo) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no outinfo available", buffer); mcx_free(buffer); - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } info->connType_ = outInfo->type; @@ -158,7 +158,7 @@ McxStatus ConnectionInfoInit(ConnectionInfo * info) { info->hasDiscreteTarget = FALSE; - info->connType_ = CHANNEL_UNKNOWN; + info->connType_ = ChannelTypeUnknown; return RETURN_OK; } diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index cbf73ed..507a314 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -23,7 +23,7 @@ extern "C" { static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionData * data) { data->filter = NULL; - ChannelValueInit(&data->store, CHANNEL_UNKNOWN); + ChannelValueInit(&data->store, ChannelTypeUnknown); return data; } diff --git a/src/core/connections/filters/DiscreteFilter.c b/src/core/connections/filters/DiscreteFilter.c index 279ca3a..a9e25b7 100644 --- a/src/core/connections/filters/DiscreteFilter.c +++ b/src/core/connections/filters/DiscreteFilter.c @@ -69,8 +69,8 @@ static DiscreteFilter * DiscreteFilterCreate(DiscreteFilter * discreteFilter) { discreteFilter->Setup = DiscreteFilterSetup; - ChannelValueInit(&discreteFilter->lastSynchronizationStepValue, CHANNEL_UNKNOWN); - ChannelValueInit(&discreteFilter->lastCouplingStepValue, CHANNEL_UNKNOWN); + ChannelValueInit(&discreteFilter->lastSynchronizationStepValue, ChannelTypeUnknown); + ChannelValueInit(&discreteFilter->lastCouplingStepValue, ChannelTypeUnknown); return discreteFilter; } diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c index b4fddd0..b5bf3b3 100644 --- a/src/core/connections/filters/MemoryFilter.c +++ b/src/core/connections/filters/MemoryFilter.c @@ -39,7 +39,7 @@ static McxStatus MemoryFilterSetValue(ChannelFilter * filter, double time, Chann #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (memoryFilter->valueHistoryWrite[0].type == CHANNEL_DOUBLE) { + if (ChannelTypeEq(memoryFilter->valueHistoryWrite[0].type, ChannelTypeDouble)) { MCX_DEBUG_LOG("MemoryFilter: F SET (%x) (%f, %f)", filter, time, value.d); } else { MCX_DEBUG_LOG("MemoryFilter: F SET (%x) (%f, -)", filter, time); @@ -62,7 +62,7 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub if (double_eq(memoryFilter->timeHistoryRead[i], time)) { #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { 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); @@ -95,7 +95,7 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { 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); @@ -116,7 +116,7 @@ static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time if (double_eq(memoryFilter->timeHistoryRead[i], time)) { #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { 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); @@ -149,7 +149,7 @@ static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (memoryFilter->valueHistoryRead[i].type == CHANNEL_DOUBLE) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { 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); diff --git a/src/core/parameters/ParameterProxies.c b/src/core/parameters/ParameterProxies.c index 107daae..cf491f4 100644 --- a/src/core/parameters/ParameterProxies.c +++ b/src/core/parameters/ParameterProxies.c @@ -25,7 +25,7 @@ static ChannelType ScalarParameterProxyGetType(ScalarParameterProxy * proxy) { return ChannelValueType(&proxy->value_->val); } - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } static Fmu2Value * ScalarParameterProxyGetValue(ScalarParameterProxy * proxy) { @@ -57,7 +57,7 @@ static McxStatus ArrayParameterProxyAddValue(ArrayParameterProxy * proxy, Fmu2Va Fmu2Value * val = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); // check that data types match - if (ChannelValueType(&val->val) != ChannelValueType(&value->val)) { + if (!ChannelTypeEq(ChannelValueType(&val->val), ChannelValueType(&value->val))) { mcx_log(LOG_ERROR, "Adding value of '%s' to array proxy '%s' failed: Data type mismatch", value->name, proxy->name_); return RETURN_ERROR; } @@ -142,7 +142,7 @@ static ChannelType ArrayParameterProxyGetType(ArrayParameterProxy * proxy) { return ChannelValueType(&value->val); } - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } static void ArrayParameterProxyDestructor(ArrayParameterProxy * proxy) { diff --git a/src/fmu/Fmu1Value.c b/src/fmu/Fmu1Value.c index f5cc149..1b1266d 100644 --- a/src/fmu/Fmu1Value.c +++ b/src/fmu/Fmu1Value.c @@ -37,7 +37,7 @@ Fmu1Value * Fmu1ValueCreate(Fmu1Value * v) { v->name = NULL; v->var = NULL; v->channel = NULL; - ChannelValueInit(&v->val, CHANNEL_UNKNOWN); + ChannelValueInit(&v->val, ChannelTypeUnknown); return v; } diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index dc5c8ab..1d71551 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -52,34 +52,34 @@ Fmu2VariableInfo * Fmu2VariableInfoMake(fmi2_import_variable_t * var) { switch (type) { case fmi2_base_type_real: - info->type = CHANNEL_DOUBLE; + info->type = ChannelTypeDouble; min.d = fmi2_import_get_real_variable_min(fmi2_import_get_variable_as_real(var)); minDefined = min.d != -DBL_MAX; max.d = fmi2_import_get_real_variable_max(fmi2_import_get_variable_as_real(var)); maxDefined = max.d != DBL_MAX; break; case fmi2_base_type_int: - info->type = CHANNEL_INTEGER; + info->type = ChannelTypeInteger; min.i = fmi2_import_get_integer_variable_min(fmi2_import_get_variable_as_integer(var)); minDefined = min.i != -INT_MIN; max.i = fmi2_import_get_integer_variable_max(fmi2_import_get_variable_as_integer(var)); maxDefined = max.i != INT_MAX; break; case fmi2_base_type_enum: - info->type = CHANNEL_INTEGER; + info->type = ChannelTypeInteger; min.i = fmi2_import_get_enum_variable_min(fmi2_import_get_variable_as_enum(var)); minDefined = min.i != -INT_MIN; max.i = fmi2_import_get_enum_variable_max(fmi2_import_get_variable_as_enum(var)); maxDefined = max.i != INT_MAX; break; case fmi2_base_type_str: - info->type = CHANNEL_STRING; + info->type = ChannelTypeString; break; case fmi2_base_type_bool: - info->type = CHANNEL_BOOL; + info->type = ChannelTypeBool; break; default: - info->type = CHANNEL_UNKNOWN; + info->type = ChannelTypeUnknown; break; } @@ -121,7 +121,7 @@ static void Fmu2VariableInfoDestructor(Fmu2VariableInfo * info) { } static Fmu2VariableInfo * Fmu2VariableInfoCreate(Fmu2VariableInfo * info) { - info->type = CHANNEL_UNKNOWN; + info->type = ChannelTypeUnknown; info->min = NULL; info->max = NULL; @@ -253,7 +253,7 @@ static Fmu2Value * Fmu2ValueCreate(Fmu2Value * v) { v->channel = NULL; v->info = NULL; - ChannelValueInit(&v->val, CHANNEL_UNKNOWN); + ChannelValueInit(&v->val, ChannelTypeUnknown); return v; } diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index 94bbf97..e9a9e18 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -114,17 +114,17 @@ static fmi1_callback_functions_t fmi1Callbacks = { ChannelType Fmi1TypeToChannelType(fmi1_base_type_enu_t type) { switch (type) { case fmi1_base_type_real: - return CHANNEL_DOUBLE; + return ChannelTypeDouble; case fmi1_base_type_int: - return CHANNEL_INTEGER; + return ChannelTypeInteger; case fmi1_base_type_bool: - return CHANNEL_BOOL; + return ChannelTypeBool; case fmi1_base_type_str: - return CHANNEL_STRING; + return ChannelTypeString; case fmi1_base_type_enum: - return CHANNEL_INTEGER; + return ChannelTypeInteger; default: - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } } @@ -381,14 +381,14 @@ static ObjectContainer * Fmu1ReadArrayParamValues(const char * name, goto cleanup_1; } - if (input->type == CHANNEL_DOUBLE) { - ChannelValueInit(&chVal, CHANNEL_DOUBLE); + if (ChannelTypeEq(input->type, ChannelTypeDouble)) { + ChannelValueInit(&chVal, ChannelTypeDouble); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { return RETURN_ERROR; } } else { // integer - ChannelValueInit(&chVal, CHANNEL_INTEGER); + ChannelValueInit(&chVal, ChannelTypeInteger); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { return RETURN_ERROR; } @@ -550,7 +550,7 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { ChannelValue * const chVal = &fmuVal->val; ChannelType type = ChannelValueType(chVal); - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: { double value = chVal->value.d; @@ -634,7 +634,7 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { ChannelValue * const chVal = &fmuVal->val; ChannelType type = ChannelValueType(chVal); - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: status = fmi1_import_get_real(fmu->fmiImport, vr, 1, (fmi1_real_t *)ChannelValueReference(chVal)); if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index c6c7e3f..9af68d4 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -32,7 +32,7 @@ extern "C" { fmi2_base_type_enu_t ChannelTypeToFmi2Type(ChannelType type) { - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: return fmi2_base_type_real; case CHANNEL_INTEGER: @@ -49,17 +49,17 @@ fmi2_base_type_enu_t ChannelTypeToFmi2Type(ChannelType type) { ChannelType Fmi2TypeToChannelType(fmi2_base_type_enu_t type) { switch (type) { case fmi2_base_type_real: - return CHANNEL_DOUBLE; + return ChannelTypeDouble; case fmi2_base_type_int: - return CHANNEL_INTEGER; + return ChannelTypeInteger; case fmi2_base_type_bool: - return CHANNEL_BOOL; + return ChannelTypeBool; case fmi2_base_type_str: - return CHANNEL_STRING; + return ChannelTypeString; case fmi2_base_type_enum: - return CHANNEL_INTEGER; + return ChannelTypeInteger; default: - return CHANNEL_UNKNOWN; + return ChannelTypeUnknown; } } @@ -389,14 +389,14 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, goto fmu2_read_array_param_values_for_cleanup; } - if (input->type == CHANNEL_DOUBLE) { - ChannelValueInit(&chVal, CHANNEL_DOUBLE); + if (ChannelTypeEq(input->type, ChannelTypeDouble)) { + ChannelValueInit(&chVal, ChannelTypeDouble); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { retVal = RETURN_ERROR; goto fmu2_read_array_param_values_for_cleanup; } } else { // integer - ChannelValueInit(&chVal, CHANNEL_INTEGER); + ChannelValueInit(&chVal, ChannelTypeInteger); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { retVal = RETURN_ERROR; goto fmu2_read_array_param_values_for_cleanup; @@ -683,7 +683,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { ChannelValue * const chVal = &fmuVal->val; ChannelType type = ChannelValueType(chVal); - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: { fmi2_value_reference_t vr[] = {fmuVal->data->vr.scalar}; @@ -792,7 +792,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { ChannelType type = ChannelValueType(chVal); - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; @@ -935,7 +935,7 @@ McxStatus Fmi2RegisterLocalChannelsAtDatabus(ObjectContainer * vals, const char const char * unitName; ChannelType type = ChannelValueType(&val->val); - if (CHANNEL_DOUBLE == type) { + if (ChannelTypeEq(ChannelTypeDouble, type)) { unit = fmi2_import_get_real_variable_unit(fmi2_import_get_variable_as_real(val->data->data.scalar)); } if (unit) { diff --git a/src/reader/model/components/specific_data/ConstantInput.c b/src/reader/model/components/specific_data/ConstantInput.c index c14a354..415cc72 100644 --- a/src/reader/model/components/specific_data/ConstantInput.c +++ b/src/reader/model/components/specific_data/ConstantInput.c @@ -19,7 +19,7 @@ static void ScalarConstantValueInputDestructor(ScalarConstantValueInput * input) } static ScalarConstantValueInput * ScalarConstantValueInputCreate(ScalarConstantValueInput * input) { - input->type = CHANNEL_UNKNOWN; + input->type = ChannelTypeUnknown; input->value.d = 0.0; return input; @@ -32,7 +32,7 @@ static void ArrayConstantValueInputDestructor(ArrayConstantValueInput * input) { } static ArrayConstantValueInput * ArrayConstantValueInputCreate(ArrayConstantValueInput * input) { - input->type = CHANNEL_UNKNOWN; + input->type = ChannelTypeUnknown; input->numValues = 0; input->values = NULL; diff --git a/src/reader/model/parameters/ArrayParameterInput.c b/src/reader/model/parameters/ArrayParameterInput.c index 203c426..d8681b6 100644 --- a/src/reader/model/parameters/ArrayParameterInput.c +++ b/src/reader/model/parameters/ArrayParameterInput.c @@ -29,7 +29,7 @@ static void ArrayParameterInputDestructor(ArrayParameterInput * input) { } if (input->values) { - if (input->type == CHANNEL_STRING) { + if (ChannelTypeEq(input->type, ChannelTypeString)) { size_t i = 0; for (i = 0; i < input->numValues; i++) { @@ -47,7 +47,7 @@ static ArrayParameterInput * ArrayParameterInputCreate(ArrayParameterInput * inp input->numDims = 0; input->dims = NULL; - input->type = CHANNEL_UNKNOWN; + input->type = ChannelTypeUnknown; input->numValues = 0; input->values = NULL; diff --git a/src/reader/model/parameters/ScalarParameterInput.c b/src/reader/model/parameters/ScalarParameterInput.c index 6b217c6..22783d6 100644 --- a/src/reader/model/parameters/ScalarParameterInput.c +++ b/src/reader/model/parameters/ScalarParameterInput.c @@ -19,7 +19,7 @@ static void ScalarParameterInputDestructor(ScalarParameterInput * input) { if (input->unit) { mcx_free(input->unit); } - if (input->type == CHANNEL_STRING && input->value.defined && input->value.value.s) { + if (ChannelTypeEq(input->type, ChannelTypeString) && input->value.defined && input->value.value.s) { mcx_free(input->value.value.s); } } @@ -27,7 +27,7 @@ static void ScalarParameterInputDestructor(ScalarParameterInput * input) { static ScalarParameterInput * ScalarParameterInputCreate(ScalarParameterInput * input) { input->name = NULL; - input->type = CHANNEL_UNKNOWN; + input->type = ChannelTypeUnknown; OPTIONAL_UNSET(input->value); input->unit = NULL; diff --git a/src/reader/model/ports/ScalarPortInput.c b/src/reader/model/ports/ScalarPortInput.c index 38d4b18..96d732e 100644 --- a/src/reader/model/ports/ScalarPortInput.c +++ b/src/reader/model/ports/ScalarPortInput.c @@ -133,7 +133,7 @@ static McxStatus CopyFrom(ScalarPortInput * self, ScalarPortInput * src) { static void PrintOptionalChannelValueData(char * prefix, ChannelType type, OPTIONAL_VALUE(ChannelValueData) value) { - switch(type) { + switch(type.con) { case CHANNEL_DOUBLE: if (value.defined) { mcx_log(LOG_DEBUG, "%s%f,", prefix, value.value.d); @@ -208,7 +208,7 @@ static ScalarPortInput * ScalarPortInputCreate(ScalarPortInput * input) { input->id = NULL; input->unit = NULL; - input->type = CHANNEL_UNKNOWN; + input->type = ChannelTypeUnknown; OPTIONAL_UNSET(input->min); OPTIONAL_UNSET(input->max); diff --git a/src/reader/model/ports/VectorPortInput.c b/src/reader/model/ports/VectorPortInput.c index 5461096..a90b53f 100644 --- a/src/reader/model/ports/VectorPortInput.c +++ b/src/reader/model/ports/VectorPortInput.c @@ -159,7 +159,7 @@ static void PrintVec(char * prefix, ChannelType type, size_t len, void * value) if (value) { for (i = 0; i < len; i++) { - switch(type) { + switch(type.con) { case CHANNEL_DOUBLE: num += sprintf(buffer + num, " %f", ((double*)value)[i]); break; @@ -235,7 +235,7 @@ static VectorPortInput * VectorPortInputCreate(VectorPortInput * input) { input->id = NULL; input->unit = NULL; - input->type = CHANNEL_UNKNOWN; + input->type = ChannelTypeUnknown; input->min = NULL; input->max = NULL; diff --git a/src/reader/ssp/Parameters.c b/src/reader/ssp/Parameters.c index 03963d7..1269e58 100644 --- a/src/reader/ssp/Parameters.c +++ b/src/reader/ssp/Parameters.c @@ -25,6 +25,7 @@ extern "C" { #endif /* __cplusplus */ + typedef struct SSDParameterValue SSDParameterValue; typedef McxStatus(*fSSDParameterValueSetup)(SSDParameterValue * paramValue, xmlNodePtr node, ObjectContainer * units); @@ -614,12 +615,12 @@ static McxStatus CollectParameterValues(xmlNodePtr paramBindingsNode, ObjectCont return RETURN_OK; } -static MapStringInt _typeMappingScalar[] = { - {"Real", CHANNEL_DOUBLE}, - {"Integer", CHANNEL_INTEGER}, - {"Boolean", CHANNEL_BOOL}, - {"String", CHANNEL_STRING}, - {NULL, 0}, +static MapStringChannelType _typeMappingScalar[] = { + {"Real", &ChannelTypeDouble}, + {"Integer", &ChannelTypeInteger}, + {"Boolean", &ChannelTypeBool}, + {"String", &ChannelTypeString}, + {NULL, &ChannelTypeUnknown}, }; static ScalarParameterInput * SSDReadScalarParameter(SSDParameter * parameter) { @@ -671,12 +672,12 @@ static ScalarParameterInput * SSDReadScalarParameter(SSDParameter * parameter) { for (i = 0; _typeMappingScalar[i].key; i++) { if (!strcmp(connectorType, _typeMappingScalar[i].key)) { - input->type = _typeMappingScalar[i].value; + input->type = *_typeMappingScalar[i].value; break; } } - if (input->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(input->type)) { retVal = xml_error_unsupported_node(connectorTypeNode); goto cleanup; } @@ -705,11 +706,11 @@ static ScalarParameterInput * SSDReadScalarParameter(SSDParameter * parameter) { return input; } -static MapStringInt _typeMappingArray[] = { - {"Real", CHANNEL_DOUBLE}, - {"Integer", CHANNEL_INTEGER}, - {"Boolean", CHANNEL_BOOL}, - {NULL, 0}, +static MapStringChannelType _typeMappingArray[] = { + {"Real", &ChannelTypeDouble}, + {"Integer", &ChannelTypeInteger}, + {"Boolean", &ChannelTypeBool}, + {NULL, &ChannelTypeUnknown}, }; static ArrayParameterDimensionInput * SSDReadArrayParameterDimension(xmlNodePtr node) { @@ -749,7 +750,7 @@ static ArrayParameterDimensionInput * SSDReadArrayParameterDimension(xmlNodePtr static McxStatus AllocateMemory(SSDParameter * parameter, ChannelType type, size_t numValues, void ** dest) { size_t size = 0; - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: size = sizeof(double); break; @@ -825,7 +826,7 @@ static McxStatus SSDReadDimensionlessArrayParameter(SSDParameter * parameter, Ar continue; } - switch (input->type) { + switch (input->type.con) { case CHANNEL_DOUBLE: retVal = xml_attr_double(paramTypeNode, "value", (double*)input->values + paramValue->idx1, SSD_MANDATORY); break; @@ -911,7 +912,7 @@ static McxStatus SSDReadDimensionArrayParameter(SSDParameter * parameter, ArrayP index = (paramValue->idx1 - input->dims[0]->start) * (input->dims[1]->end - input->dims[1]->start + 1) + paramValue->idx2 - input->dims[1]->start; } - switch (input->type) { + switch (input->type.con) { case CHANNEL_DOUBLE: retVal = xml_attr_double(paramTypeNode, "value", (double*)input->values + index, SSD_MANDATORY); break; @@ -1020,12 +1021,12 @@ static ArrayParameterInput * SSDReadArrayParameter(SSDParameter * parameter) { for (i = 0; _typeMappingArray[i].key; i++) { if (!strcmp(connectorType, _typeMappingArray[i].key)) { - input->type = _typeMappingArray[i].value; + input->type = *_typeMappingArray[i].value; break; } } - if (input->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(input->type)) { retVal = xml_error_unsupported_node(connectorTypeNode); goto cleanup; } diff --git a/src/reader/ssp/Ports.c b/src/reader/ssp/Ports.c index 8c03a63..c5f03c1 100644 --- a/src/reader/ssp/Ports.c +++ b/src/reader/ssp/Ports.c @@ -17,6 +17,7 @@ #include "reader/model/ports/ScalarPortInput.h" #include "reader/model/ports/VectorPortInput.h" +#include "core/channels/ChannelValue.h" #include "util/string.h" @@ -24,20 +25,20 @@ extern "C" { #endif /* __cplusplus */ -static MapStringInt _typeMapping[] = { - {"Real", CHANNEL_DOUBLE}, - {"Integer", CHANNEL_INTEGER}, - {"Boolean", CHANNEL_BOOL}, - {"String", CHANNEL_STRING}, - {"Binary", CHANNEL_BINARY}, - {NULL, 0}, +static MapStringChannelType _typeMapping[] = { + {"Real", &ChannelTypeDouble}, + {"Integer", &ChannelTypeInteger}, + {"Boolean", &ChannelTypeBool}, + {"String", &ChannelTypeString}, + {"Binary", &ChannelTypeBinary}, + {NULL, &ChannelTypeUnknown}, }; -static MapStringInt _vectorTypeMapping[] = { - {"RealVector", CHANNEL_DOUBLE}, - {"IntegerVector", CHANNEL_INTEGER}, - {"BooleanVector", CHANNEL_BOOL}, - {NULL, 0}, +static MapStringChannelType _vectorTypeMapping[] = { + {"RealVector", &ChannelTypeDouble}, + {"IntegerVector", &ChannelTypeInteger}, + {"BooleanVector", &ChannelTypeBool}, + {NULL, &ChannelTypeUnknown}, }; @@ -136,11 +137,11 @@ VectorPortInput * SSDReadComponentVectorPort(xmlNodePtr connectorNode, const cha for (i = 0; _typeMapping[i].key; i++) { if (!strcmp(typeName, _typeMapping[i].key)) { - vectorPortInput->type = _typeMapping[i].value; + vectorPortInput->type = *_typeMapping[i].value; break; } } - if (vectorPortInput->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(vectorPortInput->type)) { retVal = xml_error_unsupported_node(typeNode); goto cleanup; } @@ -172,7 +173,7 @@ VectorPortInput * SSDReadComponentVectorPort(xmlNodePtr connectorNode, const cha xmlNodePtr vectorNode = NULL; size_t num = 0; - switch (vectorPortInput->type) { + switch (vectorPortInput->type.con) { case CHANNEL_DOUBLE: vectorNode = xml_child(portNode, "RealVector"); break; @@ -350,11 +351,11 @@ ScalarPortInput * SSDReadComponentScalarPort(xmlNodePtr connectorNode, const cha for (i = 0; _typeMapping[i].key; i++) { if (!strcmp(typeName, _typeMapping[i].key)) { - scalarPortInput->type = _typeMapping[i].value; + scalarPortInput->type = *_typeMapping[i].value; break; } } - if (scalarPortInput->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(scalarPortInput->type)) { retVal = xml_error_unsupported_node(typeNode); goto cleanup; } @@ -386,7 +387,7 @@ ScalarPortInput * SSDReadComponentScalarPort(xmlNodePtr connectorNode, const cha xmlNodePtr scalarNode = NULL; size_t num = 0; - switch (scalarPortInput->type) { + switch (scalarPortInput->type.con) { case CHANNEL_DOUBLE: scalarNode = xml_child(portNode, "Real"); break; diff --git a/src/reader/ssp/SpecificData.c b/src/reader/ssp/SpecificData.c index 1af4a25..530693d 100644 --- a/src/reader/ssp/SpecificData.c +++ b/src/reader/ssp/SpecificData.c @@ -17,6 +17,7 @@ #include "reader/model/components/specific_data/VectorIntegratorInput.h" #include "reader/model/components/specific_data/ConstantInput.h" +#include "core/channels/ChannelValue.h" #ifdef __cplusplus extern "C" { @@ -150,12 +151,12 @@ McxStatus SSDReadVectorIntegratorData(xmlNodePtr componentNode, xmlNodePtr speci return RETURN_OK; } -static MapStringInt _scalarConstantTypeMapping[] = { - {"Real", CHANNEL_DOUBLE}, - {"Integer", CHANNEL_INTEGER}, - {"String", CHANNEL_STRING}, - {"Boolean", CHANNEL_BOOL}, - {NULL, CHANNEL_UNKNOWN} +static MapStringChannelType _scalarConstantTypeMapping[] = { + {"Real", &ChannelTypeDouble}, + {"Integer", &ChannelTypeInteger}, + {"String", &ChannelTypeString}, + {"Boolean", &ChannelTypeBool}, + {NULL, &ChannelTypeUnknown} }; static ScalarConstantValueInput * SSDReadScalarConstantValue(xmlNodePtr node) { @@ -176,12 +177,12 @@ static ScalarConstantValueInput * SSDReadScalarConstantValue(xmlNodePtr node) { for (i = 0; _scalarConstantTypeMapping[i].key; i++) { if (!strcmp(xml_node_get_name(node), _scalarConstantTypeMapping[i].key)) { - input->type = _scalarConstantTypeMapping[i].value; + input->type = *_scalarConstantTypeMapping[i].value; break; } } - if (input->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(input->type)) { retVal = xml_error_unsupported_node(node); goto cleanup; } @@ -201,10 +202,10 @@ static ScalarConstantValueInput * SSDReadScalarConstantValue(xmlNodePtr node) { return input; } -static MapStringInt _vectorConstantTypeMapping[] = { - {"RealVector", CHANNEL_DOUBLE}, - {"IntegerVector", CHANNEL_INTEGER}, - {NULL, CHANNEL_UNKNOWN} +static MapStringChannelType _vectorConstantTypeMapping[] = { + {"RealVector", &ChannelTypeDouble}, + {"IntegerVector", &ChannelTypeInteger}, + {NULL, &ChannelTypeUnknown} }; static ArrayConstantValueInput * SSDReadArrayConstantValue(xmlNodePtr node) { @@ -225,18 +226,18 @@ static ArrayConstantValueInput * SSDReadArrayConstantValue(xmlNodePtr node) { for (i = 0; _vectorConstantTypeMapping[i].key; i++) { if (!strcmp(xml_node_get_name(node), _vectorConstantTypeMapping[i].key)) { - input->type = _vectorConstantTypeMapping[i].value; + input->type = *_vectorConstantTypeMapping[i].value; break; } } - if (input->type == CHANNEL_UNKNOWN) { + if (!ChannelTypeIsValid(input->type)) { retVal = xml_error_unsupported_node(node); goto cleanup; } } - switch (input->type) { + switch (input->type.con) { case CHANNEL_DOUBLE: retVal = xml_attr_double_vec(node, "value", &input->numValues, (double**)&input->values, SSD_MANDATORY); break; diff --git a/src/reader/ssp/Util.c b/src/reader/ssp/Util.c index 2c8e76c..6186dc0 100644 --- a/src/reader/ssp/Util.c +++ b/src/reader/ssp/Util.c @@ -747,7 +747,7 @@ McxStatus xml_attr_enum_weak_ptr(xmlNodePtr node, } McxStatus xml_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType type, ChannelValueData * dest, SSDParamMode mode) { - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: return xml_attr_double(node, attribute_name, &dest->d, mode); case CHANNEL_INTEGER: @@ -1209,7 +1209,7 @@ McxStatus xml_attr_vec_len(xmlNodePtr node, const char * attribute_name, Channel goto cleanup; } - switch (type) { + switch (type.con) { case CHANNEL_DOUBLE: ret_status = xml_attr_double_vec(node, attribute_name, &len, (double **) &values, mode); break; diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index cfda2e6..4a8a3ff 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -83,7 +83,7 @@ static McxStatus ChannelStorageSetup(ChannelStorage * channelStore, int fullStor goto cleanup; } - retVal = ChannelInfoSetup(&timeInfo, "Time", "Time", "", GetTimeUnitString(), CHANNEL_DOUBLE, ""); + retVal = ChannelInfoSetup(&timeInfo, "Time", "Time", "", GetTimeUnitString(), ChannelTypeDouble, ""); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Results: Setup port storage: Could not set up time port data"); goto cleanup; diff --git a/src/storage/StorageBackendText.c b/src/storage/StorageBackendText.c index 56c38b0..b7ca92f 100644 --- a/src/storage/StorageBackendText.c +++ b/src/storage/StorageBackendText.c @@ -215,7 +215,7 @@ static McxStatus WriteRow(FILE * file, ChannelValue * values, size_t numChannels if (channel == 0) { // leave out separator at the beginning sep = ""; } - switch (ChannelValueType(&val)) { + switch (ChannelValueType(&val).con) { case CHANNEL_DOUBLE: case CHANNEL_INTEGER: case CHANNEL_BOOL: From ea3030ce5889e3158a32e6ed5633747a12f5a08b Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 13 Jul 2021 15:36:03 +0200 Subject: [PATCH 121/295] channel: Use ChannelType only via references --- src/components/comp_fmu.c | 24 ++-- src/components/comp_integrator.c | 4 +- src/components/comp_vector_integrator.c | 4 +- src/core/Component.c | 2 +- src/core/Conversion.c | 78 ++++++------ src/core/Conversion.h | 8 +- src/core/Databus.c | 33 +++-- src/core/Databus.h | 14 +-- src/core/Model.c | 8 +- src/core/channels/Channel.c | 33 +++-- src/core/channels/Channel.h | 10 +- src/core/channels/ChannelInfo.c | 8 +- src/core/channels/ChannelInfo.h | 7 +- src/core/channels/ChannelValue.c | 119 +++++++++--------- src/core/channels/ChannelValue.h | 38 +++--- src/core/connections/Connection.c | 8 +- src/core/connections/ConnectionInfo.c | 12 +- src/core/connections/ConnectionInfo.h | 4 +- src/core/connections/FilteredConnection.c | 2 +- src/core/connections/filters/DiscreteFilter.c | 6 +- src/core/connections/filters/DiscreteFilter.h | 2 +- src/core/connections/filters/MemoryFilter.c | 12 +- src/core/connections/filters/MemoryFilter.h | 2 +- src/core/parameters/ParameterProxies.c | 8 +- src/core/parameters/ParameterProxies.h | 4 +- src/fmu/Fmu1Value.c | 2 +- src/fmu/Fmu2Value.c | 16 +-- src/fmu/Fmu2Value.h | 2 +- src/fmu/common_fmu1.c | 28 ++--- src/fmu/common_fmu1.h | 2 +- src/fmu/common_fmu2.c | 40 +++--- src/fmu/common_fmu2.h | 2 +- .../components/specific_data/ConstantInput.c | 4 +- .../components/specific_data/ConstantInput.h | 4 +- .../model/parameters/ArrayParameterInput.c | 4 +- .../model/parameters/ArrayParameterInput.h | 2 +- .../model/parameters/ScalarParameterInput.c | 4 +- .../model/parameters/ScalarParameterInput.h | 2 +- src/reader/model/ports/ScalarPortInput.c | 6 +- src/reader/model/ports/ScalarPortInput.h | 2 +- src/reader/model/ports/VectorPortInput.c | 6 +- src/reader/model/ports/VectorPortInput.h | 2 +- src/reader/ssp/Parameters.c | 12 +- src/reader/ssp/Ports.c | 8 +- src/reader/ssp/SpecificData.c | 6 +- src/reader/ssp/Util.c | 10 +- src/reader/ssp/Util.h | 6 +- src/storage/ChannelStorage.c | 2 +- src/storage/StorageBackendText.c | 2 +- 49 files changed, 315 insertions(+), 309 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index eedea53..eb9edd6 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -552,24 +552,24 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab return RETURN_ERROR; } - if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))) { + if (!ChannelTypeEq(&ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelNameLo); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); + ChannelTypeToString(&ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); return RETURN_ERROR; } - if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))) { + if (!ChannelTypeEq(&ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelNameHi); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); + ChannelTypeToString(&ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); return RETURN_ERROR; } - if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))) { + if (!ChannelTypeEq(&ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, channelNameSize); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); + ChannelTypeToString(&ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); return RETURN_ERROR; } @@ -661,24 +661,24 @@ static McxStatus Fmu2ReadChannelOut(ObjectContainer /* Fmu2Value */ * vals, Data return RETURN_ERROR; } - if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))) { + if (!ChannelTypeEq(&ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelNameLo); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", - ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); + ChannelTypeToString(&ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varLo)))); return RETURN_ERROR; } - if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))) { + if (!ChannelTypeEq(&ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelNameHi); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", - ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); + ChannelTypeToString(&ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varHi)))); return RETURN_ERROR; } - if (!ChannelTypeEq(ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))) { + if (!ChannelTypeEq(&ChannelTypeInteger, Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix , channelNameSize); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", - ChannelTypeToString(ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); + ChannelTypeToString(&ChannelTypeInteger), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(varSize)))); return RETURN_ERROR; } diff --git a/src/components/comp_integrator.c b/src/components/comp_integrator.c index 82fcc8f..c05c538 100644 --- a/src/components/comp_integrator.c +++ b/src/components/comp_integrator.c @@ -56,13 +56,13 @@ static McxStatus Setup(Component * comp) { CompIntegrator * integrator = (CompIntegrator *) comp; McxStatus retVal = RETURN_OK; - retVal = DatabusSetInReference(comp->GetDatabus(comp), 0, &integrator->deriv, ChannelTypeDouble); + retVal = DatabusSetInReference(comp->GetDatabus(comp), 0, &integrator->deriv, &ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; } - retVal = DatabusSetOutReference(comp->GetDatabus(comp), 0, &integrator->state, ChannelTypeDouble); + retVal = DatabusSetOutReference(comp->GetDatabus(comp), 0, &integrator->state, &ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 9002ee3..6eaeda6 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -80,7 +80,7 @@ static McxStatus Setup(Component * comp) { size_t startIdx = vInfo->GetStartIndex(vInfo); size_t endIdx = vInfo->GetEndIndex(vInfo); size_t numCh = endIdx - startIdx; - retVal = DatabusSetInRefVector(db, i, startIdx, endIdx, integrator->deriv + nextIdx, ChannelTypeDouble); + retVal = DatabusSetInRefVector(db, i, startIdx, endIdx, integrator->deriv + nextIdx, &ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; @@ -94,7 +94,7 @@ static McxStatus Setup(Component * comp) { size_t startIdx = vInfo->GetStartIndex(vInfo); size_t endIdx = vInfo->GetEndIndex(vInfo); size_t numCh = endIdx - startIdx; - retVal = DatabusSetOutRefVector(db, i, startIdx, endIdx, integrator->state + nextIdx, ChannelTypeDouble); + retVal = DatabusSetOutRefVector(db, i, startIdx, endIdx, integrator->state + nextIdx, &ChannelTypeDouble); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; diff --git a/src/core/Component.c b/src/core/Component.c index 25d188c..5bab659 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -216,7 +216,7 @@ static McxStatus DefineTimingChannel(Component * comp, const char * chName, cons return RETURN_ERROR; } - retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, unit, reference, ChannelTypeDouble); + retVal = DatabusAddRTFactorChannel(comp->data->databus, chName, id, unit, reference, &ChannelTypeDouble); mcx_free(id); diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 18714be..7adc2ab 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -42,7 +42,7 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va McxStatus retVal = RETURN_OK; - if (!ChannelTypeEq(value->type, ChannelTypeDouble) && !ChannelTypeEq(value->type, ChannelTypeInteger)) { + if (!ChannelTypeEq(value->type, &ChannelTypeDouble) && !ChannelTypeEq(value->type, &ChannelTypeInteger)) { return RETURN_OK; } @@ -150,8 +150,8 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue conversion->type = ChannelValueType(max); } - if (!(ChannelTypeEq(conversion->type, ChannelTypeDouble) - || ChannelTypeEq(conversion->type, ChannelTypeInteger))) { + if (!(ChannelTypeEq(conversion->type, &ChannelTypeDouble) + || ChannelTypeEq(conversion->type, &ChannelTypeInteger))) { mcx_log(LOG_ERROR, "Range conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -163,7 +163,7 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue } static int RangeConversionIsEmpty(RangeConversion * conversion) { - switch (conversion->type.con) { + switch (conversion->type->con) { case CHANNEL_DOUBLE: return (!conversion->min || * (double *) ChannelValueReference(conversion->min) == (-DBL_MAX)) && @@ -194,7 +194,7 @@ static RangeConversion * RangeConversionCreate(RangeConversion * rangeConversion rangeConversion->Setup = RangeConversionSetup; rangeConversion->IsEmpty = RangeConversionIsEmpty; - rangeConversion->type = ChannelTypeUnknown; + rangeConversion->type = &ChannelTypeUnknown; rangeConversion->min = NULL; rangeConversion->max = NULL; @@ -263,8 +263,8 @@ static McxStatus UnitConversionConvert(Conversion * conversion, ChannelValue * v double val = 0.0; - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeDouble)) { - mcx_log(LOG_ERROR, "Unit conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeDouble)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeDouble)) { + mcx_log(LOG_ERROR, "Unit conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeDouble)); return RETURN_ERROR; } @@ -353,7 +353,7 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal McxStatus retVal = RETURN_OK; - if (!ChannelTypeEq(value->type, ChannelTypeDouble) && !ChannelTypeEq(value->type, ChannelTypeInteger)) { + if (!ChannelTypeEq(value->type, &ChannelTypeDouble) && !ChannelTypeEq(value->type, &ChannelTypeInteger)) { return RETURN_OK; } @@ -454,8 +454,8 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal conversion->type = ChannelValueType(offset); } - if (!(ChannelTypeEq(conversion->type, ChannelTypeDouble) - || ChannelTypeEq(conversion->type, ChannelTypeInteger))) { + if (!(ChannelTypeEq(conversion->type, &ChannelTypeDouble) + || ChannelTypeEq(conversion->type, &ChannelTypeInteger))) { mcx_log(LOG_WARNING, "Linear conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -467,7 +467,7 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal } static int LinearConversionIsEmpty(LinearConversion * conversion) { - switch (conversion->type.con) { + switch (conversion->type->con) { case CHANNEL_DOUBLE: return (!conversion->factor || * (double *) ChannelValueReference(conversion->factor) == 1.0) && @@ -497,7 +497,7 @@ static LinearConversion * LinearConversionCreate(LinearConversion * linearConver linearConversion->Setup = LinearConversionSetup; linearConversion->IsEmpty = LinearConversionIsEmpty; - linearConversion->type = ChannelTypeUnknown; + linearConversion->type = &ChannelTypeUnknown; linearConversion->factor = NULL; linearConversion->offset = NULL; @@ -511,7 +511,7 @@ OBJECT_CLASS(LinearConversion, Conversion); // ---------------------------------------------------------------------- // Type Conversion -McxStatus ConvertType(ChannelType fromType, ChannelType toType, ChannelValue * value) { +McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue * value) { TypeConversion * typeConv = NULL; Conversion * conv = NULL; @@ -544,72 +544,72 @@ McxStatus ConvertType(ChannelType fromType, ChannelType toType, ChannelValue * v } static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeInteger)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeInteger)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeInteger)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeInteger)); return RETURN_ERROR; } - value->type = ChannelTypeDouble; + value->type = &ChannelTypeDouble; value->value.d = (double)value->value.i; return RETURN_OK; } static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeDouble)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeDouble)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeDouble)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeDouble)); return RETURN_ERROR; } - value->type = ChannelTypeInteger; + value->type = &ChannelTypeInteger; value->value.i = (int)floor(value->value.d + 0.5); return RETURN_OK; } static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeBool)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeBool)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeBool)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeBool)); return RETURN_ERROR; } - value->type = ChannelTypeDouble; + value->type = &ChannelTypeDouble; value->value.d = (value->value.i != 0) ? 1. : 0.; return RETURN_OK; } static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeDouble)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeDouble)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeDouble)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeDouble)); return RETURN_ERROR; } - value->type = ChannelTypeBool; + value->type = &ChannelTypeBool; value->value.i = (value->value.d > 0) ? 1 : 0; return RETURN_OK; } static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeBool)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeBool)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeBool)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeBool)); return RETURN_ERROR; } - value->type = ChannelTypeInteger; + value->type = &ChannelTypeInteger; value->value.i = (value->value.i != 0) ? 1 : 0; return RETURN_OK; } static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), ChannelTypeInteger)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(ChannelTypeInteger)); + if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeInteger)) { + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeInteger)); return RETURN_ERROR; } - value->type = ChannelTypeBool; + value->type = &ChannelTypeBool; value->value.i = (value->value.i != 0) ? 1 : 0; return RETURN_OK; @@ -620,23 +620,23 @@ static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValue * } static McxStatus TypeConversionSetup(TypeConversion * typeConversion, - ChannelType fromType, - ChannelType toType) { + ChannelType * fromType, + ChannelType * toType) { Conversion * conversion = (Conversion *) typeConversion; if (ChannelTypeEq(fromType, toType)) { conversion->convert = TypeConversionConvertId; - } else if (ChannelTypeEq(fromType, ChannelTypeInteger) && ChannelTypeEq(toType, ChannelTypeDouble)) { + } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeDouble)) { conversion->convert = TypeConversionConvertIntDouble; - } else if (ChannelTypeEq(fromType, ChannelTypeDouble) && ChannelTypeEq(toType, ChannelTypeInteger)) { + } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeInteger)) { conversion->convert = TypeConversionConvertDoubleInt; - } else if (ChannelTypeEq(fromType, ChannelTypeBool) && ChannelTypeEq(toType, ChannelTypeDouble)) { + } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeDouble)) { conversion->convert = TypeConversionConvertBoolDouble; - } else if (ChannelTypeEq(fromType, ChannelTypeDouble) && ChannelTypeEq(toType, ChannelTypeBool)) { + } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeBool)) { conversion->convert = TypeConversionConvertDoubleBool; - } else if (ChannelTypeEq(fromType, ChannelTypeBool) && ChannelTypeEq(toType, ChannelTypeInteger)) { + } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeInteger)) { conversion->convert = TypeConversionConvertBoolInteger; - } else if (ChannelTypeEq(fromType, ChannelTypeInteger) && ChannelTypeEq(toType, ChannelTypeBool)) { + } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeBool)) { conversion->convert = TypeConversionConvertIntegerBool; } else { mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion selected"); diff --git a/src/core/Conversion.h b/src/core/Conversion.h index 1f542f2..90ab771 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -47,7 +47,7 @@ typedef struct RangeConversion { fRangeConversionSetup Setup; fRangeConversionIsEmpty IsEmpty; - ChannelType type; + ChannelType * type; ChannelValue * min; ChannelValue * max; @@ -99,7 +99,7 @@ typedef struct LinearConversion { fLinearConversionSetup Setup; fLinearConversionIsEmpty IsEmpty; - ChannelType type; + ChannelType * type; ChannelValue * factor; ChannelValue * offset; @@ -114,7 +114,7 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal typedef struct TypeConversion TypeConversion; -typedef McxStatus (* fTypeConversionSetup)(TypeConversion * conversion, ChannelType fromType, ChannelType toType); +typedef McxStatus (* fTypeConversionSetup)(TypeConversion * conversion, ChannelType * fromType, ChannelType * toType); typedef int (* fTypeConversionIsEmpty)(TypeConversion * conversion); extern const struct ObjectClass _TypeConversion; @@ -126,7 +126,7 @@ struct TypeConversion { fTypeConversionIsEmpty IsEmpty; }; -McxStatus ConvertType(ChannelType fromType, ChannelType toType, ChannelValue * value); +McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue * value); #ifdef __cplusplus diff --git a/src/core/Databus.c b/src/core/Databus.c index 121aaf6..739ef21 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -107,7 +107,7 @@ static Vector * DatabusReadPortInput(PortInput * input) { VectorPortInput * vectorPortInput = input->port.vectorPort; InputElement * vectorPortElement = (InputElement *) vectorPortInput; - ChannelType expectedType = vectorPortInput->type; + ChannelType * expectedType = vectorPortInput->type; size_t expectedLen = 0; if (!vector) { @@ -310,8 +310,7 @@ static Vector * DatabusReadPortInput(PortInput * input) { ChannelInfoSetUnit(&info, "-"); } - ChannelType expectedType = info.type; - + ChannelType * expectedType = info.type; ChannelValue value; ChannelValueInit(&value, expectedType); @@ -1133,7 +1132,7 @@ size_t DatabusGetRTFactorChannelsNum(Databus * db) { } -McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * reference, ChannelType type) { +McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * reference, ChannelType * type) { ChannelOut * out = NULL; if (!db) { @@ -1167,7 +1166,7 @@ McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * refe return out->SetReference(out, reference, type); } -McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const void * reference, ChannelType type) { +McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const void * reference, ChannelType * type) { ChannelOut * out = NULL; ChannelInfo * info = NULL; @@ -1206,7 +1205,7 @@ McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, VectorChannelInfo * vInfo = NULL; size_t i = 0; size_t ii = 0; - ChannelType type = ChannelValueType(value); + ChannelType * type = ChannelValueType(value); if (startIdx > endIdx) { mcx_log(LOG_ERROR, "Ports: Set out reference vector: Start index %d bigger than end index %d", startIdx, endIdx); @@ -1251,7 +1250,7 @@ McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, } McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, const void * reference, ChannelType type) + size_t startIdx, size_t endIdx, const void * reference, ChannelType * type) { VectorChannelInfo * vInfo = NULL; size_t i = 0; @@ -1287,7 +1286,7 @@ McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, return RETURN_ERROR; } ii = i - startIdx; - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: ref = (const void *) (((double *) reference) + ii); break; @@ -1316,7 +1315,7 @@ McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, return RETURN_OK; } -McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, ChannelType type) { +McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, ChannelType * type) { ChannelIn * in = NULL; ChannelInfo * info = NULL; @@ -1352,7 +1351,7 @@ McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, return in->SetReference(in, reference, type); } -McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, size_t endIdx, void * reference, ChannelType type) +McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, size_t endIdx, void * reference, ChannelType * type) { VectorChannelInfo * vInfo = NULL; size_t i = 0; @@ -1386,11 +1385,11 @@ McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, s return RETURN_ERROR; } ii = i - startIdx; - if (ChannelTypeEq(ChannelTypeDouble, type)) { + if (ChannelTypeEq(&ChannelTypeDouble, type)) { ref = (void *) (((double *) reference) + ii); - } else if (ChannelTypeEq(ChannelTypeInteger, type)) { + } else if (ChannelTypeEq(&ChannelTypeInteger, type)) { ref = (void *) (((int *) reference) + ii); - } else if (ChannelTypeEq(ChannelTypeBool, type)) { + } else if (ChannelTypeEq(&ChannelTypeBool, type)) { ref = (void *) (((int *) reference) + ii); } else { mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector not allowed"); @@ -1412,7 +1411,7 @@ McxStatus DatabusSetInRefVectorChannel(Databus * db, size_t channel, VectorChannelInfo * vInfo = NULL; size_t i = 0; size_t ii = 0; - ChannelType type = ChannelValueType(value); + ChannelType * type = ChannelValueType(value); if (startIdx > endIdx) { mcx_log(LOG_ERROR, "Ports: Set in reference vector: Start index %d bigger than end index %d", startIdx, endIdx); @@ -1491,7 +1490,7 @@ static McxStatus DatabusAddLocalChannelInternal(Databus * db, const char * id, const char * unit, const void * reference, - ChannelType type) { + ChannelType * type) { ChannelInfo chInfo = { 0 }; ChannelLocal * local = NULL; Channel * channel = NULL; @@ -1563,7 +1562,7 @@ McxStatus DatabusAddLocalChannel(Databus * db, const char * id, const char * unit, const void * reference, - ChannelType type) { + ChannelType * type) { DatabusData * dbData = db->data; DatabusInfoData * infoData = dbData->localInfo->data; @@ -1592,7 +1591,7 @@ McxStatus DatabusAddRTFactorChannel(Databus * db, const char * id, const char * unit, const void * reference, - ChannelType type) { + ChannelType * type) { DatabusData * dbData = db->data; DatabusInfoData * infoData = dbData->rtfactorInfo->data; diff --git a/src/core/Databus.h b/src/core/Databus.h index 70cda7e..dad4d21 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -86,13 +86,13 @@ size_t DatabusGetRTFactorChannelsNum(struct Databus * db); McxStatus DatabusSetOutReference(struct Databus * db, size_t channel, const void * reference, - ChannelType type); + ChannelType * type); McxStatus DatabusSetOutReferenceFunction(struct Databus * db, size_t channel, const void * reference, - ChannelType type); + ChannelType * type); /** * Connects a variable of type \a type at \a reference to the in channel \a channel @@ -101,7 +101,7 @@ McxStatus DatabusSetOutReferenceFunction(struct Databus * db, * * \return \c RETURN_OK on success, or \c RETURN_ERROR otherwise. */ -McxStatus DatabusSetInReference(struct Databus * db, size_t channel, void * reference, ChannelType type); +McxStatus DatabusSetInReference(struct Databus * db, size_t channel, void * reference, ChannelType * type); /** * Adds a local channel of type \a type at \a reference to the databus \a db. @@ -111,7 +111,7 @@ McxStatus DatabusAddLocalChannel(Databus * db, const char * id, const char * unit, const void * reference, - ChannelType type); + ChannelType * type); /** * Adds a rtfactor channel of type \a type at \a reference to the databus \a db. @@ -121,7 +121,7 @@ McxStatus DatabusAddRTFactorChannel(Databus * db, const char * id, const char * unit, const void * reference, - ChannelType type); + ChannelType * type); /* vector channel functions */ @@ -133,13 +133,13 @@ size_t DatabusGetInVectorChannelsNum(Databus * db); size_t DatabusGetOutVectorChannelsNum(Databus * db); McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, const void * reference, ChannelType type); + size_t startIdx, size_t endIdx, const void * reference, ChannelType * type); McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, size_t startIdx, size_t endIdx, ChannelValue * value); McxStatus DatabusSetInRefVector(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, void * reference, ChannelType type); + size_t startIdx, size_t endIdx, void * reference, ChannelType * type); McxStatus DatabusSetInRefVectorChannel(Databus * db, size_t channel, size_t startIdx, size_t endIdx, ChannelValue * value); diff --git a/src/core/Model.c b/src/core/Model.c index 5894488..8c9a786 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -136,15 +136,15 @@ static void UpdateBinaryChannelTypes(Vector * connInfos, Task * task) { mcx_log(LOG_DEBUG, "Fast binary channel requirements fulfilled for connection %s", buffer); mcx_free(buffer); - trgInfo->type = ChannelTypeBinaryReference; - srcInfo->type = ChannelTypeBinaryReference; + trgInfo->type = &ChannelTypeBinaryReference; + srcInfo->type = &ChannelTypeBinaryReference; } else { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "Using binary channels for connection %s", buffer); mcx_free(buffer); - trgInfo->type = ChannelTypeBinary; - srcInfo->type = ChannelTypeBinary; + trgInfo->type = &ChannelTypeBinary; + srcInfo->type = &ChannelTypeBinary; } } } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 56223fa..58c281b 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -59,7 +59,7 @@ static Channel * ChannelCreate(Channel * channel) { channel->isDefinedDuringInit = FALSE; channel->internalValue = NULL; - ChannelValueInit(&channel->value, ChannelTypeUnknown); + ChannelValueInit(&channel->value, &ChannelTypeUnknown); channel->Setup = ChannelSetup; channel->IsDefinedDuringInit = ChannelIsDefinedDuringInit; @@ -116,7 +116,7 @@ OBJECT_CLASS(ChannelInData, Object); -static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, ChannelType type) { +static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, ChannelType * type) { Channel * ch = (Channel *) in; ChannelInfo * info = &ch->info; @@ -245,7 +245,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } - if (time->startTime < MCX_DEBUG_LOG_TIME && ChannelTypeEq(info->type, ChannelTypeDouble)) { + if (time->startTime < MCX_DEBUG_LOG_TIME && ChannelTypeEq(info->type, &ChannelTypeDouble)) { MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); } @@ -306,8 +306,7 @@ static Connection * ChannelInGetConnection(ChannelIn * in) { } } -static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType type -) { +static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType * type) { Channel * channel = (Channel *) in; ChannelInfo * inInfo = NULL; @@ -319,7 +318,7 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, // setup unit conversion inInfo = &channel->info; - if (ChannelTypeEq(inInfo->type, ChannelTypeDouble)) { + if (ChannelTypeEq(inInfo->type, &ChannelTypeDouble)) { in->data->unitConversion = (UnitConversion *) object_create(UnitConversion); retVal = in->data->unitConversion->Setup(in->data->unitConversion, unit, @@ -385,8 +384,8 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { // unit conversion is setup when a connection is set // min/max conversions are only used for double types - if (ChannelTypeEq(info->type, ChannelTypeDouble) - || ChannelTypeEq(info->type, ChannelTypeInteger)) + if (ChannelTypeEq(info->type, &ChannelTypeDouble) + || ChannelTypeEq(info->type, &ChannelTypeInteger)) { ChannelValue * min = info->min; ChannelValue * max = info->max; @@ -524,8 +523,8 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * // min/max conversions are only used for double types - if (ChannelTypeEq(info->type, ChannelTypeDouble) - || ChannelTypeEq(info->type, ChannelTypeInteger)) + if (ChannelTypeEq(info->type, &ChannelTypeDouble) + || ChannelTypeEq(info->type, &ChannelTypeInteger)) { out->data->rangeConversion = (RangeConversion *) object_create(RangeConversion); retVal = out->data->rangeConversion->Setup(out->data->rangeConversion, min, max); @@ -609,7 +608,7 @@ static int ChannelOutIsConnected(Channel * channel) { return FALSE; } -static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference, ChannelType type) { +static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference, ChannelType * type) { Channel * channel = (Channel *) out; ChannelInfo * info = NULL; @@ -643,7 +642,7 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference return RETURN_OK; } -static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * reference, ChannelType type) { +static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * reference, ChannelType * type) { Channel * channel = (Channel *) out; ChannelInfo * info = NULL; if (!out) { @@ -717,7 +716,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } else { #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - if (ChannelTypeEq(ChannelTypeDouble, info->type)) { + if (ChannelTypeEq(&ChannelTypeDouble, info->type)) { MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), @@ -734,8 +733,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // Apply conversion - if (ChannelTypeEq(info->type, ChannelTypeDouble) || - ChannelTypeEq(info->type, ChannelTypeInteger)) { + if (ChannelTypeEq(info->type, &ChannelTypeDouble) || + ChannelTypeEq(info->type, &ChannelTypeInteger)) { ChannelValue * val = &channel->value; // range @@ -771,7 +770,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } - if (ChannelTypeEq(ChannelTypeDouble, info->type)) { + if (ChannelTypeEq(&ChannelTypeDouble, info->type)) { const double * val = NULL; { @@ -872,7 +871,7 @@ static int ChannelLocalIsValid(Channel * channel) { // TODO: Unify with ChannelOutsetReference (similar code) static McxStatus ChannelLocalSetReference(ChannelLocal * local, const void * reference, - ChannelType type) { + ChannelType * type) { Channel * channel = (Channel *) local; ChannelInfo * info = NULL; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index 9847dc1..e022dfb 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -113,7 +113,7 @@ typedef McxStatus (* fChannelInSetup)(ChannelIn * in, struct ChannelInfo * info) typedef McxStatus (* fChannelInSetReference) (ChannelIn * in, void * reference, - ChannelType type); + ChannelType * type); typedef struct ConnectionInfo * (* fChannelInGetConnectionInfo)(ChannelIn * in); @@ -122,7 +122,7 @@ typedef struct Connection * (* fChannelInGetConnection)(ChannelIn * in); typedef McxStatus (* fChannelInSetConnection)(ChannelIn * in, struct Connection * connection, const char * unit, - ChannelType type); + ChannelType * type); typedef int (*fChannelInIsDiscrete)(ChannelIn * in); typedef void (*fChannelInSetDiscrete)(ChannelIn * in); @@ -184,10 +184,10 @@ typedef McxStatus (* fChannelOutSetup)(ChannelOut * out, typedef McxStatus (* fChannelOutSetReference) (ChannelOut * out, const void * reference, - ChannelType type); + ChannelType * type); typedef McxStatus (* fChannelOutSetReferenceFunction) (ChannelOut * out, const proc * reference, - ChannelType type); + ChannelType * type); typedef McxStatus (* fChannelOutRegisterConnection)(struct ChannelOut * out, struct Connection * connection); @@ -252,7 +252,7 @@ typedef McxStatus (* fChannelLocalSetup)(ChannelLocal * local, struct ChannelInf typedef McxStatus (* fChannelLocalSetReference) (ChannelLocal * local, const void * reference, - ChannelType type); + ChannelType * type); extern const struct ObjectClass _ChannelLocal; diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index e8c72ab..14e0fbe 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -74,7 +74,7 @@ McxStatus ChannelInfoSetUnit(ChannelInfo * info, const char * name) { return ChannelInfoSetString(&info->unitString, name); } -McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType type) { +McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType * type) { if (ChannelTypeIsValid(info->type)) { mcx_log(LOG_ERROR, "Port %s: Type already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; @@ -105,7 +105,7 @@ McxStatus ChannelInfoSetup(ChannelInfo * info, const char * nameInModel, const char * descr, const char * unit, - ChannelType type, + ChannelType * type, const char * id) { if (name && RETURN_OK != ChannelInfoSetName(info, name)) { mcx_log(LOG_DEBUG, "Port %s: Could not set name", name); @@ -277,7 +277,7 @@ void ChannelInfoDestroy(ChannelInfo * info) { info->channel = NULL; info->initialValueIsExact = FALSE; - info->type = ChannelTypeUnknown; + info->type = &ChannelTypeUnknown; info->connected = FALSE; info->writeResult = TRUE; } @@ -300,7 +300,7 @@ McxStatus ChannelInfoInit(ChannelInfo * info) { info->scale = NULL; info->offset = NULL; - info->type = ChannelTypeUnknown; + info->type = &ChannelTypeUnknown; info->defaultValue = NULL; info->initialValue = NULL; diff --git a/src/core/channels/ChannelInfo.h b/src/core/channels/ChannelInfo.h index a995413..ab26336 100644 --- a/src/core/channels/ChannelInfo.h +++ b/src/core/channels/ChannelInfo.h @@ -44,10 +44,11 @@ typedef struct ChannelInfo { ChannelValue * max; ChannelValue * scale; ChannelValue * offset; + ChannelValue * defaultValue; ChannelValue * initialValue; - ChannelType type; + ChannelType * type; int connected; int initialValueIsExact; @@ -66,7 +67,7 @@ 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 ChannelInfoSetType(ChannelInfo * info, ChannelType * type); McxStatus ChannelInfoSetVector(ChannelInfo * info, VectorChannelInfo * vector); int ChannelInfoIsBinary(const ChannelInfo * info); @@ -76,7 +77,7 @@ McxStatus ChannelInfoSetup(ChannelInfo * info, const char * nameInModel, const char * descr, const char * unit, - ChannelType type, + ChannelType * type, const char * id); McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other); diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index cecaf9c..5c0e6f2 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -24,62 +24,67 @@ ChannelType ChannelTypeString = { CHANNEL_STRING, NULL}; ChannelType ChannelTypeBinary = { CHANNEL_BINARY, NULL}; ChannelType ChannelTypeBinaryReference = { CHANNEL_BINARY_REFERENCE, NULL}; -ChannelType ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims) { - ChannelType array; +ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims) { + ChannelType * array = NULL; if (!inner) { - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } - array.con = CHANNEL_ARRAY; - array.ty.a.inner = inner; - array.ty.a.numDims = numDims; - array.ty.a.dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); - if (!array.ty.a.dims) { - return ChannelTypeUnknown; + array = (ChannelType *) mcx_malloc(sizeof(ChannelType)); + if (!array) { + return &ChannelTypeUnknown; } - memcpy(array.ty.a.dims, dims, sizeof(size_t)*numDims); + array->con = CHANNEL_ARRAY; + array->ty.a.inner = inner; + array->ty.a.numDims = numDims; + array->ty.a.dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); + if (!array->ty.a.dims) { + return &ChannelTypeUnknown; + } + + memcpy(array->ty.a.dims, dims, sizeof(size_t)*numDims); return array; } -int ChannelTypeIsValid(ChannelType a) { - return a.con != CHANNEL_UNKNOWN; +int ChannelTypeIsValid(ChannelType * a) { + return a->con != CHANNEL_UNKNOWN; } -int ChannelTypeIsScalar(ChannelType a) { - return a.con != CHANNEL_ARRAY; +int ChannelTypeIsScalar(ChannelType * a) { + return a->con != CHANNEL_ARRAY; } -int ChannelTypeIsArray(ChannelType a) { - return a.con == CHANNEL_ARRAY; +int ChannelTypeIsArray(ChannelType * a) { + return a->con == CHANNEL_ARRAY; } -int ChannelTypeIsBinary(ChannelType a) { - return a.con == CHANNEL_BINARY || a.con == CHANNEL_BINARY_REFERENCE; +int ChannelTypeIsBinary(ChannelType * a) { + return a->con == CHANNEL_BINARY || a->con == CHANNEL_BINARY_REFERENCE; } -int ChannelTypeEq(ChannelType a, ChannelType b) { - if (a.con == CHANNEL_ARRAY && b.con == CHANNEL_ARRAY) { +int ChannelTypeEq(ChannelType * a, ChannelType * b) { + if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { size_t i = 0; - if (a.ty.a.numDims != b.ty.a.numDims) { + if (a->ty.a.numDims != b->ty.a.numDims) { return 0; } - for (i = 0; i < a.ty.a.numDims; i++) { - if (a.ty.a.dims[i] != b.ty.a.dims[i]) { + for (i = 0; i < a->ty.a.numDims; i++) { + if (a->ty.a.dims[i] != b->ty.a.dims[i]) { return 0; } } return 1; - } else if ((a.con == CHANNEL_BINARY || a.con == CHANNEL_BINARY_REFERENCE) && - (b.con == CHANNEL_BINARY || b.con == CHANNEL_BINARY_REFERENCE)) { + } else if ((a->con == CHANNEL_BINARY || a->con == CHANNEL_BINARY_REFERENCE) && + (b->con == CHANNEL_BINARY || b->con == CHANNEL_BINARY_REFERENCE)) { } else { - return a.con == b.con; + return a->con == b->con; } } -McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType inner) { +McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * inner) { a->numDims = numDims; a->dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); if (!a->dims) { @@ -130,25 +135,25 @@ size_t array_num_elements(array * a) { return n; } -void ChannelValueInit(ChannelValue * value, ChannelType type) { +void ChannelValueInit(ChannelValue * value, ChannelType * type) { value->type = type; ChannelValueDataInit(&value->value, type); } -void ChannelValueDataDestructor(ChannelValueData * data, ChannelType type) { - if (type.con == CHANNEL_STRING) { +void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type) { + if (type->con == CHANNEL_STRING) { if (data->s) { mcx_free(data->s); data->s = NULL; } - } else if (type.con == CHANNEL_BINARY) { + } else if (type->con == CHANNEL_BINARY) { if (data->b.data) { mcx_free(data->b.data); data->b.data = NULL; } - } else if (type.con == CHANNEL_BINARY_REFERENCE) { + } else if (type->con == CHANNEL_BINARY_REFERENCE) { // do not free references to binary, they are not owned by the ChannelValueData - } else if (type.con == CHANNEL_ARRAY) { + } else if (type->con == CHANNEL_ARRAY) { if (data->a.dims) { mcx_free(data->a.dims); data->a.dims = NULL; @@ -157,6 +162,8 @@ void ChannelValueDataDestructor(ChannelValueData * data, ChannelType type) { mcx_free(data->a.data); data->a.data = NULL; } + // other ChannelTypes are static + mcx_free(type); } } @@ -176,7 +183,7 @@ char * ChannelValueToString(ChannelValue * value) { const uint32_t digits_of_exp = 4; // = (mcx_digits10(DBL_MAX_10_EXP) + 1 /* sign */ char * buffer = NULL; - switch (value->type.con) { + switch (value->type->con) { case CHANNEL_DOUBLE: length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; buffer = (char *) mcx_malloc(sizeof(char) * length); @@ -242,14 +249,14 @@ char * ChannelValueToString(ChannelValue * value) { return buffer; } -McxStatus ChannelValueDataToStringBuffer(const 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; const uint32_t digits_of_exp = 4; // = (mcx_digits10(DBL_MAX_10_EXP) + 1 /* sign */ const char * doubleFmt = "%*.*E"; - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; if (len < length) { @@ -320,20 +327,20 @@ McxStatus ChannelValueToStringBuffer(const ChannelValue * value, char * buffer, return ChannelValueDataToStringBuffer(&value->value, value->type, buffer, len); } -ChannelType ChannelValueType(ChannelValue * value) { +ChannelType * ChannelValueType(ChannelValue * value) { return value->type; } void * ChannelValueReference(ChannelValue * value) { - if (value->type.con == CHANNEL_UNKNOWN) { + if (value->type->con == CHANNEL_UNKNOWN) { return NULL; } else { return &value->value; } } -void ChannelValueDataInit(ChannelValueData * data, ChannelType type) { - switch (type.con) { +void ChannelValueDataInit(ChannelValueData * data, ChannelType * type) { + switch (type->con) { case CHANNEL_DOUBLE: data->d = 0.0; break; @@ -362,10 +369,10 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType type) { } } -McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference) { +McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType * type, const void * reference) { if (!reference) { return RETURN_OK; } // TODO: change to ERROR - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: data->d = * (double *) reference; break; @@ -453,7 +460,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { } McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { - switch (value->type.con) { + switch (value->type->con) { case CHANNEL_DOUBLE: * (double *) reference = value->value.d; break; @@ -527,8 +534,8 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { // TODO: invalid size should be (-1) #ifdef __cplusplus -size_t ChannelValueTypeSize(ChannelType type) { - switch (type.con) { +size_t ChannelValueTypeSize(ChannelType * type) { + switch (type->con) { case CHANNEL_DOUBLE: return sizeof(ChannelValueData::d); case CHANNEL_INTEGER: @@ -546,9 +553,9 @@ size_t ChannelValueTypeSize(ChannelType type) { return 0; } #else //__cplusplus -size_t ChannelValueTypeSize(ChannelType type) { +size_t ChannelValueTypeSize(ChannelType * type) { ChannelValueData value; - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: return sizeof(value.d); case CHANNEL_INTEGER: @@ -567,12 +574,12 @@ size_t ChannelValueTypeSize(ChannelType type) { } #endif //__cplusplus -int ChannelTypeMatch(ChannelType a, ChannelType b) { +int ChannelTypeMatch(ChannelType * a, ChannelType * b) { return ChannelTypeEq(a, b); } -const char * ChannelTypeToString(ChannelType type) { - switch (type.con) { +const char * ChannelTypeToString(ChannelType * type) { + switch (type->con) { case CHANNEL_UNKNOWN: return "Unknown"; case CHANNEL_DOUBLE: @@ -614,7 +621,7 @@ int ChannelValueLeq(ChannelValue * val1, ChannelValue * val2) { return 0; } - switch (ChannelValueType(val1).con) { + switch (ChannelValueType(val1)->con) { case CHANNEL_DOUBLE: return val1->value.d <= val2->value.d; case CHANNEL_INTEGER: @@ -629,7 +636,7 @@ int ChannelValueGeq(ChannelValue * val1, ChannelValue * val2) { return 0; } - switch (ChannelValueType(val1).con) { + switch (ChannelValueType(val1)->con) { case CHANNEL_DOUBLE: return val1->value.d >= val2->value.d; case CHANNEL_INTEGER: @@ -644,7 +651,7 @@ int ChannelValueEq(ChannelValue * val1, ChannelValue * val2) { return 0; } - switch (ChannelValueType(val1).con) { + switch (ChannelValueType(val1)->con) { case CHANNEL_DOUBLE: return val1->value.d == val2->value.d; case CHANNEL_BOOL: @@ -664,7 +671,7 @@ McxStatus ChannelValueAddOffset(ChannelValue * val, ChannelValue * offset) { return RETURN_ERROR; } - switch (ChannelValueType(val).con) { + switch (ChannelValueType(val)->con) { case CHANNEL_DOUBLE: val->value.d += offset->value.d; return RETURN_OK; @@ -684,7 +691,7 @@ McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { return RETURN_ERROR; } - switch (ChannelValueType(val).con) { + switch (ChannelValueType(val)->con) { case CHANNEL_DOUBLE: val->value.d *= factor->value.d; return RETURN_OK; @@ -703,7 +710,7 @@ void ChannelValueDestroy(ChannelValue ** value) { *value = NULL; } -ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType type) { +ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType * type) { ChannelValue ** array = NULL; size_t size = ChannelValueTypeSize(type); diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index c0ba1aa..1830d0b 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -51,14 +51,14 @@ extern ChannelType ChannelTypeBool; extern ChannelType ChannelTypeString; extern ChannelType ChannelTypeBinary; extern ChannelType ChannelTypeBinaryReference; -ChannelType ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims); +ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims); -int ChannelTypeIsValid(ChannelType a); -int ChannelTypeIsScalar(ChannelType a); -int ChannelTypeIsArray(ChannelType a); -int ChannelTypeIsBinary(ChannelType a); +int ChannelTypeIsValid(ChannelType * a); +int ChannelTypeIsScalar(ChannelType * a); +int ChannelTypeIsArray(ChannelType * a); +int ChannelTypeIsBinary(ChannelType * a); -int ChannelTypeEq(ChannelType a, ChannelType b); +int ChannelTypeEq(ChannelType * a, ChannelType * b); typedef struct MapStringChannelType { const char * key; @@ -84,11 +84,11 @@ typedef struct { typedef struct { size_t numDims; size_t * dims; - ChannelType type; + ChannelType * type; void * data; } array; -McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType type); +McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * type); int array_dims_match(array * a, array * b); size_t array_num_elements(array * a); @@ -103,40 +103,40 @@ typedef union ChannelValueData { } ChannelValueData; typedef struct ChannelValue { - ChannelType type; + ChannelType * type; ChannelValueData value; } ChannelValue; -void ChannelValueInit(ChannelValue * value, ChannelType type); +void ChannelValueInit(ChannelValue * value, ChannelType * type); void ChannelValueDestructor(ChannelValue * value); char * ChannelValueToString(ChannelValue * value); -McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, ChannelType type, 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); +ChannelType * ChannelValueType(ChannelValue * value); void * ChannelValueReference(ChannelValue * value); -void ChannelValueDataDestructor(ChannelValueData * data, ChannelType type); -void ChannelValueDataInit(ChannelValueData * data, ChannelType type); -McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType type, const void * reference); +void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type); +void ChannelValueDataInit(ChannelValueData * data, ChannelType * type); +McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType * type, const void * reference); McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * reference); McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference); McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); -size_t ChannelValueTypeSize(ChannelType type); -int ChannelTypeMatch(ChannelType a, ChannelType b); +size_t ChannelValueTypeSize(ChannelType * type); +int ChannelTypeMatch(ChannelType * a, ChannelType * b); void ChannelValueDestroy(ChannelValue ** value); -ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType type); +ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType * type); /* * Returns a string representation of ChannelType for use in log * messages. */ -const char * ChannelTypeToString(ChannelType type); +const char * ChannelTypeToString(ChannelType * type); /* * Creates a copy of value. Allocates memory if needed, e.g. when diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 1e6e0d3..b914f2d 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -941,7 +941,7 @@ static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { return size + model->config->memFilterHistoryExtra; } -static MemoryFilter * SetMemoryFilter(int reverseSearch, ChannelType sourceType, size_t historySize) { +static MemoryFilter * SetMemoryFilter(int reverseSearch, ChannelType * sourceType, size_t historySize) { McxStatus retVal = RETURN_OK; MemoryFilter * filter = (MemoryFilter *)object_create(MemoryFilter); @@ -976,7 +976,7 @@ ChannelFilter * FilterFactory(Connection * connection) { Task * task = model->GetTask(model); int useInputsAtEndTime = task->useInputsAtEndTime; - if (ChannelTypeEq(ConnectionInfoGetType(info), ChannelTypeDouble)) { + if (ChannelTypeEq(ConnectionInfoGetType(info), &ChannelTypeDouble)) { 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"); } @@ -1061,7 +1061,7 @@ ChannelFilter * FilterFactory(Connection * connection) { filter = (ChannelFilter *) discreteFilter; } - if (NULL == filter && ChannelTypeEq(ConnectionInfoGetType(info), ChannelTypeDouble)) { + if (NULL == filter && ChannelTypeEq(ConnectionInfoGetType(info), &ChannelTypeDouble)) { // TODO: add a check to avoid filters for non-multirate cases size_t memFilterHist = MemoryFilterHistorySize(info, 0); @@ -1410,7 +1410,7 @@ static Connection * ConnectionCreate(Connection * connection) { connection->isActiveDependency_ = TRUE; - ChannelValueInit(&connection->store_, ChannelTypeUnknown); + ChannelValueInit(&connection->store_, &ChannelTypeUnknown); connection->state_ = InCommunicationMode; diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index 298091e..606fdb6 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -28,7 +28,7 @@ void ConnectionInfoSetDecoupled(ConnectionInfo * info) { info->isDecoupled_ = TRUE; } -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; @@ -40,28 +40,28 @@ ChannelType ConnectionInfoGetType(ConnectionInfo * info) { if (NULL == info) { mcx_log(LOG_DEBUG, "ConnectionInfo: GetType: no info available"); - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } source = info->sourceComponent; if (NULL == source) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no source available", buffer); mcx_free(buffer); - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } db = source->GetDatabus(source); if (NULL == db) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no databus available", buffer); mcx_free(buffer); - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } outInfo = DatabusInfoGetChannel(DatabusGetOutInfo(db), info->sourceChannel); if (!outInfo) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_DEBUG, "ConnectionInfo '%s': GetType: no outinfo available", buffer); mcx_free(buffer); - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } info->connType_ = outInfo->type; @@ -158,7 +158,7 @@ McxStatus ConnectionInfoInit(ConnectionInfo * info) { info->hasDiscreteTarget = FALSE; - info->connType_ = ChannelTypeUnknown; + info->connType_ = &ChannelTypeUnknown; return RETURN_OK; } diff --git a/src/core/connections/ConnectionInfo.h b/src/core/connections/ConnectionInfo.h index ec262c9..23cbff0 100644 --- a/src/core/connections/ConnectionInfo.h +++ b/src/core/connections/ConnectionInfo.h @@ -38,7 +38,7 @@ typedef struct ConnectionInfo { int hasDiscreteTarget; - ChannelType connType_; + ChannelType * connType_; InterExtrapolatingType isInterExtrapolating; @@ -54,7 +54,7 @@ typedef struct ConnectionInfo { McxStatus ConnectionInfoInit(ConnectionInfo * info); -ChannelType ConnectionInfoGetType(ConnectionInfo * info); +ChannelType * ConnectionInfoGetType(ConnectionInfo * info); int ConnectionInfoIsDecoupled(ConnectionInfo * info); void ConnectionInfoSetDecoupled(ConnectionInfo * info); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 507a314..e142869 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -23,7 +23,7 @@ extern "C" { static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionData * data) { data->filter = NULL; - ChannelValueInit(&data->store, ChannelTypeUnknown); + ChannelValueInit(&data->store, &ChannelTypeUnknown); return data; } diff --git a/src/core/connections/filters/DiscreteFilter.c b/src/core/connections/filters/DiscreteFilter.c index a9e25b7..42bdb84 100644 --- a/src/core/connections/filters/DiscreteFilter.c +++ b/src/core/connections/filters/DiscreteFilter.c @@ -46,7 +46,7 @@ static McxStatus DiscreteFilterEnterCommunicationMode(ChannelFilter * filter, do return RETURN_OK; } -static McxStatus DiscreteFilterSetup(DiscreteFilter * filter, ChannelType type) { +static McxStatus DiscreteFilterSetup(DiscreteFilter * filter, ChannelType * type) { ChannelValueInit(&filter->lastSynchronizationStepValue, type); ChannelValueInit(&filter->lastCouplingStepValue, type); @@ -69,8 +69,8 @@ static DiscreteFilter * DiscreteFilterCreate(DiscreteFilter * discreteFilter) { discreteFilter->Setup = DiscreteFilterSetup; - ChannelValueInit(&discreteFilter->lastSynchronizationStepValue, ChannelTypeUnknown); - ChannelValueInit(&discreteFilter->lastCouplingStepValue, ChannelTypeUnknown); + ChannelValueInit(&discreteFilter->lastSynchronizationStepValue, &ChannelTypeUnknown); + ChannelValueInit(&discreteFilter->lastCouplingStepValue, &ChannelTypeUnknown); return discreteFilter; } diff --git a/src/core/connections/filters/DiscreteFilter.h b/src/core/connections/filters/DiscreteFilter.h index e98af60..cca3e6e 100644 --- a/src/core/connections/filters/DiscreteFilter.h +++ b/src/core/connections/filters/DiscreteFilter.h @@ -19,7 +19,7 @@ extern "C" { typedef struct DiscreteFilter DiscreteFilter; -typedef McxStatus (* fDiscreteFilterSetup)(DiscreteFilter * filter, ChannelType type); +typedef McxStatus (* fDiscreteFilterSetup)(DiscreteFilter * filter, ChannelType * type); extern const struct ObjectClass _DiscreteFilter; diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c index b5bf3b3..d37e8c9 100644 --- a/src/core/connections/filters/MemoryFilter.c +++ b/src/core/connections/filters/MemoryFilter.c @@ -39,7 +39,7 @@ static McxStatus MemoryFilterSetValue(ChannelFilter * filter, double time, Chann #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (ChannelTypeEq(memoryFilter->valueHistoryWrite[0].type, ChannelTypeDouble)) { + if (ChannelTypeEq(memoryFilter->valueHistoryWrite[0].type, &ChannelTypeDouble)) { MCX_DEBUG_LOG("MemoryFilter: F SET (%x) (%f, %f)", filter, time, value.d); } else { MCX_DEBUG_LOG("MemoryFilter: F SET (%x) (%f, -)", filter, time); @@ -62,7 +62,7 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub if (double_eq(memoryFilter->timeHistoryRead[i], time)) { #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, &ChannelTypeDouble)) { 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); @@ -95,7 +95,7 @@ static ChannelValueData MemoryFilterGetValueReverse(ChannelFilter * filter, doub #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, &ChannelTypeDouble)) { 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); @@ -116,7 +116,7 @@ static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time if (double_eq(memoryFilter->timeHistoryRead[i], time)) { #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, &ChannelTypeDouble)) { 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); @@ -149,7 +149,7 @@ static ChannelValueData MemoryFilterGetValue(ChannelFilter * filter, double time #ifdef MCX_DEBUG if (time < MCX_DEBUG_LOG_TIME) { - if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, ChannelTypeDouble)) { + if (ChannelTypeEq(memoryFilter->valueHistoryRead[i].type, &ChannelTypeDouble)) { 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); @@ -206,7 +206,7 @@ static McxStatus MemoryFilterEnterCommunicationMode(ChannelFilter * filter, doub return RETURN_OK; } -static McxStatus MemoryFilterSetup(MemoryFilter * filter, ChannelType type, size_t historySize, int reverseSearch) { +static McxStatus MemoryFilterSetup(MemoryFilter * filter, ChannelType * type, size_t historySize, int reverseSearch) { ChannelFilter * channelFilter = (ChannelFilter *)filter; size_t i = 0; diff --git a/src/core/connections/filters/MemoryFilter.h b/src/core/connections/filters/MemoryFilter.h index 7b97d4a..1561fe6 100644 --- a/src/core/connections/filters/MemoryFilter.h +++ b/src/core/connections/filters/MemoryFilter.h @@ -19,7 +19,7 @@ extern "C" { typedef struct MemoryFilter MemoryFilter; -typedef McxStatus (* fMemoryFilterSetup)(MemoryFilter * filter, ChannelType type, size_t historySize, int reverseSearch); +typedef McxStatus (* fMemoryFilterSetup)(MemoryFilter * filter, ChannelType * type, size_t historySize, int reverseSearch); extern const struct ObjectClass _MemoryFilter; diff --git a/src/core/parameters/ParameterProxies.c b/src/core/parameters/ParameterProxies.c index cf491f4..e48e4ae 100644 --- a/src/core/parameters/ParameterProxies.c +++ b/src/core/parameters/ParameterProxies.c @@ -20,12 +20,12 @@ static void ScalarParameterProxySetValue(ScalarParameterProxy * proxy, Fmu2Value proxy->value_ = value; } -static ChannelType ScalarParameterProxyGetType(ScalarParameterProxy * proxy) { +static ChannelType * ScalarParameterProxyGetType(ScalarParameterProxy * proxy) { if (proxy->value_) { return ChannelValueType(&proxy->value_->val); } - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } static Fmu2Value * ScalarParameterProxyGetValue(ScalarParameterProxy * proxy) { @@ -136,13 +136,13 @@ static size_t ArrayParameterProxyGetDim(ArrayParameterProxy * proxy, size_t idx) return proxy->dims_[idx]; } -static ChannelType ArrayParameterProxyGetType(ArrayParameterProxy * proxy) { +static ChannelType * ArrayParameterProxyGetType(ArrayParameterProxy * proxy) { if (proxy->values_->Size(proxy->values_) > 0) { Fmu2Value * value = (Fmu2Value *)proxy->values_->At(proxy->values_, 0); return ChannelValueType(&value->val); } - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } static void ArrayParameterProxyDestructor(ArrayParameterProxy * proxy) { diff --git a/src/core/parameters/ParameterProxies.h b/src/core/parameters/ParameterProxies.h index 3d96aec..f4cf7a8 100644 --- a/src/core/parameters/ParameterProxies.h +++ b/src/core/parameters/ParameterProxies.h @@ -26,7 +26,7 @@ struct ScalarParameterProxy; typedef struct ScalarParameterProxy ScalarParameterProxy; typedef void (*fScalarParameterProxySetValue)(ScalarParameterProxy * proxy, Fmu2Value * value); -typedef ChannelType (*fScalarParameterProxyGetType)(ScalarParameterProxy * proxy); +typedef ChannelType * (*fScalarParameterProxyGetType)(ScalarParameterProxy * proxy); typedef Fmu2Value * (*fScalarParameterProxyGetValue)(ScalarParameterProxy * proxy); extern const struct ObjectClass _ScalarParameterProxy; @@ -53,7 +53,7 @@ typedef const char * (*fArrayParameterProxyGetUnit)(ArrayParameterProxy * proxy) typedef size_t (*fArrayParameterProxyGetNumDims)(ArrayParameterProxy * proxy); typedef size_t (*fArrayParameterProxyGetDim)(ArrayParameterProxy * proxy, size_t idx); typedef ObjectContainer * (*fArrayParameterProxyGetValues)(ArrayParameterProxy * proxy); -typedef ChannelType (*fArrayParameterProxyGetType)(ArrayParameterProxy * proxy); +typedef ChannelType * (*fArrayParameterProxyGetType)(ArrayParameterProxy * proxy); typedef fmi2_value_reference_t (*fArrayParameterProxyGetValueReference)(ArrayParameterProxy * proxy, size_t idx); typedef ChannelValueData * (*fArrayParameterProxyGetMin)(ArrayParameterProxy * proxy); typedef ChannelValueData * (*fArrayParameterProxyGetMax)(ArrayParameterProxy * proxy); diff --git a/src/fmu/Fmu1Value.c b/src/fmu/Fmu1Value.c index 1b1266d..e80de39 100644 --- a/src/fmu/Fmu1Value.c +++ b/src/fmu/Fmu1Value.c @@ -37,7 +37,7 @@ Fmu1Value * Fmu1ValueCreate(Fmu1Value * v) { v->name = NULL; v->var = NULL; v->channel = NULL; - ChannelValueInit(&v->val, ChannelTypeUnknown); + ChannelValueInit(&v->val, &ChannelTypeUnknown); return v; } diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 1d71551..9be5076 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -52,34 +52,34 @@ Fmu2VariableInfo * Fmu2VariableInfoMake(fmi2_import_variable_t * var) { switch (type) { case fmi2_base_type_real: - info->type = ChannelTypeDouble; + info->type = &ChannelTypeDouble; min.d = fmi2_import_get_real_variable_min(fmi2_import_get_variable_as_real(var)); minDefined = min.d != -DBL_MAX; max.d = fmi2_import_get_real_variable_max(fmi2_import_get_variable_as_real(var)); maxDefined = max.d != DBL_MAX; break; case fmi2_base_type_int: - info->type = ChannelTypeInteger; + info->type = &ChannelTypeInteger; min.i = fmi2_import_get_integer_variable_min(fmi2_import_get_variable_as_integer(var)); minDefined = min.i != -INT_MIN; max.i = fmi2_import_get_integer_variable_max(fmi2_import_get_variable_as_integer(var)); maxDefined = max.i != INT_MAX; break; case fmi2_base_type_enum: - info->type = ChannelTypeInteger; + info->type = &ChannelTypeInteger; min.i = fmi2_import_get_enum_variable_min(fmi2_import_get_variable_as_enum(var)); minDefined = min.i != -INT_MIN; max.i = fmi2_import_get_enum_variable_max(fmi2_import_get_variable_as_enum(var)); maxDefined = max.i != INT_MAX; break; case fmi2_base_type_str: - info->type = ChannelTypeString; + info->type = &ChannelTypeString; break; case fmi2_base_type_bool: - info->type = ChannelTypeBool; + info->type = &ChannelTypeBool; break; default: - info->type = ChannelTypeUnknown; + info->type = &ChannelTypeUnknown; break; } @@ -121,7 +121,7 @@ static void Fmu2VariableInfoDestructor(Fmu2VariableInfo * info) { } static Fmu2VariableInfo * Fmu2VariableInfoCreate(Fmu2VariableInfo * info) { - info->type = ChannelTypeUnknown; + info->type = &ChannelTypeUnknown; info->min = NULL; info->max = NULL; @@ -253,7 +253,7 @@ static Fmu2Value * Fmu2ValueCreate(Fmu2Value * v) { v->channel = NULL; v->info = NULL; - ChannelValueInit(&v->val, ChannelTypeUnknown); + ChannelValueInit(&v->val, &ChannelTypeUnknown); return v; } diff --git a/src/fmu/Fmu2Value.h b/src/fmu/Fmu2Value.h index 004b277..f811c65 100644 --- a/src/fmu/Fmu2Value.h +++ b/src/fmu/Fmu2Value.h @@ -62,7 +62,7 @@ extern const struct ObjectClass _Fmu2VariableInfo; typedef struct Fmu2VariableInfo { Object _; - ChannelType type; + ChannelType * type; ChannelValueData * min; ChannelValueData * max; diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index e9a9e18..bb91efe 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -111,20 +111,20 @@ static fmi1_callback_functions_t fmi1Callbacks = { NULL }; -ChannelType Fmi1TypeToChannelType(fmi1_base_type_enu_t type) { +ChannelType * Fmi1TypeToChannelType(fmi1_base_type_enu_t type) { switch (type) { case fmi1_base_type_real: - return ChannelTypeDouble; + return &ChannelTypeDouble; case fmi1_base_type_int: - return ChannelTypeInteger; + return &ChannelTypeInteger; case fmi1_base_type_bool: - return ChannelTypeBool; + return &ChannelTypeBool; case fmi1_base_type_str: - return ChannelTypeString; + return &ChannelTypeString; case fmi1_base_type_enum: - return ChannelTypeInteger; + return &ChannelTypeInteger; default: - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } } @@ -381,14 +381,14 @@ static ObjectContainer * Fmu1ReadArrayParamValues(const char * name, goto cleanup_1; } - if (ChannelTypeEq(input->type, ChannelTypeDouble)) { - ChannelValueInit(&chVal, ChannelTypeDouble); + if (ChannelTypeEq(input->type, &ChannelTypeDouble)) { + ChannelValueInit(&chVal, &ChannelTypeDouble); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { return RETURN_ERROR; } } else { // integer - ChannelValueInit(&chVal, ChannelTypeInteger); + ChannelValueInit(&chVal, &ChannelTypeInteger); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { return RETURN_ERROR; } @@ -548,9 +548,9 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { } ChannelValue * const chVal = &fmuVal->val; - ChannelType type = ChannelValueType(chVal); + ChannelType * type = ChannelValueType(chVal); - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: { double value = chVal->value.d; @@ -632,9 +632,9 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { fmi1_value_reference_t vr[] = { fmuVal->vr }; ChannelValue * const chVal = &fmuVal->val; - ChannelType type = ChannelValueType(chVal); + ChannelType * type = ChannelValueType(chVal); - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: status = fmi1_import_get_real(fmu->fmiImport, vr, 1, (fmi1_real_t *)ChannelValueReference(chVal)); if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { diff --git a/src/fmu/common_fmu1.h b/src/fmu/common_fmu1.h index eed6676..945e655 100644 --- a/src/fmu/common_fmu1.h +++ b/src/fmu/common_fmu1.h @@ -36,7 +36,7 @@ typedef enum enum_VAR_TYPE { VAR_STRING } FMI_VAR_TYPE; -ChannelType Fmi1TypeToChannelType(fmi1_base_type_enu_t type); +ChannelType * Fmi1TypeToChannelType(fmi1_base_type_enu_t type); typedef struct Fmu1CommonStruct { diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 9af68d4..3d0df67 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -31,8 +31,8 @@ extern "C" { #endif /* __cplusplus */ -fmi2_base_type_enu_t ChannelTypeToFmi2Type(ChannelType type) { - switch (type.con) { +fmi2_base_type_enu_t ChannelTypeToFmi2Type(ChannelType * type) { + switch (type->con) { case CHANNEL_DOUBLE: return fmi2_base_type_real; case CHANNEL_INTEGER: @@ -46,20 +46,20 @@ fmi2_base_type_enu_t ChannelTypeToFmi2Type(ChannelType type) { } } -ChannelType Fmi2TypeToChannelType(fmi2_base_type_enu_t type) { +ChannelType * Fmi2TypeToChannelType(fmi2_base_type_enu_t type) { switch (type) { case fmi2_base_type_real: - return ChannelTypeDouble; + return &ChannelTypeDouble; case fmi2_base_type_int: - return ChannelTypeInteger; + return &ChannelTypeInteger; case fmi2_base_type_bool: - return ChannelTypeBool; + return &ChannelTypeBool; case fmi2_base_type_str: - return ChannelTypeString; + return &ChannelTypeString; case fmi2_base_type_enum: - return ChannelTypeInteger; + return &ChannelTypeInteger; default: - return ChannelTypeUnknown; + return &ChannelTypeUnknown; } } @@ -389,14 +389,14 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, goto fmu2_read_array_param_values_for_cleanup; } - if (ChannelTypeEq(input->type, ChannelTypeDouble)) { - ChannelValueInit(&chVal, ChannelTypeDouble); + if (ChannelTypeEq(input->type, &ChannelTypeDouble)) { + ChannelValueInit(&chVal, &ChannelTypeDouble); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { retVal = RETURN_ERROR; goto fmu2_read_array_param_values_for_cleanup; } } else { // integer - ChannelValueInit(&chVal, ChannelTypeInteger); + ChannelValueInit(&chVal, &ChannelTypeInteger); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { retVal = RETURN_ERROR; goto fmu2_read_array_param_values_for_cleanup; @@ -681,9 +681,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { } ChannelValue * const chVal = &fmuVal->val; - ChannelType type = ChannelValueType(chVal); + ChannelType * type = ChannelValueType(chVal); - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: { fmi2_value_reference_t vr[] = {fmuVal->data->vr.scalar}; @@ -790,9 +790,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { char * const name = fmuVal->name; ChannelValue * const chVal = &fmuVal->val; - ChannelType type = ChannelValueType(chVal); + ChannelType * type = ChannelValueType(chVal); - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; @@ -933,9 +933,9 @@ McxStatus Fmi2RegisterLocalChannelsAtDatabus(ObjectContainer * vals, const char const char * name = val->name; fmi2_import_unit_t * unit = NULL; const char * unitName; - ChannelType type = ChannelValueType(&val->val); + ChannelType * type = ChannelValueType(&val->val); - if (ChannelTypeEq(ChannelTypeDouble, type)) { + if (ChannelTypeEq(&ChannelTypeDouble, type)) { unit = fmi2_import_get_real_variable_unit(fmi2_import_get_variable_as_real(val->data->data.scalar)); } if (unit) { @@ -974,7 +974,7 @@ ObjectContainer * Fmu2ValueScalarListFromVarList(fmi2_import_variable_list_t * v for (i = 0; i < num; i++) { fmi2_import_variable_t * var = fmi2_import_get_variable(vars, i); char * name = (char *)fmi2_import_get_variable_name(var); - ChannelType type = Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)); + ChannelType * type = Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)); Fmu2Value * value = Fmu2ValueScalarMake(name, var, NULL, NULL); if (value) { @@ -1007,7 +1007,7 @@ ObjectContainer * Fmu2ValueScalarListFromValVarList(ObjectContainer * vals, fmi2 for (i = 0; i < num; i++) { fmi2_import_variable_t * var = fmi2_import_get_variable(vars, i); char * name = (char *)fmi2_import_get_variable_name(var); - ChannelType type = Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)); + ChannelType * type = Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)); ChannelValue * chVal = (ChannelValue *) vals->At(vals, i); Fmu2Value * value = NULL; diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h index 024d2ee..fe175bb 100644 --- a/src/fmu/common_fmu2.h +++ b/src/fmu/common_fmu2.h @@ -23,7 +23,7 @@ extern "C" { #endif /* __cplusplus */ -ChannelType Fmi2TypeToChannelType(fmi2_base_type_enu_t type); +ChannelType * Fmi2TypeToChannelType(fmi2_base_type_enu_t type); const char * Fmi2TypeToString(fmi2_base_type_enu_t type); struct Fmu2CommonStruct; diff --git a/src/reader/model/components/specific_data/ConstantInput.c b/src/reader/model/components/specific_data/ConstantInput.c index 415cc72..a5b5559 100644 --- a/src/reader/model/components/specific_data/ConstantInput.c +++ b/src/reader/model/components/specific_data/ConstantInput.c @@ -19,7 +19,7 @@ static void ScalarConstantValueInputDestructor(ScalarConstantValueInput * input) } static ScalarConstantValueInput * ScalarConstantValueInputCreate(ScalarConstantValueInput * input) { - input->type = ChannelTypeUnknown; + input->type = &ChannelTypeUnknown; input->value.d = 0.0; return input; @@ -32,7 +32,7 @@ static void ArrayConstantValueInputDestructor(ArrayConstantValueInput * input) { } static ArrayConstantValueInput * ArrayConstantValueInputCreate(ArrayConstantValueInput * input) { - input->type = ChannelTypeUnknown; + input->type = &ChannelTypeUnknown; input->numValues = 0; input->values = NULL; diff --git a/src/reader/model/components/specific_data/ConstantInput.h b/src/reader/model/components/specific_data/ConstantInput.h index 5a38b5b..6896fbd 100644 --- a/src/reader/model/components/specific_data/ConstantInput.h +++ b/src/reader/model/components/specific_data/ConstantInput.h @@ -25,7 +25,7 @@ extern const ObjectClass _ScalarConstantValueInput; typedef struct ScalarConstantValueInput { InputElement _; - ChannelType type; + ChannelType * type; ChannelValueData value; } ScalarConstantValueInput; @@ -34,7 +34,7 @@ extern const ObjectClass _ArrayConstantValueInput; typedef struct ArrayConstantValueInput { InputElement _; - ChannelType type; + ChannelType * type; size_t numValues; void * values; diff --git a/src/reader/model/parameters/ArrayParameterInput.c b/src/reader/model/parameters/ArrayParameterInput.c index d8681b6..b12419a 100644 --- a/src/reader/model/parameters/ArrayParameterInput.c +++ b/src/reader/model/parameters/ArrayParameterInput.c @@ -29,7 +29,7 @@ static void ArrayParameterInputDestructor(ArrayParameterInput * input) { } if (input->values) { - if (ChannelTypeEq(input->type, ChannelTypeString)) { + if (ChannelTypeEq(input->type, &ChannelTypeString)) { size_t i = 0; for (i = 0; i < input->numValues; i++) { @@ -47,7 +47,7 @@ static ArrayParameterInput * ArrayParameterInputCreate(ArrayParameterInput * inp input->numDims = 0; input->dims = NULL; - input->type = ChannelTypeUnknown; + input->type = &ChannelTypeUnknown; input->numValues = 0; input->values = NULL; diff --git a/src/reader/model/parameters/ArrayParameterInput.h b/src/reader/model/parameters/ArrayParameterInput.h index 8c45675..cf0a0dc 100644 --- a/src/reader/model/parameters/ArrayParameterInput.h +++ b/src/reader/model/parameters/ArrayParameterInput.h @@ -29,7 +29,7 @@ typedef struct ArrayParameterInput { size_t numDims; ArrayParameterDimensionInput ** dims; - ChannelType type; + ChannelType * type; size_t numValues; void * values; diff --git a/src/reader/model/parameters/ScalarParameterInput.c b/src/reader/model/parameters/ScalarParameterInput.c index 22783d6..1244cda 100644 --- a/src/reader/model/parameters/ScalarParameterInput.c +++ b/src/reader/model/parameters/ScalarParameterInput.c @@ -19,7 +19,7 @@ static void ScalarParameterInputDestructor(ScalarParameterInput * input) { if (input->unit) { mcx_free(input->unit); } - if (ChannelTypeEq(input->type, ChannelTypeString) && input->value.defined && input->value.value.s) { + if (ChannelTypeEq(input->type, &ChannelTypeString) && input->value.defined && input->value.value.s) { mcx_free(input->value.value.s); } } @@ -27,7 +27,7 @@ static void ScalarParameterInputDestructor(ScalarParameterInput * input) { static ScalarParameterInput * ScalarParameterInputCreate(ScalarParameterInput * input) { input->name = NULL; - input->type = ChannelTypeUnknown; + input->type = &ChannelTypeUnknown; OPTIONAL_UNSET(input->value); input->unit = NULL; diff --git a/src/reader/model/parameters/ScalarParameterInput.h b/src/reader/model/parameters/ScalarParameterInput.h index b52d1ae..5be3ac0 100644 --- a/src/reader/model/parameters/ScalarParameterInput.h +++ b/src/reader/model/parameters/ScalarParameterInput.h @@ -24,7 +24,7 @@ typedef struct ScalarParameterInput { char * name; - ChannelType type; + ChannelType * type; OPTIONAL_VALUE(ChannelValueData) value; char * unit; diff --git a/src/reader/model/ports/ScalarPortInput.c b/src/reader/model/ports/ScalarPortInput.c index 96d732e..13e309b 100644 --- a/src/reader/model/ports/ScalarPortInput.c +++ b/src/reader/model/ports/ScalarPortInput.c @@ -132,8 +132,8 @@ static McxStatus CopyFrom(ScalarPortInput * self, ScalarPortInput * src) { } -static void PrintOptionalChannelValueData(char * prefix, ChannelType type, OPTIONAL_VALUE(ChannelValueData) value) { - switch(type.con) { +static void PrintOptionalChannelValueData(char * prefix, ChannelType * type, OPTIONAL_VALUE(ChannelValueData) value) { + switch(type->con) { case CHANNEL_DOUBLE: if (value.defined) { mcx_log(LOG_DEBUG, "%s%f,", prefix, value.value.d); @@ -208,7 +208,7 @@ static ScalarPortInput * ScalarPortInputCreate(ScalarPortInput * input) { input->id = NULL; input->unit = NULL; - input->type = ChannelTypeUnknown; + input->type = &ChannelTypeUnknown; OPTIONAL_UNSET(input->min); OPTIONAL_UNSET(input->max); diff --git a/src/reader/model/ports/ScalarPortInput.h b/src/reader/model/ports/ScalarPortInput.h index 258e38e..1361328 100644 --- a/src/reader/model/ports/ScalarPortInput.h +++ b/src/reader/model/ports/ScalarPortInput.h @@ -32,7 +32,7 @@ struct ScalarPortInput { char * id; char * unit; - ChannelType type; + ChannelType * type; OPTIONAL_VALUE(ChannelValueData) min; OPTIONAL_VALUE(ChannelValueData) max; diff --git a/src/reader/model/ports/VectorPortInput.c b/src/reader/model/ports/VectorPortInput.c index a90b53f..a5d5ab4 100644 --- a/src/reader/model/ports/VectorPortInput.c +++ b/src/reader/model/ports/VectorPortInput.c @@ -149,7 +149,7 @@ static McxStatus CopyFrom(VectorPortInput * self, VectorPortInput * src) { return RETURN_OK; } -static void PrintVec(char * prefix, ChannelType type, size_t len, void * value) { +static void PrintVec(char * prefix, ChannelType * type, size_t len, void * value) { char buffer[4096] = { 0 }; size_t num = 0; @@ -159,7 +159,7 @@ static void PrintVec(char * prefix, ChannelType type, size_t len, void * value) if (value) { for (i = 0; i < len; i++) { - switch(type.con) { + switch(type->con) { case CHANNEL_DOUBLE: num += sprintf(buffer + num, " %f", ((double*)value)[i]); break; @@ -235,7 +235,7 @@ static VectorPortInput * VectorPortInputCreate(VectorPortInput * input) { input->id = NULL; input->unit = NULL; - input->type = ChannelTypeUnknown; + input->type = &ChannelTypeUnknown; input->min = NULL; input->max = NULL; diff --git a/src/reader/model/ports/VectorPortInput.h b/src/reader/model/ports/VectorPortInput.h index 9516e31..8dacb80 100644 --- a/src/reader/model/ports/VectorPortInput.h +++ b/src/reader/model/ports/VectorPortInput.h @@ -35,7 +35,7 @@ struct VectorPortInput { char * id; char * unit; - ChannelType type; + ChannelType * type; void * min; void * max; diff --git a/src/reader/ssp/Parameters.c b/src/reader/ssp/Parameters.c index 1269e58..83b24b2 100644 --- a/src/reader/ssp/Parameters.c +++ b/src/reader/ssp/Parameters.c @@ -672,7 +672,7 @@ static ScalarParameterInput * SSDReadScalarParameter(SSDParameter * parameter) { for (i = 0; _typeMappingScalar[i].key; i++) { if (!strcmp(connectorType, _typeMappingScalar[i].key)) { - input->type = *_typeMappingScalar[i].value; + input->type = _typeMappingScalar[i].value; break; } } @@ -747,10 +747,10 @@ static ArrayParameterDimensionInput * SSDReadArrayParameterDimension(xmlNodePtr return input; } -static McxStatus AllocateMemory(SSDParameter * parameter, ChannelType type, size_t numValues, void ** dest) { +static McxStatus AllocateMemory(SSDParameter * parameter, ChannelType * type, size_t numValues, void ** dest) { size_t size = 0; - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: size = sizeof(double); break; @@ -826,7 +826,7 @@ static McxStatus SSDReadDimensionlessArrayParameter(SSDParameter * parameter, Ar continue; } - switch (input->type.con) { + switch (input->type->con) { case CHANNEL_DOUBLE: retVal = xml_attr_double(paramTypeNode, "value", (double*)input->values + paramValue->idx1, SSD_MANDATORY); break; @@ -912,7 +912,7 @@ static McxStatus SSDReadDimensionArrayParameter(SSDParameter * parameter, ArrayP index = (paramValue->idx1 - input->dims[0]->start) * (input->dims[1]->end - input->dims[1]->start + 1) + paramValue->idx2 - input->dims[1]->start; } - switch (input->type.con) { + switch (input->type->con) { case CHANNEL_DOUBLE: retVal = xml_attr_double(paramTypeNode, "value", (double*)input->values + index, SSD_MANDATORY); break; @@ -1021,7 +1021,7 @@ static ArrayParameterInput * SSDReadArrayParameter(SSDParameter * parameter) { for (i = 0; _typeMappingArray[i].key; i++) { if (!strcmp(connectorType, _typeMappingArray[i].key)) { - input->type = *_typeMappingArray[i].value; + input->type = _typeMappingArray[i].value; break; } } diff --git a/src/reader/ssp/Ports.c b/src/reader/ssp/Ports.c index c5f03c1..466520c 100644 --- a/src/reader/ssp/Ports.c +++ b/src/reader/ssp/Ports.c @@ -137,7 +137,7 @@ VectorPortInput * SSDReadComponentVectorPort(xmlNodePtr connectorNode, const cha for (i = 0; _typeMapping[i].key; i++) { if (!strcmp(typeName, _typeMapping[i].key)) { - vectorPortInput->type = *_typeMapping[i].value; + vectorPortInput->type = _typeMapping[i].value; break; } } @@ -173,7 +173,7 @@ VectorPortInput * SSDReadComponentVectorPort(xmlNodePtr connectorNode, const cha xmlNodePtr vectorNode = NULL; size_t num = 0; - switch (vectorPortInput->type.con) { + switch (vectorPortInput->type->con) { case CHANNEL_DOUBLE: vectorNode = xml_child(portNode, "RealVector"); break; @@ -351,7 +351,7 @@ ScalarPortInput * SSDReadComponentScalarPort(xmlNodePtr connectorNode, const cha for (i = 0; _typeMapping[i].key; i++) { if (!strcmp(typeName, _typeMapping[i].key)) { - scalarPortInput->type = *_typeMapping[i].value; + scalarPortInput->type = _typeMapping[i].value; break; } } @@ -387,7 +387,7 @@ ScalarPortInput * SSDReadComponentScalarPort(xmlNodePtr connectorNode, const cha xmlNodePtr scalarNode = NULL; size_t num = 0; - switch (scalarPortInput->type.con) { + switch (scalarPortInput->type->con) { case CHANNEL_DOUBLE: scalarNode = xml_child(portNode, "Real"); break; diff --git a/src/reader/ssp/SpecificData.c b/src/reader/ssp/SpecificData.c index 530693d..b151743 100644 --- a/src/reader/ssp/SpecificData.c +++ b/src/reader/ssp/SpecificData.c @@ -177,7 +177,7 @@ static ScalarConstantValueInput * SSDReadScalarConstantValue(xmlNodePtr node) { for (i = 0; _scalarConstantTypeMapping[i].key; i++) { if (!strcmp(xml_node_get_name(node), _scalarConstantTypeMapping[i].key)) { - input->type = *_scalarConstantTypeMapping[i].value; + input->type = _scalarConstantTypeMapping[i].value; break; } } @@ -226,7 +226,7 @@ static ArrayConstantValueInput * SSDReadArrayConstantValue(xmlNodePtr node) { for (i = 0; _vectorConstantTypeMapping[i].key; i++) { if (!strcmp(xml_node_get_name(node), _vectorConstantTypeMapping[i].key)) { - input->type = *_vectorConstantTypeMapping[i].value; + input->type = _vectorConstantTypeMapping[i].value; break; } } @@ -237,7 +237,7 @@ static ArrayConstantValueInput * SSDReadArrayConstantValue(xmlNodePtr node) { } } - switch (input->type.con) { + switch (input->type->con) { case CHANNEL_DOUBLE: retVal = xml_attr_double_vec(node, "value", &input->numValues, (double**)&input->values, SSD_MANDATORY); break; diff --git a/src/reader/ssp/Util.c b/src/reader/ssp/Util.c index 6186dc0..7b883da 100644 --- a/src/reader/ssp/Util.c +++ b/src/reader/ssp/Util.c @@ -746,8 +746,8 @@ McxStatus xml_attr_enum_weak_ptr(xmlNodePtr node, return ret_status; } -McxStatus xml_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType type, ChannelValueData * dest, SSDParamMode mode) { - switch (type.con) { +McxStatus xml_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType * type, ChannelValueData * dest, SSDParamMode mode) { + switch (type->con) { case CHANNEL_DOUBLE: return xml_attr_double(node, attribute_name, &dest->d, mode); case CHANNEL_INTEGER: @@ -1160,7 +1160,7 @@ McxStatus xml_opt_attr_enum(xmlNodePtr node, const char * attribute_name, MapStr return RETURN_OK; } -McxStatus xml_opt_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType type, OPTIONAL_VALUE(ChannelValueData) * dest) { +McxStatus xml_opt_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType * type, OPTIONAL_VALUE(ChannelValueData) * dest) { McxStatus ret_val = xml_attr_channel_value_data(node, attribute_name, type, &dest->value, SSD_OPTIONAL); if (ret_val == RETURN_ERROR) { @@ -1172,7 +1172,7 @@ McxStatus xml_opt_attr_channel_value_data(xmlNodePtr node, const char * attribut return RETURN_OK; } -McxStatus xml_attr_vec_len(xmlNodePtr node, const char * attribute_name, ChannelType type, size_t expectedLen, void ** dest, SSDParamMode mode) { +McxStatus xml_attr_vec_len(xmlNodePtr node, const char * attribute_name, ChannelType * type, size_t expectedLen, void ** dest, SSDParamMode mode) { McxStatus ret_status = RETURN_OK; int ret_val = 0; xmlChar * buffer = NULL; @@ -1209,7 +1209,7 @@ McxStatus xml_attr_vec_len(xmlNodePtr node, const char * attribute_name, Channel goto cleanup; } - switch (type.con) { + switch (type->con) { case CHANNEL_DOUBLE: ret_status = xml_attr_double_vec(node, attribute_name, &len, (double **) &values, mode); break; diff --git a/src/reader/ssp/Util.h b/src/reader/ssp/Util.h index 524fe31..8c1af9f 100644 --- a/src/reader/ssp/Util.h +++ b/src/reader/ssp/Util.h @@ -69,20 +69,20 @@ McxStatus xml_attr_string(xmlNodePtr node, const char * attribute_name, char ** McxStatus xml_attr_path(xmlNodePtr node, const char * attribute_name, char ** dest, SSDParamMode mode); McxStatus xml_attr_enum(xmlNodePtr node, const char * attribute_name, MapStringInt * mapping, int * dest, SSDParamMode mode); McxStatus xml_attr_enum_weak_ptr(xmlNodePtr node, const char * attribute_name, void * map[], size_t entry_size, void ** value, SSDParamMode mode); -McxStatus xml_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType type, ChannelValueData * dest, SSDParamMode mode); +McxStatus xml_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType * type, ChannelValueData * dest, SSDParamMode mode); McxStatus xml_opt_attr_double(xmlNodePtr node, const char * attribute_name, OPTIONAL_VALUE(double) * dest); McxStatus xml_opt_attr_int(xmlNodePtr node, const char * attribute_name, OPTIONAL_VALUE(int) * dest); McxStatus xml_opt_attr_size_t(xmlNodePtr node, const char * attribute_name, OPTIONAL_VALUE(size_t) * dest); McxStatus xml_opt_attr_bool(xmlNodePtr node, const char * attribute_name, OPTIONAL_VALUE(int) * dest); McxStatus xml_opt_attr_enum(xmlNodePtr node, const char * attribute_name, MapStringInt * mapping, OPTIONAL_VALUE(int) * dest); -McxStatus xml_opt_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType type, OPTIONAL_VALUE(ChannelValueData) * dest); +McxStatus xml_opt_attr_channel_value_data(xmlNodePtr node, const char * attribute_name, ChannelType * type, OPTIONAL_VALUE(ChannelValueData) * dest); McxStatus xml_attr_double_vec(xmlNodePtr node, const char * attribute_name, size_t * len, double ** dest, SSDParamMode mode); McxStatus xml_attr_bool_vec(xmlNodePtr node, const char * attribute_name, size_t * len, int ** dest, SSDParamMode mode); McxStatus xml_attr_int_vec(xmlNodePtr node, const char * attribute_name, size_t * len, int ** dest, SSDParamMode mode); -McxStatus xml_attr_vec_len(xmlNodePtr node, const char * attribute_name, ChannelType type, size_t expectedLen, void ** dest, SSDParamMode mode); +McxStatus xml_attr_vec_len(xmlNodePtr node, const char * attribute_name, ChannelType * type, size_t expectedLen, void ** dest, SSDParamMode mode); /*****************************************************************************/ /* Errors */ diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 4a8a3ff..50c6323 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -83,7 +83,7 @@ static McxStatus ChannelStorageSetup(ChannelStorage * channelStore, int fullStor goto cleanup; } - retVal = ChannelInfoSetup(&timeInfo, "Time", "Time", "", GetTimeUnitString(), ChannelTypeDouble, ""); + retVal = ChannelInfoSetup(&timeInfo, "Time", "Time", "", GetTimeUnitString(), &ChannelTypeDouble, ""); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Results: Setup port storage: Could not set up time port data"); goto cleanup; diff --git a/src/storage/StorageBackendText.c b/src/storage/StorageBackendText.c index b7ca92f..2f99855 100644 --- a/src/storage/StorageBackendText.c +++ b/src/storage/StorageBackendText.c @@ -215,7 +215,7 @@ static McxStatus WriteRow(FILE * file, ChannelValue * values, size_t numChannels if (channel == 0) { // leave out separator at the beginning sep = ""; } - switch (ChannelValueType(&val).con) { + switch (ChannelValueType(&val)->con) { case CHANNEL_DOUBLE: case CHANNEL_INTEGER: case CHANNEL_BOOL: From 7517e8b6931073abbaf06e35ccc2e6b9307c201e Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 20 Jul 2021 09:44:11 +0200 Subject: [PATCH 122/295] channel: Use ChannelInfo with Dimension instead of VectorChannelInfo Note: This changes the type in Databus `origInfos` from `VectorChannelInfo` to `ChannelInfo`, but the uses of `DatabusGetOutVectorChannelInfo` haven't been updated. That means that this change breaks all components using `DatabusGetOutVectorChannelInfo`. --- src/core/Conversion.c | 27 +- src/core/Databus.c | 387 +++++-------------- src/core/Databus.h | 2 - src/core/channels/Channel.c | 3 + src/core/channels/ChannelDimension.c | 67 ++++ src/core/channels/ChannelDimension.h | 39 ++ src/core/channels/ChannelInfo.c | 2 + src/core/channels/ChannelInfo.h | 4 + src/core/channels/ChannelValue.c | 147 ++++++- src/core/channels/ChannelValue.h | 6 + src/core/connections/ConnectionInfo.c | 2 + src/core/connections/ConnectionInfo.h | 2 + src/core/connections/ConnectionInfoFactory.c | 83 ++-- src/core/connections/ConnectionInfoFactory.h | 3 +- src/core/connections/ConnectionInfo_impl.h | 67 ++++ src/core/connections/FilteredConnection.c | 2 + 16 files changed, 497 insertions(+), 346 deletions(-) create mode 100644 src/core/channels/ChannelDimension.c create mode 100644 src/core/channels/ChannelDimension.h create mode 100644 src/core/connections/ConnectionInfo_impl.h diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 7adc2ab..942af6f 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -151,7 +151,8 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue } if (!(ChannelTypeEq(conversion->type, &ChannelTypeDouble) - || ChannelTypeEq(conversion->type, &ChannelTypeInteger))) { + || ChannelTypeEq(conversion->type, &ChannelTypeInteger) + || ChannelTypeIsArray(conversion->type))) { mcx_log(LOG_ERROR, "Range conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -455,7 +456,8 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal } if (!(ChannelTypeEq(conversion->type, &ChannelTypeDouble) - || ChannelTypeEq(conversion->type, &ChannelTypeInteger))) { + || ChannelTypeEq(conversion->type, &ChannelTypeInteger) + || ChannelTypeIsArray(conversion->type))) { mcx_log(LOG_WARNING, "Linear conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -615,6 +617,25 @@ static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, Chann return RETURN_OK; } +static McxStatus TypeConversionConvertSingletonDoubleToDouble(Conversion * conversion, ChannelValue * value) { + if (!(ChannelTypeIsArray(ChannelValueType(value)) && value->value.a.type, &ChannelTypeDouble)) { + ChannelType * array = ChannelTypeArray(&ChannelTypeDouble, 0, NULL); + mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), array); + ChannelTypeDestructor(array); + return RETURN_ERROR; + } + + double val = *(double *)value->value.a.data; + + ChannelValueDataDestructor(&value->value, value->type); + ChannelTypeDestructor(value->type); + value->type = &ChannelTypeDouble; + + value->value.d = val; + + return RETURN_OK; +} + static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValue * value) { return RETURN_OK; } @@ -638,6 +659,8 @@ static McxStatus TypeConversionSetup(TypeConversion * typeConversion, conversion->convert = TypeConversionConvertBoolInteger; } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeBool)) { conversion->convert = TypeConversionConvertIntegerBool; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeDouble)) { + conversion->convert = TypeConversionConvertSingletonDoubleToDouble; } else { mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion selected"); return RETURN_ERROR; diff --git a/src/core/Databus.c b/src/core/Databus.c index 739ef21..63756d9 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -52,257 +52,124 @@ static DatabusInfoData * DatabusInfoDataCreate(DatabusInfoData * data) { OBJECT_CLASS(DatabusInfoData, Object); - -char * CreateIndexedName(const char * name, unsigned i) { - size_t len = 0; - char * buffer = NULL; - - len = strlen(name) + (mcx_digits10(i) + 1) + 2 + 1; - - buffer = (char *) mcx_calloc(len, sizeof(char)); - if (!buffer) { - return NULL; - } - - snprintf(buffer, len, "%s[%d]", name, i); - - return buffer; -} - - - -static Vector * DatabusReadPortInput(PortInput * input) { +static ChannelInfo * DatabusReadPortInput(PortInput * input) { McxStatus retVal = RETURN_OK; - Vector * list = NULL; - VectorChannelInfo * vector = NULL; - - 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; - goto cleanup_0; + ChannelInfo * info = (ChannelInfo *)mcx_calloc(1, sizeof(ChannelInfo)); + if (!info) { + return NULL; } if (input->type == PORT_VECTOR) { - /* vector of channels: Copy info and add "[i]" to name, nameInTool and id */ - ChannelValue ** mins = NULL; - ChannelValue ** maxs = NULL; - ChannelValue ** scales = NULL; - ChannelValue ** offsets = NULL; - ChannelValue ** defaults = NULL; - ChannelValue ** initials = NULL; - - int startIndex = 0; - int endIndex = 0; - - int i = 0; - VectorPortInput * vectorPortInput = input->port.vectorPort; InputElement * vectorPortElement = (InputElement *) vectorPortInput; - ChannelType * expectedType = vectorPortInput->type; - size_t expectedLen = 0; + int startIdx = 0; + int endIdx = 0; - if (!vector) { - retVal = RETURN_ERROR; - goto cleanup_1; - } - - startIndex = vectorPortInput->startIndex; - if (startIndex < 0) { + startIdx = vectorPortInput->startIndex; + if (startIdx < 0) { input_element_error(vectorPortElement, "start index must not be smaller than 0"); retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - endIndex = vectorPortInput->endIndex; - if (endIndex < startIndex) { + endIdx = vectorPortInput->endIndex; + if (endIdx < startIdx) { input_element_error(vectorPortElement, "end index must not be smaller than start index"); retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - expectedLen = endIndex - startIndex + 1; - - retVal = vector->Setup(vector, vectorPortInput->name, vectorPortInput->nameInModel, FALSE, (size_t) startIndex, (size_t) endIndex); - if (RETURN_ERROR == retVal) { - goto cleanup_1; + info->dimension = (ChannelDimension *) object_create(ChannelDimension); + if (!info->dimension) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; } - mins = ArrayToChannelValueArray(vectorPortInput->min, expectedLen, expectedType); - if (vectorPortInput->min && !mins) { + if (RETURN_OK != ChannelDimensionSetup(info->dimension, 1)) { + mcx_log(LOG_ERROR, "Could not setup ChannelDimension"); retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - maxs = ArrayToChannelValueArray(vectorPortInput->max, expectedLen, expectedType); - if (vectorPortInput->max && !maxs) { + if (RETURN_OK != ChannelDimensionSetDimension(info->dimension, 0, (size_t) startIdx, (size_t) endIdx)) { + mcx_log(LOG_ERROR, "Could not SetDimension"); retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - scales = ArrayToChannelValueArray(vectorPortInput->scale, expectedLen, expectedType); - if (vectorPortInput->scale && !scales) { + size_t dims[1] = { endIdx - startIdx + 1 }; + + if (RETURN_OK != ChannelInfoInit(info, + vectorPortInput->name, + vectorPortInput->nameInModel, + vectorPortInput->description, + vectorPortInput->unit, + ChannelTypeArray(vectorPortInput->type, 1, dims), + vectorPortInput->id)) { + mcx_log(LOG_ERROR, "Could not Init ChannelInfo"); retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - offsets = ArrayToChannelValueArray(vectorPortInput->offset, expectedLen, expectedType); - if (vectorPortInput->offset && !offsets) { + info->min = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->min); + if (!info->min) { retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - defaults = ArrayToChannelValueArray(vectorPortInput->default_, expectedLen, expectedType); - if (vectorPortInput->default_ && !defaults) { + info->max = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->max); + if (!info->max) { retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - initials = ArrayToChannelValueArray(vectorPortInput->initial, expectedLen, expectedType); - if (vectorPortInput->initial && !initials) { + info->scale = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->scale); + if (!info->scale) { retVal = RETURN_ERROR; - goto cleanup_1; + goto vector_cleanup_0; } - for (i = startIndex; i <= endIndex; i++) { - char * name = NULL; - char * nameInTool = NULL; - char * id = NULL; - - ChannelInfo copy = { 0 }; - - if (!(name = CreateIndexedName(vectorPortInput->name, i))) { - retVal = RETURN_ERROR; - goto cleanup_2; - } - if (vectorPortInput->nameInModel) { // optional - if (!(nameInTool = CreateIndexedName(vectorPortInput->nameInModel, i))) { - retVal = RETURN_ERROR; - goto cleanup_2; - } - } - if (vectorPortInput->id) { // optional - if (!(id = CreateIndexedName(vectorPortInput->id, i))) { - retVal = RETURN_ERROR; - goto cleanup_2; - } - } - - retVal = ChannelInfoInit(©); - if (RETURN_ERROR == retVal) { - goto cleanup_2; - } - - ChannelInfoSetName(©, name); - ChannelInfoSetNameInTool(©, nameInTool); - ChannelInfoSetID(©, id); - - ChannelInfoSetDescription(©, vectorPortInput->description); - ChannelInfoSetType(©, vectorPortInput->type); - - if (!ChannelInfoIsBinary(©)) { - ChannelInfoSetUnit(©, vectorPortInput->unit); - } else { - ChannelInfoSetUnit(©, "-"); - } - - ChannelInfoSetVector(©, (VectorChannelInfo *) object_strong_reference(vector)); - - if (mins) { - copy.min = mins[i - startIndex]; - } - if (maxs) { - copy.max = maxs[i - startIndex]; - } - - if (scales) { - copy.scale = scales[i - startIndex]; - } - if (offsets) { - copy.offset = offsets[i - startIndex]; - } - - if (defaults) { - copy.defaultValue = defaults[i - startIndex]; - } - if (initials) { - copy.initialValue = initials[i - startIndex]; - } - - if (vectorPortInput->writeResults.defined) { - copy.writeResult = vectorPortInput->writeResults.value; - } - - list->PushBack(list, ©); - - retVal = vector->AddElement(vector, list->At(list, list->Size(list) - 1), i); - if (RETURN_ERROR == retVal) { - goto cleanup_2; - } - - cleanup_2: - if (name) { - mcx_free(name); - } - if (nameInTool) { - mcx_free(nameInTool); - } - if (id) { - mcx_free(id); - } - if (RETURN_ERROR == retVal) { - goto cleanup_1; - } + info->offset = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->offset); + if (!info->offset) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; } - cleanup_1: - - if (mins) { - mcx_free(mins); - } - if (maxs) { - mcx_free(maxs); + info->initialValue = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->initial); + if (!info->initialValue) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; } - if (scales) { - mcx_free(scales); - } - if (offsets) { - mcx_free(offsets); + info->defaultValue = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->default_); + if (!info->defaultValue) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; } - if (defaults) { - mcx_free(defaults); - } - if (initials) { - mcx_free(initials); + if (vectorPortInput->writeResults.defined) { + info->writeResult = vectorPortInput->writeResults.value; } - if (RETURN_ERROR == retVal) { + vector_cleanup_0: + if (retVal == RETURN_ERROR) { goto cleanup_0; } } else { ScalarPortInput * scalarPortInput = input->port.scalarPort; - ChannelInfo info = { 0 }; - retVal = ChannelInfoInit(&info); + retVal = ChannelInfoInit(info); if (RETURN_ERROR == retVal) { goto cleanup_else_1; } - ChannelInfoSetName(&info, scalarPortInput->name); - ChannelInfoSetNameInTool(&info, scalarPortInput->nameInModel); - ChannelInfoSetDescription(&info, scalarPortInput->description); - ChannelInfoSetID(&info, scalarPortInput->id); - ChannelInfoSetType(&info, scalarPortInput->type); + ChannelInfoSetName(info, scalarPortInput->name); + ChannelInfoSetNameInTool(info, scalarPortInput->nameInModel); + ChannelInfoSetDescription(info, scalarPortInput->description); + ChannelInfoSetID(info, scalarPortInput->id); + ChannelInfoSetType(info, scalarPortInput->type); if (!ChannelInfoIsBinary(&info)) { ChannelInfoSetUnit(&info, scalarPortInput->unit); @@ -310,7 +177,7 @@ static Vector * DatabusReadPortInput(PortInput * input) { ChannelInfoSetUnit(&info, "-"); } - ChannelType * expectedType = info.type; + ChannelType * expectedType = info->type; ChannelValue value; ChannelValueInit(&value, expectedType); @@ -319,8 +186,8 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->min.value)) { goto cleanup_else_1; } - info.min = ChannelValueClone(&value); - if (!info.min) { + info->min = ChannelValueClone(&value); + if (!info->min) { goto cleanup_else_1; } } @@ -329,8 +196,8 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->max.value)) { goto cleanup_else_1; } - info.max = ChannelValueClone(&value); - if (!info.max) { + info->max = ChannelValueClone(&value); + if (!info->max) { goto cleanup_else_1; } } @@ -339,8 +206,8 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->scale.value)) { goto cleanup_else_1; } - info.scale = ChannelValueClone(&value); - if (!info.scale) { + info->scale = ChannelValueClone(&value); + if (!info->scale) { goto cleanup_else_1; } } @@ -349,8 +216,8 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->offset.value)) { goto cleanup_else_1; } - info.offset = ChannelValueClone(&value); - if (!info.offset) { + info->offset = ChannelValueClone(&value); + if (!info->offset) { goto cleanup_else_1; } } @@ -359,8 +226,8 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->default_.value)) { goto cleanup_else_1; } - info.defaultValue = ChannelValueClone(&value); - if (!info.defaultValue) { + info->defaultValue = ChannelValueClone(&value); + if (!info->defaultValue) { goto cleanup_else_1; } } @@ -369,43 +236,27 @@ static Vector * DatabusReadPortInput(PortInput * input) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->initial.value)) { goto cleanup_else_1; } - info.initialValue = ChannelValueClone(&value); - if (!info.initialValue) { + info->initialValue = ChannelValueClone(&value); + if (!info->initialValue) { goto cleanup_else_1; } } if (scalarPortInput->writeResults.defined) { - info.writeResult = scalarPortInput->writeResults.value; - } - - retVal = vector->Setup(vector, ChannelInfoGetName(&info), info.nameInTool, TRUE, -1, -1); - if (RETURN_ERROR == retVal) { - goto cleanup_else_1; - } - ChannelInfoSetVector(&info, (VectorChannelInfo *) object_strong_reference(vector)); - - list->PushBack(list, &info); - - retVal = vector->AddElement(vector, list->At(list, list->Size(list) - 1), 0); - if (RETURN_ERROR == retVal) { - goto cleanup_else_1; + info->writeResult = scalarPortInput->writeResults.value; } cleanup_else_1: - ChannelInfoDestroy(&info); ChannelValueDestructor(&value); goto cleanup_0; } cleanup_0: if (RETURN_ERROR == retVal) { - object_destroy(list); + object_destroy(info); } - object_destroy(vector); - - return list; + return info; } static int ChannelInfoSameNamePred(void * elem, const char * name) { @@ -439,10 +290,6 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, 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"); - return RETURN_ERROR; - } for (i = 0; i < numChildren; i++) { PortInput * portInput = (PortInput *) input->ports->At(input->ports, i); @@ -451,76 +298,32 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, } else { requiredSize += portInput->port.vectorPort->endIndex - portInput->port.vectorPort->startIndex + 1; } - } - - 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 %zu", i); + ChannelInfo * info = DatabusReadPortInput(portInput); + if (!info) { + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read info of port %d", i); return RETURN_ERROR; } - for (j = 0; j < infos->Size(infos); j++) { - ChannelInfo * info = (ChannelInfo *) infos->At(infos, j); - const char * name = ChannelInfoGetName(info); - int n = ChannelInfosGetNameIdx(dbInfos, name); + info->mode = mode; - if (n >= 0) { // key already exists - mcx_log(LOG_ERROR, "Ports: Duplicate port %s", name); - object_destroy(infos); - return RETURN_ERROR; - } + const char * name = ChannelInfoGetName(info); + if (info->dimension) { + mcx_log(LOG_DEBUG, " Port: \"%s[%d:%d]\"", name, info->dimension->startIdxs[0], info->dimension->endIdxs[0]); + } else { mcx_log(LOG_DEBUG, " Port: \"%s\"", name); - - info->mode = mode; } - 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 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; - } - } + if (RETURN_OK != allChannels->PushBackNamed(allChannels, (Object *) info, name)) { + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); + 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)); + if (RETURN_OK != dbInfos->PushBack(dbInfos, (Object *) object_strong_reference(info), name)) { + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); + return RETURN_ERROR; } - - object_destroy(infos); } + return RETURN_OK; } diff --git a/src/core/Databus.h b/src/core/Databus.h index dad4d21..d003e85 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -341,8 +341,6 @@ typedef struct Databus { size_t modeSwitchDataSize; } Databus; -char * CreateIndexedName(const char * name, unsigned i); - #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 58c281b..7019c44 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -565,6 +565,9 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * static McxStatus ChannelOutRegisterConnection(ChannelOut * out, Connection * connection) { ObjectList * conns = out->data->connections; + // TODO: do we have to check that channelout and connection match + // in type/dimension? + return conns->PushBack(conns, (Object *) connection); } diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c new file mode 100644 index 0000000..a0886b3 --- /dev/null +++ b/src/core/channels/ChannelDimension.c @@ -0,0 +1,67 @@ +/******************************************************************************** + * Copyright (c) 2021 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/channels/ChannelDimension.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +void ChannelDimensionDestructor(ChannelDimension * dimension) { + if (dimension->startIdxs) { mcx_free(dimension->startIdxs); } + if (dimension->endIdxs) { mcx_free(dimension->endIdxs); } +} + +ChannelDimension * ChannelDimensionCreate(ChannelDimension * dimension) { + dimension->num = 0; + dimension->startIdxs = NULL; + dimension->endIdxs = NULL; + + return dimension; +} + +OBJECT_CLASS(ChannelDimension, Object); + +McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num) { + dimension->num = num; + + dimension->startIdxs = (size_t *) mcx_calloc(dimension->num, sizeof(size_t)); + if (!dimension->startIdxs) { + goto error_cleanup; + } + dimension->endIdxs = (size_t *) mcx_calloc(dimension->num, sizeof(size_t)); + if (!dimension->endIdxs) { + goto error_cleanup; + } + + return RETURN_OK; + +error_cleanup: + if (dimension->startIdxs) { mcx_free(dimension->startIdxs); } + if (dimension->endIdxs) { mcx_free(dimension->endIdxs); } + + return RETURN_ERROR; +} + +McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end) { + if (num > dimension->num) { + return RETURN_ERROR; + } + + dimension->startIdxs[num] = start; + dimension->endIdxs[num] = end; + + return RETURN_OK; +} + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h new file mode 100644 index 0000000..20c11f1 --- /dev/null +++ b/src/core/channels/ChannelDimension.h @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2021 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_CHANNELS_CHANNELDIMENSION_H +#define MCX_CORE_CHANNELS_CHANNELDIMENSION_H + +#include "CentralParts.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern const struct ObjectClass _ChannelDimension; + +typedef struct ChannelDimension { + Object * _; // super class first + + size_t num; + size_t * startIdxs; + size_t * endIdxs; +} ChannelDimension; + + +McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); +McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); + + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif /* __cplusplus */ + +#endif // MCX_CORE_CHANNELS_CHANNELDIMENSION_H \ No newline at end of file diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index 14e0fbe..d75de81 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -285,6 +285,8 @@ void ChannelInfoDestroy(ChannelInfo * info) { McxStatus ChannelInfoInit(ChannelInfo * info) { info->vector = NULL; + info->dimension = NULL; + info->name = NULL; info->nameInTool = NULL; info->description = NULL; diff --git a/src/core/channels/ChannelInfo.h b/src/core/channels/ChannelInfo.h index ab26336..59815cb 100644 --- a/src/core/channels/ChannelInfo.h +++ b/src/core/channels/ChannelInfo.h @@ -13,6 +13,7 @@ #include "core/channels/ChannelValue.h" #include "core/channels/VectorChannelInfo.h" +#include "core/channels/ChannelDimension.h" #include "common/status.h" @@ -31,6 +32,9 @@ typedef struct ChannelInfo { struct Channel * channel; + // Channel is a scalar iff dimension == NULL + ChannelDimension * dimension; + char * name; char * nameInTool; char * description; diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 5c0e6f2..807e767 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -15,6 +15,16 @@ extern "C" { #endif /* __cplusplus */ +void * mcx_copy(void * object, size_t size) { + void * copy = mcx_malloc(size); + if (!copy) { + return NULL; + } + + memcpy(copy, object, size); + + return copy; +} ChannelType ChannelTypeUnknown = { CHANNEL_UNKNOWN, NULL}; ChannelType ChannelTypeInteger = { CHANNEL_INTEGER, NULL}; @@ -24,6 +34,57 @@ ChannelType ChannelTypeString = { CHANNEL_STRING, NULL}; ChannelType ChannelTypeBinary = { CHANNEL_BINARY, NULL}; ChannelType ChannelTypeBinaryReference = { CHANNEL_BINARY_REFERENCE, NULL}; + +ChannelType * ChannelTypeClone(ChannelType * type) { + switch (type->con) { + case CHANNEL_UNKNOWN: + case CHANNEL_INTEGER: + case CHANNEL_DOUBLE: + case CHANNEL_BOOL: + case CHANNEL_STRING: + case CHANNEL_BINARY: + case CHANNEL_BINARY_REFERENCE: + // Scalar types are used statically (&ChannelTypeDouble, etc) + return type; + case CHANNEL_ARRAY: { + ChannelType * clone = (ChannelType *) mcx_calloc(sizeof(ChannelType), 1); + if (!clone) { return NULL; } + + clone->con = type->con; + + clone->ty.a.inner = ChannelTypeClone(type->ty.a.inner); + clone->ty.a.numDims = type->ty.a.numDims; + clone->ty.a.dims = mcx_copy(type->ty.a.dims, sizeof(size_t) * type->ty.a.numDims); + if (!clone->ty.a.dims) { + mcx_free(clone); + return NULL; + } + + return clone; + } + } + + return NULL; +} + +void ChannelTypeDestructor(ChannelType * type) { + if (&ChannelTypeUnknown == type) { } + else if (&ChannelTypeInteger == type) { } + else if (&ChannelTypeDouble == type) { } + else if (&ChannelTypeBool == type) { } + else if (&ChannelTypeString == type) { } + else if (&ChannelTypeBinary == type) { } + else if (&ChannelTypeBinaryReference == type) { } + else if (type->con == CHANNEL_ARRAY) { + // other ChannelTypes are static + ChannelTypeDestructor(type->ty.a.inner); + mcx_free(type->ty.a.dims); + mcx_free(type); + } else { + mcx_free(type); + } +} + ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims) { ChannelType * array = NULL; @@ -136,7 +197,7 @@ size_t array_num_elements(array * a) { } void ChannelValueInit(ChannelValue * value, ChannelType * type) { - value->type = type; + value->type = ChannelTypeClone(type); ChannelValueDataInit(&value->value, type); } @@ -155,6 +216,7 @@ void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type) { // do not free references to binary, they are not owned by the ChannelValueData } else if (type->con == CHANNEL_ARRAY) { if (data->a.dims) { + mcx_free(data->a.dims); data->a.dims = NULL; } @@ -162,13 +224,12 @@ void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type) { mcx_free(data->a.data); data->a.data = NULL; } - // other ChannelTypes are static - mcx_free(type); } } void ChannelValueDestructor(ChannelValue * value) { ChannelValueDataDestructor(&value->value, value->type); + ChannelTypeDestructor(value->type); } static int isSpecialChar(unsigned char c) { @@ -242,6 +303,31 @@ char * ChannelValueToString(ChannelValue * value) { } } break; + case CHANNEL_ARRAY:{ + const char * doubleFmt = "% *.*E"; + + // TODO: + + length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; + length *= array_num_elements(&value->value.a); + buffer = (char *) mcx_malloc(sizeof(char) * length); + if (!buffer) { + return NULL; + } + + size_t i = 0; + size_t n = 0; + + if (array_num_elements(&value->value.a) > 0) { + n += sprintf(buffer + n, doubleFmt, (unsigned)precision, (unsigned)precision, ((double *)value->value.a.data)[0]); + for (i = 1; i < array_num_elements(&value->value.a); i++) { + n += sprintf(buffer + n, ","); + n += sprintf(buffer + n, doubleFmt, (unsigned)precision, (unsigned)precision, ((double *)value->value.a.data)[i]); + } + } + + break; + } default: return NULL; } @@ -315,6 +401,21 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel } } break; + case CHANNEL_ARRAY: { + const char * doubleFmt = "% *.*E"; + + // TODO: + + length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; + if (len < length) { + mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + return RETURN_ERROR; + } + sprintf(buffer, doubleFmt, (unsigned)precision, (unsigned)precision, *(double *)value->a.data); + + + break; + } default: mcx_log(LOG_DEBUG, "Port value to string: Unknown type"); return RETURN_ERROR; @@ -358,11 +459,17 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType * type) { data->b.len = 0; data->b.data = NULL; break; - case CHANNEL_ARRAY: - data->a.numDims = 0; - data->a.dims = NULL; - data->a.data = NULL; + case CHANNEL_ARRAY: { + void * tmp = data->a.dims; + data->a.type = ChannelTypeClone(type->ty.a.inner); + data->a.numDims = type->ty.a.numDims; + data->a.dims = (size_t *) mcx_calloc(sizeof(size_t), type->ty.a.numDims); + if (data->a.dims) { + memcpy(data->a.dims, type->ty.a.dims, type->ty.a.numDims * sizeof(size_t)); + } + data->a.data = mcx_calloc(array_num_elements(&data->a), ChannelValueTypeSize(data->a.type)); break; + } case CHANNEL_UNKNOWN: default: break; @@ -431,7 +538,7 @@ McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType return RETURN_ERROR; } - memcpy(data->a.data, a->data, ChannelValueTypeSize(a->type) * array_num_elements(a)); + memcpy(data->a.data, a->data, ChannelValueTypeSize(data->a.type) * array_num_elements(&data->a)); } case CHANNEL_UNKNOWN: default: @@ -601,6 +708,8 @@ const char * ChannelTypeToString(ChannelType * type) { } ChannelValue * ChannelValueClone(ChannelValue * value) { + if (!value) { return NULL; } + ChannelValue * clone = (ChannelValue *) mcx_malloc(sizeof(ChannelValue)); if (!clone) { return NULL; } @@ -704,6 +813,28 @@ McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { } } +// Does not take ownership of dims or data +ChannelValue * ChannelValueNewArray(size_t numDims, size_t dims[], ChannelType * type, void * data) { + ChannelValue * value = mcx_malloc(sizeof(ChannelValue)); + if (!value) { + return NULL; + } + + ChannelType * arrayType = ChannelTypeArray(type, numDims, dims); + if (!ChannelTypeIsValid(arrayType)) { + mcx_free(value); + return NULL; + } + ChannelValueInit(value, arrayType); + ChannelTypeDestructor(arrayType); + + if (value->value.a.data && data) { + memcpy(value->value.a.data, data, ChannelValueTypeSize(type) * array_num_elements(&value->value.a)); + } + + return value; +} + void ChannelValueDestroy(ChannelValue ** value) { ChannelValueDestructor(*value); mcx_free(*value); diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 1830d0b..278acaf 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -18,6 +18,8 @@ extern "C" { #endif /* __cplusplus */ +void * mcx_copy(void * object, size_t size); + // possible types of values that can be put on channels typedef enum ChannelTypeConstructor { CHANNEL_UNKNOWN = 0, @@ -53,6 +55,9 @@ extern ChannelType ChannelTypeBinary; extern ChannelType ChannelTypeBinaryReference; ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims); +ChannelType * ChannelTypeClone(ChannelType * type); +void ChannelTypeDestructor(ChannelType * type); + int ChannelTypeIsValid(ChannelType * a); int ChannelTypeIsScalar(ChannelType * a); int ChannelTypeIsArray(ChannelType * a); @@ -128,6 +133,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); size_t ChannelValueTypeSize(ChannelType * type); int ChannelTypeMatch(ChannelType * a, ChannelType * b); +ChannelValue * ChannelValueNewArray(size_t numDims, size_t dims[], ChannelType * type, void * data); void ChannelValueDestroy(ChannelValue ** value); ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType * type); diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index 606fdb6..1675ae6 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -160,6 +160,8 @@ McxStatus ConnectionInfoInit(ConnectionInfo * info) { info->connType_ = &ChannelTypeUnknown; + info->sourceDimension = NULL; + return RETURN_OK; } diff --git a/src/core/connections/ConnectionInfo.h b/src/core/connections/ConnectionInfo.h index 23cbff0..8c18150 100644 --- a/src/core/connections/ConnectionInfo.h +++ b/src/core/connections/ConnectionInfo.h @@ -13,6 +13,7 @@ #include "CentralParts.h" #include "core/Component_interface.h" +#include "core/channels/ChannelDimension.h" #define DECOUPLE_DEFAULT DECOUPLE_IFNEEDED @@ -48,6 +49,7 @@ typedef struct ConnectionInfo { DecoupleType decoupleType; int decouplePriority; + ChannelDimension * sourceDimension; } ConnectionInfo; diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 6de46c3..f0f774b 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -10,9 +10,11 @@ #include "core/connections/ConnectionInfoFactory.h" #include "core/connections/ConnectionInfo.h" +#include "core/channels/ChannelDimension.h" #include "core/Databus.h" #include "objects/Vector.h" +#include "util/stdlib.h" #include "util/string.h" #ifdef __cplusplus @@ -20,13 +22,27 @@ extern "C" { #endif /* __cplusplus */ -static McxStatus ConnectionInfoFactoryInitConnectionInfo( - ConnectionInfo * info, - ObjectContainer * components, - ConnectionInput * connInput, - Component * sourceCompOverride, - Component * targetCompOverride) -{ +char * CreateIndexedName(const char * name, unsigned i) { + size_t len = 0; + char * buffer = NULL; + + len = strlen(name) + (mcx_digits10(i) + 1) + 2 + 1; + + buffer = (char *) mcx_calloc(len, sizeof(char)); + if (!buffer) { + return NULL; + } + + snprintf(buffer, len, "%s[%d]", name, i); + + return buffer; +} + +static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, + ObjectContainer * components, + ConnectionInput * connInput, + Component * sourceCompOverride, + Component * targetCompOverride) { McxStatus retVal = RETURN_OK; int id = 0; @@ -105,19 +121,34 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo( 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; } + // TODO: multiplexing here? if (connInput->fromType == ENDPOINT_VECTOR) { - mcx_free(strFromChannel); - strFromChannel = CreateIndexedName(inputFromChannel, connInput->from.vectorEndpoint->startIndex); - if (!strFromChannel) { + ChannelDimension * sourceDimension = (ChannelDimension *) object_create(ChannelDimension); + if (!sourceDimension) { retVal = RETURN_ERROR; goto cleanup; } + + if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { + mcx_log(LOG_ERROR, "Could not setup ChannelDimension"); + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, (size_t) connInput->from.vectorEndpoint->startIndex, (size_t) connInput->from.vectorEndpoint->endIndex)) { + mcx_log(LOG_ERROR, "Could not SetDimension"); + retVal = RETURN_ERROR; + goto cleanup; + } + + info->sourceDimension = sourceDimension; } info->sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel); @@ -259,36 +290,8 @@ Vector * ConnectionInfoFactoryCreateConnectionInfos( goto cleanup; } - if (connInput->fromType == ENDPOINT_VECTOR || connInput->toType == ENDPOINT_VECTOR) { - /* vector of connections */ - int fromStartIndex = connInput->fromType == ENDPOINT_VECTOR ? connInput->from.vectorEndpoint->startIndex : 0; - int fromEndIndex = connInput->fromType == ENDPOINT_VECTOR ? connInput->from.vectorEndpoint->endIndex : 0; - - int toStartIndex = connInput->toType == ENDPOINT_VECTOR ? connInput->to.vectorEndpoint->startIndex : 0; - int toEndIndex = connInput->toType == ENDPOINT_VECTOR ? connInput->to.vectorEndpoint->endIndex : 0; - - int i = 0; - int fromStart = info.sourceChannel; - int toStart = info.targetChannel; - - if (fromEndIndex - fromStartIndex != toEndIndex - toStartIndex) { - /* the lenghts of both sides do not match */ - mcx_log(LOG_ERROR, "Connection: Lengths of vectors do not match"); - goto cleanup; - } - - for (i = 0; fromStartIndex + i <= fromEndIndex; i++) { - ConnectionInfo * copy = NULL; - - 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, &info); - } + /* info is the only connection: leave as is */ + list->PushBack(list, &info); return list; diff --git a/src/core/connections/ConnectionInfoFactory.h b/src/core/connections/ConnectionInfoFactory.h index 5881b14..e8494da 100644 --- a/src/core/connections/ConnectionInfoFactory.h +++ b/src/core/connections/ConnectionInfoFactory.h @@ -20,13 +20,12 @@ extern "C" { #endif /* __cplusplus */ - +char * CreateIndexedName(const char * name, unsigned i); Vector * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * components, ConnectionInput * connInput, Component * sourceCompOverride, Component * targetCompOverride); - #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ diff --git a/src/core/connections/ConnectionInfo_impl.h b/src/core/connections/ConnectionInfo_impl.h new file mode 100644 index 0000000..bd7bc91 --- /dev/null +++ b/src/core/connections/ConnectionInfo_impl.h @@ -0,0 +1,67 @@ +/******************************************************************************** + * 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 ChannelDimension */ +#include "core/channels/ChannelDimension.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; + + ChannelDimension * sourceDimension; + + // 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/FilteredConnection.c b/src/core/connections/FilteredConnection.c index e142869..bb7bf27 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -130,6 +130,8 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter } #endif + // TODO: copy only sourceDimension slice + if (filter && time->startTime >= 0) { ChannelValueData value = * (ChannelValueData *) channel->GetValueReference(channel); filter->SetValue(filter, time->startTime, value); From 458edde172a1206dfc4e7ee58cb53320eb560cb3 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 20 Jul 2021 10:01:24 +0200 Subject: [PATCH 123/295] storage: Expand arrays to scalars in the csv backend --- src/storage/StorageBackendCsv.c | 101 ++++++++++++++++++++++++++----- src/storage/StorageBackendText.c | 9 +++ 2 files changed, 95 insertions(+), 15 deletions(-) diff --git a/src/storage/StorageBackendCsv.c b/src/storage/StorageBackendCsv.c index f5bdef4..0a13c35 100644 --- a/src/storage/StorageBackendCsv.c +++ b/src/storage/StorageBackendCsv.c @@ -16,6 +16,7 @@ #include "storage/StorageBackendCsv.h" #include "storage/StorageBackendText_impl.h" #include "storage/PPD.h" +#include "core/connections/ConnectionInfoFactory.h" #include "util/string.h" #include "util/os.h" @@ -182,6 +183,29 @@ static char * QuoteString(const char * _str) { return newStr; } +static char * ExpandedChannelNames(const char * name, size_t start, size_t end) { + char ** names = (char **) mcx_malloc(sizeof(char *) * (end - start + 1 + 1)); + if (!names) { return NULL; } + + size_t i = 0; + + for (i = start; i <= end; i++) { + names[i-start] = CreateIndexedName(name, i); + } + names[i-start] = NULL; + + return names; +} + +static void FreeExpandedChannelNames(char ** names) { + size_t i = 0; + while (names[i]) { + mcx_free(names[i]); + ++i; + } + mcx_free(names); +} + static McxStatus SetupComponentFilesCsv(StorageBackend * backend) { StorageBackendText * textBackend = (StorageBackendText *) backend; ResultsStorage * storage = backend->storage; @@ -255,30 +279,77 @@ static McxStatus SetupComponentFilesCsv(StorageBackend * backend) { for (chIdx = 0; chIdx < chNum; chIdx++) { ChannelInfo * info = chStore->GetChannelInfo(chStore, chIdx); const char * channelName = ChannelInfoGetName(info); - char * quotedChannelName = QuoteString(channelName); - const char * sep = textBackend->separator; - - if (chIdx == 0) { - sep = ""; - } - if(quotedChannelName){ - mcx_os_fprintf(textFile->fp, "%s\"%s\"", sep, quotedChannelName); - mcx_free(quotedChannelName); + ChannelType * type = info->type; + + if (ChannelTypeIsArray(type)) { + if (type->ty.a.numDims > 1) { + // multi-dim not yet supported + continue; + } + ChannelDimension * dimension = info->dimension; + size_t array_start = dimension->startIdxs[0]; + size_t array_end = dimension->endIdxs[0]; + + size_t array_idx = 0; + + char ** names = ExpandedChannelNames(channelName, array_start, array_end); + const char * sep = textBackend->separator; + while (names[array_idx]) { + char * quotedChannelName = QuoteString(names[array_idx]); + + if(quotedChannelName){ + mcx_os_fprintf(textFile->fp, "%s\"%s\"", sep, quotedChannelName); + mcx_free(quotedChannelName); + } else { + mcx_os_fprintf(textFile->fp, "%s", sep); + } + ++array_idx; + } + FreeExpandedChannelNames(names); } else { - mcx_os_fprintf(textFile->fp, "%s", sep); + char * quotedChannelName = QuoteString(channelName); + const char * sep = textBackend->separator; + + if (chIdx == 0) { + sep = ""; + } + if(quotedChannelName){ + mcx_os_fprintf(textFile->fp, "%s\"%s\"", sep, quotedChannelName); + mcx_free(quotedChannelName); + } else { + mcx_os_fprintf(textFile->fp, "%s", sep); + } } - } mcx_os_fprintf(textFile->fp, "\n"); for (chIdx = 0; chIdx < chNum; chIdx++) { ChannelInfo * info = chStore->GetChannelInfo(chStore, chIdx); + ChannelType * type = info->type; const char * channelUnit = info->unitString; - const char * sep = textBackend->separator; - if (chIdx == 0) { - sep = ""; + + if (ChannelTypeIsArray(type)) { + if (type->ty.a.numDims > 1) { + // multi-dim not yet supported + continue; + } + ChannelDimension * dimension = info->dimension; + size_t array_start = dimension->startIdxs[0]; + size_t array_end = dimension->endIdxs[0]; + + size_t array_idx = 0; + + const char * sep = textBackend->separator; + for (array_idx = array_start; array_idx <= array_end; array_idx++) { + mcx_os_fprintf(textFile->fp, "%s%s", sep, channelUnit); + } + } else { + const char * sep = textBackend->separator; + if (chIdx == 0) { + sep = ""; + } + mcx_os_fprintf(textFile->fp, "%s%s", sep, channelUnit); } - mcx_os_fprintf(textFile->fp, "%s%s", sep, channelUnit); } mcx_os_fprintf(textFile->fp, "\n"); } diff --git a/src/storage/StorageBackendText.c b/src/storage/StorageBackendText.c index 2f99855..b14f4c6 100644 --- a/src/storage/StorageBackendText.c +++ b/src/storage/StorageBackendText.c @@ -215,6 +215,9 @@ static McxStatus WriteRow(FILE * file, ChannelValue * values, size_t numChannels if (channel == 0) { // leave out separator at the beginning sep = ""; } + + // TODO: This should not mention CHANNEL_* anymore + switch (ChannelValueType(&val)->con) { case CHANNEL_DOUBLE: case CHANNEL_INTEGER: @@ -245,6 +248,12 @@ static McxStatus WriteRow(FILE * file, ChannelValue * values, size_t numChannels } break; } + case CHANNEL_ARRAY: { + char * str = ChannelValueToString(&val); + mcx_os_fprintf(file, "%s%s", sep, str); + mcx_free(str); + break; + } default: mcx_os_fprintf(file, "%s\"\"", sep); break; From 24cbf758778cbc9b8e3c1bcbc61d6587c6485e5e Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 6 Sep 2021 14:58:26 +0200 Subject: [PATCH 124/295] channel: Add ChannelTypeBaseType --- src/core/channels/ChannelValue.c | 8 ++++++++ src/core/channels/ChannelValue.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 807e767..25207df 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -126,6 +126,14 @@ int ChannelTypeIsBinary(ChannelType * a) { return a->con == CHANNEL_BINARY || a->con == CHANNEL_BINARY_REFERENCE; } +ChannelType * ChannelTypeBaseType(ChannelType * a) { + if (ChannelTypeIsArray(a)) { + return ChannelTypeBaseType(a->ty.a.inner); + } else { + return a; + } +} + int ChannelTypeEq(ChannelType * a, ChannelType * b) { if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { size_t i = 0; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 278acaf..5ee85ca 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -63,6 +63,8 @@ int ChannelTypeIsScalar(ChannelType * a); int ChannelTypeIsArray(ChannelType * a); int ChannelTypeIsBinary(ChannelType * a); +ChannelType * ChannelTypeBaseType(ChannelType * a); + int ChannelTypeEq(ChannelType * a, ChannelType * b); typedef struct MapStringChannelType { From 0de5c26e495153b545dbd7511802c505e794ee00 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Thu, 22 Jul 2021 09:24:04 +0200 Subject: [PATCH 125/295] channel: Add ChannelValueNewScalar --- src/core/channels/ChannelValue.c | 13 +++++++++++++ src/core/channels/ChannelValue.h | 1 + 2 files changed, 14 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 25207df..9a77972 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -821,6 +821,19 @@ McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { } } +// Does not take ownership of dims or data +ChannelValue * ChannelValueNewScalar(ChannelType * type, void * data) { + ChannelValue * value = mcx_malloc(sizeof(ChannelValue)); + if (!value) { + return NULL; + } + + ChannelValueInit(value, type); + ChannelValueSetFromReference(value, data); + + return value; +} + // Does not take ownership of dims or data ChannelValue * ChannelValueNewArray(size_t numDims, size_t dims[], ChannelType * type, void * data) { ChannelValue * value = mcx_malloc(sizeof(ChannelValue)); diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 5ee85ca..be15765 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -135,6 +135,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source); size_t ChannelValueTypeSize(ChannelType * type); int ChannelTypeMatch(ChannelType * a, ChannelType * b); +ChannelValue * ChannelValueNewScalar(ChannelType * type, void * data); ChannelValue * ChannelValueNewArray(size_t numDims, size_t dims[], ChannelType * type, void * data); void ChannelValueDestroy(ChannelValue ** value); From 888534e8cec4faf16d5cef70e835c4ca6dc425d7 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Thu, 22 Jul 2021 09:23:27 +0200 Subject: [PATCH 126/295] constant: Remove use of VectorChannelInfo --- src/components/comp_constant.c | 55 +++++++++++----------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index 1825b67..c1b1140 100644 --- a/src/components/comp_constant.c +++ b/src/components/comp_constant.c @@ -10,6 +10,7 @@ #include "components/comp_constant.h" +#include "core/channels/ChannelValue.h" #include "core/Databus.h" #include "reader/model/components/specific_data/ConstantInput.h" @@ -23,37 +24,27 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con ConstantInput * constantInput = (ConstantInput *)input; Databus * db = comp->GetDatabus(comp); - size_t numVecOut = DatabusGetOutVectorChannelsNum(db); + size_t numOut = DatabusGetOutChannelsNum(db); - // We read each vector channel (scalars are vectors of length 1) - // and the corresponding values from the input file. - compConstant->values = (ChannelValue **)mcx_calloc(numVecOut, sizeof(ChannelValue *)); + compConstant->values = (ChannelValue **)mcx_calloc(numOut, sizeof(ChannelValue *)); if (constantInput->values) { ConstantValuesInput * values = constantInput->values; size_t i = 0; - for (i = 0; i < numVecOut; i++) { + for (i = 0; i < numOut; i++) { ConstantValueInput * value = (ConstantValueInput *)values->values->At(values->values, i); if (value->type == CONSTANT_VALUE_SCALAR) { - compConstant->values[i] = (ChannelValue *)mcx_calloc(1, sizeof(ChannelValue)); - ChannelValueInit(compConstant->values[i], value->value.scalar->type); - if (RETURN_OK != ChannelValueSetFromReference(compConstant->values[i], &value->value.scalar->value)) { + compConstant->values[i] = ChannelValueNewScalar(value->value.scalar->type, &value->value.scalar->value); + if (!compConstant->values[i]) { ComponentLog(comp, LOG_ERROR, "Could not set channel value"); return RETURN_ERROR; } } else { - size_t j = 0; - size_t size = ChannelValueTypeSize(value->value.array->type); - compConstant->values[i] = (ChannelValue *)mcx_calloc(value->value.array->numValues, - sizeof(ChannelValue)); - for (j = 0; j < value->value.array->numValues; j++) { - ChannelValueInit(compConstant->values[i] + j, value->value.array->type); - if (RETURN_OK != ChannelValueSetFromReference(compConstant->values[i] + j, - (char *)value->value.array->values + j * size)) { - ComponentLog(comp, LOG_ERROR, "Could not set channel value"); - return RETURN_ERROR; - } + compConstant->values[i] = ChannelValueNewArray(1, &value->value.array->numValues, value->value.array->type, value->value.array->values); + if (!compConstant->values[i]) { + ComponentLog(comp, LOG_ERROR, "Could not set channel value"); + return RETURN_ERROR; } } } @@ -103,16 +94,12 @@ static McxStatus Setup(Component * comp) { CompConstant * constComp = (CompConstant *)comp; McxStatus retVal = RETURN_OK; Databus * db = comp->GetDatabus(comp); - size_t numVecOut = DatabusGetOutVectorChannelsNum(db); + size_t numOut = DatabusGetOutChannelsNum(db); size_t i = 0; - for (i = 0; i < numVecOut; i++) { - VectorChannelInfo * vInfo = DatabusGetOutVectorChannelInfo(db, i); - size_t startIdx = vInfo->GetStartIndex(vInfo); - size_t endIdx = vInfo->GetEndIndex(vInfo); - size_t numCh = endIdx - startIdx; - retVal = DatabusSetOutRefVectorChannel(db, i, startIdx, endIdx, constComp->values[i]); + for (i = 0; i < numOut; i++) { + retVal = DatabusSetOutReference(db, i, (void *) &constComp->values[i]->value, constComp->values[i]->type); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; @@ -134,18 +121,12 @@ static void CompConstantDestructor(CompConstant * compConst) { Component * comp = (Component *)compConst; McxStatus retVal = RETURN_OK; Databus * db = comp->GetDatabus(comp); - size_t numVecOut = DatabusGetOutVectorChannelsNum(db); + size_t numOut = DatabusGetOutChannelsNum(db); - if (numVecOut > 0 && compConst->values != NULL) { - size_t i, j; - for (i = 0; i < numVecOut; i++) { - VectorChannelInfo * vInfo = DatabusGetOutVectorChannelInfo(db, i); - size_t startIdx = vInfo->GetStartIndex(vInfo); - size_t endIdx = vInfo->GetEndIndex(vInfo); - size_t numCh = endIdx - startIdx + 1; - for (j = 0; j < numCh; j++) { - ChannelValueDestructor(&compConst->values[i][j]); - } + if (numOut > 0 && compConst->values != NULL) { + size_t i; + for (i = 0; i < numOut; i++) { + ChannelValueDestructor(compConst->values[i]); mcx_free(compConst->values[i]); } mcx_free(compConst->values); From e8e149519713111d8e2bf60723bef3f87070c7bc Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Fri, 10 Sep 2021 12:08:49 +0200 Subject: [PATCH 127/295] value: Add array_destroy --- src/core/channels/ChannelValue.c | 6 ++++++ src/core/channels/ChannelValue.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 9a77972..543b52c 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -170,6 +170,12 @@ McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * inn return RETURN_OK; } +void array_destroy(array * a) { + if (a->dims) { mcx_free(a->dims); } + if (a->data) { mcx_free(a->data); } + if (a->type) { ChannelTypeDestructor(a->type); } +} + int array_dims_match(array * a, array * b) { size_t i = 0; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index be15765..8d79666 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -96,6 +96,7 @@ typedef struct { } array; McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * type); +void array_destroy(array * a); int array_dims_match(array * a, array * b); size_t array_num_elements(array * a); From 67c0d1bb3b1466c3fd50086509d3b1678346de41 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Fri, 20 Aug 2021 06:40:25 +0200 Subject: [PATCH 128/295] vector_integrator: Remove use of VectorChannelInfo --- src/components/comp_vector_integrator.c | 123 +++++++++++++++--------- 1 file changed, 77 insertions(+), 46 deletions(-) diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 6eaeda6..295ac6b 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -11,6 +11,7 @@ #include "components/comp_vector_integrator.h" #include "core/Databus.h" +#include "core/channels/ChannelValue.h" #include "reader/model/components/specific_data/VectorIntegratorInput.h" #ifdef __cplusplus @@ -20,9 +21,10 @@ extern "C" { typedef struct CompVectorIntegrator { Component _; - size_t numStates; - double * state; - double * deriv; + size_t num; + + ChannelValue * state; + ChannelValue * deriv; double initialState; @@ -33,32 +35,52 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con CompVectorIntegrator * integrator = (CompVectorIntegrator *) comp; VectorIntegratorInput * integratorInput = (VectorIntegratorInput *) input; - size_t numAllIn = 0, numAllOut = 0; size_t i = 0; Databus * db = comp->GetDatabus(comp); - size_t numVecIn = DatabusGetInVectorChannelsNum(db); - size_t numVecOut = DatabusGetOutVectorChannelsNum(db); + size_t numIn = DatabusGetInChannelsNum(db); + size_t numOut = DatabusGetOutChannelsNum(db); - for (i = 0; i < numVecIn; i++) { - VectorChannelInfo *vInfo = DatabusGetInVectorChannelInfo(db, i); - size_t numCh = vInfo->GetEndIndex(vInfo) - vInfo->GetStartIndex(vInfo) + 1; - numAllIn += numCh; + if (numIn != numOut) { + ComponentLog(comp, LOG_ERROR, "#inports (%d) does not match the #outports (%d)", numIn, numOut); + return RETURN_ERROR; } - for (i = 0; i < numVecOut; i++) { - VectorChannelInfo *vInfo = DatabusGetOutVectorChannelInfo(db, i); - size_t numCh = vInfo->GetEndIndex(vInfo) - vInfo->GetStartIndex(vInfo) + 1; - numAllOut += numCh; + + integrator->num = numOut; + + integrator->deriv = mcx_calloc(sizeof(ChannelValue), integrator->num); + if (!integrator->deriv) { + return RETURN_ERROR; } - if (numAllIn != numAllOut) { - ComponentLog(comp, LOG_ERROR, "#inports (%d) does not match the #outports (%d)", numAllIn, numAllOut); + integrator->state = mcx_calloc(sizeof(ChannelValue), integrator->num); + if (!integrator->state) { return RETURN_ERROR; } - integrator->numStates = numAllOut; integrator->initialState = integratorInput->initialState.defined ? integratorInput->initialState.value : 0.0; + for (i = 0; i < integrator->num; i++) { + ChannelInfo * inInfo = DatabusGetInChannelInfo(db, i); + ChannelInfo * outInfo = DatabusGetOutChannelInfo(db, i); + + if (!ChannelTypeEq(inInfo->GetType(inInfo), outInfo->GetType(outInfo))) { + ComponentLog(comp, LOG_ERROR, "Types of inport %s and outport %s do not match", inInfo->GetName(inInfo), outInfo->GetName(outInfo)); + return RETURN_ERROR; + } + + ChannelInfo * info = outInfo; + ChannelType * type = info->GetType(info); + + if (!ChannelTypeEq(type, &ChannelTypeDouble) || ChannelTypeIsArray(type)) { + ComponentLog(comp, LOG_ERROR, "Inport %s: Invalid type", info->GetName(info)); + return RETURN_ERROR; + } + + ChannelValueInit(&integrator->deriv[i], type); + ChannelValueInit(&integrator->state[i], type); + } + return RETURN_OK; } @@ -66,40 +88,26 @@ static McxStatus Setup(Component * comp) { CompVectorIntegrator * integrator = (CompVectorIntegrator *) comp; McxStatus retVal = RETURN_OK; Databus * db = comp->GetDatabus(comp); - size_t numVecIn = DatabusGetInVectorChannelsNum(db); - size_t numVecOut = DatabusGetOutVectorChannelsNum(db); + size_t numIn = DatabusGetInChannelsNum(db); + size_t numOut = DatabusGetOutChannelsNum(db); size_t i = 0; - size_t nextIdx = 0; - - integrator->deriv = (double *) mcx_malloc(integrator->numStates * sizeof(double)); - integrator->state = (double *) mcx_malloc(integrator->numStates * sizeof(double)); - - nextIdx = 0; - for (i = 0; i < numVecIn; i++) { - VectorChannelInfo *vInfo = DatabusGetInVectorChannelInfo(db, i); - size_t startIdx = vInfo->GetStartIndex(vInfo); - size_t endIdx = vInfo->GetEndIndex(vInfo); - size_t numCh = endIdx - startIdx; - retVal = DatabusSetInRefVector(db, i, startIdx, endIdx, integrator->deriv + nextIdx, &ChannelTypeDouble); + + for (i = 0; i < integrator->num; i++) { + ChannelInfo * inInfo = DatabusGetInChannelInfo(db, i); + ChannelInfo * outInfo = DatabusGetOutChannelInfo(db, i); + + retVal = DatabusSetInReference(db, i, ChannelValueReference(&integrator->deriv[i]), inInfo->GetType(inInfo)); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; } - nextIdx = nextIdx + numCh + 1; - } - nextIdx = 0; - for (i = 0; i < numVecOut; i++) { - VectorChannelInfo *vInfo = DatabusGetOutVectorChannelInfo(db, i); - size_t startIdx = vInfo->GetStartIndex(vInfo); - size_t endIdx = vInfo->GetEndIndex(vInfo); - size_t numCh = endIdx - startIdx; - retVal = DatabusSetOutRefVector(db, i, startIdx, endIdx, integrator->state + nextIdx, &ChannelTypeDouble); + retVal = DatabusSetOutReference(db, i, ChannelValueReference(&integrator->state[i]), outInfo->GetType(outInfo)); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; } - nextIdx = nextIdx + numCh + 1; + } return RETURN_OK; @@ -109,8 +117,22 @@ static McxStatus Setup(Component * comp) { static McxStatus DoStep(Component * comp, size_t group, double time, double deltaTime, double endTime, int isNewStep) { CompVectorIntegrator * integrator = (CompVectorIntegrator *) comp; size_t i; - for (i = 0; i < integrator->numStates; i++) { - integrator->state[i] = integrator->state[i] + integrator->deriv[i] * deltaTime; + for (i = 0; i < integrator->num; i++) { + if (ChannelTypeIsArray(ChannelValueType(&integrator->state[i]))) { + array * state = ChannelValueReference(&integrator->state[i]); + array * deriv = ChannelValueReference(&integrator->deriv[i]); + + size_t j = 0; + for (j = 0; j < array_num_elements(state); j++) { + ((double *)state->data)[j] = ((double *)state->data)[j] * ((double *)deriv->data)[j] + deltaTime; + } + + } else { + double * state = (double *) ChannelValueReference(&integrator->state[i]); + double * deriv = (double *) ChannelValueReference(&integrator->deriv[i]); + + (*state) = (*state) * (*deriv) + deltaTime; + } } return RETURN_OK; @@ -120,8 +142,17 @@ static McxStatus DoStep(Component * comp, size_t group, double time, double delt static McxStatus Initialize(Component * comp, size_t idx, double startTime) { CompVectorIntegrator * integrator = (CompVectorIntegrator *) comp; size_t i; - for (i = 0; i < integrator->numStates; i++) { - integrator->state[i] = integrator->initialState; + for (i = 0; i < integrator->num; i++) { + if (ChannelTypeIsArray(ChannelValueType(&integrator->state[i]))) { + array * a = (array *) ChannelValueReference(&integrator->state[i]); + size_t j; + + for (j = 0; j < array_num_elements(a); j++) { + ((double *) a->data)[j] = integrator->initialState; + } + } else { + ChannelValueSetFromReference(&integrator->state[i], &integrator->initialState); + } } return RETURN_OK; } @@ -146,7 +177,7 @@ static Component * CompVectorIntegratorCreate(Component * comp) { // local values self->initialState = 0.; - self->numStates = 0; + self->num = 0; self->state = NULL; self->deriv = NULL; From b790646e4ca47eb96e098c82a67089f3af163e45 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 09:15:23 +0200 Subject: [PATCH 129/295] ChannelValueToString: Support ChannelTypeArray --- src/core/channels/ChannelValue.c | 34 +++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 543b52c..7dbe76e 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -251,6 +251,19 @@ static int isSpecialChar(unsigned char c) { return (c < ' ' || c > '~'); } +size_t ChannelValueDataDoubleToBuffer(char * buffer, void * value, size_t i) { + const size_t precision = 13; + return sprintf(buffer, "%*.*E", (unsigned) precision, (unsigned) precision, ((double *) value)[i]); +} + +size_t ChannelValueDataIntegerToBuffer(char * buffer, void * value, size_t i) { + return sprintf(buffer, "%d", ((int *) value)[i]); +} + +size_t ChannelValueDataBoolToBuffer(char * buffer, void * value, size_t i) { + return sprintf(buffer, "%1d", (((int *) value)[i] != 0) ? 1 : 0); +} + char * ChannelValueToString(ChannelValue * value) { size_t i = 0; size_t length = 0; @@ -265,7 +278,7 @@ char * ChannelValueToString(ChannelValue * value) { if (!buffer) { return NULL; } - sprintf(buffer, "%*.*E", (unsigned) precision, (unsigned) precision, value->value.d); + ChannelValueDataDoubleToBuffer(buffer, &value->value.d, 0); break; case CHANNEL_INTEGER: length = 1 /* sign */ + mcx_digits10(abs(value->value.i)) + 1 /* string termination*/; @@ -273,7 +286,7 @@ char * ChannelValueToString(ChannelValue * value) { if (!buffer) { return NULL; } - sprintf(buffer, "%d", value->value.i); + ChannelValueDataIntegerToBuffer(buffer, &value->value.i, 0); break; case CHANNEL_BOOL: length = 2; @@ -281,7 +294,7 @@ char * ChannelValueToString(ChannelValue * value) { if (!buffer) { return NULL; } - sprintf(buffer, "%1d", (value->value.i != 0) ? 1 : 0); + ChannelValueDataBoolToBuffer(buffer, &value->value.i, 0); break; case CHANNEL_STRING: if (!value->value.s) { @@ -318,6 +331,17 @@ char * ChannelValueToString(ChannelValue * value) { } break; case CHANNEL_ARRAY:{ + size_t (*fmt)(char * buffer, void * value, size_t i); + if (ChannelTypeEq(ChannelTypeArrayInner(value->type), &ChannelTypeDouble)) { + fmt = ChannelValueDataDoubleToBuffer; + } else if (ChannelTypeEq(ChannelTypeArrayInner(value->type), &ChannelTypeInteger)) { + fmt = ChannelValueDataIntegerToBuffer; + } else if (ChannelTypeEq(ChannelTypeArrayInner(value->type), &ChannelTypeBool)) { + fmt = ChannelValueDataBoolToBuffer; + } else { + return NULL; + } + const char * doubleFmt = "% *.*E"; // TODO: @@ -333,10 +357,10 @@ char * ChannelValueToString(ChannelValue * value) { size_t n = 0; if (array_num_elements(&value->value.a) > 0) { - n += sprintf(buffer + n, doubleFmt, (unsigned)precision, (unsigned)precision, ((double *)value->value.a.data)[0]); + n += fmt(buffer + n, value->value.a.data, 0); for (i = 1; i < array_num_elements(&value->value.a); i++) { n += sprintf(buffer + n, ","); - n += sprintf(buffer + n, doubleFmt, (unsigned)precision, (unsigned)precision, ((double *)value->value.a.data)[i]); + n += fmt(buffer + n, value->value.a.data, i); } } From d1f3404356f159f029a6e576a37c5eb92c60176b Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 09:16:15 +0200 Subject: [PATCH 130/295] channel: Add ChannelTypeArrayInner --- src/core/channels/ChannelValue.c | 8 ++++++++ src/core/channels/ChannelValue.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 7dbe76e..f346cdf 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -110,6 +110,14 @@ ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dim return array; } +ChannelType * ChannelTypeArrayInner(ChannelType * array) { + if (!ChannelTypeIsArray(array)) { + return &ChannelTypeUnknown; + } + + return array->ty.a.inner; +} + int ChannelTypeIsValid(ChannelType * a) { return a->con != CHANNEL_UNKNOWN; } diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 8d79666..a2a8dc8 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -58,6 +58,8 @@ ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dim ChannelType * ChannelTypeClone(ChannelType * type); void ChannelTypeDestructor(ChannelType * type); +ChannelType * ChannelTypeArrayInner(ChannelType * array); + int ChannelTypeIsValid(ChannelType * a); int ChannelTypeIsScalar(ChannelType * a); int ChannelTypeIsArray(ChannelType * a); From acb52ef43326a7527ecac9cc79328c8da530edcc Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 09:17:31 +0200 Subject: [PATCH 131/295] fmu: Support ChannelTypeArray --- src/components/comp_fmu.c | 146 ++++++++++++++++++------ src/components/comp_vector_integrator.c | 12 +- src/fmu/Fmu2Value.c | 115 +++++++++++++------ src/fmu/Fmu2Value.h | 17 ++- src/fmu/common_fmu2.c | 39 +++++++ 5 files changed, 249 insertions(+), 80 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index eb9edd6..2f28f20 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -15,6 +15,7 @@ #include "core/Databus.h" #include "core/Component_impl.h" #include "core/channels/ChannelInfo.h" +#include "core/connections/ConnectionInfoFactory.h" #include "fmilib.h" #include "fmu/Fmu1Value.h" #include "fmu/Fmu2Value.h" @@ -399,14 +400,14 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat val->SetChannel(val, info->channel); - if (!ChannelTypeEq(val->val.type, info->type)) { + if (!ChannelTypeIsValid(val->val.type)) { ChannelValueInit(&val->val, info->type); } retVal = DatabusSetInReference(db, i, ChannelValueReference(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "%s: Could not set reference for channel %s", logPrefix, channelName); + mcx_log(LOG_ERROR, "%s: Could not set reference for channel %s", logPrefix, val->name); return RETURN_ERROR; } } @@ -504,6 +505,80 @@ static McxStatus Fmu2Setup(Component * comp) { return RETURN_OK; } +static Fmu2Value * Fmu2ReadFmu2ScalarValue(const char * logPrefix, ChannelType * type, const char * channelName, const char * unitString, fmi2_import_t * fmiImport) { + Fmu2Value * val = NULL; + fmi2_import_variable_t * var = NULL; + + var = fmi2_import_get_variable_by_name(fmiImport, channelName); + if (!var) { + mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, channelName); + return NULL; + } + + if (!ChannelTypeEq(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(type), + ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); + return NULL; + } + + val = Fmu2ValueScalarMake(channelName, var, unitString, NULL); + if (!val) { + mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + return NULL; + } + + return val; +} + +static Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, const char * channelName, ChannelDimension * dimension, const char * unitString, fmi2_import_t * fmiImport) { + Fmu2Value * val = NULL; + fmi2_import_variable_t * var = NULL; + + if (dimension->num > 1) { + mcx_log(LOG_ERROR, "%s: Port %s: Invalid dimension", logPrefix, channelName); + return RETURN_ERROR; + } + + size_t i = 0; + size_t startIdx = dimension->startIdxs[0]; + size_t endIdx = dimension->endIdxs[0]; + + fmi2_import_variable_t ** vars = mcx_calloc(endIdx - startIdx + 1, sizeof(fmi2_import_variable_t *)); + if (!vars) { + return NULL; + } + + for (i = startIdx; i <= endIdx; i++) { + char * indexedChannelName = CreateIndexedName(channelName, i); + fmi2_import_variable_t * var = fmi2_import_get_variable_by_name(fmiImport, indexedChannelName); + if (!var) { + mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, indexedChannelName); + return NULL; + } + if (!ChannelTypeEq(ChannelTypeArrayInner(type), Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))) { + mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, indexedChannelName); + mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, + ChannelTypeToString(ChannelTypeArrayInner(type)), + ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); + return NULL; + } + vars[i - startIdx] = var; + + mcx_free(indexedChannelName); + } + + size_t dims[] = { endIdx - startIdx + 1 }; + val = Fmu2ValueArrayMake(channelName, 1 /* numDims */, dims, vars, unitString, NULL); + if (!val) { + mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + return NULL; + } + + return val; +} + static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Databus * db, fmi2_import_t * fmiImport, const char * logPrefix) { McxStatus retVal = RETURN_OK; @@ -582,33 +657,33 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab mcx_free(channelNameLo); mcx_free(channelNameHi); mcx_free(channelNameSize); - } else { // scalar - var = fmi2_import_get_variable_by_name(fmiImport, channelName); - if (!var) { - mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, channelName); + + retVal = vals->PushBack(vals, (Object *)val); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix, channelName); return RETURN_ERROR; } + } else if (info->dimension) { + val = Fmu2ReadFmu2ArrayValue(logPrefix, info->type, channelName, info->dimension, info->unitString, fmiImport); - if (!ChannelTypeEq(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->type), - ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); + val->SetChannel(val, info->channel); + + retVal = vals->PushBack(vals, (Object *)val); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix, channelName); return RETURN_ERROR; } + } else { // scalar + val = Fmu2ReadFmu2ScalarValue(logPrefix, info->type, channelName, info->unitString, fmiImport); - val = Fmu2ValueScalarMake(channelName, var, info->unitString, NULL); - if (!val) { - mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + val->SetChannel(val, info->channel); + + retVal = vals->PushBack(vals, (Object *)val); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix, channelName); return RETURN_ERROR; } } - - retVal = vals->PushBack(vals, (Object *)val); - if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix, channelName); - return RETURN_ERROR; - } } return RETURN_OK; @@ -691,32 +766,29 @@ static McxStatus Fmu2ReadChannelOut(ObjectContainer /* Fmu2Value */ * vals, Data mcx_free(channelNameLo); mcx_free(channelNameHi); mcx_free(channelNameSize); - } else { // scalar - var = fmi2_import_get_variable_by_name(fmiImport, channelName); - if (!var) { - mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix , channelName); + + retVal = vals->PushBack(vals, (Object *)val); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix , channelName); return RETURN_ERROR; } + } else if (info->dimension) { + val = Fmu2ReadFmu2ArrayValue(logPrefix, info->type, channelName, info->dimension, info->unitString, fmiImport); - if (!ChannelTypeEq(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->type), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); + retVal = vals->PushBack(vals, (Object *)val); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix, channelName); return RETURN_ERROR; } + } else { // scalar + val = Fmu2ReadFmu2ScalarValue(logPrefix, info->type, channelName, info->unitString, fmiImport); - val = Fmu2ValueScalarMake(channelName, var, info->unitString, NULL); - if (!val) { - mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix , channelName); + retVal = vals->PushBack(vals, (Object *)val); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix, channelName); return RETURN_ERROR; } } - - retVal = vals->PushBack(vals, (Object *)val); - if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "%s: Could not store value for %s", logPrefix , channelName); - return RETURN_ERROR; - } } return RETURN_OK; diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 295ac6b..d14424f 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -64,16 +64,16 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con ChannelInfo * inInfo = DatabusGetInChannelInfo(db, i); ChannelInfo * outInfo = DatabusGetOutChannelInfo(db, i); - if (!ChannelTypeEq(inInfo->GetType(inInfo), outInfo->GetType(outInfo))) { - ComponentLog(comp, LOG_ERROR, "Types of inport %s and outport %s do not match", inInfo->GetName(inInfo), outInfo->GetName(outInfo)); + if (!ChannelTypeEq(inInfo->type, outInfo->type)) { + ComponentLog(comp, LOG_ERROR, "Types of inport %s and outport %s do not match", ChannelInfoGetName(inInfo), ChannelInfoGetName(outInfo)); return RETURN_ERROR; } ChannelInfo * info = outInfo; - ChannelType * type = info->GetType(info); + ChannelType * type = info->type; if (!ChannelTypeEq(type, &ChannelTypeDouble) || ChannelTypeIsArray(type)) { - ComponentLog(comp, LOG_ERROR, "Inport %s: Invalid type", info->GetName(info)); + ComponentLog(comp, LOG_ERROR, "Inport %s: Invalid type", ChannelInfoGetName(info)); return RETURN_ERROR; } @@ -96,13 +96,13 @@ static McxStatus Setup(Component * comp) { ChannelInfo * inInfo = DatabusGetInChannelInfo(db, i); ChannelInfo * outInfo = DatabusGetOutChannelInfo(db, i); - retVal = DatabusSetInReference(db, i, ChannelValueReference(&integrator->deriv[i]), inInfo->GetType(inInfo)); + retVal = DatabusSetInReference(db, i, ChannelValueReference(&integrator->deriv[i]), inInfo->type); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; } - retVal = DatabusSetOutReference(db, i, ChannelValueReference(&integrator->state[i]), outInfo->GetType(outInfo)); + retVal = DatabusSetOutReference(db, i, ChannelValueReference(&integrator->state[i]), outInfo->type); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 9be5076..2ae6329 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -13,6 +13,7 @@ #include "core/channels/ChannelValue.h" #include "CentralParts.h" #include "util/string.h" +#include "util/stdlib.h" #include "fmu/common_fmu2.h" #ifdef __cplusplus @@ -23,11 +24,9 @@ static void Fmu2ValueDataDestructor(Fmu2ValueData * data) { } static Fmu2ValueData * Fmu2ValueDataCreate(Fmu2ValueData * data) { - data->type = FMU2_VALUE_INVALID; + memset(data, 0, sizeof(Fmu2ValueData)); - data->data.binary.lo = NULL; - data->data.binary.hi = NULL; - data->data.binary.size = NULL; + data->type = FMU2_VALUE_INVALID; return data; } @@ -150,6 +149,44 @@ Fmu2ValueData * Fmu2ValueDataScalarMake(fmi2_import_variable_t * scalar) { return data; } +Fmu2ValueData * Fmu2ValueDataArrayMake(size_t numDims, size_t dims[], fmi2_import_variable_t ** values) { + Fmu2ValueData * data = NULL; + + if (!numDims) { + return NULL; + } + + data = (Fmu2ValueData *) object_create(Fmu2ValueData); + if (data) { + size_t num = 1; + size_t i = 0; + + for (i = 0; i < numDims; i++) { + num *= dims[i]; + } + + data->type = FMU2_VALUE_ARRAY; + data->data.array.numDims = numDims; + data->data.array.dims = mcx_copy(dims, sizeof(size_t) * numDims); + if (!data->data.array.dims) { goto error; } + + data->data.array.values = mcx_copy(values, num * sizeof(fmi2_import_variable_t *)); + if (!data->data.array.values) { goto error; } + + data->vr.array.values = mcx_calloc(num, sizeof(fmi2_value_reference_t)); + if (!data->vr.array.values) { goto error; } + + for (i = 0; i < num; i++) { + data->vr.array.values[i] = fmi2_import_get_variable_vr(data->data.array.values[i]); + } + } + + return data; +error: + if (data) { object_destroy(data); } + return NULL; +} + Fmu2ValueData * Fmu2ValueDataBinaryMake(fmi2_import_variable_t * hi, fmi2_import_variable_t * lo, fmi2_import_variable_t * size) { Fmu2ValueData * data = (Fmu2ValueData *) object_create(Fmu2ValueData); @@ -176,49 +213,52 @@ static McxStatus Fmu2ValueSetFromChannelValue(Fmu2Value * v, ChannelValue * val) } static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData * data, const char * unit, Channel * channel) { - fmi2_base_type_enu_t t; - if (!name || !data) { mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Name or data missing"); return RETURN_ERROR; } - t = fmi2_import_get_variable_base_type(data->data.scalar); - v->name = mcx_string_copy(name); v->unit = mcx_string_copy(unit); v->data = data; v->channel = channel; - ChannelValueInit(&v->val, Fmi2TypeToChannelType(t)); - if (!v->name) { - mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Cannot copy name"); - return RETURN_ERROR; - } + if (v->data->type == FMU2_VALUE_SCALAR) { + fmi2_base_type_enu_t t = fmi2_import_get_variable_base_type(data->data.scalar); - switch (t) { - case fmi2_base_type_real: - v->val.value.d = fmi2_import_get_real_variable_start(fmi2_import_get_variable_as_real(data->data.scalar)); - break; - case fmi2_base_type_int: - v->val.value.i = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(data->data.scalar)); - break; - case fmi2_base_type_bool: - v->val.value.i = fmi2_import_get_boolean_variable_start(fmi2_import_get_variable_as_boolean(data->data.scalar)); - break; - case fmi2_base_type_str: { - const char * buffer = fmi2_import_get_string_variable_start(fmi2_import_get_variable_as_string(data->data.scalar)); - if (RETURN_OK != ChannelValueSetFromReference(&v->val, &buffer)) { + ChannelValueInit(&v->val, Fmi2TypeToChannelType(t)); + + if (!v->name) { + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Cannot copy name"); return RETURN_ERROR; } - break; - } - case fmi2_base_type_enum: - v->val.value.i = fmi2_import_get_enum_variable_start(fmi2_import_get_variable_as_enum(data->data.scalar)); - break; - default: - mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Base type %s not supported", fmi2_base_type_to_string(t)); - return RETURN_ERROR; + + switch (t) { + case fmi2_base_type_real: + v->val.value.d = fmi2_import_get_real_variable_start(fmi2_import_get_variable_as_real(data->data.scalar)); + break; + case fmi2_base_type_int: + v->val.value.i = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(data->data.scalar)); + break; + case fmi2_base_type_bool: + v->val.value.i = fmi2_import_get_boolean_variable_start(fmi2_import_get_variable_as_boolean(data->data.scalar)); + break; + case fmi2_base_type_str: { + const char * buffer = fmi2_import_get_string_variable_start(fmi2_import_get_variable_as_string(data->data.scalar)); + if (RETURN_OK != ChannelValueSetFromReference(&v->val, &buffer)) { + return RETURN_ERROR; + } + break; + } + case fmi2_base_type_enum: + v->val.value.i = fmi2_import_get_enum_variable_start(fmi2_import_get_variable_as_enum(data->data.scalar)); + break; + default: + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Base type %s not supported", fmi2_base_type_to_string(t)); + return RETURN_ERROR; + } + } else { + // TODO } return RETURN_OK; @@ -284,6 +324,13 @@ Fmu2Value * Fmu2ValueScalarMake(const char * name, fmi2_import_variable_t * scal return value; } +Fmu2Value * Fmu2ValueArrayMake(const char * name, size_t numDims, size_t dims[], fmi2_import_variable_t ** values, const char * unit, Channel * channel) { + Fmu2ValueData * data = Fmu2ValueDataArrayMake(numDims, dims, values); + Fmu2Value * value = Fmu2ValueMake(name, data, unit, channel); + + return value; +} + Fmu2Value * Fmu2ValueBinaryMake(const char * name, fmi2_import_variable_t * hi, fmi2_import_variable_t * lo, fmi2_import_variable_t * size, Channel * channel) { Fmu2ValueData * data = Fmu2ValueDataBinaryMake(hi, lo, size); Fmu2Value * value = Fmu2ValueMake(name, data, NULL, channel); diff --git a/src/fmu/Fmu2Value.h b/src/fmu/Fmu2Value.h index f811c65..6c70d07 100644 --- a/src/fmu/Fmu2Value.h +++ b/src/fmu/Fmu2Value.h @@ -26,9 +26,10 @@ typedef struct Fmu2ValueData Fmu2ValueData; extern const struct ObjectClass _Fmu2ValueData; typedef enum Fmu2ValueType { - FMU2_VALUE_SCALAR - , FMU2_VALUE_BINARY_OSI - , FMU2_VALUE_INVALID + FMU2_VALUE_SCALAR, + FMU2_VALUE_ARRAY, + FMU2_VALUE_BINARY_OSI, + FMU2_VALUE_INVALID } Fmu2ValueType; struct Fmu2ValueData { @@ -37,6 +38,11 @@ struct Fmu2ValueData { Fmu2ValueType type; union { fmi2_import_variable_t * scalar; + struct { + size_t numDims; + size_t * dims; + fmi2_import_variable_t ** values; + } array; struct { fmi2_import_variable_t * lo; fmi2_import_variable_t * hi; @@ -45,6 +51,9 @@ struct Fmu2ValueData { } data; union { fmi2_value_reference_t scalar; + struct { + fmi2_value_reference_t * values; + } array; struct { fmi2_value_reference_t lo; fmi2_value_reference_t hi; @@ -54,6 +63,7 @@ struct Fmu2ValueData { }; Fmu2ValueData * Fmu2ValueDataScalarMake(fmi2_import_variable_t * scalar); +Fmu2ValueData * Fmu2ValueDataArrayMake(size_t numDims, size_t dims[], fmi2_import_variable_t ** values); Fmu2ValueData * Fmu2ValueDataBinaryMake(fmi2_import_variable_t * hi, fmi2_import_variable_t * lo, fmi2_import_variable_t * size); @@ -99,6 +109,7 @@ struct Fmu2Value { Fmu2Value * Fmu2ValueMake(const char * name, Fmu2ValueData * data, const char * unit, Channel * channel); Fmu2Value * Fmu2ValueScalarMake(const char * name, fmi2_import_variable_t * scalar, const char * unit, Channel * channel); +Fmu2Value * Fmu2ValueArrayMake(const char * name, size_t numDims, size_t dims[], fmi2_import_variable_t ** values, const char * unit, Channel * channel); Fmu2Value * Fmu2ValueBinaryMake(const char * name, fmi2_import_variable_t * hi, fmi2_import_variable_t * lo, fmi2_import_variable_t * size, Channel * channel); void Fmu2ValuePrintDebug(Fmu2Value * val); diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 3d0df67..d010a03 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -669,6 +669,7 @@ McxStatus Fmu2UpdateTunableParamValues(ObjectContainer * tunableParams, ObjectCo } +// TODO: move into fmu2value? McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { fmi2_status_t status = fmi2_status_ok; @@ -739,6 +740,25 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { break; } + case CHANNEL_ARRAY: + { + fmi2_value_reference_t * vrs = fmuVal->data->vr.array.values; + array * a = (array *) ChannelValueReference(&fmuVal->val); + + size_t num = array_num_elements(a); + void * vals = a->data; + + if (ChannelTypeEq(a->type, &ChannelTypeDouble)) { + status = fmi2_import_set_real(fmu->fmiImport, vrs, num, vals); + } else if (ChannelTypeEq(a->type, &ChannelTypeInteger)) { + status = fmi2_import_set_integer(fmu->fmiImport, vrs, num, vals); + } else { + mcx_log(LOG_ERROR, "FMU: Unsupported array variable type: %s", ChannelTypeToString(a->type)); + return RETURN_ERROR; + } + + break; + } default: mcx_log(LOG_ERROR, "FMU: Unknown variable type"); return RETURN_ERROR; @@ -855,6 +875,25 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { break; } + case CHANNEL_ARRAY: + { + fmi2_value_reference_t * vrs = fmuVal->data->vr.array.values; + array * a = (array *) ChannelValueReference(&fmuVal->val); + + size_t num = array_num_elements(a); + void * vals = a->data; + + if (ChannelTypeEq(a->type, &ChannelTypeDouble)) { + status = fmi2_import_get_real(fmu->fmiImport, vrs, num, vals); + } else if (ChannelTypeEq(a->type, &ChannelTypeInteger)) { + status = fmi2_import_get_integer(fmu->fmiImport, vrs, num, vals); + } else { + // TODO: log message + return RETURN_ERROR; + } + + break; + } default: mcx_log(LOG_WARNING, "FMU: Unknown variable type of variable %s", name); return RETURN_ERROR; From 257b6d832ba1616f2b91dd96861d44323ec42ac8 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 27 Jul 2021 14:29:59 +0200 Subject: [PATCH 132/295] channel: Let ChannelValueInit take ownership of type --- src/components/comp_fmu.c | 4 ++-- src/core/Databus.c | 2 +- src/core/channels/Channel.c | 6 +++--- src/core/channels/ChannelValue.c | 18 +++++++----------- src/core/channels/ChannelValue.h | 1 + src/core/connections/Connection.c | 4 ++-- src/core/connections/FilteredConnection.c | 4 ++-- src/core/connections/filters/DiscreteFilter.c | 8 ++++---- src/fmu/Fmu1Value.c | 4 ++-- src/fmu/Fmu2Value.c | 4 ++-- src/fmu/common_fmu1.c | 6 +++--- src/fmu/common_fmu2.c | 6 +++--- src/storage/ChannelStorage.c | 2 +- 13 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 2f28f20..ef00d91 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -401,7 +401,7 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat val->SetChannel(val, info->channel); if (!ChannelTypeIsValid(val->val.type)) { - ChannelValueInit(&val->val, info->type); + ChannelValueInit(&val->val, ChannelTypeClone(info->type)); } retVal = DatabusSetInReference(db, i, ChannelValueReference(&val->val), @@ -439,7 +439,7 @@ static McxStatus Fmu2SetupChannelOut(ObjectContainer /* Fmu2Values */ * vals, Da val->SetChannel(val, info->channel); if (!ChannelTypeEq(val->val.type, info->type)) { - ChannelValueInit(&val->val, info->type); + ChannelValueInit(&val->val, ChannelTypeClone(info->type)); } retVal = DatabusSetOutReference(db, i, ChannelValueReference(&val->val), diff --git a/src/core/Databus.c b/src/core/Databus.c index 63756d9..0be9d88 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -180,7 +180,7 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { ChannelType * expectedType = info->type; ChannelValue value; - ChannelValueInit(&value, expectedType); + ChannelValueInit(&value, ChannelTypeClone(expectedType)); if (scalarPortInput->min.defined) { if (RETURN_OK != ChannelValueSetFromReference(&value, &scalarPortInput->min.value)) { diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 7019c44..653cb6e 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -179,7 +179,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { connInfo = &conn->info; ChannelValueDestructor(val); - ChannelValueInit(val, ConnectionInfoGetType(connInfo)); + ChannelValueInit(val, ChannelTypeClone(ConnectionInfoGetType(connInfo))); /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { @@ -360,7 +360,7 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { mcx_log(LOG_ERROR, "Port %s: Setup inport: Unknown type", ChannelInfoGetLogName(info)); return RETURN_ERROR; } - ChannelValueInit(&channel->value, info->type); + ChannelValueInit(&channel->value, ChannelTypeClone(info->type)); // default value if (info->defaultValue) { @@ -514,7 +514,7 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * mcx_log(LOG_ERROR, "Port %s: Setup outport: Unknown type", ChannelInfoGetLogName(info)); return RETURN_ERROR; } - ChannelValueInit(&channel->value, info->type); + ChannelValueInit(&channel->value, ChannelTypeClone(info->type)); // default value if (info->defaultValue) { diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index f346cdf..f290ba7 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -219,7 +219,7 @@ size_t array_num_elements(array * a) { } void ChannelValueInit(ChannelValue * value, ChannelType * type) { - value->type = ChannelTypeClone(type); + value->type = type; ChannelValueDataInit(&value->value, type); } @@ -760,7 +760,9 @@ ChannelValue * ChannelValueClone(ChannelValue * value) { if (!clone) { return NULL; } - ChannelValueInit(clone, ChannelValueType(value)); + // ChannelTypeClone might fail, then clone will be + // ChannelTypeUnknown and ChannelValueSet below returns an error + ChannelValueInit(clone, ChannelTypeClone(ChannelValueType(value))); if (ChannelValueSet(clone, value) != RETURN_OK) { mcx_free(clone); @@ -866,7 +868,7 @@ ChannelValue * ChannelValueNewScalar(ChannelType * type, void * data) { return NULL; } - ChannelValueInit(value, type); + ChannelValueInit(value, ChannelTypeClone(type)); ChannelValueSetFromReference(value, data); return value; @@ -879,13 +881,7 @@ ChannelValue * ChannelValueNewArray(size_t numDims, size_t dims[], ChannelType * return NULL; } - ChannelType * arrayType = ChannelTypeArray(type, numDims, dims); - if (!ChannelTypeIsValid(arrayType)) { - mcx_free(value); - return NULL; - } - ChannelValueInit(value, arrayType); - ChannelTypeDestructor(arrayType); + ChannelValueInit(value, ChannelTypeArray(type, numDims, dims)); if (value->value.a.data && data) { memcpy(value->value.a.data, data, ChannelValueTypeSize(type) * array_num_elements(&value->value.a)); @@ -925,7 +921,7 @@ ChannelValue ** ArrayToChannelValueArray(void * values, size_t num, ChannelType return NULL; } - ChannelValueInit(array[i], type); + ChannelValueInit(array[i], ChannelTypeClone(type)); if (RETURN_OK != ChannelValueSetFromReference(array[i], (char *) values + i*size)) { return RETURN_ERROR; } diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index a2a8dc8..fda2fb1 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -117,6 +117,7 @@ typedef struct ChannelValue { ChannelValueData value; } ChannelValue; +// Takes ownership of type void ChannelValueInit(ChannelValue * value, ChannelType * type); void ChannelValueDestructor(ChannelValue * value); char * ChannelValueToString(ChannelValue * value); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index b914f2d..67ec793 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1208,7 +1208,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { mcx_log(LOG_WARNING, "Connection %s: No initial values are specified for the ports of the connection", buffer); mcx_free(buffer); } - ChannelValueInit(&connection->store_, ConnectionInfoGetType(info)); + ChannelValueInit(&connection->store_, ChannelTypeClone(ConnectionInfoGetType(info))); } return RETURN_OK; @@ -1343,7 +1343,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * connection->info = *info; - ChannelValueInit(&connection->store_, outInfo->type); + ChannelValueInit(&connection->store_, ChannelTypeClone(outInfo->type)); // Add connection to channel out retVal = out->RegisterConnection(out, connection); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index bb7bf27..a33e2fb 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -23,7 +23,7 @@ extern "C" { static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionData * data) { data->filter = NULL; - ChannelValueInit(&data->store, &ChannelTypeUnknown); + ChannelValueInit(&data->store, ChannelTypeClone(&ChannelTypeUnknown)); return data; } @@ -54,7 +54,7 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o filteredConnection->data->filter = NULL; // value store - ChannelValueInit(&filteredConnection->data->store, sourceInfo->type); + ChannelValueInit(&filteredConnection->data->store, ChannelTypeClone(sourceInfo->type)); // value reference connection->value_ = ChannelValueReference(&filteredConnection->data->store); diff --git a/src/core/connections/filters/DiscreteFilter.c b/src/core/connections/filters/DiscreteFilter.c index 42bdb84..5f41c77 100644 --- a/src/core/connections/filters/DiscreteFilter.c +++ b/src/core/connections/filters/DiscreteFilter.c @@ -47,8 +47,8 @@ static McxStatus DiscreteFilterEnterCommunicationMode(ChannelFilter * filter, do } static McxStatus DiscreteFilterSetup(DiscreteFilter * filter, ChannelType * type) { - ChannelValueInit(&filter->lastSynchronizationStepValue, type); - ChannelValueInit(&filter->lastCouplingStepValue, type); + ChannelValueInit(&filter->lastSynchronizationStepValue, ChannelTypeClone(type)); + ChannelValueInit(&filter->lastCouplingStepValue, ChannelTypeClone(type)); return RETURN_OK; } @@ -69,8 +69,8 @@ static DiscreteFilter * DiscreteFilterCreate(DiscreteFilter * discreteFilter) { discreteFilter->Setup = DiscreteFilterSetup; - ChannelValueInit(&discreteFilter->lastSynchronizationStepValue, &ChannelTypeUnknown); - ChannelValueInit(&discreteFilter->lastCouplingStepValue, &ChannelTypeUnknown); + ChannelValueInit(&discreteFilter->lastSynchronizationStepValue, ChannelTypeClone(&ChannelTypeUnknown)); + ChannelValueInit(&discreteFilter->lastCouplingStepValue, ChannelTypeClone(&ChannelTypeUnknown)); return discreteFilter; } diff --git a/src/fmu/Fmu1Value.c b/src/fmu/Fmu1Value.c index e80de39..6800ce0 100644 --- a/src/fmu/Fmu1Value.c +++ b/src/fmu/Fmu1Value.c @@ -37,7 +37,7 @@ Fmu1Value * Fmu1ValueCreate(Fmu1Value * v) { v->name = NULL; v->var = NULL; v->channel = NULL; - ChannelValueInit(&v->val, &ChannelTypeUnknown); + ChannelValueInit(&v->val, ChannelTypeClone(&ChannelTypeUnknown)); return v; } @@ -64,7 +64,7 @@ Fmu1Value * Fmu1ValueMake(const char * name, fmi1_import_variable_t * var, Chann value->name = mcx_string_copy(name); value->vr = fmi1_import_get_variable_vr(var); value->var = var; - ChannelValueInit(&value->val, Fmi1TypeToChannelType(t)); + ChannelValueInit(&value->val, ChannelTypeClone(Fmi1TypeToChannelType(t))); if (!value->name) { mcx_log(LOG_ERROR, "Fmu1Value: Setup failed: Cannot copy name"); diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 2ae6329..bad234b 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -226,7 +226,7 @@ static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData if (v->data->type == FMU2_VALUE_SCALAR) { fmi2_base_type_enu_t t = fmi2_import_get_variable_base_type(data->data.scalar); - ChannelValueInit(&v->val, Fmi2TypeToChannelType(t)); + ChannelValueInit(&v->val, ChannelTypeClone(Fmi2TypeToChannelType(t))); if (!v->name) { mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Cannot copy name"); @@ -293,7 +293,7 @@ static Fmu2Value * Fmu2ValueCreate(Fmu2Value * v) { v->channel = NULL; v->info = NULL; - ChannelValueInit(&v->val, &ChannelTypeUnknown); + ChannelValueInit(&v->val, ChannelTypeClone(&ChannelTypeUnknown)); return v; } diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index bb91efe..ecdc12b 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -282,7 +282,7 @@ Fmu1Value * Fmu1ReadParamValue(ScalarParameterInput * input, fmi1_import_t * imp return NULL; } - ChannelValueInit(&chVal, input->type); + ChannelValueInit(&chVal, ChannelTypeClone(input->type)); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &input->value.value)) { return NULL; } @@ -382,13 +382,13 @@ static ObjectContainer * Fmu1ReadArrayParamValues(const char * name, } if (ChannelTypeEq(input->type, &ChannelTypeDouble)) { - ChannelValueInit(&chVal, &ChannelTypeDouble); + ChannelValueInit(&chVal, ChannelTypeClone(&ChannelTypeDouble)); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { return RETURN_ERROR; } } else { // integer - ChannelValueInit(&chVal, &ChannelTypeInteger); + ChannelValueInit(&chVal, ChannelTypeClone(&ChannelTypeInteger)); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { return RETURN_ERROR; } diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index d010a03..743952a 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -298,7 +298,7 @@ Fmu2Value * Fmu2ReadParamValue(ScalarParameterInput * input, return NULL; } - ChannelValueInit(&chVal, input->type); + ChannelValueInit(&chVal, ChannelTypeClone(input->type)); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &input->value.value)) { return NULL; } @@ -390,13 +390,13 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, } if (ChannelTypeEq(input->type, &ChannelTypeDouble)) { - ChannelValueInit(&chVal, &ChannelTypeDouble); + ChannelValueInit(&chVal, ChannelTypeClone(&ChannelTypeDouble)); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((double *)input->values)[index])) { retVal = RETURN_ERROR; goto fmu2_read_array_param_values_for_cleanup; } } else { // integer - ChannelValueInit(&chVal, &ChannelTypeInteger); + ChannelValueInit(&chVal, ChannelTypeClone(&ChannelTypeInteger)); if (RETURN_OK != ChannelValueSetFromReference(&chVal, &((int *)input->values)[index])) { retVal = RETURN_ERROR; goto fmu2_read_array_param_values_for_cleanup; diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 50c6323..6921ba4 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -153,7 +153,7 @@ static McxStatus ChannelStorageSetValueFromReferenceAt(ChannelStorage * channelS if (row >= channelStore->numValues) { ChannelInfo * info = &channel->info; - ChannelValueInit(&channelStore->values[row * colNum + col], info->type); + ChannelValueInit(&channelStore->values[row * colNum + col], ChannelTypeClone(info->type)); } if (RETURN_OK != ChannelValueSetFromReference(&channelStore->values[row * colNum + col], reference)) { From e675ea3f96272bf492dbd00c59a299a7da23591c Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 06:18:45 +0200 Subject: [PATCH 133/295] fmu: Move Fmu2ReadFmu2{Scalar,Array}Value to Fmu2Value.c --- src/components/comp_fmu.c | 74 -------------------------------------- src/fmu/Fmu2Value.c | 76 +++++++++++++++++++++++++++++++++++++++ src/fmu/Fmu2Value.h | 4 +++ 3 files changed, 80 insertions(+), 74 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index ef00d91..71c2b2f 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -505,80 +505,6 @@ static McxStatus Fmu2Setup(Component * comp) { return RETURN_OK; } -static Fmu2Value * Fmu2ReadFmu2ScalarValue(const char * logPrefix, ChannelType * type, const char * channelName, const char * unitString, fmi2_import_t * fmiImport) { - Fmu2Value * val = NULL; - fmi2_import_variable_t * var = NULL; - - var = fmi2_import_get_variable_by_name(fmiImport, channelName); - if (!var) { - mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, channelName); - return NULL; - } - - if (!ChannelTypeEq(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(type), - ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); - return NULL; - } - - val = Fmu2ValueScalarMake(channelName, var, unitString, NULL); - if (!val) { - mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); - return NULL; - } - - return val; -} - -static Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, const char * channelName, ChannelDimension * dimension, const char * unitString, fmi2_import_t * fmiImport) { - Fmu2Value * val = NULL; - fmi2_import_variable_t * var = NULL; - - if (dimension->num > 1) { - mcx_log(LOG_ERROR, "%s: Port %s: Invalid dimension", logPrefix, channelName); - return RETURN_ERROR; - } - - size_t i = 0; - size_t startIdx = dimension->startIdxs[0]; - size_t endIdx = dimension->endIdxs[0]; - - fmi2_import_variable_t ** vars = mcx_calloc(endIdx - startIdx + 1, sizeof(fmi2_import_variable_t *)); - if (!vars) { - return NULL; - } - - for (i = startIdx; i <= endIdx; i++) { - char * indexedChannelName = CreateIndexedName(channelName, i); - fmi2_import_variable_t * var = fmi2_import_get_variable_by_name(fmiImport, indexedChannelName); - if (!var) { - mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, indexedChannelName); - return NULL; - } - if (!ChannelTypeEq(ChannelTypeArrayInner(type), Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))) { - mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, indexedChannelName); - mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, - ChannelTypeToString(ChannelTypeArrayInner(type)), - ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); - return NULL; - } - vars[i - startIdx] = var; - - mcx_free(indexedChannelName); - } - - size_t dims[] = { endIdx - startIdx + 1 }; - val = Fmu2ValueArrayMake(channelName, 1 /* numDims */, dims, vars, unitString, NULL); - if (!val) { - mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); - return NULL; - } - - return val; -} - static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Databus * db, fmi2_import_t * fmiImport, const char * logPrefix) { McxStatus retVal = RETURN_OK; diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index bad234b..b3c1929 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -11,6 +11,7 @@ #include "fmu/Fmu2Value.h" #include "core/channels/ChannelValue.h" +#include "core/connections/ConnectionInfoFactory.h" #include "CentralParts.h" #include "util/string.h" #include "util/stdlib.h" @@ -342,6 +343,81 @@ void Fmu2ValuePrintDebug(Fmu2Value * val) { mcx_log(LOG_DEBUG, "Fmu2Value { name: \"%s\" }", val->name); } +Fmu2Value * Fmu2ReadFmu2ScalarValue(const char * logPrefix, ChannelType * type, const char * channelName, const char * unitString, fmi2_import_t * fmiImport) { + Fmu2Value * val = NULL; + fmi2_import_variable_t * var = NULL; + + var = fmi2_import_get_variable_by_name(fmiImport, channelName); + if (!var) { + mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, channelName); + return NULL; + } + + if (!ChannelTypeEq(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(type), + ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); + return NULL; + } + + val = Fmu2ValueScalarMake(channelName, var, unitString, NULL); + if (!val) { + mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + return NULL; + } + + return val; +} + +Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, const char * channelName, ChannelDimension * dimension, const char * unitString, fmi2_import_t * fmiImport) { + Fmu2Value * val = NULL; + fmi2_import_variable_t * var = NULL; + + if (dimension->num > 1) { + mcx_log(LOG_ERROR, "%s: Port %s: Invalid dimension", logPrefix, channelName); + return RETURN_ERROR; + } + + size_t i = 0; + size_t startIdx = dimension->startIdxs[0]; + size_t endIdx = dimension->endIdxs[0]; + + fmi2_import_variable_t ** vars = mcx_calloc(endIdx - startIdx + 1, sizeof(fmi2_import_variable_t *)); + if (!vars) { + return NULL; + } + + for (i = startIdx; i <= endIdx; i++) { + char * indexedChannelName = CreateIndexedName(channelName, i); + fmi2_import_variable_t * var = fmi2_import_get_variable_by_name(fmiImport, indexedChannelName); + if (!var) { + mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, indexedChannelName); + return NULL; + } + if (!ChannelTypeEq(ChannelTypeArrayInner(type), Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))) { + mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, indexedChannelName); + mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, + ChannelTypeToString(ChannelTypeArrayInner(type)), + ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); + return NULL; + } + vars[i - startIdx] = var; + + mcx_free(indexedChannelName); + } + + size_t dims[] = { endIdx - startIdx + 1 }; + val = Fmu2ValueArrayMake(channelName, 1 /* numDims */, dims, vars, unitString, NULL); + if (!val) { + mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + return NULL; + } + + return val; +} + + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/fmu/Fmu2Value.h b/src/fmu/Fmu2Value.h index 6c70d07..fb85f7e 100644 --- a/src/fmu/Fmu2Value.h +++ b/src/fmu/Fmu2Value.h @@ -13,6 +13,7 @@ #include "CentralParts.h" #include "core/channels/Channel.h" +#include "core/channels/ChannelDimension.h" #include "fmilib.h" #ifdef __cplusplus @@ -114,6 +115,9 @@ Fmu2Value * Fmu2ValueBinaryMake(const char * name, fmi2_import_variable_t * hi, void Fmu2ValuePrintDebug(Fmu2Value * val); +Fmu2Value * Fmu2ReadFmu2ScalarValue(const char * logPrefix, ChannelType * type, const char * channelName, const char * unitString, fmi2_import_t * fmiImport); +Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, const char * channelName, ChannelDimension * dimension, const char * unitString, fmi2_import_t * fmiImport); + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ From 97935ae374e95513f63913c44e443a4c8259a503 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 06:24:39 +0200 Subject: [PATCH 134/295] fmu: Check status of Fmu2ReadFmu2{Scalar,Array}Value --- src/components/comp_fmu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 71c2b2f..6ffe7c7 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -591,6 +591,10 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab } } else if (info->dimension) { val = Fmu2ReadFmu2ArrayValue(logPrefix, info->type, channelName, info->dimension, info->unitString, fmiImport); + if (!val) { + mcx_log(LOG_ERROR, "%s: Could not create value for %s", logPrefix, channelName); + return RETURN_ERROR; + } val->SetChannel(val, info->channel); @@ -601,6 +605,10 @@ static McxStatus Fmu2ReadChannelIn(ObjectContainer /* Fmu2Value */ * vals, Datab } } else { // scalar val = Fmu2ReadFmu2ScalarValue(logPrefix, info->type, channelName, info->unitString, fmiImport); + if (!val) { + mcx_log(LOG_ERROR, "%s: Could not create value for %s", logPrefix, channelName); + return RETURN_ERROR; + } val->SetChannel(val, info->channel); From bf5d66df8f5ebba0d2add3ee06af0573acbeeea3 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 24 Aug 2021 12:38:15 +0200 Subject: [PATCH 135/295] fmu: Improve error message for "unknown type" --- src/fmu/common_fmu2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 743952a..925560b 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -760,7 +760,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { break; } default: - mcx_log(LOG_ERROR, "FMU: Unknown variable type"); + mcx_log(LOG_ERROR, "FMU: Unknown variable type: %s", ChannelTypeToString(type)); return RETURN_ERROR; } From 6be26231fb6a028498491e8fb5f798e640aab2d3 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 06:25:24 +0200 Subject: [PATCH 136/295] fmu: Extend Fmu2ValueSetup to handle arrays This includes a workaround for a crash in binary channel values. --- src/fmu/Fmu2Value.c | 157 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 133 insertions(+), 24 deletions(-) diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index b3c1929..70cc1a4 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -213,6 +213,96 @@ static McxStatus Fmu2ValueSetFromChannelValue(Fmu2Value * v, ChannelValue * val) return ChannelValueSet(&v->val, val); } +static McxStatus Fmu2ValueGetVariableStart(fmi2_base_type_enu_t t, fmi2_import_variable_t * var, ChannelValue * value) { + + switch (t) { + case fmi2_base_type_real: + value->value.d = fmi2_import_get_real_variable_start(fmi2_import_get_variable_as_real(var)); + break; + case fmi2_base_type_int: + value->value.i = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(var)); + break; + case fmi2_base_type_bool: + value->value.i = fmi2_import_get_boolean_variable_start(fmi2_import_get_variable_as_boolean(var)); + break; + case fmi2_base_type_str: { + const char * buffer = fmi2_import_get_string_variable_start(fmi2_import_get_variable_as_string(var)); + if (RETURN_OK != ChannelValueSetFromReference(value, &buffer)) { + return RETURN_ERROR; + } + break; + } + case fmi2_base_type_enum: + value->value.i = fmi2_import_get_enum_variable_start(fmi2_import_get_variable_as_enum(var)); + break; + default: + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Base type %s not supported", fmi2_base_type_to_string(t)); + return RETURN_ERROR; + } + + return RETURN_OK; +} + +static McxStatus Fmu2ValueGetArrayVariableStart(fmi2_base_type_enu_t t, fmi2_import_variable_t * var, array * a, size_t i) { + + switch (t) { + case fmi2_base_type_real: + ((double *)a->data)[i] = fmi2_import_get_real_variable_start(fmi2_import_get_variable_as_real(var)); + break; + case fmi2_base_type_int: + ((int *)a->data)[i] = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(var)); + break; + case fmi2_base_type_enum: + ((int *)a->data)[i] = fmi2_import_get_enum_variable_start(fmi2_import_get_variable_as_enum(var)); + break; + case fmi2_base_type_bool: + ((int *)a->data)[i] = fmi2_import_get_boolean_variable_start(fmi2_import_get_variable_as_boolean(var)); + break; + default: + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Array base type %s not supported", fmi2_base_type_to_string(t)); + return RETURN_ERROR; + } + + return RETURN_OK; +} + +static McxStatus Fmu2ValueGetBinaryVariableStart(fmi2_import_variable_t * varHi, fmi2_import_variable_t * varLo, fmi2_import_variable_t * varSize, ChannelValue * value) { + fmi2_base_type_enu_t t; + + t = fmi2_import_get_variable_base_type(varHi); + if (t != fmi2_base_type_int) { + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Binary base type (hi) %s not supported", fmi2_base_type_to_string(t)); + return RETURN_ERROR; + } + t = fmi2_import_get_variable_base_type(varLo); + if (t != fmi2_base_type_int) { + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Binary base type (lo) %s not supported", fmi2_base_type_to_string(t)); + return RETURN_ERROR; + } + t = fmi2_import_get_variable_base_type(varSize); + if (t != fmi2_base_type_int) { + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Binary base type (size) %s not supported", fmi2_base_type_to_string(t)); + return RETURN_ERROR; + } + + fmi2_integer_t hi = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(varHi)); + fmi2_integer_t lo = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(varLo)); + fmi2_integer_t size = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(varSize)); + + binary_string b; + + b.len = size; + b.data = (char *) ((((long long)hi & 0xffffffff) << 32) | (lo & 0xffffffff)); + + if (RETURN_OK != ChannelValueSetFromReference(value, &b)) { + mcx_log(LOG_ERROR, "Fmu2Value: Could not set value"); + return RETURN_ERROR; + } + + return RETURN_OK; +} + + static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData * data, const char * unit, Channel * channel) { if (!name || !data) { mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Name or data missing"); @@ -224,42 +314,61 @@ static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData v->data = data; v->channel = channel; + if (!v->name) { + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Cannot copy name"); + return RETURN_ERROR; + } + if (v->data->type == FMU2_VALUE_SCALAR) { fmi2_base_type_enu_t t = fmi2_import_get_variable_base_type(data->data.scalar); ChannelValueInit(&v->val, ChannelTypeClone(Fmi2TypeToChannelType(t))); - if (!v->name) { - mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Cannot copy name"); + + if (RETURN_OK != Fmu2ValueGetVariableStart(t, data->data.scalar, &v->val)) { + return RETURN_ERROR; + } + } else if (v->data->type == FMU2_VALUE_ARRAY) { + fmi2_base_type_enu_t t = fmi2_import_get_variable_base_type(data->data.array.values[0]); + + ChannelValueInit(&v->val, ChannelTypeArray(Fmi2TypeToChannelType(t), data->data.array.numDims, data->data.array.dims)); + + if (data->data.array.numDims == 0) { + mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Array of dimension 0 is not supported"); return RETURN_ERROR; } - switch (t) { - case fmi2_base_type_real: - v->val.value.d = fmi2_import_get_real_variable_start(fmi2_import_get_variable_as_real(data->data.scalar)); - break; - case fmi2_base_type_int: - v->val.value.i = fmi2_import_get_integer_variable_start(fmi2_import_get_variable_as_integer(data->data.scalar)); - break; - case fmi2_base_type_bool: - v->val.value.i = fmi2_import_get_boolean_variable_start(fmi2_import_get_variable_as_boolean(data->data.scalar)); - break; - case fmi2_base_type_str: { - const char * buffer = fmi2_import_get_string_variable_start(fmi2_import_get_variable_as_string(data->data.scalar)); - if (RETURN_OK != ChannelValueSetFromReference(&v->val, &buffer)) { + size_t i = 0, n = 1; + + for (i = 0; i < data->data.array.numDims; i++) { + n *= data->data.array.dims[i]; + } + + array * a = (array *) ChannelValueReference(&v->val); + + for (i = 0; i < n; i++) { + if (RETURN_OK != Fmu2ValueGetArrayVariableStart(t, data->data.array.values[i], a, i)) { return RETURN_ERROR; } - break; - } - case fmi2_base_type_enum: - v->val.value.i = fmi2_import_get_enum_variable_start(fmi2_import_get_variable_as_enum(data->data.scalar)); - break; - default: - mcx_log(LOG_ERROR, "Fmu2Value: Setup failed: Base type %s not supported", fmi2_base_type_to_string(t)); - return RETURN_ERROR; } + } else if (v->data->type == FMU2_VALUE_BINARY_OSI) { + return RETURN_OK; + + // TODO: Setting the initial value causes some memory errors. + + // ChannelValueInit(&v->val, &ChannelTypeBinary); + + // if (RETURN_OK != Fmu2ValueGetBinaryVariableStart( + // data->data.binary.hi, + // data->data.binary.lo, + // data->data.binary.size, + // &v->val)) { + // return RETURN_ERROR; + // } + + } else { - // TODO + return RETURN_ERROR; } return RETURN_OK; From d18c5ec6756350dd6a27860022af129679815c94 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Fri, 20 Aug 2021 13:50:37 +0200 Subject: [PATCH 137/295] icos: Refactor ports and remove VectorChannelInfo --- src/core/channels/ChannelDimension.c | 14 ++++++++++++++ src/core/channels/ChannelDimension.h | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index a0886b3..7a01564 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -62,6 +62,20 @@ McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, return RETURN_OK; } +size_t ChannelDimensionNumElements(ChannelDimension * dimension) { + size_t i = 0, n = 1; + + if (dimension->num == 0) { + return 0; + } + + for (i = 0; i < dimension->num; i++) { + n *= (dimension->endIdxs[i] - dimension->startIdxs[i] + 1); + } + + return n; +} + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 20c11f1..d8763c7 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -30,7 +30,7 @@ typedef struct ChannelDimension { McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); - +size_t ChannelDimensionNumElements(ChannelDimension * dimension); #ifdef __cplusplus } /* closing brace for extern "C" */ From a3839e32f2706349249bc7d1cd84118067b3dd7a Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 31 Aug 2021 14:10:08 +0200 Subject: [PATCH 138/295] channel: Replace double with ChannelValueData for proc functions --- src/core/channels/Channel.c | 7 +++++-- src/core/channels/ChannelValue.h | 13 ++++++++----- src/core/connections/FilteredConnection.c | 9 ++++++--- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 653cb6e..b1323f8 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -707,10 +707,13 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { if (out->GetFunction(out)) { // function value proc * p = (proc *) out->GetFunction(out); - double val = p->fn(time, p->env); + ChannelValueData val = { 0 }; + if (p->fn(time, p->env, &val) != 0) { + return RETURN_ERROR; + } #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, val); + MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, val.d); } #endif // MCX_DEBUG if (RETURN_OK != ChannelValueSetFromReference(&channel->value, &val)) { diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index fda2fb1..eefeb57 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -80,8 +80,11 @@ typedef struct { double endTime; } TimeInterval; +typedef union ChannelValueData ChannelValueData; +typedef struct ChannelValue ChannelValue; + typedef struct { - double (* fn)(TimeInterval * arg, void * env); + int (* fn)(TimeInterval * arg, void * env, ChannelValueData * res); void * env; } proc; @@ -103,19 +106,19 @@ int array_dims_match(array * a, array * b); size_t array_num_elements(array * a); // TODO: change concrete types to McxDouble, McxInteger, etc -typedef union ChannelValueData { +union ChannelValueData { /* the order is significant. double needs to be the first entry for union initialization to work */ double d; int i; char * s; binary_string b; array a; -} ChannelValueData; +}; -typedef struct ChannelValue { +struct ChannelValue { ChannelType * type; ChannelValueData value; -} ChannelValue; +}; // Takes ownership of type void ChannelValueInit(ChannelValue * value, ChannelType * type); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index a33e2fb..c8fd206 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -155,9 +155,12 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI if (out->GetFunction(out)) { proc * p = (proc *) out->GetFunction(out); - double value = 0.0; + ChannelValueData value = { 0 }; - value = p->fn(time, p->env); + if (p->fn(time, p->env, &value) != 0) { + mcx_log(LOG_ERROR, "FilteredConnection: Function failed"); + return RETURN_ERROR; + } if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; @@ -165,7 +168,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI } else { // only filter if time is not negative (negative time means filter disabled) if (filteredConnection->GetReadFilter(filteredConnection) && time->startTime >= 0) { - ChannelValueData value; + ChannelValueData value = { 0 }; filter = filteredConnection->GetReadFilter(filteredConnection); value = filter->GetValue(filter, time->startTime); From c3d9c55761eb43e2bc3bd587c5f694ff4354a146 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 23 Aug 2021 18:43:48 +0200 Subject: [PATCH 139/295] Move CreateIndexedName to ChannelValue --- src/core/channels/ChannelValue.c | 17 +++++++++++++++++ src/core/channels/ChannelValue.h | 2 ++ src/core/connections/ConnectionInfoFactory.c | 18 ++---------------- src/core/connections/ConnectionInfoFactory.h | 1 - 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index f290ba7..0dbb319 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -35,6 +35,23 @@ ChannelType ChannelTypeBinary = { CHANNEL_BINARY, NULL}; ChannelType ChannelTypeBinaryReference = { CHANNEL_BINARY_REFERENCE, NULL}; +char * CreateIndexedName(const char * name, unsigned i) { + size_t len = 0; + char * buffer = NULL; + + len = strlen(name) + (mcx_digits10(i) + 1) + 2 + 1; + + buffer = (char *) mcx_calloc(len, sizeof(char)); + if (!buffer) { + return NULL; + } + + snprintf(buffer, len, "%s[%d]", name, i); + + return buffer; +} + + ChannelType * ChannelTypeClone(ChannelType * type) { switch (type->con) { case CHANNEL_UNKNOWN: diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index eefeb57..a919268 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -20,6 +20,8 @@ extern "C" { void * mcx_copy(void * object, size_t size); +char * CreateIndexedName(const char * name, unsigned i); + // possible types of values that can be put on channels typedef enum ChannelTypeConstructor { CHANNEL_UNKNOWN = 0, diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index f0f774b..0db5751 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -17,27 +17,13 @@ #include "util/stdlib.h" #include "util/string.h" +#include "core/channels/ChannelValue.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -char * CreateIndexedName(const char * name, unsigned i) { - size_t len = 0; - char * buffer = NULL; - - len = strlen(name) + (mcx_digits10(i) + 1) + 2 + 1; - - buffer = (char *) mcx_calloc(len, sizeof(char)); - if (!buffer) { - return NULL; - } - - snprintf(buffer, len, "%s[%d]", name, i); - - return buffer; -} - static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, ObjectContainer * components, ConnectionInput * connInput, diff --git a/src/core/connections/ConnectionInfoFactory.h b/src/core/connections/ConnectionInfoFactory.h index e8494da..b7e0b63 100644 --- a/src/core/connections/ConnectionInfoFactory.h +++ b/src/core/connections/ConnectionInfoFactory.h @@ -20,7 +20,6 @@ extern "C" { #endif /* __cplusplus */ -char * CreateIndexedName(const char * name, unsigned i); Vector * ConnectionInfoFactoryCreateConnectionInfos(ObjectContainer * components, ConnectionInput * connInput, Component * sourceCompOverride, From 1c29e105c1da74cd66d74fea9db7598457e243e3 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Wed, 1 Sep 2021 14:15:25 +0200 Subject: [PATCH 140/295] db: Remove DatabusGet{In,Out}VectorChannel{Info,Num} --- src/components/comp_constant.c | 8 ++-- src/core/Databus.c | 79 ++++++---------------------------- src/core/Databus.h | 7 --- 3 files changed, 16 insertions(+), 78 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index c1b1140..b911ad8 100644 --- a/src/components/comp_constant.c +++ b/src/components/comp_constant.c @@ -56,7 +56,7 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) { Component * comp = (Component *) (compConstant); Databus * db = comp->GetDatabus(comp); - size_t numVecOut = DatabusGetOutVectorChannelsNum(db); + size_t numOut = DatabusGetOutChannelsNum(db); size_t i = 0; size_t sum = 0; ChannelValue * value = NULL; @@ -65,8 +65,8 @@ static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) { size_t startIdx = 0; size_t endIdx = 0; - for (i = 0; i < numVecOut; i++) { - vInfo = DatabusGetOutVectorChannelInfo(db, i); + for (i = 0; i < numOut; i++) { + vInfo = DatabusGetOutChannelInfo(db, i); startIdx = vInfo->GetStartIndex(vInfo); endIdx = vInfo->GetEndIndex(vInfo); numCh = endIdx - startIdx + 1; @@ -77,7 +77,7 @@ static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) { } } - if (i >= numVecOut) { + if (i >= numOut) { ComponentLog(comp, LOG_ERROR, "GetValue: Invalid index (%zu) provided", idx); return NULL; } diff --git a/src/core/Databus.c b/src/core/Databus.c index 0be9d88..a55ee9a 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -894,26 +894,6 @@ size_t DatabusGetInChannelsNum(Databus * db) { return DatabusInfoGetChannelNum(DatabusGetInInfo(db)); } -// Only returns SIZE_T_ERROR if db was NULL -size_t DatabusGetOutVectorChannelsNum(Databus * db) { - if (!db) { - mcx_log(LOG_ERROR, "Ports: Get outport number: Invalid structure"); - return SIZE_T_ERROR; - } - - return DatabusInfoGetVectorChannelNum(DatabusGetOutInfo(db)); -} - -// Only returns SIZE_T_ERROR if db was NULL -size_t DatabusGetInVectorChannelsNum(Databus * db) { - if (!db) { - mcx_log(LOG_ERROR, "Ports: Get inport number: Invalid structure"); - return SIZE_T_ERROR; - } - - return DatabusInfoGetVectorChannelNum(DatabusGetInInfo(db)); -} - // Only returns SIZE_T_ERROR if db was NULL size_t DatabusGetLocalChannelsNum(Databus * db) { if (!db) { @@ -1019,12 +999,12 @@ McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, return RETURN_ERROR; } - if (channel > DatabusGetOutVectorChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutVectorChannelsNum(db)); + if (channel > DatabusGetOutChannelsNum(db)) { + mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutChannelsNum(db)); return RETURN_ERROR; } - vInfo = DatabusGetOutVectorChannelInfo(db, channel); + vInfo = DatabusGetOutChannelInfo(db, channel); for (i = startIdx; i <= endIdx; i++) { McxStatus retVal = RETURN_OK; const void * ref = NULL; @@ -1068,12 +1048,12 @@ McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, return RETURN_ERROR; } - if (channel > DatabusGetOutVectorChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutVectorChannelsNum(db)); + if (channel > DatabusGetOutChannelsNum(db)) { + mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutChannelsNum(db)); return RETURN_ERROR; } - vInfo = DatabusGetOutVectorChannelInfo(db, channel); + vInfo = DatabusGetOutChannelInfo(db, channel); for (i = startIdx; i <= endIdx; i++) { McxStatus retVal = RETURN_OK; const void * ref = NULL; @@ -1167,12 +1147,12 @@ McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, s mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector needs to be specified"); return RETURN_ERROR; } - if (channel > DatabusGetInVectorChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutVectorChannelsNum(db)); + if (channel > DatabusGetInChannelsNum(db)) { + mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutChannelsNum(db)); return RETURN_ERROR; } - vInfo = DatabusGetInVectorChannelInfo(db, channel); + vInfo = DatabusGetInChannelInfo(db, channel); for (i = startIdx; i <= endIdx; i++) { McxStatus retVal = RETURN_OK; void * ref = NULL; @@ -1224,12 +1204,12 @@ McxStatus DatabusSetInRefVectorChannel(Databus * db, size_t channel, mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector needs to be specified"); return RETURN_ERROR; } - if (channel > DatabusGetInVectorChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetInVectorChannelsNum(db)); + if (channel > DatabusGetInChannelsNum(db)) { + mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetInChannelsNum(db)); return RETURN_ERROR; } - vInfo = DatabusGetInVectorChannelInfo(db, channel); + vInfo = DatabusGetInChannelInfo(db, channel); for (i = startIdx; i <= endIdx; i++) { McxStatus retVal = RETURN_OK; void * ref = NULL; @@ -1486,41 +1466,6 @@ ChannelInfo * DatabusGetLocalChannelInfo(Databus * db, size_t channel) { return (ChannelInfo *) data->infos->At(data->infos, channel); } -ChannelInfo * DatabusGetRTFactorChannelInfo(Databus * db, size_t channel) { - DatabusInfoData * data = db->data->rtfactorInfo->data; - - if (channel >= data->infos->Size(data->infos)) { - mcx_log(LOG_ERROR, "Ports: Get rtfactor-info: Unknown port %d", channel); - return NULL; - } - - return (ChannelInfo *) data->infos->At(data->infos, channel); -} - -VectorChannelInfo * DatabusGetInVectorChannelInfo(Databus * db, size_t channel) { - DatabusInfo * inInfo = NULL; - if (!db) { - mcx_log(LOG_ERROR, "Ports: Get in-info: Invalid structure"); - return NULL; - } - - inInfo = DatabusGetInInfo(db); - - return DatabusInfoGetVectorChannelInfo(inInfo, channel); -} - -VectorChannelInfo * DatabusGetOutVectorChannelInfo(Databus * db, size_t channel) { - DatabusInfo * outInfo = NULL; - if (!db) { - mcx_log(LOG_ERROR, "Ports: Get out-info: Invalid structure"); - return NULL; - } - - outInfo = DatabusGetOutInfo(db); - - return DatabusInfoGetVectorChannelInfo(outInfo, channel); -} - int DatabusChannelInIsValid(Databus * db, size_t channel) { Channel * in = NULL; diff --git a/src/core/Databus.h b/src/core/Databus.h index d003e85..572285e 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -125,13 +125,6 @@ McxStatus DatabusAddRTFactorChannel(Databus * db, /* vector channel functions */ -VectorChannelInfo * DatabusGetInVectorChannelInfo(Databus * db, size_t channel); -VectorChannelInfo * DatabusGetOutVectorChannelInfo(Databus * db, size_t channel); - -size_t DatabusGetInVectorChannelsNum(Databus * db); - -size_t DatabusGetOutVectorChannelsNum(Databus * db); - McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, size_t startIdx, size_t endIdx, const void * reference, ChannelType * type); From 7f54ae7b7340fbb16c80cf441b23dd1af76e4c3f Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Thu, 2 Sep 2021 09:21:00 +0200 Subject: [PATCH 141/295] db: Remove DatabusSet{In,Out}RefVector{Channel} --- src/core/Databus.c | 219 --------------------------------------------- src/core/Databus.h | 13 --- 2 files changed, 232 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index a55ee9a..b044bcb 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -982,122 +982,6 @@ McxStatus DatabusSetOutReferenceFunction(Databus * db, size_t channel, const voi return out->SetReferenceFunction(out, (const proc *) reference, type); } -McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, ChannelValue * value) -{ - VectorChannelInfo * vInfo = NULL; - size_t i = 0; - size_t ii = 0; - ChannelType * type = ChannelValueType(value); - - if (startIdx > endIdx) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Start index %d bigger than end index %d", startIdx, endIdx); - return RETURN_ERROR; - } - if (!ChannelTypeIsValid(type)) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Type of vector needs to be specified"); - return RETURN_ERROR; - } - - if (channel > DatabusGetOutChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutChannelsNum(db)); - return RETURN_ERROR; - } - - vInfo = DatabusGetOutChannelInfo(db, channel); - for (i = startIdx; i <= endIdx; i++) { - McxStatus retVal = RETURN_OK; - const void * ref = NULL; - ChannelOut * chOut = NULL; - ChannelInfo * chInfo = vInfo->GetElement(vInfo, i); - if (!chInfo) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector Port does not exist"); - return RETURN_ERROR; - } - chOut = (ChannelOut *) chInfo->channel; - if (!chOut) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector Port not initialized"); - return RETURN_ERROR; - } - ii = i - startIdx; - ref = (const void *) ( &((ChannelValue*)value + ii)->value ); - - retVal = chOut->SetReference(chOut, ref, type); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Reference could not be set"); - return RETURN_ERROR; - } - } - - return RETURN_OK; -} - -McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, const void * reference, ChannelType * type) -{ - VectorChannelInfo * vInfo = NULL; - size_t i = 0; - size_t ii = 0; - - if (startIdx > endIdx) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Start index %d bigger than end index %d", startIdx, endIdx); - return RETURN_ERROR; - } - if (!ChannelTypeIsValid(type)) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Type of vector needs to be specified"); - return RETURN_ERROR; - } - - if (channel > DatabusGetOutChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutChannelsNum(db)); - return RETURN_ERROR; - } - - vInfo = DatabusGetOutChannelInfo(db, channel); - for (i = startIdx; i <= endIdx; i++) { - McxStatus retVal = RETURN_OK; - const void * ref = NULL; - ChannelOut * chOut = NULL; - ChannelInfo * chInfo = vInfo->GetElement(vInfo, i); - if (!chInfo) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector Port does not exist"); - return RETURN_ERROR; - } - chOut = (ChannelOut *) chInfo->channel; - if (!chOut) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Vector Port not initialized"); - return RETURN_ERROR; - } - ii = i - startIdx; - switch (type->con) { - case CHANNEL_DOUBLE: - ref = (const void *) (((double *) reference) + ii); - break; - case CHANNEL_INTEGER: - ref = (const void *) (((int *) reference) + ii); - break; - case CHANNEL_BOOL: - ref = (const void *) (((int *) reference) + ii); - break; - case CHANNEL_BINARY: - case CHANNEL_BINARY_REFERENCE: - ref = (const void *) (((binary_string *) reference) + ii); - break; - default: - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Type of vector not allowed"); - return RETURN_ERROR; - } - - retVal = chOut->SetReference(chOut, ref, type); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Ports: Set out reference vector: Reference could not be set"); - return RETURN_ERROR; - } - } - - return RETURN_OK; -} - McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, ChannelType * type) { ChannelIn * in = NULL; ChannelInfo * info = NULL; @@ -1134,109 +1018,6 @@ McxStatus DatabusSetInReference(Databus * db, size_t channel, void * reference, return in->SetReference(in, reference, type); } -McxStatus DatabusSetInRefVector(Databus * db, size_t channel, size_t startIdx, size_t endIdx, void * reference, ChannelType * type) -{ - VectorChannelInfo * vInfo = NULL; - size_t i = 0; - size_t ii = 0; - if (startIdx > endIdx) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Start index %d bigger than end index %d", startIdx, endIdx); - return RETURN_ERROR; - } - if (!ChannelTypeIsValid(type)) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector needs to be specified"); - return RETURN_ERROR; - } - if (channel > DatabusGetInChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetOutChannelsNum(db)); - return RETURN_ERROR; - } - - vInfo = DatabusGetInChannelInfo(db, channel); - for (i = startIdx; i <= endIdx; i++) { - McxStatus retVal = RETURN_OK; - void * ref = NULL; - ChannelIn * chIn = NULL; - ChannelInfo * chInfo = vInfo->GetElement(vInfo, i); - if (!chInfo) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector Port does not exist"); - return RETURN_ERROR; - } - chIn = (ChannelIn *) chInfo->channel; - if (!chIn) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector Port not initialized"); - return RETURN_ERROR; - } - ii = i - startIdx; - if (ChannelTypeEq(&ChannelTypeDouble, type)) { - ref = (void *) (((double *) reference) + ii); - } else if (ChannelTypeEq(&ChannelTypeInteger, type)) { - ref = (void *) (((int *) reference) + ii); - } else if (ChannelTypeEq(&ChannelTypeBool, type)) { - ref = (void *) (((int *) reference) + ii); - } else { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector not allowed"); - return RETURN_ERROR; - } - retVal = chIn->SetReference(chIn, ref, type); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Reference could not be set"); - return RETURN_ERROR; - } - } - - return RETURN_OK; -} - -McxStatus DatabusSetInRefVectorChannel(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, ChannelValue * value) -{ - VectorChannelInfo * vInfo = NULL; - size_t i = 0; - size_t ii = 0; - ChannelType * type = ChannelValueType(value); - - if (startIdx > endIdx) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Start index %d bigger than end index %d", startIdx, endIdx); - return RETURN_ERROR; - } - if (!ChannelTypeIsValid(type)) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Type of vector needs to be specified"); - return RETURN_ERROR; - } - if (channel > DatabusGetInChannelsNum(db)) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector port %d does not exist (numer of vector ports=%d)", channel, DatabusGetInChannelsNum(db)); - return RETURN_ERROR; - } - - vInfo = DatabusGetInChannelInfo(db, channel); - for (i = startIdx; i <= endIdx; i++) { - McxStatus retVal = RETURN_OK; - void * ref = NULL; - ChannelIn * chIn = NULL; - ChannelInfo * chInfo = vInfo->GetElement(vInfo, i); - if (!chInfo) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector Port does not exist"); - return RETURN_ERROR; - } - chIn = (ChannelIn *) chInfo->channel; - if (!chIn) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Vector Port not initialized"); - return RETURN_ERROR; - } - ii = i - startIdx; - ref = (void *) ( &((ChannelValue*)value + ii)->value ); - - retVal = chIn->SetReference(chIn, ref, type); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Ports: Set in reference vector: Reference could not be set"); - return RETURN_ERROR; - } - } - - return RETURN_OK; -} - static char * DatabusGetUniqueChannelName(Databus * db, const char * name) { #define SUFFIX_LEN 5 diff --git a/src/core/Databus.h b/src/core/Databus.h index 572285e..9772d25 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -123,19 +123,6 @@ McxStatus DatabusAddRTFactorChannel(Databus * db, const void * reference, ChannelType * type); -/* vector channel functions */ - -McxStatus DatabusSetOutRefVector(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, const void * reference, ChannelType * type); - -McxStatus DatabusSetOutRefVectorChannel(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, ChannelValue * value); - -McxStatus DatabusSetInRefVector(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, void * reference, ChannelType * type); -McxStatus DatabusSetInRefVectorChannel(Databus * db, size_t channel, - size_t startIdx, size_t endIdx, ChannelValue * value); - /** * \return The address of the value of the in channel \a channel in \a db or \c NULL From ae6ba5d8bf5c95d15b242c934f6800ea203a1661 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 08:53:21 +0200 Subject: [PATCH 142/295] channel: Remove VectorChannelInfo --- src/components/comp_constant.c | 16 ---------------- src/core/Databus.c | 24 +----------------------- src/core/Databus.h | 1 - src/core/Databus_impl.h | 1 - src/core/channels/ChannelInfo.c | 24 ------------------------ src/core/channels/ChannelInfo.h | 8 +------- 6 files changed, 2 insertions(+), 72 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index b911ad8..b670cd8 100644 --- a/src/components/comp_constant.c +++ b/src/components/comp_constant.c @@ -60,32 +60,16 @@ static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) { 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 < numOut; i++) { - vInfo = DatabusGetOutChannelInfo(db, i); - startIdx = vInfo->GetStartIndex(vInfo); - endIdx = vInfo->GetEndIndex(vInfo); - numCh = endIdx - startIdx + 1; - - sum += numCh; - if (sum > idx) { - break; - } - } - if (i >= numOut) { 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; } diff --git a/src/core/Databus.c b/src/core/Databus.c index b044bcb..67dca95 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -38,14 +38,11 @@ extern "C" { static void DatabusInfoDataDestructor(DatabusInfoData * data) { object_destroy(data->infos); - data->origInfos->DestroyObjects(data->origInfos); - object_destroy(data->origInfos); } static DatabusInfoData * DatabusInfoDataCreate(DatabusInfoData * data) { data->infos = (Vector *) object_create(Vector); data->infos->Setup(data->infos, sizeof(ChannelInfo), ChannelInfoInit, ChannelInfoSetFrom, ChannelInfoDestroy); - data->origInfos = (ObjectContainer *) object_create(ObjectContainer); return data; } @@ -289,7 +286,6 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, Vector * dbInfos = dbInfo->data->infos; size_t requiredSize = 0; - ObjectContainer * allChannels = dbInfo->data->origInfos; for (i = 0; i < numChildren; i++) { PortInput * portInput = (PortInput *) input->ports->At(input->ports, i); @@ -314,10 +310,6 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, mcx_log(LOG_DEBUG, " Port: \"%s\"", name); } - if (RETURN_OK != allChannels->PushBackNamed(allChannels, (Object *) info, name)) { - mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); - return RETURN_ERROR; - } if (RETURN_OK != dbInfos->PushBack(dbInfos, (Object *) object_strong_reference(info), name)) { mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); return RETURN_ERROR; @@ -751,7 +743,7 @@ size_t DatabusInfoGetVectorChannelNum(DatabusInfo * info) { return SIZE_T_ERROR; } - return info->data->origInfos->Size(info->data->origInfos); + return info->data->infos->Size(info->data->infos); } ChannelInfo * DatabusInfoGetChannel(DatabusInfo * info, size_t i) { @@ -768,20 +760,6 @@ ChannelInfo * DatabusInfoGetChannel(DatabusInfo * info, size_t i) { return (ChannelInfo *) info->data->infos->At(info->data->infos, i); } -static VectorChannelInfo * DatabusInfoGetVectorChannelInfo(DatabusInfo * info, size_t i) { - if (!info) { - mcx_log(LOG_ERROR, "Ports: Get vector port info: Invalid structure"); - return NULL; - } - - if (i >= info->data->origInfos->Size(info->data->origInfos)) { - mcx_log(LOG_ERROR, "Ports: Get vector port info: Unknown port %d", i); - return NULL; - } - - return (VectorChannelInfo *) info->data->origInfos->At(info->data->origInfos, i); -} - int DatabusInChannelsDefined(Databus * db) { return db->data->in != NULL; } diff --git a/src/core/Databus.h b/src/core/Databus.h index 9772d25..d69a9ca 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -18,7 +18,6 @@ #include "core/channels/Channel.h" #include "core/connections/Connection.h" #include "core/Component.h" -#include "core/channels/VectorChannelInfo.h" #include "reader/model/ports/PortsInput.h" #ifdef __cplusplus diff --git a/src/core/Databus_impl.h b/src/core/Databus_impl.h index 8527c27..8799e8c 100644 --- a/src/core/Databus_impl.h +++ b/src/core/Databus_impl.h @@ -30,7 +30,6 @@ typedef struct DatabusInfoData { Object _; // base class Vector * infos; - ObjectContainer * origInfos; } DatabusInfoData; diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index d75de81..fa1d1cf 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -90,16 +90,6 @@ McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType * type) { return RETURN_OK; } -McxStatus ChannelInfoSetVector(ChannelInfo * info, VectorChannelInfo * vector) { - if (info->vector) { - object_destroy(info->vector); - } - - info->vector = vector; - - return RETURN_OK; -} - McxStatus ChannelInfoSetup(ChannelInfo * info, const char * name, const char * nameInModel, @@ -239,14 +229,6 @@ McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other) { } } - if (info->vector) { - object_destroy(info->vector); - } - - if (other->vector) { - info->vector = (VectorChannelInfo *) object_strong_reference(other->vector); - } - return RETURN_OK; } @@ -271,10 +253,6 @@ void ChannelInfoDestroy(ChannelInfo * info) { FreeChannelValue(&info->defaultValue); FreeChannelValue(&info->initialValue); - if (info->vector) { - object_destroy(info->vector); - } - info->channel = NULL; info->initialValueIsExact = FALSE; info->type = &ChannelTypeUnknown; @@ -283,8 +261,6 @@ void ChannelInfoDestroy(ChannelInfo * info) { } McxStatus ChannelInfoInit(ChannelInfo * info) { - info->vector = NULL; - info->dimension = NULL; info->name = NULL; diff --git a/src/core/channels/ChannelInfo.h b/src/core/channels/ChannelInfo.h index 59815cb..adad36d 100644 --- a/src/core/channels/ChannelInfo.h +++ b/src/core/channels/ChannelInfo.h @@ -12,7 +12,7 @@ #define MCX_CORE_CHANNELS_CHANNELINFO_H #include "core/channels/ChannelValue.h" -#include "core/channels/VectorChannelInfo.h" +#include "CentralParts.h" #include "core/channels/ChannelDimension.h" #include "common/status.h" @@ -25,11 +25,6 @@ extern "C" { 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. - */ - VectorChannelInfo * vector; - struct Channel * channel; // Channel is a scalar iff dimension == NULL @@ -72,7 +67,6 @@ 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); From cfea69bf4a1563fb6d9be50e7cc130127d6e1696 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 13:08:45 +0200 Subject: [PATCH 143/295] fmu: Fix memory cleanup of Fmu2Value --- src/fmu/Fmu2Value.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 70cc1a4..af8a5bc 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -22,6 +22,12 @@ extern "C" { #endif /* __cplusplus */ static void Fmu2ValueDataDestructor(Fmu2ValueData * data) { + if (data->type == FMU2_VALUE_ARRAY) { + mcx_free(data->data.array.dims); + mcx_free(data->data.array.values); + + mcx_free(data->vr.array.values); + } } static Fmu2ValueData * Fmu2ValueDataCreate(Fmu2ValueData * data) { @@ -387,6 +393,7 @@ static void Fmu2ValueDestructor(Fmu2Value * v) { mcx_free(v->unit); v->unit = NULL; } + Fmu2ValueDataDestructor(v->data); object_destroy(v->data); object_destroy(v->info); ChannelValueDestructor(&v->val); @@ -485,7 +492,7 @@ Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, c if (dimension->num > 1) { mcx_log(LOG_ERROR, "%s: Port %s: Invalid dimension", logPrefix, channelName); - return RETURN_ERROR; + goto cleanup; } size_t i = 0; @@ -494,7 +501,7 @@ Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, c fmi2_import_variable_t ** vars = mcx_calloc(endIdx - startIdx + 1, sizeof(fmi2_import_variable_t *)); if (!vars) { - return NULL; + goto cleanup; } for (i = startIdx; i <= endIdx; i++) { @@ -502,14 +509,14 @@ Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, c fmi2_import_variable_t * var = fmi2_import_get_variable_by_name(fmiImport, indexedChannelName); if (!var) { mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, indexedChannelName); - return NULL; + goto cleanup; } if (!ChannelTypeEq(ChannelTypeArrayInner(type), Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))) { mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, indexedChannelName); mcx_log(LOG_ERROR, "%s: Expected: %s, Imported from FMU: %s", logPrefix, ChannelTypeToString(ChannelTypeArrayInner(type)), ChannelTypeToString(Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)))); - return NULL; + goto cleanup; } vars[i - startIdx] = var; @@ -520,7 +527,12 @@ Fmu2Value * Fmu2ReadFmu2ArrayValue(const char * logPrefix, ChannelType * type, c val = Fmu2ValueArrayMake(channelName, 1 /* numDims */, dims, vars, unitString, NULL); if (!val) { mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); - return NULL; + goto cleanup; + } + +cleanup: + if (vars) { + mcx_free(vars); } return val; From 13b38d03462355fda61bbae94e92cd5bb22b33d4 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 13:10:02 +0200 Subject: [PATCH 144/295] channel: Fix memory cleanup of ChannelInfo --- src/core/channels/ChannelInfo.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index fa1d1cf..b54717f 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -12,6 +12,8 @@ #include "core/channels/ChannelInfo.h" +#include "core/channels/ChannelValue.h" +#include "objects/Object.h" #include "util/string.h" #ifdef __cplusplus @@ -253,6 +255,14 @@ void ChannelInfoDestroy(ChannelInfo * info) { FreeChannelValue(&info->defaultValue); FreeChannelValue(&info->initialValue); + if (info->type) { + ChannelTypeDestructor(info->type); + } + + if (info->dimension) { + object_destroy(info->dimension); + } + info->channel = NULL; info->initialValueIsExact = FALSE; info->type = &ChannelTypeUnknown; From 373b5b4499f5ffcf5bf82b41cb45688bad97f68f Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 13:10:52 +0200 Subject: [PATCH 145/295] reader: Fix memory cleanup --- mcx/mcx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mcx/mcx.c b/mcx/mcx.c index c180997..d3afd34 100644 --- a/mcx/mcx.c +++ b/mcx/mcx.c @@ -573,6 +573,10 @@ McxStatus RunMCX(int argc, char *argv[]) { cleanup: + if (reader) { + reader->Cleanup(reader); + object_destroy(reader); + } if (mcxInput) { object_destroy(mcxInput); } if (model) { object_destroy(model); } From 3772aed45b92f0e6a900b9e69c1b0cc6b7621650 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 7 Sep 2021 13:32:44 +0200 Subject: [PATCH 146/295] channel: ChannelOutUpdate: Add error messages to all error returns --- src/core/channels/Channel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index b1323f8..cbb4ceb 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -709,6 +709,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { proc * p = (proc *) out->GetFunction(out); ChannelValueData val = { 0 }; if (p->fn(time, p->env, &val) != 0) { + mcx_log(LOG_ERROR, "Port %s: Update outport: Function failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } #ifdef MCX_DEBUG @@ -734,6 +735,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } #endif // MCX_DEBUG if (RETURN_OK != ChannelValueSetFromReference(&channel->value, channel->internalValue)) { + mcx_log(LOG_ERROR, "Port %s: Update outport: Setting value failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } } From 358768d8b071a7dd1f2fed68f3eba4a9d3eff140 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Thu, 9 Sep 2021 14:05:27 +0200 Subject: [PATCH 147/295] Rename array -> mcx_array --- src/components/comp_vector_integrator.c | 10 +++---- src/core/channels/ChannelValue.c | 36 ++++++++++++------------- src/core/channels/ChannelValue.h | 12 ++++----- src/fmu/Fmu2Value.c | 4 +-- src/fmu/common_fmu2.c | 8 +++--- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index d14424f..92e28fe 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -119,11 +119,11 @@ static McxStatus DoStep(Component * comp, size_t group, double time, double delt size_t i; for (i = 0; i < integrator->num; i++) { if (ChannelTypeIsArray(ChannelValueType(&integrator->state[i]))) { - array * state = ChannelValueReference(&integrator->state[i]); - array * deriv = ChannelValueReference(&integrator->deriv[i]); + mcx_array * state = ChannelValueReference(&integrator->state[i]); + mcx_array * deriv = ChannelValueReference(&integrator->deriv[i]); size_t j = 0; - for (j = 0; j < array_num_elements(state); j++) { + for (j = 0; j < mcx_array_num_elements(state); j++) { ((double *)state->data)[j] = ((double *)state->data)[j] * ((double *)deriv->data)[j] + deltaTime; } @@ -144,10 +144,10 @@ static McxStatus Initialize(Component * comp, size_t idx, double startTime) { size_t i; for (i = 0; i < integrator->num; i++) { if (ChannelTypeIsArray(ChannelValueType(&integrator->state[i]))) { - array * a = (array *) ChannelValueReference(&integrator->state[i]); + mcx_array * a = (mcx_array *) ChannelValueReference(&integrator->state[i]); size_t j; - for (j = 0; j < array_num_elements(a); j++) { + for (j = 0; j < mcx_array_num_elements(a); j++) { ((double *) a->data)[j] = integrator->initialState; } } else { diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 0dbb319..26e5927 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -178,7 +178,7 @@ int ChannelTypeEq(ChannelType * a, ChannelType * b) { } } -McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * inner) { +McxStatus mcx_array_init(mcx_array * a, size_t numDims, size_t * dims, ChannelType * inner) { a->numDims = numDims; a->dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); if (!a->dims) { @@ -187,7 +187,7 @@ McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * inn memcpy(a->dims, dims, sizeof(size_t) * numDims); a->type = inner; - a->data = (void *) mcx_calloc(ChannelValueTypeSize(inner), array_num_elements(a)); + a->data = (void *) mcx_calloc(ChannelValueTypeSize(inner), mcx_array_num_elements(a)); if (!a->data) { return RETURN_ERROR; } @@ -195,13 +195,13 @@ McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * inn return RETURN_OK; } -void array_destroy(array * a) { +void mcx_array_destroy(mcx_array * a) { if (a->dims) { mcx_free(a->dims); } if (a->data) { mcx_free(a->data); } if (a->type) { ChannelTypeDestructor(a->type); } } -int array_dims_match(array * a, array * b) { +int mcx_array_dims_match(mcx_array * a, mcx_array * b) { size_t i = 0; if (a->numDims != b->numDims) { @@ -220,7 +220,7 @@ int array_dims_match(array * a, array * b) { return 1; } -size_t array_num_elements(array * a) { +size_t mcx_array_num_elements(mcx_array * a) { size_t i = 0; size_t n = 1; @@ -372,7 +372,7 @@ char * ChannelValueToString(ChannelValue * value) { // TODO: length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; - length *= array_num_elements(&value->value.a); + length *= mcx_array_num_elements(&value->value.a); buffer = (char *) mcx_malloc(sizeof(char) * length); if (!buffer) { return NULL; @@ -381,9 +381,9 @@ char * ChannelValueToString(ChannelValue * value) { size_t i = 0; size_t n = 0; - if (array_num_elements(&value->value.a) > 0) { + if (mcx_array_num_elements(&value->value.a) > 0) { n += fmt(buffer + n, value->value.a.data, 0); - for (i = 1; i < array_num_elements(&value->value.a); i++) { + for (i = 1; i < mcx_array_num_elements(&value->value.a); i++) { n += sprintf(buffer + n, ","); n += fmt(buffer + n, value->value.a.data, i); } @@ -530,7 +530,7 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType * type) { if (data->a.dims) { memcpy(data->a.dims, type->ty.a.dims, type->ty.a.numDims * sizeof(size_t)); } - data->a.data = mcx_calloc(array_num_elements(&data->a), ChannelValueTypeSize(data->a.type)); + data->a.data = mcx_calloc(mcx_array_num_elements(&data->a), ChannelValueTypeSize(data->a.type)); break; } case CHANNEL_UNKNOWN: @@ -583,17 +583,17 @@ McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType break; case CHANNEL_ARRAY: if (NULL != reference) { - array * a = (array *) reference; + mcx_array * a = (mcx_array *) reference; // The first call to SetFromReference fixes the dimensions if (!data->a.numDims && a->numDims) { - if (RETURN_OK != array_init(&data->a, a->numDims, a->dims, a->type)) { + if (RETURN_OK != mcx_array_init(&data->a, a->numDims, a->dims, a->type)) { return RETURN_ERROR; } } // Arrays do not support multiplexing (yet) - if (!array_dims_match(&data->a, a)) { + if (!mcx_array_dims_match(&data->a, a)) { return RETURN_ERROR; } @@ -601,7 +601,7 @@ McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType return RETURN_ERROR; } - memcpy(data->a.data, a->data, ChannelValueTypeSize(data->a.type) * array_num_elements(&data->a)); + memcpy(data->a.data, a->data, ChannelValueTypeSize(data->a.type) * mcx_array_num_elements(&data->a)); } case CHANNEL_UNKNOWN: default: @@ -673,17 +673,17 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { break; case CHANNEL_ARRAY: if (NULL != reference) { - array * a = (array *) reference; + mcx_array * a = (mcx_array *) reference; // First Set fixes the dimensions if (value->value.a.numDims && !a->numDims) { - if (RETURN_OK != array_init(a, value->value.a.numDims, value->value.a.dims, value->value.a.type)) { + if (RETURN_OK != mcx_array_init(a, value->value.a.numDims, value->value.a.dims, value->value.a.type)) { return RETURN_ERROR; } } // Arrays do not support multiplexing (yet) - if (!array_dims_match(a, &value->value.a)) { + if (!mcx_array_dims_match(a, &value->value.a)) { return RETURN_ERROR; } @@ -691,7 +691,7 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { return RETURN_ERROR; } - memcpy(a->data, value->value.a.data, ChannelValueTypeSize(a->type) * array_num_elements(a)); + memcpy(a->data, value->value.a.data, ChannelValueTypeSize(a->type) * mcx_array_num_elements(a)); } break; case CHANNEL_UNKNOWN: @@ -901,7 +901,7 @@ ChannelValue * ChannelValueNewArray(size_t numDims, size_t dims[], ChannelType * ChannelValueInit(value, ChannelTypeArray(type, numDims, dims)); if (value->value.a.data && data) { - memcpy(value->value.a.data, data, ChannelValueTypeSize(type) * array_num_elements(&value->value.a)); + memcpy(value->value.a.data, data, ChannelValueTypeSize(type) * mcx_array_num_elements(&value->value.a)); } return value; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index a919268..c91a04b 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -100,12 +100,12 @@ typedef struct { size_t * dims; ChannelType * type; void * data; -} array; +} mcx_array; -McxStatus array_init(array * a, size_t numDims, size_t * dims, ChannelType * type); -void array_destroy(array * a); -int array_dims_match(array * a, array * b); -size_t array_num_elements(array * a); +McxStatus mcx_array_init(mcx_array * a, size_t numDims, size_t * dims, ChannelType * type); +void mcx_array_destroy(mcx_array * a); +int mcx_array_dims_match(mcx_array * a, mcx_array * b); +size_t mcx_array_num_elements(mcx_array * a); // TODO: change concrete types to McxDouble, McxInteger, etc union ChannelValueData { @@ -114,7 +114,7 @@ union ChannelValueData { int i; char * s; binary_string b; - array a; + mcx_array a; }; struct ChannelValue { diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index af8a5bc..7701a95 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -249,7 +249,7 @@ static McxStatus Fmu2ValueGetVariableStart(fmi2_base_type_enu_t t, fmi2_import_v return RETURN_OK; } -static McxStatus Fmu2ValueGetArrayVariableStart(fmi2_base_type_enu_t t, fmi2_import_variable_t * var, array * a, size_t i) { +static McxStatus Fmu2ValueGetArrayVariableStart(fmi2_base_type_enu_t t, fmi2_import_variable_t * var, mcx_array * a, size_t i) { switch (t) { case fmi2_base_type_real: @@ -350,7 +350,7 @@ static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData n *= data->data.array.dims[i]; } - array * a = (array *) ChannelValueReference(&v->val); + mcx_array * a = (mcx_array *) ChannelValueReference(&v->val); for (i = 0; i < n; i++) { if (RETURN_OK != Fmu2ValueGetArrayVariableStart(t, data->data.array.values[i], a, i)) { diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 925560b..e114158 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -743,9 +743,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { case CHANNEL_ARRAY: { fmi2_value_reference_t * vrs = fmuVal->data->vr.array.values; - array * a = (array *) ChannelValueReference(&fmuVal->val); + mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); - size_t num = array_num_elements(a); + size_t num = mcx_array_num_elements(a); void * vals = a->data; if (ChannelTypeEq(a->type, &ChannelTypeDouble)) { @@ -878,9 +878,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { case CHANNEL_ARRAY: { fmi2_value_reference_t * vrs = fmuVal->data->vr.array.values; - array * a = (array *) ChannelValueReference(&fmuVal->val); + mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); - size_t num = array_num_elements(a); + size_t num = mcx_array_num_elements(a); void * vals = a->data; if (ChannelTypeEq(a->type, &ChannelTypeDouble)) { From 378e3b6343d35aaf36d365270a1b2c08cb108c8a Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Fri, 10 Sep 2021 07:33:19 +0200 Subject: [PATCH 148/295] Move mcx_copy to util/stdlib --- src/core/channels/ChannelValue.c | 11 ----------- src/core/channels/ChannelValue.h | 2 -- src/util/common/stdlib.c | 11 +++++++++++ src/util/stdlib.h | 2 ++ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 26e5927..794e606 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -15,17 +15,6 @@ extern "C" { #endif /* __cplusplus */ -void * mcx_copy(void * object, size_t size) { - void * copy = mcx_malloc(size); - if (!copy) { - return NULL; - } - - memcpy(copy, object, size); - - return copy; -} - ChannelType ChannelTypeUnknown = { CHANNEL_UNKNOWN, NULL}; ChannelType ChannelTypeInteger = { CHANNEL_INTEGER, NULL}; ChannelType ChannelTypeDouble = { CHANNEL_DOUBLE, NULL}; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index c91a04b..72501b0 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -18,8 +18,6 @@ extern "C" { #endif /* __cplusplus */ -void * mcx_copy(void * object, size_t size); - char * CreateIndexedName(const char * name, unsigned i); // possible types of values that can be put on channels diff --git a/src/util/common/stdlib.c b/src/util/common/stdlib.c index cfa25b8..3109219 100644 --- a/src/util/common/stdlib.c +++ b/src/util/common/stdlib.c @@ -20,6 +20,17 @@ extern "C" { #endif /* __cplusplus */ +void * mcx_copy(void * object, size_t size) { + void * copy = mcx_malloc(size); + if (!copy) { + return NULL; + } + + memcpy(copy, object, size); + + return copy; +} + size_t mcx_filter(void * dst, void * base, size_t nmemb, size_t size, int (*pred)(const void *, void *), void * arg) { size_t i; size_t j = 0; diff --git a/src/util/stdlib.h b/src/util/stdlib.h index 52332c2..2dd3470 100644 --- a/src/util/stdlib.h +++ b/src/util/stdlib.h @@ -18,6 +18,8 @@ extern "C" { #endif /* __cplusplus */ +void * mcx_copy(void * object, size_t size); + /** * Sorts the given array in-place using quicksort. * From a9cccb77237bbc108dc585550e09d312c573a6a2 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Fri, 10 Sep 2021 07:45:46 +0200 Subject: [PATCH 149/295] value: Cleanup ChannelValueToString --- src/core/channels/ChannelValue.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 794e606..0d1e4fb 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -345,7 +345,11 @@ char * ChannelValueToString(ChannelValue * value) { } break; case CHANNEL_ARRAY:{ + size_t i = 0; + size_t n = 0; + size_t (*fmt)(char * buffer, void * value, size_t i); + if (ChannelTypeEq(ChannelTypeArrayInner(value->type), &ChannelTypeDouble)) { fmt = ChannelValueDataDoubleToBuffer; } else if (ChannelTypeEq(ChannelTypeArrayInner(value->type), &ChannelTypeInteger)) { @@ -356,10 +360,6 @@ char * ChannelValueToString(ChannelValue * value) { return NULL; } - const char * doubleFmt = "% *.*E"; - - // TODO: - length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; length *= mcx_array_num_elements(&value->value.a); buffer = (char *) mcx_malloc(sizeof(char) * length); @@ -367,9 +367,6 @@ char * ChannelValueToString(ChannelValue * value) { return NULL; } - size_t i = 0; - size_t n = 0; - if (mcx_array_num_elements(&value->value.a) > 0) { n += fmt(buffer + n, value->value.a.data, 0); for (i = 1; i < mcx_array_num_elements(&value->value.a); i++) { From d7f36b3281db96328f2a7947607dd883d42cde45 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 13 Sep 2021 09:43:39 +0200 Subject: [PATCH 150/295] value: Remove obsolete TODOs --- src/core/channels/ChannelValue.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 0d1e4fb..d9ac3cf 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -453,8 +453,6 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel case CHANNEL_ARRAY: { const char * doubleFmt = "% *.*E"; - // TODO: - length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; if (len < length) { mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); @@ -526,7 +524,7 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType * type) { } McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType * type, const void * reference) { - if (!reference) { return RETURN_OK; } // TODO: change to ERROR + if (!reference) { return RETURN_OK; } switch (type->con) { case CHANNEL_DOUBLE: @@ -688,7 +686,6 @@ McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { return RETURN_OK; } -// TODO: invalid size should be (-1) #ifdef __cplusplus size_t ChannelValueTypeSize(ChannelType * type) { switch (type->con) { From 9bc123773df95a44285414c969f17b21e11b62a4 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 14 Sep 2021 07:55:47 +0200 Subject: [PATCH 151/295] fmu: Add defaults in actuation switch statement --- src/fmu/common_fmu2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index e114158..0602ecd 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -9,6 +9,7 @@ ********************************************************************************/ #include "fmu/common_fmu2.h" +#include "core/channels/ChannelValue.h" #include "fmu/common_fmu.h" /* for jm callbacks */ #include "fmu/Fmu2Value.h" From e4227e475b18924154f12a4072fb7cbe6e8d80c7 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 20 Sep 2021 06:54:05 +0200 Subject: [PATCH 152/295] Fix binary channel initialization --- src/core/channels/Channel.c | 10 +++++++--- src/core/channels/ChannelValue.c | 5 ++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index cbb4ceb..135daad 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -134,9 +134,13 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel mcx_log(LOG_ERROR, "Port %s: Set inport reference: Port not set up", ChannelInfoGetLogName(info)); return RETURN_ERROR; } - if (!ChannelTypeMatch(info->type, type)) { - mcx_log(LOG_ERROR, "Port %s: Set inport reference: Mismatching types", ChannelInfoGetLogName(info)); - return RETURN_ERROR; + if (!ChannelTypeEq(info->type, type)) { + if (ChannelInfoIsBinary(info) && ChannelTypeIsBinary(type)) { + // ok + } else { + mcx_log(LOG_ERROR, "Port %s: Set inport reference: Mismatching types", ChannelInfoGetLogName(info)); + return RETURN_ERROR; + } } } diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index d9ac3cf..50996c2 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -160,8 +160,6 @@ int ChannelTypeEq(ChannelType * a, ChannelType * b) { } } return 1; - } else if ((a->con == CHANNEL_BINARY || a->con == CHANNEL_BINARY_REFERENCE) && - (b->con == CHANNEL_BINARY || b->con == CHANNEL_BINARY_REFERENCE)) { } else { return a->con == b->con; } @@ -744,8 +742,9 @@ const char * ChannelTypeToString(ChannelType * type) { case CHANNEL_STRING: return "String"; case CHANNEL_BINARY: - case CHANNEL_BINARY_REFERENCE: return "Binary"; + case CHANNEL_BINARY_REFERENCE: + return "BinaryReference"; case CHANNEL_ARRAY: return "Array"; default: From 2677d063cf1c24ce2828ba41f3d6a44fc74a8352 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 20 Sep 2021 13:39:31 +0200 Subject: [PATCH 153/295] values: Fix printing of binary values --- src/core/channels/ChannelValue.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 50996c2..7df70b3 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -338,7 +338,13 @@ char * ChannelValueToString(ChannelValue * value) { size_t i = 0; for (i = 0; i < value->value.b.len; i++) { - sprintf(buffer + (4 * i), "\\x%02x", value->value.b.data[i]); + // specifier: x (hex integer) -----+ + // length: 2 (unsigned char) -----+| + // width: 2 --------------------+ || + // flag: 0-padded -------------+| || + // || || + // string literal "\x" ------+ || || + sprintf(buffer + (4 * i), "\\x%02hhx", value->value.b.data[i]); } } break; From d39476c944572145818cb777ecab4f6ffa2acca5 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Mon, 20 Sep 2021 13:40:14 +0200 Subject: [PATCH 154/295] channel: Store type of registered inport reference This avoids mismatches between `ChannelTypeBinary` and `ChannelTypeBinaryReference`. --- src/core/channels/Channel.c | 7 ++++++- src/core/channels/Channel_impl.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 135daad..4d7688f 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -10,6 +10,7 @@ #include "CentralParts.h" #include "core/Config.h" +#include "core/channels/ChannelValue.h" #include "core/connections/Connection.h" #include "core/Conversion.h" @@ -110,6 +111,9 @@ static void ChannelInDataDestructor(ChannelInData * data) { if (data->rangeConversion) { object_destroy(data->rangeConversion); } + if (data->type) { + ChannelTypeDestructor(data->type); + } } OBJECT_CLASS(ChannelInData, Object); @@ -145,6 +149,7 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel } in->data->reference = reference; + in->data->type = ChannelTypeClone(type); return RETURN_OK; } @@ -253,7 +258,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); } - if (RETURN_OK != ChannelValueDataSetFromReference(in->data->reference, info->type, channel->GetValueReference(channel))) { + if (RETURN_OK != ChannelValueDataSetFromReference(in->data->reference, in->data->type, channel->GetValueReference(channel))) { return RETURN_ERROR; } diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index af2a837..83c0133 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -44,6 +44,7 @@ typedef struct ChannelInData { int isDiscrete; void * reference; + ChannelType * type; } ChannelInData; // ---------------------------------------------------------------------- From 94c171d20017f64a7b4d7136400e6970037e61c9 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Tue, 14 Sep 2021 07:37:52 +0200 Subject: [PATCH 155/295] fmu: Get start value for binary channels --- src/fmu/Fmu2Value.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 7701a95..3cff407 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -358,19 +358,15 @@ static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData } } } else if (v->data->type == FMU2_VALUE_BINARY_OSI) { - return RETURN_OK; + ChannelValueInit(&v->val, &ChannelTypeBinary); - // TODO: Setting the initial value causes some memory errors. - - // ChannelValueInit(&v->val, &ChannelTypeBinary); - - // if (RETURN_OK != Fmu2ValueGetBinaryVariableStart( - // data->data.binary.hi, - // data->data.binary.lo, - // data->data.binary.size, - // &v->val)) { - // return RETURN_ERROR; - // } + if (RETURN_OK != Fmu2ValueGetBinaryVariableStart( + data->data.binary.hi, + data->data.binary.lo, + data->data.binary.size, + &v->val)) { + return RETURN_ERROR; + } } else { From dd3324fdeccb55cc547b52fbb8fe6516181502c2 Mon Sep 17 00:00:00 2001 From: Herwig Stuetz Date: Thu, 23 Sep 2021 08:43:04 +0200 Subject: [PATCH 156/295] monitoring: Add array support to Online Monitor --- src/core/Model.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/Model.c b/src/core/Model.c index 8c9a786..35c8f6e 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -677,7 +677,6 @@ static void ModelDestructor(void * self) { object_destroy(model->initialSubModelGenerator); object_destroy(model->subModel); object_destroy(model->initialSubModel); - } static McxStatus ModelReadComponents(void * self, ComponentsInput * input) { From 863cf396bdc9e5aafbf5f921dc098738f5cb1b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 12 May 2022 11:38:02 +0200 Subject: [PATCH 157/295] Fix: Correctly set up ChannelInfo --- src/core/Databus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 67dca95..972570d 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -98,7 +98,7 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { size_t dims[1] = { endIdx - startIdx + 1 }; - if (RETURN_OK != ChannelInfoInit(info, + if (RETURN_OK != ChannelInfoSetup(info, vectorPortInput->name, vectorPortInput->nameInModel, vectorPortInput->description, From 7683fc4e2fa3005fa6efc77d52a299e4cd634f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 12 May 2022 11:42:14 +0200 Subject: [PATCH 158/295] Fix: Vector does not have PushBackNamed --- src/core/Databus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 972570d..ceddc00 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -310,7 +310,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, mcx_log(LOG_DEBUG, " Port: \"%s\"", name); } - if (RETURN_OK != dbInfos->PushBack(dbInfos, (Object *) object_strong_reference(info), name)) { + if (RETURN_OK != dbInfos->PushBack(dbInfos, info)) { mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); return RETURN_ERROR; } From d2b80fb420e36422f30f9a4958664cfb9d4c961e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 12 May 2022 13:45:12 +0200 Subject: [PATCH 159/295] Fix: Pass the correct pointer value --- src/core/Databus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index ceddc00..746a71c 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -168,10 +168,10 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { ChannelInfoSetID(info, scalarPortInput->id); ChannelInfoSetType(info, scalarPortInput->type); - if (!ChannelInfoIsBinary(&info)) { - ChannelInfoSetUnit(&info, scalarPortInput->unit); + if (!ChannelInfoIsBinary(info)) { + ChannelInfoSetUnit(info, scalarPortInput->unit); } else { - ChannelInfoSetUnit(&info, "-"); + ChannelInfoSetUnit(info, "-"); } ChannelType * expectedType = info->type; From 362530329c57aa25e6581fce89a3bb712fb30aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 17 Sep 2021 08:24:52 +0200 Subject: [PATCH 160/295] Make FilterFactory arguments explicit --- src/core/connections/Connection.c | 89 ++++++++++------------- src/core/connections/Connection.h | 11 ++- src/core/connections/FilteredConnection.c | 15 +++- 3 files changed, 64 insertions(+), 51 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 67ec793..0ac45af 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -127,9 +127,7 @@ McxStatus MakeOneConnection(ConnectionInfo * info, InterExtrapolatingType isInte return RETURN_OK; } -static void LogStepRatios(double sourceStep, double targetStep, double synchStep, ConnectionInfo * info) { - char * connString = ConnectionInfoConnectionString(info); - +static void LogStepRatios(double sourceStep, double targetStep, double synchStep, const char * connString) { if (sourceStep <= synchStep && targetStep <= synchStep) { MCX_DEBUG_LOG("CONN %s: source <= synch && target <= synch", connString); } else if (sourceStep <= synchStep && targetStep > synchStep) { @@ -139,18 +137,13 @@ static void LogStepRatios(double sourceStep, double targetStep, double synchStep } 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; - +static size_t DetermineFilterBufferSize(Component * source, Component * target, const char * connString) { Model * model = source->GetModel(source); Task * task = model->GetTask(model); @@ -173,10 +166,8 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { 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; } @@ -184,12 +175,9 @@ static size_t DetermineFilterBufferSize(ConnectionInfo * info) { return buffSize; } -static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { +static size_t MemoryFilterHistorySize(Component * sourceComp, Component * targetComp, int extDegree, const char * connString) { size_t size = 0; - Component * sourceComp = info->sourceComponent; - Component * targetComp = info->targetComponent; - Model * model = sourceComp->GetModel(sourceComp); Task * task = model->GetTask(model); @@ -929,11 +917,9 @@ static size_t MemoryFilterHistorySize(ConnectionInfo * info, int extDegree) { } 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; } @@ -963,46 +949,51 @@ static MemoryFilter * SetMemoryFilter(int reverseSearch, ChannelType * sourceTyp return filter; } -ChannelFilter * FilterFactory(Connection * connection) { +ChannelFilter * FilterFactory(ConnectionState * state, + InterExtrapolationType extrapolation_type, + InterExtrapolationParams * extrapolation_params, + ChannelType * channel_type, + InterExtrapolatingType inter_extrapolating_type, + int is_decoupled, + Component * sourceComp, + Component * targetComp, + const char * connString) { ChannelFilter * filter = NULL; McxStatus retVal; - ConnectionInfo * info = connection->GetInfo(connection); - - 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 (ChannelTypeEq(ConnectionInfoGetType(info), &ChannelTypeDouble)) { - if (!(INTERVAL_COUPLING == params->interpolationInterval && INTERVAL_SYNCHRONIZATION == params->extrapolationInterval)) { + if (ChannelTypeEq(channel_type, &ChannelTypeDouble)) { + if (!(INTERVAL_COUPLING == extrapolation_params->interpolationInterval && + INTERVAL_SYNCHRONIZATION == extrapolation_params->extrapolationInterval)) + { mcx_log(LOG_WARNING, "The use of inter/extrapolation interval settings for double is not supported"); } - if (extrapolType == INTEREXTRAPOLATION_POLYNOMIAL) { + if (extrapolation_type == INTEREXTRAPOLATION_POLYNOMIAL) { - InterExtrapolatingType isInterExtrapol = info->isInterExtrapolating; - if (INTERPOLATING == isInterExtrapol && ConnectionInfoIsDecoupled(info)) { - isInterExtrapol = INTEREXTRAPOLATING; + if (INTERPOLATING == inter_extrapolating_type && is_decoupled) { + inter_extrapolating_type = INTEREXTRAPOLATING; } - int degree = (INTERPOLATING == isInterExtrapol) ? params->interpolationOrder : params->extrapolationOrder; + int degree = (INTERPOLATING == inter_extrapolating_type) ? extrapolation_params->interpolationOrder : + extrapolation_params->extrapolationOrder; - if (EXTRAPOLATING == isInterExtrapol || INTEREXTRAPOLATING == isInterExtrapol) { - size_t memFilterHist = MemoryFilterHistorySize(info, params->extrapolationOrder); + if (EXTRAPOLATING == inter_extrapolating_type || INTEREXTRAPOLATING == inter_extrapolating_type) { + size_t memFilterHist = MemoryFilterHistorySize(sourceComp, targetComp, extrapolation_params->extrapolationOrder, connString); if (0 != memFilterHist) { - filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, channel_type, memFilterHist); if (!filter) { return NULL; } - } else if (INTEREXTRAPOLATING == isInterExtrapol) { + } else if (INTEREXTRAPOLATING == inter_extrapolating_type) { 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); - size_t buffSize = DetermineFilterBufferSize(info); - retVal = intExtFilter->Setup(intExtFilter, params->extrapolationOrder, params->interpolationOrder, buffSize); + mcx_log(LOG_DEBUG, " Interpolation order: %d, extrapolation order: %d", extrapolation_params->interpolationOrder, extrapolation_params->extrapolationOrder); + size_t buffSize = DetermineFilterBufferSize(sourceComp, targetComp, connString); + retVal = intExtFilter->Setup(intExtFilter, extrapolation_params->extrapolationOrder, extrapolation_params->interpolationOrder, buffSize); if (RETURN_OK != retVal) { return NULL; } @@ -1017,9 +1008,9 @@ ChannelFilter * FilterFactory(Connection * connection) { } } } else { - size_t memFilterHist = MemoryFilterHistorySize(info, degree); + size_t memFilterHist = MemoryFilterHistorySize(sourceComp, targetComp, degree, connString); if (0 != memFilterHist) { - filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, channel_type, memFilterHist); if (!filter) { return NULL; } @@ -1028,7 +1019,7 @@ ChannelFilter * FilterFactory(Connection * connection) { 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); + size_t buffSize = DetermineFilterBufferSize(sourceComp, targetComp, connString); retVal = intFilter->Setup(intFilter, degree, buffSize); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Connection: Filter: Could not setup"); @@ -1045,28 +1036,28 @@ ChannelFilter * FilterFactory(Connection * connection) { } else { DiscreteFilter * discreteFilter = NULL; - if (!(0 == params->extrapolationOrder && - 0 == params->interpolationOrder && - INTERVAL_COUPLING == params->interpolationInterval && - INTERVAL_SYNCHRONIZATION == params->extrapolationInterval + if (!(0 == extrapolation_params->extrapolationOrder && + 0 == extrapolation_params->interpolationOrder && + INTERVAL_COUPLING == extrapolation_params->interpolationInterval && + INTERVAL_SYNCHRONIZATION == extrapolation_params->extrapolationInterval )) { mcx_log(LOG_WARNING, "Invalid inter/extrapolation settings for non-double connection detected"); } mcx_log(LOG_DEBUG, "Using constant synchronization step extrapolation for non-double connection"); discreteFilter = (DiscreteFilter *) object_create(DiscreteFilter); - discreteFilter->Setup(discreteFilter, ConnectionInfoGetType(info)); + discreteFilter->Setup(discreteFilter, channel_type); filter = (ChannelFilter *) discreteFilter; } - if (NULL == filter && ChannelTypeEq(ConnectionInfoGetType(info), &ChannelTypeDouble)) { + if (NULL == filter && ChannelTypeEq(channel_type, &ChannelTypeDouble)) { // TODO: add a check to avoid filters for non-multirate cases - size_t memFilterHist = MemoryFilterHistorySize(info, 0); + size_t memFilterHist = MemoryFilterHistorySize(sourceComp, targetComp, 0, connString); if (0 != memFilterHist) { - filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, ConnectionInfoGetType(info), memFilterHist); + filter = (ChannelFilter *) SetMemoryFilter(useInputsAtEndTime, channel_type, memFilterHist); if (!filter) { return NULL; } @@ -1077,7 +1068,7 @@ ChannelFilter * FilterFactory(Connection * connection) { } } - filter->AssignState(filter, &connection->state_); + filter->AssignState(filter, state); return filter; } diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h index 648ed86..94d720f 100644 --- a/src/core/connections/Connection.h +++ b/src/core/connections/Connection.h @@ -211,7 +211,16 @@ struct Connection { // Common Functionality for Subclasses McxStatus ConnectionSetup(Connection * connection, struct ChannelOut * out, struct ChannelIn * in, ConnectionInfo * info); -struct ChannelFilter * FilterFactory(Connection * connection); +struct ChannelFilter *FilterFactory(ConnectionState *state, + InterExtrapolationType extrapolation_type, + InterExtrapolationParams *extrapolation_params, + ChannelType *channel_type, + InterExtrapolatingType inter_extrapolating_type, + int is_decoupled, + Component * sourceComp, + Component * targetComp, + const char * connString); + #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index c8fd206..a4b069e 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -192,7 +192,20 @@ static McxStatus AddFilter(Connection * connection) { if (filteredConnection->data->filter) { mcx_log(LOG_DEBUG, "Connection: Not inserting filter"); } else { - filteredConnection->data->filter = FilterFactory(connection); + ConnectionInfo *info = connection->GetInfo(connection); + const char * connString = ConnectionInfoConnectionString(info); + + filteredConnection->data->filter = FilterFactory(&connection->state_, + info->interExtrapolationType, + &info->interExtrapolationParams, + ConnectionInfoGetType(info), + info->isInterExtrapolating, + ConnectionInfoIsDecoupled(info), + info->sourceComponent, + info->targetComponent, + connString); + mcx_free(connString); + if (NULL == filteredConnection->data->filter) { mcx_log(LOG_DEBUG, "Connection: No Filter created"); retVal = RETURN_ERROR; From 6e7077fd0f09113f3658c11b5f6fc7d9c68a57d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 27 Sep 2021 12:57:26 +0200 Subject: [PATCH 161/295] Create a separate filter for every array element --- src/core/channels/ChannelValue.c | 159 ++++++++------ src/core/channels/ChannelValue.h | 2 + src/core/connections/FilteredConnection.c | 202 ++++++++++++++---- src/core/connections/FilteredConnection.h | 2 +- .../connections/FilteredConnection_impl.h | 3 +- 5 files changed, 260 insertions(+), 108 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 7df70b3..12a9fd0 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -222,6 +222,40 @@ size_t mcx_array_num_elements(mcx_array * a) { return n; } +McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element) { + size_t num_elems = mcx_array_num_elements(a); + + if (idx >= num_elems) { + mcx_log(LOG_ERROR, "mcx_array_get_elem: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); + return RETURN_ERROR; + } + + switch (a->type->con) { + case CHANNEL_DOUBLE: + ChannelValueDataSetFromReference(element, a->type, ((double*)a->data) + idx); + break; + case CHANNEL_INTEGER: + case CHANNEL_BOOL: + ChannelValueDataSetFromReference(element, a->type, ((int *) a->data) + idx); + break; + case CHANNEL_STRING: + ChannelValueDataSetFromReference(element, a->type, ((char **) a->data) + idx); + break; + case CHANNEL_BINARY: + case CHANNEL_BINARY_REFERENCE: + ChannelValueDataSetFromReference(element, a->type, ((binary_string *) a->data) + idx); + break; + case CHANNEL_ARRAY: + ChannelValueDataSetFromReference(element, a->type, ((mcx_array *) a->data) + idx); + break; + default: + mcx_log(LOG_ERROR, "mcx_array_get_elem: Unknown array type"); + return RETURN_ERROR; + } + + return RETURN_OK; +} + void ChannelValueInit(ChannelValue * value, ChannelType * type) { value->type = type; ChannelValueDataInit(&value->value, type); @@ -617,77 +651,82 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { return RETURN_OK; } -McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { - switch (value->type->con) { - case CHANNEL_DOUBLE: - * (double *) reference = value->value.d; - break; - case CHANNEL_INTEGER: - * (int *) reference = value->value.i; - break; - case CHANNEL_BOOL: - * (int *) reference = value->value.i; - break; - case CHANNEL_STRING: - if (* (char **) reference) { - mcx_free(* (char **) reference); - * (char **) reference = NULL; - } - if (value->value.s) { - * (char **) reference = (char *) mcx_calloc(strlen(value->value.s) + 1, sizeof(char)); - if (* (char **) reference) { - strncpy(* (char **) reference, value->value.s, strlen(value->value.s) + 1); +McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * type, void * reference) { + switch (type->con) { + case CHANNEL_DOUBLE: + *(double *) reference = value->d; + break; + case CHANNEL_INTEGER: + *(int *) reference = value->i; + break; + case CHANNEL_BOOL: + *(int *) reference = value->i; + break; + case CHANNEL_STRING: + if (*(char **) reference) { + mcx_free(*(char **) reference); + *(char **) reference = NULL; } - } - break; - case CHANNEL_BINARY: - if (NULL != reference && NULL != ((binary_string *) reference)->data) { - mcx_free(((binary_string *) reference)->data); - ((binary_string *) reference)->data = NULL; - } - if (value->value.b.data) { - ((binary_string *) reference)->len = value->value.b.len; - ((binary_string *) reference)->data = (char *) mcx_calloc(value->value.b.len, 1); - if (((binary_string *) reference)->data) { - memcpy(((binary_string *) reference)->data, value->value.b.data, value->value.b.len); + if (value->s) { + *(char **) reference = (char *) mcx_calloc(strlen(value->s) + 1, sizeof(char)); + if (*(char **) reference) { + strncpy(*(char **) reference, value->s, strlen(value->s) + 1); + } } - } - break; - case CHANNEL_BINARY_REFERENCE: - if (NULL != reference) { - ((binary_string *) reference)->len = value->value.b.len; - ((binary_string *) reference)->data = value->value.b.data; - } - break; - case CHANNEL_ARRAY: - if (NULL != reference) { - mcx_array * a = (mcx_array *) reference; + break; + case CHANNEL_BINARY: + if (NULL != reference && NULL != ((binary_string *) reference)->data) { + mcx_free(((binary_string *) reference)->data); + ((binary_string *) reference)->data = NULL; + } + if (value->b.data) { + ((binary_string *) reference)->len = value->b.len; + ((binary_string *) reference)->data = (char *) mcx_calloc(value->b.len, 1); + if (((binary_string *) reference)->data) { + memcpy(((binary_string *) reference)->data, value->b.data, value->b.len); + } + } + break; + case CHANNEL_BINARY_REFERENCE: + if (NULL != reference) { + ((binary_string *) reference)->len = value->b.len; + ((binary_string *) reference)->data = value->b.data; + } + break; + case CHANNEL_ARRAY: + if (NULL != reference) { + mcx_array * a = (mcx_array *) reference; + + // First Set fixes the dimensions + if (value->a.numDims && !a->numDims) { + if (RETURN_OK != mcx_array_init(a, value->a.numDims, value->a.dims, value->a.type)) { + return RETURN_ERROR; + } + } - // First Set fixes the dimensions - if (value->value.a.numDims && !a->numDims) { - if (RETURN_OK != mcx_array_init(a, value->value.a.numDims, value->value.a.dims, value->value.a.type)) { + // Arrays do not support multiplexing (yet) + if (!mcx_array_dims_match(a, &value->a)) { return RETURN_ERROR; } - } - // Arrays do not support multiplexing (yet) - if (!mcx_array_dims_match(a, &value->value.a)) { - return RETURN_ERROR; - } + if (value->a.data == NULL || a->data == NULL) { + return RETURN_ERROR; + } - if (value->value.a.data == NULL || a->data == NULL) { - return RETURN_ERROR; + memcpy(a->data, value->a.data, ChannelValueTypeSize(a->type) * mcx_array_num_elements(a)); } - - memcpy(a->data, value->value.a.data, ChannelValueTypeSize(a->type) * mcx_array_num_elements(a)); - } - break; - case CHANNEL_UNKNOWN: - default: - break; + break; + case CHANNEL_UNKNOWN: + default: + break; } return RETURN_OK; + +} + +McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference) { + return ChannelValueDataSetToReference(&value->value, value->type, reference); } #ifdef __cplusplus diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 72501b0..142be36 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -104,6 +104,7 @@ McxStatus mcx_array_init(mcx_array * a, size_t numDims, size_t * dims, ChannelTy void mcx_array_destroy(mcx_array * a); int mcx_array_dims_match(mcx_array * a, mcx_array * b); size_t mcx_array_num_elements(mcx_array * a); +McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element); // TODO: change concrete types to McxDouble, McxInteger, etc union ChannelValueData { @@ -133,6 +134,7 @@ void * ChannelValueReference(ChannelValue * value); void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type); void ChannelValueDataInit(ChannelValueData * data, ChannelType * type); McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType * type, const void * reference); +McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * type, void * reference); McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * reference); McxStatus ChannelValueSetToReference(ChannelValue * value, void * reference); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index a4b069e..2caa143 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -21,7 +21,8 @@ extern "C" { #endif /* __cplusplus */ static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionData * data) { - data->filter = NULL; + data->filters = NULL; + data->numFilters = 0; ChannelValueInit(&data->store, ChannelTypeClone(&ChannelTypeUnknown)); @@ -30,7 +31,14 @@ static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionD static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { ChannelValueDestructor(&data->store); - object_destroy(data->filter); + + if (data->filters) { + size_t i = 0; + for (i = 0; i < data->numFilters; i++) { + object_destroy(data->filters[i]); + } + mcx_free(data->filters); + } } OBJECT_CLASS(FilteredConnectionData, Object); @@ -51,7 +59,8 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o } // filter will be added after model is connected - filteredConnection->data->filter = NULL; + filteredConnection->data->filters = NULL; + filteredConnection->data->numFilters = 0; // value store ChannelValueInit(&filteredConnection->data->store, ChannelTypeClone(sourceInfo->type)); @@ -72,15 +81,18 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o static McxStatus FilteredConnectionEnterCommunicationMode(Connection * connection, double time) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; - ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection); McxStatus retVal = RETURN_OK; + size_t i = 0; - if (filter) { - if (filter->EnterCommunicationMode) { - retVal = filter->EnterCommunicationMode(filter, time); - if (RETURN_OK != retVal) { - return RETURN_ERROR; + for (i = 0; i < filteredConnection->data->numFilters; i++) { + ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, i); + if (filter) { + if (filter->EnterCommunicationMode) { + retVal = filter->EnterCommunicationMode(filter, time); + if (RETURN_OK != retVal) { + return RETURN_ERROR; + } } } } @@ -93,15 +105,18 @@ static McxStatus FilteredConnectionEnterCouplingStepMode(Connection * connection , double communicationTimeStepSize, double sourceTimeStepSize, double targetTimeStepSize) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; - ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection); McxStatus retVal = RETURN_OK; + size_t i = 0; - if (filter) { - if (filter->EnterCouplingStepMode) { - retVal = filter->EnterCouplingStepMode(filter, communicationTimeStepSize, sourceTimeStepSize, targetTimeStepSize); - if (RETURN_OK != retVal) { - return RETURN_ERROR; + for (i = 0; i < filteredConnection->data->numFilters; i++) { + ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, i); + if (filter) { + if (filter->EnterCouplingStepMode) { + retVal = filter->EnterCouplingStepMode(filter, communicationTimeStepSize, sourceTimeStepSize, targetTimeStepSize); + if (RETURN_OK != retVal) { + return RETURN_ERROR; + } } } } @@ -110,8 +125,15 @@ static McxStatus FilteredConnectionEnterCouplingStepMode(Connection * connection return RETURN_OK; } -static ChannelFilter * FilteredConnectionGetFilter(FilteredConnection * connection) { - return connection->data->filter; +static ChannelFilter * FilteredConnectionGetFilter(FilteredConnection * connection, size_t idx) { + if (connection->data->filters && idx < connection->data->numFilters) { + return connection->data->filters[idx]; + } + return NULL; +} + +static size_t FilteredConnectionGetNumFilters(FilteredConnection *connection) { + return connection->data->numFilters; } static McxStatus FilteredConnectionSetResult(FilteredConnection * connection, const void * value) { @@ -120,21 +142,37 @@ static McxStatus FilteredConnectionSetResult(FilteredConnection * connection, co static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInterval * time) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; - ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection); Channel * channel = (Channel *) connection->GetSource(connection); + ChannelInfo * info = &channel->info; #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateFromInput", time->startTime, ChannelInfoGetName(info)); } #endif // TODO: copy only sourceDimension slice - if (filter && time->startTime >= 0) { - ChannelValueData value = * (ChannelValueData *) channel->GetValueReference(channel); - filter->SetValue(filter, time->startTime, value); + if (ChannelTypeIsScalar(info->type)) { + ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, 0); + if (filter && time->startTime >= 0) { + ChannelValueData value = *(ChannelValueData *) channel->GetValueReference(channel); + filter->SetValue(filter, time->startTime, value); + } + } else { + size_t i = 0; + ChannelValueData element; + ChannelValueDataInit(&element, ChannelTypeBaseType(info->type)); + + for (i = 0; i < FilteredConnectionGetNumFilters(filteredConnection); i++) { + ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, i); + + if (filter && time->startTime >= 0) { + ChannelValueData value = *(ChannelValueData *) channel->GetValueReference(channel); + mcx_array_get_elem(&value.a, i, &element); + filter->SetValue(filter, time->startTime, element); + } + } } } @@ -144,11 +182,11 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI ChannelFilter * filter = NULL; Channel * channel = (Channel *) connection->GetSource(connection); + ChannelInfo * info = &channel->info; ChannelOut * out = (ChannelOut *) channel; #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - ChannelInfo * info = &channel->info; MCX_DEBUG_LOG("[%f] FCONN (%s) UpdateToOutput", time->startTime, ChannelInfoGetName(info)); } #endif @@ -167,15 +205,38 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI } } else { // only filter if time is not negative (negative time means filter disabled) - if (filteredConnection->GetReadFilter(filteredConnection) && time->startTime >= 0) { + if (filteredConnection->GetReadFilter(filteredConnection, 0) && time->startTime >= 0) { ChannelValueData value = { 0 }; - filter = filteredConnection->GetReadFilter(filteredConnection); - value = filter->GetValue(filter, time->startTime); - - if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { - mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); - return RETURN_ERROR; + if (ChannelTypeIsScalar(info->type)) { + filter = filteredConnection->GetReadFilter(filteredConnection, 0); + value = filter->GetValue(filter, time->startTime); + + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { + mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); + return RETURN_ERROR; + } + } else { + size_t i = 0; + size_t numFilters = FilteredConnectionGetNumFilters(filteredConnection); + ChannelType * type = info->type; + + mcx_array elements = {0}; + mcx_array_init(&elements, type->ty.a.numDims, type->ty.a.dims, type->ty.a.inner); + + char * dest = (char *) elements.data; + for (i = 0; i < numFilters; i++) { + filter = filteredConnection->GetReadFilter(filteredConnection, i); + value = filter->GetValue(filter, time->startTime); + + ChannelValueDataSetToReference(&value, ChannelTypeBaseType(type), (void *) dest); + dest += ChannelValueTypeSize(ChannelTypeBaseType(type)); + } + + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &elements)) { + mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); + return RETURN_ERROR; + } } } } @@ -189,30 +250,79 @@ static McxStatus AddFilter(Connection * connection) { McxStatus retVal = RETURN_OK; - if (filteredConnection->data->filter) { + if (filteredConnection->data->filters) { mcx_log(LOG_DEBUG, "Connection: Not inserting filter"); } else { - ConnectionInfo *info = connection->GetInfo(connection); + ConnectionInfo * info = connection->GetInfo(connection); const char * connString = ConnectionInfoConnectionString(info); + ChannelDimension * dimension = info->sourceDimension; - filteredConnection->data->filter = FilterFactory(&connection->state_, - info->interExtrapolationType, - &info->interExtrapolationParams, - ConnectionInfoGetType(info), - info->isInterExtrapolating, - ConnectionInfoIsDecoupled(info), - info->sourceComponent, - info->targetComponent, - connString); - mcx_free(connString); + if (dimension) { // array + size_t i = 0; + + if (dimension->num > 1) { + mcx_log(LOG_ERROR, "Setting filters for multi-dimensional connections is not supported"); + retVal = RETURN_ERROR; + goto cleanup; + } + + filteredConnection->data->numFilters = dimension->endIdxs[0] - dimension->startIdxs[0] + 1; + filteredConnection->data->filters = (ChannelFilter **) mcx_calloc(filteredConnection->data->numFilters, sizeof(ChannelFilter*)); + if (!filteredConnection->data->filters) { + mcx_log(LOG_ERROR, "Creating array filters failed: no memory"); + retVal = RETURN_ERROR; + goto cleanup; + } + + for (i = 0; i < filteredConnection->data->numFilters; i++) { + filteredConnection->data->filters[i] = FilterFactory(&connection->state_, + info->interExtrapolationType, + &info->interExtrapolationParams, + ChannelTypeBaseType(ConnectionInfoGetType(info)), + info->isInterExtrapolating, + ConnectionInfoIsDecoupled(info), + info->sourceComponent, + info->targetComponent, + connString); + if (NULL == filteredConnection->data->filters[i]) { + mcx_log(LOG_DEBUG, "Connection: Array filter creation failed for index %d", i); + retVal = RETURN_ERROR; + goto cleanup; + } + } + } else { + filteredConnection->data->filters = (ChannelFilter **) mcx_calloc(1, sizeof(ChannelFilter *)); + if (!filteredConnection->data->filters) { + mcx_log(LOG_ERROR, "Creating filter failed: no memory"); + retVal = RETURN_ERROR; + goto cleanup; + } - if (NULL == filteredConnection->data->filter) { - mcx_log(LOG_DEBUG, "Connection: No Filter created"); - retVal = RETURN_ERROR; + filteredConnection->data->numFilters = 1; + filteredConnection->data->filters[0] = FilterFactory(&connection->state_, + info->interExtrapolationType, + &info->interExtrapolationParams, + ConnectionInfoGetType(info), + info->isInterExtrapolating, + ConnectionInfoIsDecoupled(info), + info->sourceComponent, + info->targetComponent, + connString); + if (NULL == filteredConnection->data->filters[0]) { + mcx_log(LOG_DEBUG, "Connection: No Filter created"); + retVal = RETURN_ERROR; + goto cleanup; + } + } + +cleanup: + mcx_free(connString); + if (retVal != RETURN_OK) { + return retVal; } } - return retVal; + return RETURN_OK; } static void FilteredConnectionDestructor(FilteredConnection * filteredConnection) { diff --git a/src/core/connections/FilteredConnection.h b/src/core/connections/FilteredConnection.h index 00dc94a..01f0f4e 100644 --- a/src/core/connections/FilteredConnection.h +++ b/src/core/connections/FilteredConnection.h @@ -20,7 +20,7 @@ extern "C" { typedef struct FilteredConnection FilteredConnection; -typedef struct ChannelFilter * (* fConnectionGetFilter)(FilteredConnection * connection); +typedef struct ChannelFilter * (* fConnectionGetFilter)(FilteredConnection * connection, size_t idx); typedef McxStatus (* fFilteredConnectionSetResult)(FilteredConnection * connection, const void * value); diff --git a/src/core/connections/FilteredConnection_impl.h b/src/core/connections/FilteredConnection_impl.h index 09ab299..3a534d0 100644 --- a/src/core/connections/FilteredConnection_impl.h +++ b/src/core/connections/FilteredConnection_impl.h @@ -28,7 +28,8 @@ typedef struct FilteredConnectionData { // storage of the filtered value provided by the output channel ChannelValue store; - ChannelFilter * filter; + ChannelFilter ** filters; + size_t numFilters; } FilteredConnectionData; From 0a9c099400b37071108ee1326eca635eeffb1fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 6 Oct 2021 13:56:52 +0200 Subject: [PATCH 162/295] Remove unused function --- src/core/Databus.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 746a71c..7db70c0 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -736,16 +736,6 @@ size_t DatabusInfoGetChannelNum(DatabusInfo * info) { return info->data->infos->Size(info->data->infos); } -// Only returns SIZE_T_ERROR if info was NULL -size_t DatabusInfoGetVectorChannelNum(DatabusInfo * info) { - if (!info) { - mcx_log(LOG_ERROR, "Ports: Get vector port number: Invalid structure"); - return SIZE_T_ERROR; - } - - return info->data->infos->Size(info->data->infos); -} - ChannelInfo * DatabusInfoGetChannel(DatabusInfo * info, size_t i) { if (!info) { mcx_log(LOG_ERROR, "Ports: Get port info: Invalid structure"); From 378e26bcf074c4d1e12f2ab114c371301c4ef94a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 12 Oct 2021 11:06:11 +0200 Subject: [PATCH 163/295] Add functions for calculating the number of in/out databus elements When all channels are scalars, the functions behave the same way as DatabusGetIn/OutChannelsNum. If some channels are array, they will contribute to the results with the total number of their elements. --- src/core/Databus.c | 26 ++++++++++++++++++++++++++ src/core/Databus.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/src/core/Databus.c b/src/core/Databus.c index 7db70c0..b29083e 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -736,6 +736,24 @@ size_t DatabusInfoGetChannelNum(DatabusInfo * info) { return info->data->infos->Size(info->data->infos); } +size_t DatabusInfoGetChannelElemNum(DatabusInfo * info) { + size_t numInfos = info->data->infos->Size(info->data->infos); + size_t i = 0; + size_t numElems = 0; + + for (i = 0; i < numInfos; i++) { + ChannelInfo * chInfo = (ChannelInfo*)info->data->infos->At(info->data->infos, i); + if (chInfo->dimension) { + // array + numElems += ChannelDimensionNumElements(chInfo->dimension); + } else { + numElems += 1; + } + } + + return numElems; +} + ChannelInfo * DatabusInfoGetChannel(DatabusInfo * info, size_t i) { if (!info) { mcx_log(LOG_ERROR, "Ports: Get port info: Invalid structure"); @@ -882,6 +900,14 @@ size_t DatabusGetRTFactorChannelsNum(Databus * db) { return DatabusInfoGetChannelNum(DatabusGetRTFactorInfo(db)); } +size_t DatabusGetOutChannelsElemNum(Databus * db) { + return DatabusInfoGetChannelElemNum(DatabusGetOutInfo(db)); +} + +size_t DatabusGetInChannelsElemNum(Databus * db) { + return DatabusInfoGetChannelElemNum(DatabusGetInInfo(db)); +} + McxStatus DatabusSetOutReference(Databus * db, size_t channel, const void * reference, ChannelType * type) { ChannelOut * out = NULL; diff --git a/src/core/Databus.h b/src/core/Databus.h index d69a9ca..8ae0cfe 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -69,6 +69,9 @@ size_t DatabusGetInChannelsNum(struct Databus * db); */ size_t DatabusGetLocalChannelsNum(struct Databus * db); +size_t DatabusGetInChannelsElemNum(Databus * db); +size_t DatabusGetOutChannelsElemNum(Databus * db); + /** * \return The number of rtfactor channels of \a db or -1 if \a db is not initialized * correctly. From 15b99662c342afebdb9df4c39cf4e9cf1a7ff227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 12 Oct 2021 12:11:59 +0200 Subject: [PATCH 164/295] Pre-allocate memory for channel value data used by channel functions --- src/core/channels/Channel.c | 17 +++++++++++++---- src/core/channels/ChannelValue.h | 2 +- src/core/channels/Channel_impl.h | 3 +++ src/core/connections/FilteredConnection.c | 12 +++++++++--- src/core/connections/FilteredConnection_impl.h | 3 +++ 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 4d7688f..42fff71 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -468,6 +468,7 @@ static ChannelIn * ChannelInCreate(ChannelIn * in) { static ChannelOutData * ChannelOutDataCreate(ChannelOutData * data) { data->valueFunction = NULL; + ChannelValueInit(&data->valueFunctionRes, ChannelTypeClone(&ChannelTypeUnknown)); data->rangeConversion = NULL; data->linearConversion = NULL; @@ -499,6 +500,8 @@ static void ChannelOutDataDestructor(ChannelOutData * data) { object_destroy(conns->elements[i]); } object_destroy(data->connections); + + ChannelValueDestructor(&data->valueFunctionRes); } OBJECT_CLASS(ChannelOutData, Object); @@ -678,6 +681,9 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r // Save channel procedure out->data->valueFunction = (const proc *) reference; + // Initialize (and allocate necessary memory) + ChannelValueInit(&out->data->valueFunctionRes, ChannelTypeClone(type)); + // Setup value reference to point to internal value channel->internalValue = ChannelValueReference(&channel->value); @@ -716,17 +722,20 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { if (out->GetFunction(out)) { // function value proc * p = (proc *) out->GetFunction(out); - ChannelValueData val = { 0 }; - if (p->fn(time, p->env, &val) != 0) { + if (p->fn(time, p->env, &out->data->valueFunctionRes) != 0) { mcx_log(LOG_ERROR, "Port %s: Update outport: Function failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { - MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, val.d); + MCX_DEBUG_LOG("[%f] CH OUT (%s) (%f, %f)", + time->startTime, + ChannelInfoGetLogName(info), + time->startTime, + out->data->valueFunctionRes.value.d); } #endif // MCX_DEBUG - if (RETURN_OK != ChannelValueSetFromReference(&channel->value, &val)) { + if (RETURN_OK != ChannelValueSetFromReference(&channel->value, ChannelValueReference(&out->data->valueFunctionRes))) { return RETURN_ERROR; } } else { diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 142be36..34489b6 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -84,7 +84,7 @@ typedef union ChannelValueData ChannelValueData; typedef struct ChannelValue ChannelValue; typedef struct { - int (* fn)(TimeInterval * arg, void * env, ChannelValueData * res); + int (* fn)(TimeInterval * arg, void * env, ChannelValue * res); void * env; } proc; diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index 83c0133..8708cc6 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -57,6 +57,9 @@ typedef struct ChannelOutData { // Function pointer that provides the value of the channel when called const proc * valueFunction; + // Used to store results of channel-internal valueFunction calls + ChannelValue valueFunctionRes; + // ---------------------------------------------------------------------- // Conversion diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 2caa143..024fdad 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -24,6 +24,7 @@ static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionD data->filters = NULL; data->numFilters = 0; + ChannelValueInit(&data->fnResBuffer, ChannelTypeClone(&ChannelTypeUnknown)); ChannelValueInit(&data->store, ChannelTypeClone(&ChannelTypeUnknown)); return data; @@ -31,6 +32,7 @@ static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionD static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { ChannelValueDestructor(&data->store); + ChannelValueDestructor(&data->fnResBuffer); if (data->filters) { size_t i = 0; @@ -68,6 +70,10 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o // value reference connection->value_ = ChannelValueReference(&filteredConnection->data->store); + // initialize the buffer for channel function calls + if (out->GetFunction(out)) { + ChannelValueInit(&filteredConnection->data->fnResBuffer, sourceInfo->type); + } // Connection::Setup() // this has to be done last as it connects the channels @@ -193,13 +199,13 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI if (out->GetFunction(out)) { proc * p = (proc *) out->GetFunction(out); - ChannelValueData value = { 0 }; - if (p->fn(time, p->env, &value) != 0) { + if (p->fn(time, p->env, &filteredConnection->data->fnResBuffer) != 0) { mcx_log(LOG_ERROR, "FilteredConnection: Function failed"); return RETURN_ERROR; } - if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &value)) { + + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueReference(&filteredConnection->data->fnResBuffer))) { mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } diff --git a/src/core/connections/FilteredConnection_impl.h b/src/core/connections/FilteredConnection_impl.h index 3a534d0..c586c4c 100644 --- a/src/core/connections/FilteredConnection_impl.h +++ b/src/core/connections/FilteredConnection_impl.h @@ -28,6 +28,9 @@ typedef struct FilteredConnectionData { // storage of the filtered value provided by the output channel ChannelValue store; + // storage for temporary results of channel function calls + ChannelValue fnResBuffer; + ChannelFilter ** filters; size_t numFilters; From 2d7da5618d581409e1c39ddd5a625861f8065e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 14 Oct 2021 11:15:51 +0200 Subject: [PATCH 165/295] Do not allocate memory for arrays in UpdateToOutput --- src/core/connections/FilteredConnection.c | 20 ++++++++----------- .../connections/FilteredConnection_impl.h | 4 ++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 024fdad..4140637 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -24,7 +24,7 @@ static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionD data->filters = NULL; data->numFilters = 0; - ChannelValueInit(&data->fnResBuffer, ChannelTypeClone(&ChannelTypeUnknown)); + ChannelValueInit(&data->updateBuffer, ChannelTypeClone(&ChannelTypeUnknown)); ChannelValueInit(&data->store, ChannelTypeClone(&ChannelTypeUnknown)); return data; @@ -32,7 +32,7 @@ static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionD static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { ChannelValueDestructor(&data->store); - ChannelValueDestructor(&data->fnResBuffer); + ChannelValueDestructor(&data->updateBuffer); if (data->filters) { size_t i = 0; @@ -71,9 +71,7 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o connection->value_ = ChannelValueReference(&filteredConnection->data->store); // initialize the buffer for channel function calls - if (out->GetFunction(out)) { - ChannelValueInit(&filteredConnection->data->fnResBuffer, sourceInfo->type); - } + ChannelValueInit(&filteredConnection->data->updateBuffer, ChannelTypeClone(sourceInfo->type)); // Connection::Setup() // this has to be done last as it connects the channels @@ -200,12 +198,12 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI if (out->GetFunction(out)) { proc * p = (proc *) out->GetFunction(out); - if (p->fn(time, p->env, &filteredConnection->data->fnResBuffer) != 0) { + if (p->fn(time, p->env, &filteredConnection->data->updateBuffer) != 0) { mcx_log(LOG_ERROR, "FilteredConnection: Function failed"); return RETURN_ERROR; } - if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueReference(&filteredConnection->data->fnResBuffer))) { + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueReference(&filteredConnection->data->updateBuffer))) { mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } @@ -227,10 +225,8 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI size_t numFilters = FilteredConnectionGetNumFilters(filteredConnection); ChannelType * type = info->type; - mcx_array elements = {0}; - mcx_array_init(&elements, type->ty.a.numDims, type->ty.a.dims, type->ty.a.inner); - - char * dest = (char *) elements.data; + mcx_array * elements = (mcx_array *) ChannelValueReference(&filteredConnection->data->updateBuffer); + char * dest = (char *) elements->data; for (i = 0; i < numFilters; i++) { filter = filteredConnection->GetReadFilter(filteredConnection, i); value = filter->GetValue(filter, time->startTime); @@ -239,7 +235,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI dest += ChannelValueTypeSize(ChannelTypeBaseType(type)); } - if (RETURN_OK != filteredConnection->SetResult(filteredConnection, &elements)) { + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, elements)) { mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } diff --git a/src/core/connections/FilteredConnection_impl.h b/src/core/connections/FilteredConnection_impl.h index c586c4c..8071a00 100644 --- a/src/core/connections/FilteredConnection_impl.h +++ b/src/core/connections/FilteredConnection_impl.h @@ -28,8 +28,8 @@ typedef struct FilteredConnectionData { // storage of the filtered value provided by the output channel ChannelValue store; - // storage for temporary results of channel function calls - ChannelValue fnResBuffer; + // storage for temporary results during out channel updates + ChannelValue updateBuffer; ChannelFilter ** filters; size_t numFilters; From d3842b831b93ace0e6748c870539fddebc2d8822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 14 Oct 2021 15:35:18 +0200 Subject: [PATCH 166/295] Properly initialize the type in ChannelInData --- src/core/channels/Channel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 42fff71..a42b980 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -87,6 +87,7 @@ static Channel * ChannelCreate(Channel * channel) { static ChannelInData * ChannelInDataCreate(ChannelInData * data) { data->connection = NULL; data->reference = NULL; + data->type = ChannelTypeClone(&ChannelTypeUnknown); data->unitConversion = NULL; data->typeConversion = NULL; From fc8a20bb1227ffeb3eb3171bd17d7b0feabf0677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:12:26 +0200 Subject: [PATCH 167/295] Do not forget to call ChannelInfoInit --- src/core/Databus.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/Databus.c b/src/core/Databus.c index b29083e..78b57d1 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -57,6 +57,11 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { return NULL; } + retVal = ChannelInfoInit(info); + if (RETURN_ERROR == retVal) { + goto cleanup_0; + } + if (input->type == PORT_VECTOR) { VectorPortInput * vectorPortInput = input->port.vectorPort; InputElement * vectorPortElement = (InputElement *) vectorPortInput; From 0530ea23ced06aac92b9f92da5b36223c4560908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:12:42 +0200 Subject: [PATCH 168/295] Fix indentation --- src/core/Databus.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 78b57d1..067b514 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -104,12 +104,12 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { size_t dims[1] = { endIdx - startIdx + 1 }; if (RETURN_OK != ChannelInfoSetup(info, - vectorPortInput->name, - vectorPortInput->nameInModel, - vectorPortInput->description, - vectorPortInput->unit, - ChannelTypeArray(vectorPortInput->type, 1, dims), - vectorPortInput->id)) { + vectorPortInput->name, + vectorPortInput->nameInModel, + vectorPortInput->description, + vectorPortInput->unit, + ChannelTypeArray(vectorPortInput->type, 1, dims), + vectorPortInput->id)) { mcx_log(LOG_ERROR, "Could not Init ChannelInfo"); retVal = RETURN_ERROR; goto vector_cleanup_0; From 2106dd488d195b27404e29e7d1475acc5bbb3d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:13:00 +0200 Subject: [PATCH 169/295] Fix ChannelDimension definition --- src/core/channels/ChannelDimension.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index d8763c7..d107edf 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -20,7 +20,7 @@ extern "C" { extern const struct ObjectClass _ChannelDimension; typedef struct ChannelDimension { - Object * _; // super class first + Object _; // super class first size_t num; size_t * startIdxs; From 2178a44ae4b418bf131fd6465f4c446bdbd2f84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:13:39 +0200 Subject: [PATCH 170/295] Remove obsolete explicit destruction of channel info --- src/storage/ChannelStorage.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index 6921ba4..e1c0f24 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -306,15 +306,12 @@ static void ChannelStorageDestructor(ChannelStorage * channelStore) { if (channels) { size_t i = 0; - if (channels->Size(channels) > 0) { - Channel * channel = (Channel *) channels->At(channels, 0); - ChannelInfo * timeInfo = &channel->info; - object_destroy(timeInfo); - } + for (i = 0; i < channels->Size(channels); i++) { Channel * channel = (Channel *) channels->At(channels, i); object_destroy(channel); } + object_destroy(channels); } } From eeece338944ed50f28e5de8c0c49dac48cd18f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:14:14 +0200 Subject: [PATCH 171/295] Do not forget to clone types --- src/core/Model.c | 2 +- src/core/channels/ChannelInfo.c | 8 ++++---- src/core/connections/filters/MemoryFilter.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/Model.c b/src/core/Model.c index 35c8f6e..f828ec0 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -197,7 +197,7 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { goto cleanup_1; } - ChannelValueInit(src, srcChannelInfo->type); + ChannelValueInit(src, ChannelTypeClone(srcChannelInfo->type)); retVal = ChannelValueSet(src, srcCompConst->GetValue(srcCompConst, info->sourceChannel)); if (retVal == RETURN_ERROR) { goto cleanup_1; diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index b54717f..dcfa340 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -82,7 +82,7 @@ McxStatus ChannelInfoSetType(ChannelInfo * info, ChannelType * type) { return RETURN_ERROR; } - info->type = type; + info->type = ChannelTypeClone(type); if (ChannelInfoIsBinary(info)) { // the default for binary is off @@ -168,7 +168,7 @@ McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other) { return RETURN_ERROR; } - info->type = other->type; + info->type = ChannelTypeClone(other->type); info->mode = other->mode; info->writeResult = other->writeResult; info->connected = other->connected; @@ -265,7 +265,7 @@ void ChannelInfoDestroy(ChannelInfo * info) { info->channel = NULL; info->initialValueIsExact = FALSE; - info->type = &ChannelTypeUnknown; + info->type = ChannelTypeClone(&ChannelTypeUnknown); info->connected = FALSE; info->writeResult = TRUE; } @@ -288,7 +288,7 @@ McxStatus ChannelInfoInit(ChannelInfo * info) { info->scale = NULL; info->offset = NULL; - info->type = &ChannelTypeUnknown; + info->type = ChannelTypeClone(&ChannelTypeUnknown); info->defaultValue = NULL; info->initialValue = NULL; diff --git a/src/core/connections/filters/MemoryFilter.c b/src/core/connections/filters/MemoryFilter.c index d37e8c9..ac14fa0 100644 --- a/src/core/connections/filters/MemoryFilter.c +++ b/src/core/connections/filters/MemoryFilter.c @@ -241,11 +241,11 @@ static McxStatus MemoryFilterSetup(MemoryFilter * filter, ChannelType * type, si } for (i = 0; i < filter->historySize; i++) { - ChannelValueInit(filter->valueHistoryRead + i, type); + ChannelValueInit(filter->valueHistoryRead + i, ChannelTypeClone(type)); } for (i = 0; i < filter->historySize; i++) { - ChannelValueInit(filter->valueHistoryWrite + i, type); + ChannelValueInit(filter->valueHistoryWrite + i, ChannelTypeClone(type)); } return RETURN_OK; From 92567b756c83edb09d561b40568cbc676e3c93f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:14:25 +0200 Subject: [PATCH 172/295] Fix ChannelInfo --- src/core/channels/ChannelDimension.c | 36 ++++++++++++++++++++++++++++ src/core/channels/ChannelDimension.h | 1 + src/core/channels/ChannelInfo.c | 9 +++++++ 3 files changed, 46 insertions(+) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 7a01564..6b97627 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -76,6 +76,42 @@ size_t ChannelDimensionNumElements(ChannelDimension * dimension) { return n; } +ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension) { + ChannelDimension * clone = NULL; + McxStatus retVal = RETURN_OK; + size_t i = 0; + + if (!dimension) { + return NULL; + } + + clone = (ChannelDimension *) object_create(ChannelDimension); + if (!clone) { + mcx_log(LOG_ERROR, "ChannelDimensionClone: Not enough memory"); + return NULL; + } + + retVal = ChannelDimensionSetup(clone, dimension->num); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Channel dimension setup failed"); + goto cleanup; + } + + for (i = 0; i < dimension->num; i++) { + retVal = ChannelDimensionSetDimension(clone, i, dimension->startIdxs[i], dimension->endIdxs[i]); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Channel dimension %zu set failed", i); + goto cleanup; + } + } + + return clone; + +cleanup: + object_destroy(clone); + return NULL; +} + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index d107edf..2e361eb 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -30,6 +30,7 @@ typedef struct ChannelDimension { McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); +ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); size_t ChannelDimensionNumElements(ChannelDimension * dimension); #ifdef __cplusplus diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index dcfa340..b88b83c 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -231,6 +231,15 @@ McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other) { } } + object_destroy(info->dimension); + if (other->dimension) { + info->dimension = ChannelDimensionClone(other->dimension); + if (!info->dimension) { + mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set dimension"); + return RETURN_ERROR; + } + } + return RETURN_OK; } From 1dd1f5cf9d0b11bab09095f67b94f60c7a4611c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:16:29 +0200 Subject: [PATCH 173/295] Fix Constant::GetValue --- src/components/comp_constant.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/comp_constant.c b/src/components/comp_constant.c index b670cd8..57556fb 100644 --- a/src/components/comp_constant.c +++ b/src/components/comp_constant.c @@ -57,19 +57,14 @@ static ChannelValue * GetValue(CompConstant * compConstant, size_t idx) { Component * comp = (Component *) (compConstant); Databus * db = comp->GetDatabus(comp); size_t numOut = DatabusGetOutChannelsNum(db); - size_t i = 0; - size_t sum = 0; ChannelValue * value = NULL; - size_t numCh = 0; - size_t startIdx = 0; - size_t endIdx = 0; - if (i >= numOut) { + if (idx >= numOut) { ComponentLog(comp, LOG_ERROR, "GetValue: Invalid index (%zu) provided", idx); return NULL; } - value = compConstant->values[i]; + value = compConstant->values[idx]; return value; } From dce9d34ce50a001c160a88220608df421b698609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 13 May 2022 11:21:53 +0200 Subject: [PATCH 174/295] Fix ConnectionInfo construction --- src/core/connections/ConnectionInfoFactory.c | 61 ++++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 0db5751..344d6a9 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -115,28 +115,6 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, } // TODO: multiplexing here? - if (connInput->fromType == ENDPOINT_VECTOR) { - ChannelDimension * sourceDimension = (ChannelDimension *) object_create(ChannelDimension); - if (!sourceDimension) { - retVal = RETURN_ERROR; - goto cleanup; - } - - if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { - mcx_log(LOG_ERROR, "Could not setup ChannelDimension"); - retVal = RETURN_ERROR; - goto cleanup; - } - - if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, (size_t) connInput->from.vectorEndpoint->startIndex, (size_t) connInput->from.vectorEndpoint->endIndex)) { - mcx_log(LOG_ERROR, "Could not SetDimension"); - retVal = RETURN_ERROR; - goto cleanup; - } - - info->sourceDimension = sourceDimension; - } - 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) @@ -168,15 +146,6 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, goto cleanup; } - if (connInput->toType == ENDPOINT_VECTOR) { - mcx_free(strToChannel); - strToChannel = CreateIndexedName(inputToChannel, connInput->to.vectorEndpoint->startIndex); - if (!strToChannel) { - retVal = RETURN_ERROR; - goto cleanup; - } - } - if (0 == connectionInverted) { databusInfo = DatabusGetInInfo(databus); } else { @@ -212,6 +181,36 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->targetComponent->GetName(info->targetComponent), strFromChannel, info->sourceComponent->GetName(info->sourceComponent), strToChannel); } + // source dimension + { + EndpointInputType endpointType = connectionInverted ? connInput->toType : connInput->fromType; + + if (endpointType == ENDPOINT_VECTOR) { + size_t startIndex = (size_t) (connectionInverted ? connInput->to.vectorEndpoint->startIndex : connInput->from.vectorEndpoint->startIndex); + size_t endIndex = (size_t)(connectionInverted ? connInput->to.vectorEndpoint->endIndex : connInput->from.vectorEndpoint->endIndex); + + ChannelDimension* sourceDimension = (ChannelDimension*)object_create(ChannelDimension); + if (!sourceDimension) { + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { + mcx_log(LOG_ERROR, "Could not setup ChannelDimension"); + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, startIndex, endIndex)) { + mcx_log(LOG_ERROR, "Could not SetDimension"); + retVal = RETURN_ERROR; + goto cleanup; + } + + info->sourceDimension = sourceDimension; + } + } + // extrapolation if (connInput->interExtrapolationType.defined) { info->interExtrapolationType = connInput->interExtrapolationType.value; From a70a831446899464b519a7e340cec34784fadb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 18 Oct 2021 10:05:22 +0200 Subject: [PATCH 175/295] Extend ConnectionInfo with slice information --- src/core/channels/ChannelDimension.h | 1 + src/core/connections/ConnectionInfo.c | 1 + src/core/connections/ConnectionInfo.h | 1 + src/core/connections/ConnectionInfoFactory.c | 55 +++++++++++++++++++- src/core/connections/ConnectionInfo_impl.h | 1 + 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 2e361eb..9fd8909 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -32,6 +32,7 @@ McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); size_t ChannelDimensionNumElements(ChannelDimension * dimension); +ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index 1675ae6..eec8b3b 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -161,6 +161,7 @@ McxStatus ConnectionInfoInit(ConnectionInfo * info) { info->connType_ = &ChannelTypeUnknown; info->sourceDimension = NULL; + info->targetDimension = NULL; return RETURN_OK; } diff --git a/src/core/connections/ConnectionInfo.h b/src/core/connections/ConnectionInfo.h index 8c18150..8d9a171 100644 --- a/src/core/connections/ConnectionInfo.h +++ b/src/core/connections/ConnectionInfo.h @@ -50,6 +50,7 @@ typedef struct ConnectionInfo { int decouplePriority; ChannelDimension * sourceDimension; + ChannelDimension * targetDimension; } ConnectionInfo; diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 344d6a9..4c1c23e 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -114,7 +114,29 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, goto cleanup; } - // TODO: multiplexing here? + // arrays/multiplexing: source slice dimensions + if (connInput->fromType == ENDPOINT_VECTOR) { + ChannelDimension* sourceDimension = (ChannelDimension*)object_create(ChannelDimension); + if (!sourceDimension) { + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { + mcx_log(LOG_ERROR, "Source port %s: Could not set number of dimensions", strFromChannel); + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, connInput->from.vectorEndpoint->startIndex, connInput->from.vectorEndpoint->endIndex)) { + mcx_log(LOG_ERROR, "Source port %s: Could not set dimension boundaries", strFromChannel); + retVal = RETURN_ERROR; + goto cleanup; + } + + info->sourceDimension = sourceDimension; + } + 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) @@ -152,6 +174,33 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, databusInfo = DatabusGetOutInfo(databus); } + // arrays/multiplexing: target slice dimensions + if (connInput->toType == ENDPOINT_VECTOR) { + ChannelDimension * targetDimension = (ChannelDimension *) object_create(ChannelDimension); + if (!targetDimension) { + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetup(targetDimension, 1)) { + mcx_log(LOG_ERROR, "Target port %s: Could not set number of dimensions", strToChannel); + retVal = RETURN_ERROR; + goto cleanup; + } + + if (RETURN_OK != ChannelDimensionSetDimension(targetDimension, + 0, + (size_t) connInput->to.vectorEndpoint->startIndex, + (size_t) connInput->to.vectorEndpoint->endIndex)) + { + mcx_log(LOG_ERROR, "Target port %s: Could not set dimension boundaries", strToChannel); + retVal = RETURN_ERROR; + goto cleanup; + } + + info->targetDimension = targetDimension; + } + info->targetChannel = DatabusInfoGetChannelID(databusInfo, strToChannel); if (info->targetChannel < 0) { if (0 == connectionInverted) { @@ -170,6 +219,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, if (connectionInverted) { int tmp = info->sourceChannel; Component * tmpCmp = info->sourceComponent; + ChannelDimension * tmpDim = info->sourceDimension; info->sourceChannel = info->targetChannel; info->targetChannel = tmp; @@ -177,6 +227,9 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->sourceComponent = info->targetComponent; info->targetComponent = tmpCmp; + info->sourceDimension = info->targetDimension; + info->targetDimension = tmpDim; + mcx_log(LOG_DEBUG, "Connection: Inverted connection (%s, %s) -- (%s, %s)", info->targetComponent->GetName(info->targetComponent), strFromChannel, info->sourceComponent->GetName(info->sourceComponent), strToChannel); } diff --git a/src/core/connections/ConnectionInfo_impl.h b/src/core/connections/ConnectionInfo_impl.h index bd7bc91..455b13a 100644 --- a/src/core/connections/ConnectionInfo_impl.h +++ b/src/core/connections/ConnectionInfo_impl.h @@ -42,6 +42,7 @@ typedef struct ConnectionInfoData { int targetChannel; ChannelDimension * sourceDimension; + ChannelDimension * targetDimension; // 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 From 3899951fbcc49a93fdaf601813345fe3547c893f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 18 Oct 2021 13:20:45 +0200 Subject: [PATCH 176/295] Do not fill internalValue as it is not used anywhere --- src/core/channels/Channel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index a42b980..1d816b7 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -323,7 +323,6 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, McxStatus retVal; in->data->connection = connection; - channel->internalValue = connection->GetValueReference(connection); // setup unit conversion inInfo = &channel->info; @@ -388,7 +387,6 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { } channel->SetDefinedDuringInit(channel); - channel->internalValue = ChannelValueReference(&channel->value); } // unit conversion is setup when a connection is set From 8079f30ac40abd9e11b817fd7e5964d84037b69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 29 Oct 2021 13:41:09 +0200 Subject: [PATCH 177/295] Allow registering multiple connections with the same ChannelIn --- src/core/Component.c | 8 +- src/core/Component.h | 4 +- src/core/SubModel.c | 60 +++++++--- src/core/channels/Channel.c | 128 ++++++++++++++++------ src/core/channels/Channel.h | 15 +-- src/core/channels/ChannelDimension.c | 22 ++++ src/core/channels/ChannelDimension.h | 1 + src/core/channels/ChannelValueReference.c | 48 ++++++++ src/core/channels/ChannelValueReference.h | 54 +++++++++ src/core/channels/Channel_impl.h | 4 +- src/core/connections/Connection.c | 2 +- 11 files changed, 280 insertions(+), 66 deletions(-) create mode 100644 src/core/channels/ChannelValueReference.c create mode 100644 src/core/channels/ChannelValueReference.h diff --git a/src/core/Component.c b/src/core/Component.c index 5bab659..93b8193 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -840,22 +840,22 @@ static void ComponentSetModel(Component * comp, Model * model) { comp->data->model = model; } -ConnectionInfo * GetInConnectionInfo(const Component * comp, size_t channelID) { +ObjectContainer * GetInConnectionInfos(const Component * comp, size_t channelID) { size_t channelNum = DatabusInfoGetChannelNum(DatabusGetInInfo(comp->data->databus)); if (channelID < channelNum) { ChannelIn * in = DatabusGetInChannel(comp->data->databus, channelID); - return in->GetConnectionInfo(in); + return in->GetConnectionInfos(in); } return NULL; } -Connection * GetInConnection(const Component * comp, size_t channelID) { +ObjectContainer * GetInConnections(const Component * comp, size_t channelID) { size_t channelNum = DatabusInfoGetChannelNum(DatabusGetInInfo(comp->data->databus)); if (channelID < channelNum) { ChannelIn * in = DatabusGetInChannel(comp->data->databus, channelID); - return in->GetConnection(in); + return in->GetConnections(in); } return NULL; diff --git a/src/core/Component.h b/src/core/Component.h index 9d6f1cc..8abede0 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -250,8 +250,8 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, struct St McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time); McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time); -ConnectionInfo * GetInConnectionInfo(const Component * comp, size_t channelID); -struct Connection * GetInConnection(const Component * comp, size_t channelID); +struct ObjectContainer * GetInConnectionInfos(const Component * comp, size_t channelID); +struct ObjectContainer * GetInConnections(const Component * comp, size_t channelID); size_t ComponentGetNumOutGroups(const Component * comp); size_t ComponentGetNumInitialOutGroups(const Component * comp); diff --git a/src/core/SubModel.c b/src/core/SubModel.c index 87feb06..eeb36ce 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -689,27 +689,59 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen // initial inputs are always exact if (info->initialValue) { //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 (ConnectionInfoIsDecoupled(info)) {//decoupled connection + ObjectContainer * infos = GetInConnectionInfos(targetComp, targetInChannelID); + size_t numInfos = infos->Size(infos); + size_t i = 0; + + if (numInfos == 0) { // no connections + dependency = DEP_INDEPENDENT; + } else { + int allDecoupled = TRUE; + for (i = 0; i < numInfos; i++) { + ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, i); + if (!ConnectionInfoIsDecoupled(info)) { + allDecoupled = FALSE; + } + } + + if (allDecoupled) { // decoupled connections dependency = DEP_INDEPENDENT; } - } else {//no connection - dependency = DEP_INDEPENDENT; } } } if (DEP_INDEPENDENT != dependency) { - ConnectionInfo * info = GetInConnectionInfo(targetComp, targetInChannelID); - Connection * conn = GetInConnection(targetComp, targetInChannelID); - - if (info - && (info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED)) - && (!ConnectionInfoIsDecoupled(info)) - && conn - && conn->IsActiveDependency(conn)) - { + ObjectContainer * infos = GetInConnectionInfos(targetComp, targetInChannelID); + ObjectContainer * conns = GetInConnections(targetComp, targetInChannelID); + size_t numInfos = infos->Size(infos); + size_t numConns = conns->Size(conns); + size_t i = 0; + + int isDecoupled = TRUE; + size_t decoupleType = (size_t) -1; + int isActiveDependency = FALSE; + + for (i = 0; i < numInfos; i++) { + ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, i); + if (!ConnectionInfoIsDecoupled(info)) { + isDecoupled = FALSE; + } + + decoupleType &= info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED); + } + + for (i = 0; i < numConns; i++) { + Connection * conn = (Connection *) conns->At(conns, i); + if (conn->IsActiveDependency(conn)) { + isActiveDependency = TRUE; + break; + } + } + + if (numInfos > 0 && decoupleType && !isDecoupled && numConns > 0 && isActiveDependency) { + ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, 0); + Component * sourceComp = info->sourceComponent; size_t sourceOutGroup, sourceNode; Databus * db = targetComp->GetDatabus(targetComp); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 1d816b7..4ef43f3 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -15,6 +15,7 @@ #include "core/Conversion.h" #include "core/channels/ChannelInfo.h" +#include "core/channels/ChannelValueReference.h" #include "core/channels/Channel.h" #include "core/channels/ChannelValue.h" #include "core/channels/Channel_impl.h" @@ -85,7 +86,16 @@ static Channel * ChannelCreate(Channel * channel) { static ChannelInData * ChannelInDataCreate(ChannelInData * data) { - data->connection = NULL; + data->connections = (ObjectContainer *) object_create(ObjectContainer); + if (!data->connections) { + return NULL; + } + + data->valueReferences = (ObjectContainer *) object_create(ObjectContainer); + if (!data->valueReferences) { + return NULL; + } + data->reference = NULL; data->type = ChannelTypeClone(&ChannelTypeUnknown); @@ -115,6 +125,8 @@ static void ChannelInDataDestructor(ChannelInData * data) { if (data->type) { ChannelTypeDestructor(data->type); } + + // TODO destroy connections/valueReference ???? } OBJECT_CLASS(ChannelInData, Object); @@ -177,34 +189,37 @@ static const void * ChannelInGetValueReference(Channel * channel) { static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ChannelIn * in = (ChannelIn *) channel; ChannelInfo * info = &channel->info; - Connection * conn = in->data->connection; McxStatus retVal = RETURN_OK; /* if no connection is present we have nothing to update*/ - if (conn) { - ConnectionInfo * connInfo = NULL; - ChannelValue * val = &channel->value; - - connInfo = &conn->info; + size_t i = 0; + size_t numConns = in->data->connections->Size(in->data->connections); + for (i = 0; i < numConns; i++) { + Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); + ChannelValueRef * valueRef = (ChannelValueRef *) in->data->valueReferences->At(in->data->valueReferences, i); + ConnectionInfo * connInfo = &conn->info; + char * connString = ConnectionInfoConnectionString(connInfo); - ChannelValueDestructor(val); - ChannelValueInit(val, ChannelTypeClone(ConnectionInfoGetType(connInfo))); + // TODO do we need this Init ??? + /*ChannelValueDestructor(val); + ChannelValueInit(val, ChannelTypeClone(connInfo->GetType(connInfo)));*/ /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { - mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection failed", ChannelInfoGetLogName(info)); + mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection %s failed", ChannelInfoGetLogName(info), connString); return RETURN_ERROR; } - if (RETURN_OK != ChannelValueSetFromReference(val, conn->GetValueReference(conn))) { - mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueSetFromReference failed", ChannelInfoGetLogName(info)); + if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn))) { // TODO conn->GetValueReference - let it maybe return our reference + mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueRefSetFromReference for connection %s failed", ChannelInfoGetLogName(info), connString); return RETURN_ERROR; } - //type + // type + // TODO per connection if (in->data->typeConversion) { Conversion * conversion = (Conversion *) in->data->typeConversion; - retVal = conversion->convert(conversion, val); + retVal = conversion->convert(conversion, valueRef->ref.value); // TODO convert valueRef directly if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute type conversion", ChannelInfoGetLogName(info)); return RETURN_ERROR; @@ -292,7 +307,7 @@ static int ChannelInIsConnected(Channel * channel) { return TRUE; } else { ChannelIn * in = (ChannelIn *) channel; - if (NULL != in->data->connection) { + if (in->data->connections->Size(in->data->connections) > 0) { return TRUE; } } @@ -300,32 +315,68 @@ static int ChannelInIsConnected(Channel * channel) { return FALSE; } -static ConnectionInfo * ChannelInGetConnectionInfo(ChannelIn * in) { - if (in->data->connection) { - return &in->data->connection->info; - } else { +static ObjectContainer * ChannelInGetConnectionInfos(ChannelIn * in) { + ObjectContainer * infos = (ObjectContainer *) object_create(ObjectContainer); + size_t numConns = in->data->connections->Size(in->data->connections); + size_t i = 0; + + if (!infos) { return NULL; } -} -static Connection * ChannelInGetConnection(ChannelIn * in) { - if (in->data->connection) { - return in->data->connection; - } else { - return NULL; + for (i = 0; i < numConns; i++) { + Connection * conn = in->data->connections->At(in->data->connections, i); + ConnectionInfo * connInfo = &conn->info; + if (RETURN_ERROR == infos->PushBack(infos, (Object *) connInfo)) { + object_destroy(infos); + return NULL; + } } + + return infos; +} + +static ObjectContainer * ChannelInGetConnections(ChannelIn * in) { + return in->data->connections; } -static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType * type) { +static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType * type) { + ConnectionInfo * connInfo = &connection->info; + char * connString = ConnectionInfoConnectionString(connInfo); Channel * channel = (Channel *) in; - ChannelInfo * inInfo = NULL; + ChannelInfo * inInfo = &channel->info; - McxStatus retVal; + McxStatus retVal = RETURN_OK; - in->data->connection = connection; + retVal = in->data->connections->PushBack(in->data->connections, (Object *) connection); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Port %s: Register inport connection %s: Could not register connection", ChannelInfoGetLogName(inInfo), connString); + mcx_free(connString); + return RETURN_ERROR; + } - // setup unit conversion - inInfo = &channel->info; + // TODO setup valueReference + ChannelValueRef * valRef = (ChannelValueRef *) object_create(ChannelValueRef); + if (!valRef) { + return RETURN_ERROR; + } + + ChannelDimension * dimension = connInfo->targetDimension; + // TODO check ret values + // TODO do we need some plausibility checks? + // TODO is it fine to use connInfo here? + if (dimension && !ChannelDimensionEq(dimension, inInfo->dimension)) { + valRef->type = CHANNEL_VALUE_REF_SLICE; + valRef->ref.slice = (ArraySlice *) mcx_calloc(1, sizeof(ArraySlice)); + valRef->ref.slice->ref = &channel->value; + valRef->ref.slice->dimension = ChannelDimensionClone(dimension); + } else { + valRef->type = CHANNEL_VALUE_REF_VALUE; + valRef->ref.value = &channel->value; + } + + retVal = in->data->valueReferences->PushBack(in->data->valueReferences, (Object *) valRef); + // TODO check retVal if (ChannelTypeEq(inInfo->type, &ChannelTypeDouble)) { in->data->unitConversion = (UnitConversion *) object_create(UnitConversion); @@ -342,6 +393,7 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, } } + // TODO - array // setup type conversion if (!ChannelTypeEq(inInfo->type, type)) { in->data->typeConversion = (TypeConversion *) object_create(TypeConversion); @@ -354,8 +406,14 @@ static McxStatus ChannelInSetConnection(ChannelIn * in, Connection * connection, } } - return RETURN_OK; +cleanup: + if (RETURN_ERROR == retVal) { + if (connString) { + mcx_free(connString); + } + } + return retVal; } static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { @@ -450,10 +508,10 @@ static ChannelIn * ChannelInCreate(ChannelIn * in) { in->Setup = ChannelInSetup; in->SetReference = ChannelInSetReference; - in->GetConnectionInfo = ChannelInGetConnectionInfo; + in->GetConnectionInfos = ChannelInGetConnectionInfos; - in->GetConnection = ChannelInGetConnection; - in->SetConnection = ChannelInSetConnection; + in->GetConnections = ChannelInGetConnections; + in->RegisterConnection = ChannelInRegisterConnection; in->IsDiscrete = ChannelInIsDiscrete; in->SetDiscrete = ChannelInSetDiscrete; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index e022dfb..7dae1cb 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -115,14 +115,11 @@ typedef McxStatus (* fChannelInSetReference) (ChannelIn * in, void * reference, ChannelType * type); -typedef struct ConnectionInfo * (* fChannelInGetConnectionInfo)(ChannelIn * in); +typedef struct ObjectContainer * (* fChannelInGetConnectionInfos)(ChannelIn * in); -typedef struct Connection * (* fChannelInGetConnection)(ChannelIn * in); +typedef struct ObjectContainer * (* fChannelInGetConnections)(ChannelIn * in); -typedef McxStatus (* fChannelInSetConnection)(ChannelIn * in, - struct Connection * connection, - const char * unit, - ChannelType * type); +typedef McxStatus (*fChannelInRegisterConnection)(ChannelIn * in, struct Connection * connection, const char * unit, ChannelType * type); typedef int (*fChannelInIsDiscrete)(ChannelIn * in); typedef void (*fChannelInSetDiscrete)(ChannelIn * in); @@ -150,15 +147,15 @@ struct ChannelIn { /** * Returns the ConnectionInfo of the incoming connection. */ - fChannelInGetConnectionInfo GetConnectionInfo; + fChannelInGetConnectionInfos GetConnectionInfos; - fChannelInGetConnection GetConnection; + fChannelInGetConnections GetConnections; /** * Set the connection from which the channel retrieves the values in the * specified unit. */ - fChannelInSetConnection SetConnection; + fChannelInRegisterConnection RegisterConnection; /** * Returns true if a channel value is discrete diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 6b97627..ea3965e 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -112,6 +112,28 @@ ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension) { return NULL; } +int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second) { + size_t i = 0; + + if (!first && !second) { + return TRUE; + } else if (!first || !second) { + return FALSE; + } + + if (first->num != second->num) { + return FALSE; + } + + for (i = 0; i < first->num; i++) { + if (first->startIdxs[i] != second->startIdxs[i] || first->endIdxs[i] != second->endIdxs[i]) { + return FALSE; + } + } + + return TRUE; +} + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 9fd8909..f654c3e 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -33,6 +33,7 @@ McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); size_t ChannelDimensionNumElements(ChannelDimension * dimension); ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); +int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c new file mode 100644 index 0000000..974d8ec --- /dev/null +++ b/src/core/channels/ChannelValueReference.c @@ -0,0 +1,48 @@ +/******************************************************************************** + * Copyright (c) 2021 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/channels/ChannelValueReference.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +void ChannelValueRefDestructor(ChannelValueRef * ref) { + // TODO ??? +} + +ChannelValueRef * ChannelValueRefCreate(ChannelValueRef * ref) { + ref->type = CHANNEL_VALUE_REF_VALUE; + ref->ref.value = NULL; + + return ref; +} + +OBJECT_CLASS(ChannelValueRef, Object); + + +McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference) { + if (ref->type == CHANNEL_VALUE_REF_VALUE) { + // value + return ChannelValueDataSetFromReference(&ref->ref.value->value, ref->ref.value->type, reference); + } else { + // slice + + // TODO + } + + return RETURN_OK; +} + + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h new file mode 100644 index 0000000..13ab9e5 --- /dev/null +++ b/src/core/channels/ChannelValueReference.h @@ -0,0 +1,54 @@ +/******************************************************************************** + * Copyright (c) 2021 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_CHANNELS_CHANNEL_VALUE_REFERENCE_H +#define MCX_CORE_CHANNELS_CHANNEL_VALUE_REFERENCE_H + +#include "CentralParts.h" +#include "core/channels/ChannelDimension.h" + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +typedef struct ArraySlice { + ChannelDimension * dimension; + ChannelValue * ref; +} ArraySlice; + +typedef enum ChannelValueRefType { + CHANNEL_VALUE_REF_VALUE, + CHANNEL_VALUE_REF_SLICE +} ChannelValueRefType; + + +extern const struct ObjectClass _ChannelValueRef; + +typedef struct ChannelValueRef { + Object * _; + + ChannelValueRefType type; + union { + ChannelValue * value; + ArraySlice * slice; + } ref; +} ChannelValueRef; + + +McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference); + + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif /* __cplusplus */ + +#endif // MCX_CORE_CHANNELS_CHANNEL_VALUE_REFERENCE_H \ No newline at end of file diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index 8708cc6..16d8d45 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -28,7 +28,9 @@ extern "C" { typedef struct ChannelInData { Object _; // base class - struct Connection * connection; + ObjectContainer * connections; // connections (non-overlapping) going into the channel + ObjectContainer * valueReferences; // references to non-overlapping parts of ChannelData::value, where + // values gotten from connections are going to be stored // ---------------------------------------------------------------------- // Conversions diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 0ac45af..8923fc1 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1345,7 +1345,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * return RETURN_ERROR; } - retVal = in->SetConnection(in, connection, outInfo->unitString, outInfo->type); + retVal = in->RegisterConnection(in, connection, outInfo->unitString, outInfo->type); if (RETURN_OK != retVal) { char * buffer = ConnectionInfoConnectionString(info); mcx_log(LOG_ERROR, "Connection %s: Setup connection: Could not register with inport", buffer); From 497b74391106531eed459b95caf5b36b4390ba5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 3 Nov 2021 08:37:28 +0100 Subject: [PATCH 178/295] Modify type conversions to work with destination/source arguments Reason: Avoid memory allocation in ChannelInUpdate that would happen due to ChannelValueInit allocating memory for array data of an array channel --- src/core/Conversion.c | 119 ++++++++++------------ src/core/Conversion.h | 12 ++- src/core/channels/Channel.c | 26 +++-- src/core/channels/ChannelValueReference.c | 21 +++- src/core/channels/ChannelValueReference.h | 6 +- 5 files changed, 94 insertions(+), 90 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 942af6f..f3191d0 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -10,6 +10,7 @@ #include "CentralParts.h" #include "core/Conversion.h" +#include "core/channels/ChannelValueReference.h" #include "units/Units.h" #ifdef __cplusplus @@ -545,122 +546,114 @@ McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue return retVal; } -static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeInteger)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeInteger)); +static McxStatus CheckTypesValidForConversion(ChannelType * destType, + ChannelType * expectedDestType) +{ + if (!ChannelTypeEq(destType, expectedDestType)) { + mcx_log(LOG_ERROR, + "Type conversion: Destination value has wrong type %s, expected: %s", + ChannelTypeToString(ChannelValueType(destType)), + ChannelTypeToString(expectedDestType)); return RETURN_ERROR; } - value->type = &ChannelTypeDouble; - value->value.d = (double)value->value.i; - return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeDouble)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeDouble)); +static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } - value->type = &ChannelTypeInteger; - value->value.i = (int)floor(value->value.d + 0.5); + dest->ref.value->value.d = (double) *((int *) src); return RETURN_OK; } -static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeBool)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeBool)); +static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } - value->type = &ChannelTypeDouble; - value->value.d = (value->value.i != 0) ? 1. : 0.; + dest->ref.value->value.i = (int) floor(*((double *) src) + 0.5); return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeDouble)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeDouble)); +static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } - value->type = &ChannelTypeBool; - value->value.i = (value->value.d > 0) ? 1 : 0; + dest->ref.value->value.d = *((int *) src) != 0 ? 1. : 0.; return RETURN_OK; } -static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeBool)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeBool)); +static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } - value->type = &ChannelTypeInteger; - value->value.i = (value->value.i != 0) ? 1 : 0; + dest->ref.value->value.i = *((double *) src) > 0 ? 1 : 0; return RETURN_OK; } -static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, ChannelValue * value) { - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeInteger)) { - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeInteger)); +static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } - value->type = &ChannelTypeBool; - value->value.i = (value->value.i != 0) ? 1 : 0; + dest->ref.value->value.i = *((int *) src) != 0 ? 1 : 0; return RETURN_OK; } -static McxStatus TypeConversionConvertSingletonDoubleToDouble(Conversion * conversion, ChannelValue * value) { - if (!(ChannelTypeIsArray(ChannelValueType(value)) && value->value.a.type, &ChannelTypeDouble)) { - ChannelType * array = ChannelTypeArray(&ChannelTypeDouble, 0, NULL); - mcx_log(LOG_ERROR, "Type conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), array); - ChannelTypeDestructor(array); +static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } - double val = *(double *)value->value.a.data; + dest->ref.value->value.i = *((int *) src) != 0 ? 1 : 0; + + return RETURN_OK; +} - ChannelValueDataDestructor(&value->value, value->type); - ChannelTypeDestructor(value->type); - value->type = &ChannelTypeDouble; +static McxStatus TypeConversionConvertSingletonDoubleToDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { + return RETURN_ERROR; + } - value->value.d = val; + dest->ref.value->value.d = *(double *) ((mcx_array*)src)->data; return RETURN_OK; } -static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValue * value) { - return RETURN_OK; +static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValueRef * dest, void * src) { + return ChannelValueRefSetFromReference(dest, src, NULL); } -static McxStatus TypeConversionSetup(TypeConversion * typeConversion, +static McxStatus TypeConversionSetup(TypeConversion * conversion, ChannelType * fromType, ChannelType * toType) { - Conversion * conversion = (Conversion *) typeConversion; if (ChannelTypeEq(fromType, toType)) { - conversion->convert = TypeConversionConvertId; + conversion->Convert = TypeConversionConvertId; } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeDouble)) { - conversion->convert = TypeConversionConvertIntDouble; + conversion->Convert = TypeConversionConvertIntDouble; } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeInteger)) { - conversion->convert = TypeConversionConvertDoubleInt; + conversion->Convert = TypeConversionConvertDoubleInt; } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeDouble)) { - conversion->convert = TypeConversionConvertBoolDouble; + conversion->Convert = TypeConversionConvertBoolDouble; } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeBool)) { - conversion->convert = TypeConversionConvertDoubleBool; + conversion->Convert = TypeConversionConvertDoubleBool; } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeInteger)) { - conversion->convert = TypeConversionConvertBoolInteger; + conversion->Convert = TypeConversionConvertBoolInteger; } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeBool)) { - conversion->convert = TypeConversionConvertIntegerBool; + conversion->Convert = TypeConversionConvertIntegerBool; } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeDouble)) { - conversion->convert = TypeConversionConvertSingletonDoubleToDouble; + conversion->Convert = TypeConversionConvertSingletonDoubleToDouble; } else { mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion selected"); return RETURN_ERROR; @@ -669,28 +662,18 @@ static McxStatus TypeConversionSetup(TypeConversion * typeConversion, return RETURN_OK; } -static int TypeConversionIsEmpty(TypeConversion * typeConversion) { - Conversion * conversion = (Conversion *) typeConversion; - - return (conversion->convert == TypeConversionConvertId); -} - static void TypeConversionDestructor(TypeConversion * conversion) { } -static TypeConversion * TypeConversionCreate(TypeConversion * typeConversion) { - Conversion * conversion = (Conversion *) typeConversion; +static TypeConversion * TypeConversionCreate(TypeConversion * conversion) { + conversion->Setup = TypeConversionSetup; + conversion->Convert = NULL; - conversion->convert = TypeConversionConvertId; - - typeConversion->Setup = TypeConversionSetup; - typeConversion->IsEmpty = TypeConversionIsEmpty; - - return typeConversion; + return conversion; } -OBJECT_CLASS(TypeConversion, Conversion); +OBJECT_CLASS(TypeConversion, Object); #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/Conversion.h b/src/core/Conversion.h index 90ab771..22cf68e 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -13,6 +13,7 @@ #include "units/Units.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -112,18 +113,21 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal // ---------------------------------------------------------------------- // Type Conversion +typedef struct ChannelValueRef ChannelValueRef; + + typedef struct TypeConversion TypeConversion; -typedef McxStatus (* fTypeConversionSetup)(TypeConversion * conversion, ChannelType * fromType, ChannelType * toType); -typedef int (* fTypeConversionIsEmpty)(TypeConversion * conversion); +typedef McxStatus (*fTypeConversionSetup)(TypeConversion * conversion, const ChannelType * fromType, const ChannelType * toType); +typedef McxStatus (*fTypeConversionConvert)(TypeConversion * conversion, ChannelValueRef * dest, void * src); extern const struct ObjectClass _TypeConversion; struct TypeConversion { - Conversion _; + Object _; fTypeConversionSetup Setup; - fTypeConversionIsEmpty IsEmpty; + fTypeConversionConvert Convert; }; McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue * value); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 4ef43f3..6e756cc 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -210,21 +210,21 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection %s failed", ChannelInfoGetLogName(info), connString); return RETURN_ERROR; } - if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn))) { // TODO conn->GetValueReference - let it maybe return our reference + if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), in->data->typeConversion)) { // TODO conn->GetValueReference - let it maybe return our reference mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueRefSetFromReference for connection %s failed", ChannelInfoGetLogName(info), connString); return RETURN_ERROR; } - // type - // TODO per connection - if (in->data->typeConversion) { - Conversion * conversion = (Conversion *) in->data->typeConversion; - retVal = conversion->convert(conversion, valueRef->ref.value); // TODO convert valueRef directly - if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute type conversion", ChannelInfoGetLogName(info)); - return RETURN_ERROR; - } - } + //// type + //// TODO per connection + //if (in->data->typeConversion) { + // Conversion * conversion = (Conversion *) in->data->typeConversion; + // retVal = conversion->convert(conversion, valueRef->ref.value); // TODO convert valueRef directly + // if (RETURN_OK != retVal) { + // mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute type conversion", info->GetLogName(info)); + // return RETURN_ERROR; + // } + //} } @@ -397,9 +397,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec // setup type conversion if (!ChannelTypeEq(inInfo->type, type)) { in->data->typeConversion = (TypeConversion *) object_create(TypeConversion); - retVal = in->data->typeConversion->Setup(in->data->typeConversion, - type, - inInfo->type); + retVal = in->data->typeConversion->Setup(in->data->typeConversion, type, inInfo->type); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Port %s: Set connection: Could not setup type conversion", ChannelInfoGetLogName(inInfo)); return RETURN_ERROR; diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 974d8ec..e97dff5 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -9,6 +9,7 @@ ********************************************************************************/ #include "core/channels/ChannelValueReference.h" +#include "common/logging.h" #ifdef __cplusplus extern "C" { @@ -29,9 +30,12 @@ ChannelValueRef * ChannelValueRefCreate(ChannelValueRef * ref) { OBJECT_CLASS(ChannelValueRef, Object); -McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference) { +McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, TypeConversion * conv) { if (ref->type == CHANNEL_VALUE_REF_VALUE) { - // value + if (conv) { + return conv->Convert(conv, ref, reference); + } + return ChannelValueDataSetFromReference(&ref->ref.value->value, ref->ref.value->type, reference); } else { // slice @@ -42,6 +46,19 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re return RETURN_OK; } +ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { + switch (ref->type) { + case CHANNEL_VALUE_REF_VALUE: + return ChannelValueType(ref->ref.value); + case CHANNEL_VALUE_REF_SLICE: + mcx_log(LOG_ERROR, "TODO - change the dimension in ArraySlice to a type and return that to avoid memory allocation"); + return NULL; + default: + mcx_log(LOG_ERROR, "Invalid internal channel value reference type (%d)", ref->type); + return NULL; + } +} + #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index 13ab9e5..a1a7990 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -14,6 +14,8 @@ #include "CentralParts.h" #include "core/channels/ChannelDimension.h" +#include "core/Conversion.h" + #ifdef __cplusplus extern "C" { @@ -43,8 +45,8 @@ typedef struct ChannelValueRef { } ref; } ChannelValueRef; - -McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference); +McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, TypeConversion * typeConv); +ChannelType * ChannelValueRefGetType(const ChannelValueRef * ref); #ifdef __cplusplus From f01ff41c033ec49714e8bf5c6e5e6ddd15c438b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 3 Nov 2021 08:38:27 +0100 Subject: [PATCH 179/295] Fix ChannelValueRef definition --- src/core/channels/ChannelValueReference.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index a1a7990..7290a4d 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -36,7 +36,7 @@ typedef enum ChannelValueRefType { extern const struct ObjectClass _ChannelValueRef; typedef struct ChannelValueRef { - Object * _; + Object _; ChannelValueRefType type; union { From ff0c24e37e5a19150a89f3d9912f760a759aa4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 3 Nov 2021 15:38:13 +0100 Subject: [PATCH 180/295] Define 1 type conversion per connection --- src/core/Conversion.h | 3 ++ src/core/channels/Channel.c | 52 ++++++++++++++++++-------------- src/core/channels/Channel_impl.h | 2 +- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/core/Conversion.h b/src/core/Conversion.h index 22cf68e..dbef44d 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -119,6 +119,9 @@ typedef struct ChannelValueRef ChannelValueRef; typedef struct TypeConversion TypeConversion; typedef McxStatus (*fTypeConversionSetup)(TypeConversion * conversion, const ChannelType * fromType, const ChannelType * toType); + +// TODO: Ideally the `src` argument would also be ChannelValueRef, but that requires quite of lot of changes +// in the API of databus definition (i.e. DatabusSetIn(Out)Reference) typedef McxStatus (*fTypeConversionConvert)(TypeConversion * conversion, ChannelValueRef * dest, void * src); extern const struct ObjectClass _TypeConversion; diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 6e756cc..b84c885 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -99,8 +99,12 @@ static ChannelInData * ChannelInDataCreate(ChannelInData * data) { data->reference = NULL; data->type = ChannelTypeClone(&ChannelTypeUnknown); + data->typeConversions = (ObjectContainer *) object_create(ObjectContainer); + if (!data->typeConversions) { + return NULL; + } + data->unitConversion = NULL; - data->typeConversion = NULL; data->linearConversion = NULL; data->rangeConversion = NULL; @@ -110,12 +114,13 @@ static ChannelInData * ChannelInDataCreate(ChannelInData * data) { } static void ChannelInDataDestructor(ChannelInData * data) { + // clean up conversion objects + data->typeConversions->DestroyObjects(data->typeConversions); + object_destroy(data->typeConversions); + if (data->unitConversion) { object_destroy(data->unitConversion); } - if (data->typeConversion) { - object_destroy(data->typeConversion); - } if (data->linearConversion) { object_destroy(data->linearConversion); } @@ -197,34 +202,22 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { size_t numConns = in->data->connections->Size(in->data->connections); for (i = 0; i < numConns; i++) { Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); + TypeConversion * typeConv = (TypeConversion *) in->data->typeConversions->At(in->data->typeConversions, i); ChannelValueRef * valueRef = (ChannelValueRef *) in->data->valueReferences->At(in->data->valueReferences, i); ConnectionInfo * connInfo = &conn->info; char * connString = ConnectionInfoConnectionString(connInfo); - // TODO do we need this Init ??? - /*ChannelValueDestructor(val); - ChannelValueInit(val, ChannelTypeClone(connInfo->GetType(connInfo)));*/ - /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection %s failed", ChannelInfoGetLogName(info), connString); return RETURN_ERROR; } - if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), in->data->typeConversion)) { // TODO conn->GetValueReference - let it maybe return our reference + + // TODO: ideally make conn->GetValueReference return ChannelValueRef + if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), typeConv)) { mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueRefSetFromReference for connection %s failed", ChannelInfoGetLogName(info), connString); return RETURN_ERROR; } - - //// type - //// TODO per connection - //if (in->data->typeConversion) { - // Conversion * conversion = (Conversion *) in->data->typeConversion; - // retVal = conversion->convert(conversion, valueRef->ref.value); // TODO convert valueRef directly - // if (RETURN_OK != retVal) { - // mcx_log(LOG_ERROR, "Port %s: Update inport: Could not execute type conversion", info->GetLogName(info)); - // return RETURN_ERROR; - // } - //} } @@ -396,10 +389,23 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec // TODO - array // setup type conversion if (!ChannelTypeEq(inInfo->type, type)) { - in->data->typeConversion = (TypeConversion *) object_create(TypeConversion); - retVal = in->data->typeConversion->Setup(in->data->typeConversion, type, inInfo->type); + TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); + retVal = typeConv->Setup(typeConv, type, inInfo->type); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Port %s: Register inport connection: Could not set up type conversion", ChannelInfoGetLogName(inInfo)); + return RETURN_ERROR; + } + + + retVal = in->data->typeConversions->PushBack(in->data->typeConversions, (Object *) typeConv); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Port %s: Register inport connection: Could not add type conversion", ChannelInfoGetLogName(inInfo)); + return RETURN_ERROR; + } + } else { + retVal = in->data->typeConversions->PushBack(in->data->typeConversions, NULL); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Port %s: Set connection: Could not setup type conversion", ChannelInfoGetLogName(inInfo)); + mcx_log(LOG_ERROR, "Port %s: Register inport connection: Could not add empty type conversion", ChannelInfoGetLogName(inInfo)); return RETURN_ERROR; } } diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index 16d8d45..f0aca73 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -35,7 +35,7 @@ typedef struct ChannelInData { // ---------------------------------------------------------------------- // Conversions - struct TypeConversion * typeConversion; + ObjectContainer * typeConversions; // conversion objects (or NULL) for each connection in `connections` struct UnitConversion * unitConversion; struct LinearConversion * linearConversion; struct RangeConversion * rangeConversion; From f7948fc2392d1b9b68dfb37761c592a00197e28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 3 Nov 2021 16:04:47 +0100 Subject: [PATCH 181/295] Avoid getting connection string (mem allocation) during runtime --- src/core/channels/Channel.c | 102 +++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 25 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index b84c885..906312e 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -20,10 +20,79 @@ #include "core/channels/ChannelValue.h" #include "core/channels/Channel_impl.h" +#include +#include + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ + +static McxStatus ReportConnStringError(ChannelInfo * chInfo, const char * prefixFmt, ConnectionInfo * connInfo, const char * fmt, ...) { + // create format string + const char * portPrefix = "Port %s: "; + char * connString = NULL; + char * formatString = NULL; + char * prefix = NULL; + + if (connInfo) { + char * connString = ConnectionInfoConnectionString(connInfo); + + prefix = (char *) mcx_calloc(strlen(portPrefix) - 2 /* format specifier %s */ + + strlen(prefixFmt) - (connInfo == NULL ? 0 : 2 /* format specifier %s */) + + (connInfo == NULL ? 0 : connString ? strlen(connString) : strlen("(null)")) + + strlen(ChannelInfoGetLogName(chInfo)) + 1 /* \0 at the end of the string */, + sizeof(char)); + if (!prefix) { + goto cleanup; + } + + sprintf(prefix, portPrefix, ChannelInfoGetLogName(chInfo)); + sprintf(prefix + strlen(prefix), prefixFmt, connString); + } else { + prefix = (char *) mcx_calloc(strlen(portPrefix) - 2 /* format specifier %s */ + strlen(prefixFmt) + + strlen(ChannelInfoGetLogName(chInfo)) + 1 /* \0 at the end of the string */, + sizeof(char)); + if (!prefix) { + goto cleanup; + } + + sprintf(prefix, portPrefix, ChannelInfoGetLogName(chInfo)); + } + + formatString = (char *) mcx_calloc(strlen(fmt) + strlen(prefix) + 1, sizeof(char)); + if (!formatString) { + goto cleanup; + } + + strcat(formatString, prefix); + strcat(formatString, fmt); + + // log error message + va_list args; + va_start(args, fmt); + + mcx_vlog(LOG_ERROR, formatString, args); + + va_end(args); + +cleanup: + // free connection string + if (connString) { + mcx_free(connString); + } + + if (prefix) { + mcx_free(prefix); + } + + if (formatString) { + mcx_free(formatString); + } + + return RETURN_ERROR; +} + // ---------------------------------------------------------------------- // Channel @@ -202,21 +271,18 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { size_t numConns = in->data->connections->Size(in->data->connections); for (i = 0; i < numConns; i++) { Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); + ConnectionInfo * connInfo = &conn->info; TypeConversion * typeConv = (TypeConversion *) in->data->typeConversions->At(in->data->typeConversions, i); ChannelValueRef * valueRef = (ChannelValueRef *) in->data->valueReferences->At(in->data->valueReferences, i); - ConnectionInfo * connInfo = &conn->info; - char * connString = ConnectionInfoConnectionString(connInfo); /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { - mcx_log(LOG_ERROR, "Port %s: Update inport: UpdateToOutput of connection %s failed", ChannelInfoGetLogName(info), connString); - return RETURN_ERROR; + return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "UpdateToOutput failed"); } // TODO: ideally make conn->GetValueReference return ChannelValueRef if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), typeConv)) { - mcx_log(LOG_ERROR, "Port %s: Update inport: ChannelValueRefSetFromReference for connection %s failed", ChannelInfoGetLogName(info), connString); - return RETURN_ERROR; + return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "ChannelValueRefSetFromReference failed"); } } @@ -335,7 +401,6 @@ static ObjectContainer * ChannelInGetConnections(ChannelIn * in) { static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType * type) { ConnectionInfo * connInfo = &connection->info; - char * connString = ConnectionInfoConnectionString(connInfo); Channel * channel = (Channel *) in; ChannelInfo * inInfo = &channel->info; @@ -343,9 +408,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec retVal = in->data->connections->PushBack(in->data->connections, (Object *) connection); if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "Port %s: Register inport connection %s: Could not register connection", ChannelInfoGetLogName(inInfo), connString); - mcx_free(connString); - return RETURN_ERROR; + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not register connection"); } // TODO setup valueReference @@ -377,8 +440,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec unit, inInfo->unitString); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Port %s: Set inport connection: Could not setup unit conversion", ChannelInfoGetLogName(inInfo)); - return RETURN_ERROR; + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up unit conversion"); } if (in->data->unitConversion->IsEmpty(in->data->unitConversion)) { @@ -392,28 +454,18 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); retVal = typeConv->Setup(typeConv, type, inInfo->type); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Port %s: Register inport connection: Could not set up type conversion", ChannelInfoGetLogName(inInfo)); - return RETURN_ERROR; + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up type conversion"); } retVal = in->data->typeConversions->PushBack(in->data->typeConversions, (Object *) typeConv); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Port %s: Register inport connection: Could not add type conversion", ChannelInfoGetLogName(inInfo)); - return RETURN_ERROR; + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add type conversion"); } } else { retVal = in->data->typeConversions->PushBack(in->data->typeConversions, NULL); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Port %s: Register inport connection: Could not add empty type conversion", ChannelInfoGetLogName(inInfo)); - return RETURN_ERROR; - } - } - -cleanup: - if (RETURN_ERROR == retVal) { - if (connString) { - mcx_free(connString); + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add empty type conversion"); } } From efcde0469b8480f5a51810a7e40855a46e3c718a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 3 Nov 2021 17:00:43 +0100 Subject: [PATCH 182/295] Fix vector integrator --- src/components/comp_vector_integrator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 92e28fe..2d054a4 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -72,7 +72,7 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con ChannelInfo * info = outInfo; ChannelType * type = info->type; - if (!ChannelTypeEq(type, &ChannelTypeDouble) || ChannelTypeIsArray(type)) { + if (!ChannelTypeEq(ChannelTypeBaseType(type), &ChannelTypeDouble)) { ComponentLog(comp, LOG_ERROR, "Inport %s: Invalid type", ChannelInfoGetName(info)); return RETURN_ERROR; } @@ -124,14 +124,14 @@ static McxStatus DoStep(Component * comp, size_t group, double time, double delt size_t j = 0; for (j = 0; j < mcx_array_num_elements(state); j++) { - ((double *)state->data)[j] = ((double *)state->data)[j] * ((double *)deriv->data)[j] + deltaTime; + ((double *)state->data)[j] = ((double *)state->data)[j] + ((double *)deriv->data)[j] * deltaTime; } } else { double * state = (double *) ChannelValueReference(&integrator->state[i]); double * deriv = (double *) ChannelValueReference(&integrator->deriv[i]); - (*state) = (*state) * (*deriv) + deltaTime; + (*state) = (*state) + (*deriv) * deltaTime; } } From cb154dce4b50d07b81b6a87dde3ddf1386598a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 4 Nov 2021 14:00:21 +0100 Subject: [PATCH 183/295] Make filtered connections operate on sliced data --- src/core/connections/FilteredConnection.c | 55 ++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 4140637..5901d6f 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -46,6 +46,32 @@ static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { OBJECT_CLASS(FilteredConnectionData, Object); +static ChannelType * SliceDimensionToType(ChannelType * sourceType, ChannelDimension * dimension) { + if (dimension) { + // source data is an array + size_t i = 0; + ChannelType * type = NULL; + size_t * dims = (size_t *) mcx_calloc(sizeof(size_t), dimension->num); + + if (!dims) { + mcx_log(LOG_ERROR, "DetermineSliceType: Not enough memory for dimension calculation"); + return NULL; + } + + for (i = 0; i < dimension->num; i++) { + dims[i] = dimension->endIdxs[i] - dimension->startIdxs[i] + 1; // indices are inclusive + } + + type = ChannelTypeArray(ChannelTypeClone(ChannelTypeBaseType(sourceType)), dimension->num, dims); + mcx_free(dims); + return type; + } else { + // source data is a scalar + return ChannelTypeClone(sourceType); + } +} + + static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * in, ConnectionInfo * info) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; @@ -53,6 +79,8 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o ChannelInfo * sourceInfo = &((Channel *)out)->info; ChannelInfo * targetInfo = &((Channel *)in)->info; + ChannelType * storeType = NULL; + McxStatus retVal = RETURN_OK; // Decoupling @@ -64,14 +92,19 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o filteredConnection->data->filters = NULL; filteredConnection->data->numFilters = 0; + storeType = SliceDimensionToType(sourceInfo->type, info->sourceDimension); + if (!storeType) { + return RETURN_ERROR; + } + // value store - ChannelValueInit(&filteredConnection->data->store, ChannelTypeClone(sourceInfo->type)); + ChannelValueInit(&filteredConnection->data->store, storeType); // steals ownership of storeType -> no clone needed // value reference connection->value_ = ChannelValueReference(&filteredConnection->data->store); // initialize the buffer for channel function calls - ChannelValueInit(&filteredConnection->data->updateBuffer, ChannelTypeClone(sourceInfo->type)); + ChannelValueInit(&filteredConnection->data->updateBuffer, ChannelTypeClone(storeType)); // Connection::Setup() // this has to be done last as it connects the channels @@ -144,6 +177,18 @@ static McxStatus FilteredConnectionSetResult(FilteredConnection * connection, co return ChannelValueSetFromReference(&connection->data->store, value); } +static size_t GetSliceShift(Connection * connection) { + Channel * channel = (Channel *) connection->GetSource(connection); + ChannelInfo * channelInfo = &channel->info; + ChannelDimension * sourceDimension = channelInfo->dimension; + + ConnectionInfo * connInfo = connection->GetInfo(connection); + ChannelDimension * sliceDimension = connInfo->sourceDimension; + + // only 1D at the moment + return sliceDimension->startIdxs[0] - sourceDimension->startIdxs[0]; +} + static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInterval * time) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; Channel * channel = (Channel *) connection->GetSource(connection); @@ -155,8 +200,6 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter } #endif - // TODO: copy only sourceDimension slice - if (ChannelTypeIsScalar(info->type)) { ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, 0); if (filter && time->startTime >= 0) { @@ -165,6 +208,7 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter } } else { size_t i = 0; + size_t shift = GetSliceShift(connection); ChannelValueData element; ChannelValueDataInit(&element, ChannelTypeBaseType(info->type)); @@ -173,7 +217,7 @@ static void FilteredConnectionUpdateFromInput(Connection * connection, TimeInter if (filter && time->startTime >= 0) { ChannelValueData value = *(ChannelValueData *) channel->GetValueReference(channel); - mcx_array_get_elem(&value.a, i, &element); + mcx_array_get_elem(&value.a, i + shift, &element); filter->SetValue(filter, time->startTime, element); } } @@ -198,6 +242,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI if (out->GetFunction(out)) { proc * p = (proc *) out->GetFunction(out); + // TODO: Update functions to only update the slices ? if (p->fn(time, p->env, &filteredConnection->data->updateBuffer) != 0) { mcx_log(LOG_ERROR, "FilteredConnection: Function failed"); return RETURN_ERROR; From 8ae0b54bb31e814925eee2d1f1cac42cf7c55356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 5 Nov 2021 12:12:12 +0100 Subject: [PATCH 184/295] Drop indexed vector element indexing in connection definitions --- src/core/channels/ChannelDimension.c | 68 ++++++++++++++++++++ src/core/channels/ChannelDimension.h | 2 + src/core/connections/ConnectionInfoFactory.c | 63 ++++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index ea3965e..a2ed9df 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -9,6 +9,7 @@ ********************************************************************************/ #include "core/channels/ChannelDimension.h" +#include "util/stdlib.h" #ifdef __cplusplus extern "C" { @@ -134,6 +135,73 @@ int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second) { return TRUE; } +int ChannelDimensionIncludedIn(const ChannelDimension* first, const ChannelDimension* second) { + size_t i = 0; + + if (!first && !second) { + return TRUE; + } else if (!first || !second) { + return FALSE; + } + + if (first->num != second->num) { + return FALSE; // only same number of dimensions is comparable + } + + for (i = 0; i < first->num; i++) { + if (first->startIdxs[i] < second->startIdxs[i] || first->startIdxs[i] > second->endIdxs[i]) { + return FALSE; + } + + if (first->endIdxs[i] > second->endIdxs[i] || first->endIdxs[i] < second->startIdxs[i]) { + return FALSE; + } + } + + return TRUE; +} + +char * ChannelDimensionString(const ChannelDimension * dimension) { + char * str = NULL; + size_t length = 0; + size_t i = 0; + int n = 0; + + if (!dimension) { + return NULL; + } + + for (i = 0; i < dimension->num; i++) { + length += 1; // '(' + length += mcx_digits10(dimension->startIdxs[i]); // a + length += 2; // ', ' + length += mcx_digits10(dimension->endIdxs[i]); // b + length += 1; // ')' + } + + length += dimension->num - 1; // spaces between dimensions + length += 2; // '[' at the beginning and ']' at the end + length += 1; // '\0' + + str = (char *) mcx_calloc(sizeof(char), length); + if (!str) { + mcx_log(LOG_ERROR, "ChannelDimensionString: Not enough memory"); + return NULL; + } + + n += sprintf(str, "["); + for (i = 0; i < dimension->num; i++) { + if (i > 0) { + n += sprintf(str + n, " "); + } + n += sprintf(str + n, "(%zu, %zu)", dimension->startIdxs[i], dimension->endIdxs[i]); + } + sprintf(str + n, "]"); + + return str; +} + + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index f654c3e..493adc3 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -34,6 +34,8 @@ ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); size_t ChannelDimensionNumElements(ChannelDimension * dimension); ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); +int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); +char * ChannelDimensionString(const ChannelDimension * dimension); #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 4c1c23e..32079b9 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -104,6 +104,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, { Databus * databus = info->sourceComponent->GetDatabus(info->sourceComponent); DatabusInfo * databusInfo = DatabusGetOutInfo(databus); + ChannelInfo * sourceInfo = NULL; char * inputFromChannel = connInput->fromType == ENDPOINT_SCALAR ? connInput->from.scalarEndpoint->channel : connInput->from.vectorEndpoint->channel; @@ -137,6 +138,29 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->sourceDimension = sourceDimension; } + // check that the source endpoint "fits" into the channel + sourceInfo = DatabusInfoGetChannel(databusInfo, info->sourceChannel); + if (!ChannelDimensionIncludedIn(info->sourceDimension, sourceInfo->dimension)) { + char* channelDimString = ChannelDimensionString(sourceInfo->dimension); + char* connDimString = ChannelDimensionString(info->sourceDimension); + mcx_log(LOG_ERROR, + "Connection: Dimension index mismatch between source port %s of element %s and the connection endpoint: %s vs %s", + strFromChannel, + info->sourceComponent->GetName(info->sourceComponent), + channelDimString, + connDimString); + retVal = RETURN_ERROR; + + if (channelDimString) { + mcx_free(channelDimString); + } + if (connDimString) { + mcx_free(connDimString); + } + + 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) @@ -159,6 +183,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, { Databus * databus = info->targetComponent->GetDatabus(info->targetComponent); DatabusInfo * databusInfo = NULL; + ChannelInfo * targetInfo = NULL; char * inputToChannel = connInput->toType == ENDPOINT_SCALAR ? connInput->to.scalarEndpoint->channel : connInput->to.vectorEndpoint->channel; @@ -201,6 +226,29 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->targetDimension = targetDimension; } + // check that the target endpoint "fits" into the channel + targetInfo = DatabusInfoGetChannel(databusInfo, info->targetChannel); + if (!ChannelDimensionIncludedIn(info->targetDimension, targetInfo->dimension)) { + char * channelDimString = ChannelDimensionString(targetInfo->dimension); + char * connDimString = ChannelDimensionString(info->targetDimension); + mcx_log(LOG_ERROR, + "Connection: Dimension index mismatch between connection endpoint and the target port %s of element %s: %s vs %s", + strToChannel, + info->targetComponent->GetName(info->targetComponent), + connDimString, + channelDimString); + retVal = RETURN_ERROR; + + if (channelDimString) { + mcx_free(channelDimString); + } + if (connDimString) { + mcx_free(connDimString); + } + + goto cleanup; + } + info->targetChannel = DatabusInfoGetChannelID(databusInfo, strToChannel); if (info->targetChannel < 0) { if (0 == connectionInverted) { @@ -264,6 +312,21 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, } } + { + // check that connection endpoint dimensions match + ChannelDimension * sourceDim = info->sourceDimension; + ChannelDimension * targetDim = info->targetDimension; + + size_t numSourceElems = sourceDim ? ChannelDimensionNumElements(sourceDim) : 1; + size_t numTargetElems = targetDim ? ChannelDimensionNumElements(targetDim) : 1; + + if (numSourceElems != numTargetElems) { + mcx_log(LOG_ERROR, "Connection: Lengths of vectors do not match"); + retVal = RETURN_ERROR; + goto cleanup; + } + } + // extrapolation if (connInput->interExtrapolationType.defined) { info->interExtrapolationType = connInput->interExtrapolationType.value; From afa3ef0aa3083bf22b168e96e20d8399f124b904 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:12:50 +0100 Subject: [PATCH 185/295] Add ChannelTypeNumElements --- src/core/channels/ChannelValue.c | 15 +++++++++++++++ src/core/channels/ChannelValue.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 12a9fd0..91225ed 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -148,6 +148,21 @@ ChannelType * ChannelTypeBaseType(ChannelType * a) { } } +size_t ChannelTypeNumElements(ChannelType * type) { + if (ChannelTypeIsArray(type)) { + size_t i = 0; + size_t num_elems = 1; + + for (i = 0; i < type->ty.a.numDims; i++) { + num_elems *= type->ty.a.dims[i]; + } + + return num_elems; + } else { + return 1; + } +} + int ChannelTypeEq(ChannelType * a, ChannelType * b) { if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { size_t i = 0; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 34489b6..eb126db 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -65,6 +65,8 @@ int ChannelTypeIsScalar(ChannelType * a); int ChannelTypeIsArray(ChannelType * a); int ChannelTypeIsBinary(ChannelType * a); +size_t ChannelTypeNumElements(ChannelType * type); + ChannelType * ChannelTypeBaseType(ChannelType * a); int ChannelTypeEq(ChannelType * a, ChannelType * b); From 1c1dd6048917d3d806a149548f1a537c43ece589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:15:36 +0100 Subject: [PATCH 186/295] Add const qualifiers --- src/core/channels/ChannelValue.c | 10 +++++----- src/core/channels/ChannelValue.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 91225ed..9922278 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -124,19 +124,19 @@ ChannelType * ChannelTypeArrayInner(ChannelType * array) { return array->ty.a.inner; } -int ChannelTypeIsValid(ChannelType * a) { +int ChannelTypeIsValid(const ChannelType * a) { return a->con != CHANNEL_UNKNOWN; } -int ChannelTypeIsScalar(ChannelType * a) { +int ChannelTypeIsScalar(const ChannelType * a) { return a->con != CHANNEL_ARRAY; } -int ChannelTypeIsArray(ChannelType * a) { +int ChannelTypeIsArray(const ChannelType * a) { return a->con == CHANNEL_ARRAY; } -int ChannelTypeIsBinary(ChannelType * a) { +int ChannelTypeIsBinary(const ChannelType * a) { return a->con == CHANNEL_BINARY || a->con == CHANNEL_BINARY_REFERENCE; } @@ -148,7 +148,7 @@ ChannelType * ChannelTypeBaseType(ChannelType * a) { } } -size_t ChannelTypeNumElements(ChannelType * type) { +size_t ChannelTypeNumElements(const ChannelType * type) { if (ChannelTypeIsArray(type)) { size_t i = 0; size_t num_elems = 1; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index eb126db..c90990d 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -60,12 +60,12 @@ void ChannelTypeDestructor(ChannelType * type); ChannelType * ChannelTypeArrayInner(ChannelType * array); -int ChannelTypeIsValid(ChannelType * a); -int ChannelTypeIsScalar(ChannelType * a); -int ChannelTypeIsArray(ChannelType * a); -int ChannelTypeIsBinary(ChannelType * a); +int ChannelTypeIsValid(const ChannelType * a); +int ChannelTypeIsScalar(const ChannelType * a); +int ChannelTypeIsArray(const ChannelType * a); +int ChannelTypeIsBinary(const ChannelType * a); -size_t ChannelTypeNumElements(ChannelType * type); +size_t ChannelTypeNumElements(const ChannelType * type); ChannelType * ChannelTypeBaseType(ChannelType * a); From b1ec11354ac29fc933c99c2db1a8433b66099a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:34:39 +0100 Subject: [PATCH 187/295] Add type conversions scalar -> double array --- src/core/Conversion.c | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index f3191d0..e344a96 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -11,6 +11,7 @@ #include "CentralParts.h" #include "core/Conversion.h" #include "core/channels/ChannelValueReference.h" +#include "core/channels/ChannelValue.h" #include "units/Units.h" #ifdef __cplusplus @@ -560,6 +561,32 @@ static McxStatus CheckTypesValidForConversion(ChannelType * destType, return RETURN_OK; } +static McxStatus CheckArrayReferencingOnlyOneElement(ChannelValueRef * dest, ChannelType * expectedDestType) { + if (!ChannelTypeIsArray(ChannelValueRefGetType(dest))) { + mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array"); + return RETURN_ERROR; + } + + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelTypeBaseType(ChannelValueRefGetType(dest)), expectedDestType)) { + return RETURN_ERROR; + } + + // check only one element referenced + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + if (ChannelTypeNumElements(dest->ref.value->type) != 1) { + mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array of size 1"); + return RETURN_ERROR; + } + } else { + if (ChannelDimensionNumElements(dest->ref.slice->dimension) != 1) { + mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array of size 1"); + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; @@ -630,6 +657,51 @@ static McxStatus TypeConversionConvertSingletonDoubleToDouble(Conversion * conve return RETURN_OK; } +static McxStatus TypeConversionConvertDoubleToArrayDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeDouble)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(double *) dest->ref.value->value.a.data = *(double *) src; + } else { + double * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *(double *) src; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertIntegerToArrayDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeDouble)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(double *) dest->ref.value->value.a.data = (double) *((int *) src); + } else { + double * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = (double) *((int *) src); + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeDouble)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(double *) dest->ref.value->value.a.data = *((int *) src) != 0 ? 1. : 0.; + } else { + double * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *((int *) src) != 0 ? 1. : 0.; + } + + return RETURN_OK; +} + static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValueRef * dest, void * src) { return ChannelValueRefSetFromReference(dest, src, NULL); } @@ -640,6 +712,7 @@ static McxStatus TypeConversionSetup(TypeConversion * conversion, if (ChannelTypeEq(fromType, toType)) { conversion->Convert = TypeConversionConvertId; + /* scalar <-> scalar */ } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeDouble)) { conversion->Convert = TypeConversionConvertIntDouble; } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeInteger)) { @@ -652,8 +725,15 @@ static McxStatus TypeConversionSetup(TypeConversion * conversion, conversion->Convert = TypeConversionConvertBoolInteger; } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeBool)) { conversion->Convert = TypeConversionConvertIntegerBool; + /* scalar <-> array */ } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeDouble)) { conversion->Convert = TypeConversionConvertSingletonDoubleToDouble; + } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertDoubleToArrayDouble; + } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertIntegerToArrayDouble; + } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertBoolToArrayDouble; } else { mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion selected"); return RETURN_ERROR; From 6c24cb3f7528483076a15eadbe49ea4c95fa736d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:42:54 +0100 Subject: [PATCH 188/295] Add ChannelDimension utility functions --- src/core/channels/ChannelDimension.c | 45 ++++++++++++++++++++++++++++ src/core/channels/ChannelDimension.h | 2 ++ 2 files changed, 47 insertions(+) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index a2ed9df..266184d 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -201,6 +201,51 @@ char * ChannelDimensionString(const ChannelDimension * dimension) { return str; } +McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension * base) { + size_t i = 0; + if (!target && !base) { + return RETURN_OK; + } else if (!target || !base) { + return RETURN_ERROR; + } + + if (target->num != base->num) { + return RETURN_ERROR; + } + + for (i = 0; i < target->num; i++) { + target->startIdxs[i] -= base->startIdxs[i]; + target->endIdxs[i] -= base->startIdxs[i]; + } + + return RETURN_OK; +} + +ChannelType * ChannelDimensionToChannelType(ChannelDimension * dimension, ChannelType * sourceType) { + if (dimension) { + // source data is an array + size_t i = 0; + ChannelType * type = NULL; + size_t * dims = (size_t *) mcx_calloc(sizeof(size_t), dimension->num); + + if (!dims) { + mcx_log(LOG_ERROR, "ChannelDimensionToChannelType: Not enough memory for dimension calculation"); + return NULL; + } + + for (i = 0; i < dimension->num; i++) { + dims[i] = dimension->endIdxs[i] - dimension->startIdxs[i] + 1; // indices are inclusive + } + + type = ChannelTypeArray(ChannelTypeClone(ChannelTypeBaseType(sourceType)), dimension->num, dims); + mcx_free(dims); + return type; + } else { + // source data is a scalar + return ChannelTypeClone(sourceType); + } +} + #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 493adc3..555bb6a 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -36,6 +36,8 @@ ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); char * ChannelDimensionString(const ChannelDimension * dimension); +McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension * base); +ChannelType * ChannelDimensionToChannelType(ChannelDimension * dimension, ChannelType * sourceType); #ifdef __cplusplus } /* closing brace for extern "C" */ From 7e7c135349728b6cdbfd24a6cbf66fc96971653c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:48:14 +0100 Subject: [PATCH 189/295] Remove const qualifier --- src/core/channels/ChannelValueReference.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index 7290a4d..fc9d164 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -46,7 +46,7 @@ typedef struct ChannelValueRef { } ChannelValueRef; McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, TypeConversion * typeConv); -ChannelType * ChannelValueRefGetType(const ChannelValueRef * ref); +ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); #ifdef __cplusplus From 79dbc0c8fc6d105d97aa32d842ae2684a759956f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:49:07 +0100 Subject: [PATCH 190/295] Extend ChannelValueRefSetFromReference to work with slice conversions --- src/core/channels/ChannelValueReference.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index e97dff5..9aa1165 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -41,6 +41,12 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re // slice // TODO + + if (conv) { + return conv->Convert(conv, ref, reference); + } + + return ChannelValueDataSetFromReference(&ref->ref.slice->ref, ref->ref.value->type, reference); } return RETURN_OK; From d08347c259011e72d6ac234298ec485edce70acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 8 Nov 2021 10:52:53 +0100 Subject: [PATCH 191/295] Forward correct types to TypeConversion constructor --- src/core/channels/Channel.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 906312e..5c26b5f 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -426,6 +426,11 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec valRef->ref.slice = (ArraySlice *) mcx_calloc(1, sizeof(ArraySlice)); valRef->ref.slice->ref = &channel->value; valRef->ref.slice->dimension = ChannelDimensionClone(dimension); + retVal = ChannelDimensionNormalize(valRef->ref.slice->dimension, inInfo->dimension); + if (retVal == RETURN_ERROR) { + ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Normalizing array slice dimension failed"); + return RETURN_ERROR; + } } else { valRef->type = CHANNEL_VALUE_REF_VALUE; valRef->ref.value = &channel->value; @@ -450,9 +455,15 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec // TODO - array // setup type conversion + + ChannelType * connType = ChannelDimensionToChannelType(connInfo->sourceDimension, type); + if (!connType) { + return RETURN_ERROR; + } + if (!ChannelTypeEq(inInfo->type, type)) { TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); - retVal = typeConv->Setup(typeConv, type, inInfo->type); + retVal = typeConv->Setup(typeConv, connType, inInfo->type); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up type conversion"); } @@ -469,6 +480,8 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec } } + ChannelTypeDestructor(connType); + return retVal; } From 1d51dd643b8477ee08d0eabd7b2f9c7a0bfc85db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 9 Nov 2021 14:38:07 +0100 Subject: [PATCH 192/295] Define writeResults flag as a scalar for SSP as well --- scripts/SSP/Ports.xsd | 6 +----- src/reader/ssp/Ports.c | 15 +++------------ 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/scripts/SSP/Ports.xsd b/scripts/SSP/Ports.xsd index dee8489..448802c 100644 --- a/scripts/SSP/Ports.xsd +++ b/scripts/SSP/Ports.xsd @@ -25,10 +25,6 @@ - - - - @@ -38,7 +34,7 @@ - + diff --git a/src/reader/ssp/Ports.c b/src/reader/ssp/Ports.c index 466520c..93c4b08 100644 --- a/src/reader/ssp/Ports.c +++ b/src/reader/ssp/Ports.c @@ -239,18 +239,9 @@ VectorPortInput * SSDReadComponentVectorPort(xmlNodePtr connectorNode, const cha goto cleanup; } - { - size_t n = 0; - retVal = xml_attr_bool_vec(vectorNode, "writeResults", &n, &vectorPortInput->writeResults, SSD_OPTIONAL); - if (RETURN_ERROR == retVal) { - goto cleanup; - } else if (RETURN_OK == retVal) { - if (n != num) { - mcx_log(LOG_ERROR, "xml_attr_vec_len: Expected length (%d) does not match actual length (%d)", num, n); - retVal = RETURN_ERROR; - goto cleanup; - } - } + retVal = xml_opt_attr_bool(vectorNode, "writeResults", &vectorPortInput->writeResults); + if (RETURN_ERROR == retVal) { + goto cleanup; } } } From 374777ec0ca518e3f0f0207602380371bde067ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 12:16:45 +0100 Subject: [PATCH 193/295] Define mcx_array_set_elem --- src/core/channels/ChannelValue.c | 66 ++++++++++++++++++++++++++++++++ src/core/channels/ChannelValue.h | 1 + 2 files changed, 67 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 9922278..60eaa44 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -271,6 +271,72 @@ McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * eleme return RETURN_OK; } +McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element) { + size_t num_elems = mcx_array_num_elements(a); + + if (idx >= num_elems) { + mcx_log(LOG_ERROR, "mcx_array_set_elem: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); + return RETURN_ERROR; + } + + switch (a->type->con) { + case CHANNEL_DOUBLE: + *((double *) a->data + idx) = element->d; + break; + case CHANNEL_INTEGER: + *((int *) a->data + idx) = element->i; + break; + case CHANNEL_BOOL: + *((int *) a->data + idx) = element->i != 0 ? 1 : 0; + break; + case CHANNEL_STRING: + { + char ** elements = (char **) a->data; + + if (elements[idx]) { + mcx_free(elements[idx]); + } + + elements[idx] = (char *) mcx_calloc(strlen(element->s) + 1, sizeof(char)); + if (!elements[idx]) { + mcx_log(LOG_ERROR, "mcx_array_set_elem: Not enough memory"); + return RETURN_ERROR; + } + + strncpy(elements[idx], element->s, strlen(element->s) + 1); + break; + } + case CHANNEL_BINARY: + { + binary_string * elements = (binary_string *) a->data; + if (elements[idx].data) { + mcx_free(elements[idx].data); + } + + elements[idx].len = element->b.len; + elements[idx].data = (char *) mcx_calloc(elements[idx].len, 1); + if (!elements[idx].data) { + mcx_log(LOG_ERROR, "mcx_array_set_elem: Not enough memory"); + return RETURN_ERROR; + } + memcpy(elements[idx].data, element->b.data, elements[idx].len); + break; + } + case CHANNEL_BINARY_REFERENCE: + ((binary_string *) a->data)[idx].len = element->b.len; + ((binary_string *) a->data)[idx].data = element->b.data; + break; + case CHANNEL_ARRAY: + mcx_log(LOG_ERROR, "mcx_array_set_elem: Nested arrays are not supported"); + return RETURN_ERROR; + default: + mcx_log(LOG_ERROR, "mcx_array_set_elem: Unknown array type"); + return RETURN_ERROR; + } + + return RETURN_OK; +} + void ChannelValueInit(ChannelValue * value, ChannelType * type) { value->type = type; ChannelValueDataInit(&value->value, type); diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index c90990d..9abe021 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -107,6 +107,7 @@ void mcx_array_destroy(mcx_array * a); int mcx_array_dims_match(mcx_array * a, mcx_array * b); size_t mcx_array_num_elements(mcx_array * a); McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element); +McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element); // TODO: change concrete types to McxDouble, McxInteger, etc union ChannelValueData { From dc5fc053a6fc404b9157ba30cb0abfb957311fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 12:30:01 +0100 Subject: [PATCH 194/295] Define mcx_array_all and mcx_array_leq --- src/core/channels/ChannelValue.c | 48 ++++++++++++++++++++++++++++++++ src/core/channels/ChannelValue.h | 4 +++ 2 files changed, 52 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 60eaa44..f6c1aba 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -203,6 +203,54 @@ void mcx_array_destroy(mcx_array * a) { if (a->type) { ChannelTypeDestructor(a->type); } } +int mcx_array_all(mcx_array * a, mcx_array_predicate_f_ptr predicate) { + size_t i = 0; + ChannelValueData element = {0}; + + for (i = 0; i < mcx_array_num_elements(a); i++) { + if (RETURN_OK != mcx_array_get_elem(a, i, &element)) { + mcx_log(LOG_WARNING, "mcx_array_all: Getting element %zu failed", i); + return 0; + } + + if (!predicate(&element, a->type)) { + return 0; + } + } + + return 1; +} + +int mcx_array_leq(const mcx_array * left, const mcx_array * right) { + size_t numElems = 0; + size_t i = 0; + + if (!ChannelTypeEq(left->type, right->type)) { + return 0; + } + + numElems = mcx_array_num_elements(left); + + for (i = 0; i < numElems; i++) { + switch (left->type->con) { + case CHANNEL_DOUBLE: + if (((double *)left->data)[i] > ((double*)right->data)[i]) { + return 0; + } + break; + case CHANNEL_INTEGER: + if (((int *) left->data)[i] > ((int *) right->data)[i]) { + return 0; + } + break; + default: + return 0; + } + } + + return 1; +} + int mcx_array_dims_match(mcx_array * a, mcx_array * b) { size_t i = 0; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 9abe021..3fa733e 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -109,6 +109,10 @@ size_t mcx_array_num_elements(mcx_array * a); McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element); McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element); +typedef int (*mcx_array_predicate_f_ptr)(void * element, ChannelType * type); +int mcx_array_all(mcx_array * a, mcx_array_predicate_f_ptr predicate); +int mcx_array_leq(const mcx_array * left, const mcx_array * right); + // TODO: change concrete types to McxDouble, McxInteger, etc union ChannelValueData { /* the order is significant. double needs to be the first entry for union initialization to work */ From b94183ceda353da32ff4ba27bd343023abcf388e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 12:31:22 +0100 Subject: [PATCH 195/295] Implement conditional ChannelValueData element-wise setter --- src/core/channels/ChannelValue.c | 55 ++++++++++++++++++++++++++++++++ src/core/channels/ChannelValue.h | 5 +++ 2 files changed, 60 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index f6c1aba..a36d19a 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -690,6 +690,61 @@ void ChannelValueDataInit(ChannelValueData * data, ChannelType * type) { } } +McxStatus ChannelValueDataSetFromReferenceIfElemwisePred(ChannelValueData * data, + ChannelType * type, + const void * reference, + fChannelValueDataSetterPredicate predicate) { + if (!reference) { + return RETURN_OK; + } + + if (ChannelTypeIsArray(type)) { + mcx_array * a = (mcx_array *) reference; + size_t i = 0; + ChannelValueData first = {0}; + ChannelValueData second = {0}; + + if (!mcx_array_dims_match(&data->a, a)) { + mcx_log(LOG_ERROR, "ChannelValueDataSetFromReferenceIfElemwisePred: Mismatching array dimensions"); + return RETURN_ERROR; + } + + if (a->data == NULL || data->a.data == NULL) { + mcx_log(LOG_ERROR, "ChannelValueDataSetFromReferenceIfElemwisePred: Array data not initialized"); + return RETURN_ERROR; + } + + for (i = 0; i < mcx_array_num_elements(&data->a); i++) { + if (RETURN_OK != mcx_array_get_elem(&data->a, i, &first)) { + mcx_log(LOG_ERROR, "ChannelValueDataSetFromReferenceIfElemwisePred: Getting destination element %zu failed", i); + return RETURN_ERROR; + } + + if (RETURN_OK != mcx_array_get_elem(a, i, &second)) { + mcx_log(LOG_ERROR, "ChannelValueDataSetFromReferenceIfElemwisePred: Getting source element %zu failed", i); + return RETURN_ERROR; + } + + if (predicate(&first, &second, a->type)) { + mcx_array_set_elem(&data->a, i, &second); + } + } + + return RETURN_OK; + } else { + + } + switch (type->con) { + default: + if (predicate(data, reference, type)) { + return ChannelValueDataSetFromReference(data, type, reference); + } + break; + } + + return RETURN_OK; +} + McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType * type, const void * reference) { if (!reference) { return RETURN_OK; } diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 3fa733e..025770d 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -141,6 +141,11 @@ void * ChannelValueReference(ChannelValue * value); void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type); void ChannelValueDataInit(ChannelValueData * data, ChannelType * type); McxStatus ChannelValueDataSetFromReference(ChannelValueData * data, ChannelType * type, const void * reference); +typedef int (*fChannelValueDataSetterPredicate)(void * first, void * second, ChannelType * type); +McxStatus ChannelValueDataSetFromReferenceIfElemwisePred(ChannelValueData * data, + ChannelType * type, + const void * reference, + fChannelValueDataSetterPredicate predicate); McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * type, void * reference); McxStatus ChannelValueSetFromReference(ChannelValue * value, const void * reference); From 4536533204a9b29fa4c346342db39268d91e2452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 12:33:08 +0100 Subject: [PATCH 196/295] Support array in RangeConversion --- src/core/Conversion.c | 103 ++++++++++++++++++++++++------- src/core/channels/Channel.c | 12 ++-- src/core/channels/ChannelValue.c | 2 + 3 files changed, 87 insertions(+), 30 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index e344a96..9851623 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -104,24 +104,56 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va return retVal; } +static int RangeConversionElemwiseLeq(void * first, void * second, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) first <= *(double *) second; + case CHANNEL_INTEGER: + return *(int *) first <= *(int *) second; + default: + return 0; + } +} + +static int RangeConversionElemwiseGeq(void * first, void * second, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) first >= *(double *) second; + case CHANNEL_INTEGER: + return *(int *) first >= *(int *) second; + default: + return 0; + } +} + static McxStatus RangeConversionConvert(Conversion * conversion, ChannelValue * value) { RangeConversion * rangeConversion = (RangeConversion *) conversion; - McxStatus retVal = RETURN_OK; if (!ChannelTypeEq(ChannelValueType(value), rangeConversion->type)) { - mcx_log(LOG_ERROR, "Range conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(rangeConversion->type)); + mcx_log(LOG_ERROR, + "Range conversion: Value has wrong type %s, expected: %s", + ChannelTypeToString(ChannelValueType(value)), + ChannelTypeToString(rangeConversion->type)); return RETURN_ERROR; } - if (rangeConversion->min && ChannelValueLeq(value, rangeConversion->min)) { - retVal = ChannelValueSet(value, rangeConversion->min); + if (rangeConversion->min) { + retVal = ChannelValueDataSetFromReferenceIfElemwisePred(&value->value, + value->type, + &rangeConversion->min->value, + RangeConversionElemwiseLeq); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Range conversion: Set value to min failed"); return RETURN_ERROR; } - } else if (rangeConversion->max && ChannelValueGeq(value, rangeConversion->max)) { - retVal = ChannelValueSet(value, rangeConversion->max); + } + + if (rangeConversion->max) { + retVal = ChannelValueDataSetFromReferenceIfElemwisePred(&value->value, + value->type, + &rangeConversion->max->value, + RangeConversionElemwiseGeq); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Range conversion: Set value to max failed"); return RETURN_ERROR; @@ -146,15 +178,11 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue return RETURN_ERROR; } - if (min) { - conversion->type = ChannelValueType(min); - } else { - conversion->type = ChannelValueType(max); - } + conversion->type = ChannelTypeClone(ChannelValueType(min ? min : max)); - if (!(ChannelTypeEq(conversion->type, &ChannelTypeDouble) - || ChannelTypeEq(conversion->type, &ChannelTypeInteger) - || ChannelTypeIsArray(conversion->type))) { + if (!(ChannelTypeEq(ChannelTypeBaseType(conversion->type), &ChannelTypeDouble) || + ChannelTypeEq(ChannelTypeBaseType(conversion->type), &ChannelTypeInteger))) + { mcx_log(LOG_ERROR, "Range conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -165,22 +193,49 @@ static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue return RETURN_OK; } +static int RangeConversionElementEqualsMin(void * element, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) element == (-DBL_MAX); + case CHANNEL_INTEGER: + return *(int *) element == INT_MIN; + default: + return 0; + } +} + +static int RangeConversionElementEqualsMax(void * element, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) element == DBL_MAX; + case CHANNEL_INTEGER: + return *(int *) element == INT_MAX; + default: + return 0; + } +} + static int RangeConversionIsEmpty(RangeConversion * conversion) { switch (conversion->type->con) { - case CHANNEL_DOUBLE: - return - (!conversion->min || * (double *) ChannelValueReference(conversion->min) == (-DBL_MAX)) && - (!conversion->max || * (double *) ChannelValueReference(conversion->max) == DBL_MAX); - case CHANNEL_INTEGER: - return - (!conversion->min || * (int *) ChannelValueReference(conversion->min) == INT_MIN) && - (!conversion->max || * (int *) ChannelValueReference(conversion->max) == INT_MAX); - default: - return 1; + case CHANNEL_DOUBLE: + return (!conversion->min || *(double *) ChannelValueReference(conversion->min) == (-DBL_MAX)) && + (!conversion->max || *(double *) ChannelValueReference(conversion->max) == DBL_MAX); + case CHANNEL_INTEGER: + return (!conversion->min || *(int *) ChannelValueReference(conversion->min) == INT_MIN) && + (!conversion->max || *(int *) ChannelValueReference(conversion->max) == INT_MAX); + case CHANNEL_ARRAY: + return (!conversion->min || mcx_array_all(&conversion->min->value.a, RangeConversionElementEqualsMin)) && + (!conversion->max || mcx_array_all(&conversion->max->value.a, RangeConversionElementEqualsMax)); + default: + return 1; } } static void RangeConversionDestructor(RangeConversion * rangeConversion) { + if (rangeConversion->type) { + ChannelTypeDestructor(rangeConversion->type); + } + if (rangeConversion->min) { mcx_free(rangeConversion->min); } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 5c26b5f..4d4ce08 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -519,8 +519,8 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { // unit conversion is setup when a connection is set // min/max conversions are only used for double types - if (ChannelTypeEq(info->type, &ChannelTypeDouble) - || ChannelTypeEq(info->type, &ChannelTypeInteger)) + if (ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeDouble) || + ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeInteger)) { ChannelValue * min = info->min; ChannelValue * max = info->max; @@ -661,8 +661,8 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * // min/max conversions are only used for double types - if (ChannelTypeEq(info->type, &ChannelTypeDouble) - || ChannelTypeEq(info->type, &ChannelTypeInteger)) + if (ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeDouble) + || ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeInteger)) { out->data->rangeConversion = (RangeConversion *) object_create(RangeConversion); retVal = out->data->rangeConversion->Setup(out->data->rangeConversion, min, max); @@ -885,8 +885,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // Apply conversion - if (ChannelTypeEq(info->type, &ChannelTypeDouble) || - ChannelTypeEq(info->type, &ChannelTypeInteger)) { + if (ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeDouble) || + ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeInteger)) { ChannelValue * val = &channel->value; // range diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index a36d19a..139e48a 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -1011,6 +1011,8 @@ int ChannelValueLeq(ChannelValue * val1, ChannelValue * val2) { return val1->value.d <= val2->value.d; case CHANNEL_INTEGER: return val1->value.i <= val2->value.i; + case CHANNEL_ARRAY: + return mcx_array_leq(&val1->value.a, &val2->value.a); default: return 0; } From a5c6860b20ea5ec556d10917266245d7432b68b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 12:35:38 +0100 Subject: [PATCH 197/295] Do not define ChannelValueArrays if min/max/offset/etc. are not specified --- src/core/Databus.c | 60 +++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 067b514..85da1a2 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -115,40 +115,52 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { goto vector_cleanup_0; } - info->min = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->min); - if (!info->min) { - retVal = RETURN_ERROR; - goto vector_cleanup_0; + if (vectorPortInput->min) { + info->min = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->min); + if (!info->min) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; + } } - info->max = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->max); - if (!info->max) { - retVal = RETURN_ERROR; - goto vector_cleanup_0; + if (vectorPortInput->max) { + info->max = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->max); + if (!info->max) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; + } } - info->scale = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->scale); - if (!info->scale) { - retVal = RETURN_ERROR; - goto vector_cleanup_0; + if (vectorPortInput->scale) { + info->scale = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->scale); + if (!info->scale) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; + } } - info->offset = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->offset); - if (!info->offset) { - retVal = RETURN_ERROR; - goto vector_cleanup_0; + if (vectorPortInput->offset) { + info->offset = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->offset); + if (!info->offset) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; + } } - info->initialValue = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->initial); - if (!info->initialValue) { - retVal = RETURN_ERROR; - goto vector_cleanup_0; + if (vectorPortInput->initial) { + info->initialValue = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->initial); + if (!info->initialValue) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; + } } - info->defaultValue = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->default_); - if (!info->defaultValue) { - retVal = RETURN_ERROR; - goto vector_cleanup_0; + if (vectorPortInput->default_) { + info->defaultValue = ChannelValueNewArray(1, dims, vectorPortInput->type, vectorPortInput->default_); + if (!info->defaultValue) { + retVal = RETURN_ERROR; + goto vector_cleanup_0; + } } if (vectorPortInput->writeResults.defined) { From 85b9c3c38ba3b23315da915efc6964b74dd34de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 12:36:20 +0100 Subject: [PATCH 198/295] Fix ChannelDimensionNormalize --- src/core/channels/ChannelDimension.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 266184d..1b42ef4 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -214,8 +214,8 @@ McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension } for (i = 0; i < target->num; i++) { - target->startIdxs[i] -= base->startIdxs[i]; target->endIdxs[i] -= base->startIdxs[i]; + target->startIdxs[i] -= base->startIdxs[i]; } return RETURN_OK; From ba594c25c1e41b957cb94d3e20eb17349a7867dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 14:13:16 +0100 Subject: [PATCH 199/295] Define scale and offset operation on ChannelValue --- src/core/channels/ChannelValue.c | 53 ++++++++++++++++++++++++++++++++ src/core/channels/ChannelValue.h | 4 +++ 2 files changed, 57 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 139e48a..4e23412 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -285,6 +285,19 @@ size_t mcx_array_num_elements(mcx_array * a) { return n; } +McxStatus mcx_array_map(mcx_array * a, mcx_array_map_f_ptr fn, void * ctx) { + size_t num_elems = mcx_array_num_elements(a); + size_t i = 0; + + for (i = 0; i < num_elems; i++) { + if (fn((char *) a->data + i * ChannelValueTypeSize(a->type), i, a->type, ctx)) { + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element) { size_t num_elems = mcx_array_num_elements(a); @@ -1051,6 +1064,24 @@ int ChannelValueEq(ChannelValue * val1, ChannelValue * val2) { } } +static int ChannelValueArrayElemAddOffset(void * elem, size_t idx, ChannelType * type, void * ctx) { + mcx_array * offset = (mcx_array *) ctx; + + switch (type->con) { + case CHANNEL_DOUBLE: + *(double *) elem = *(double *) elem + ((double *) offset->data)[idx]; + break; + case CHANNEL_INTEGER: + *(int *) elem = *(int *) elem + ((int *) offset->data)[idx]; + break; + default: + mcx_log(LOG_ERROR, "ChannelValueArrayElemAddOffset: Type %s not allowed", ChannelTypeToString(type)); + return 1; + } + + return 0; +} + McxStatus ChannelValueAddOffset(ChannelValue * val, ChannelValue * offset) { if (!ChannelTypeEq(val->type, offset->type)) { mcx_log(LOG_ERROR, "Port: Add offset: Mismatching types. Value type: %s, offset type: %s", @@ -1065,12 +1096,32 @@ McxStatus ChannelValueAddOffset(ChannelValue * val, ChannelValue * offset) { case CHANNEL_INTEGER: val->value.i += offset->value.i; return RETURN_OK; + case CHANNEL_ARRAY: + return mcx_array_map(&val->value.a, ChannelValueArrayElemAddOffset, &offset->value.a); default: mcx_log(LOG_ERROR, "Port: Add offset: Type %s not allowed", ChannelTypeToString(ChannelValueType(val))); return RETURN_ERROR; } } +static int ChannelValueArrayElemScale(void * elem, size_t idx, ChannelType * type, void * ctx) { + mcx_array * factor = (mcx_array *) ctx; + + switch (type->con) { + case CHANNEL_DOUBLE: + *(double *) elem = *(double *) elem * ((double *) factor->data)[idx]; + break; + case CHANNEL_INTEGER: + *(int *) elem = *(int *) elem * ((int *) factor->data)[idx]; + break; + default: + mcx_log(LOG_ERROR, "ChannelValueArrayElemScale: Type %s not allowed", ChannelTypeToString(type)); + return 1; + } + + return 0; +} + McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { if (!ChannelTypeEq(val->type, factor->type)) { mcx_log(LOG_ERROR, "Port: Scale: Mismatching types. Value type: %s, factor type: %s", @@ -1085,6 +1136,8 @@ McxStatus ChannelValueScale(ChannelValue * val, ChannelValue * factor) { case CHANNEL_INTEGER: val->value.i *= factor->value.i; return RETURN_OK; + case CHANNEL_ARRAY: + return mcx_array_map(&val->value.a, ChannelValueArrayElemScale, &factor->value.a); default: mcx_log(LOG_ERROR, "Port: Scale: Type %s not allowed", ChannelTypeToString(ChannelValueType(val))); return RETURN_ERROR; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 025770d..53fe10b 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -106,6 +106,10 @@ McxStatus mcx_array_init(mcx_array * a, size_t numDims, size_t * dims, ChannelTy void mcx_array_destroy(mcx_array * a); int mcx_array_dims_match(mcx_array * a, mcx_array * b); size_t mcx_array_num_elements(mcx_array * a); + +typedef int (*mcx_array_map_f_ptr)(void * element, size_t idx, ChannelType * type, void * ctx); + +McxStatus mcx_array_map(mcx_array * a, mcx_array_map_f_ptr fn, void * ctx); McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element); McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element); From e3105627f4a07c49b98716513f72ae5f232962ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 10 Nov 2021 14:14:17 +0100 Subject: [PATCH 200/295] Linear conversion for arrays --- src/core/Conversion.c | 47 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 9851623..5762663 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -501,20 +501,18 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal } if (factor && offset && !ChannelTypeEq(ChannelValueType(factor), ChannelValueType(offset))) { - mcx_log(LOG_WARNING, "Linear conversion: Types of factor value (%s) and offset value (%s) do not match", - ChannelTypeToString(ChannelValueType(factor)), ChannelTypeToString(ChannelValueType(offset))); + mcx_log(LOG_WARNING, + "Linear conversion: Types of factor value (%s) and offset value (%s) do not match", + ChannelTypeToString(ChannelValueType(factor)), + ChannelTypeToString(ChannelValueType(offset))); return RETURN_ERROR; } - if (factor) { - conversion->type = ChannelValueType(factor); - } else { - conversion->type = ChannelValueType(offset); - } + conversion->type = ChannelTypeClone(ChannelValueType(factor ? factor : offset)); - if (!(ChannelTypeEq(conversion->type, &ChannelTypeDouble) - || ChannelTypeEq(conversion->type, &ChannelTypeInteger) - || ChannelTypeIsArray(conversion->type))) { + if (!(ChannelTypeEq(ChannelTypeBaseType(conversion->type), &ChannelTypeDouble) || + ChannelTypeEq(ChannelTypeBaseType(conversion->type), &ChannelTypeInteger))) + { mcx_log(LOG_WARNING, "Linear conversion is not defined for type %s", ChannelTypeToString(conversion->type)); return RETURN_ERROR; } @@ -525,6 +523,28 @@ static McxStatus LinearConversionSetup(LinearConversion * conversion, ChannelVal return RETURN_OK; } +static int LinearConversionElementEqualsOne(void* element, ChannelType* type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) element == 1.0; + case CHANNEL_INTEGER: + return *(int *) element == 1; + default: + return 0; + } +} + +static int LinearConversionElementEqualsZero(void * element, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) element == 0.0; + case CHANNEL_INTEGER: + return *(int *) element == 0; + default: + return 0; + } +} + static int LinearConversionIsEmpty(LinearConversion * conversion) { switch (conversion->type->con) { case CHANNEL_DOUBLE: @@ -535,12 +555,19 @@ static int LinearConversionIsEmpty(LinearConversion * conversion) { return (!conversion->factor || * (int *) ChannelValueReference(conversion->factor) == 1) && (!conversion->offset || * (int *) ChannelValueReference(conversion->offset) == 0); + case CHANNEL_ARRAY: + return (!conversion->factor || mcx_array_all(&conversion->factor->value.a, LinearConversionElementEqualsOne)) && + (!conversion->offset || mcx_array_all(&conversion->offset->value.a, LinearConversionElementEqualsZero)); default: return 1; } } static void LinearConversionDestructor(LinearConversion * linearConversion) { + if (linearConversion->type) { + ChannelTypeDestructor(linearConversion->type); + } + if (linearConversion->factor) { mcx_free(linearConversion->factor); } From 52bb364f3d0ea415bc4ca9eeb55be691d835cd77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 11 Nov 2021 10:00:33 +0100 Subject: [PATCH 201/295] Adapt Dependency matrix generation wrt. array channels --- src/core/SubModel.c | 122 ++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 67 deletions(-) diff --git a/src/core/SubModel.c b/src/core/SubModel.c index eeb36ce..c2315d9 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -701,6 +701,7 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, i); if (!ConnectionInfoIsDecoupled(info)) { allDecoupled = FALSE; + break; } } @@ -714,81 +715,68 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen if (DEP_INDEPENDENT != dependency) { ObjectContainer * infos = GetInConnectionInfos(targetComp, targetInChannelID); ObjectContainer * conns = GetInConnections(targetComp, targetInChannelID); - size_t numInfos = infos->Size(infos); - size_t numConns = conns->Size(conns); size_t i = 0; - int isDecoupled = TRUE; - size_t decoupleType = (size_t) -1; - int isActiveDependency = FALSE; - - for (i = 0; i < numInfos; i++) { - ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, i); - if (!ConnectionInfoIsDecoupled(info)) { - isDecoupled = FALSE; - } - - decoupleType &= info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED); - } - - for (i = 0; i < numConns; i++) { - Connection * conn = (Connection *) conns->At(conns, i); - if (conn->IsActiveDependency(conn)) { - isActiveDependency = TRUE; - break; - } - } - - if (numInfos > 0 && decoupleType && !isDecoupled && numConns > 0 && isActiveDependency) { - ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, 0); - - 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->sourceChannel); - } else { - sourceOutGroup = sourceComp->GetOutGroup(sourceComp, info->sourceChannel); - } + for (i = 0; i < infos->Size(infos); i++) { + ConnectionInfo * info = infos->At(infos, i); + Connection * conn = conns->At(conns, i); + + if (info && (info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED)) && (!ConnectionInfoIsDecoupled(info)) && + conn && conn->IsActiveDependency(conn)) + { + 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->sourceChannel); + } else { + sourceOutGroup = sourceComp->GetOutGroup(sourceComp, info->sourceChannel); + } - sourceNode = SubModelGeneratorGetNodeID(subModelGenerator, sourceComp, sourceOutGroup); + sourceNode = SubModelGeneratorGetNodeID(subModelGenerator, sourceComp, sourceOutGroup); - if (SIZE_T_ERROR == sourceNode) { - // source is not part of this submodel - // -> no dependency -> do nothing - continue; - } + if (SIZE_T_ERROR == sourceNode) { + // source is not part of this submodel + // -> no dependency -> do nothing + continue; + } - if (INITIAL_DEPENDENCIES == depType) { - // check if the target output has an exact initial value - ChannelInfo * info = NULL; - // check if target outputs even exits - if (0 < numOutChannels) { - info = DatabusGetOutChannelInfo(db, targetGroup); - // initial outputs are exact only if specified - if (info->initialValueIsExact && info->initialValue) { - continue; + if (INITIAL_DEPENDENCIES == depType) { + // check if the target output has an exact initial value + ChannelInfo * info = NULL; + // check if target outputs even exits + if (0 < numOutChannels) { + info = DatabusGetOutChannelInfo(db, targetGroup); + // initial outputs are exact only if specified + if (info->initialValueIsExact && info->initialValue) { + continue; + } } } - } - retVal = SetDependency(A, sourceNode, targetNode, DEP_DEPENDENT); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "SetDependency failed in SubModelGeneratorCreateDependencyMatrix"); - mcx_free(A); - return NULL; - } + retVal = SetDependency(A, sourceNode, targetNode, DEP_DEPENDENT); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "SetDependency failed in SubModelGeneratorCreateDependencyMatrix"); + mcx_free(A); + return NULL; + } - if (0 == numOutChannels && (INITIAL_DEPENDENCIES == depType) ) { - mcx_log(LOG_DEBUG, "(%s,%d) -> (%s,-)", - sourceComp->GetName(sourceComp), sourceOutGroup, - targetComp->GetName(targetComp) ); - } else { - mcx_log(LOG_DEBUG, "(%s,%d) -> (%s,%d)", - sourceComp->GetName(sourceComp), sourceOutGroup, - targetComp->GetName(targetComp), targetGroup); + if (0 == numOutChannels && (INITIAL_DEPENDENCIES == depType)) { + mcx_log(LOG_DEBUG, + "(%s,%d) -> (%s,-)", + sourceComp->GetName(sourceComp), + sourceOutGroup, + targetComp->GetName(targetComp)); + } else { + mcx_log(LOG_DEBUG, + "(%s,%d) -> (%s,%d)", + sourceComp->GetName(sourceComp), + sourceOutGroup, + targetComp->GetName(targetComp), + targetGroup); + } } } } From a7d81f41ec62aca64dc0bd15d63de5171decd394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 11 Nov 2021 10:07:06 +0100 Subject: [PATCH 202/295] Adapt UnitConversion to arrays --- src/core/Conversion.c | 58 +++++++++++++++++------ src/core/Conversion.h | 9 ++-- src/core/channels/Channel.c | 57 +++++++++++++--------- src/core/channels/ChannelDimension.c | 34 +++++++++++++ src/core/channels/ChannelDimension.h | 1 + src/core/channels/ChannelValue.c | 12 +++++ src/core/channels/ChannelValue.h | 2 + src/core/channels/ChannelValueReference.c | 48 +++++++++++++++++++ src/core/channels/ChannelValueReference.h | 3 ++ src/core/channels/Channel_impl.h | 2 +- 10 files changed, 184 insertions(+), 42 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 5762663..3d43ac8 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -265,6 +265,12 @@ OBJECT_CLASS(RangeConversion, Conversion); // ---------------------------------------------------------------------- // Unit Conversion +static double UnitConversionConvertValue(UnitConversion * conversion, double value) { + value = (value + conversion->source.offset) * conversion->source.factor; + value = (value / conversion->target.factor) - conversion->target.offset; + + return value; +} McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * value) { UnitConversion * unitConv = NULL; @@ -306,12 +312,7 @@ static void UnitConversionConvertVector(UnitConversion * unitConversion, double size_t i; if (!unitConversion->IsEmpty(unitConversion)) { for (i = 0; i < vectorLength; i++) { - double val = vector[i]; - - val = (val + unitConversion->source.offset) * unitConversion->source.factor; - val = (val / unitConversion->target.factor) - unitConversion->target.offset; - - vector[i] = val; + vector[i] = UnitConversionConvertValue(unitConversion, vector[i]); } } } @@ -319,25 +320,53 @@ static void UnitConversionConvertVector(UnitConversion * unitConversion, double static McxStatus UnitConversionConvert(Conversion * conversion, ChannelValue * value) { UnitConversion * unitConversion = (UnitConversion *) conversion; - double val = 0.0; - - if (!ChannelTypeEq(ChannelValueType(value), &ChannelTypeDouble)) { + if (!ChannelTypeEq(ChannelTypeBaseType(ChannelValueType(value)), &ChannelTypeDouble)) { mcx_log(LOG_ERROR, "Unit conversion: Value has wrong type %s, expected: %s", ChannelTypeToString(ChannelValueType(value)), ChannelTypeToString(&ChannelTypeDouble)); return RETURN_ERROR; } - val = * (double *) ChannelValueReference(value); + if (ChannelTypeIsArray(value->type)) { + size_t i = 0; - val = (val + unitConversion->source.offset) * unitConversion->source.factor; - val = (val / unitConversion->target.factor) - unitConversion->target.offset; + for (i = 0; i < mcx_array_num_elements(&value->value.a); i++) { + double * elem = (double *)mcx_array_get_elem_reference(&value->value.a, i); + if (!elem) { + return RETURN_ERROR; + } - if (RETURN_OK != ChannelValueSetFromReference(value, &val)) { - return RETURN_ERROR; + *elem = UnitConversionConvertValue(conversion, *elem); + } + } else { + double val = UnitConversionConvertValue(unitConversion, *(double *) ChannelValueReference(value)); + if (RETURN_OK != ChannelValueSetFromReference(value, &val)) { + return RETURN_ERROR; + } } return RETURN_OK; } +McxStatus UnitConversionValueRefConversion(void * element, ChannelType * type, void * ctx) { + double * elem = (double *) element; + UnitConversion * conversion = (UnitConversion *) ctx; + + *elem = UnitConversionConvertValue(conversion, *elem); + + return RETURN_OK; +} + +static McxStatus UnitConversionConvertValueRef(UnitConversion * conversion, ChannelValueRef * ref) { + if (!ChannelTypeEq(ChannelTypeBaseType(ChannelValueRefGetType(ref)), &ChannelTypeDouble)) { + mcx_log(LOG_ERROR, + "Unit conversion: Value has wrong type %s, expected: %s", + ChannelTypeToString(ChannelTypeBaseType(ChannelValueRefGetType(ref))), + ChannelTypeToString(&ChannelTypeDouble)); + return RETURN_ERROR; + } + + return ChannelValueRefElemMap(ref, UnitConversionValueRefConversion, conversion); +} + static McxStatus UnitConversionSetup(UnitConversion * conversion, const char * fromUnit, const char * toUnit) { @@ -385,6 +414,7 @@ static UnitConversion * UnitConversionCreate(UnitConversion * unitConversion) { conversion->convert = UnitConversionConvert; unitConversion->convertVector = UnitConversionConvertVector; + unitConversion->ConvertValueReference = UnitConversionConvertValueRef; unitConversion->Setup = UnitConversionSetup; unitConversion->IsEmpty = UnitConversionIsEmpty; diff --git a/src/core/Conversion.h b/src/core/Conversion.h index dbef44d..7aa9b78 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -18,6 +18,9 @@ extern "C" { #endif /* __cplusplus */ + +typedef struct ChannelValueRef ChannelValueRef; + typedef struct Conversion Conversion; typedef McxStatus (* fConversion)(Conversion * conversion, ChannelValue * value); @@ -66,6 +69,7 @@ typedef void(*fUnitConversionVector)(UnitConversion * conversion, double * value typedef McxStatus (* fUnitConversionSetup)(UnitConversion * conversion, const char * fromUnit, const char * toUnit); typedef int (* fUnitConversionIsEmpty)(UnitConversion * conversion); +typedef McxStatus (*fUnitConversionConvertValueRef)(UnitConversion * conversion, ChannelValueRef * ref); extern const struct ObjectClass _UnitConversion; @@ -74,6 +78,7 @@ struct UnitConversion { fUnitConversionSetup Setup; fUnitConversionIsEmpty IsEmpty; + fUnitConversionConvertValueRef ConvertValueReference; si_def source; si_def target; @@ -112,10 +117,6 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal // ---------------------------------------------------------------------- // Type Conversion - -typedef struct ChannelValueRef ChannelValueRef; - - typedef struct TypeConversion TypeConversion; typedef McxStatus (*fTypeConversionSetup)(TypeConversion * conversion, const ChannelType * fromType, const ChannelType * toType); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 4d4ce08..72361a4 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -172,8 +172,10 @@ static ChannelInData * ChannelInDataCreate(ChannelInData * data) { if (!data->typeConversions) { return NULL; } - - data->unitConversion = NULL; + data->unitConversions = (ObjectContainer *) object_create(ObjectContainer); + if (!data->unitConversions) { + return NULL; + } data->linearConversion = NULL; data->rangeConversion = NULL; @@ -182,14 +184,16 @@ static ChannelInData * ChannelInDataCreate(ChannelInData * data) { return data; } +// TODO fix Create and Destructor to properly free memory in case of failure + static void ChannelInDataDestructor(ChannelInData * data) { // clean up conversion objects data->typeConversions->DestroyObjects(data->typeConversions); object_destroy(data->typeConversions); - if (data->unitConversion) { - object_destroy(data->unitConversion); - } + data->unitConversions->DestroyObjects(data->unitConversions); + object_destroy(data->unitConversions); + if (data->linearConversion) { object_destroy(data->linearConversion); } @@ -273,6 +277,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); ConnectionInfo * connInfo = &conn->info; TypeConversion * typeConv = (TypeConversion *) in->data->typeConversions->At(in->data->typeConversions, i); + UnitConversion * unitConv = (UnitConversion *) in->data->unitConversions->At(in->data->unitConversions, i); ChannelValueRef * valueRef = (ChannelValueRef *) in->data->valueReferences->At(in->data->valueReferences, i); /* Update the connection for the current time */ @@ -284,6 +289,14 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), typeConv)) { return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "ChannelValueRefSetFromReference failed"); } + + // unit conversion + if (unitConv) { + retVal = unitConv->ConvertValueReference(unitConv, valueRef); + if (RETURN_OK != retVal) { + return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "Unit conversion failed"); + } + } } @@ -292,17 +305,6 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { 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; - } - } - - // linear if (in->data->linearConversion) { Conversion * conversion = (Conversion *) in->data->linearConversion; @@ -439,17 +441,26 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec retVal = in->data->valueReferences->PushBack(in->data->valueReferences, (Object *) valRef); // TODO check retVal - if (ChannelTypeEq(inInfo->type, &ChannelTypeDouble)) { - in->data->unitConversion = (UnitConversion *) object_create(UnitConversion); - retVal = in->data->unitConversion->Setup(in->data->unitConversion, - unit, - inInfo->unitString); + if (ChannelTypeEq(ChannelTypeBaseType(inInfo->type), &ChannelTypeDouble)) { + UnitConversion * conversion = (UnitConversion *) object_create(UnitConversion); + + retVal = conversion->Setup(conversion, unit, inInfo->unitString); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up unit conversion"); } - if (in->data->unitConversion->IsEmpty(in->data->unitConversion)) { - object_destroy(in->data->unitConversion); + if (conversion->IsEmpty(conversion)) { + object_destroy(conversion); + } + + retVal = in->data->unitConversions->PushBack(in->data->unitConversions, (Object *) conversion); + if (RETURN_ERROR == retVal) { + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add unit conversion"); + } + } else { + retVal = in->data->unitConversions->PushBack(in->data->unitConversions, NULL); + if (RETURN_ERROR == retVal) { + return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add empty unit conversion"); } } diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 1b42ef4..b408d94 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -161,6 +161,40 @@ int ChannelDimensionIncludedIn(const ChannelDimension* first, const ChannelDimen return TRUE; } +size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes) { + switch (dimension->num) { + case 1: + { + size_t idx = dimension->startIdxs[0] + elem_idx; + if (idx > dimension->endIdxs[0]) { + mcx_log(LOG_ERROR, "ChannelDimensionGetIndex: Index out of range"); + break; + } + + return idx; + } + case 2: + { + size_t dim_1_slice_size = dimension->endIdxs[1] - dimension->startIdxs[1] + 1; + + size_t slice_idx_0 = elem_idx / dim_1_slice_size + dimension->startIdxs[0]; + size_t slice_idx_1 = elem_idx % dim_1_slice_size + dimension->startIdxs[1]; + + if (slice_idx_0 > dimension->endIdxs[0] || slice_idx_1 > dimension->endIdxs[1]) { + mcx_log(LOG_ERROR, "ChannelDimensionGetIndex: Index out of range"); + break; + } + + return slice_idx_0 * sizes[1] + slice_idx_1; + } + default: + mcx_log(LOG_ERROR, "ChannelDimensionGetIndex: Number of dimensions not supported (%d)", dimension->num); + break; + } + + return (size_t) -1; +} + char * ChannelDimensionString(const ChannelDimension * dimension) { char * str = NULL; size_t length = 0; diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 555bb6a..0a245b5 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -35,6 +35,7 @@ size_t ChannelDimensionNumElements(ChannelDimension * dimension); ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); +size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes); char * ChannelDimensionString(const ChannelDimension * dimension); McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension * base); ChannelType * ChannelDimensionToChannelType(ChannelDimension * dimension, ChannelType * sourceType); diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 4e23412..02072f3 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -398,6 +398,18 @@ McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * eleme return RETURN_OK; } +void * mcx_array_get_elem_reference(mcx_array * a, size_t idx) { + size_t num_elems = mcx_array_num_elements(a); + char * data = (char *) a->data; + + if (idx >= num_elems) { + mcx_log(LOG_ERROR, "mcx_array_get_elem_reference: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); + return RETURN_ERROR; + } + + return data + idx * ChannelValueTypeSize(a->type); +} + void ChannelValueInit(ChannelValue * value, ChannelType * type) { value->type = type; ChannelValueDataInit(&value->value, type); diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 53fe10b..784f93e 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -113,6 +113,8 @@ McxStatus mcx_array_map(mcx_array * a, mcx_array_map_f_ptr fn, void * ctx); McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element); McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element); +void * mcx_array_get_elem_reference(mcx_array * a, size_t idx); + typedef int (*mcx_array_predicate_f_ptr)(void * element, ChannelType * type); int mcx_array_all(mcx_array * a, mcx_array_predicate_f_ptr predicate); int mcx_array_leq(const mcx_array * left, const mcx_array * right); diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 9aa1165..9b9d5a9 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -52,6 +52,54 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re return RETURN_OK; } +McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx) { + switch (ref->type) { + case CHANNEL_VALUE_REF_VALUE: + if (ChannelTypeIsArray(ref->ref.value->type)) { + size_t i = 0; + + for (i = 0; i < mcx_array_num_elements(&ref->ref.value->value.a); i++) { + void * elem = mcx_array_get_elem_reference(&ref->ref.value->value.a, i); + if (!elem) { + return RETURN_ERROR; + } + + if (RETURN_ERROR == fn(elem, ChannelValueType(ref->ref.value), ctx)) { + return RETURN_ERROR; + } + } + + return RETURN_OK; + } else { + return fn(ChannelValueReference(ref->ref.value), ChannelValueType(ref->ref.value), ctx); + } + case CHANNEL_VALUE_REF_SLICE: + if (ChannelTypeIsArray(ref->ref.slice->ref->type)) { + size_t i = 0; + + for (i = 0; i < ChannelDimensionNumElements(ref->ref.slice->dimension); i++) { + size_t idx = ChannelDimensionGetIndex(ref->ref.slice->dimension, i, ref->ref.slice->ref->value.a.dims); + + void * elem = mcx_array_get_elem_reference(&ref->ref.slice->ref->value.a, idx); + if (!elem) { + return RETURN_ERROR; + } + + if (RETURN_ERROR == fn(elem, ChannelValueType(ref->ref.slice->ref), ctx)) { + return RETURN_ERROR; + } + } + + return RETURN_OK; + } else { + return fn(ChannelValueReference(ref->ref.slice->ref), ChannelValueType(ref->ref.slice->ref), ctx); + } + default: + mcx_log(LOG_ERROR, "ChannelValueRefElemMap: Invalid internal channel value reference type (%d)", ref->type); + return RETURN_ERROR; + } +} + ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { switch (ref->type) { case CHANNEL_VALUE_REF_VALUE: diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index fc9d164..d48e30e 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -48,6 +48,9 @@ typedef struct ChannelValueRef { McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, TypeConversion * typeConv); ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); +typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, ChannelType * type, void * ctx); +McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx); + #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index f0aca73..e594a78 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -36,7 +36,7 @@ typedef struct ChannelInData { // Conversions ObjectContainer * typeConversions; // conversion objects (or NULL) for each connection in `connections` - struct UnitConversion * unitConversion; + ObjectContainer * unitConversions; // conversion objects (or NULL) for each connection in `connections` struct LinearConversion * linearConversion; struct RangeConversion * rangeConversion; From 588461c6e3a3b61632a39133c9966bbffb618fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 11 Nov 2021 12:26:55 +0100 Subject: [PATCH 203/295] Fix log message --- src/core/Conversion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 3d43ac8..5abbaa4 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -665,7 +665,7 @@ static McxStatus CheckTypesValidForConversion(ChannelType * destType, if (!ChannelTypeEq(destType, expectedDestType)) { mcx_log(LOG_ERROR, "Type conversion: Destination value has wrong type %s, expected: %s", - ChannelTypeToString(ChannelValueType(destType)), + ChannelTypeToString(destType), ChannelTypeToString(expectedDestType)); return RETURN_ERROR; } From 9b8f42e2c51b275bdee670daac04e478fcd779f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 11 Nov 2021 14:58:18 +0100 Subject: [PATCH 204/295] Implement ChannelValueRefSetFromReference --- src/core/channels/ChannelValueReference.c | 116 ++++++++++++++++++++-- src/core/channels/ChannelValueReference.h | 3 +- 2 files changed, 107 insertions(+), 12 deletions(-) diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 9b9d5a9..875c09a 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -30,23 +30,117 @@ ChannelValueRef * ChannelValueRefCreate(ChannelValueRef * ref) { OBJECT_CLASS(ChannelValueRef, Object); -McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, TypeConversion * conv) { +McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * conv) { + if (conv) { + return conv->Convert(conv, ref, reference); + } + if (ref->type == CHANNEL_VALUE_REF_VALUE) { - if (conv) { - return conv->Convert(conv, ref, reference); - } + if (ChannelTypeIsArray(ref->ref.value->type)) { + mcx_array * destArray = &ref->ref.value->value.a; + mcx_array * srcArray = (mcx_array *) reference; - return ChannelValueDataSetFromReference(&ref->ref.value->value, ref->ref.value->type, reference); - } else { - // slice + if (srcArray->data == NULL || destArray->data == NULL) { + mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Empty array data given"); + return RETURN_ERROR; + } - // TODO + if (srcArray->numDims == 1) { + // if there is only one dimension, values are sequentially stored in memory so we can use memcpy + // we could also check if for numDims > 1, values are sequentially stored or not, but there is no + // need for that now + size_t numBytes = ChannelValueTypeSize(destArray->type) * mcx_array_num_elements(destArray); + size_t srcOffset = srcDimension != 0 ? srcDimension->startIdxs[0] * ChannelValueTypeSize(srcArray->type) : 0; + void * sourceData = (char *) srcArray->data + srcOffset; - if (conv) { - return conv->Convert(conv, ref, reference); + memcpy(destArray->data, sourceData, numBytes); + } else { + // copy element by element + size_t i = 0; + size_t numElems = srcDimension ? ChannelDimensionNumElements(srcDimension) : mcx_array_num_elements(destArray); + + for (i = 0; i < numElems; i++) { + size_t srcIdx = srcDimension ? ChannelDimensionGetIndex(srcDimension, i, srcArray->dims) : i; + void * srcElem = mcx_array_get_elem_reference(srcArray, srcIdx); + void * destElem = mcx_array_get_elem_reference(destArray, i); + memcpy(destElem, srcElem, ChannelValueTypeSize(destArray->type)); + } + } + + return RETURN_OK; + } else { + if (srcDimension) { + mcx_array * src = (mcx_array *) (reference); + + if (ChannelDimensionNumElements(srcDimension) != 1) { + mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Setting scalar value from an array"); + return RETURN_ERROR; + } + + return ChannelValueDataSetFromReference( + &ref->ref.value->value, + ref->ref.value->type, + mcx_array_get_elem_reference(src, ChannelDimensionGetIndex(srcDimension, 0, src->dims))); + } else { + return ChannelValueDataSetFromReference(&ref->ref.value->value, ref->ref.value->type, reference); + } } + } else { + if (ChannelTypeIsArray(ref->ref.slice->ref->type)) { + mcx_array * destArray = &ref->ref.slice->ref->value.a; + mcx_array * srcArray = (mcx_array *) reference; - return ChannelValueDataSetFromReference(&ref->ref.slice->ref, ref->ref.value->type, reference); + ChannelDimension * destDimension = ref->ref.slice->dimension; + + if (srcArray->data == NULL || destArray->data == NULL) { + mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Empty array data given"); + return RETURN_ERROR; + } + + if (srcArray->numDims == 1) { + // if there is only one dimension, values are sequentially stored in memory so we can use memcpy + // we could also check if for numDims > 1, values are sequentially stored or not, but there is no + // need for that now + size_t numBytes = ChannelValueTypeSize(destArray->type) * (destDimension->endIdxs[0] - destDimension->startIdxs[0] + 1); + size_t destOffset = destDimension->startIdxs[0] * ChannelValueTypeSize(destArray->type); + void * destData = (char *) destArray->data + destOffset; + size_t srcOffset = srcDimension != 0 ? srcDimension->startIdxs[0] * ChannelValueTypeSize(srcArray->type) : 0; + void * sourceData = (char *) srcArray->data + srcOffset; + + memcpy(destData, sourceData, numBytes); + } else { + // copy element by element + size_t i = 0; + size_t numElems = srcDimension ? ChannelDimensionNumElements(srcDimension) : mcx_array_num_elements(destArray); + + for (i = 0; i < numElems; i++) { + size_t srcIdx = srcDimension ? ChannelDimensionGetIndex(srcDimension, i, srcArray->dims) : i; + size_t destIdx = ChannelDimensionGetIndex(destDimension, i, destArray->dims); + + void * srcElem = mcx_array_get_elem_reference(srcArray, srcIdx); + void * destElem = mcx_array_get_elem_reference(destArray, destIdx); + memcpy(destElem, srcElem, ChannelValueTypeSize(destArray->type)); + } + } + + return RETURN_OK; + } else { + if (srcDimension) { + mcx_array * src = (mcx_array *) (reference); + + if (ChannelDimensionNumElements(srcDimension) != 1) { + mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Setting scalar value from an array"); + return RETURN_ERROR; + } + + return ChannelValueDataSetFromReference( + &ref->ref.slice->ref->value, + ref->ref.slice->ref->type, + mcx_array_get_elem_reference(src, ChannelDimensionGetIndex(srcDimension, 0, src->dims))); + } else { + return ChannelValueDataSetFromReference(&ref->ref.slice->ref->value, ref->ref.slice->ref->type, reference); + } + } } return RETURN_OK; diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index d48e30e..a9b2a2f 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -45,7 +45,8 @@ typedef struct ChannelValueRef { } ref; } ChannelValueRef; -McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, TypeConversion * typeConv); +McxStatus +ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * typeConv); ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, ChannelType * type, void * ctx); From 8e9946e468d45ed14f50b23a838f2dcc84bb9b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 11 Nov 2021 14:58:54 +0100 Subject: [PATCH 205/295] Add a function to check whether dimensions are conformable (same sizes) --- src/core/channels/ChannelDimension.c | 22 ++++++++++++++++++++++ src/core/channels/ChannelDimension.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index b408d94..c3443bf 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -135,6 +135,28 @@ int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second) { return TRUE; } +int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * second) { + size_t i = 0; + + if (!first && !second) { + return TRUE; + } else if (!first || !second) { + return FALSE; + } + + if (first->num != second->num) { + return FALSE; + } + + for (i = 0; i < first->num; i++) { + if (first->endIdxs[i] - first->startIdxs[i] != second->endIdxs[i] - second->startIdxs[i]) { + return FALSE; + } + } + + return TRUE; +} + int ChannelDimensionIncludedIn(const ChannelDimension* first, const ChannelDimension* second) { size_t i = 0; diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 0a245b5..3bf5f69 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -34,6 +34,7 @@ ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); size_t ChannelDimensionNumElements(ChannelDimension * dimension); ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); +int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * second); int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes); char * ChannelDimensionString(const ChannelDimension * dimension); From c177617ee45e1203450c14d9524b2f8b5cfb22bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:25:57 +0100 Subject: [PATCH 206/295] Add ChannelDimensionsConform --- src/core/channels/ChannelDimension.c | 15 +++++++++++++++ src/core/channels/ChannelDimension.h | 1 + 2 files changed, 16 insertions(+) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index c3443bf..cfb31a0 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -157,6 +157,21 @@ int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * sec return TRUE; } +int ChannelDimensionsConform(ChannelDimension * dimension, size_t * dims, size_t numDims) { + size_t i = 0; + if (dimension->num != numDims) { + return 0; + } + + for (i = 0; i < numDims; i++) { + if (dims[i] != (dimension->endIdxs[i] - dimension->startIdxs[i] + 1)) { + return 0; + } + } + + return 1; +} + int ChannelDimensionIncludedIn(const ChannelDimension* first, const ChannelDimension* second) { size_t i = 0; diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 3bf5f69..ae5681d 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -35,6 +35,7 @@ size_t ChannelDimensionNumElements(ChannelDimension * dimension); ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * second); +int ChannelDimensionsConform(ChannelDimension * dimension, size_t * dims, size_t numDims); int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes); char * ChannelDimensionString(const ChannelDimension * dimension); From 4417a44abde2fafd7db91b9299f4219495a80f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:26:19 +0100 Subject: [PATCH 207/295] Add ChannelDimensionGetSliceIndex --- src/core/channels/ChannelDimension.c | 32 ++++++++++++++++++++++++++++ src/core/channels/ChannelDimension.h | 1 + 2 files changed, 33 insertions(+) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index cfb31a0..8064fd2 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -232,6 +232,38 @@ size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, s return (size_t) -1; } +size_t ChannelDimensionGetSliceIndex(ChannelDimension * dimension, size_t slice_idx, size_t * dims) { + switch (dimension->num) { + case 1: + { + size_t idx = slice_idx - dimension->startIdxs[0]; + if (idx > dimension->endIdxs[0]) { + mcx_log(LOG_ERROR, "ChannelDimensionGetSliceIndex: Index out of range"); + break; + } + + return idx; + } + case 2: + { + size_t idx_0 = slice_idx / dims[1]; + size_t idx_1 = slice_idx - idx_0 * dims[1]; + + size_t slice_idx_0 = idx_0 - dimension->startIdxs[0]; + size_t slice_idx_1 = idx_1 - dimension->startIdxs[1]; + + size_t dim_1_slice_size = dimension->endIdxs[1] - dimension->startIdxs[1] + 1; + + return slice_idx_0 * dim_1_slice_size * slice_idx_1; + } + default: + mcx_log(LOG_ERROR, "ChannelDimensionGetSliceIndex: Number of dimensions not supported (%d)", dimension->num); + break; + } + + return (size_t) -1; +} + char * ChannelDimensionString(const ChannelDimension * dimension) { char * str = NULL; size_t length = 0; diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index ae5681d..9f9da44 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -38,6 +38,7 @@ int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * sec int ChannelDimensionsConform(ChannelDimension * dimension, size_t * dims, size_t numDims); int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes); +size_t ChannelDimensionGetSliceIndex(ChannelDimension * dimension, size_t slice_idx, size_t * dims); char * ChannelDimensionString(const ChannelDimension * dimension); McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension * base); ChannelType * ChannelDimensionToChannelType(ChannelDimension * dimension, ChannelType * sourceType); From ead2a514bece738c3f4b56bfb69e597761255938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:27:11 +0100 Subject: [PATCH 208/295] Add Type and Dimension getters for Connection value reference --- src/core/Conversion.c | 2 +- src/core/channels/Channel.c | 2 +- src/core/connections/Connection.c | 15 +++++++++++++++ src/core/connections/Connection.h | 6 ++++++ src/core/connections/FilteredConnection.c | 6 ++++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 5abbaa4..d5e1d78 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -815,7 +815,7 @@ static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, } static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValueRef * dest, void * src) { - return ChannelValueRefSetFromReference(dest, src, NULL); + return ChannelValueRefSetFromReference(dest, src, NULL, NULL); } static McxStatus TypeConversionSetup(TypeConversion * conversion, diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 72361a4..d2fb896 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -286,7 +286,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { } // TODO: ideally make conn->GetValueReference return ChannelValueRef - if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), typeConv)) { + if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), conn->GetValueDimension(conn), typeConv)) { return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "ChannelValueRefSetFromReference failed"); } diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 8923fc1..e0f9d48 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1081,6 +1081,19 @@ static void ConnectionSetValueReference(Connection * connection, void * referenc connection->value_ = reference; } +static ChannelDimension * ConnectionGetValueDimension(Connection * connection) { + return NULL; +} + +static ChannelType * ConnectionGetValueType(Connection * connection) { + ChannelOut * out = connection->out_; + Channel * channel = (Channel *) out; + ChannelInfo * channelInfo = &channel->info; + + return channelInfo->type; +} + + static void ConnectionDestructor(Connection * connection) { ChannelValueDestructor(&connection->store_); } @@ -1366,6 +1379,8 @@ static Connection * ConnectionCreate(Connection * connection) { connection->GetValueReference = ConnectionGetValueReference; connection->SetValueReference = ConnectionSetValueReference; + connection->GetValueDimension = ConnectionGetValueDimension; + connection->GetValueType = ConnectionGetValueType; connection->GetInfo = ConnectionGetInfo; diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h index 94d720f..ed2222b 100644 --- a/src/core/connections/Connection.h +++ b/src/core/connections/Connection.h @@ -51,6 +51,8 @@ typedef struct ChannelIn * (* fConnectionGetTarget)(Connection * connection); typedef void * (* fConnectionGetValueReference)(Connection * connection); typedef void (* fConnectionSetValueReference)(Connection * connection, void * reference); +typedef ChannelDimension * (*fConnectionGetValueDimension)(Connection * connection); +typedef ChannelType * (*fConnectionGetValueType)(Connection * connection); typedef ConnectionInfo * (* fConnectionGetInfo)(Connection * connection); @@ -132,6 +134,10 @@ struct Connection { */ fConnectionGetValueReference GetValueReference; + fConnectionGetValueDimension GetValueDimension; + + fConnectionGetValueType GetValueType; + /** * Set the reference to the value of the connection. This value will be * updated on each call to UpdateToOutput(). diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 5901d6f..46aa490 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -372,6 +372,11 @@ static McxStatus AddFilter(Connection * connection) { return RETURN_OK; } +static ChannelType * FilteredConnectionGetValueType(Connection * connection) { + FilteredConnection * filteredConnection = (FilteredConnection *) connection; + return filteredConnection->data->store.type; +} + static void FilteredConnectionDestructor(FilteredConnection * filteredConnection) { object_destroy(filteredConnection->data); } @@ -387,6 +392,7 @@ static FilteredConnection * FilteredConnectionCreate(FilteredConnection * filter connection->EnterCouplingStepMode = FilteredConnectionEnterCouplingStepMode; connection->AddFilter = AddFilter; + connection->GetValueType = FilteredConnectionGetValueType; filteredConnection->GetReadFilter = FilteredConnectionGetFilter; filteredConnection->GetWriteFilter = FilteredConnectionGetFilter; From b5bea2a12072b4a8898ea485fbcaffb3b3c3a0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:28:45 +0100 Subject: [PATCH 209/295] Extend arguments of fChannelValueRefElemMapFunc --- src/core/Conversion.c | 2 +- src/core/channels/ChannelValueReference.c | 8 ++++---- src/core/channels/ChannelValueReference.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index d5e1d78..5754fd5 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -346,7 +346,7 @@ static McxStatus UnitConversionConvert(Conversion * conversion, ChannelValue * v return RETURN_OK; } -McxStatus UnitConversionValueRefConversion(void * element, ChannelType * type, void * ctx) { +McxStatus UnitConversionValueRefConversion(void * element, size_t idx, ChannelType * type, void * ctx) { double * elem = (double *) element; UnitConversion * conversion = (UnitConversion *) ctx; diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 875c09a..ac0a5d3 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -158,14 +158,14 @@ McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapF return RETURN_ERROR; } - if (RETURN_ERROR == fn(elem, ChannelValueType(ref->ref.value), ctx)) { + if (RETURN_ERROR == fn(elem, i, ChannelValueType(ref->ref.value), ctx)) { return RETURN_ERROR; } } return RETURN_OK; } else { - return fn(ChannelValueReference(ref->ref.value), ChannelValueType(ref->ref.value), ctx); + return fn(ChannelValueReference(ref->ref.value), 0, ChannelValueType(ref->ref.value), ctx); } case CHANNEL_VALUE_REF_SLICE: if (ChannelTypeIsArray(ref->ref.slice->ref->type)) { @@ -179,14 +179,14 @@ McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapF return RETURN_ERROR; } - if (RETURN_ERROR == fn(elem, ChannelValueType(ref->ref.slice->ref), ctx)) { + if (RETURN_ERROR == fn(elem, idx, ChannelValueType(ref->ref.slice->ref), ctx)) { return RETURN_ERROR; } } return RETURN_OK; } else { - return fn(ChannelValueReference(ref->ref.slice->ref), ChannelValueType(ref->ref.slice->ref), ctx); + return fn(ChannelValueReference(ref->ref.slice->ref), 0, ChannelValueType(ref->ref.slice->ref), ctx); } default: mcx_log(LOG_ERROR, "ChannelValueRefElemMap: Invalid internal channel value reference type (%d)", ref->type); diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index a9b2a2f..87e5ba4 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -49,7 +49,7 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * typeConv); ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); -typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, ChannelType * type, void * ctx); +typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, size_t idx, ChannelType * type, void * ctx); McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx); From c0baed100518b61788c185a18a1e09227410c12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:30:31 +0100 Subject: [PATCH 210/295] Implement ChannelValueRefGetType --- src/core/channels/ChannelValueReference.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index ac0a5d3..9984d9f 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -199,8 +199,8 @@ ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { case CHANNEL_VALUE_REF_VALUE: return ChannelValueType(ref->ref.value); case CHANNEL_VALUE_REF_SLICE: - mcx_log(LOG_ERROR, "TODO - change the dimension in ArraySlice to a type and return that to avoid memory allocation"); - return NULL; + // TODO (do we need to adapt the indices wrt. dimension) ? + return ChannelValueType(ref->ref.slice->ref); default: mcx_log(LOG_ERROR, "Invalid internal channel value reference type (%d)", ref->type); return NULL; From 64fbbb3c4cae428a14c5a2caa245f111d266a497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:31:33 +0100 Subject: [PATCH 211/295] Compare inner types in ChannelTypeEq as well --- src/core/channels/ChannelValue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 02072f3..3f1bfce 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -174,6 +174,7 @@ int ChannelTypeEq(ChannelType * a, ChannelType * b) { return 0; } } + return a->ty.a.inner == b->ty.a.inner; return 1; } else { return a->con == b->con; From caa252b798df6e35728720b72178c562684795b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:31:59 +0100 Subject: [PATCH 212/295] Fix return value of mcx_array_get_elem_reference --- src/core/channels/ChannelValue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 3f1bfce..4b1a23b 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -405,7 +405,7 @@ void * mcx_array_get_elem_reference(mcx_array * a, size_t idx) { if (idx >= num_elems) { mcx_log(LOG_ERROR, "mcx_array_get_elem_reference: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); - return RETURN_ERROR; + return NULL; } return data + idx * ChannelValueTypeSize(a->type); From 36241d200cdbe3520f156ddffe0c58bbc3c8aea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:32:21 +0100 Subject: [PATCH 213/295] Define ChannelTypeConformable --- src/core/channels/ChannelValue.c | 21 +++++++++++++++++++++ src/core/channels/ChannelValue.h | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 4b1a23b..f3d87d1 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -9,6 +9,7 @@ ********************************************************************************/ #include "core/channels/ChannelValue.h" +#include "core/channels/ChannelDimension.h" #include "util/stdlib.h" #ifdef __cplusplus @@ -163,6 +164,26 @@ size_t ChannelTypeNumElements(const ChannelType * type) { } } +int ChannelTypeConformable(ChannelType * a, ChannelDimension * sliceA, ChannelType * b, ChannelDimension * sliceB) { + if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { + if (sliceA && sliceB) { + return a->ty.a.inner == b->ty.a.inner && ChannelDimensionConformable(sliceA, sliceB); + } else if (sliceA && !sliceB) { + return a->ty.a.inner == b->ty.a.inner && ChannelDimensionsConform(sliceA, b->ty.a.dims, b->ty.a.numDims); + } else if (!sliceA && sliceB) { + return a->ty.a.inner == b->ty.a.inner && ChannelDimensionsConform(sliceB, a->ty.a.dims, a->ty.a.numDims); + } else { + return ChannelTypeEq(a, b); + } + } else { + if (sliceA || sliceB) { + return 0; + } + + return a->con == b->con; + } +} + int ChannelTypeEq(ChannelType * a, ChannelType * b) { if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { size_t i = 0; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 784f93e..05e9529 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -18,6 +18,9 @@ extern "C" { #endif /* __cplusplus */ + +typedef struct ChannelDimension ChannelDimension; + char * CreateIndexedName(const char * name, unsigned i); // possible types of values that can be put on channels @@ -70,6 +73,7 @@ size_t ChannelTypeNumElements(const ChannelType * type); ChannelType * ChannelTypeBaseType(ChannelType * a); int ChannelTypeEq(ChannelType * a, ChannelType * b); +int ChannelTypeConformable(ChannelType * a, ChannelDimension * sliceA, ChannelType * b, ChannelDimension * sliceB); typedef struct MapStringChannelType { const char * key; From 267895becaf8f62252437b65b4feb68bb3bdd9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 12 Nov 2021 14:33:05 +0100 Subject: [PATCH 214/295] Adapt TypeConversion to arrays --- src/core/Conversion.c | 495 +++++++++++++++++++++++++++++- src/core/Conversion.h | 9 +- src/core/channels/Channel.c | 18 +- src/core/connections/Connection.c | 2 +- 4 files changed, 502 insertions(+), 22 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 5754fd5..be83f8a 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -641,7 +641,7 @@ McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue conv = (Conversion *) typeConv; - retVal = typeConv->Setup(typeConv, fromType, toType); + retVal = typeConv->Setup(typeConv, fromType, NULL, toType, NULL); if (retVal == RETURN_ERROR) { mcx_log(LOG_ERROR, "ConvertType: Conversion setup failed"); goto cleanup; @@ -699,6 +699,37 @@ static McxStatus CheckArrayReferencingOnlyOneElement(ChannelValueRef * dest, Cha return RETURN_OK; } +static McxStatus ArraysValidForConversion(ChannelValueRef * dest, + ChannelType * expectedDestType, + mcx_array * src, + ChannelDimension * srcDimension) { + if (!ChannelTypeIsArray(ChannelValueRefGetType(dest))) { + mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array"); + return RETURN_ERROR; + } + + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelTypeBaseType(ChannelValueRefGetType(dest)), expectedDestType)) { + return RETURN_ERROR; + } + + // check dimensions match + if (srcDimension) { + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + return ChannelDimensionsConform(srcDimension, dest->ref.value->type->ty.a.dims, dest->ref.value->type->ty.a.numDims) ? RETURN_OK : RETURN_ERROR; + } else { + return ChannelDimensionConformable(dest->ref.slice->dimension, srcDimension) ? RETURN_OK : RETURN_ERROR; + } + } else { + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + return mcx_array_dims_match(&dest->ref.value->value.a, src) ? RETURN_OK : RETURN_ERROR; + } else { + return ChannelDimensionsConform(dest->ref.slice->dimension, src->dims, src->numDims) ? RETURN_OK : RETURN_ERROR; + } + } + + return RETURN_OK; +} + static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; @@ -759,12 +790,128 @@ static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, Chann return RETURN_OK; } -static McxStatus TypeConversionConvertSingletonDoubleToDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayDoubleToDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } - dest->ref.value->value.d = *(double *) ((mcx_array*)src)->data; + if (conversion->sourceSlice) { + dest->ref.value->value.d = *((double *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]); + } else { + dest->ref.value->value.d = *(double *) ((mcx_array *) src)->data; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayIntegerToDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.d = (double) *((int *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]); + } else { + dest->ref.value->value.d = (double) *(int *) ((mcx_array *) src)->data; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayBoolToDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.d = *((int *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]) != 0 ? 1. : 0.; + } else { + dest->ref.value->value.d = *(int *) ((mcx_array *) src)->data != 0 ? 1. : 0.; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayDoubleToInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.i = (int) floor(*((double *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]) + 0.5); + } else { + dest->ref.value->value.i = (int) floor(*(double *) ((mcx_array *) src)->data + 0.5); + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayIntegerToInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.i = *((int *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]); + } else { + dest->ref.value->value.i = *(int *) ((mcx_array *) src)->data; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayBoolToInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.i = *((int *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]) != 0 ? 1 : 0; + } else { + dest->ref.value->value.i = *(int *) ((mcx_array *) src)->data != 0 ? 1 : 0; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayDoubleToBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.i = *((double *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]) > 0 ? 1 : 0; + } else { + dest->ref.value->value.i = *(double *) ((mcx_array *) src)->data > 0 ? 1 : 0; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayIntegerToBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.i = *((int *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]) != 0 ? 1 : 0; + } else { + dest->ref.value->value.i = *(int *) ((mcx_array *) src)->data != 0 ? 1 : 0; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayBoolToBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { + return RETURN_ERROR; + } + + if (conversion->sourceSlice) { + dest->ref.value->value.i = *((int *) ((mcx_array *) src)->data + conversion->sourceSlice->startIdxs[0]); + } else { + dest->ref.value->value.i = *(int *) ((mcx_array *) src)->data; + } return RETURN_OK; } @@ -814,15 +961,296 @@ static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, return RETURN_OK; } -static McxStatus TypeConversionConvertId(Conversion * conversion, ChannelValueRef * dest, void * src) { - return ChannelValueRefSetFromReference(dest, src, NULL, NULL); +static McxStatus TypeConversionConvertDoubleToArrayInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeInteger)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(int *) dest->ref.value->value.a.data = (int) floor(*((double *) src) + 0.5); + } else { + int * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = (int) floor(*((double *) src) + 0.5); + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertIntegerToArrayInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeInteger)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(int *) dest->ref.value->value.a.data = *(int *) src; + } else { + int * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *(int *) src; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertBoolToArrayInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeInteger)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(int *) dest->ref.value->value.a.data = *((int *) src) != 0 ? 1 : 0; + } else { + int * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *((int *) src) != 0 ? 1 : 0; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertDoubleToArrayBool(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeBool)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(int *) dest->ref.value->value.a.data = *((double *) src) > 0 ? 1 : 0; + } else { + int * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *((double *) src) > 0 ? 1 : 0; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertIntegerToArrayBool(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeBool)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(int *) dest->ref.value->value.a.data = *((int *) src) != 0 ? 1 : 0; + } else { + int * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *((int *) src) != 0 ? 1 : 0; + } + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertBoolToArrayBool(Conversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeBool)) { + return RETURN_ERROR; + } + + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + *(int *) dest->ref.value->value.a.data = *(int *) src; + } else { + int * data = dest->ref.slice->ref->value.a.data; + *(data + dest->ref.slice->dimension->startIdxs[0]) = *(int *) src; + } + + return RETURN_OK; +} + +static size_t IndexOfElemInSrcArray(size_t dest_idx, mcx_array * src_array, ChannelDimension * src_dim, ChannelValueRef * dest) { + if (src_dim) { + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + return ChannelDimensionGetIndex(src_dim, dest_idx, src_array->dims); + } else { + size_t idx = ChannelDimensionGetSliceIndex(dest->ref.slice->dimension, dest_idx, dest->ref.slice->ref->type->ty.a.dims); + return ChannelDimensionGetIndex(src_dim, idx, src_array->dims); + } + } else { + if (dest->type == CHANNEL_VALUE_REF_VALUE) { + return dest_idx; + } else { + return ChannelDimensionGetSliceIndex(dest->ref.slice->dimension, dest_idx, dest->ref.slice->ref->type->ty.a.dims); + } + } +} + +typedef struct Array2ArrayCtx { + mcx_array * src_array; + ChannelDimension * src_dim; + ChannelValueRef * dest; +} Array2ArrayCtx; + +static McxStatus IntegerArrayToDouble(void * element, size_t idx, ChannelType * type, void * ctx) { + Array2ArrayCtx * context = (Array2ArrayCtx *) ctx; + size_t i = IndexOfElemInSrcArray(idx, context->src_array, context->src_dim, context->dest); + void * src_elem = mcx_array_get_elem_reference(context->src_array, i); + + if (!src_elem) { + return RETURN_ERROR; + } + + *(double *) element = (double) *((int *) src_elem); + + return RETURN_OK; +} + +static McxStatus BoolArrayToDouble(void * element, size_t idx, ChannelType * type, void * ctx) { + Array2ArrayCtx * context = (Array2ArrayCtx *) ctx; + size_t i = IndexOfElemInSrcArray(idx, context->src_array, context->src_dim, context->dest); + void * src_elem = mcx_array_get_elem_reference(context->src_array, i); + + if (!src_elem) { + return RETURN_ERROR; + } + + *(double *) element = *((int *) src_elem) != 0 ? 1. : 0.; + + return RETURN_OK; +} + +static McxStatus BoolArrayToInteger(void * element, size_t idx, ChannelType * type, void * ctx) { + Array2ArrayCtx * context = (Array2ArrayCtx *) ctx; + size_t i = IndexOfElemInSrcArray(idx, context->src_array, context->src_dim, context->dest); + void * src_elem = mcx_array_get_elem_reference(context->src_array, i); + + if (!src_elem) { + return RETURN_ERROR; + } + + *(int *) element = *((int *) src_elem) != 0 ? 1 : 0; + + return RETURN_OK; +} + +static McxStatus DoubleArrayToInteger(void * element, size_t idx, ChannelType * type, void * ctx) { + Array2ArrayCtx * context = (Array2ArrayCtx *) ctx; + size_t i = IndexOfElemInSrcArray(idx, context->src_array, context->src_dim, context->dest); + void * src_elem = mcx_array_get_elem_reference(context->src_array, i); + + if (!src_elem) { + return RETURN_ERROR; + } + + *(int *) element = (int) floor(*((double *) src_elem) + 0.5); + + return RETURN_OK; +} + +static McxStatus DoubleArrayToBool(void * element, size_t idx, ChannelType * type, void * ctx) { + Array2ArrayCtx * context = (Array2ArrayCtx *) ctx; + size_t i = IndexOfElemInSrcArray(idx, context->src_array, context->src_dim, context->dest); + void * src_elem = mcx_array_get_elem_reference(context->src_array, i); + + if (!src_elem) { + return RETURN_ERROR; + } + + *(int *) element = *((double *) src_elem) > 0 ? 1 : 0; + + return RETURN_OK; +} + +static McxStatus IntegerArrayToBool(void * element, size_t idx, ChannelType * type, void * ctx) { + Array2ArrayCtx * context = (Array2ArrayCtx *) ctx; + size_t i = IndexOfElemInSrcArray(idx, context->src_array, context->src_dim, context->dest); + void * src_elem = mcx_array_get_elem_reference(context->src_array, i); + + if (!src_elem) { + return RETURN_ERROR; + } + + *(int *) element = *((int *) src_elem) != 0 ? 1 : 0; + + return RETURN_OK; +} + +static McxStatus TypeConversionConvertArrayIntegerToArrayDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeDouble, (mcx_array *) src, conversion->sourceSlice)) { + return RETURN_ERROR; + } + + Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; + return ChannelValueRefElemMap(dest, IntegerArrayToDouble, &ctx); +} + +static McxStatus TypeConversionConvertArrayBoolToArrayDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeDouble, (mcx_array *) src, conversion->sourceSlice)) { + return RETURN_ERROR; + } + + Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; + return ChannelValueRefElemMap(dest, BoolArrayToDouble, &ctx); +} + +static McxStatus TypeConversionConvertArrayDoubleToArrayInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeInteger, (mcx_array *) src, conversion->sourceSlice)) { + return RETURN_ERROR; + } + + Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; + return ChannelValueRefElemMap(dest, DoubleArrayToInteger, &ctx); +} + +static McxStatus TypeConversionConvertArrayBoolToArrayInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeInteger, (mcx_array *) src, conversion->sourceSlice)) { + return RETURN_ERROR; + } + + Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; + return ChannelValueRefElemMap(dest, BoolArrayToInteger, &ctx); +} + +static McxStatus TypeConversionConvertArrayDoubleToArrayBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeBool, (mcx_array *) src, conversion->sourceSlice)) { + return RETURN_ERROR; + } + + Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; + return ChannelValueRefElemMap(dest, DoubleArrayToBool, &ctx); +} + +static McxStatus TypeConversionConvertArrayIntegerToArrayBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeBool, (mcx_array *) src, conversion->sourceSlice)) { + return RETURN_ERROR; + } + + Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; + return ChannelValueRefElemMap(dest, IntegerArrayToBool, &ctx); +} + +static McxStatus TypeConversionConvertId(TypeConversion * conversion, ChannelValueRef * dest, void * src) { + return ChannelValueRefSetFromReference(dest, src, conversion->sourceSlice, NULL); +} + +static int DimensionsMatch(ChannelType * fromType, ChannelDimension * fromDimension, ChannelType * toType, ChannelDimension * toDimension) { + if (fromDimension) { + if (!toDimension) { + return ChannelDimensionsConform(fromDimension, toType->ty.a.dims, toType->ty.a.numDims); + } else { + return ChannelDimensionConformable(toDimension, fromDimension); + } + } else { + if (!toDimension) { + size_t i = 0; + if (fromType->ty.a.numDims != toType->ty.a.numDims) { + return 0; + } + + for (i = 0; i < fromType->ty.a.numDims; i++) { + if (fromType->ty.a.dims[i] != toType->ty.a.dims[i]) { + return 0; + } + } + + return 1; + } else { + return ChannelDimensionsConform(toDimension, fromType->ty.a.dims, fromType->ty.a.numDims); + } + } } static McxStatus TypeConversionSetup(TypeConversion * conversion, ChannelType * fromType, - ChannelType * toType) { + ChannelDimension * fromDimension, + ChannelType * toType, + ChannelDimension * toDimension) { + conversion->sourceSlice = fromDimension; - if (ChannelTypeEq(fromType, toType)) { + if (ChannelTypeConformable(fromType, fromDimension, toType, toDimension)) { conversion->Convert = TypeConversionConvertId; /* scalar <-> scalar */ } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeDouble)) { @@ -839,13 +1267,64 @@ static McxStatus TypeConversionSetup(TypeConversion * conversion, conversion->Convert = TypeConversionConvertIntegerBool; /* scalar <-> array */ } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeDouble)) { - conversion->Convert = TypeConversionConvertSingletonDoubleToDouble; + conversion->Convert = TypeConversionConvertArrayDoubleToDouble; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertArrayIntegerToDouble; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertArrayBoolToDouble; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertArrayDoubleToBool; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertArrayIntegerToBool; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertArrayBoolToBool; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeDouble) && ChannelTypeEq(toType, &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertArrayDoubleToInteger; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeInteger) && ChannelTypeEq(toType, &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertArrayIntegerToInteger; + } else if (ChannelTypeIsArray(fromType) && ChannelTypeEq(fromType->ty.a.inner, &ChannelTypeBool) && ChannelTypeEq(toType, &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertArrayBoolToInteger; } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeDouble)) { conversion->Convert = TypeConversionConvertDoubleToArrayDouble; } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeDouble)) { conversion->Convert = TypeConversionConvertIntegerToArrayDouble; } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeDouble)) { conversion->Convert = TypeConversionConvertBoolToArrayDouble; + } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertDoubleToArrayInteger; + } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertIntegerToArrayInteger; + } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertBoolToArrayInteger; + } else if (ChannelTypeEq(fromType, &ChannelTypeDouble) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertDoubleToArrayBool; + } else if (ChannelTypeEq(fromType, &ChannelTypeInteger) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertIntegerToArrayBool; + } else if (ChannelTypeEq(fromType, &ChannelTypeBool) && ChannelTypeIsArray(toType) && ChannelTypeEq(toType->ty.a.inner, &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertBoolToArrayBool; + /* array <-> array */ + } else if (ChannelTypeIsArray(fromType) && ChannelTypeIsArray(toType)) { + if (!DimensionsMatch(fromType, fromDimension, toType, toDimension)) { + mcx_log(LOG_ERROR, "Setup type conversion: Array dimensions do not match"); + return RETURN_ERROR; + } + + if (ChannelTypeEq(ChannelTypeBaseType(fromType), &ChannelTypeInteger) && ChannelTypeEq(ChannelTypeBaseType(toType), &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertArrayIntegerToArrayDouble; + } else if (ChannelTypeEq(ChannelTypeBaseType(fromType), &ChannelTypeBool) && ChannelTypeEq(ChannelTypeBaseType(toType), &ChannelTypeDouble)) { + conversion->Convert = TypeConversionConvertArrayBoolToArrayDouble; + } else if (ChannelTypeEq(ChannelTypeBaseType(fromType), &ChannelTypeDouble) && ChannelTypeEq(ChannelTypeBaseType(toType), &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertArrayDoubleToArrayInteger; + } else if (ChannelTypeEq(ChannelTypeBaseType(fromType), &ChannelTypeBool) && ChannelTypeEq(ChannelTypeBaseType(toType), &ChannelTypeInteger)) { + conversion->Convert = TypeConversionConvertArrayBoolToArrayInteger; + } else if (ChannelTypeEq(ChannelTypeBaseType(fromType), &ChannelTypeDouble) && ChannelTypeEq(ChannelTypeBaseType(toType), &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertArrayDoubleToArrayBool; + } else if (ChannelTypeEq(ChannelTypeBaseType(fromType), &ChannelTypeInteger) && ChannelTypeEq(ChannelTypeBaseType(toType), &ChannelTypeBool)) { + conversion->Convert = TypeConversionConvertArrayIntegerToArrayBool; + } else { + mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion between array types selected"); + return RETURN_ERROR; + } } else { mcx_log(LOG_ERROR, "Setup type conversion: Illegal conversion selected"); return RETURN_ERROR; diff --git a/src/core/Conversion.h b/src/core/Conversion.h index 7aa9b78..7ac4c34 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -12,6 +12,7 @@ #define MCX_CORE_CONVERSION_H #include "units/Units.h" +#include "core/channels/ChannelDimension.h" #ifdef __cplusplus @@ -119,7 +120,11 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal // Type Conversion typedef struct TypeConversion TypeConversion; -typedef McxStatus (*fTypeConversionSetup)(TypeConversion * conversion, const ChannelType * fromType, const ChannelType * toType); +typedef McxStatus (*fTypeConversionSetup)(TypeConversion * conversion, + const ChannelType * fromType, + ChannelDimension * fromDimension, + const ChannelType * toType, + ChannelDimension * toDimension); // TODO: Ideally the `src` argument would also be ChannelValueRef, but that requires quite of lot of changes // in the API of databus definition (i.e. DatabusSetIn(Out)Reference) @@ -132,6 +137,8 @@ struct TypeConversion { fTypeConversionSetup Setup; fTypeConversionConvert Convert; + + ChannelDimension * sourceSlice; }; McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue * value); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index d2fb896..53b7d05 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -464,22 +464,18 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec } } - // TODO - array // setup type conversion - - ChannelType * connType = ChannelDimensionToChannelType(connInfo->sourceDimension, type); - if (!connType) { - return RETURN_ERROR; - } - - if (!ChannelTypeEq(inInfo->type, type)) { + if (!ChannelTypeConformable(inInfo->type, inInfo->dimension, connection->GetValueType(connection), connection->GetValueDimension(connection))) { TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); - retVal = typeConv->Setup(typeConv, connType, inInfo->type); + retVal = typeConv->Setup(typeConv, + connection->GetValueType(connection), + connection->GetValueDimension(connection), + inInfo->type, + connInfo->targetDimension); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up type conversion"); } - retVal = in->data->typeConversions->PushBack(in->data->typeConversions, (Object *) typeConv); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add type conversion"); @@ -491,8 +487,6 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec } } - ChannelTypeDestructor(connType); - return retVal; } diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index e0f9d48..53c0186 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1177,7 +1177,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { if (!ChannelTypeEq(inValue->type, store->type)) { TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); Conversion * conv = (Conversion *) typeConv; - retVal = typeConv->Setup(typeConv, inValue->type, store->type); + retVal = typeConv->Setup(typeConv, inValue->type, NULL, store->type, NULL); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Could not set up initial type conversion"); object_destroy(typeConv); From 7f93f351f08b65fc683fbf5cb8bf75f1c6133e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 15 Nov 2021 15:28:51 +0100 Subject: [PATCH 215/295] Take into account arrays in dependency matrix creation --- src/components/comp_fmu.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 6ffe7c7..fae5e06 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -1241,13 +1241,30 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps if (processed_out_channels->Get(processed_out_channels, i) == NULL) { Fmu2Value *val = (Fmu2Value *)out_vars->At(out_vars, i); - if (fmi2_import_get_initial(val->data->data.scalar) != fmi2_initial_enu_exact) { - for (k = 0; k < num_in_channels; ++k) { - SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, k); - if (elem) { - ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup; + if (val->data->type == FMU2_VALUE_ARRAY) { + size_t elem_idx = 0; + for (elem_idx = 0; elem_idx < val->data->data.array.numDims; elem_idx++) { + if (fmi2_import_get_initial(val->data->data.array.values[elem_idx]) != fmi2_initial_enu_exact) { + for (k = 0; k < num_in_channels; ++k) { + SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, k); + if (elem) { + ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } + } + } + } + } + } else { + if (fmi2_import_get_initial(val->data->data.scalar) != fmi2_initial_enu_exact) { + for (k = 0; k < num_in_channels; ++k) { + SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, k); + if (elem) { + ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } } } } From ec18455a8e387e367b004781845e86413315a050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 15 Nov 2021 15:36:31 +0100 Subject: [PATCH 216/295] Change connection->data->store to the size of the input slice --- src/core/channels/ChannelValue.c | 25 +++++ src/core/channels/ChannelValue.h | 2 + src/core/connections/Connection.c | 118 ++++++++++++++++------ src/core/connections/FilteredConnection.c | 28 +---- 4 files changed, 116 insertions(+), 57 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index f3d87d1..218059a 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -432,6 +432,31 @@ void * mcx_array_get_elem_reference(mcx_array * a, size_t idx) { return data + idx * ChannelValueTypeSize(a->type); } +ChannelType * ChannelTypeFromDimension(ChannelType * base_type, ChannelDimension * dimension) { + if (dimension) { + // source data is an array + size_t i = 0; + ChannelType * type = NULL; + size_t * dims = (size_t *) mcx_calloc(sizeof(size_t), dimension->num); + + if (!dims) { + mcx_log(LOG_ERROR, "DetermineSliceType: Not enough memory for dimension calculation"); + return NULL; + } + + for (i = 0; i < dimension->num; i++) { + dims[i] = dimension->endIdxs[i] - dimension->startIdxs[i] + 1; // indices are inclusive + } + + type = ChannelTypeArray(ChannelTypeClone(ChannelTypeBaseType(base_type)), dimension->num, dims); + mcx_free(dims); + return type; + } else { + // source data is a scalar + return ChannelTypeClone(base_type); + } +} + void ChannelValueInit(ChannelValue * value, ChannelType * type) { value->type = type; ChannelValueDataInit(&value->value, type); diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 05e9529..ff908e2 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -70,6 +70,8 @@ int ChannelTypeIsBinary(const ChannelType * a); size_t ChannelTypeNumElements(const ChannelType * type); +ChannelType * ChannelTypeFromDimension(ChannelType * base_type, ChannelDimension * dimension); + ChannelType * ChannelTypeBaseType(ChannelType * a); int ChannelTypeEq(ChannelType * a, ChannelType * b); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 53c0186..ec6f4e9 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -12,6 +12,7 @@ #include "core/connections/Connection.h" #include "core/channels/Channel.h" #include "core/channels/ChannelInfo.h" +#include "core/channels/ChannelValueReference.h" #include "core/connections/ConnectionInfo.h" #include "core/Conversion.h" @@ -1145,6 +1146,10 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { ChannelInfo * inInfo = &in->info; ChannelInfo * outInfo = &out->info; + ChannelValueRef * storeRef = NULL; + + McxStatus retVal = RETURN_OK; + 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); @@ -1159,52 +1164,76 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { return RETURN_ERROR; } + storeRef = (ChannelValueRef *) object_create(ChannelValueRef); + if (!storeRef) { + mcx_log(LOG_ERROR, "Could not create store reference for initial connection"); + return RETURN_ERROR; + } + storeRef->type = CHANNEL_VALUE_REF_VALUE; + storeRef->ref.value = &connection->store_; + if (inInfo->initialValue) { - McxStatus retVal = RETURN_OK; - ChannelValue * store = &connection->store_; + TypeConversion * typeConv = NULL; ChannelValue * inChannelValue = inInfo->initialValue; - ChannelValue * inValue = ChannelValueClone(inChannelValue); + ChannelDimension * srcDim = NULL; - if (NULL == inValue) { - mcx_log(LOG_ERROR, "Could not clone initial value for initial connection"); - return RETURN_ERROR; + srcDim = ChannelDimensionClone(info->targetDimension); + if (srcDim) { + mcx_log(LOG_ERROR, "Could not clone source dimension"); + retVal = RETURN_ERROR; + goto cleanup_1; + } + retVal = ChannelDimensionNormalize(srcDim, inInfo->dimension); + if (retVal == RETURN_ERROR) { + mcx_log(LOG_ERROR, "Dimension normalization failed"); + goto cleanup_1; } // The type of the stored value of a connection is the type of the out channel. // If the value is taken from the in channel, the value must be converted. // TODO: It might be a better idea to use the type of the in channel as type of the connection. // Such a change might be more complex to implement. - if (!ChannelTypeEq(inValue->type, store->type)) { - TypeConversion * typeConv = (TypeConversion *) object_create(TypeConversion); - Conversion * conv = (Conversion *) typeConv; - retVal = typeConv->Setup(typeConv, inValue->type, NULL, store->type, NULL); + if (!ChannelTypeConformable(storeRef->ref.value->type, NULL, inChannelValue->type, srcDim)) { + typeConv = (TypeConversion *) object_create(TypeConversion); + retVal = typeConv->Setup(typeConv, inChannelValue->type, info->targetDimension, storeRef->ref.value->type, NULL); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Could not set up initial type conversion"); - object_destroy(typeConv); - mcx_free(inValue); - return RETURN_ERROR; - } - retVal = conv->convert(conv, inValue); - object_destroy(typeConv); - - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Could not convert type of initial value"); - mcx_free(inValue); - return RETURN_ERROR; + retVal = RETURN_ERROR; + goto cleanup_1; } } - retVal = ChannelValueSet(store, inValue); + retVal = ChannelValueRefSetFromReference(storeRef, ChannelValueReference(inChannelValue), srcDim, typeConv); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Could not set up initial value in connection"); - mcx_free(inValue); - return RETURN_ERROR; + goto cleanup_1; } - mcx_free(inValue); connection->useInitialValue_ = TRUE; + +cleanup_1: + object_destroy(typeConv); + object_destroy(srcDim); + + if (retVal == RETURN_ERROR) { + goto cleanup; + } } else if (outInfo->initialValue) { - ChannelValueSet(&connection->store_, outInfo->initialValue); + ChannelDimension * targetDim = ChannelDimensionClone(info->sourceDimension); + if (targetDim) { + mcx_log(LOG_ERROR, "Could not clone target dimension"); + retVal = RETURN_ERROR; + goto cleanup; + } + + retVal = ChannelDimensionNormalize(targetDim, outInfo->dimension); + if (retVal == RETURN_ERROR) { + mcx_log(LOG_ERROR, "Dimension normalization failed"); + object_destroy(targetDim); + goto cleanup; + } + + ChannelValueRefSetFromReference(storeRef, outInfo->initialValue, targetDim, NULL); connection->useInitialValue_ = TRUE; } else { { @@ -1212,10 +1241,21 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { mcx_log(LOG_WARNING, "Connection %s: No initial values are specified for the ports of the connection", buffer); mcx_free(buffer); } - ChannelValueInit(&connection->store_, ChannelTypeClone(ConnectionInfoGetType(info))); + + ChannelType * storeType = ChannelTypeFromDimension(info->connType_, info->sourceDimension); + if (!storeType) { + mcx_log(LOG_ERROR, "Creating type from the dimension failed"); + retVal = RETURN_ERROR; + goto cleanup; + } + + ChannelValueInit(&connection->store_, storeType); } - return RETURN_OK; +cleanup: + object_destroy(storeRef); + + return retVal; } static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * time) { @@ -1231,6 +1271,7 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim static McxStatus ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) { Channel * channel = (Channel *) connection->out_; + ChannelInfo * info = &channel->info; #ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME) { @@ -1240,7 +1281,18 @@ static McxStatus ConnectionInitUpdateTo(Connection * connection, TimeInterval * #endif if (!connection->useInitialValue_) { - if (RETURN_OK != ChannelValueSetFromReference(&connection->store_, channel->GetValueReference(channel))) { + ChannelValueRef * storeRef = (ChannelValueRef *) object_create(ChannelValueRef); + if (!storeRef) { + mcx_log(LOG_ERROR, "Could not create store reference for initial connection"); + return RETURN_ERROR; + } + storeRef->type = CHANNEL_VALUE_REF_VALUE; + storeRef->ref.value = &connection->store_; + + ConnectionInfo * connInfo = connection->GetInfo(connection); + ChannelDimension * clone = ChannelDimensionClone(connInfo->sourceDimension); + ChannelDimensionNormalize(clone, info->dimension); + if (RETURN_OK != ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL)) { return RETURN_ERROR; } if (channel->IsDefinedDuringInit(channel)) { @@ -1337,6 +1389,7 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * Channel * chOut = (Channel *) out; ChannelInfo * outInfo = &chOut->info; + ChannelType * storeType = NULL; connection->out_ = out; connection->in_ = in; @@ -1347,7 +1400,12 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * connection->info = *info; - ChannelValueInit(&connection->store_, ChannelTypeClone(outInfo->type)); + storeType = ChannelTypeFromDimension(outInfo->type, info->sourceDimension); + if (!storeType) { + return RETURN_ERROR; + } + + ChannelValueInit(&connection->store_, storeType); // Add connection to channel out retVal = out->RegisterConnection(out, connection); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 46aa490..9693dd5 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -46,32 +46,6 @@ static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { OBJECT_CLASS(FilteredConnectionData, Object); -static ChannelType * SliceDimensionToType(ChannelType * sourceType, ChannelDimension * dimension) { - if (dimension) { - // source data is an array - size_t i = 0; - ChannelType * type = NULL; - size_t * dims = (size_t *) mcx_calloc(sizeof(size_t), dimension->num); - - if (!dims) { - mcx_log(LOG_ERROR, "DetermineSliceType: Not enough memory for dimension calculation"); - return NULL; - } - - for (i = 0; i < dimension->num; i++) { - dims[i] = dimension->endIdxs[i] - dimension->startIdxs[i] + 1; // indices are inclusive - } - - type = ChannelTypeArray(ChannelTypeClone(ChannelTypeBaseType(sourceType)), dimension->num, dims); - mcx_free(dims); - return type; - } else { - // source data is a scalar - return ChannelTypeClone(sourceType); - } -} - - static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * in, ConnectionInfo * info) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; @@ -92,7 +66,7 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o filteredConnection->data->filters = NULL; filteredConnection->data->numFilters = 0; - storeType = SliceDimensionToType(sourceInfo->type, info->sourceDimension); + storeType = ChannelTypeFromDimension(sourceInfo->type, info->sourceDimension); if (!storeType) { return RETURN_ERROR; } From edcc8d4c64c393fe299e817bb408de8d30a165f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 19 Nov 2021 13:15:04 +0100 Subject: [PATCH 217/295] Support array channels in FMU 1 --- src/components/comp_fmu.c | 50 +++----- src/fmu/Fmu1Value.c | 261 +++++++++++++++++++++++++++++++++++--- src/fmu/Fmu1Value.h | 52 +++++++- src/fmu/common_fmu1.c | 92 ++++++++++---- 4 files changed, 379 insertions(+), 76 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index fae5e06..a0495d0 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -51,6 +51,8 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { vals = fmu1->in; for (i = 0; i < numChannels; i++) { ChannelInfo * info = DatabusInfoGetChannel(dbInfo, i); + ChannelDimension * dimension = info->dimension; + ChannelType * type = info->type; if (DatabusChannelInIsValid(db, i)) { Fmu1Value * val = NULL; @@ -63,33 +65,24 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { channelName = ChannelInfoGetName(info); } - var = fmi1_import_get_variable_by_name(fmu1->fmiImport, channelName); - if (!var) { - ComponentLog(comp, LOG_ERROR, "Could not get variable %s", channelName); - return RETURN_ERROR; - } - - if (!ChannelTypeEq(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->type), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))); - return RETURN_ERROR; + if (dimension) { // arrays + val = Fmu1ValueReadArray(comp->GetName(comp), type, info->channel, channelName, dimension, fmu1->fmiImport); + } else { // scalars + val = Fmu1ValueReadScalar(comp->GetName(comp), type, info->channel, channelName, fmu1->fmiImport); } - val = Fmu1ValueMake(channelName, var, info->channel); if (!val) { - ComponentLog(comp, LOG_ERROR, "Could not set value for channel %s", channelName); + ComponentLog(comp, LOG_ERROR, "Could not create value for channel %s", channelName); return RETURN_ERROR; } - retVal = vals->PushBackNamed(vals, (Object *)val, channelName); + retVal = vals->PushBackNamed(vals, (Object *) val, channelName); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not store value for %s", channelName); return RETURN_ERROR; } - retVal = DatabusSetInReference(comp->GetDatabus(comp), i, ChannelValueReference(&val->val), - ChannelValueType(&val->val)); + retVal = DatabusSetInReference(db, i, ChannelValueReference(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not set reference for channel %s", channelName); return RETURN_ERROR; @@ -102,6 +95,8 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { vals = fmu1->out; for (i = 0; i < numChannels; i++) { ChannelInfo * info = DatabusInfoGetChannel(dbInfo, i); + ChannelDimension * dimension = info->dimension; + ChannelType * type = info->type; Fmu1Value * val = NULL; fmi1_import_variable_t * var = NULL; @@ -112,33 +107,24 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { channelName = ChannelInfoGetName(info); } - var = fmi1_import_get_variable_by_name(fmu1->fmiImport, channelName); - if (!var) { - ComponentLog(comp, LOG_ERROR, "Could not get variable %s", channelName); - return RETURN_ERROR; - } - - if (!ChannelTypeEq(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->type), ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))); - return RETURN_ERROR; + if (dimension) { // arrays + val = Fmu1ValueReadArray(comp->GetName(comp), type, info->channel, channelName, dimension, fmu1->fmiImport); + } else { // scalars + val = Fmu1ValueReadScalar(comp->GetName(comp), type, info->channel, channelName, fmu1->fmiImport); } - val = Fmu1ValueMake(channelName, var, NULL); if (!val) { - ComponentLog(comp, LOG_ERROR, "Could not set value for channel %s", channelName); + ComponentLog(comp, LOG_ERROR, "Could not create value for channel %s", channelName); return RETURN_ERROR; } - retVal = vals->PushBack(vals, (Object *)val); + retVal = vals->PushBackNamed(vals, (Object *) val, channelName); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not store value for %s", channelName); return RETURN_ERROR; } - retVal = DatabusSetOutReference(comp->GetDatabus(comp), i, ChannelValueReference(&val->val), - ChannelValueType(&val->val)); + retVal = DatabusSetOutReference(db, i, ChannelValueReference(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not set reference for channel %s", channelName); return RETURN_ERROR; diff --git a/src/fmu/Fmu1Value.c b/src/fmu/Fmu1Value.c index 6800ce0..7f2818a 100644 --- a/src/fmu/Fmu1Value.c +++ b/src/fmu/Fmu1Value.c @@ -13,29 +13,178 @@ #include "fmu/common_fmu1.h" #include "util/string.h" +#include "util/stdlib.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ + +static void Fmu1ValueDataDestructor(Fmu1ValueData * data) { + if (data->type == FMU1_VALUE_ARRAY) { + if (data->var.array.dims) { + mcx_free(data->var.array.dims); + } + if (data->var.array.values) { + mcx_free(data->var.array.values); + } + data->var.array.numDims = 0; + + if (data->vr.array.values) { + mcx_free(data->vr.array.values); + } + } + + data->type = FMU1_VALUE_INVALID; +} + +static Fmu1ValueData * Fmu1ValueDataCreate(Fmu1ValueData * data) { + memset(data, 0, sizeof(Fmu1ValueData)); + + data->type = FMU1_VALUE_INVALID; + + return data; +} + +OBJECT_CLASS(Fmu1ValueData, Object); + + +size_t Fmu1ValueDataArrayNumElems(const Fmu1ValueData * data) { + size_t i = 0; + size_t num = 1; + + if (data->type != FMU1_VALUE_ARRAY) { + return 0; + } + + for (i = 0; i < data->var.array.numDims; i++) { + num *= data->var.array.dims[i]; + } + + return num; +} + + +static Fmu1ValueData * Fmu1ValueDataScalarMake(fmi1_import_variable_t * scalar) { + Fmu1ValueData * data = NULL; + + if (!scalar) { + return NULL; + } + + data = (Fmu1ValueData *) object_create(Fmu1ValueData); + if (data) { + data->type = FMU1_VALUE_SCALAR; + data->var.scalar = scalar; + data->vr.scalar = fmi1_import_get_variable_vr(scalar); + } + + return data; +} + +static Fmu1ValueData * Fmu1ValueDataArrayMake(size_t numDims, size_t dims[], fmi1_import_variable_t ** values) { + Fmu1ValueData * data = NULL; + + if (numDims == 0) { + return NULL; + } + + data = (Fmu1ValueData *) object_create(Fmu1ValueData); + if (data) { + size_t i = 0; + size_t num = 1; + + for (i = 0; i < numDims; i++) { + num *= dims[i]; + } + + data->type = FMU1_VALUE_ARRAY; + + data->var.array.numDims = numDims; + data->var.array.dims = mcx_copy(dims, sizeof(size_t) * numDims); + if (!data->var.array.dims) { + goto cleanup; + } + + data->var.array.values = mcx_copy(values, sizeof(fmi1_import_variable_t *) * num); + if (!data->var.array.values) { + goto cleanup; + } + + data->vr.array.values = mcx_calloc(num, sizeof(fmi1_value_reference_t)); + if (!data->vr.array.values) { + goto cleanup; + } + + for (i = 0; i < num; i++) { + data->vr.array.values[i] = fmi2_import_get_variable_vr(data->var.array.values[i]); + } + } + return data; + +cleanup: + object_destroy(data); + return NULL; +} + + static McxStatus Fmu1ValueSetFromChannelValue(Fmu1Value * v, ChannelValue * val) { return ChannelValueSet(&v->val, val); } +static McxStatus Fmu1ValueSetup(Fmu1Value * value, const char * name, Fmu1ValueData * data, Channel * channel) { + if (!name || !data) { + mcx_log(LOG_ERROR, "Fmu1Value: Setup failed: Name or data missing"); + return RETURN_ERROR; + } + + value->name = mcx_string_copy(name); + value->data = data; + value->channel = channel; + + if (!value->name) { + mcx_log(LOG_ERROR, "Fmu1Value: Setup failed: Can not copy name"); + return RETURN_ERROR; + } + + switch (data->type) { + case FMU1_VALUE_SCALAR: + { + fmi1_base_type_enu_t t = fmi1_import_get_variable_base_type(data->var.scalar); + ChannelValueInit(&value->val, ChannelTypeClone(Fmi1TypeToChannelType(t))); + break; + } + case FMU1_VALUE_ARRAY: + { + fmi1_base_type_enu_t t = fmi1_import_get_variable_base_type(data->var.array.values[0]); + ChannelValueInit(&value->val, ChannelTypeArray(Fmi1TypeToChannelType(t), data->var.array.numDims, data->var.array.dims)); + break; + } + default: + mcx_log(LOG_ERROR, "Fmu1Value: Setup failed: Invalid data type"); + return RETURN_ERROR; + } + + return RETURN_OK; +} + void Fmu1ValueDestructor(Fmu1Value * v) { if (v->name) { mcx_free(v->name); v->name = NULL; } + object_destroy(v->data); + ChannelValueDestructor(&v->val); } Fmu1Value * Fmu1ValueCreate(Fmu1Value * v) { v->SetFromChannelValue = Fmu1ValueSetFromChannelValue; + v->Setup = Fmu1ValueSetup; v->name = NULL; - v->var = NULL; + v->data = NULL; v->channel = NULL; ChannelValueInit(&v->val, ChannelTypeClone(&ChannelTypeUnknown)); @@ -44,38 +193,114 @@ Fmu1Value * Fmu1ValueCreate(Fmu1Value * v) { OBJECT_CLASS(Fmu1Value, Object); -Fmu1Value * Fmu1ValueMake(const char * name, fmi1_import_variable_t * var, Channel * channel) { + +static Fmu1Value * Fmu1ValueMake(const char * name, Fmu1ValueData * data, Channel * channel) { Fmu1Value * value = (Fmu1Value *)object_create(Fmu1Value); if (value) { - McxStatus retVal = RETURN_OK; - fmi1_base_type_enu_t t; - - if (!name || !var) { - mcx_log(LOG_ERROR, "Fmu1Value: Setup failed: Name or data missing"); - mcx_free(value); + if (RETURN_OK != value->Setup(value, name, data, channel)) { + object_destroy(value); return NULL; } + } - value->channel = channel; + return value; +} - t = fmi1_import_get_variable_base_type(var); +Fmu1Value * Fmu1ValueScalarMake(const char * name, fmi1_import_variable_t * var, Channel * channel) { + Fmu1ValueData * data = Fmu1ValueDataScalarMake(var); + return Fmu1ValueMake(name, data, channel); +} - value->name = mcx_string_copy(name); - value->vr = fmi1_import_get_variable_vr(var); - value->var = var; - ChannelValueInit(&value->val, ChannelTypeClone(Fmi1TypeToChannelType(t))); +Fmu1Value * Fmu1ValueArrayMake(const char * name, size_t numDims, size_t * dims, fmi1_import_variable_t ** vars, Channel * channel) { + Fmu1ValueData * data = Fmu1ValueDataArrayMake(numDims, dims, vars); + return Fmu1ValueMake(name, data, channel); +} - if (!value->name) { - mcx_log(LOG_ERROR, "Fmu1Value: Setup failed: Cannot copy name"); - mcx_free(value); - return NULL; +Fmu1Value * Fmu1ValueReadScalar(const char * logPrefix, ChannelType * type, Channel * channel, const char * channelName, fmi1_import_t * fmiImport) { + Fmu1Value * value = NULL; + fmi1_import_variable_t * var = NULL; + + var = fmi1_import_get_variable_by_name(fmiImport, channelName); + if (!var) { + mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, channelName); + return NULL; + } + + if (!ChannelTypeEq(type, Fmi1TypeToChannelType(fmi1_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(type), + ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))); + return NULL; + } + + value = Fmu1ValueScalarMake(channelName, var, channel); + if (!value) { + mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + return RETURN_ERROR; + } + + return value; +} + +Fmu1Value * Fmu1ValueReadArray(const char * logPrefix, ChannelType * type, Channel * channel, const char * channelName, ChannelDimension * dimension, fmi1_import_t * fmiImport) { + Fmu1Value * value = NULL; + fmi1_import_variable_t * var = NULL; + + if (dimension->num > 1) { + mcx_log(LOG_ERROR, "%s: Port %s: Invalid dimension", logPrefix, channelName); + goto cleanup; + } + + size_t i = 0; + size_t startIdx = dimension->startIdxs[0]; + size_t endIdx = dimension->endIdxs[0]; + + fmi1_import_variable_t ** vars = mcx_calloc(endIdx - startIdx + 1, sizeof(fmi1_import_variable_t *)); + if (!vars) { + goto cleanup; + } + + for (i = startIdx; i <= endIdx; i++) { + char * indexedChannelName = CreateIndexedName(channelName, i); + fmi1_import_variable_t * var = fmi1_import_get_variable_by_name(fmiImport, indexedChannelName); + if (!var) { + mcx_log(LOG_ERROR, "%s: Could not get variable %s", logPrefix, indexedChannelName); + goto cleanup; + } + if (!ChannelTypeEq(ChannelTypeArrayInner(type), Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))) { + mcx_log(LOG_ERROR, "%s: Variable types of %s do not match", logPrefix, indexedChannelName); + mcx_log(LOG_ERROR, + "%s: Expected: %s, Imported from FMU: %s", + logPrefix, + ChannelTypeToString(ChannelTypeArrayInner(type)), + ChannelTypeToString(Fmi1TypeToChannelType(fmi1_import_get_variable_base_type(var)))); + goto cleanup; } + vars[i - startIdx] = var; + + mcx_free(indexedChannelName); + } + + size_t dims[] = {endIdx - startIdx + 1}; + value = Fmu1ValueArrayMake(channelName, 1 /* numDims */, dims, vars, channel); + if (!value) { + mcx_log(LOG_ERROR, "%s: Could not set value for channel %s", logPrefix, channelName); + goto cleanup; + } + +cleanup: + if (vars) { + mcx_free(vars); } return value; } + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/fmu/Fmu1Value.h b/src/fmu/Fmu1Value.h index 4fe99dd..3844657 100644 --- a/src/fmu/Fmu1Value.h +++ b/src/fmu/Fmu1Value.h @@ -19,11 +19,43 @@ extern "C" { #endif /* __cplusplus */ + +typedef enum Fmu1ValueType { + FMU1_VALUE_SCALAR, + FMU1_VALUE_ARRAY, + FMU1_VALUE_INVALID +} Fmu1ValueType; + +extern const struct ObjectClass _Fmu1ValueData; + +typedef struct Fmu1ValueData { + Object _; + + Fmu1ValueType type; + union { + fmi1_import_variable_t * scalar; + struct { + size_t numDims; + size_t * dims; + fmi1_import_variable_t ** values; + } array; + } var; + union { + fmi1_value_reference_t scalar; + struct { + fmi1_value_reference_t * values; + } array; + } vr; +} Fmu1ValueData; + +size_t Fmu1ValueDataArrayNumElems(const Fmu1ValueData * data); + struct Fmu1Value; typedef struct Fmu1Value Fmu1Value; typedef McxStatus(*fFmu1ValueSetFromChannelValue)(Fmu1Value * v, ChannelValue * val); +typedef McxStatus (*fFmu1ValueSetup)(Fmu1Value * value, const char * name, Fmu1ValueData * data, Channel * channel); extern const struct ObjectClass _Fmu1Value; @@ -31,16 +63,30 @@ struct Fmu1Value { Object _; /* base class */ fFmu1ValueSetFromChannelValue SetFromChannelValue; + fFmu1ValueSetup Setup; char * name; Channel * channel; - fmi1_value_reference_t vr; - fmi1_import_variable_t * var; + Fmu1ValueData * data; ChannelValue val; }; -Fmu1Value * Fmu1ValueMake(const char * name, fmi1_import_variable_t * var, Channel * channel); +Fmu1Value * Fmu1ValueScalarMake(const char * name, fmi1_import_variable_t * var, Channel * channel); +Fmu1Value * Fmu1ValueArrayMake(const char * name, size_t numDims, size_t * dims, fmi1_import_variable_t ** vars, Channel * channel); + +Fmu1Value * Fmu1ValueReadScalar(const char * logPrefix, + ChannelType * type, + Channel * channel, + const char * channelName, + fmi1_import_t * fmiImport); +Fmu1Value * Fmu1ValueReadArray(const char * logPrefix, + ChannelType * type, + Channel * channel, + const char * channelName, + ChannelDimension * dimension, + fmi1_import_t * fmiImport); + #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index ecdc12b..41582bd 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -292,7 +292,7 @@ Fmu1Value * Fmu1ReadParamValue(ScalarParameterInput * input, fmi1_import_t * imp return NULL; } - val = Fmu1ValueMake(input->name, var, NULL); + val = Fmu1ValueScalarMake(input->name, var, NULL); if (!val) { return NULL; } @@ -375,7 +375,7 @@ static ObjectContainer * Fmu1ReadArrayParamValues(const char * name, goto cleanup_1; } - val = Fmu1ValueMake(varName, var, NULL); + val = Fmu1ValueScalarMake(varName, var, NULL); if (!val) { retVal = RETURN_ERROR; goto cleanup_1; @@ -538,9 +538,6 @@ ObjectContainer * Fmu1ReadParams(ParametersInput * input, fmi1_import_t * import McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { fmi1_status_t status = fmi1_status_ok; - fmi1_import_variable_t * var = fmuVal->var; - fmi1_value_reference_t vr[] = { fmuVal->vr }; - Channel * channel = fmuVal->channel; if (channel && FALSE == channel->IsDefinedDuringInit(channel)) { MCX_DEBUG_LOG("Fmu1SetVariable: %s not set: no defined value during initialization", fmuVal->name); @@ -553,8 +550,9 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { switch (type->con) { case CHANNEL_DOUBLE: { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; double value = chVal->value.d; - if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { + if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { value *= -1.; } status = fmi1_import_set_real(fmu->fmiImport, vr, 1, &value); @@ -562,8 +560,9 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { break; case CHANNEL_INTEGER: { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; int value = chVal->value.i; - if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { + if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { value *= -1; } status = fmi1_import_set_integer(fmu->fmiImport, vr, 1, &value); @@ -571,16 +570,38 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { break; case CHANNEL_BOOL: { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; fmi1_boolean_t value = chVal->value.i; - if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { + if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { value = !value; } status = fmi1_import_set_boolean(fmu->fmiImport, vr, 1, &value); } break; case CHANNEL_STRING: + { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; status = fmi1_import_set_string(fmu->fmiImport, vr, 1, (fmi1_string_t *) &chVal->value.s); break; + } + case CHANNEL_ARRAY: + { + fmi1_value_reference_t * vrs = fmuVal->data->vr.array.values; + mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); + + size_t num = mcx_array_num_elements(a); + void * vals = a->data; + + if (ChannelTypeEq(a->type, &ChannelTypeDouble)) { + status = fmi1_import_set_real(fmu->fmiImport, vrs, num, vals); + } else if (ChannelTypeEq(a->type, &ChannelTypeInteger)) { + status = fmi1_import_set_integer(fmu->fmiImport, vrs, num, vals); + } else { + mcx_log(LOG_ERROR, "FMU: Unsupported array variable type: %s", ChannelTypeToString(a->type)); + return RETURN_ERROR; + } + break; + } default: mcx_log(LOG_WARNING, "FMU: Unknown variable type"); break; @@ -589,13 +610,13 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { if (fmi1_status_ok != status) { if (fmi1_status_error == status || fmi1_status_fatal == status) { fmu->runOk = fmi1_false; - mcx_log(LOG_ERROR, "FMU: Setting of variable %s (%d) failed", fmi1_import_get_variable_name(var), vr[0]); + mcx_log(LOG_ERROR, "FMU: Setting of variable %s failed", fmuVal->name); return RETURN_ERROR; } else { if (fmi1_status_warning == status) { - mcx_log(LOG_WARNING, "FMU: Setting of variable %s (%d) returned with a warning", fmi1_import_get_variable_name(var), vr[0]); + mcx_log(LOG_WARNING, "FMU: Setting of variable %s returned with a warning", fmuVal->name); } else if (fmi1_status_discard == status) { - mcx_log(LOG_WARNING, "FMU: Setting of variable %s (%d) discarded", fmi1_import_get_variable_name(var), vr[0]); + mcx_log(LOG_WARNING, "FMU: Setting of variable %s discarded", fmuVal->name); } } } else { @@ -628,33 +649,40 @@ McxStatus Fmu1SetVariableArray(Fmu1CommonStruct * fmu, ObjectContainer * vals) { McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { fmi1_status_t status = fmi1_status_ok; - fmi1_import_variable_t * var = fmuVal->var; - fmi1_value_reference_t vr[] = { fmuVal->vr }; - ChannelValue * const chVal = &fmuVal->val; ChannelType * type = ChannelValueType(chVal); switch (type->con) { case CHANNEL_DOUBLE: - status = fmi1_import_get_real(fmu->fmiImport, vr, 1, (fmi1_real_t *)ChannelValueReference(chVal)); - if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { + { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; + status = fmi1_import_get_real(fmu->fmiImport, vr, 1, (fmi1_real_t *) ChannelValueReference(chVal)); + if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { fmuVal->val.value.d *= -1.; } break; + } case CHANNEL_INTEGER: - status = fmi1_import_get_integer(fmu->fmiImport, vr, 1, (fmi1_integer_t *)ChannelValueReference(chVal)); - if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { + { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; + status = fmi1_import_get_integer(fmu->fmiImport, vr, 1, (fmi1_integer_t *) ChannelValueReference(chVal)); + if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { fmuVal->val.value.i *= -1; } break; + } case CHANNEL_BOOL: - status = fmi1_import_get_boolean(fmu->fmiImport, vr, 1, (fmi1_boolean_t *)ChannelValueReference(chVal)); - if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(var)) { + { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; + status = fmi1_import_get_boolean(fmu->fmiImport, vr, 1, (fmi1_boolean_t *) ChannelValueReference(chVal)); + if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { fmuVal->val.value.i = !fmuVal->val.value.i; } break; + } case CHANNEL_STRING: { + fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; char * buffer = NULL; status = fmi1_import_get_string(fmu->fmiImport, vr, 1, (fmi1_string_t *)&buffer); @@ -663,6 +691,24 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { } break; } + case CHANNEL_ARRAY: + { + fmi1_value_reference_t * vrs = fmuVal->data->vr.array.values; + mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); + + size_t num = mcx_array_num_elements(a); + void * vals = a->data; + + if (ChannelTypeEq(a->type, &ChannelTypeDouble)) { + status = fmi1_import_get_real(fmu->fmiImport, vrs, num, vals); + } else if (ChannelTypeEq(a->type, &ChannelTypeInteger)) { + status = fmi1_import_get_integer(fmu->fmiImport, vrs, num, vals); + } else { + mcx_log(LOG_ERROR, "FMU: Unsupported array variable type: %s", ChannelTypeToString(a->type)); + return RETURN_ERROR; + } + break; + } default: mcx_log(LOG_WARNING, "FMU: Unknown variable type"); break; @@ -671,7 +717,7 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { if (fmi1_status_ok != status) { if (fmi1_status_error == status || fmi1_status_fatal == status) { fmu->runOk = fmi1_false; - mcx_log(LOG_ERROR, "FMU: Getting of variable %s (%d) failed", fmi1_import_get_variable_name(var), vr[0]); + mcx_log(LOG_ERROR, "FMU: Getting of variable %s failed", fmuVal->name); return RETURN_ERROR; } else { // TODO: handle warning @@ -723,7 +769,7 @@ McxStatus fmi1CreateValuesOutOfVariables(ObjectContainer * vals, fmi1_import_var Fmu1Value * val = NULL; const char * name = fmi1_import_get_variable_name(actualVar); - val = Fmu1ValueMake(name, actualVar, NULL); + val = Fmu1ValueScalarMake(name, actualVar, NULL); retVal = vals->PushBack(vals, (Object *)val); if (RETURN_ERROR == retVal) { @@ -745,7 +791,7 @@ McxStatus fmi1AddLocalChannelsFromLocalValues(ObjectContainer * vals, const char for (i = 0; i < sizeList; i++) { Fmu1Value * val = (Fmu1Value *) vals->At(vals, i); - fmi1_import_variable_t * actualVar = val->var; + fmi1_import_variable_t * actualVar = val->data->var.scalar; // TODO array const char * name = NULL; fmi1_base_type_enu_t type; From f44dd6d0c2ad8342f78bd479f9f70305495fc681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 24 May 2022 07:32:52 +0200 Subject: [PATCH 218/295] Extend conversions to slices --- src/core/Conversion.c | 513 +++++++++++++++------- src/core/Conversion.h | 8 +- src/core/Model.c | 51 ++- src/core/channels/Channel.c | 4 +- src/core/channels/ChannelValueReference.c | 20 + src/core/channels/ChannelValueReference.h | 2 + 6 files changed, 419 insertions(+), 179 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index be83f8a..f601665 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -36,15 +36,158 @@ OBJECT_CLASS(Conversion, Object); // ---------------------------------------------------------------------- // Range Conversion +static int RangeConversionElemwiseLeq(void * first, void * second, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) first <= *(double *) second; + case CHANNEL_INTEGER: + return *(int *) first <= *(int *) second; + default: + return 0; + } +} + +static int RangeConversionElemwiseGeq(void * first, void * second, ChannelType * type) { + switch (type->con) { + case CHANNEL_DOUBLE: + return *(double *) first >= *(double *) second; + case CHANNEL_INTEGER: + return *(int *) first >= *(int *) second; + default: + return 0; + } +} + +static McxStatus RangeConversionConvert(Conversion * conversion, ChannelValue * value) { + RangeConversion * rangeConversion = (RangeConversion *) conversion; + McxStatus retVal = RETURN_OK; -McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * value) { + if (!ChannelTypeEq(ChannelValueType(value), rangeConversion->type)) { + mcx_log(LOG_ERROR, + "Range conversion: Value has wrong type %s, expected: %s", + ChannelTypeToString(ChannelValueType(value)), + ChannelTypeToString(rangeConversion->type)); + return RETURN_ERROR; + } + + if (rangeConversion->min) { + retVal = ChannelValueDataSetFromReferenceIfElemwisePred(&value->value, + value->type, + &rangeConversion->min->value, + RangeConversionElemwiseLeq); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Range conversion: Set value to min failed"); + return RETURN_ERROR; + } + } + + if (rangeConversion->max) { + retVal = ChannelValueDataSetFromReferenceIfElemwisePred(&value->value, + value->type, + &rangeConversion->max->value, + RangeConversionElemwiseGeq); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Range conversion: Set value to max failed"); + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + +McxStatus RangeConversionMinValueRefConversion(void * element, size_t idx, ChannelType * type, void * ctx) { + ChannelValue * min = (ChannelValue *) ctx; + void * minElem = mcx_array_get_elem_reference(&min->value.a, idx); + if (RangeConversionElemwiseLeq(element, minElem, type)) { + switch (type->con) + { + case CHANNEL_DOUBLE: + { + double * elem = (double *) element; + *elem = *((double *)minElem); + break; + } + case CHANNEL_INTEGER: + { + int * elem = (int *) element; + *elem = *((int *)minElem); + break; + } + default: + mcx_log(LOG_ERROR, "RangeConversion: Unsupported type"); + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + +McxStatus RangeConversionMaxValueRefConversion(void * element, size_t idx, ChannelType * type, void * ctx) { + ChannelValue * max = (ChannelValue *) ctx; + void * maxElem = mcx_array_get_elem_reference(&max->value.a, idx); + if (RangeConversionElemwiseGeq(element, maxElem, type)) { + switch (type->con) + { + case CHANNEL_DOUBLE: + { + double * elem = (double *) element; + *elem = *((double *)maxElem); + break; + } + case CHANNEL_INTEGER: + { + int * elem = (int *) element; + *elem = *((int *)maxElem); + break; + } + default: + mcx_log(LOG_ERROR, "RangeConversion: Unsupported type"); + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + +static McxStatus RangeConversionConvertValueRef(RangeConversion * conversion, ChannelValueRef * ref) { + RangeConversion * rangeConversion = (RangeConversion *) conversion; + McxStatus retVal = RETURN_OK; + + if (!ChannelTypeEq(ChannelValueRefGetType(ref), rangeConversion->type)) { + mcx_log(LOG_ERROR, + "Range conversion: Value has wrong type %s, expected: %s", + ChannelTypeToString(ChannelValueRefGetType(ref)), + ChannelTypeToString(rangeConversion->type)); + return RETURN_ERROR; + } + + if (rangeConversion->min) { + retVal = ChannelValueRefElemMap(ref, RangeConversionMinValueRefConversion, rangeConversion->min); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Range conversion: Set value to min failed"); + return RETURN_ERROR; + } + } + + if (rangeConversion->max) { + retVal = ChannelValueRefElemMap(ref, RangeConversionMaxValueRefConversion, rangeConversion->max); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Range conversion: Set value to max failed"); + return RETURN_ERROR; + } + } + + return RETURN_OK; +} + +McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * value, ChannelDimension * slice) { RangeConversion * rangeConv = NULL; ChannelValue * minToUse = NULL; ChannelValue * maxToUse = NULL; McxStatus retVal = RETURN_OK; - if (!ChannelTypeEq(value->type, &ChannelTypeDouble) && !ChannelTypeEq(value->type, &ChannelTypeInteger)) { + if (!ChannelTypeEq(ChannelTypeBaseType(value->type), &ChannelTypeDouble) && !ChannelTypeEq(ChannelTypeBaseType(value->type), &ChannelTypeInteger)) { return RETURN_OK; } @@ -82,9 +225,15 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va } if (rangeConv) { - Conversion * conversion = (Conversion *) rangeConv; - retVal = conversion->convert(conversion, value); - if (RETURN_OK != retVal) { + if (slice) { + ChannelValueRef * ref = MakeChannelValueRef(value, slice); + retVal = RangeConversionConvertValueRef(rangeConv, ref); + object_destroy(ref); + } else { + retVal = RangeConversionConvert(rangeConv, value); + } + + if (retVal == RETURN_ERROR) { mcx_log(LOG_ERROR, "ConvertRange: Conversion failed"); goto cleanup; } @@ -104,65 +253,6 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va return retVal; } -static int RangeConversionElemwiseLeq(void * first, void * second, ChannelType * type) { - switch (type->con) { - case CHANNEL_DOUBLE: - return *(double *) first <= *(double *) second; - case CHANNEL_INTEGER: - return *(int *) first <= *(int *) second; - default: - return 0; - } -} - -static int RangeConversionElemwiseGeq(void * first, void * second, ChannelType * type) { - switch (type->con) { - case CHANNEL_DOUBLE: - return *(double *) first >= *(double *) second; - case CHANNEL_INTEGER: - return *(int *) first >= *(int *) second; - default: - return 0; - } -} - -static McxStatus RangeConversionConvert(Conversion * conversion, ChannelValue * value) { - RangeConversion * rangeConversion = (RangeConversion *) conversion; - McxStatus retVal = RETURN_OK; - - if (!ChannelTypeEq(ChannelValueType(value), rangeConversion->type)) { - mcx_log(LOG_ERROR, - "Range conversion: Value has wrong type %s, expected: %s", - ChannelTypeToString(ChannelValueType(value)), - ChannelTypeToString(rangeConversion->type)); - return RETURN_ERROR; - } - - if (rangeConversion->min) { - retVal = ChannelValueDataSetFromReferenceIfElemwisePred(&value->value, - value->type, - &rangeConversion->min->value, - RangeConversionElemwiseLeq); - if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "Range conversion: Set value to min failed"); - return RETURN_ERROR; - } - } - - if (rangeConversion->max) { - retVal = ChannelValueDataSetFromReferenceIfElemwisePred(&value->value, - value->type, - &rangeConversion->max->value, - RangeConversionElemwiseGeq); - if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "Range conversion: Set value to max failed"); - return RETURN_ERROR; - } - } - - return RETURN_OK; -} - static McxStatus RangeConversionSetup(RangeConversion * conversion, ChannelValue * min, ChannelValue * max) { if (!min && !max) { return RETURN_OK; @@ -272,42 +362,6 @@ static double UnitConversionConvertValue(UnitConversion * conversion, double val return value; } -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)) { @@ -405,6 +459,48 @@ static int UnitConversionIsEmpty(UnitConversion * conversion) { || (conversion->target.factor == 0.0 && conversion->target.offset == 0.0); } +McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * value, ChannelDimension * slice) { + 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) { + if (slice) { + ChannelValueRef * ref = MakeChannelValueRef(value, slice); + retVal = UnitConversionConvertValueRef(unitConv, ref); + object_destroy(ref); + } else { + retVal = UnitConversionConvert(unitConv, value); + } + + if (retVal == RETURN_ERROR) { + mcx_log(LOG_ERROR, "ConvertUnit: Conversion failed"); + goto cleanup; + } + } + +cleanup: + object_destroy(unitConv); + + return retVal; +} + static void UnitConversionDestructor(UnitConversion * conversion) { } @@ -433,81 +529,97 @@ OBJECT_CLASS(UnitConversion, Conversion); // ---------------------------------------------------------------------- // Linear Conversion - -McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelValue * value) { - LinearConversion * linearConv = NULL; - ChannelValue * factorToUse = NULL; - ChannelValue * offsetToUse = NULL; +static McxStatus LinearConversionConvert(Conversion * conversion, ChannelValue * value) { + LinearConversion * linearConversion = (LinearConversion *) conversion; McxStatus retVal = RETURN_OK; - if (!ChannelTypeEq(value->type, &ChannelTypeDouble) && !ChannelTypeEq(value->type, &ChannelTypeInteger)) { - 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; + if (linearConversion->factor) { + retVal = ChannelValueScale(value, linearConversion->factor); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Linear conversion: Port value scaling failed"); + return RETURN_ERROR; + } } - offsetToUse = offset ? ChannelValueClone(offset) : NULL; - if (offset && !offsetToUse) { - mcx_log(LOG_ERROR, "ConvertLinear: Not enough memory for offset"); - retVal = RETURN_ERROR; - goto cleanup; + if (linearConversion->offset) { + retVal = ChannelValueAddOffset(value, linearConversion->offset); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Linear conversion: Adding offset failed"); + return RETURN_ERROR; + } } - retVal = linearConv->Setup(linearConv, factorToUse, offsetToUse); - if (retVal == RETURN_ERROR) { - mcx_log(LOG_ERROR, "ConvertLinear: Conversion setup failed"); - goto cleanup; - } + return RETURN_OK; +} - factorToUse = NULL; - offsetToUse = NULL; +McxStatus LinearConversionScaleValueRefConversion(void * element, size_t idx, ChannelType * type, void * ctx) { + ChannelValue * factor = (ChannelValue *) ctx; + void * factorElem = mcx_array_get_elem_reference(&factor->value.a, idx); - if (linearConv->IsEmpty(linearConv)) { - object_destroy(linearConv); + if (!ChannelTypeEq(type, factor->type)) { + mcx_log(LOG_ERROR, "Port: Scale: Mismatching types. Value type: %s, factor type: %s", + ChannelTypeToString(type), ChannelTypeToString(ChannelValueType(factor))); + return RETURN_ERROR; } - if (linearConv) { - Conversion * conversion = (Conversion *) linearConv; - retVal = conversion->convert(conversion, value); - if (RETURN_OK != retVal) { - mcx_log(LOG_ERROR, "ConvertLinear: Conversion failed"); - goto cleanup; + switch (type->con) { + case CHANNEL_DOUBLE: + { + double * elem = (double *) element; + *elem = *elem * *((double *)factorElem); + break; + } + case CHANNEL_INTEGER: + { + int * elem = (int *) element; + *elem = *elem * *((int *)factorElem); + break; } + default: + mcx_log(LOG_ERROR, "Linear conversion: Unsupported type"); + return RETURN_ERROR; } -cleanup: - if (factorToUse) { - mcx_free(factorToUse); - } + return RETURN_OK; +} - if (offsetToUse) { - mcx_free(offsetToUse); +McxStatus LinearConversionOffsetValueRefConversion(void * element, size_t idx, ChannelType * type, void * ctx) { + ChannelValue * offset = (ChannelValue *) ctx; + void * offsetElem = mcx_array_get_elem_reference(&offset->value.a, idx); + + if (!ChannelTypeEq(type, offset->type)) { + mcx_log(LOG_ERROR, "Port: Scale: Mismatching types. Value type: %s, factor type: %s", + ChannelTypeToString(type), ChannelTypeToString(ChannelValueType(offset))); + return RETURN_ERROR; } - object_destroy(linearConv); + switch (type->con) { + case CHANNEL_DOUBLE: + { + double * elem = (double *) element; + *elem = *elem + *((double *)offsetElem); + break; + } + case CHANNEL_INTEGER: + { + int * elem = (int *) element; + *elem = *elem + *((int *)offsetElem); + break; + } + default: + mcx_log(LOG_ERROR, "Linear conversion: Unsupported type"); + return RETURN_ERROR; + } - return retVal; + return RETURN_OK; } -static McxStatus LinearConversionConvert(Conversion * conversion, ChannelValue * value) { - LinearConversion * linearConversion = (LinearConversion *) conversion; - +static McxStatus LinearConversionConvertValueRef(LinearConversion * linearConversion, ChannelValueRef * ref) { McxStatus retVal = RETURN_OK; if (linearConversion->factor) { - retVal = ChannelValueScale(value, linearConversion->factor); + retVal = ChannelValueRefElemMap(ref, LinearConversionScaleValueRefConversion, linearConversion->factor); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Linear conversion: Port value scaling failed"); return RETURN_ERROR; @@ -515,7 +627,7 @@ static McxStatus LinearConversionConvert(Conversion * conversion, ChannelValue * } if (linearConversion->offset) { - retVal = ChannelValueAddOffset(value, linearConversion->offset); + retVal = ChannelValueRefElemMap(ref, LinearConversionOffsetValueRefConversion, linearConversion->offset); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Linear conversion: Adding offset failed"); return RETURN_ERROR; @@ -593,6 +705,79 @@ static int LinearConversionIsEmpty(LinearConversion * conversion) { } } +McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelValue * value, ChannelDimension * slice) { + LinearConversion * linearConv = NULL; + ChannelValue * factorToUse = NULL; + ChannelValue * offsetToUse = NULL; + + McxStatus retVal = RETURN_OK; + + if (!ChannelTypeEq(ChannelTypeBaseType(value->type), &ChannelTypeDouble) && !ChannelTypeEq(ChannelTypeBaseType(value->type), &ChannelTypeInteger)) { + 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) { + if (slice) { + ChannelValueRef * ref = MakeChannelValueRef(value, slice); + retVal = LinearConversionConvertValueRef(linearConv, ref); + object_destroy(ref); + } else { + retVal = LinearConversionConvert(linearConv, 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 void LinearConversionDestructor(LinearConversion * linearConversion) { if (linearConversion->type) { ChannelTypeDestructor(linearConversion->type); @@ -626,35 +811,35 @@ OBJECT_CLASS(LinearConversion, Conversion); // ---------------------------------------------------------------------- // Type Conversion - -McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue * value) { +McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, ChannelValue * src, ChannelDimension * srcSlice) { TypeConversion * typeConv = NULL; - Conversion * conv = NULL; + ChannelValueRef * ref = NULL; McxStatus retVal = RETURN_OK; typeConv = (TypeConversion *) object_create(TypeConversion); if (!typeConv) { - mcx_log(LOG_ERROR, "ConvertType: Not enough memory"); + mcx_log(LOG_ERROR, "ConvertType: Converter allocation failed"); return RETURN_ERROR; } - conv = (Conversion *) typeConv; - - retVal = typeConv->Setup(typeConv, fromType, NULL, toType, NULL); + retVal = typeConv->Setup(typeConv, src->type, srcSlice, dest->type, destSlice); if (retVal == RETURN_ERROR) { - mcx_log(LOG_ERROR, "ConvertType: Conversion setup failed"); + mcx_log(LOG_ERROR, "ConvertType: Setup failed"); goto cleanup; } - retVal = conv->convert(conv, value); - if (retVal == RETURN_ERROR) { - mcx_log(LOG_ERROR, "Type conversion failed"); + ref = MakeChannelValueRef(dest, destSlice); + if (!ref) { + mcx_log(LOG_ERROR, "ConvertType: Value reference allocation failed"); goto cleanup; } + ChannelValueRefSetFromReference(ref, ChannelValueReference(src), srcSlice, typeConv); + cleanup: object_destroy(typeConv); + object_destroy(ref); return retVal; } diff --git a/src/core/Conversion.h b/src/core/Conversion.h index 7ac4c34..fe98f8b 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -59,7 +59,7 @@ typedef struct RangeConversion { } RangeConversion; -McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * value); +McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * value, ChannelDimension * slice); // ---------------------------------------------------------------------- @@ -87,7 +87,7 @@ struct UnitConversion { fUnitConversionVector convertVector; }; -McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * value); +McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * value, ChannelDimension * slice); // ---------------------------------------------------------------------- @@ -113,7 +113,7 @@ typedef struct LinearConversion { } LinearConversion; -McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelValue * value); +McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelValue * value, ChannelDimension * slice); // ---------------------------------------------------------------------- @@ -141,7 +141,7 @@ struct TypeConversion { ChannelDimension * sourceSlice; }; -McxStatus ConvertType(ChannelType * fromType, ChannelType * toType, ChannelValue * value); +McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, ChannelValue * src, ChannelDimension * srcSlice); #ifdef __cplusplus diff --git a/src/core/Model.c b/src/core/Model.c index f828ec0..4d9b1b2 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -24,6 +24,7 @@ #include "core/Databus.h" #include "core/channels/Channel.h" +#include "core/channels/ChannelValueReference.h" #include "core/channels/ChannelInfo.h" #include "core/connections/Connection.h" #include "core/connections/FilteredConnection.h" @@ -177,10 +178,12 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { CompConstant * srcCompConst = NULL; Databus * srcDb = srcComp->GetDatabus(srcComp); ChannelInfo * srcChannelInfo = DatabusGetOutChannelInfo(srcDb, info->sourceChannel); + ChannelDimension * srcDim = NULL; Component * trgComp = info->targetComponent; Databus * trgDb = trgComp->GetDatabus(trgComp); ChannelInfo * trgChannelInfo = DatabusGetInChannelInfo(trgDb, info->targetChannel); + ChannelDimension * trgDim = NULL; // if not a const conn, add to the filtered conns if (0 != strcmp(compConstantTypeString, srcComp->GetType(srcComp))) { @@ -203,34 +206,61 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { goto cleanup_1; } + if (!trgChannelInfo->defaultValue) { + trgChannelInfo->defaultValue = (ChannelValue *) mcx_calloc(1, sizeof(ChannelValue)); + ChannelValueInit(trgChannelInfo->defaultValue, ChannelTypeClone(trgChannelInfo->type)); + } + + // prepare slice dimensions + srcDim = ChannelDimensionClone(info->sourceDimension); + if (info->sourceDimension && !srcDim) { + mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Source dimension slice allocation failed"); + goto cleanup_1; + } + + retVal = ChannelDimensionNormalize(srcDim, srcChannelInfo->dimension); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Source dimension normalization failed"); + goto cleanup_1; + } + + trgDim = ChannelDimensionClone(info->targetDimension); + if (info->targetDimension && !trgDim) { + mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Target dimension slice allocation failed"); + goto cleanup_1; + } + + retVal = ChannelDimensionNormalize(trgDim, trgChannelInfo->dimension); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Target dimension normalization failed"); + goto cleanup_1; + } + // out channel range and linear conversions - retVal = ConvertRange(srcChannelInfo->min, srcChannelInfo->max, src); + retVal = ConvertRange(srcChannelInfo->min, srcChannelInfo->max, src, srcDim); if (retVal == RETURN_ERROR) { goto cleanup_1; } - retVal = ConvertLinear(srcChannelInfo->scale, srcChannelInfo->offset, src); + retVal = ConvertLinear(srcChannelInfo->scale, srcChannelInfo->offset, src, srcDim); if (retVal == RETURN_ERROR) { goto cleanup_1; } // type conversion - retVal = ConvertType(srcChannelInfo->type, trgChannelInfo->type, src); + retVal = ConvertType(trgChannelInfo->defaultValue, trgDim, src, srcDim); if (retVal == RETURN_ERROR) { goto cleanup_1; } // unit conversion - retVal = ConvertUnit(srcChannelInfo->unitString, trgChannelInfo->unitString, src); + retVal = ConvertUnit(srcChannelInfo->unitString, trgChannelInfo->unitString, trgChannelInfo->defaultValue, trgDim); if (retVal == RETURN_ERROR) { goto cleanup_1; } - // set the default value - if (trgChannelInfo->defaultValue) { - ChannelValueDestructor(trgChannelInfo->defaultValue); - } - trgChannelInfo->defaultValue = src; + object_destroy(srcDim); + object_destroy(trgDim); continue; @@ -240,6 +270,9 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { mcx_free(src); } + object_destroy(srcDim); + object_destroy(trgDim); + retVal = RETURN_ERROR; goto cleanup; } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 53b7d05..bc673d1 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -508,12 +508,12 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { ChannelValueSet(&channel->value, info->defaultValue); // apply range and linear conversions immediately - retVal = ConvertRange(info->min, info->max, &channel->value); + retVal = ConvertRange(info->min, info->max, &channel->value, NULL); if (retVal == RETURN_ERROR) { return RETURN_ERROR; } - retVal = ConvertLinear(info->scale, info->offset, &channel->value); + retVal = ConvertLinear(info->scale, info->offset, &channel->value, NULL); if (retVal == RETURN_ERROR) { return RETURN_ERROR; } diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 9984d9f..083de27 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -208,6 +208,26 @@ ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { } +ChannelValueRef * MakeChannelValueRef(ChannelValue * val, ChannelDimension * slice) { + ChannelValueRef * ref = (ChannelValueRef *)object_create(ChannelValueRef); + if (!ref) { + return NULL; + } + + if (slice) { + ref->type = CHANNEL_VALUE_REF_SLICE; + ref->ref.slice = (ArraySlice *) mcx_calloc(1, sizeof(ArraySlice)); + ref->ref.slice->dimension = slice; + ref->ref.slice->ref = val; + } else { + ref->type = CHANNEL_VALUE_REF_VALUE; + ref->ref.value = val; + } + + return ref; +} + + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index 87e5ba4..bf18bdc 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -52,6 +52,8 @@ ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, size_t idx, ChannelType * type, void * ctx); McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx); +ChannelValueRef * MakeChannelValueRef(ChannelValue * val, ChannelDimension * slice); + #ifdef __cplusplus } /* closing brace for extern "C" */ From 1060769281c91963e5870984296efcaf47c47b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 24 May 2022 07:33:54 +0200 Subject: [PATCH 219/295] Check for duplicate ports and read specific data --- src/core/Databus.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/core/Databus.c b/src/core/Databus.c index 85da1a2..1a8b152 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -303,6 +303,13 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, Vector * dbInfos = dbInfo->data->infos; size_t requiredSize = 0; + StringContainer * portNames = StringContainerCreate(numChildren); + + if (!portNames) { + mcx_log(LOG_ERROR, "Ports: Port name container allocation failed"); + retVal = RETURN_ERROR; + goto cleanup; + } for (i = 0; i < numChildren; i++) { PortInput * portInput = (PortInput *) input->ports->At(input->ports, i); @@ -315,7 +322,8 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, ChannelInfo * info = DatabusReadPortInput(portInput); if (!info) { mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read info of port %d", i); - return RETURN_ERROR; + retVal = RETURN_ERROR; + goto cleanup; } info->mode = mode; @@ -327,13 +335,41 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, mcx_log(LOG_DEBUG, " Port: \"%s\"", name); } + { + // check for duplicates + int n = StringContainerGetIndex(portNames, name); + if (n >= 0) { // key already exists + mcx_log(LOG_ERROR, "Ports: Duplicate port %s", name); + retVal = RETURN_ERROR; + goto cleanup; + } + } + + if (SpecificRead) { + retVal = SpecificRead(comp, info, portInput, i); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not read element specific data of port %d", i); + goto cleanup; + } + } + if (RETURN_OK != dbInfos->PushBack(dbInfos, info)) { mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); - return RETURN_ERROR; + retVal = RETURN_ERROR; + goto cleanup; + } + + retVal = StringContainerAddString(portNames, name); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Ports: Storing port name failed"); + goto cleanup; } } - return RETURN_OK; +cleanup: + StringContainerDestroy(portNames); + + return retVal; } static int IsWriteResults(void * elem, void * ignore) { From 0d13275997651be80e14b6c6a97b76aa1afbc136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 24 May 2022 07:34:12 +0200 Subject: [PATCH 220/295] Apply conversions only if necessary --- src/core/channels/Channel.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index bc673d1..3eba157 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -301,10 +301,9 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { // Conversions - { + if (numConns > 0) { ChannelValue * val = &channel->value; - // linear if (in->data->linearConversion) { Conversion * conversion = (Conversion *) in->data->linearConversion; From 9f262cb5db9b94ed45a7549ad495bb99f84ff611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 24 May 2022 07:34:36 +0200 Subject: [PATCH 221/295] Use the correct reference --- src/core/connections/Connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index ec6f4e9..c41a6e7 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1233,7 +1233,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { goto cleanup; } - ChannelValueRefSetFromReference(storeRef, outInfo->initialValue, targetDim, NULL); + ChannelValueRefSetFromReference(storeRef, ChannelValueReference(outInfo->initialValue), targetDim, NULL); connection->useInitialValue_ = TRUE; } else { { From bf420c94e89d614d49a9b93e9e3e02fb369357ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 24 May 2022 07:35:19 +0200 Subject: [PATCH 222/295] Use function instead of member function --- src/core/connections/Connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index c41a6e7..602036f 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1242,7 +1242,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { mcx_free(buffer); } - ChannelType * storeType = ChannelTypeFromDimension(info->connType_, info->sourceDimension); + ChannelType * storeType = ChannelTypeFromDimension(ConnectionInfoGetType(info), info->sourceDimension); if (!storeType) { mcx_log(LOG_ERROR, "Creating type from the dimension failed"); retVal = RETURN_ERROR; From f484a2eaf84eaa24948bd0013299d51b2b3b79b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 24 May 2022 07:36:14 +0200 Subject: [PATCH 223/295] Fix target/source channel reading during ConnectionInfo construction --- src/core/connections/ConnectionInfoFactory.c | 60 ++++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 32079b9..1fea098 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -138,6 +138,23 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->sourceDimension = sourceDimension; } + 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) + + databusInfo = DatabusGetInInfo(databus); + info->sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel); + + 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; + } + } + // check that the source endpoint "fits" into the channel sourceInfo = DatabusInfoGetChannel(databusInfo, info->sourceChannel); if (!ChannelDimensionIncludedIn(info->sourceDimension, sourceInfo->dimension)) { @@ -160,23 +177,6 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, 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) - - databusInfo = DatabusGetInInfo(databus); - info->sourceChannel = DatabusInfoGetChannelID(databusInfo, strFromChannel); - - 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 @@ -226,6 +226,19 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->targetDimension = targetDimension; } + 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; + } + // check that the target endpoint "fits" into the channel targetInfo = DatabusInfoGetChannel(databusInfo, info->targetChannel); if (!ChannelDimensionIncludedIn(info->targetDimension, targetInfo->dimension)) { @@ -248,19 +261,6 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, goto cleanup; } - - 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; - } } // swap endpoints if connection is inverted From a89fc6a0a939a2728f6c37f3f545b774cae82106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 23 May 2022 17:00:20 +0200 Subject: [PATCH 224/295] Expose the whole source value (not just a slice) in direct connections --- src/core/connections/Connection.c | 37 +++++++++++++++++++++---------- src/core/connections/Connection.h | 3 +++ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 602036f..fa57c79 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1269,6 +1269,28 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim // Do nothing } +static McxStatus ConnectionInitSetToStore(Connection * connection) { + Channel* channel = (Channel*)connection->out_; + ChannelInfo* info = &channel->info; + ChannelValueRef * storeRef = (ChannelValueRef *) object_create(ChannelValueRef); + + if (!storeRef) { + mcx_log(LOG_ERROR, "Could not create store reference for initial connection"); + return RETURN_ERROR; + } + storeRef->type = CHANNEL_VALUE_REF_VALUE; + storeRef->ref.value = &connection->store_; + + ConnectionInfo * connInfo = connection->GetInfo(connection); + ChannelDimension * clone = ChannelDimensionClone(connInfo->sourceDimension); + ChannelDimensionNormalize(clone, info->dimension); + if (RETURN_OK != ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL)) { + return RETURN_ERROR; + } + + return RETURN_OK; +} + static McxStatus ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) { Channel * channel = (Channel *) connection->out_; ChannelInfo * info = &channel->info; @@ -1281,18 +1303,7 @@ static McxStatus ConnectionInitUpdateTo(Connection * connection, TimeInterval * #endif if (!connection->useInitialValue_) { - ChannelValueRef * storeRef = (ChannelValueRef *) object_create(ChannelValueRef); - if (!storeRef) { - mcx_log(LOG_ERROR, "Could not create store reference for initial connection"); - return RETURN_ERROR; - } - storeRef->type = CHANNEL_VALUE_REF_VALUE; - storeRef->ref.value = &connection->store_; - - ConnectionInfo * connInfo = connection->GetInfo(connection); - ChannelDimension * clone = ChannelDimensionClone(connInfo->sourceDimension); - ChannelDimensionNormalize(clone, info->dimension); - if (RETURN_OK != ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL)) { + if (RETURN_OK != connection->InitSetToStore(connection)) { return RETURN_ERROR; } if (channel->IsDefinedDuringInit(channel)) { @@ -1482,6 +1493,8 @@ static Connection * ConnectionCreate(Connection * connection) { connection->NormalUpdateTo_ = NULL; connection->normalValue_ = NULL; + connection->InitSetToStore = ConnectionInitSetToStore; + return connection; } diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h index ed2222b..bd07776 100644 --- a/src/core/connections/Connection.h +++ b/src/core/connections/Connection.h @@ -67,6 +67,7 @@ typedef void (* fConnectionUpdateFromInput)(Connection * connection, TimeInterva typedef McxStatus (* fConnectionUpdateToOutput)(Connection * connection, TimeInterval * time); typedef McxStatus (* fConnectionUpdateInitialValue)(Connection * connection); +typedef McxStatus (* fConnectionInitSetToStore)(Connection * connection); typedef McxStatus (* fConnectionEnterInitializationMode)(Connection * connection); typedef McxStatus (* fConnectionExitInitializationMode)(Connection * connection, double time); @@ -138,6 +139,8 @@ struct Connection { fConnectionGetValueType GetValueType; + fConnectionInitSetToStore InitSetToStore; + /** * Set the reference to the value of the connection. This value will be * updated on each call to UpdateToOutput(). From 11126616adb073693b48fe5652b30f833f92e4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 27 May 2022 11:46:15 +0200 Subject: [PATCH 225/295] Disable support for co-sim init with vector ports --- src/core/Model.c | 36 ++++++++++++++++++++++++++++++++++++ src/core/Model.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/src/core/Model.c b/src/core/Model.c index 4d9b1b2..b675846 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -540,6 +540,35 @@ static McxStatus ModelSignalConnectionsDone(ObjectContainer * comps) { return RETURN_OK; } +int ComponentsHaveVectorChannels(ObjectContainer * components) { + size_t numComps = components->Size(components); + size_t i = 0; + + for (i = 0; i < numComps; i++) { + Component * comp = (Component *) components->At(components, i); + Databus * db = comp->GetDatabus(comp); + size_t numIns = DatabusGetInChannelsNum(db); + size_t numOuts = DatabusGetOutChannelsNum(db); + size_t j = 0; + + for (j = 0; j < numIns; j++) { + ChannelInfo * info = DatabusGetInChannelInfo(db, j); + if (ChannelTypeIsArray(info->type)) { + return TRUE; + } + } + + for (j = 0; j < numOuts; j++) { + ChannelInfo* info = DatabusGetOutChannelInfo(db, j); + if (ChannelTypeIsArray(info->type)) { + return TRUE; + } + } + } + + return FALSE; +} + static McxStatus ModelConnectionsDone(Model * model) { OrderedNodes * orderedNodes = NULL; McxStatus retVal = RETURN_OK; @@ -564,6 +593,13 @@ static McxStatus ModelConnectionsDone(Model * model) { // determine initialization evaluation order if (model->config->cosimInitEnabled) { + // separate triggering of array elements is not supported at the moment + // therefore some models with array ports might not work + if (ComponentsHaveVectorChannels(model->components)) { + mcx_log(LOG_ERROR, "Co-Simulation initialization: Components with vector ports are not supported"); + return RETURN_ERROR; + } + retVal = ModelCreateInitSubModel(model); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Model: InitSubModel could not be created"); diff --git a/src/core/Model.h b/src/core/Model.h index 5465ad7..a0fefb5 100644 --- a/src/core/Model.h +++ b/src/core/Model.h @@ -97,6 +97,8 @@ McxStatus ModelConnectionsEnterInitMode(ObjectContainer * comps); McxStatus ModelConnectionsExitInitMode(ObjectContainer * comps, double time); McxStatus ModelDoConnectionsInitialization(ObjectContainer * comps, int onlyIfDecoupled); +int ComponentsHaveVectorChannels(ObjectContainer * components); + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ From 10b689362d076fa5ebc6a95ca6fe3e794ccf0c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 27 May 2022 17:16:51 +0200 Subject: [PATCH 226/295] ChannelDimension cleanup --- src/core/Conversion.c | 12 ++-- src/core/Databus.c | 2 +- src/core/Model.c | 8 +-- src/core/channels/Channel.c | 4 +- src/core/channels/ChannelDimension.c | 74 +++++++------------- src/core/channels/ChannelDimension.h | 38 +++++----- src/core/channels/ChannelInfo.c | 2 +- src/core/channels/ChannelValue.c | 6 +- src/core/connections/Connection.c | 12 ++-- src/core/connections/ConnectionInfoFactory.c | 38 ++-------- 10 files changed, 77 insertions(+), 119 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index f601665..96de63c 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -900,15 +900,15 @@ static McxStatus ArraysValidForConversion(ChannelValueRef * dest, // check dimensions match if (srcDimension) { if (dest->type == CHANNEL_VALUE_REF_VALUE) { - return ChannelDimensionsConform(srcDimension, dest->ref.value->type->ty.a.dims, dest->ref.value->type->ty.a.numDims) ? RETURN_OK : RETURN_ERROR; + return ChannelDimensionConformsTo(srcDimension, dest->ref.value->type->ty.a.dims, dest->ref.value->type->ty.a.numDims) ? RETURN_OK : RETURN_ERROR; } else { - return ChannelDimensionConformable(dest->ref.slice->dimension, srcDimension) ? RETURN_OK : RETURN_ERROR; + return ChannelDimensionConformsToDimension(dest->ref.slice->dimension, srcDimension) ? RETURN_OK : RETURN_ERROR; } } else { if (dest->type == CHANNEL_VALUE_REF_VALUE) { return mcx_array_dims_match(&dest->ref.value->value.a, src) ? RETURN_OK : RETURN_ERROR; } else { - return ChannelDimensionsConform(dest->ref.slice->dimension, src->dims, src->numDims) ? RETURN_OK : RETURN_ERROR; + return ChannelDimensionConformsTo(dest->ref.slice->dimension, src->dims, src->numDims) ? RETURN_OK : RETURN_ERROR; } } @@ -1404,9 +1404,9 @@ static McxStatus TypeConversionConvertId(TypeConversion * conversion, ChannelVal static int DimensionsMatch(ChannelType * fromType, ChannelDimension * fromDimension, ChannelType * toType, ChannelDimension * toDimension) { if (fromDimension) { if (!toDimension) { - return ChannelDimensionsConform(fromDimension, toType->ty.a.dims, toType->ty.a.numDims); + return ChannelDimensionConformsTo(fromDimension, toType->ty.a.dims, toType->ty.a.numDims); } else { - return ChannelDimensionConformable(toDimension, fromDimension); + return ChannelDimensionConformsToDimension(toDimension, fromDimension); } } else { if (!toDimension) { @@ -1423,7 +1423,7 @@ static int DimensionsMatch(ChannelType * fromType, ChannelDimension * fromDimens return 1; } else { - return ChannelDimensionsConform(toDimension, fromType->ty.a.dims, fromType->ty.a.numDims); + return ChannelDimensionConformsTo(toDimension, fromType->ty.a.dims, fromType->ty.a.numDims); } } } diff --git a/src/core/Databus.c b/src/core/Databus.c index 1a8b152..e2c5e92 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -83,7 +83,7 @@ static ChannelInfo * DatabusReadPortInput(PortInput * input) { goto vector_cleanup_0; } - info->dimension = (ChannelDimension *) object_create(ChannelDimension); + info->dimension = MakeChannelDimension(); if (!info->dimension) { retVal = RETURN_ERROR; goto vector_cleanup_0; diff --git a/src/core/Model.c b/src/core/Model.c index b675846..1969b0d 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -212,25 +212,25 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { } // prepare slice dimensions - srcDim = ChannelDimensionClone(info->sourceDimension); + srcDim = CloneChannelDimension(info->sourceDimension); if (info->sourceDimension && !srcDim) { mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Source dimension slice allocation failed"); goto cleanup_1; } - retVal = ChannelDimensionNormalize(srcDim, srcChannelInfo->dimension); + retVal = ChannelDimensionAlignIndicesWithZero(srcDim, srcChannelInfo->dimension); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Source dimension normalization failed"); goto cleanup_1; } - trgDim = ChannelDimensionClone(info->targetDimension); + trgDim = CloneChannelDimension(info->targetDimension); if (info->targetDimension && !trgDim) { mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Target dimension slice allocation failed"); goto cleanup_1; } - retVal = ChannelDimensionNormalize(trgDim, trgChannelInfo->dimension); + retVal = ChannelDimensionAlignIndicesWithZero(trgDim, trgChannelInfo->dimension); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "ModelPreprocessConstConnections: Target dimension normalization failed"); goto cleanup_1; diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 3eba157..e720d98 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -426,8 +426,8 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec valRef->type = CHANNEL_VALUE_REF_SLICE; valRef->ref.slice = (ArraySlice *) mcx_calloc(1, sizeof(ArraySlice)); valRef->ref.slice->ref = &channel->value; - valRef->ref.slice->dimension = ChannelDimensionClone(dimension); - retVal = ChannelDimensionNormalize(valRef->ref.slice->dimension, inInfo->dimension); + valRef->ref.slice->dimension = CloneChannelDimension(dimension); + retVal = ChannelDimensionAlignIndicesWithZero(valRef->ref.slice->dimension, inInfo->dimension); if (retVal == RETURN_ERROR) { ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Normalizing array slice dimension failed"); return RETURN_ERROR; diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 8064fd2..f86c675 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -9,27 +9,15 @@ ********************************************************************************/ #include "core/channels/ChannelDimension.h" + #include "util/stdlib.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -void ChannelDimensionDestructor(ChannelDimension * dimension) { - if (dimension->startIdxs) { mcx_free(dimension->startIdxs); } - if (dimension->endIdxs) { mcx_free(dimension->endIdxs); } -} - -ChannelDimension * ChannelDimensionCreate(ChannelDimension * dimension) { - dimension->num = 0; - dimension->startIdxs = NULL; - dimension->endIdxs = NULL; - - return dimension; -} - -OBJECT_CLASS(ChannelDimension, Object); McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num) { dimension->num = num; @@ -63,8 +51,9 @@ McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, return RETURN_OK; } -size_t ChannelDimensionNumElements(ChannelDimension * dimension) { - size_t i = 0, n = 1; +size_t ChannelDimensionNumElements(const ChannelDimension * dimension) { + size_t i = 0; + size_t n = 1; if (dimension->num == 0) { return 0; @@ -77,7 +66,7 @@ size_t ChannelDimensionNumElements(ChannelDimension * dimension) { return n; } -ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension) { +ChannelDimension * CloneChannelDimension(const ChannelDimension * dimension) { ChannelDimension * clone = NULL; McxStatus retVal = RETURN_OK; size_t i = 0; @@ -86,22 +75,22 @@ ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension) { return NULL; } - clone = (ChannelDimension *) object_create(ChannelDimension); + clone = MakeChannelDimension(); if (!clone) { - mcx_log(LOG_ERROR, "ChannelDimensionClone: Not enough memory"); + mcx_log(LOG_ERROR, "CloneChannelDimension: Not enough memory"); return NULL; } retVal = ChannelDimensionSetup(clone, dimension->num); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Channel dimension setup failed"); + mcx_log(LOG_ERROR, "CloneChannelDimension: Channel dimension setup failed"); goto cleanup; } for (i = 0; i < dimension->num; i++) { retVal = ChannelDimensionSetDimension(clone, i, dimension->startIdxs[i], dimension->endIdxs[i]); if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Channel dimension %zu set failed", i); + mcx_log(LOG_ERROR, "CloneChannelDimension: Channel dimension %zu set failed", i); goto cleanup; } } @@ -113,7 +102,7 @@ ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension) { return NULL; } -int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second) { +int ChannelDimensionEq(const ChannelDimension * first, const ChannelDimension * second) { size_t i = 0; if (!first && !second) { @@ -135,7 +124,7 @@ int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second) { return TRUE; } -int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * second) { +int ChannelDimensionConformsToDimension(const ChannelDimension * first, const ChannelDimension * second) { size_t i = 0; if (!first && !second) { @@ -157,7 +146,7 @@ int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * sec return TRUE; } -int ChannelDimensionsConform(ChannelDimension * dimension, size_t * dims, size_t numDims) { +int ChannelDimensionConformsTo(const ChannelDimension * dimension, const size_t * dims, size_t numDims) { size_t i = 0; if (dimension->num != numDims) { return 0; @@ -172,7 +161,7 @@ int ChannelDimensionsConform(ChannelDimension * dimension, size_t * dims, size_t return 1; } -int ChannelDimensionIncludedIn(const ChannelDimension* first, const ChannelDimension* second) { +int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second) { size_t i = 0; if (!first && !second) { @@ -198,7 +187,7 @@ int ChannelDimensionIncludedIn(const ChannelDimension* first, const ChannelDimen return TRUE; } -size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes) { +size_t ChannelDimensionGetIndex(const ChannelDimension * dimension, size_t elem_idx, const size_t * sizes) { switch (dimension->num) { case 1: { @@ -232,7 +221,7 @@ size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, s return (size_t) -1; } -size_t ChannelDimensionGetSliceIndex(ChannelDimension * dimension, size_t slice_idx, size_t * dims) { +size_t ChannelDimensionGetSliceIndex(const ChannelDimension * dimension, size_t slice_idx, const size_t * dims) { switch (dimension->num) { case 1: { @@ -304,7 +293,7 @@ char * ChannelDimensionString(const ChannelDimension * dimension) { return str; } -McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension * base) { +McxStatus ChannelDimensionAlignIndicesWithZero(ChannelDimension * target, const ChannelDimension * base) { size_t i = 0; if (!target && !base) { return RETURN_OK; @@ -324,32 +313,21 @@ McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension return RETURN_OK; } -ChannelType * ChannelDimensionToChannelType(ChannelDimension * dimension, ChannelType * sourceType) { - if (dimension) { - // source data is an array - size_t i = 0; - ChannelType * type = NULL; - size_t * dims = (size_t *) mcx_calloc(sizeof(size_t), dimension->num); +ChannelDimension * MakeChannelDimension() { + ChannelDimension * dimension = (ChannelDimension *) mcx_calloc(1, sizeof(ChannelDimension)); - if (!dims) { - mcx_log(LOG_ERROR, "ChannelDimensionToChannelType: Not enough memory for dimension calculation"); - return NULL; - } + return dimension; +} - for (i = 0; i < dimension->num; i++) { - dims[i] = dimension->endIdxs[i] - dimension->startIdxs[i] + 1; // indices are inclusive - } +void DestroyChannelDimension(ChannelDimension ** dimension) { + if ((*dimension)->startIdxs) { mcx_free((*dimension)->startIdxs); } + if ((*dimension)->endIdxs) { mcx_free((*dimension)->endIdxs); } - type = ChannelTypeArray(ChannelTypeClone(ChannelTypeBaseType(sourceType)), dimension->num, dims); - mcx_free(dims); - return type; - } else { - // source data is a scalar - return ChannelTypeClone(sourceType); - } + *dimension = NULL; } + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 9f9da44..0fdbf0d 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -8,43 +8,49 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#ifndef MCX_CORE_CHANNELS_CHANNELDIMENSION_H -#define MCX_CORE_CHANNELS_CHANNELDIMENSION_H +#ifndef MCX_CORE_CHANNELS_CHANNEL_DIMENSION_H +#define MCX_CORE_CHANNELS_CHANNEL_DIMENSION_H #include "CentralParts.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -extern const struct ObjectClass _ChannelDimension; -typedef struct ChannelDimension { - Object _; // super class first +typedef struct ChannelDimension { size_t num; + size_t * startIdxs; size_t * endIdxs; } ChannelDimension; +ChannelDimension * MakeChannelDimension(); +ChannelDimension * CloneChannelDimension(const ChannelDimension * dimension); +void DestroyChannelDimension(ChannelDimension ** dimension); + McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); -ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); -size_t ChannelDimensionNumElements(ChannelDimension * dimension); -ChannelDimension * ChannelDimensionClone(ChannelDimension * dimension); -int ChannelDimensionEq(ChannelDimension * first, ChannelDimension * second); -int ChannelDimensionConformable(ChannelDimension * first, ChannelDimension * second); -int ChannelDimensionsConform(ChannelDimension * dimension, size_t * dims, size_t numDims); + +int ChannelDimensionEq(const ChannelDimension * first, const ChannelDimension * second); +int ChannelDimensionConformsToDimension(const ChannelDimension * first, const ChannelDimension * second); +int ChannelDimensionConformsTo(const ChannelDimension * dimension, const size_t * dims, size_t numDims); int ChannelDimensionIncludedIn(const ChannelDimension * first, const ChannelDimension * second); -size_t ChannelDimensionGetIndex(ChannelDimension * dimension, size_t elem_idx, size_t * sizes); -size_t ChannelDimensionGetSliceIndex(ChannelDimension * dimension, size_t slice_idx, size_t * dims); + +size_t ChannelDimensionNumElements(const ChannelDimension* dimension); char * ChannelDimensionString(const ChannelDimension * dimension); -McxStatus ChannelDimensionNormalize(ChannelDimension * target, ChannelDimension * base); -ChannelType * ChannelDimensionToChannelType(ChannelDimension * dimension, ChannelType * sourceType); +size_t ChannelDimensionGetIndex(const ChannelDimension * dimension, size_t elem_idx, const size_t * sizes); +size_t ChannelDimensionGetSliceIndex(const ChannelDimension * dimension, size_t slice_idx, const size_t * dims); + +McxStatus ChannelDimensionAlignIndicesWithZero(ChannelDimension * target, const ChannelDimension * base); + + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ -#endif // MCX_CORE_CHANNELS_CHANNELDIMENSION_H \ No newline at end of file +#endif // MCX_CORE_CHANNELS_CHANNEL_DIMENSION_H \ No newline at end of file diff --git a/src/core/channels/ChannelInfo.c b/src/core/channels/ChannelInfo.c index b88b83c..ff93130 100644 --- a/src/core/channels/ChannelInfo.c +++ b/src/core/channels/ChannelInfo.c @@ -233,7 +233,7 @@ McxStatus ChannelInfoSetFrom(ChannelInfo * info, const ChannelInfo * other) { object_destroy(info->dimension); if (other->dimension) { - info->dimension = ChannelDimensionClone(other->dimension); + info->dimension = CloneChannelDimension(other->dimension); if (!info->dimension) { mcx_log(LOG_ERROR, "ChannelInfoSetFrom: Failed to set dimension"); return RETURN_ERROR; diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 218059a..79be3d3 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -167,11 +167,11 @@ size_t ChannelTypeNumElements(const ChannelType * type) { int ChannelTypeConformable(ChannelType * a, ChannelDimension * sliceA, ChannelType * b, ChannelDimension * sliceB) { if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { if (sliceA && sliceB) { - return a->ty.a.inner == b->ty.a.inner && ChannelDimensionConformable(sliceA, sliceB); + return a->ty.a.inner == b->ty.a.inner && ChannelDimensionConformsToDimension(sliceA, sliceB); } else if (sliceA && !sliceB) { - return a->ty.a.inner == b->ty.a.inner && ChannelDimensionsConform(sliceA, b->ty.a.dims, b->ty.a.numDims); + return a->ty.a.inner == b->ty.a.inner && ChannelDimensionConformsTo(sliceA, b->ty.a.dims, b->ty.a.numDims); } else if (!sliceA && sliceB) { - return a->ty.a.inner == b->ty.a.inner && ChannelDimensionsConform(sliceB, a->ty.a.dims, a->ty.a.numDims); + return a->ty.a.inner == b->ty.a.inner && ChannelDimensionConformsTo(sliceB, a->ty.a.dims, a->ty.a.numDims); } else { return ChannelTypeEq(a, b); } diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index fa57c79..8ffbe90 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1177,13 +1177,13 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { ChannelValue * inChannelValue = inInfo->initialValue; ChannelDimension * srcDim = NULL; - srcDim = ChannelDimensionClone(info->targetDimension); + srcDim = CloneChannelDimension(info->targetDimension); if (srcDim) { mcx_log(LOG_ERROR, "Could not clone source dimension"); retVal = RETURN_ERROR; goto cleanup_1; } - retVal = ChannelDimensionNormalize(srcDim, inInfo->dimension); + retVal = ChannelDimensionAlignIndicesWithZero(srcDim, inInfo->dimension); if (retVal == RETURN_ERROR) { mcx_log(LOG_ERROR, "Dimension normalization failed"); goto cleanup_1; @@ -1219,14 +1219,14 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { goto cleanup; } } else if (outInfo->initialValue) { - ChannelDimension * targetDim = ChannelDimensionClone(info->sourceDimension); + ChannelDimension * targetDim = CloneChannelDimension(info->sourceDimension); if (targetDim) { mcx_log(LOG_ERROR, "Could not clone target dimension"); retVal = RETURN_ERROR; goto cleanup; } - retVal = ChannelDimensionNormalize(targetDim, outInfo->dimension); + retVal = ChannelDimensionAlignIndicesWithZero(targetDim, outInfo->dimension); if (retVal == RETURN_ERROR) { mcx_log(LOG_ERROR, "Dimension normalization failed"); object_destroy(targetDim); @@ -1282,8 +1282,8 @@ static McxStatus ConnectionInitSetToStore(Connection * connection) { storeRef->ref.value = &connection->store_; ConnectionInfo * connInfo = connection->GetInfo(connection); - ChannelDimension * clone = ChannelDimensionClone(connInfo->sourceDimension); - ChannelDimensionNormalize(clone, info->dimension); + ChannelDimension * clone = CloneChannelDimension(connInfo->sourceDimension); + ChannelDimensionAlignIndicesWithZero(clone, info->dimension); if (RETURN_OK != ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL)) { return RETURN_ERROR; } diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 1fea098..1e73034 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -117,7 +117,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, // arrays/multiplexing: source slice dimensions if (connInput->fromType == ENDPOINT_VECTOR) { - ChannelDimension* sourceDimension = (ChannelDimension*)object_create(ChannelDimension); + ChannelDimension * sourceDimension = MakeChannelDimension(); if (!sourceDimension) { retVal = RETURN_ERROR; goto cleanup; @@ -126,12 +126,14 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { mcx_log(LOG_ERROR, "Source port %s: Could not set number of dimensions", strFromChannel); retVal = RETURN_ERROR; + DestroyChannelDimension(&sourceDimension); goto cleanup; } if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, connInput->from.vectorEndpoint->startIndex, connInput->from.vectorEndpoint->endIndex)) { mcx_log(LOG_ERROR, "Source port %s: Could not set dimension boundaries", strFromChannel); retVal = RETURN_ERROR; + DestroyChannelDimension(&sourceDimension); goto cleanup; } @@ -201,7 +203,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, // arrays/multiplexing: target slice dimensions if (connInput->toType == ENDPOINT_VECTOR) { - ChannelDimension * targetDimension = (ChannelDimension *) object_create(ChannelDimension); + ChannelDimension * targetDimension = MakeChannelDimension(); if (!targetDimension) { retVal = RETURN_ERROR; goto cleanup; @@ -210,6 +212,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, if (RETURN_OK != ChannelDimensionSetup(targetDimension, 1)) { mcx_log(LOG_ERROR, "Target port %s: Could not set number of dimensions", strToChannel); retVal = RETURN_ERROR; + DestroyChannelDimension(&targetDimension); goto cleanup; } @@ -220,6 +223,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, { mcx_log(LOG_ERROR, "Target port %s: Could not set dimension boundaries", strToChannel); retVal = RETURN_ERROR; + DestroyChannelDimension(&targetDimension); goto cleanup; } @@ -282,36 +286,6 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, info->targetComponent->GetName(info->targetComponent), strFromChannel, info->sourceComponent->GetName(info->sourceComponent), strToChannel); } - // source dimension - { - EndpointInputType endpointType = connectionInverted ? connInput->toType : connInput->fromType; - - if (endpointType == ENDPOINT_VECTOR) { - size_t startIndex = (size_t) (connectionInverted ? connInput->to.vectorEndpoint->startIndex : connInput->from.vectorEndpoint->startIndex); - size_t endIndex = (size_t)(connectionInverted ? connInput->to.vectorEndpoint->endIndex : connInput->from.vectorEndpoint->endIndex); - - ChannelDimension* sourceDimension = (ChannelDimension*)object_create(ChannelDimension); - if (!sourceDimension) { - retVal = RETURN_ERROR; - goto cleanup; - } - - if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { - mcx_log(LOG_ERROR, "Could not setup ChannelDimension"); - retVal = RETURN_ERROR; - goto cleanup; - } - - if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, startIndex, endIndex)) { - mcx_log(LOG_ERROR, "Could not SetDimension"); - retVal = RETURN_ERROR; - goto cleanup; - } - - info->sourceDimension = sourceDimension; - } - } - { // check that connection endpoint dimensions match ChannelDimension * sourceDim = info->sourceDimension; From 8335ddb83e7df2d741db92793f4af7940aca30f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 31 May 2022 11:14:11 +0200 Subject: [PATCH 227/295] Replace IsValid functions with their channel counterparts Rename ChannelIsValid -> ChannelProvidesValue Define a IsFullyConnected function for in and out channels --- src/components/comp_fmu.c | 12 ++++-- src/core/Component.c | 10 ++--- src/core/Databus.c | 77 +---------------------------------- src/core/Databus.h | 31 -------------- src/core/Model.c | 35 ++++++++-------- src/core/channels/Channel.c | 81 ++++++++++++++++++++++++++++++++----- src/core/channels/Channel.h | 11 ++++- 7 files changed, 109 insertions(+), 148 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index a0495d0..3292f41 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -50,11 +50,12 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { numChannels = DatabusInfoGetChannelNum(dbInfo); vals = fmu1->in; for (i = 0; i < numChannels; i++) { + Channel * ch = (Channel *) DatabusGetInChannel(db, i); ChannelInfo * info = DatabusInfoGetChannel(dbInfo, i); ChannelDimension * dimension = info->dimension; ChannelType * type = info->type; - if (DatabusChannelInIsValid(db, i)) { + if (ch->IsConnected(ch) || ch->info.defaultValue) { Fmu1Value * val = NULL; fmi1_import_variable_t * var = NULL; @@ -375,10 +376,11 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat numChannels = DatabusInfoGetChannelNum(dbInfo); for (i = 0; i < numChannels; i++) { + Channel * ch = (Channel *)DatabusGetInChannel(db, i); ChannelInfo * info = DatabusInfoGetChannel(dbInfo, i); Fmu2Value * val = (Fmu2Value *) vals->At(vals, i); - if (DatabusChannelInIsValid(db, i)) { + if (ch->IsConnected(ch) || ch->info.defaultValue) { const char * channelName = info->nameInTool; if (NULL == channelName) { channelName = ChannelInfoGetName(info); @@ -1132,8 +1134,9 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps for (i = 0; i < num_in_vars; ++i) { Fmu2Value *val = (Fmu2Value *)in_vars->At(in_vars, i); + Channel * ch = (Channel *) DatabusGetInChannel(db, i); ChannelInfo * info = DatabusInfoGetChannel(db_info, i); - if (DatabusChannelInIsValid(db, k) && info->connected) { + if (ch->IsConnected(ch)) { // key i in the map means channel i is connected in_channel_connectivity->Add(in_channel_connectivity, i, 1 /* true */); } @@ -1284,7 +1287,8 @@ static struct Dependencies* Fmu2GetInOutGroupsInitialDependency(const Component size_t dummy_num_out = 1; dependencies = DependenciesCreate(num_in, dummy_num_out); for (j = 0; j < num_in; ++j) { - if (DatabusChannelInIsValid(db, j)) { + Channel * ch = (Channel *) DatabusGetInChannel(db, j); + if (ch->IsConnected(ch) || ch->info.defaultValue) { retVal = SetDependency(dependencies, j, 0, DEP_DEPENDENT); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Initial dependency matrix for %s could not be created", comp->GetName(comp)); diff --git a/src/core/Component.c b/src/core/Component.c index 93b8193..427e7e5 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -384,7 +384,7 @@ McxStatus ComponentRegisterStorage(Component * comp, ResultsStorage * storage) { for (i = 0; i < numInChannels; i++) { Channel * channel = (Channel *) DatabusGetInChannel(db, i); - if (channel->IsValid(channel)) { + if (channel->ProvidesValue(channel)) { retVal = compStore->RegisterChannel(compStore, CHANNEL_STORE_IN, channel); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register inport %d at storage", i); @@ -650,7 +650,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numIn; i++) { Channel * channel = (Channel *) DatabusGetInChannel(db, i); char * id = channel->info.id; - int isValid = DatabusChannelInIsValid(db, i); + int isValid = channel->IsConnected(channel) || channel->info.defaultValue; if (NULL != id && isValid) { StringContainerSetKeyValue(container, *count, id, channel); @@ -661,7 +661,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numLocal; i++) { Channel * channel = (Channel *) DatabusGetLocalChannel(db, i); char * id = channel->info.id; - int isValid = DatabusChannelLocalIsValid(db, i); + int isValid = channel->ProvidesValue(channel); if (NULL != id && isValid) { StringContainerSetKeyValue(container, *count, id, channel); @@ -672,7 +672,7 @@ static McxStatus AddObservableChannels(const Component * comp, StringContainer * for (i = 0; i < numRTFactor; i++) { Channel * channel = (Channel *) DatabusGetRTFactorChannel(db, i); char * id = channel->info.id; - int isValid = DatabusChannelRTFactorIsValid(db, i); + int isValid = channel->ProvidesValue(channel); if (NULL != id && isValid) { StringContainerSetKeyValue(container, *count, id, channel); @@ -690,7 +690,7 @@ static size_t ComponentGetNumConnectedOutChannels(const Component * comp) { for (i = 0; (int) i < DatabusInfoGetChannelNum(DatabusGetOutInfo(comp->data->databus)); i++) { Channel * channel = (Channel *) DatabusGetOutChannel(comp->data->databus, i); - if (channel->IsValid(channel)) { + if (channel->IsConnected(channel)) { count++; } } diff --git a/src/core/Databus.c b/src/core/Databus.c index e2c5e92..e5580c9 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -656,7 +656,7 @@ McxStatus DatabusTriggerInConnections(Databus * db, TimeInterval * consumerTime) for (i = 0; i < numIn; i++) { Channel * channel = (Channel *) db->data->in[i]; - if (channel->IsValid(channel)) { + if (channel->IsConnected(channel) || channel->info.defaultValue) { retVal = channel->Update(channel, consumerTime); if (RETURN_OK != retVal) { ChannelInfo * info = &channel->info; @@ -1294,81 +1294,6 @@ ChannelInfo * DatabusGetLocalChannelInfo(Databus * db, size_t channel) { return (ChannelInfo *) data->infos->At(data->infos, channel); } -int DatabusChannelInIsValid(Databus * db, size_t channel) { - Channel * in = NULL; - - if (!db) { - return FALSE; - } - - in = (Channel *) DatabusGetInChannel(db, channel); - if (!in) { - return FALSE; - } - - return in->IsValid(in); -} - -int DatabusChannelInIsConnected(struct Databus * db, size_t channel) { - Channel * in = NULL; - - if (!db) { - return FALSE; - } - - in = (Channel *) DatabusGetInChannel(db, channel); - if (!in) { - return FALSE; - } - - return in->IsConnected(in); -} - -int DatabusChannelOutIsValid(Databus * db, size_t channel) { - Channel * out = NULL; - - if (!db) { - return FALSE; - } - - out = (Channel *) DatabusGetOutChannel(db, channel); - if (!out) { - return FALSE; - } - - return out->IsValid(out); -} - -int DatabusChannelLocalIsValid(Databus * db, size_t channel) { - Channel * local = NULL; - - if (!db) { - return FALSE; - } - - local = (Channel *) DatabusGetLocalChannel(db, channel); - if (!local) { - return FALSE; - } - - return local->IsValid(local); -} - -int DatabusChannelRTFactorIsValid(Databus * db, size_t channel) { - Channel * rtfactor = NULL; - - if (!db) { - return FALSE; - } - - rtfactor = (Channel *) DatabusGetRTFactorChannel(db, channel); - if (!rtfactor) { - return FALSE; - } - - return rtfactor->IsValid(rtfactor); -} - McxStatus DatabusCollectModeSwitchData(Databus * db) { Vector * infos = db->data->outInfo->data->infos; size_t size = infos->Size(infos); diff --git a/src/core/Databus.h b/src/core/Databus.h index 8ae0cfe..7e0df44 100644 --- a/src/core/Databus.h +++ b/src/core/Databus.h @@ -150,37 +150,6 @@ struct ChannelInfo * DatabusGetInChannelInfo (struct Databus * db, size_t channe */ struct ChannelInfo * DatabusGetOutChannelInfo(struct Databus * db, size_t channel); -/** - * \return \c TRUE if the in channel \a channel in \a db is connected or - * provides a default value, and \c FALSE if it is not connected or \a db or \a - * channel are invalid. - */ -int DatabusChannelInIsValid(struct Databus * db, size_t channel); - -/** - * \return \c TRUE if the in channel \a channel in \a db is connected or - * and \c FALSE otherwise - */ -int DatabusChannelInIsConnected(struct Databus * db, size_t channel); - -/** - * \return \c TRUE if the out channel \a channel in \a db is connected, and \c - * FALSE if it is not connected or \a db or \a channel are invalid. - */ -int DatabusChannelOutIsValid(struct Databus * db, size_t channel); - -/** - * \return \c TRUE if the local channel \a channel in \a db has a reference, and \c - * FALSE if it has no reference or \a db or \a channel are invalid. - */ -int DatabusChannelLocalIsValid(struct Databus * db, size_t channel); - -/** - * \return \c TRUE if the rtfactor channel \a channel in \a db has a reference, and \c - * FALSE if it has no reference or \a db or \a channel are invalid. - */ -int DatabusChannelRTFactorIsValid(struct Databus * db, size_t channel); - /** private interface for Component **/ diff --git a/src/core/Model.c b/src/core/Model.c index 1969b0d..2c97c22 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -950,12 +950,11 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para for (i = 0; i < numInChannels; i++) { Channel * channel = (Channel *)DatabusGetInChannel(db, i); + ChannelIn * in = (ChannelIn *) channel; ChannelInfo * info = &channel->info; - if ((info->mode == CHANNEL_MANDATORY) - && !channel->IsValid(channel)) { - mcx_log(LOG_ERROR, "Model: %zu. inport (%s) of element %s not connected" - , i+1, ChannelInfoGetName(info), comp->GetName(comp)); + if (info->mode == CHANNEL_MANDATORY && !channel->ProvidesValue(channel)) { + mcx_log(LOG_ERROR, "Model: %zu. inport (%s) of element %s not connected", i+1, ChannelInfoGetName(info), comp->GetName(comp)); return RETURN_ERROR; } } @@ -964,10 +963,8 @@ static McxStatus ModelDoComponentConsistencyChecks(Component * comp, void * para Channel * channel = (Channel *)DatabusGetOutChannel(db, i); ChannelInfo * info = &channel->info; - if ((info->mode == CHANNEL_MANDATORY) - && !channel->IsValid(channel)) { - mcx_log(LOG_ERROR, "Model: %zu. outport (%s) of element %s not connected" - , i+1, ChannelInfoGetName(info), comp->GetName(comp)); + if (info->mode == CHANNEL_MANDATORY && !channel->ProvidesValue(channel)) { + mcx_log(LOG_ERROR, "Model: %zu. outport (%s) of element %s not connected", i+1, ChannelInfoGetName(info), comp->GetName(comp)); return RETURN_ERROR; } } @@ -1483,7 +1480,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, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%zu%d
\n"); @@ -1501,7 +1498,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, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%zu%d
\n"); @@ -1525,7 +1522,7 @@ McxStatus PrintComponentGraph(Component * comp, } GetDependency(A, i, grp, &dep); if (dep != DEP_INDEPENDENT) { - mcx_os_fprintf(dotFile, "in:in%zu -> out:out%zu;\n", i, j); + mcx_os_fprintf(dotFile, "in:in%d -> out:out%d;\n", i, j); } } } @@ -1567,14 +1564,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%zu%d
\n"); } mcx_os_fprintf(dotFile, " \n"); mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, ">] comp%zu;\n", comps->Size(comps)); + mcx_os_fprintf(dotFile, ">] comp%d;\n", comps->Size(comps)); } for (i = 0; i < comps->Size(comps); i++) { @@ -1590,7 +1587,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%zu%d
\n"); @@ -1604,14 +1601,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%zu%d
\n"); } mcx_os_fprintf(dotFile, " \n"); mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, ">] comp%zu;\n", c->GetID(c)); + mcx_os_fprintf(dotFile, ">] comp%d;\n", c->GetID(c)); } if (outComp) { @@ -1626,7 +1623,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%zu%d
\n"); @@ -1634,13 +1631,13 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n"); mcx_os_fprintf(dotFile, " out\n"); mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, ">] comp%zu;\n", comps->Size(comps) + 1); + mcx_os_fprintf(dotFile, ">] comp%d;\n", comps->Size(comps) + 1); } mcx_os_fprintf(dotFile, "{\n"); if (inComp && outComp) { - mcx_os_fprintf(dotFile, "comp%zu -> comp%zu [style=invis];\n", + mcx_os_fprintf(dotFile, "comp%d -> comp%d [style=invis];\n", comps->Size(comps), comps->Size(comps) + 1); } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index e720d98..9a52e41 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -139,9 +139,10 @@ static Channel * ChannelCreate(Channel * channel) { // virtual functions channel->GetValueReference = NULL; channel->Update = NULL; - channel->IsValid = NULL; + channel->ProvidesValue = NULL; channel->IsConnected = NULL; + channel->IsFullyConnected = NULL; return channel; } @@ -247,7 +248,7 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel static const void * ChannelInGetValueReference(Channel * channel) { ChannelIn * in = (ChannelIn *) channel; - if (!channel->IsValid(channel)) { + if (!channel->ProvidesValue(channel)) { const static int maxCountError = 10; static int i = 0; if (i < maxCountError) { @@ -341,9 +342,28 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } -static int ChannelInIsValid(Channel * channel) { +static int ChannelInIsFullyConnected(Channel * channel) { + ChannelIn * in = (ChannelIn *) channel; + size_t i = 0; + size_t connectedElems = 0; + size_t channelNumElems = channel->info.dimension ? ChannelDimensionNumElements(channel->info.dimension) : 1; + + for (i = 0; i < in->data->connections->Size(in->data->connections); i++) { + Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); + ConnectionInfo * info = &conn->info; - if (channel->IsConnected(channel)) { + connectedElems += info->targetDimension ? ChannelDimensionNumElements(info->targetDimension) : 1; + } + + if (connectedElems == channelNumElems) { + return TRUE; + } + + return FALSE; +} + +static int ChannelInProvidesValue(Channel * channel) { + if (ChannelInIsFullyConnected(channel)) { return TRUE; } else { ChannelInfo * info = &channel->info; @@ -574,9 +594,10 @@ static ChannelIn * ChannelInCreate(ChannelIn * in) { // virtual functions channel->GetValueReference = ChannelInGetValueReference; - channel->IsValid = ChannelInIsValid; + channel->ProvidesValue = ChannelInProvidesValue; channel->Update = ChannelInUpdate; channel->IsConnected = ChannelInIsConnected; + channel->IsFullyConnected = ChannelInIsFullyConnected; in->Setup = ChannelInSetup; in->SetReference = ChannelInSetReference; @@ -718,7 +739,7 @@ static const void * ChannelOutGetValueReference(Channel * channel) { ChannelInfo * info = &channel->info; // check if out is initialized - if (!channel->IsValid(channel)) { + if (!channel->ProvidesValue(channel)) { mcx_log(LOG_ERROR, "Port %s: Get value reference: No Value Reference", ChannelInfoGetLogName(info)); return NULL; } @@ -734,7 +755,7 @@ static ObjectList * ChannelOutGetConnections(ChannelOut * out) { return out->data->connections; } -static int ChannelOutIsValid(Channel * channel) { +static int ChannelOutProvidesValue(Channel * channel) { return (NULL != channel->internalValue); } @@ -753,6 +774,43 @@ static int ChannelOutIsConnected(Channel * channel) { return FALSE; } +static int ChannelOutIsFullyConnected(Channel * channel) { + ChannelOut * out = (ChannelOut *) channel; + + if (ChannelTypeIsArray(&channel->info.type)) { + ObjectList* conns = out->data->connections; + size_t i = 0; + size_t num_elems = ChannelDimensionNumElements(channel->info.dimension); + + int * connected = (int *) mcx_calloc(num_elems, sizeof(int)); + if (!connected) { + mcx_log(LOG_ERROR, "ChannelOutIsFullyConnected: Not enough memory"); + return -1; + } + + for (i = 0; i < conns->Size(conns); i++) { + Connection * conn = (Connection *) out->data->connections->At(out->data->connections, i); + ConnectionInfo * info = &conn->info; + size_t j = 0; + + for (j = 0; j < ChannelDimensionNumElements(info->sourceDimension); i++) { + size_t idx = ChannelDimensionGetIndex(info->sourceDimension, j, channel->info.type->ty.a.dims); + connected[idx] = 1; + } + } + + for (i = 0; i < num_elems; i++) { + if (!connected[i]) { + return FALSE; + } + } + + return TRUE; + } else { + return ChannelOutIsConnected(channel); + } +} + static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference, ChannelType * type) { Channel * channel = (Channel *) out; ChannelInfo * info = NULL; @@ -978,9 +1036,10 @@ static ChannelOut * ChannelOutCreate(ChannelOut * out) { // virtual functions channel->GetValueReference = ChannelOutGetValueReference; - channel->IsValid = ChannelOutIsValid; + channel->ProvidesValue = ChannelOutProvidesValue; channel->Update = ChannelOutUpdate; channel->IsConnected = ChannelOutIsConnected; + channel->IsFullyConnected = ChannelOutIsFullyConnected; out->Setup = ChannelOutSetup; out->RegisterConnection = ChannelOutRegisterConnection; @@ -1020,7 +1079,7 @@ static McxStatus ChannelLocalUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } -static int ChannelLocalIsValid(Channel * channel) { +static int ChannelLocalProvidesValue(Channel * channel) { return (channel->internalValue != NULL); } @@ -1068,9 +1127,9 @@ static ChannelLocal * ChannelLocalCreate(ChannelLocal * local) { // virtual functions channel->GetValueReference = ChannelLocalGetValueReference; channel->Update = ChannelLocalUpdate; - channel->IsValid = ChannelLocalIsValid; + channel->ProvidesValue = ChannelLocalProvidesValue; - channel->IsConnected = ChannelLocalIsValid; + channel->IsConnected = ChannelLocalProvidesValue; local->Setup = ChannelLocalSetup; local->SetReference = ChannelLocalSetReference; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index 7dae1cb..dbebf8d 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -37,6 +37,8 @@ typedef int (* fChannelIsValid)(Channel * channel); typedef int (* fChannelIsConnected)(Channel * channel); +typedef int (* fChannelIsFullyConnected)(Channel * channel); + typedef int (* fChannelIsDefinedDuringInit)(Channel * channel); typedef void (* fChannelSetDefinedDuringInit)(Channel * channel); @@ -82,13 +84,18 @@ struct Channel { * * Returns true if a channel provides a value (connected or default value) */ - fChannelIsValid IsValid; + fChannelIsValid ProvidesValue; /** - * Returns true if a channel is connected + * Returns true if a channel is connected (i.e., atleast one element of the channel) */ fChannelIsConnected IsConnected; + /** + * Returns true if all elements of the channel are connected + */ + fChannelIsFullyConnected IsFullyConnected; + /** * Getter for the flag data->isDefinedDuringInit */ From e2aaaa817c16e08dc336d50cb83f7a21d71bfe89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 1 Jun 2022 09:16:26 +0200 Subject: [PATCH 228/295] FMU2: Take into account vector elements during dependency matrix generation --- src/components/comp_fmu.c | 236 ++++++++++++++++++++++++++++++++------ 1 file changed, 201 insertions(+), 35 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 3292f41..c37e7c4 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -1095,6 +1095,41 @@ static ChannelMode GetInChannelDefaultMode(struct Component * comp) { return CHANNEL_OPTIONAL; } +typedef struct ConnectedElems{ + int is_connected; + size_t num_elems; + size_t * elems; +} ConnectedElems; + +typedef struct ChannelElement { + size_t channel_idx; + size_t elem_idx; +} ChannelElement; + +static Vector * GetAllElems(ChannelElement * elems, size_t num, size_t channel_idx) { + size_t i = 0; + Vector * indices = (Vector *) object_create(Vector); + + if (!indices) { + mcx_log(LOG_ERROR, "GetAllElems: Not enough memory"); + return NULL; + } + + indices->Setup(indices, sizeof(size_t), NULL, NULL, NULL); + + for (i = 0; i < num; i++) { + if (elems[i].channel_idx == channel_idx) { + if (RETURN_ERROR == indices->PushBack(indices, &elems[i].elem_idx)) { + mcx_log(LOG_ERROR, "GetAllElems: Collecting element indices failed"); + object_destroy(indices); + return NULL; + } + } + } + + return indices; +} + static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps) { Component * comp = (Component *) compFmu; McxStatus ret_val = RETURN_OK; @@ -1107,12 +1142,10 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps size_t num_dependencies = 0; size_t dep_idx = 0; + // mapping between dependency indices (from the modelDescription file) and the dependency <-> channel mapping SizeTSizeTMap *dependencies_to_in_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); - // dictionary used to store input connection information - SizeTSizeTMap *in_channel_connectivity = (SizeTSizeTMap*)object_create(SizeTSizeTMap); + // mapping between unknown indices (from the modelDescription file) and the unknowns <-> channel list SizeTSizeTMap *unknowns_to_out_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); - // dictionary used to later find ommitted elements - SizeTSizeTMap *processed_out_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); // get dependency information via the fmi library fmi2_import_variable_list_t * init_unknowns = fmi2_import_get_initial_unknowns_list(compFmu->fmu2.fmiImport); @@ -1132,19 +1165,104 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps DatabusInfo * db_info = DatabusGetInInfo(db); size_t num_in_channels = DatabusInfoGetChannelNum(db_info); + // list describing for each channel which channel elements are connected + ConnectedElems * in_channel_connectivity = (ConnectedElems *) mcx_calloc(num_in_channels, sizeof(ConnectedElems)); + if (!in_channel_connectivity) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity map allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // List which for each dependency describes which channel and element index it corresponds to + // The index of elements in this list doesn't correspond to the dependency index from the modelDescription file + ChannelElement * dependencies_to_inputs = (ChannelElement *) mcx_calloc(DatabusGetInChannelsElemNum(db), sizeof(ChannelElement)); + if (!dependencies_to_inputs) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Dependencies to inputs map allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // list used to know the mapping between unknowns and channels/elements + ChannelElement * unknowns_to_outputs = (ChannelElement *) mcx_calloc(DatabusGetOutChannelsElemNum(db), sizeof(ChannelElement)); + if (!unknowns_to_outputs) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Unknowns to outputs map allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // List used to later find ommitted elements + ChannelElement * processed_output_elems = (ChannelElement *) mcx_calloc(DatabusGetOutChannelsElemNum(db), sizeof(ChannelElement)); + if (!processed_output_elems) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Processed output elements allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + for (i = 0; i < num_in_vars; ++i) { Fmu2Value *val = (Fmu2Value *)in_vars->At(in_vars, i); Channel * ch = (Channel *) DatabusGetInChannel(db, i); + ChannelIn * in = (ChannelIn *) ch; ChannelInfo * info = DatabusInfoGetChannel(db_info, i); if (ch->IsConnected(ch)) { - // key i in the map means channel i is connected - in_channel_connectivity->Add(in_channel_connectivity, i, 1 /* true */); + if (ChannelTypeIsArray(info->type)) { + in_channel_connectivity[i].is_connected = TRUE; + in_channel_connectivity[i].num_elems = 0; + in_channel_connectivity[i].elems = (int *) mcx_calloc(ChannelDimensionNumElements(info->dimension), sizeof(size_t)); + if (!in_channel_connectivity[i].elems) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity element container allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // if an element index appears in elems, it means that element is connected + ObjectContainer * connInfos = in->GetConnectionInfos(in); + for (j = 0; j < connInfos->Size(connInfos); j++) { + ConnectionInfo * connInfo = (ConnectionInfo *) connInfos->At(connInfos, j); + size_t k = 0; + + for (k = 0; k < ChannelDimensionNumElements(connInfo->targetDimension); k++) { + size_t idx = ChannelDimensionGetIndex(connInfo->targetDimension, k, info->type->ty.a.dims) - info->dimension->startIdxs[0]; + in_channel_connectivity[i].elems[in_channel_connectivity[i].num_elems++] = idx; + } + } + } else { + in_channel_connectivity[i].is_connected = TRUE; + // scalar channels are treated like they have 1 element (equal to zero) + in_channel_connectivity[i].num_elems = 1; + in_channel_connectivity[i].elems = (int*)mcx_calloc(1, sizeof(size_t)); + if (!in_channel_connectivity[i].elems) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity element allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + in_channel_connectivity[i].elems[0] = 0; + } } if (val->data->type == FMU2_VALUE_SCALAR) { fmi2_import_variable_t *var = val->data->data.scalar; size_t idx = fmi2_import_get_variable_original_order(var) + 1; - dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, i); + dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, dep_idx); + + dependencies_to_inputs[dep_idx].channel_idx = i; + dep_idx++; + } else if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; + + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + fmi2_import_variable_t * var = val->data->data.array.values[j]; + size_t idx = fmi2_import_get_variable_original_order(var) + 1; + dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, dep_idx); + + dependencies_to_inputs[dep_idx].channel_idx = i; + dependencies_to_inputs[dep_idx].elem_idx = j; + dep_idx++; + } } } @@ -1153,8 +1271,7 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps if (start_index == NULL) { for (i = 0; i < GetDependencyNumOut(deps); ++i) { for (j = 0; j < GetDependencyNumIn(deps); ++j) { - SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, j); - if (elem) { + if (in_channel_connectivity[j].is_connected) { ret_val = SetDependency(deps, j, i, DEP_DEPENDENT); if (RETURN_OK != ret_val) { goto cleanup; @@ -1167,20 +1284,42 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps } // map each initial_unkown index to an output channel index + // for array channels, there might be multiple entries initial_unknown_idx -> channel_idx ObjectContainer *out_vars = compFmu->fmu2.out; size_t num_out_vars = out_vars->Size(out_vars); - + size_t unknown_idx = 0; for (i = 0; i < num_out_vars; ++i) { Fmu2Value *val = (Fmu2Value *)out_vars->At(out_vars, i); if (val->data->type == FMU2_VALUE_SCALAR) { fmi2_import_variable_t *var = val->data->data.scalar; size_t idx = fmi2_import_get_variable_original_order(var) + 1; - unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, i); + unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, unknown_idx); + + unknowns_to_outputs[unknown_idx].channel_idx = i; + unknown_idx++; + } else if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; + + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + fmi2_import_variable_t * var = val->data->data.array.values[j]; + size_t idx = fmi2_import_get_variable_original_order(var) + 1; + unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, unknown_idx); + + unknowns_to_outputs[unknown_idx].channel_idx = i; + unknowns_to_outputs[unknown_idx].elem_idx = j; + unknown_idx++; + } } } // fill up the dependency matrix + size_t processed_elems = 0; for (i = 0; i < num_init_unknowns; ++i) { fmi2_import_variable_t *init_unknown = fmi2_import_get_variable(init_unknowns, i); size_t init_unknown_idx = fmi2_import_get_variable_original_order(init_unknown) + 1; @@ -1190,7 +1329,11 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps continue; // in case some variables are ommitted from the input file } - processed_out_channels->Add(processed_out_channels, out_pair->value, 1); + ChannelElement * out_elem = &unknowns_to_outputs[out_pair->value]; + + processed_output_elems[processed_elems].channel_idx = out_elem->channel_idx; + processed_output_elems[processed_elems].elem_idx = out_elem->elem_idx; + processed_elems++; num_dependencies = start_index[i + 1] - start_index[i]; for (j = 0; j < num_dependencies; ++j) { @@ -1199,9 +1342,8 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps // The element does not explicitly define a `dependencies` attribute // In this case it depends on all inputs for (k = 0; k < num_in_channels; ++k) { - SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, k); - if (elem) { - ret_val = SetDependency(deps, k, out_pair->value, DEP_DEPENDENT); + if (in_channel_connectivity[k].is_connected) { + ret_val = SetDependency(deps, k, out_elem->channel_idx, DEP_DEPENDENT); if (RETURN_OK != ret_val) { goto cleanup; } @@ -1210,13 +1352,20 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps } else { // The element explicitly defines its dependencies SizeTSizeTElem * in_pair = dependencies_to_in_channels->Get(dependencies_to_in_channels, dep_idx); - if (in_pair) { - SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, in_pair->value); - if (elem) { - ret_val = SetDependency(deps, in_pair->value, out_pair->value, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup; + ChannelElement * dep = &dependencies_to_inputs[in_pair->value]; + + ConnectedElems * elems = &in_channel_connectivity[dep->channel_idx]; + if (elems->is_connected) { + size_t k = 0; + for (k = 0; k < elems->num_elems; k++) { + if (elems->elems[k] == dep->elem_idx) { + ret_val = SetDependency(deps, dep->channel_idx, out_elem->channel_idx, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } + break; + } } } } @@ -1227,16 +1376,23 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps // Initial unknowns which are ommitted from the element in // modelDescription.xml file depend on all inputs for (i = 0; i < num_out_vars; ++i) { - if (processed_out_channels->Get(processed_out_channels, i) == NULL) { - Fmu2Value *val = (Fmu2Value *)out_vars->At(out_vars, i); + Fmu2Value * val = (Fmu2Value *) out_vars->At(out_vars, i); + + Vector * elems = GetAllElems(processed_output_elems, processed_elems, i); + + if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; - if (val->data->type == FMU2_VALUE_ARRAY) { - size_t elem_idx = 0; - for (elem_idx = 0; elem_idx < val->data->data.array.numDims; elem_idx++) { - if (fmi2_import_get_initial(val->data->data.array.values[elem_idx]) != fmi2_initial_enu_exact) { + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + if (!elems->Contains(elems, &j)) { + if (fmi2_import_get_initial(val->data->data.array.values[j]) != fmi2_initial_enu_exact) { for (k = 0; k < num_in_channels; ++k) { - SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, k); - if (elem) { + if (in_channel_connectivity[k].is_connected) { ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); if (RETURN_OK != ret_val) { goto cleanup; @@ -1245,27 +1401,37 @@ static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps } } } - } else { + } + } else { + if (elems->Size(elems) == 0) { if (fmi2_import_get_initial(val->data->data.scalar) != fmi2_initial_enu_exact) { for (k = 0; k < num_in_channels; ++k) { - SizeTSizeTElem * elem = in_channel_connectivity->Get(in_channel_connectivity, k); - if (elem) { + if (in_channel_connectivity[k].is_connected) { ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); if (RETURN_OK != ret_val) { - goto cleanup; + goto cleanup_1; } } } } } } + + object_destroy(elems); + continue; + +cleanup_1: + object_destroy(elems); + goto cleanup; } cleanup: // free dynamically allocated objects object_destroy(dependencies_to_in_channels); - object_destroy(in_channel_connectivity); object_destroy(unknowns_to_out_channels); - object_destroy(processed_out_channels); + if (in_channel_connectivity) { mcx_free(in_channel_connectivity); } + if (dependencies_to_inputs) { mcx_free(dependencies_to_inputs); } + if (unknowns_to_outputs) { mcx_free(unknowns_to_outputs); } + if (processed_output_elems) { mcx_free(processed_output_elems); } fmi2_import_free_variable_list(init_unknowns); return ret_val; From 505c84959209aae9538c23c34585cfe0fe2acfb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 1 Jun 2022 12:01:15 +0200 Subject: [PATCH 229/295] Move dependency matrix generation code to common --- src/components/comp_fmu.c | 344 +------------------------------------ src/core/Dependency.h | 2 +- src/fmu/common_fmu2.c | 349 ++++++++++++++++++++++++++++++++++++++ src/fmu/common_fmu2.h | 4 + 4 files changed, 355 insertions(+), 344 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index c37e7c4..ca8cf76 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -1095,348 +1095,6 @@ static ChannelMode GetInChannelDefaultMode(struct Component * comp) { return CHANNEL_OPTIONAL; } -typedef struct ConnectedElems{ - int is_connected; - size_t num_elems; - size_t * elems; -} ConnectedElems; - -typedef struct ChannelElement { - size_t channel_idx; - size_t elem_idx; -} ChannelElement; - -static Vector * GetAllElems(ChannelElement * elems, size_t num, size_t channel_idx) { - size_t i = 0; - Vector * indices = (Vector *) object_create(Vector); - - if (!indices) { - mcx_log(LOG_ERROR, "GetAllElems: Not enough memory"); - return NULL; - } - - indices->Setup(indices, sizeof(size_t), NULL, NULL, NULL); - - for (i = 0; i < num; i++) { - if (elems[i].channel_idx == channel_idx) { - if (RETURN_ERROR == indices->PushBack(indices, &elems[i].elem_idx)) { - mcx_log(LOG_ERROR, "GetAllElems: Collecting element indices failed"); - object_destroy(indices); - return NULL; - } - } - } - - return indices; -} - -static McxStatus SetDependenciesFMU2(CompFMU *compFmu, struct Dependencies *deps) { - Component * comp = (Component *) compFmu; - McxStatus ret_val = RETURN_OK; - - size_t *start_index = NULL; - size_t *dependency = NULL; - char *factor_kind = NULL; - - size_t i = 0, j = 0, k = 0; - size_t num_dependencies = 0; - size_t dep_idx = 0; - - // mapping between dependency indices (from the modelDescription file) and the dependency <-> channel mapping - SizeTSizeTMap *dependencies_to_in_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); - // mapping between unknown indices (from the modelDescription file) and the unknowns <-> channel list - SizeTSizeTMap *unknowns_to_out_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); - - // get dependency information via the fmi library - fmi2_import_variable_list_t * init_unknowns = fmi2_import_get_initial_unknowns_list(compFmu->fmu2.fmiImport); - size_t num_init_unknowns = fmi2_import_get_variable_list_size(init_unknowns); - - fmi2_import_get_initial_unknowns_dependencies(compFmu->fmu2.fmiImport, &start_index, &dependency, &factor_kind); - - // the dependency information in is encoded via variable indices in modelDescription.xml - // our dependency matrix uses channel indices - // to align those 2 index types we use helper dictionaries which store the mapping between them - - // map each dependency index to an input channel index - ObjectContainer *in_vars = compFmu->fmu2.in; - size_t num_in_vars = in_vars->Size(in_vars); - - Databus * db = comp->GetDatabus(comp); - DatabusInfo * db_info = DatabusGetInInfo(db); - size_t num_in_channels = DatabusInfoGetChannelNum(db_info); - - // list describing for each channel which channel elements are connected - ConnectedElems * in_channel_connectivity = (ConnectedElems *) mcx_calloc(num_in_channels, sizeof(ConnectedElems)); - if (!in_channel_connectivity) { - mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity map allocation failed"); - ret_val = RETURN_ERROR; - goto cleanup; - } - - // List which for each dependency describes which channel and element index it corresponds to - // The index of elements in this list doesn't correspond to the dependency index from the modelDescription file - ChannelElement * dependencies_to_inputs = (ChannelElement *) mcx_calloc(DatabusGetInChannelsElemNum(db), sizeof(ChannelElement)); - if (!dependencies_to_inputs) { - mcx_log(LOG_ERROR, "SetDependenciesFMU2: Dependencies to inputs map allocation failed"); - ret_val = RETURN_ERROR; - goto cleanup; - } - - // list used to know the mapping between unknowns and channels/elements - ChannelElement * unknowns_to_outputs = (ChannelElement *) mcx_calloc(DatabusGetOutChannelsElemNum(db), sizeof(ChannelElement)); - if (!unknowns_to_outputs) { - mcx_log(LOG_ERROR, "SetDependenciesFMU2: Unknowns to outputs map allocation failed"); - ret_val = RETURN_ERROR; - goto cleanup; - } - - // List used to later find ommitted elements - ChannelElement * processed_output_elems = (ChannelElement *) mcx_calloc(DatabusGetOutChannelsElemNum(db), sizeof(ChannelElement)); - if (!processed_output_elems) { - mcx_log(LOG_ERROR, "SetDependenciesFMU2: Processed output elements allocation failed"); - ret_val = RETURN_ERROR; - goto cleanup; - } - - for (i = 0; i < num_in_vars; ++i) { - Fmu2Value *val = (Fmu2Value *)in_vars->At(in_vars, i); - Channel * ch = (Channel *) DatabusGetInChannel(db, i); - ChannelIn * in = (ChannelIn *) ch; - ChannelInfo * info = DatabusInfoGetChannel(db_info, i); - if (ch->IsConnected(ch)) { - if (ChannelTypeIsArray(info->type)) { - in_channel_connectivity[i].is_connected = TRUE; - in_channel_connectivity[i].num_elems = 0; - in_channel_connectivity[i].elems = (int *) mcx_calloc(ChannelDimensionNumElements(info->dimension), sizeof(size_t)); - if (!in_channel_connectivity[i].elems) { - mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity element container allocation failed"); - ret_val = RETURN_ERROR; - goto cleanup; - } - - // if an element index appears in elems, it means that element is connected - ObjectContainer * connInfos = in->GetConnectionInfos(in); - for (j = 0; j < connInfos->Size(connInfos); j++) { - ConnectionInfo * connInfo = (ConnectionInfo *) connInfos->At(connInfos, j); - size_t k = 0; - - for (k = 0; k < ChannelDimensionNumElements(connInfo->targetDimension); k++) { - size_t idx = ChannelDimensionGetIndex(connInfo->targetDimension, k, info->type->ty.a.dims) - info->dimension->startIdxs[0]; - in_channel_connectivity[i].elems[in_channel_connectivity[i].num_elems++] = idx; - } - } - } else { - in_channel_connectivity[i].is_connected = TRUE; - // scalar channels are treated like they have 1 element (equal to zero) - in_channel_connectivity[i].num_elems = 1; - in_channel_connectivity[i].elems = (int*)mcx_calloc(1, sizeof(size_t)); - if (!in_channel_connectivity[i].elems) { - mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity element allocation failed"); - ret_val = RETURN_ERROR; - goto cleanup; - } - in_channel_connectivity[i].elems[0] = 0; - } - } - - if (val->data->type == FMU2_VALUE_SCALAR) { - fmi2_import_variable_t *var = val->data->data.scalar; - size_t idx = fmi2_import_get_variable_original_order(var) + 1; - dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, dep_idx); - - dependencies_to_inputs[dep_idx].channel_idx = i; - dep_idx++; - } else if (val->data->type == FMU2_VALUE_ARRAY) { - size_t num_elems = 1; - size_t j = 0; - - for (j = 0; j < val->data->data.array.numDims; j++) { - num_elems *= val->data->data.array.dims[j]; - } - - for (j = 0; j < num_elems; j++) { - fmi2_import_variable_t * var = val->data->data.array.values[j]; - size_t idx = fmi2_import_get_variable_original_order(var) + 1; - dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, dep_idx); - - dependencies_to_inputs[dep_idx].channel_idx = i; - dependencies_to_inputs[dep_idx].elem_idx = j; - dep_idx++; - } - } - } - - // element is not present in modelDescription.xml - // The dependency matrix consists of only 1 (if input is connected) - if (start_index == NULL) { - for (i = 0; i < GetDependencyNumOut(deps); ++i) { - for (j = 0; j < GetDependencyNumIn(deps); ++j) { - if (in_channel_connectivity[j].is_connected) { - ret_val = SetDependency(deps, j, i, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup; - } - } - } - } - - goto cleanup; - } - - // map each initial_unkown index to an output channel index - // for array channels, there might be multiple entries initial_unknown_idx -> channel_idx - ObjectContainer *out_vars = compFmu->fmu2.out; - size_t num_out_vars = out_vars->Size(out_vars); - size_t unknown_idx = 0; - for (i = 0; i < num_out_vars; ++i) { - Fmu2Value *val = (Fmu2Value *)out_vars->At(out_vars, i); - - if (val->data->type == FMU2_VALUE_SCALAR) { - fmi2_import_variable_t *var = val->data->data.scalar; - size_t idx = fmi2_import_get_variable_original_order(var) + 1; - unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, unknown_idx); - - unknowns_to_outputs[unknown_idx].channel_idx = i; - unknown_idx++; - } else if (val->data->type == FMU2_VALUE_ARRAY) { - size_t num_elems = 1; - size_t j = 0; - - for (j = 0; j < val->data->data.array.numDims; j++) { - num_elems *= val->data->data.array.dims[j]; - } - - for (j = 0; j < num_elems; j++) { - fmi2_import_variable_t * var = val->data->data.array.values[j]; - size_t idx = fmi2_import_get_variable_original_order(var) + 1; - unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, unknown_idx); - - unknowns_to_outputs[unknown_idx].channel_idx = i; - unknowns_to_outputs[unknown_idx].elem_idx = j; - unknown_idx++; - } - } - } - - // fill up the dependency matrix - size_t processed_elems = 0; - for (i = 0; i < num_init_unknowns; ++i) { - fmi2_import_variable_t *init_unknown = fmi2_import_get_variable(init_unknowns, i); - size_t init_unknown_idx = fmi2_import_get_variable_original_order(init_unknown) + 1; - - SizeTSizeTElem * out_pair = unknowns_to_out_channels->Get(unknowns_to_out_channels, init_unknown_idx); - if (out_pair == NULL) { - continue; // in case some variables are ommitted from the input file - } - - ChannelElement * out_elem = &unknowns_to_outputs[out_pair->value]; - - processed_output_elems[processed_elems].channel_idx = out_elem->channel_idx; - processed_output_elems[processed_elems].elem_idx = out_elem->elem_idx; - processed_elems++; - - num_dependencies = start_index[i + 1] - start_index[i]; - for (j = 0; j < num_dependencies; ++j) { - dep_idx = dependency[start_index[i] + j]; - if (dep_idx == 0) { - // The element does not explicitly define a `dependencies` attribute - // In this case it depends on all inputs - for (k = 0; k < num_in_channels; ++k) { - if (in_channel_connectivity[k].is_connected) { - ret_val = SetDependency(deps, k, out_elem->channel_idx, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup; - } - } - } - } else { - // The element explicitly defines its dependencies - SizeTSizeTElem * in_pair = dependencies_to_in_channels->Get(dependencies_to_in_channels, dep_idx); - if (in_pair) { - ChannelElement * dep = &dependencies_to_inputs[in_pair->value]; - - ConnectedElems * elems = &in_channel_connectivity[dep->channel_idx]; - if (elems->is_connected) { - size_t k = 0; - for (k = 0; k < elems->num_elems; k++) { - if (elems->elems[k] == dep->elem_idx) { - ret_val = SetDependency(deps, dep->channel_idx, out_elem->channel_idx, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup; - } - break; - } - } - } - } - } - } - } - - // Initial unknowns which are ommitted from the element in - // modelDescription.xml file depend on all inputs - for (i = 0; i < num_out_vars; ++i) { - Fmu2Value * val = (Fmu2Value *) out_vars->At(out_vars, i); - - Vector * elems = GetAllElems(processed_output_elems, processed_elems, i); - - if (val->data->type == FMU2_VALUE_ARRAY) { - size_t num_elems = 1; - size_t j = 0; - - for (j = 0; j < val->data->data.array.numDims; j++) { - num_elems *= val->data->data.array.dims[j]; - } - - for (j = 0; j < num_elems; j++) { - if (!elems->Contains(elems, &j)) { - if (fmi2_import_get_initial(val->data->data.array.values[j]) != fmi2_initial_enu_exact) { - for (k = 0; k < num_in_channels; ++k) { - if (in_channel_connectivity[k].is_connected) { - ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup; - } - } - } - } - } - } - } else { - if (elems->Size(elems) == 0) { - if (fmi2_import_get_initial(val->data->data.scalar) != fmi2_initial_enu_exact) { - for (k = 0; k < num_in_channels; ++k) { - if (in_channel_connectivity[k].is_connected) { - ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); - if (RETURN_OK != ret_val) { - goto cleanup_1; - } - } - } - } - } - } - - object_destroy(elems); - continue; - -cleanup_1: - object_destroy(elems); - goto cleanup; - } - -cleanup: // free dynamically allocated objects - object_destroy(dependencies_to_in_channels); - object_destroy(unknowns_to_out_channels); - if (in_channel_connectivity) { mcx_free(in_channel_connectivity); } - if (dependencies_to_inputs) { mcx_free(dependencies_to_inputs); } - if (unknowns_to_outputs) { mcx_free(unknowns_to_outputs); } - if (processed_output_elems) { mcx_free(processed_output_elems); } - fmi2_import_free_variable_list(init_unknowns); - - return ret_val; -} - static struct Dependencies* Fmu2GetInOutGroupsInitialDependency(const Component * comp) { CompFMU *comp_fmu = (CompFMU *)comp; struct Dependencies *dependencies = NULL; @@ -1464,7 +1122,7 @@ static struct Dependencies* Fmu2GetInOutGroupsInitialDependency(const Component } } else { dependencies = DependenciesCreate(num_in, num_out); - if (SetDependenciesFMU2(comp_fmu, dependencies) != RETURN_OK) { + if (Fmu2SetDependencies(&comp_fmu->fmu2, db, dependencies, TRUE) != RETURN_OK) { mcx_log(LOG_ERROR, "Initial dependency matrix for %s could not be created", comp->GetName(comp)); return NULL; } diff --git a/src/core/Dependency.h b/src/core/Dependency.h index 861cca9..4a04a03 100644 --- a/src/core/Dependency.h +++ b/src/core/Dependency.h @@ -24,7 +24,7 @@ typedef enum DependencyDef { DEP_FIXED = 3, } Dependency; -struct Dependencies; +typedef struct Dependencies Dependencies; struct Dependencies * DependenciesCreate(size_t numIn, size_t numOut); diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 0602ecd..2aa3f0a 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -25,6 +25,8 @@ #include "util/stdlib.h" #include "util/signals.h" +#include "objects/Map.h" + #include "fmilib.h" #ifdef __cplusplus @@ -669,6 +671,353 @@ McxStatus Fmu2UpdateTunableParamValues(ObjectContainer * tunableParams, ObjectCo return retVal; } +typedef struct ConnectedElems{ + int is_connected; + size_t num_elems; + size_t * elems; +} ConnectedElems; + +typedef struct ChannelElement { + size_t channel_idx; + size_t elem_idx; +} ChannelElement; + +static Vector * GetAllElems(ChannelElement * elems, size_t num, size_t channel_idx) { + size_t i = 0; + Vector * indices = (Vector *) object_create(Vector); + + if (!indices) { + mcx_log(LOG_ERROR, "GetAllElems: Not enough memory"); + return NULL; + } + + indices->Setup(indices, sizeof(size_t), NULL, NULL, NULL); + + for (i = 0; i < num; i++) { + if (elems[i].channel_idx == channel_idx) { + if (RETURN_ERROR == indices->PushBack(indices, &elems[i].elem_idx)) { + mcx_log(LOG_ERROR, "GetAllElems: Collecting element indices failed"); + object_destroy(indices); + return NULL; + } + } + } + + return indices; +} + +McxStatus Fmu2SetDependencies(Fmu2CommonStruct * fmu2, Databus * db, Dependencies * deps, int init) { + McxStatus ret_val = RETURN_OK; + + size_t *start_index = NULL; + size_t *dependency = NULL; + char *factor_kind = NULL; + + size_t i = 0, j = 0, k = 0; + size_t num_dependencies = 0; + size_t dep_idx = 0; + + // mapping between dependency indices (from the modelDescription file) and the dependency <-> channel mapping + SizeTSizeTMap *dependencies_to_in_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); + // mapping between unknown indices (from the modelDescription file) and the unknowns <-> channel list + SizeTSizeTMap *unknowns_to_out_channels = (SizeTSizeTMap*)object_create(SizeTSizeTMap); + + // get dependency information via the fmi library + fmi2_import_variable_list_t * init_unknowns = NULL; + + if (init) { + init_unknowns = fmi2_import_get_initial_unknowns_list(fmu2->fmiImport); + fmi2_import_get_initial_unknowns_dependencies(fmu2->fmiImport, &start_index, &dependency, &factor_kind); + } else { + init_unknowns = fmi2_import_get_outputs_list(fmu2->fmiImport); + fmi2_import_get_outputs_dependencies(fmu2->fmiImport, &start_index, &dependency, &factor_kind); + } + + size_t num_init_unknowns = fmi2_import_get_variable_list_size(init_unknowns); + + // the dependency information in is encoded via variable indices in modelDescription.xml + // our dependency matrix uses channel indices + // to align those 2 index types we use helper dictionaries which store the mapping between them + + // map each dependency index to an input channel index + ObjectContainer *in_vars = fmu2->in; + size_t num_in_vars = in_vars->Size(in_vars); + + DatabusInfo * db_info = DatabusGetInInfo(db); + size_t num_in_channels = DatabusInfoGetChannelNum(db_info); + + // list describing for each channel which channel elements are connected + ConnectedElems * in_channel_connectivity = (ConnectedElems *) mcx_calloc(num_in_channels, sizeof(ConnectedElems)); + if (!in_channel_connectivity) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity map allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // List which for each dependency describes which channel and element index it corresponds to + // The index of elements in this list doesn't correspond to the dependency index from the modelDescription file + ChannelElement * dependencies_to_inputs = (ChannelElement *) mcx_calloc(DatabusGetInChannelsElemNum(db), sizeof(ChannelElement)); + if (!dependencies_to_inputs) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Dependencies to inputs map allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // list used to know the mapping between unknowns and channels/elements + ChannelElement * unknowns_to_outputs = (ChannelElement *) mcx_calloc(DatabusGetOutChannelsElemNum(db), sizeof(ChannelElement)); + if (!unknowns_to_outputs) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Unknowns to outputs map allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // List used to later find ommitted elements + ChannelElement * processed_output_elems = (ChannelElement *) mcx_calloc(DatabusGetOutChannelsElemNum(db), sizeof(ChannelElement)); + if (!processed_output_elems) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Processed output elements allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + for (i = 0; i < num_in_vars; ++i) { + Fmu2Value *val = (Fmu2Value *)in_vars->At(in_vars, i); + Channel * ch = (Channel *) DatabusGetInChannel(db, i); + ChannelIn * in = (ChannelIn *) ch; + ChannelInfo * info = DatabusInfoGetChannel(db_info, i); + if (ch->IsConnected(ch)) { + if (ChannelTypeIsArray(info->type)) { + in_channel_connectivity[i].is_connected = TRUE; + in_channel_connectivity[i].num_elems = 0; + in_channel_connectivity[i].elems = (int *) mcx_calloc(ChannelDimensionNumElements(info->dimension), sizeof(size_t)); + if (!in_channel_connectivity[i].elems) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity element container allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + + // if an element index appears in elems, it means that element is connected + ObjectContainer * connInfos = in->GetConnectionInfos(in); + for (j = 0; j < connInfos->Size(connInfos); j++) { + ConnectionInfo * connInfo = (ConnectionInfo *) connInfos->At(connInfos, j); + size_t k = 0; + + for (k = 0; k < ChannelDimensionNumElements(connInfo->targetDimension); k++) { + size_t idx = ChannelDimensionGetIndex(connInfo->targetDimension, k, info->type->ty.a.dims) - info->dimension->startIdxs[0]; + in_channel_connectivity[i].elems[in_channel_connectivity[i].num_elems++] = idx; + } + } + } else { + in_channel_connectivity[i].is_connected = TRUE; + // scalar channels are treated like they have 1 element (equal to zero) + in_channel_connectivity[i].num_elems = 1; + in_channel_connectivity[i].elems = (int*)mcx_calloc(1, sizeof(size_t)); + if (!in_channel_connectivity[i].elems) { + mcx_log(LOG_ERROR, "SetDependenciesFMU2: Input connectivity element allocation failed"); + ret_val = RETURN_ERROR; + goto cleanup; + } + in_channel_connectivity[i].elems[0] = 0; + } + } + + if (val->data->type == FMU2_VALUE_SCALAR) { + fmi2_import_variable_t *var = val->data->data.scalar; + size_t idx = fmi2_import_get_variable_original_order(var) + 1; + dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, dep_idx); + + dependencies_to_inputs[dep_idx].channel_idx = i; + dep_idx++; + } else if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; + + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + fmi2_import_variable_t * var = val->data->data.array.values[j]; + size_t idx = fmi2_import_get_variable_original_order(var) + 1; + dependencies_to_in_channels->Add(dependencies_to_in_channels, idx, dep_idx); + + dependencies_to_inputs[dep_idx].channel_idx = i; + dependencies_to_inputs[dep_idx].elem_idx = j; + dep_idx++; + } + } + } + + // element is not present in modelDescription.xml + // The dependency matrix consists of only 1 (if input is connected) + if (start_index == NULL) { + for (i = 0; i < GetDependencyNumOut(deps); ++i) { + for (j = 0; j < GetDependencyNumIn(deps); ++j) { + if (in_channel_connectivity[j].is_connected) { + ret_val = SetDependency(deps, j, i, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } + } + } + } + + goto cleanup; + } + + // map each initial_unkown index to an output channel index + // for array channels, there might be multiple entries initial_unknown_idx -> channel_idx + ObjectContainer *out_vars = fmu2->out; + size_t num_out_vars = out_vars->Size(out_vars); + size_t unknown_idx = 0; + for (i = 0; i < num_out_vars; ++i) { + Fmu2Value *val = (Fmu2Value *)out_vars->At(out_vars, i); + + if (val->data->type == FMU2_VALUE_SCALAR) { + fmi2_import_variable_t *var = val->data->data.scalar; + size_t idx = fmi2_import_get_variable_original_order(var) + 1; + unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, unknown_idx); + + unknowns_to_outputs[unknown_idx].channel_idx = i; + unknown_idx++; + } else if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; + + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + fmi2_import_variable_t * var = val->data->data.array.values[j]; + size_t idx = fmi2_import_get_variable_original_order(var) + 1; + unknowns_to_out_channels->Add(unknowns_to_out_channels, idx, unknown_idx); + + unknowns_to_outputs[unknown_idx].channel_idx = i; + unknowns_to_outputs[unknown_idx].elem_idx = j; + unknown_idx++; + } + } + } + + // fill up the dependency matrix + size_t processed_elems = 0; + for (i = 0; i < num_init_unknowns; ++i) { + fmi2_import_variable_t *init_unknown = fmi2_import_get_variable(init_unknowns, i); + size_t init_unknown_idx = fmi2_import_get_variable_original_order(init_unknown) + 1; + + SizeTSizeTElem * out_pair = unknowns_to_out_channels->Get(unknowns_to_out_channels, init_unknown_idx); + if (out_pair == NULL) { + continue; // in case some variables are ommitted from the input file + } + + ChannelElement * out_elem = &unknowns_to_outputs[out_pair->value]; + + processed_output_elems[processed_elems].channel_idx = out_elem->channel_idx; + processed_output_elems[processed_elems].elem_idx = out_elem->elem_idx; + processed_elems++; + + num_dependencies = start_index[i + 1] - start_index[i]; + for (j = 0; j < num_dependencies; ++j) { + dep_idx = dependency[start_index[i] + j]; + if (dep_idx == 0) { + // The element does not explicitly define a `dependencies` attribute + // In this case it depends on all inputs + for (k = 0; k < num_in_channels; ++k) { + if (in_channel_connectivity[k].is_connected) { + ret_val = SetDependency(deps, k, out_elem->channel_idx, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } + } + } + } else { + // The element explicitly defines its dependencies + SizeTSizeTElem * in_pair = dependencies_to_in_channels->Get(dependencies_to_in_channels, dep_idx); + if (in_pair) { + ChannelElement * dep = &dependencies_to_inputs[in_pair->value]; + + ConnectedElems * elems = &in_channel_connectivity[dep->channel_idx]; + if (elems->is_connected) { + size_t k = 0; + for (k = 0; k < elems->num_elems; k++) { + if (elems->elems[k] == dep->elem_idx) { + ret_val = SetDependency(deps, dep->channel_idx, out_elem->channel_idx, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } + break; + } + } + } + } + } + } + } + + // Initial unknowns which are ommitted from the element in + // modelDescription.xml file depend on all inputs + for (i = 0; i < num_out_vars; ++i) { + Fmu2Value * val = (Fmu2Value *) out_vars->At(out_vars, i); + + Vector * elems = GetAllElems(processed_output_elems, processed_elems, i); + + if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; + + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + if (!elems->Contains(elems, &j)) { + if (fmi2_import_get_initial(val->data->data.array.values[j]) != fmi2_initial_enu_exact) { + for (k = 0; k < num_in_channels; ++k) { + if (in_channel_connectivity[k].is_connected) { + ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup; + } + } + } + } + } + } + } else { + if (elems->Size(elems) == 0) { + if (fmi2_import_get_initial(val->data->data.scalar) != fmi2_initial_enu_exact) { + for (k = 0; k < num_in_channels; ++k) { + if (in_channel_connectivity[k].is_connected) { + ret_val = SetDependency(deps, k, i, DEP_DEPENDENT); + if (RETURN_OK != ret_val) { + goto cleanup_1; + } + } + } + } + } + } + + object_destroy(elems); + continue; + +cleanup_1: + object_destroy(elems); + goto cleanup; + } + +cleanup: // free dynamically allocated objects + object_destroy(dependencies_to_in_channels); + object_destroy(unknowns_to_out_channels); + if (in_channel_connectivity) { mcx_free(in_channel_connectivity); } + if (dependencies_to_inputs) { mcx_free(dependencies_to_inputs); } + if (unknowns_to_outputs) { mcx_free(unknowns_to_outputs); } + if (processed_output_elems) { mcx_free(processed_output_elems); } + fmi2_import_free_variable_list(init_unknowns); + + return ret_val; +} + // TODO: move into fmu2value? McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h index fe175bb..5b19e8a 100644 --- a/src/fmu/common_fmu2.h +++ b/src/fmu/common_fmu2.h @@ -19,6 +19,8 @@ #include "reader/model/components/specific_data/FmuInput.h" #include "reader/model/parameters/ParametersInput.h" +#include "core/Dependency.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -32,6 +34,8 @@ typedef struct Fmu2CommonStruct Fmu2CommonStruct; McxStatus Fmu2ReadParams(ObjectContainer * params, ObjectContainer * arrayParams, ParametersInput * input, fmi2_import_t * import, ObjectContainer * ignore); +McxStatus Fmu2SetDependencies(Fmu2CommonStruct * fmu2, Databus * db, Dependencies * deps, int init); + // TODO: rename all variablearrays to something better McxStatus Fmu2SetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals); McxStatus Fmu2GetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals); From b1fb63d1a3a80a56bf21353011e0144a287efccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 1 Jun 2022 13:02:43 +0200 Subject: [PATCH 230/295] Optimize const connections away only if the whole destination channel is filled --- src/core/Model.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/Model.c b/src/core/Model.c index 2c97c22..7c0ff98 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -191,6 +191,11 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { continue; } + if (!ChannelDimensionEq(trgChannelInfo->dimension, info->targetDimension)) { + 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)); From d0d8dfdfd3aa1bf653f822b68512bee33a83bc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 1 Jun 2022 14:17:13 +0200 Subject: [PATCH 231/295] Rename ChannelValueReference -> ChannelValueDataPointer --- src/components/comp_fmu.c | 8 +++--- src/components/comp_vector_integrator.c | 14 +++++----- src/core/Conversion.c | 20 ++++++------- src/core/channels/Channel.c | 14 +++++----- src/core/channels/ChannelValue.c | 4 +-- src/core/channels/ChannelValue.h | 2 +- src/core/channels/ChannelValueReference.c | 4 +-- src/core/connections/Connection.c | 6 ++-- src/core/connections/FilteredConnection.c | 6 ++-- src/core/connections/filters/DiscreteFilter.c | 2 +- src/fmu/Fmu2Value.c | 2 +- src/fmu/common_fmu1.c | 12 ++++---- src/fmu/common_fmu2.c | 28 +++++++++---------- 13 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index ca8cf76..982efe7 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -83,7 +83,7 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { return RETURN_ERROR; } - retVal = DatabusSetInReference(db, i, ChannelValueReference(&val->val), ChannelValueType(&val->val)); + retVal = DatabusSetInReference(db, i, ChannelValueDataPointer(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not set reference for channel %s", channelName); return RETURN_ERROR; @@ -125,7 +125,7 @@ static McxStatus Fmu1SetupDatabus(Component * comp) { return RETURN_ERROR; } - retVal = DatabusSetOutReference(db, i, ChannelValueReference(&val->val), ChannelValueType(&val->val)); + retVal = DatabusSetOutReference(db, i, ChannelValueDataPointer(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not set reference for channel %s", channelName); return RETURN_ERROR; @@ -392,7 +392,7 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat ChannelValueInit(&val->val, ChannelTypeClone(info->type)); } retVal = DatabusSetInReference(db, i, - ChannelValueReference(&val->val), + ChannelValueDataPointer(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "%s: Could not set reference for channel %s", logPrefix, val->name); @@ -430,7 +430,7 @@ static McxStatus Fmu2SetupChannelOut(ObjectContainer /* Fmu2Values */ * vals, Da ChannelValueInit(&val->val, ChannelTypeClone(info->type)); } retVal = DatabusSetOutReference(db, i, - ChannelValueReference(&val->val), + ChannelValueDataPointer(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "%s: Could not set reference for channel %s", logPrefix, channelName); diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 2d054a4..102f9ab 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -96,13 +96,13 @@ static McxStatus Setup(Component * comp) { ChannelInfo * inInfo = DatabusGetInChannelInfo(db, i); ChannelInfo * outInfo = DatabusGetOutChannelInfo(db, i); - retVal = DatabusSetInReference(db, i, ChannelValueReference(&integrator->deriv[i]), inInfo->type); + retVal = DatabusSetInReference(db, i, ChannelValueDataPointer(&integrator->deriv[i]), inInfo->type); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register in channel reference"); return RETURN_ERROR; } - retVal = DatabusSetOutReference(db, i, ChannelValueReference(&integrator->state[i]), outInfo->type); + retVal = DatabusSetOutReference(db, i, ChannelValueDataPointer(&integrator->state[i]), outInfo->type); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Could not register out channel reference"); return RETURN_ERROR; @@ -119,8 +119,8 @@ static McxStatus DoStep(Component * comp, size_t group, double time, double delt size_t i; for (i = 0; i < integrator->num; i++) { if (ChannelTypeIsArray(ChannelValueType(&integrator->state[i]))) { - mcx_array * state = ChannelValueReference(&integrator->state[i]); - mcx_array * deriv = ChannelValueReference(&integrator->deriv[i]); + mcx_array * state = ChannelValueDataPointer(&integrator->state[i]); + mcx_array * deriv = ChannelValueDataPointer(&integrator->deriv[i]); size_t j = 0; for (j = 0; j < mcx_array_num_elements(state); j++) { @@ -128,8 +128,8 @@ static McxStatus DoStep(Component * comp, size_t group, double time, double delt } } else { - double * state = (double *) ChannelValueReference(&integrator->state[i]); - double * deriv = (double *) ChannelValueReference(&integrator->deriv[i]); + double * state = (double *) ChannelValueDataPointer(&integrator->state[i]); + double * deriv = (double *) ChannelValueDataPointer(&integrator->deriv[i]); (*state) = (*state) + (*deriv) * deltaTime; } @@ -144,7 +144,7 @@ static McxStatus Initialize(Component * comp, size_t idx, double startTime) { size_t i; for (i = 0; i < integrator->num; i++) { if (ChannelTypeIsArray(ChannelValueType(&integrator->state[i]))) { - mcx_array * a = (mcx_array *) ChannelValueReference(&integrator->state[i]); + mcx_array * a = (mcx_array *) ChannelValueDataPointer(&integrator->state[i]); size_t j; for (j = 0; j < mcx_array_num_elements(a); j++) { diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 96de63c..9e39f39 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -308,11 +308,11 @@ static int RangeConversionElementEqualsMax(void * element, ChannelType * type) { static int RangeConversionIsEmpty(RangeConversion * conversion) { switch (conversion->type->con) { case CHANNEL_DOUBLE: - return (!conversion->min || *(double *) ChannelValueReference(conversion->min) == (-DBL_MAX)) && - (!conversion->max || *(double *) ChannelValueReference(conversion->max) == DBL_MAX); + return (!conversion->min || *(double *) ChannelValueDataPointer(conversion->min) == (-DBL_MAX)) && + (!conversion->max || *(double *) ChannelValueDataPointer(conversion->max) == DBL_MAX); case CHANNEL_INTEGER: - return (!conversion->min || *(int *) ChannelValueReference(conversion->min) == INT_MIN) && - (!conversion->max || *(int *) ChannelValueReference(conversion->max) == INT_MAX); + return (!conversion->min || *(int *) ChannelValueDataPointer(conversion->min) == INT_MIN) && + (!conversion->max || *(int *) ChannelValueDataPointer(conversion->max) == INT_MAX); case CHANNEL_ARRAY: return (!conversion->min || mcx_array_all(&conversion->min->value.a, RangeConversionElementEqualsMin)) && (!conversion->max || mcx_array_all(&conversion->max->value.a, RangeConversionElementEqualsMax)); @@ -391,7 +391,7 @@ static McxStatus UnitConversionConvert(Conversion * conversion, ChannelValue * v *elem = UnitConversionConvertValue(conversion, *elem); } } else { - double val = UnitConversionConvertValue(unitConversion, *(double *) ChannelValueReference(value)); + double val = UnitConversionConvertValue(unitConversion, *(double *) ChannelValueDataPointer(value)); if (RETURN_OK != ChannelValueSetFromReference(value, &val)) { return RETURN_ERROR; } @@ -691,12 +691,12 @@ static int LinearConversionIsEmpty(LinearConversion * conversion) { switch (conversion->type->con) { case CHANNEL_DOUBLE: return - (!conversion->factor || * (double *) ChannelValueReference(conversion->factor) == 1.0) && - (!conversion->offset || * (double *) ChannelValueReference(conversion->offset) == 0.0); + (!conversion->factor || * (double *) ChannelValueDataPointer(conversion->factor) == 1.0) && + (!conversion->offset || * (double *) ChannelValueDataPointer(conversion->offset) == 0.0); case CHANNEL_INTEGER: return - (!conversion->factor || * (int *) ChannelValueReference(conversion->factor) == 1) && - (!conversion->offset || * (int *) ChannelValueReference(conversion->offset) == 0); + (!conversion->factor || * (int *) ChannelValueDataPointer(conversion->factor) == 1) && + (!conversion->offset || * (int *) ChannelValueDataPointer(conversion->offset) == 0); case CHANNEL_ARRAY: return (!conversion->factor || mcx_array_all(&conversion->factor->value.a, LinearConversionElementEqualsOne)) && (!conversion->offset || mcx_array_all(&conversion->offset->value.a, LinearConversionElementEqualsZero)); @@ -835,7 +835,7 @@ McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, Channel goto cleanup; } - ChannelValueRefSetFromReference(ref, ChannelValueReference(src), srcSlice, typeConv); + ChannelValueRefSetFromReference(ref, ChannelValueDataPointer(src), srcSlice, typeConv); cleanup: object_destroy(typeConv); diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 9a52e41..b9d6a68 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -262,7 +262,7 @@ static const void * ChannelInGetValueReference(Channel * channel) { return NULL; } - return ChannelValueReference(&channel->value); + return ChannelValueDataPointer(&channel->value); } static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { @@ -681,7 +681,7 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * // default value if (info->defaultValue) { - channel->internalValue = ChannelValueReference(channel->info.defaultValue); + channel->internalValue = ChannelValueDataPointer(channel->info.defaultValue); } @@ -744,7 +744,7 @@ static const void * ChannelOutGetValueReference(Channel * channel) { return NULL; } - return ChannelValueReference(&channel->value); + return ChannelValueDataPointer(&channel->value); } static const proc * ChannelOutGetFunction(ChannelOut * out) { @@ -825,7 +825,7 @@ static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference return RETURN_ERROR; } if (channel->internalValue - && !(info->defaultValue && channel->internalValue == ChannelValueReference(info->defaultValue))) { + && !(info->defaultValue && channel->internalValue == ChannelValueDataPointer(info->defaultValue))) { mcx_log(LOG_ERROR, "Port %s: Set outport reference: Reference already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -873,7 +873,7 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r ChannelValueInit(&out->data->valueFunctionRes, ChannelTypeClone(type)); // Setup value reference to point to internal value - channel->internalValue = ChannelValueReference(&channel->value); + channel->internalValue = ChannelValueDataPointer(&channel->value); return RETURN_OK; } @@ -923,7 +923,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { out->data->valueFunctionRes.value.d); } #endif // MCX_DEBUG - if (RETURN_OK != ChannelValueSetFromReference(&channel->value, ChannelValueReference(&out->data->valueFunctionRes))) { + if (RETURN_OK != ChannelValueSetFromReference(&channel->value, ChannelValueDataPointer(&out->data->valueFunctionRes))) { return RETURN_ERROR; } } else { @@ -1096,7 +1096,7 @@ static McxStatus ChannelLocalSetReference(ChannelLocal * local, return RETURN_ERROR; } if (channel->internalValue - && !(info->defaultValue && channel->internalValue == ChannelValueReference(info->defaultValue))) { + && !(info->defaultValue && channel->internalValue == ChannelValueDataPointer(info->defaultValue))) { mcx_log(LOG_ERROR, "Port %s: Set local value reference: Reference already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 79be3d3..c4a076f 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -718,7 +718,7 @@ ChannelType * ChannelValueType(ChannelValue * value) { return value->type; } -void * ChannelValueReference(ChannelValue * value) { +void * ChannelValueDataPointer(ChannelValue * value) { if (value->type->con == CHANNEL_UNKNOWN) { return NULL; } else { @@ -900,7 +900,7 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { return RETURN_ERROR; } - if (RETURN_OK != ChannelValueSetFromReference(value, ChannelValueReference((ChannelValue *) source))) { + if (RETURN_OK != ChannelValueSetFromReference(value, ChannelValueDataPointer((ChannelValue *) source))) { return RETURN_ERROR; } diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index ff908e2..0e529b0 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -148,7 +148,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel McxStatus ChannelValueToStringBuffer(const ChannelValue * value, char * buffer, size_t len); ChannelType * ChannelValueType(ChannelValue * value); -void * ChannelValueReference(ChannelValue * value); +void * ChannelValueDataPointer(ChannelValue * value); void ChannelValueDataDestructor(ChannelValueData * data, ChannelType * type); void ChannelValueDataInit(ChannelValueData * data, ChannelType * type); diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 083de27..f0a844f 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -165,7 +165,7 @@ McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapF return RETURN_OK; } else { - return fn(ChannelValueReference(ref->ref.value), 0, ChannelValueType(ref->ref.value), ctx); + return fn(ChannelValueDataPointer(ref->ref.value), 0, ChannelValueType(ref->ref.value), ctx); } case CHANNEL_VALUE_REF_SLICE: if (ChannelTypeIsArray(ref->ref.slice->ref->type)) { @@ -186,7 +186,7 @@ McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapF return RETURN_OK; } else { - return fn(ChannelValueReference(ref->ref.slice->ref), 0, ChannelValueType(ref->ref.slice->ref), ctx); + return fn(ChannelValueDataPointer(ref->ref.slice->ref), 0, ChannelValueType(ref->ref.slice->ref), ctx); } default: mcx_log(LOG_ERROR, "ChannelValueRefElemMap: Invalid internal channel value reference type (%d)", ref->type); diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 8ffbe90..0ac4972 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1203,7 +1203,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { } } - retVal = ChannelValueRefSetFromReference(storeRef, ChannelValueReference(inChannelValue), srcDim, typeConv); + retVal = ChannelValueRefSetFromReference(storeRef, ChannelValueDataPointer(inChannelValue), srcDim, typeConv); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Could not set up initial value in connection"); goto cleanup_1; @@ -1233,7 +1233,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { goto cleanup; } - ChannelValueRefSetFromReference(storeRef, ChannelValueReference(outInfo->initialValue), targetDim, NULL); + ChannelValueRefSetFromReference(storeRef, ChannelValueDataPointer(outInfo->initialValue), targetDim, NULL); connection->useInitialValue_ = TRUE; } else { { @@ -1338,7 +1338,7 @@ static McxStatus ConnectionEnterInitializationMode(Connection * connection) { // set functions for initialization mode connection->UpdateFromInput = ConnectionInitUpdateFrom; connection->UpdateToOutput = ConnectionInitUpdateTo; - connection->value_ = ChannelValueReference(&connection->store_); + connection->value_ = ChannelValueDataPointer(&connection->store_); connection->IsDefinedDuringInit = ConnectionIsDefinedDuringInit; connection->SetDefinedDuringInit = ConnectionSetDefinedDuringInit; diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 9693dd5..f4f684e 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -75,7 +75,7 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o ChannelValueInit(&filteredConnection->data->store, storeType); // steals ownership of storeType -> no clone needed // value reference - connection->value_ = ChannelValueReference(&filteredConnection->data->store); + connection->value_ = ChannelValueDataPointer(&filteredConnection->data->store); // initialize the buffer for channel function calls ChannelValueInit(&filteredConnection->data->updateBuffer, ChannelTypeClone(storeType)); @@ -222,7 +222,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI return RETURN_ERROR; } - if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueReference(&filteredConnection->data->updateBuffer))) { + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueDataPointer(&filteredConnection->data->updateBuffer))) { mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } @@ -244,7 +244,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI size_t numFilters = FilteredConnectionGetNumFilters(filteredConnection); ChannelType * type = info->type; - mcx_array * elements = (mcx_array *) ChannelValueReference(&filteredConnection->data->updateBuffer); + mcx_array * elements = (mcx_array *) ChannelValueDataPointer(&filteredConnection->data->updateBuffer); char * dest = (char *) elements->data; for (i = 0; i < numFilters; i++) { filter = filteredConnection->GetReadFilter(filteredConnection, i); diff --git a/src/core/connections/filters/DiscreteFilter.c b/src/core/connections/filters/DiscreteFilter.c index 5f41c77..2ad8241 100644 --- a/src/core/connections/filters/DiscreteFilter.c +++ b/src/core/connections/filters/DiscreteFilter.c @@ -29,7 +29,7 @@ static McxStatus DiscreteFilterSetValue(ChannelFilter * filter, double time, Cha static ChannelValueData DiscreteFilterGetValue(ChannelFilter * filter, double time) { DiscreteFilter * discreteFilter = (DiscreteFilter *) filter; - return * (ChannelValueData *) ChannelValueReference(&discreteFilter->lastSynchronizationStepValue); + return * (ChannelValueData *) ChannelValueDataPointer(&discreteFilter->lastSynchronizationStepValue); } static McxStatus DiscreteFilterEnterCouplingStepMode(ChannelFilter * filter diff --git a/src/fmu/Fmu2Value.c b/src/fmu/Fmu2Value.c index 3cff407..cf2e0e5 100644 --- a/src/fmu/Fmu2Value.c +++ b/src/fmu/Fmu2Value.c @@ -350,7 +350,7 @@ static McxStatus Fmu2ValueSetup(Fmu2Value * v, const char * name, Fmu2ValueData n *= data->data.array.dims[i]; } - mcx_array * a = (mcx_array *) ChannelValueReference(&v->val); + mcx_array * a = (mcx_array *) ChannelValueDataPointer(&v->val); for (i = 0; i < n; i++) { if (RETURN_OK != Fmu2ValueGetArrayVariableStart(t, data->data.array.values[i], a, i)) { diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index 41582bd..64c2896 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -587,7 +587,7 @@ McxStatus Fmu1SetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { case CHANNEL_ARRAY: { fmi1_value_reference_t * vrs = fmuVal->data->vr.array.values; - mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); + mcx_array * a = (mcx_array *) ChannelValueDataPointer(&fmuVal->val); size_t num = mcx_array_num_elements(a); void * vals = a->data; @@ -656,7 +656,7 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { case CHANNEL_DOUBLE: { fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; - status = fmi1_import_get_real(fmu->fmiImport, vr, 1, (fmi1_real_t *) ChannelValueReference(chVal)); + status = fmi1_import_get_real(fmu->fmiImport, vr, 1, (fmi1_real_t *) ChannelValueDataPointer(chVal)); if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { fmuVal->val.value.d *= -1.; } @@ -665,7 +665,7 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { case CHANNEL_INTEGER: { fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; - status = fmi1_import_get_integer(fmu->fmiImport, vr, 1, (fmi1_integer_t *) ChannelValueReference(chVal)); + status = fmi1_import_get_integer(fmu->fmiImport, vr, 1, (fmi1_integer_t *) ChannelValueDataPointer(chVal)); if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { fmuVal->val.value.i *= -1; } @@ -674,7 +674,7 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { case CHANNEL_BOOL: { fmi1_value_reference_t vr[] = {fmuVal->data->vr.scalar}; - status = fmi1_import_get_boolean(fmu->fmiImport, vr, 1, (fmi1_boolean_t *) ChannelValueReference(chVal)); + status = fmi1_import_get_boolean(fmu->fmiImport, vr, 1, (fmi1_boolean_t *) ChannelValueDataPointer(chVal)); if (fmi1_variable_is_negated_alias == fmi1_import_get_variable_alias_kind(fmuVal->data->var.scalar)) { fmuVal->val.value.i = !fmuVal->val.value.i; } @@ -694,7 +694,7 @@ McxStatus Fmu1GetVariable(Fmu1CommonStruct * fmu, Fmu1Value * fmuVal) { case CHANNEL_ARRAY: { fmi1_value_reference_t * vrs = fmuVal->data->vr.array.values; - mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); + mcx_array * a = (mcx_array *) ChannelValueDataPointer(&fmuVal->val); size_t num = mcx_array_num_elements(a); void * vals = a->data; @@ -816,7 +816,7 @@ McxStatus fmi1AddLocalChannelsFromLocalValues(ObjectContainer * vals, const char } - retVal = DatabusAddLocalChannel(db, name, buffer, unitName, ChannelValueReference(&val->val), ChannelValueType(&val->val)); + retVal = DatabusAddLocalChannel(db, name, buffer, unitName, ChannelValueDataPointer(&val->val), ChannelValueType(&val->val)); mcx_free(buffer); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "%s: Adding channel %s to databus failed", compName, name); diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 2aa3f0a..44b5bf6 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -1039,9 +1039,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = {fmuVal->data->vr.scalar}; - status = fmi2_import_set_real(fmu->fmiImport, vr, 1, (const fmi2_real_t *) ChannelValueReference(chVal)); + status = fmi2_import_set_real(fmu->fmiImport, vr, 1, (const fmi2_real_t *) ChannelValueDataPointer(chVal)); - MCX_DEBUG_LOG("Set %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueReference(chVal)); + MCX_DEBUG_LOG("Set %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueDataPointer(chVal)); break; } @@ -1049,9 +1049,9 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - status = fmi2_import_set_integer(fmu->fmiImport, vr, 1, (const fmi2_integer_t *) ChannelValueReference(chVal)); + status = fmi2_import_set_integer(fmu->fmiImport, vr, 1, (const fmi2_integer_t *) ChannelValueDataPointer(chVal)); - MCX_DEBUG_LOG("Set %s(%d)=%d", fmuVal->name, vr[0], *(int*)ChannelValueReference(chVal)); + MCX_DEBUG_LOG("Set %s(%d)=%d", fmuVal->name, vr[0], *(int*)ChannelValueDataPointer(chVal)); break; } @@ -1059,7 +1059,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - status = fmi2_import_set_boolean(fmu->fmiImport, vr, 1, (const fmi2_boolean_t *) ChannelValueReference(chVal)); + status = fmi2_import_set_boolean(fmu->fmiImport, vr, 1, (const fmi2_boolean_t *) ChannelValueDataPointer(chVal)); break; } @@ -1067,14 +1067,14 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - status = fmi2_import_set_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) ChannelValueReference(chVal)); + status = fmi2_import_set_string(fmu->fmiImport, vr, 1, (fmi2_string_t *) ChannelValueDataPointer(chVal)); break; } case CHANNEL_BINARY: case CHANNEL_BINARY_REFERENCE: { - binary_string * binary = (binary_string *) ChannelValueReference(chVal); + binary_string * binary = (binary_string *) ChannelValueDataPointer(chVal); fmi2_value_reference_t vrs [] = { fmuVal->data->vr.binary.lo , fmuVal->data->vr.binary.hi @@ -1093,7 +1093,7 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { case CHANNEL_ARRAY: { fmi2_value_reference_t * vrs = fmuVal->data->vr.array.values; - mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); + mcx_array * a = (mcx_array *) ChannelValueDataPointer(&fmuVal->val); size_t num = mcx_array_num_elements(a); void * vals = a->data; @@ -1167,9 +1167,9 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - status = fmi2_import_get_real(fmu->fmiImport, vr, 1, (fmi2_real_t *) ChannelValueReference(chVal)); + status = fmi2_import_get_real(fmu->fmiImport, vr, 1, (fmi2_real_t *) ChannelValueDataPointer(chVal)); - MCX_DEBUG_LOG("Get %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueReference(chVal)); + MCX_DEBUG_LOG("Get %s(%d)=%f", fmuVal->name, vr[0], *(double*)ChannelValueDataPointer(chVal)); break; } @@ -1177,7 +1177,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - status = fmi2_import_get_integer(fmu->fmiImport, vr, 1, (fmi2_integer_t *) ChannelValueReference(chVal)); + status = fmi2_import_get_integer(fmu->fmiImport, vr, 1, (fmi2_integer_t *) ChannelValueDataPointer(chVal)); break; } @@ -1185,7 +1185,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { { fmi2_value_reference_t vr[] = { fmuVal->data->vr.scalar }; - status = fmi2_import_get_boolean(fmu->fmiImport, vr, 1, (fmi2_boolean_t *) ChannelValueReference(chVal)); + status = fmi2_import_get_boolean(fmu->fmiImport, vr, 1, (fmi2_boolean_t *) ChannelValueDataPointer(chVal)); break; } @@ -1228,7 +1228,7 @@ McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { case CHANNEL_ARRAY: { fmi2_value_reference_t * vrs = fmuVal->data->vr.array.values; - mcx_array * a = (mcx_array *) ChannelValueReference(&fmuVal->val); + mcx_array * a = (mcx_array *) ChannelValueDataPointer(&fmuVal->val); size_t num = mcx_array_num_elements(a); void * vals = a->data; @@ -1339,7 +1339,7 @@ McxStatus Fmi2RegisterLocalChannelsAtDatabus(ObjectContainer * vals, const char return RETURN_ERROR; } - retVal = DatabusAddLocalChannel(db, name, buffer, unitName, ChannelValueReference(&val->val), ChannelValueType(&val->val)); + retVal = DatabusAddLocalChannel(db, name, buffer, unitName, ChannelValueDataPointer(&val->val), ChannelValueType(&val->val)); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "%s: Adding channel %s to databus failed", compName, name); return RETURN_ERROR; From 30a69dfb755d65f1245c8dd480f99f7fbdf3e28f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 2 Jun 2022 15:07:05 +0200 Subject: [PATCH 232/295] Mark tunable params as discrete for arrays as well --- src/fmu/common_fmu2.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 44b5bf6..6e3fc40 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -1516,6 +1516,31 @@ void Fmu2MarkTunableParamsAsInputAsDiscrete(ObjectContainer * in) { mcx_log(LOG_DEBUG, "Setting input \"%s\" as discrete", ChannelInfoGetLogName(info)); in->SetDiscrete(in); } + } else if (val->data->type == FMU2_VALUE_ARRAY) { + size_t num_elems = 1; + size_t j = 0; + int all_tunable = TRUE; + + for (j = 0; j < val->data->data.array.numDims; j++) { + num_elems *= val->data->data.array.dims[j]; + } + + for (j = 0; j < num_elems; j++) { + fmi2_import_variable_t * var = val->data->data.array.values[j]; + fmi2_causality_enu_t causality = fmi2_import_get_causality(var); + + if (fmi2_causality_enu_input == causality) { + all_tunable = FALSE; + break; + } + } + + if (all_tunable) { + ChannelIn * in = (ChannelIn *) val->channel; + ChannelInfo * info = &((Channel *) in)->info; + mcx_log(LOG_DEBUG, "Setting input \"%s\" as discrete", ChannelInfoGetLogName(info)); + in->SetDiscrete(in); + } } } } From 722ae1153d6060089f4a8911b4260b0e5870b137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 2 Jun 2022 16:05:53 +0200 Subject: [PATCH 233/295] Free the dimension of the ChannelValueReference slice --- src/core/channels/ChannelValueReference.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index f0a844f..a8d52c3 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -17,7 +17,11 @@ extern "C" { void ChannelValueRefDestructor(ChannelValueRef * ref) { - // TODO ??? + if (ref->type == CHANNEL_VALUE_REF_SLICE) { + if (ref->ref.slice->dimension) { + DestroyChannelDimension(&ref->ref.slice->dimension); + } + } } ChannelValueRef * ChannelValueRefCreate(ChannelValueRef * ref) { From 8510e66553d29fe4dd82db935a31fa8d11f523e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 28 Jun 2022 13:40:59 +0200 Subject: [PATCH 234/295] Make ChannelValueRef a normal struct --- src/core/Conversion.c | 62 +++++++++---------- src/core/channels/Channel.c | 20 +++--- src/core/channels/ChannelValueReference.c | 74 +++++++++++------------ src/core/channels/ChannelValueReference.h | 13 ++-- src/core/connections/Connection.c | 21 ++++--- 5 files changed, 89 insertions(+), 101 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 9e39f39..7822299 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -226,9 +226,9 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va if (rangeConv) { if (slice) { - ChannelValueRef * ref = MakeChannelValueRef(value, slice); + ChannelValueRef * ref = MakeChannelValueReference(value, slice); retVal = RangeConversionConvertValueRef(rangeConv, ref); - object_destroy(ref); + DestroyChannelValueReference(ref); } else { retVal = RangeConversionConvert(rangeConv, value); } @@ -482,9 +482,9 @@ McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * if (unitConv) { if (slice) { - ChannelValueRef * ref = MakeChannelValueRef(value, slice); + ChannelValueRef * ref = MakeChannelValueReference(value, slice); retVal = UnitConversionConvertValueRef(unitConv, ref); - object_destroy(ref); + DestroyChannelValueReference(ref); } else { retVal = UnitConversionConvert(unitConv, value); } @@ -751,9 +751,9 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal if (linearConv) { if (slice) { - ChannelValueRef * ref = MakeChannelValueRef(value, slice); + ChannelValueRef * ref = MakeChannelValueReference(value, slice); retVal = LinearConversionConvertValueRef(linearConv, ref); - object_destroy(ref); + DestroyChannelValueReference(ref); } else { retVal = LinearConversionConvert(linearConv, value); } @@ -829,7 +829,7 @@ McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, Channel goto cleanup; } - ref = MakeChannelValueRef(dest, destSlice); + ref = MakeChannelValueReference(dest, destSlice); if (!ref) { mcx_log(LOG_ERROR, "ConvertType: Value reference allocation failed"); goto cleanup; @@ -839,7 +839,7 @@ McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, Channel cleanup: object_destroy(typeConv); - object_destroy(ref); + DestroyChannelValueReference(ref); return retVal; } @@ -875,7 +875,7 @@ static McxStatus CheckArrayReferencingOnlyOneElement(ChannelValueRef * dest, Cha return RETURN_ERROR; } } else { - if (ChannelDimensionNumElements(dest->ref.slice->dimension) != 1) { + if (ChannelDimensionNumElements(dest->ref.slice.dimension) != 1) { mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array of size 1"); return RETURN_ERROR; } @@ -902,13 +902,13 @@ static McxStatus ArraysValidForConversion(ChannelValueRef * dest, if (dest->type == CHANNEL_VALUE_REF_VALUE) { return ChannelDimensionConformsTo(srcDimension, dest->ref.value->type->ty.a.dims, dest->ref.value->type->ty.a.numDims) ? RETURN_OK : RETURN_ERROR; } else { - return ChannelDimensionConformsToDimension(dest->ref.slice->dimension, srcDimension) ? RETURN_OK : RETURN_ERROR; + return ChannelDimensionConformsToDimension(dest->ref.slice.dimension, srcDimension) ? RETURN_OK : RETURN_ERROR; } } else { if (dest->type == CHANNEL_VALUE_REF_VALUE) { return mcx_array_dims_match(&dest->ref.value->value.a, src) ? RETURN_OK : RETURN_ERROR; } else { - return ChannelDimensionConformsTo(dest->ref.slice->dimension, src->dims, src->numDims) ? RETURN_OK : RETURN_ERROR; + return ChannelDimensionConformsTo(dest->ref.slice.dimension, src->dims, src->numDims) ? RETURN_OK : RETURN_ERROR; } } @@ -1109,8 +1109,8 @@ static McxStatus TypeConversionConvertDoubleToArrayDouble(Conversion * conversio if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(double *) dest->ref.value->value.a.data = *(double *) src; } else { - double * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *(double *) src; + double * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *(double *) src; } return RETURN_OK; @@ -1124,8 +1124,8 @@ static McxStatus TypeConversionConvertIntegerToArrayDouble(Conversion * conversi if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(double *) dest->ref.value->value.a.data = (double) *((int *) src); } else { - double * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = (double) *((int *) src); + double * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = (double) *((int *) src); } return RETURN_OK; @@ -1139,8 +1139,8 @@ static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(double *) dest->ref.value->value.a.data = *((int *) src) != 0 ? 1. : 0.; } else { - double * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *((int *) src) != 0 ? 1. : 0.; + double * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *((int *) src) != 0 ? 1. : 0.; } return RETURN_OK; @@ -1154,8 +1154,8 @@ static McxStatus TypeConversionConvertDoubleToArrayInteger(Conversion * conversi if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(int *) dest->ref.value->value.a.data = (int) floor(*((double *) src) + 0.5); } else { - int * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = (int) floor(*((double *) src) + 0.5); + int * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = (int) floor(*((double *) src) + 0.5); } return RETURN_OK; @@ -1169,8 +1169,8 @@ static McxStatus TypeConversionConvertIntegerToArrayInteger(Conversion * convers if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(int *) dest->ref.value->value.a.data = *(int *) src; } else { - int * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *(int *) src; + int * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *(int *) src; } return RETURN_OK; @@ -1184,8 +1184,8 @@ static McxStatus TypeConversionConvertBoolToArrayInteger(Conversion * conversion if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(int *) dest->ref.value->value.a.data = *((int *) src) != 0 ? 1 : 0; } else { - int * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *((int *) src) != 0 ? 1 : 0; + int * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *((int *) src) != 0 ? 1 : 0; } return RETURN_OK; @@ -1199,8 +1199,8 @@ static McxStatus TypeConversionConvertDoubleToArrayBool(Conversion * conversion, if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(int *) dest->ref.value->value.a.data = *((double *) src) > 0 ? 1 : 0; } else { - int * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *((double *) src) > 0 ? 1 : 0; + int * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *((double *) src) > 0 ? 1 : 0; } return RETURN_OK; @@ -1214,8 +1214,8 @@ static McxStatus TypeConversionConvertIntegerToArrayBool(Conversion * conversion if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(int *) dest->ref.value->value.a.data = *((int *) src) != 0 ? 1 : 0; } else { - int * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *((int *) src) != 0 ? 1 : 0; + int * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *((int *) src) != 0 ? 1 : 0; } return RETURN_OK; @@ -1229,8 +1229,8 @@ static McxStatus TypeConversionConvertBoolToArrayBool(Conversion * conversion, C if (dest->type == CHANNEL_VALUE_REF_VALUE) { *(int *) dest->ref.value->value.a.data = *(int *) src; } else { - int * data = dest->ref.slice->ref->value.a.data; - *(data + dest->ref.slice->dimension->startIdxs[0]) = *(int *) src; + int * data = dest->ref.slice.ref->value.a.data; + *(data + dest->ref.slice.dimension->startIdxs[0]) = *(int *) src; } return RETURN_OK; @@ -1241,14 +1241,14 @@ static size_t IndexOfElemInSrcArray(size_t dest_idx, mcx_array * src_array, Chan if (dest->type == CHANNEL_VALUE_REF_VALUE) { return ChannelDimensionGetIndex(src_dim, dest_idx, src_array->dims); } else { - size_t idx = ChannelDimensionGetSliceIndex(dest->ref.slice->dimension, dest_idx, dest->ref.slice->ref->type->ty.a.dims); + size_t idx = ChannelDimensionGetSliceIndex(dest->ref.slice.dimension, dest_idx, dest->ref.slice.ref->type->ty.a.dims); return ChannelDimensionGetIndex(src_dim, idx, src_array->dims); } } else { if (dest->type == CHANNEL_VALUE_REF_VALUE) { return dest_idx; } else { - return ChannelDimensionGetSliceIndex(dest->ref.slice->dimension, dest_idx, dest->ref.slice->ref->type->ty.a.dims); + return ChannelDimensionGetSliceIndex(dest->ref.slice.dimension, dest_idx, dest->ref.slice.ref->type->ty.a.dims); } } } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index b9d6a68..d47ca47 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -424,6 +424,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec ConnectionInfo * connInfo = &connection->info; Channel * channel = (Channel *) in; ChannelInfo * inInfo = &channel->info; + ChannelValueRef * valRef = NULL; McxStatus retVal = RETURN_OK; @@ -432,29 +433,22 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not register connection"); } - // TODO setup valueReference - ChannelValueRef * valRef = (ChannelValueRef *) object_create(ChannelValueRef); - if (!valRef) { - return RETURN_ERROR; - } - ChannelDimension * dimension = connInfo->targetDimension; // TODO check ret values // TODO do we need some plausibility checks? // TODO is it fine to use connInfo here? if (dimension && !ChannelDimensionEq(dimension, inInfo->dimension)) { - valRef->type = CHANNEL_VALUE_REF_SLICE; - valRef->ref.slice = (ArraySlice *) mcx_calloc(1, sizeof(ArraySlice)); - valRef->ref.slice->ref = &channel->value; - valRef->ref.slice->dimension = CloneChannelDimension(dimension); - retVal = ChannelDimensionAlignIndicesWithZero(valRef->ref.slice->dimension, inInfo->dimension); + ChannelDimension * slice = CloneChannelDimension(dimension); + + retVal = ChannelDimensionAlignIndicesWithZero(slice, inInfo->dimension); if (retVal == RETURN_ERROR) { ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Normalizing array slice dimension failed"); return RETURN_ERROR; } + + valRef = MakeChannelValueReference(&channel->value, slice); } else { - valRef->type = CHANNEL_VALUE_REF_VALUE; - valRef->ref.value = &channel->value; + valRef = MakeChannelValueReference(&channel->value, NULL); } retVal = in->data->valueReferences->PushBack(in->data->valueReferences, (Object *) valRef); diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index a8d52c3..6fa0e6c 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -16,23 +16,36 @@ extern "C" { #endif /* __cplusplus */ -void ChannelValueRefDestructor(ChannelValueRef * ref) { +void DestroyChannelValueReference(ChannelValueRef * ref) { if (ref->type == CHANNEL_VALUE_REF_SLICE) { - if (ref->ref.slice->dimension) { - DestroyChannelDimension(&ref->ref.slice->dimension); + if (ref->ref.slice.dimension) { + DestroyChannelDimension(&ref->ref.slice.dimension); } } + + mcx_free(ref); } -ChannelValueRef * ChannelValueRefCreate(ChannelValueRef * ref) { - ref->type = CHANNEL_VALUE_REF_VALUE; - ref->ref.value = NULL; + +ChannelValueRef * MakeChannelValueReference(ChannelValue * value, ChannelDimension * slice) { + ChannelValueRef * ref = (ChannelValueRef *) mcx_calloc(1, sizeof(ChannelValueRef)); + + if (!ref) { + return NULL; + } + + if (slice) { + ref->type = CHANNEL_VALUE_REF_SLICE; + ref->ref.slice.dimension = slice; + ref->ref.slice.ref = value; + } else { + ref->type = CHANNEL_VALUE_REF_VALUE; + ref->ref.value = value; + } return ref; } -OBJECT_CLASS(ChannelValueRef, Object); - McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * conv) { if (conv) { @@ -90,11 +103,11 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re } } } else { - if (ChannelTypeIsArray(ref->ref.slice->ref->type)) { - mcx_array * destArray = &ref->ref.slice->ref->value.a; + if (ChannelTypeIsArray(ref->ref.slice.ref->type)) { + mcx_array * destArray = &ref->ref.slice.ref->value.a; mcx_array * srcArray = (mcx_array *) reference; - ChannelDimension * destDimension = ref->ref.slice->dimension; + ChannelDimension * destDimension = ref->ref.slice.dimension; if (srcArray->data == NULL || destArray->data == NULL) { mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Empty array data given"); @@ -138,11 +151,11 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re } return ChannelValueDataSetFromReference( - &ref->ref.slice->ref->value, - ref->ref.slice->ref->type, + &ref->ref.slice.ref->value, + ref->ref.slice.ref->type, mcx_array_get_elem_reference(src, ChannelDimensionGetIndex(srcDimension, 0, src->dims))); } else { - return ChannelValueDataSetFromReference(&ref->ref.slice->ref->value, ref->ref.slice->ref->type, reference); + return ChannelValueDataSetFromReference(&ref->ref.slice.ref->value, ref->ref.slice.ref->type, reference); } } } @@ -172,25 +185,25 @@ McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapF return fn(ChannelValueDataPointer(ref->ref.value), 0, ChannelValueType(ref->ref.value), ctx); } case CHANNEL_VALUE_REF_SLICE: - if (ChannelTypeIsArray(ref->ref.slice->ref->type)) { + if (ChannelTypeIsArray(ref->ref.slice.ref->type)) { size_t i = 0; - for (i = 0; i < ChannelDimensionNumElements(ref->ref.slice->dimension); i++) { - size_t idx = ChannelDimensionGetIndex(ref->ref.slice->dimension, i, ref->ref.slice->ref->value.a.dims); + for (i = 0; i < ChannelDimensionNumElements(ref->ref.slice.dimension); i++) { + size_t idx = ChannelDimensionGetIndex(ref->ref.slice.dimension, i, ref->ref.slice.ref->value.a.dims); - void * elem = mcx_array_get_elem_reference(&ref->ref.slice->ref->value.a, idx); + void * elem = mcx_array_get_elem_reference(&ref->ref.slice.ref->value.a, idx); if (!elem) { return RETURN_ERROR; } - if (RETURN_ERROR == fn(elem, idx, ChannelValueType(ref->ref.slice->ref), ctx)) { + if (RETURN_ERROR == fn(elem, idx, ChannelValueType(ref->ref.slice.ref), ctx)) { return RETURN_ERROR; } } return RETURN_OK; } else { - return fn(ChannelValueDataPointer(ref->ref.slice->ref), 0, ChannelValueType(ref->ref.slice->ref), ctx); + return fn(ChannelValueDataPointer(ref->ref.slice.ref), 0, ChannelValueType(ref->ref.slice.ref), ctx); } default: mcx_log(LOG_ERROR, "ChannelValueRefElemMap: Invalid internal channel value reference type (%d)", ref->type); @@ -204,7 +217,7 @@ ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { return ChannelValueType(ref->ref.value); case CHANNEL_VALUE_REF_SLICE: // TODO (do we need to adapt the indices wrt. dimension) ? - return ChannelValueType(ref->ref.slice->ref); + return ChannelValueType(ref->ref.slice.ref); default: mcx_log(LOG_ERROR, "Invalid internal channel value reference type (%d)", ref->type); return NULL; @@ -212,25 +225,6 @@ ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { } -ChannelValueRef * MakeChannelValueRef(ChannelValue * val, ChannelDimension * slice) { - ChannelValueRef * ref = (ChannelValueRef *)object_create(ChannelValueRef); - if (!ref) { - return NULL; - } - - if (slice) { - ref->type = CHANNEL_VALUE_REF_SLICE; - ref->ref.slice = (ArraySlice *) mcx_calloc(1, sizeof(ArraySlice)); - ref->ref.slice->dimension = slice; - ref->ref.slice->ref = val; - } else { - ref->type = CHANNEL_VALUE_REF_VALUE; - ref->ref.value = val; - } - - return ref; -} - #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index bf18bdc..166b531 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -33,18 +33,19 @@ typedef enum ChannelValueRefType { } ChannelValueRefType; -extern const struct ObjectClass _ChannelValueRef; - typedef struct ChannelValueRef { - Object _; - ChannelValueRefType type; union { ChannelValue * value; - ArraySlice * slice; + ArraySlice slice; } ref; } ChannelValueRef; + +ChannelValueRef * MakeChannelValueReference(ChannelValue * value, ChannelDimension * slice); +void DestroyChannelValueReference(ChannelValueRef * ref); + + McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * typeConv); ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); @@ -52,8 +53,6 @@ ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, size_t idx, ChannelType * type, void * ctx); McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx); -ChannelValueRef * MakeChannelValueRef(ChannelValue * val, ChannelDimension * slice); - #ifdef __cplusplus } /* closing brace for extern "C" */ diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index 0ac4972..ab15f46 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1164,13 +1164,11 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { return RETURN_ERROR; } - storeRef = (ChannelValueRef *) object_create(ChannelValueRef); + storeRef = MakeChannelValueReference(&connection->store_, NULL); if (!storeRef) { mcx_log(LOG_ERROR, "Could not create store reference for initial connection"); return RETURN_ERROR; } - storeRef->type = CHANNEL_VALUE_REF_VALUE; - storeRef->ref.value = &connection->store_; if (inInfo->initialValue) { TypeConversion * typeConv = NULL; @@ -1253,7 +1251,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { } cleanup: - object_destroy(storeRef); + DestroyChannelValueReference(storeRef); return retVal; } @@ -1272,23 +1270,26 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim static McxStatus ConnectionInitSetToStore(Connection * connection) { Channel* channel = (Channel*)connection->out_; ChannelInfo* info = &channel->info; - ChannelValueRef * storeRef = (ChannelValueRef *) object_create(ChannelValueRef); + ChannelValueRef * storeRef = MakeChannelValueReference(&connection->store_, NULL); + McxStatus retVal = RETURN_OK; if (!storeRef) { mcx_log(LOG_ERROR, "Could not create store reference for initial connection"); return RETURN_ERROR; } - storeRef->type = CHANNEL_VALUE_REF_VALUE; - storeRef->ref.value = &connection->store_; ConnectionInfo * connInfo = connection->GetInfo(connection); ChannelDimension * clone = CloneChannelDimension(connInfo->sourceDimension); ChannelDimensionAlignIndicesWithZero(clone, info->dimension); - if (RETURN_OK != ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL)) { - return RETURN_ERROR; + retVal = ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL); + if (RETURN_ERROR == retVal) { + goto cleanup; } - return RETURN_OK; +cleanup: + DestroyChannelValueReference(storeRef); + + return retVal; } static McxStatus ConnectionInitUpdateTo(Connection * connection, TimeInterval * time) { From 3ab7d69aefbc8ac19d645a4403bbea4a8d875004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 28 Jun 2022 14:01:06 +0200 Subject: [PATCH 235/295] Rename ChannelValueRef -> ChannelValueReference --- src/core/Conversion.c | 156 +++++++++++----------- src/core/Conversion.h | 8 +- src/core/channels/Channel.c | 10 +- src/core/channels/ChannelValueReference.c | 36 ++--- src/core/channels/ChannelValueReference.h | 16 +-- src/core/connections/Connection.c | 10 +- 6 files changed, 118 insertions(+), 118 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 7822299..6ccec92 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -149,20 +149,20 @@ McxStatus RangeConversionMaxValueRefConversion(void * element, size_t idx, Chann return RETURN_OK; } -static McxStatus RangeConversionConvertValueRef(RangeConversion * conversion, ChannelValueRef * ref) { +static McxStatus RangeConversionConvertValueRef(RangeConversion * conversion, ChannelValueReference * ref) { RangeConversion * rangeConversion = (RangeConversion *) conversion; McxStatus retVal = RETURN_OK; - if (!ChannelTypeEq(ChannelValueRefGetType(ref), rangeConversion->type)) { + if (!ChannelTypeEq(ChannelValueReferenceGetType(ref), rangeConversion->type)) { mcx_log(LOG_ERROR, "Range conversion: Value has wrong type %s, expected: %s", - ChannelTypeToString(ChannelValueRefGetType(ref)), + ChannelTypeToString(ChannelValueReferenceGetType(ref)), ChannelTypeToString(rangeConversion->type)); return RETURN_ERROR; } if (rangeConversion->min) { - retVal = ChannelValueRefElemMap(ref, RangeConversionMinValueRefConversion, rangeConversion->min); + retVal = ChannelValueReferenceElemMap(ref, RangeConversionMinValueRefConversion, rangeConversion->min); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Range conversion: Set value to min failed"); return RETURN_ERROR; @@ -170,7 +170,7 @@ static McxStatus RangeConversionConvertValueRef(RangeConversion * conversion, Ch } if (rangeConversion->max) { - retVal = ChannelValueRefElemMap(ref, RangeConversionMaxValueRefConversion, rangeConversion->max); + retVal = ChannelValueReferenceElemMap(ref, RangeConversionMaxValueRefConversion, rangeConversion->max); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Range conversion: Set value to max failed"); return RETURN_ERROR; @@ -226,7 +226,7 @@ McxStatus ConvertRange(ChannelValue * min, ChannelValue * max, ChannelValue * va if (rangeConv) { if (slice) { - ChannelValueRef * ref = MakeChannelValueReference(value, slice); + ChannelValueReference * ref = MakeChannelValueReference(value, slice); retVal = RangeConversionConvertValueRef(rangeConv, ref); DestroyChannelValueReference(ref); } else { @@ -409,16 +409,16 @@ McxStatus UnitConversionValueRefConversion(void * element, size_t idx, ChannelTy return RETURN_OK; } -static McxStatus UnitConversionConvertValueRef(UnitConversion * conversion, ChannelValueRef * ref) { - if (!ChannelTypeEq(ChannelTypeBaseType(ChannelValueRefGetType(ref)), &ChannelTypeDouble)) { +static McxStatus UnitConversionConvertValueRef(UnitConversion * conversion, ChannelValueReference * ref) { + if (!ChannelTypeEq(ChannelTypeBaseType(ChannelValueReferenceGetType(ref)), &ChannelTypeDouble)) { mcx_log(LOG_ERROR, "Unit conversion: Value has wrong type %s, expected: %s", - ChannelTypeToString(ChannelTypeBaseType(ChannelValueRefGetType(ref))), + ChannelTypeToString(ChannelTypeBaseType(ChannelValueReferenceGetType(ref))), ChannelTypeToString(&ChannelTypeDouble)); return RETURN_ERROR; } - return ChannelValueRefElemMap(ref, UnitConversionValueRefConversion, conversion); + return ChannelValueReferenceElemMap(ref, UnitConversionValueRefConversion, conversion); } static McxStatus UnitConversionSetup(UnitConversion * conversion, @@ -482,7 +482,7 @@ McxStatus ConvertUnit(const char * fromUnit, const char * toUnit, ChannelValue * if (unitConv) { if (slice) { - ChannelValueRef * ref = MakeChannelValueReference(value, slice); + ChannelValueReference * ref = MakeChannelValueReference(value, slice); retVal = UnitConversionConvertValueRef(unitConv, ref); DestroyChannelValueReference(ref); } else { @@ -615,11 +615,11 @@ McxStatus LinearConversionOffsetValueRefConversion(void * element, size_t idx, C return RETURN_OK; } -static McxStatus LinearConversionConvertValueRef(LinearConversion * linearConversion, ChannelValueRef * ref) { +static McxStatus LinearConversionConvertValueRef(LinearConversion * linearConversion, ChannelValueReference * ref) { McxStatus retVal = RETURN_OK; if (linearConversion->factor) { - retVal = ChannelValueRefElemMap(ref, LinearConversionScaleValueRefConversion, linearConversion->factor); + retVal = ChannelValueReferenceElemMap(ref, LinearConversionScaleValueRefConversion, linearConversion->factor); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Linear conversion: Port value scaling failed"); return RETURN_ERROR; @@ -627,7 +627,7 @@ static McxStatus LinearConversionConvertValueRef(LinearConversion * linearConver } if (linearConversion->offset) { - retVal = ChannelValueRefElemMap(ref, LinearConversionOffsetValueRefConversion, linearConversion->offset); + retVal = ChannelValueReferenceElemMap(ref, LinearConversionOffsetValueRefConversion, linearConversion->offset); if (RETURN_OK != retVal) { mcx_log(LOG_ERROR, "Linear conversion: Adding offset failed"); return RETURN_ERROR; @@ -751,7 +751,7 @@ McxStatus ConvertLinear(ChannelValue * factor, ChannelValue * offset, ChannelVal if (linearConv) { if (slice) { - ChannelValueRef * ref = MakeChannelValueReference(value, slice); + ChannelValueReference * ref = MakeChannelValueReference(value, slice); retVal = LinearConversionConvertValueRef(linearConv, ref); DestroyChannelValueReference(ref); } else { @@ -813,7 +813,7 @@ OBJECT_CLASS(LinearConversion, Conversion); // Type Conversion McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, ChannelValue * src, ChannelDimension * srcSlice) { TypeConversion * typeConv = NULL; - ChannelValueRef * ref = NULL; + ChannelValueReference * ref = NULL; McxStatus retVal = RETURN_OK; @@ -835,7 +835,7 @@ McxStatus ConvertType(ChannelValue * dest, ChannelDimension * destSlice, Channel goto cleanup; } - ChannelValueRefSetFromReference(ref, ChannelValueDataPointer(src), srcSlice, typeConv); + ChannelValueReferenceSetFromPointer(ref, ChannelValueDataPointer(src), srcSlice, typeConv); cleanup: object_destroy(typeConv); @@ -858,13 +858,13 @@ static McxStatus CheckTypesValidForConversion(ChannelType * destType, return RETURN_OK; } -static McxStatus CheckArrayReferencingOnlyOneElement(ChannelValueRef * dest, ChannelType * expectedDestType) { - if (!ChannelTypeIsArray(ChannelValueRefGetType(dest))) { +static McxStatus CheckArrayReferencingOnlyOneElement(ChannelValueReference * dest, ChannelType * expectedDestType) { + if (!ChannelTypeIsArray(ChannelValueReferenceGetType(dest))) { mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array"); return RETURN_ERROR; } - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelTypeBaseType(ChannelValueRefGetType(dest)), expectedDestType)) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelTypeBaseType(ChannelValueReferenceGetType(dest)), expectedDestType)) { return RETURN_ERROR; } @@ -884,16 +884,16 @@ static McxStatus CheckArrayReferencingOnlyOneElement(ChannelValueRef * dest, Cha return RETURN_OK; } -static McxStatus ArraysValidForConversion(ChannelValueRef * dest, +static McxStatus ArraysValidForConversion(ChannelValueReference * dest, ChannelType * expectedDestType, mcx_array * src, ChannelDimension * srcDimension) { - if (!ChannelTypeIsArray(ChannelValueRefGetType(dest))) { + if (!ChannelTypeIsArray(ChannelValueReferenceGetType(dest))) { mcx_log(LOG_ERROR, "Type conversion: Destination value is not an array"); return RETURN_ERROR; } - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelTypeBaseType(ChannelValueRefGetType(dest)), expectedDestType)) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelTypeBaseType(ChannelValueReferenceGetType(dest)), expectedDestType)) { return RETURN_ERROR; } @@ -915,8 +915,8 @@ static McxStatus ArraysValidForConversion(ChannelValueRef * dest, return RETURN_OK; } -static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { +static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -925,8 +925,8 @@ static McxStatus TypeConversionConvertIntDouble(Conversion * conversion, Channel return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { +static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -935,8 +935,8 @@ static McxStatus TypeConversionConvertDoubleInt(Conversion * conversion, Channel return RETURN_OK; } -static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { +static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -945,8 +945,8 @@ static McxStatus TypeConversionConvertBoolDouble(Conversion * conversion, Channe return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { +static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } @@ -955,8 +955,8 @@ static McxStatus TypeConversionConvertDoubleBool(Conversion * conversion, Channe return RETURN_OK; } -static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { +static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -965,8 +965,8 @@ static McxStatus TypeConversionConvertBoolInteger(Conversion * conversion, Chann return RETURN_OK; } -static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { +static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } @@ -975,8 +975,8 @@ static McxStatus TypeConversionConvertIntegerBool(Conversion * conversion, Chann return RETURN_OK; } -static McxStatus TypeConversionConvertArrayDoubleToDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { +static McxStatus TypeConversionConvertArrayDoubleToDouble(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -989,8 +989,8 @@ static McxStatus TypeConversionConvertArrayDoubleToDouble(TypeConversion * conve return RETURN_OK; } -static McxStatus TypeConversionConvertArrayIntegerToDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { +static McxStatus TypeConversionConvertArrayIntegerToDouble(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -1003,8 +1003,8 @@ static McxStatus TypeConversionConvertArrayIntegerToDouble(TypeConversion * conv return RETURN_OK; } -static McxStatus TypeConversionConvertArrayBoolToDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeDouble)) { +static McxStatus TypeConversionConvertArrayBoolToDouble(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -1017,8 +1017,8 @@ static McxStatus TypeConversionConvertArrayBoolToDouble(TypeConversion * convers return RETURN_OK; } -static McxStatus TypeConversionConvertArrayDoubleToInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { +static McxStatus TypeConversionConvertArrayDoubleToInteger(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -1031,8 +1031,8 @@ static McxStatus TypeConversionConvertArrayDoubleToInteger(TypeConversion * conv return RETURN_OK; } -static McxStatus TypeConversionConvertArrayIntegerToInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { +static McxStatus TypeConversionConvertArrayIntegerToInteger(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -1045,8 +1045,8 @@ static McxStatus TypeConversionConvertArrayIntegerToInteger(TypeConversion * con return RETURN_OK; } -static McxStatus TypeConversionConvertArrayBoolToInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeInteger)) { +static McxStatus TypeConversionConvertArrayBoolToInteger(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -1059,8 +1059,8 @@ static McxStatus TypeConversionConvertArrayBoolToInteger(TypeConversion * conver return RETURN_OK; } -static McxStatus TypeConversionConvertArrayDoubleToBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { +static McxStatus TypeConversionConvertArrayDoubleToBool(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } @@ -1073,8 +1073,8 @@ static McxStatus TypeConversionConvertArrayDoubleToBool(TypeConversion * convers return RETURN_OK; } -static McxStatus TypeConversionConvertArrayIntegerToBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { +static McxStatus TypeConversionConvertArrayIntegerToBool(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } @@ -1087,8 +1087,8 @@ static McxStatus TypeConversionConvertArrayIntegerToBool(TypeConversion * conver return RETURN_OK; } -static McxStatus TypeConversionConvertArrayBoolToBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueRefGetType(dest), &ChannelTypeBool)) { +static McxStatus TypeConversionConvertArrayBoolToBool(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + if (RETURN_ERROR == CheckTypesValidForConversion(ChannelValueReferenceGetType(dest), &ChannelTypeBool)) { return RETURN_ERROR; } @@ -1101,7 +1101,7 @@ static McxStatus TypeConversionConvertArrayBoolToBool(TypeConversion * conversio return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleToArrayDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertDoubleToArrayDouble(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -1116,7 +1116,7 @@ static McxStatus TypeConversionConvertDoubleToArrayDouble(Conversion * conversio return RETURN_OK; } -static McxStatus TypeConversionConvertIntegerToArrayDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertIntegerToArrayDouble(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -1131,7 +1131,7 @@ static McxStatus TypeConversionConvertIntegerToArrayDouble(Conversion * conversi return RETURN_OK; } -static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeDouble)) { return RETURN_ERROR; } @@ -1146,7 +1146,7 @@ static McxStatus TypeConversionConvertBoolToArrayDouble(Conversion * conversion, return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleToArrayInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertDoubleToArrayInteger(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -1161,7 +1161,7 @@ static McxStatus TypeConversionConvertDoubleToArrayInteger(Conversion * conversi return RETURN_OK; } -static McxStatus TypeConversionConvertIntegerToArrayInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertIntegerToArrayInteger(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -1176,7 +1176,7 @@ static McxStatus TypeConversionConvertIntegerToArrayInteger(Conversion * convers return RETURN_OK; } -static McxStatus TypeConversionConvertBoolToArrayInteger(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertBoolToArrayInteger(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeInteger)) { return RETURN_ERROR; } @@ -1191,7 +1191,7 @@ static McxStatus TypeConversionConvertBoolToArrayInteger(Conversion * conversion return RETURN_OK; } -static McxStatus TypeConversionConvertDoubleToArrayBool(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertDoubleToArrayBool(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeBool)) { return RETURN_ERROR; } @@ -1206,7 +1206,7 @@ static McxStatus TypeConversionConvertDoubleToArrayBool(Conversion * conversion, return RETURN_OK; } -static McxStatus TypeConversionConvertIntegerToArrayBool(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertIntegerToArrayBool(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeBool)) { return RETURN_ERROR; } @@ -1221,7 +1221,7 @@ static McxStatus TypeConversionConvertIntegerToArrayBool(Conversion * conversion return RETURN_OK; } -static McxStatus TypeConversionConvertBoolToArrayBool(Conversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertBoolToArrayBool(Conversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_ERROR == CheckArrayReferencingOnlyOneElement(dest, &ChannelTypeBool)) { return RETURN_ERROR; } @@ -1236,7 +1236,7 @@ static McxStatus TypeConversionConvertBoolToArrayBool(Conversion * conversion, C return RETURN_OK; } -static size_t IndexOfElemInSrcArray(size_t dest_idx, mcx_array * src_array, ChannelDimension * src_dim, ChannelValueRef * dest) { +static size_t IndexOfElemInSrcArray(size_t dest_idx, mcx_array * src_array, ChannelDimension * src_dim, ChannelValueReference * dest) { if (src_dim) { if (dest->type == CHANNEL_VALUE_REF_VALUE) { return ChannelDimensionGetIndex(src_dim, dest_idx, src_array->dims); @@ -1256,7 +1256,7 @@ static size_t IndexOfElemInSrcArray(size_t dest_idx, mcx_array * src_array, Chan typedef struct Array2ArrayCtx { mcx_array * src_array; ChannelDimension * src_dim; - ChannelValueRef * dest; + ChannelValueReference * dest; } Array2ArrayCtx; static McxStatus IntegerArrayToDouble(void * element, size_t idx, ChannelType * type, void * ctx) { @@ -1343,62 +1343,62 @@ static McxStatus IntegerArrayToBool(void * element, size_t idx, ChannelType * ty return RETURN_OK; } -static McxStatus TypeConversionConvertArrayIntegerToArrayDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayIntegerToArrayDouble(TypeConversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeDouble, (mcx_array *) src, conversion->sourceSlice)) { return RETURN_ERROR; } Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; - return ChannelValueRefElemMap(dest, IntegerArrayToDouble, &ctx); + return ChannelValueReferenceElemMap(dest, IntegerArrayToDouble, &ctx); } -static McxStatus TypeConversionConvertArrayBoolToArrayDouble(TypeConversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayBoolToArrayDouble(TypeConversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeDouble, (mcx_array *) src, conversion->sourceSlice)) { return RETURN_ERROR; } Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; - return ChannelValueRefElemMap(dest, BoolArrayToDouble, &ctx); + return ChannelValueReferenceElemMap(dest, BoolArrayToDouble, &ctx); } -static McxStatus TypeConversionConvertArrayDoubleToArrayInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayDoubleToArrayInteger(TypeConversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeInteger, (mcx_array *) src, conversion->sourceSlice)) { return RETURN_ERROR; } Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; - return ChannelValueRefElemMap(dest, DoubleArrayToInteger, &ctx); + return ChannelValueReferenceElemMap(dest, DoubleArrayToInteger, &ctx); } -static McxStatus TypeConversionConvertArrayBoolToArrayInteger(TypeConversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayBoolToArrayInteger(TypeConversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeInteger, (mcx_array *) src, conversion->sourceSlice)) { return RETURN_ERROR; } Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; - return ChannelValueRefElemMap(dest, BoolArrayToInteger, &ctx); + return ChannelValueReferenceElemMap(dest, BoolArrayToInteger, &ctx); } -static McxStatus TypeConversionConvertArrayDoubleToArrayBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayDoubleToArrayBool(TypeConversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeBool, (mcx_array *) src, conversion->sourceSlice)) { return RETURN_ERROR; } Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; - return ChannelValueRefElemMap(dest, DoubleArrayToBool, &ctx); + return ChannelValueReferenceElemMap(dest, DoubleArrayToBool, &ctx); } -static McxStatus TypeConversionConvertArrayIntegerToArrayBool(TypeConversion * conversion, ChannelValueRef * dest, void * src) { +static McxStatus TypeConversionConvertArrayIntegerToArrayBool(TypeConversion * conversion, ChannelValueReference * dest, void * src) { if (RETURN_OK != ArraysValidForConversion(dest, &ChannelTypeBool, (mcx_array *) src, conversion->sourceSlice)) { return RETURN_ERROR; } Array2ArrayCtx ctx = {src, conversion->sourceSlice, dest}; - return ChannelValueRefElemMap(dest, IntegerArrayToBool, &ctx); + return ChannelValueReferenceElemMap(dest, IntegerArrayToBool, &ctx); } -static McxStatus TypeConversionConvertId(TypeConversion * conversion, ChannelValueRef * dest, void * src) { - return ChannelValueRefSetFromReference(dest, src, conversion->sourceSlice, NULL); +static McxStatus TypeConversionConvertId(TypeConversion * conversion, ChannelValueReference * dest, void * src) { + return ChannelValueReferenceSetFromPointer(dest, src, conversion->sourceSlice, NULL); } static int DimensionsMatch(ChannelType * fromType, ChannelDimension * fromDimension, ChannelType * toType, ChannelDimension * toDimension) { diff --git a/src/core/Conversion.h b/src/core/Conversion.h index fe98f8b..1c2d3ed 100644 --- a/src/core/Conversion.h +++ b/src/core/Conversion.h @@ -20,7 +20,7 @@ extern "C" { #endif /* __cplusplus */ -typedef struct ChannelValueRef ChannelValueRef; +typedef struct ChannelValueReference ChannelValueReference; typedef struct Conversion Conversion; @@ -70,7 +70,7 @@ typedef void(*fUnitConversionVector)(UnitConversion * conversion, double * value typedef McxStatus (* fUnitConversionSetup)(UnitConversion * conversion, const char * fromUnit, const char * toUnit); typedef int (* fUnitConversionIsEmpty)(UnitConversion * conversion); -typedef McxStatus (*fUnitConversionConvertValueRef)(UnitConversion * conversion, ChannelValueRef * ref); +typedef McxStatus (*fUnitConversionConvertValueRef)(UnitConversion * conversion, ChannelValueReference * ref); extern const struct ObjectClass _UnitConversion; @@ -126,9 +126,9 @@ typedef McxStatus (*fTypeConversionSetup)(TypeConversion * conversion, const ChannelType * toType, ChannelDimension * toDimension); -// TODO: Ideally the `src` argument would also be ChannelValueRef, but that requires quite of lot of changes +// TODO: Ideally the `src` argument would also be ChannelValueReference, but that requires quite of lot of changes // in the API of databus definition (i.e. DatabusSetIn(Out)Reference) -typedef McxStatus (*fTypeConversionConvert)(TypeConversion * conversion, ChannelValueRef * dest, void * src); +typedef McxStatus (*fTypeConversionConvert)(TypeConversion * conversion, ChannelValueReference * dest, void * src); extern const struct ObjectClass _TypeConversion; diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index d47ca47..f90d626 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -279,16 +279,16 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ConnectionInfo * connInfo = &conn->info; TypeConversion * typeConv = (TypeConversion *) in->data->typeConversions->At(in->data->typeConversions, i); UnitConversion * unitConv = (UnitConversion *) in->data->unitConversions->At(in->data->unitConversions, i); - ChannelValueRef * valueRef = (ChannelValueRef *) in->data->valueReferences->At(in->data->valueReferences, i); + ChannelValueReference * valueRef = (ChannelValueReference *) in->data->valueReferences->At(in->data->valueReferences, i); /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "UpdateToOutput failed"); } - // TODO: ideally make conn->GetValueReference return ChannelValueRef - if (RETURN_OK != ChannelValueRefSetFromReference(valueRef, conn->GetValueReference(conn), conn->GetValueDimension(conn), typeConv)) { - return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "ChannelValueRefSetFromReference failed"); + // TODO: ideally make conn->GetValueReference return ChannelValueReference + if (RETURN_OK != ChannelValueReferenceSetFromPointer(valueRef, conn->GetValueReference(conn), conn->GetValueDimension(conn), typeConv)) { + return ReportConnStringError(info, "Update inport for connection %s: ", connInfo, "ChannelValueReferenceSetFromPointer failed"); } // unit conversion @@ -424,7 +424,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec ConnectionInfo * connInfo = &connection->info; Channel * channel = (Channel *) in; ChannelInfo * inInfo = &channel->info; - ChannelValueRef * valRef = NULL; + ChannelValueReference * valRef = NULL; McxStatus retVal = RETURN_OK; diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 6fa0e6c..857aa29 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -16,7 +16,7 @@ extern "C" { #endif /* __cplusplus */ -void DestroyChannelValueReference(ChannelValueRef * ref) { +void DestroyChannelValueReference(ChannelValueReference * ref) { if (ref->type == CHANNEL_VALUE_REF_SLICE) { if (ref->ref.slice.dimension) { DestroyChannelDimension(&ref->ref.slice.dimension); @@ -27,8 +27,8 @@ void DestroyChannelValueReference(ChannelValueRef * ref) { } -ChannelValueRef * MakeChannelValueReference(ChannelValue * value, ChannelDimension * slice) { - ChannelValueRef * ref = (ChannelValueRef *) mcx_calloc(1, sizeof(ChannelValueRef)); +ChannelValueReference * MakeChannelValueReference(ChannelValue * value, ChannelDimension * slice) { + ChannelValueReference * ref = (ChannelValueReference *) mcx_calloc(1, sizeof(ChannelValueReference)); if (!ref) { return NULL; @@ -47,18 +47,18 @@ ChannelValueRef * MakeChannelValueReference(ChannelValue * value, ChannelDimensi } -McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * conv) { +McxStatus ChannelValueReferenceSetFromPointer(ChannelValueReference * ref, const void * ptr, ChannelDimension * srcDimension, TypeConversion * conv) { if (conv) { - return conv->Convert(conv, ref, reference); + return conv->Convert(conv, ref, ptr); } if (ref->type == CHANNEL_VALUE_REF_VALUE) { if (ChannelTypeIsArray(ref->ref.value->type)) { mcx_array * destArray = &ref->ref.value->value.a; - mcx_array * srcArray = (mcx_array *) reference; + mcx_array * srcArray = (mcx_array *) ptr; if (srcArray->data == NULL || destArray->data == NULL) { - mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Empty array data given"); + mcx_log(LOG_ERROR, "ChannelValueReferenceSetFromPointer: Empty array data given"); return RETURN_ERROR; } @@ -87,10 +87,10 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re return RETURN_OK; } else { if (srcDimension) { - mcx_array * src = (mcx_array *) (reference); + mcx_array * src = (mcx_array *) (ptr); if (ChannelDimensionNumElements(srcDimension) != 1) { - mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Setting scalar value from an array"); + mcx_log(LOG_ERROR, "ChannelValueReferenceSetFromPointer: Setting scalar value from an array"); return RETURN_ERROR; } @@ -99,18 +99,18 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re ref->ref.value->type, mcx_array_get_elem_reference(src, ChannelDimensionGetIndex(srcDimension, 0, src->dims))); } else { - return ChannelValueDataSetFromReference(&ref->ref.value->value, ref->ref.value->type, reference); + return ChannelValueDataSetFromReference(&ref->ref.value->value, ref->ref.value->type, ptr); } } } else { if (ChannelTypeIsArray(ref->ref.slice.ref->type)) { mcx_array * destArray = &ref->ref.slice.ref->value.a; - mcx_array * srcArray = (mcx_array *) reference; + mcx_array * srcArray = (mcx_array *) ptr; ChannelDimension * destDimension = ref->ref.slice.dimension; if (srcArray->data == NULL || destArray->data == NULL) { - mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Empty array data given"); + mcx_log(LOG_ERROR, "ChannelValueReferenceSetFromPointer: Empty array data given"); return RETURN_ERROR; } @@ -143,10 +143,10 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re return RETURN_OK; } else { if (srcDimension) { - mcx_array * src = (mcx_array *) (reference); + mcx_array * src = (mcx_array *) (ptr); if (ChannelDimensionNumElements(srcDimension) != 1) { - mcx_log(LOG_ERROR, "ChannelValueRefSetFromReference: Setting scalar value from an array"); + mcx_log(LOG_ERROR, "ChannelValueReferenceSetFromPointer: Setting scalar value from an array"); return RETURN_ERROR; } @@ -155,7 +155,7 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re ref->ref.slice.ref->type, mcx_array_get_elem_reference(src, ChannelDimensionGetIndex(srcDimension, 0, src->dims))); } else { - return ChannelValueDataSetFromReference(&ref->ref.slice.ref->value, ref->ref.slice.ref->type, reference); + return ChannelValueDataSetFromReference(&ref->ref.slice.ref->value, ref->ref.slice.ref->type, ptr); } } } @@ -163,7 +163,7 @@ McxStatus ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * re return RETURN_OK; } -McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx) { +McxStatus ChannelValueReferenceElemMap(ChannelValueReference * ref, fChannelValueReferenceElemMapFunc fn, void * ctx) { switch (ref->type) { case CHANNEL_VALUE_REF_VALUE: if (ChannelTypeIsArray(ref->ref.value->type)) { @@ -206,12 +206,12 @@ McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapF return fn(ChannelValueDataPointer(ref->ref.slice.ref), 0, ChannelValueType(ref->ref.slice.ref), ctx); } default: - mcx_log(LOG_ERROR, "ChannelValueRefElemMap: Invalid internal channel value reference type (%d)", ref->type); + mcx_log(LOG_ERROR, "ChannelValueReferenceElemMap: Invalid internal channel value reference type (%d)", ref->type); return RETURN_ERROR; } } -ChannelType * ChannelValueRefGetType(ChannelValueRef * ref) { +ChannelType * ChannelValueReferenceGetType(ChannelValueReference * ref) { switch (ref->type) { case CHANNEL_VALUE_REF_VALUE: return ChannelValueType(ref->ref.value); diff --git a/src/core/channels/ChannelValueReference.h b/src/core/channels/ChannelValueReference.h index 166b531..10ea9bd 100644 --- a/src/core/channels/ChannelValueReference.h +++ b/src/core/channels/ChannelValueReference.h @@ -33,25 +33,25 @@ typedef enum ChannelValueRefType { } ChannelValueRefType; -typedef struct ChannelValueRef { +typedef struct ChannelValueReference { ChannelValueRefType type; union { ChannelValue * value; ArraySlice slice; } ref; -} ChannelValueRef; +} ChannelValueReference; -ChannelValueRef * MakeChannelValueReference(ChannelValue * value, ChannelDimension * slice); -void DestroyChannelValueReference(ChannelValueRef * ref); +ChannelValueReference * MakeChannelValueReference(ChannelValue * value, ChannelDimension * slice); +void DestroyChannelValueReference(ChannelValueReference * ref); McxStatus -ChannelValueRefSetFromReference(ChannelValueRef * ref, const void * reference, ChannelDimension * srcDimension, TypeConversion * typeConv); -ChannelType * ChannelValueRefGetType(ChannelValueRef * ref); +ChannelValueReferenceSetFromPointer(ChannelValueReference * ref, const void * ptr, ChannelDimension * srcDimension, TypeConversion * typeConv); +ChannelType * ChannelValueReferenceGetType(ChannelValueReference * ref); -typedef McxStatus (*fChannelValueRefElemMapFunc)(void * element, size_t idx, ChannelType * type, void * ctx); -McxStatus ChannelValueRefElemMap(ChannelValueRef * ref, fChannelValueRefElemMapFunc fn, void * ctx); +typedef McxStatus (*fChannelValueReferenceElemMapFunc)(void * element, size_t idx, ChannelType * type, void * ctx); +McxStatus ChannelValueReferenceElemMap(ChannelValueReference * ref, fChannelValueReferenceElemMapFunc fn, void * ctx); #ifdef __cplusplus diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index ab15f46..ccb00cb 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1146,7 +1146,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { ChannelInfo * inInfo = &in->info; ChannelInfo * outInfo = &out->info; - ChannelValueRef * storeRef = NULL; + ChannelValueReference * storeRef = NULL; McxStatus retVal = RETURN_OK; @@ -1201,7 +1201,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { } } - retVal = ChannelValueRefSetFromReference(storeRef, ChannelValueDataPointer(inChannelValue), srcDim, typeConv); + retVal = ChannelValueReferenceSetFromPointer(storeRef, ChannelValueDataPointer(inChannelValue), srcDim, typeConv); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Could not set up initial value in connection"); goto cleanup_1; @@ -1231,7 +1231,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { goto cleanup; } - ChannelValueRefSetFromReference(storeRef, ChannelValueDataPointer(outInfo->initialValue), targetDim, NULL); + ChannelValueReferenceSetFromPointer(storeRef, ChannelValueDataPointer(outInfo->initialValue), targetDim, NULL); connection->useInitialValue_ = TRUE; } else { { @@ -1270,7 +1270,7 @@ static void ConnectionInitUpdateFrom(Connection * connection, TimeInterval * tim static McxStatus ConnectionInitSetToStore(Connection * connection) { Channel* channel = (Channel*)connection->out_; ChannelInfo* info = &channel->info; - ChannelValueRef * storeRef = MakeChannelValueReference(&connection->store_, NULL); + ChannelValueReference * storeRef = MakeChannelValueReference(&connection->store_, NULL); McxStatus retVal = RETURN_OK; if (!storeRef) { @@ -1281,7 +1281,7 @@ static McxStatus ConnectionInitSetToStore(Connection * connection) { ConnectionInfo * connInfo = connection->GetInfo(connection); ChannelDimension * clone = CloneChannelDimension(connInfo->sourceDimension); ChannelDimensionAlignIndicesWithZero(clone, info->dimension); - retVal = ChannelValueRefSetFromReference(storeRef, channel->GetValueReference(channel), clone, NULL); + retVal = ChannelValueReferenceSetFromPointer(storeRef, channel->GetValueReference(channel), clone, NULL); if (RETURN_ERROR == retVal) { goto cleanup; } From cfbee10775276bbdd5f426e41a065cbf976d7b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 28 Jun 2022 15:04:35 +0200 Subject: [PATCH 236/295] Make sure DirectConnection has the correct store size --- src/core/connections/Connection.c | 25 ++++++++++++++++++++----- src/core/connections/Connection.h | 6 ++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index ccb00cb..f689b11 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1401,7 +1401,6 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * Channel * chOut = (Channel *) out; ChannelInfo * outInfo = &chOut->info; - ChannelType * storeType = NULL; connection->out_ = out; connection->in_ = in; @@ -1412,13 +1411,14 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * connection->info = *info; - storeType = ChannelTypeFromDimension(outInfo->type, info->sourceDimension); - if (!storeType) { + retVal = connection->SetupStore(connection, out, in, info); + if (RETURN_ERROR == retVal) { + char * buffer = ConnectionInfoConnectionString(info); + mcx_log(LOG_ERROR, "Connection %s: Store setup failed", buffer); + mcx_free(buffer); return RETURN_ERROR; } - ChannelValueInit(&connection->store_, storeType); - // Add connection to channel out retVal = out->RegisterConnection(out, connection); if (RETURN_OK != retVal) { @@ -1439,10 +1439,25 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * return RETURN_OK; } +McxStatus ConnectionSetupStore(Connection * connection, ChannelOut * out, ChannelIn * in, ConnectionInfo * info) { + Channel * chOut = (Channel *) out; + ChannelInfo * outInfo = &chOut->info; + ChannelType * storeType = ChannelTypeFromDimension(outInfo->type, info->sourceDimension); + + if (!storeType) { + return RETURN_ERROR; + } + + ChannelValueInit(&connection->store_, storeType); + + return RETURN_OK; +} + static Connection * ConnectionCreate(Connection * connection) { McxStatus retVal = RETURN_OK; connection->Setup = NULL; + connection->SetupStore = ConnectionSetupStore; connection->GetSource = ConnectionGetSource; connection->GetTarget = ConnectionGetTarget; diff --git a/src/core/connections/Connection.h b/src/core/connections/Connection.h index bd07776..1e54b67 100644 --- a/src/core/connections/Connection.h +++ b/src/core/connections/Connection.h @@ -45,6 +45,10 @@ typedef McxStatus (* fConnectionSetup)(Connection * channel, struct ChannelOut * out, struct ChannelIn * in, struct ConnectionInfo * info); +typedef McxStatus (* fConnectionSetupStore)(Connection * conn, + struct ChannelOut * out, + struct ChannelIn * in, + struct ConnectionInfo * info); typedef struct ChannelOut * (* fConnectionGetSource)(Connection * connection); typedef struct ChannelIn * (* fConnectionGetTarget)(Connection * connection); @@ -119,6 +123,8 @@ struct Connection { */ fConnectionSetup Setup; + fConnectionSetupStore SetupStore; + /** * Returns the source out channel. */ From 6832d171391b8c91db585da2f7c6db4a98fce2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Tue, 28 Jun 2022 16:25:08 +0200 Subject: [PATCH 237/295] ConnectionInfo: free dimensions --- src/core/Model.c | 4 ++-- src/core/channels/ChannelDimension.c | 8 +++----- src/core/channels/ChannelDimension.h | 2 +- src/core/channels/ChannelValueReference.c | 2 +- src/core/connections/Connection.c | 6 +++++- src/core/connections/ConnectionInfo.c | 16 ++++++++++++++++ src/core/connections/ConnectionInfo.h | 2 ++ src/core/connections/ConnectionInfoFactory.c | 10 +++++----- 8 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/core/Model.c b/src/core/Model.c index 7c0ff98..58c5310 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -168,7 +168,7 @@ static McxStatus ModelPreprocessConstConnections(Model * model) { mcx_log(LOG_ERROR, "Not enough memory to filter out constant connections"); return RETURN_ERROR; } - filteredConns->Setup(filteredConns, sizeof(ConnectionInfo), ConnectionInfoInit, NULL, NULL); + filteredConns->Setup(filteredConns, sizeof(ConnectionInfo), ConnectionInfoInit, ConnectionInfoSetFrom, DestroyConnectionInfo); for (i = 0; i < conns->Size(conns); i++) { ConnectionInfo * info = (ConnectionInfo *) conns->At(conns, i); @@ -1716,7 +1716,7 @@ static Model * ModelCreate(Model * model) { // set to default values model->components = (ObjectContainer *) object_create(ObjectContainer); model->connections = (Vector *) object_create(Vector); - model->connections->Setup(model->connections, sizeof(ConnectionInfo), ConnectionInfoInit, NULL, NULL); + model->connections->Setup(model->connections, sizeof(ConnectionInfo), ConnectionInfoInit, ConnectionInfoSetFrom, DestroyConnectionInfo); model->factory = NULL; model->config = NULL; diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index f86c675..41b03f9 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -319,11 +319,9 @@ ChannelDimension * MakeChannelDimension() { return dimension; } -void DestroyChannelDimension(ChannelDimension ** dimension) { - if ((*dimension)->startIdxs) { mcx_free((*dimension)->startIdxs); } - if ((*dimension)->endIdxs) { mcx_free((*dimension)->endIdxs); } - - *dimension = NULL; +void DestroyChannelDimension(ChannelDimension * dimension) { + if (dimension->startIdxs) { mcx_free(dimension->startIdxs); } + if (dimension->endIdxs) { mcx_free(dimension->endIdxs); } } diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 0fdbf0d..7398fd6 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -30,7 +30,7 @@ typedef struct ChannelDimension { ChannelDimension * MakeChannelDimension(); ChannelDimension * CloneChannelDimension(const ChannelDimension * dimension); -void DestroyChannelDimension(ChannelDimension ** dimension); +void DestroyChannelDimension(ChannelDimension * dimension); McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 857aa29..0279779 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -19,7 +19,7 @@ extern "C" { void DestroyChannelValueReference(ChannelValueReference * ref) { if (ref->type == CHANNEL_VALUE_REF_SLICE) { if (ref->ref.slice.dimension) { - DestroyChannelDimension(&ref->ref.slice.dimension); + DestroyChannelDimension(ref->ref.slice.dimension); } } diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index f689b11..ac28c78 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1097,6 +1097,7 @@ static ChannelType * ConnectionGetValueType(Connection * connection) { static void ConnectionDestructor(Connection * connection) { ChannelValueDestructor(&connection->store_); + DestroyConnectionInfo(&connection->info); } static ChannelOut * ConnectionGetSource(Connection * connection) { @@ -1409,7 +1410,10 @@ McxStatus ConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * info->hasDiscreteTarget = TRUE; } - connection->info = *info; + retVal = ConnectionInfoSetFrom(&connection->info, info); + if (RETURN_ERROR == retVal) { + return RETURN_ERROR; + } retVal = connection->SetupStore(connection, out, in, info); if (RETURN_ERROR == retVal) { diff --git a/src/core/connections/ConnectionInfo.c b/src/core/connections/ConnectionInfo.c index eec8b3b..4a4ae3c 100644 --- a/src/core/connections/ConnectionInfo.c +++ b/src/core/connections/ConnectionInfo.c @@ -137,6 +137,22 @@ char * ConnectionInfoConnectionString(ConnectionInfo * info) { return buffer; } +void DestroyConnectionInfo(ConnectionInfo * info) { + if (info->sourceDimension) { DestroyChannelDimension(info->sourceDimension); } + if (info->targetDimension) { DestroyChannelDimension(info->targetDimension); } +} + +McxStatus ConnectionInfoSetFrom(ConnectionInfo * info, const ConnectionInfo * other) { + McxStatus retVal = RETURN_OK; + + memcpy(info, other, sizeof(ConnectionInfo)); + + info->sourceDimension = CloneChannelDimension(other->sourceDimension); + info->targetDimension = CloneChannelDimension(other->targetDimension); + + return RETURN_OK; +} + McxStatus ConnectionInfoInit(ConnectionInfo * info) { info->sourceComponent = NULL; info->targetComponent = NULL; diff --git a/src/core/connections/ConnectionInfo.h b/src/core/connections/ConnectionInfo.h index 8d9a171..7b27627 100644 --- a/src/core/connections/ConnectionInfo.h +++ b/src/core/connections/ConnectionInfo.h @@ -55,6 +55,8 @@ typedef struct ConnectionInfo { McxStatus ConnectionInfoInit(ConnectionInfo * info); +McxStatus ConnectionInfoSetFrom(ConnectionInfo * info, const ConnectionInfo * other); +void DestroyConnectionInfo(ConnectionInfo * info); ChannelType * ConnectionInfoGetType(ConnectionInfo * info); diff --git a/src/core/connections/ConnectionInfoFactory.c b/src/core/connections/ConnectionInfoFactory.c index 1e73034..9f0ef0b 100644 --- a/src/core/connections/ConnectionInfoFactory.c +++ b/src/core/connections/ConnectionInfoFactory.c @@ -126,14 +126,14 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, if (RETURN_OK != ChannelDimensionSetup(sourceDimension, 1)) { mcx_log(LOG_ERROR, "Source port %s: Could not set number of dimensions", strFromChannel); retVal = RETURN_ERROR; - DestroyChannelDimension(&sourceDimension); + DestroyChannelDimension(sourceDimension); goto cleanup; } if (RETURN_OK != ChannelDimensionSetDimension(sourceDimension, 0, connInput->from.vectorEndpoint->startIndex, connInput->from.vectorEndpoint->endIndex)) { mcx_log(LOG_ERROR, "Source port %s: Could not set dimension boundaries", strFromChannel); retVal = RETURN_ERROR; - DestroyChannelDimension(&sourceDimension); + DestroyChannelDimension(sourceDimension); goto cleanup; } @@ -212,7 +212,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, if (RETURN_OK != ChannelDimensionSetup(targetDimension, 1)) { mcx_log(LOG_ERROR, "Target port %s: Could not set number of dimensions", strToChannel); retVal = RETURN_ERROR; - DestroyChannelDimension(&targetDimension); + DestroyChannelDimension(targetDimension); goto cleanup; } @@ -223,7 +223,7 @@ static McxStatus ConnectionInfoFactoryInitConnectionInfo(ConnectionInfo * info, { mcx_log(LOG_ERROR, "Target port %s: Could not set dimension boundaries", strToChannel); retVal = RETURN_ERROR; - DestroyChannelDimension(&targetDimension); + DestroyChannelDimension(targetDimension); goto cleanup; } @@ -358,7 +358,7 @@ Vector * ConnectionInfoFactoryCreateConnectionInfos( goto cleanup; } - list->Setup(list, sizeof(ConnectionInfo), ConnectionInfoInit, NULL, NULL); + list->Setup(list, sizeof(ConnectionInfo), ConnectionInfoInit, ConnectionInfoSetFrom, DestroyConnectionInfo); retVal = ConnectionInfoFactoryInitConnectionInfo(&info, components, connInput, sourceCompOverride, targetCompOverride); if (RETURN_ERROR == retVal) { From 3a0fe55078e36b0f0af19fdc22e2ce0fda8ca408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 29 Jun 2022 11:59:33 +0200 Subject: [PATCH 238/295] GetInConnectionInfos: Use Vector instead of ObjectContainer --- src/core/Component.c | 2 +- src/core/Component.h | 3 ++- src/core/SubModel.c | 13 +++++++++---- src/core/channels/Channel.c | 8 +++++--- src/core/channels/Channel.h | 2 +- src/fmu/common_fmu2.c | 5 +++-- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 427e7e5..876f99f 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -840,7 +840,7 @@ static void ComponentSetModel(Component * comp, Model * model) { comp->data->model = model; } -ObjectContainer * GetInConnectionInfos(const Component * comp, size_t channelID) { +Vector * GetInConnectionInfos(const Component * comp, size_t channelID) { size_t channelNum = DatabusInfoGetChannelNum(DatabusGetInInfo(comp->data->databus)); if (channelID < channelNum) { diff --git a/src/core/Component.h b/src/core/Component.h index 8abede0..3e1493a 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -16,6 +16,7 @@ #include "core/Component_interface.h" #include "core/Dependency.h" #include "objects/StringContainer.h" +#include "objects/Vector.h" #include "reader/model/components/ComponentInput.h" #include "core/connections/ConnectionInfo.h" @@ -250,7 +251,7 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, struct St McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time); McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time); -struct ObjectContainer * GetInConnectionInfos(const Component * comp, size_t channelID); +Vector * GetInConnectionInfos(const Component * comp, size_t channelID); struct ObjectContainer * GetInConnections(const Component * comp, size_t channelID); size_t ComponentGetNumOutGroups(const Component * comp); diff --git a/src/core/SubModel.c b/src/core/SubModel.c index c2315d9..c2999e0 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -689,7 +689,7 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen // initial inputs are always exact if (info->initialValue) { //check if connection exists (cosim init values are not deoupling connections, they only have lower priority than connection values) - ObjectContainer * infos = GetInConnectionInfos(targetComp, targetInChannelID); + Vector * infos = GetInConnectionInfos(targetComp, targetInChannelID); size_t numInfos = infos->Size(infos); size_t i = 0; @@ -698,8 +698,9 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen } else { int allDecoupled = TRUE; for (i = 0; i < numInfos; i++) { - ConnectionInfo * info = (ConnectionInfo *) infos->At(infos, i); + ConnectionInfo * info = *(ConnectionInfo**) infos->At(infos, i); if (!ConnectionInfoIsDecoupled(info)) { + object_destroy(infos); allDecoupled = FALSE; break; } @@ -709,16 +710,17 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen dependency = DEP_INDEPENDENT; } } + object_destroy(infos); } } if (DEP_INDEPENDENT != dependency) { - ObjectContainer * infos = GetInConnectionInfos(targetComp, targetInChannelID); + Vector * infos = GetInConnectionInfos(targetComp, targetInChannelID); ObjectContainer * conns = GetInConnections(targetComp, targetInChannelID); size_t i = 0; for (i = 0; i < infos->Size(infos); i++) { - ConnectionInfo * info = infos->At(infos, i); + ConnectionInfo * info = *(ConnectionInfo**) infos->At(infos, i); Connection * conn = conns->At(conns, i); if (info && (info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED)) && (!ConnectionInfoIsDecoupled(info)) && @@ -760,6 +762,7 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "SetDependency failed in SubModelGeneratorCreateDependencyMatrix"); mcx_free(A); + object_destroy(infos); return NULL; } @@ -779,6 +782,8 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen } } } + + object_destroy(infos); } } if (targetCompDependency) { diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index f90d626..09ade87 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -395,8 +395,8 @@ static int ChannelInIsConnected(Channel * channel) { return FALSE; } -static ObjectContainer * ChannelInGetConnectionInfos(ChannelIn * in) { - ObjectContainer * infos = (ObjectContainer *) object_create(ObjectContainer); +static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { + Vector * infos = (Vector*) object_create(Vector); size_t numConns = in->data->connections->Size(in->data->connections); size_t i = 0; @@ -404,10 +404,12 @@ static ObjectContainer * ChannelInGetConnectionInfos(ChannelIn * in) { return NULL; } + infos->Setup(infos, sizeof(ConnectionInfo*), NULL, NULL, NULL); + for (i = 0; i < numConns; i++) { Connection * conn = in->data->connections->At(in->data->connections, i); ConnectionInfo * connInfo = &conn->info; - if (RETURN_ERROR == infos->PushBack(infos, (Object *) connInfo)) { + if (RETURN_ERROR == infos->PushBack(infos, &connInfo)) { object_destroy(infos); return NULL; } diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index dbebf8d..52d45d3 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -122,7 +122,7 @@ typedef McxStatus (* fChannelInSetReference) (ChannelIn * in, void * reference, ChannelType * type); -typedef struct ObjectContainer * (* fChannelInGetConnectionInfos)(ChannelIn * in); +typedef struct Vector * (* fChannelInGetConnectionInfos)(ChannelIn * in); typedef struct ObjectContainer * (* fChannelInGetConnections)(ChannelIn * in); diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 6e3fc40..3a07319 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -796,9 +796,9 @@ McxStatus Fmu2SetDependencies(Fmu2CommonStruct * fmu2, Databus * db, Dependencie } // if an element index appears in elems, it means that element is connected - ObjectContainer * connInfos = in->GetConnectionInfos(in); + Vector * connInfos = in->GetConnectionInfos(in); for (j = 0; j < connInfos->Size(connInfos); j++) { - ConnectionInfo * connInfo = (ConnectionInfo *) connInfos->At(connInfos, j); + ConnectionInfo * connInfo = *(ConnectionInfo**) connInfos->At(connInfos, j); size_t k = 0; for (k = 0; k < ChannelDimensionNumElements(connInfo->targetDimension); k++) { @@ -806,6 +806,7 @@ McxStatus Fmu2SetDependencies(Fmu2CommonStruct * fmu2, Databus * db, Dependencie in_channel_connectivity[i].elems[in_channel_connectivity[i].num_elems++] = idx; } } + object_destroy(connInfos); } else { in_channel_connectivity[i].is_connected = TRUE; // scalar channels are treated like they have 1 element (equal to zero) From 31c26d3f41e11a0e9c1abf53acb1e2a64676d590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 29 Jun 2022 12:35:56 +0200 Subject: [PATCH 239/295] Make sure to provide a type clone to ChannelValueInit --- src/components/comp_vector_integrator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 102f9ab..77bc342 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -77,8 +77,8 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con return RETURN_ERROR; } - ChannelValueInit(&integrator->deriv[i], type); - ChannelValueInit(&integrator->state[i], type); + ChannelValueInit(&integrator->deriv[i], ChannelTypeClone(type)); + ChannelValueInit(&integrator->state[i], ChannelTypeClone(type)); } return RETURN_OK; From 7e988a5869a9f6c9a1aaac5f825d76451af805c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 29 Jun 2022 13:08:06 +0200 Subject: [PATCH 240/295] Use Vector to store ChannelValueReferences --- src/core/channels/Channel.c | 11 ++++++++--- src/core/channels/Channel_impl.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 09ade87..19bc76d 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -154,6 +154,9 @@ static Channel * ChannelCreate(Channel * channel) { // object that is stored in target component that stores // the channel connection +static void DestroyChannelValueReferencePtr(ChannelValueReference ** ptr) { + DestroyChannelValueReference(*ptr); +} static ChannelInData * ChannelInDataCreate(ChannelInData * data) { data->connections = (ObjectContainer *) object_create(ObjectContainer); @@ -161,11 +164,13 @@ static ChannelInData * ChannelInDataCreate(ChannelInData * data) { return NULL; } - data->valueReferences = (ObjectContainer *) object_create(ObjectContainer); + data->valueReferences = (Vector *) object_create(Vector); if (!data->valueReferences) { return NULL; } + data->valueReferences->Setup(data->valueReferences, sizeof(ChannelValueReference *), NULL, NULL, DestroyChannelValueReferencePtr); + data->reference = NULL; data->type = ChannelTypeClone(&ChannelTypeUnknown); @@ -279,7 +284,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ConnectionInfo * connInfo = &conn->info; TypeConversion * typeConv = (TypeConversion *) in->data->typeConversions->At(in->data->typeConversions, i); UnitConversion * unitConv = (UnitConversion *) in->data->unitConversions->At(in->data->unitConversions, i); - ChannelValueReference * valueRef = (ChannelValueReference *) in->data->valueReferences->At(in->data->valueReferences, i); + ChannelValueReference * valueRef = *(ChannelValueReference **) in->data->valueReferences->At(in->data->valueReferences, i); /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { @@ -453,7 +458,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec valRef = MakeChannelValueReference(&channel->value, NULL); } - retVal = in->data->valueReferences->PushBack(in->data->valueReferences, (Object *) valRef); + retVal = in->data->valueReferences->PushBack(in->data->valueReferences, &valRef); // TODO check retVal if (ChannelTypeEq(ChannelTypeBaseType(inInfo->type), &ChannelTypeDouble)) { diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index e594a78..2b330e6 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -29,7 +29,7 @@ typedef struct ChannelInData { Object _; // base class ObjectContainer * connections; // connections (non-overlapping) going into the channel - ObjectContainer * valueReferences; // references to non-overlapping parts of ChannelData::value, where + Vector * valueReferences; // references to non-overlapping parts of ChannelData::value, where // values gotten from connections are going to be stored // ---------------------------------------------------------------------- From aef1a3bc3faf3e6e15a3b78aebc5103abd339764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 29 Jun 2022 15:01:36 +0200 Subject: [PATCH 241/295] Get rid of TODOs --- src/core/channels/Channel.c | 20 +++++++++++++------- src/core/channels/ChannelValue.h | 1 - src/core/channels/ChannelValueReference.c | 1 - 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 19bc76d..73f945a 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -190,8 +190,6 @@ static ChannelInData * ChannelInDataCreate(ChannelInData * data) { return data; } -// TODO fix Create and Destructor to properly free memory in case of failure - static void ChannelInDataDestructor(ChannelInData * data) { // clean up conversion objects data->typeConversions->DestroyObjects(data->typeConversions); @@ -210,7 +208,13 @@ static void ChannelInDataDestructor(ChannelInData * data) { ChannelTypeDestructor(data->type); } - // TODO destroy connections/valueReference ???? + if (data->connections) { + object_destroy(data->connections); + } + + if (data->valueReferences) { + object_destroy(data->valueReferences); + } } OBJECT_CLASS(ChannelInData, Object); @@ -441,9 +445,6 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec } ChannelDimension * dimension = connInfo->targetDimension; - // TODO check ret values - // TODO do we need some plausibility checks? - // TODO is it fine to use connInfo here? if (dimension && !ChannelDimensionEq(dimension, inInfo->dimension)) { ChannelDimension * slice = CloneChannelDimension(dimension); @@ -459,7 +460,10 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec } retVal = in->data->valueReferences->PushBack(in->data->valueReferences, &valRef); - // TODO check retVal + if (RETURN_ERROR == retVal) { + ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Storing value reference failed"); + return RETURN_ERROR; + } if (ChannelTypeEq(ChannelTypeBaseType(inInfo->type), &ChannelTypeDouble)) { UnitConversion * conversion = (UnitConversion *) object_create(UnitConversion); @@ -728,6 +732,8 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * static McxStatus ChannelOutRegisterConnection(ChannelOut * out, Connection * connection) { ObjectList * conns = out->data->connections; + ChannelDimension * outDim = ((Channel*)out)->info.dimension; + ChannelDimension * connDim = connection->info.sourceDimension; // TODO: do we have to check that channelout and connection match // in type/dimension? diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 0e529b0..212aeb1 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -125,7 +125,6 @@ typedef int (*mcx_array_predicate_f_ptr)(void * element, ChannelType * type); int mcx_array_all(mcx_array * a, mcx_array_predicate_f_ptr predicate); int mcx_array_leq(const mcx_array * left, const mcx_array * right); -// TODO: change concrete types to McxDouble, McxInteger, etc union ChannelValueData { /* the order is significant. double needs to be the first entry for union initialization to work */ double d; diff --git a/src/core/channels/ChannelValueReference.c b/src/core/channels/ChannelValueReference.c index 0279779..152e363 100644 --- a/src/core/channels/ChannelValueReference.c +++ b/src/core/channels/ChannelValueReference.c @@ -216,7 +216,6 @@ ChannelType * ChannelValueReferenceGetType(ChannelValueReference * ref) { case CHANNEL_VALUE_REF_VALUE: return ChannelValueType(ref->ref.value); case CHANNEL_VALUE_REF_SLICE: - // TODO (do we need to adapt the indices wrt. dimension) ? return ChannelValueType(ref->ref.slice.ref); default: mcx_log(LOG_ERROR, "Invalid internal channel value reference type (%d)", ref->type); From dcd906aeab59f1b29211bcee8b8c863676816840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 7 Jul 2022 09:04:38 +0200 Subject: [PATCH 242/295] Rename ChannelDimensionSetDimension argument --- src/core/channels/ChannelDimension.c | 8 ++++---- src/core/channels/ChannelDimension.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 41b03f9..986ffc3 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -40,13 +40,13 @@ McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num) { return RETURN_ERROR; } -McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end) { - if (num > dimension->num) { +McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t dim, size_t start, size_t end) { + if (dim > dimension->num) { return RETURN_ERROR; } - dimension->startIdxs[num] = start; - dimension->endIdxs[num] = end; + dimension->startIdxs[dim] = start; + dimension->endIdxs[dim] = end; return RETURN_OK; } diff --git a/src/core/channels/ChannelDimension.h b/src/core/channels/ChannelDimension.h index 7398fd6..a98d6ef 100644 --- a/src/core/channels/ChannelDimension.h +++ b/src/core/channels/ChannelDimension.h @@ -33,7 +33,7 @@ ChannelDimension * CloneChannelDimension(const ChannelDimension * dimension); void DestroyChannelDimension(ChannelDimension * dimension); McxStatus ChannelDimensionSetup(ChannelDimension * dimension, size_t num); -McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t num, size_t start, size_t end); +McxStatus ChannelDimensionSetDimension(ChannelDimension * dimension, size_t dim, size_t start, size_t end); int ChannelDimensionEq(const ChannelDimension * first, const ChannelDimension * second); int ChannelDimensionConformsToDimension(const ChannelDimension * first, const ChannelDimension * second); From 63ffb63dd2feb8dff4ab403c689baf9a6edcad6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 7 Jul 2022 09:14:54 +0200 Subject: [PATCH 243/295] Remove obsolete code --- src/components/comp_fmu.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 982efe7..2024c88 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -381,11 +381,6 @@ static McxStatus Fmu2SetupChannelIn(ObjectContainer /* Fmu2Values */ * vals, Dat Fmu2Value * val = (Fmu2Value *) vals->At(vals, i); if (ch->IsConnected(ch) || ch->info.defaultValue) { - const char * channelName = info->nameInTool; - if (NULL == channelName) { - channelName = ChannelInfoGetName(info); - } - val->SetChannel(val, info->channel); if (!ChannelTypeIsValid(val->val.type)) { From b9cd4a41974550c9d46825045cbe2ce31035d4aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 7 Jul 2022 10:20:23 +0200 Subject: [PATCH 244/295] Avoid memory allocations due to C/C++ interface --- src/core/channels/ChannelValue.c | 28 ++++++++++++++++++++++++++++ src/core/channels/ChannelValue.h | 1 + 2 files changed, 29 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index c4a076f..9c21afd 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -117,6 +117,34 @@ ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dim return array; } +ChannelType * ChannelTypeArrayLongDims(ChannelType * inner, size_t numDims, unsigned long * dims) { + ChannelType * array = NULL; + size_t i = 0; + + if (!inner) { + return &ChannelTypeUnknown; + } + + array = (ChannelType *) mcx_malloc(sizeof(ChannelType)); + if (!array) { + return &ChannelTypeUnknown; + } + + array->con = CHANNEL_ARRAY; + array->ty.a.inner = inner; + array->ty.a.numDims = numDims; + array->ty.a.dims = (size_t *) mcx_calloc(sizeof(size_t), numDims); + if (!array->ty.a.dims) { + return &ChannelTypeUnknown; + } + + for (i = 0; i < numDims; i++) { + array->ty.a.dims[i] = dims[i]; + } + + return array; +} + ChannelType * ChannelTypeArrayInner(ChannelType * array) { if (!ChannelTypeIsArray(array)) { return &ChannelTypeUnknown; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 212aeb1..7c8ebdd 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -57,6 +57,7 @@ extern ChannelType ChannelTypeString; extern ChannelType ChannelTypeBinary; extern ChannelType ChannelTypeBinaryReference; ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims); +ChannelType * ChannelTypeArrayLongDims(ChannelType * inner, size_t numDims, unsigned long * dims); ChannelType * ChannelTypeClone(ChannelType * type); void ChannelTypeDestructor(ChannelType * type); From d6dc19ee317abfae08b83ecafeebdf0ede51e4e8 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Fri, 8 Jul 2022 16:44:50 +0200 Subject: [PATCH 245/295] storage: Make utility function accessible to all backends --- src/storage/ChannelStorage.c | 23 +++++++++++++++++++++++ src/storage/ChannelStorage.h | 3 +++ src/storage/StorageBackendCsv.c | 24 +----------------------- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index e1c0f24..b885b84 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -348,6 +348,29 @@ static ChannelStorage * ChannelStorageCreate(ChannelStorage * channelStore) { return channelStore; } +char ** ExpandedChannelNames(const char * name, size_t start, size_t end) { + char ** names = (char **) mcx_malloc(sizeof(char *) * (end - start + 1 + 1)); + if (!names) { return NULL; } + + size_t i = 0; + + for (i = start; i <= end; i++) { + names[i-start] = CreateIndexedName(name, i); + } + names[i-start] = NULL; + + return names; +} + +void FreeExpandedChannelNames(char ** names) { + size_t i = 0; + while (names[i]) { + mcx_free(names[i]); + ++i; + } + mcx_free(names); +} + OBJECT_CLASS(ChannelStorage, Object); #ifdef __cplusplus diff --git a/src/storage/ChannelStorage.h b/src/storage/ChannelStorage.h index 481700a..3ed9e08 100644 --- a/src/storage/ChannelStorage.h +++ b/src/storage/ChannelStorage.h @@ -61,6 +61,9 @@ typedef struct ChannelStorage { size_t storeCallNum; } ChannelStorage; +char ** ExpandedChannelNames(const char * name, size_t start, size_t end); +void FreeExpandedChannelNames(char ** names); + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ diff --git a/src/storage/StorageBackendCsv.c b/src/storage/StorageBackendCsv.c index 0a13c35..67e216b 100644 --- a/src/storage/StorageBackendCsv.c +++ b/src/storage/StorageBackendCsv.c @@ -16,6 +16,7 @@ #include "storage/StorageBackendCsv.h" #include "storage/StorageBackendText_impl.h" #include "storage/PPD.h" +#include "storage/ChannelStorage.h" #include "core/connections/ConnectionInfoFactory.h" #include "util/string.h" @@ -183,29 +184,6 @@ static char * QuoteString(const char * _str) { return newStr; } -static char * ExpandedChannelNames(const char * name, size_t start, size_t end) { - char ** names = (char **) mcx_malloc(sizeof(char *) * (end - start + 1 + 1)); - if (!names) { return NULL; } - - size_t i = 0; - - for (i = start; i <= end; i++) { - names[i-start] = CreateIndexedName(name, i); - } - names[i-start] = NULL; - - return names; -} - -static void FreeExpandedChannelNames(char ** names) { - size_t i = 0; - while (names[i]) { - mcx_free(names[i]); - ++i; - } - mcx_free(names); -} - static McxStatus SetupComponentFilesCsv(StorageBackend * backend) { StorageBackendText * textBackend = (StorageBackendText *) backend; ResultsStorage * storage = backend->storage; From 6cc43b214181572148e2957e175a26f783b8803f Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Fri, 15 Jul 2022 11:46:24 +0200 Subject: [PATCH 246/295] storage: Make function ANSI C compliant --- src/storage/ChannelStorage.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/storage/ChannelStorage.c b/src/storage/ChannelStorage.c index b885b84..65ca204 100644 --- a/src/storage/ChannelStorage.c +++ b/src/storage/ChannelStorage.c @@ -349,11 +349,14 @@ static ChannelStorage * ChannelStorageCreate(ChannelStorage * channelStore) { } char ** ExpandedChannelNames(const char * name, size_t start, size_t end) { - char ** names = (char **) mcx_malloc(sizeof(char *) * (end - start + 1 + 1)); - if (!names) { return NULL; } - + char ** names = NULL; size_t i = 0; + names = (char **) mcx_malloc(sizeof(char *) * (end - start + 1 + 1)); + if (!names) { + return NULL; + } + for (i = start; i <= end; i++) { names[i-start] = CreateIndexedName(name, i); } From d61a172c8b03e47f98d20d0a692b6a36b4f36939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Cau=C2=9Aevic?= Date: Fri, 29 Jul 2022 15:09:09 +0200 Subject: [PATCH 247/295] Move variables closer to the place where they are used --- src/core/channels/ChannelValue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 9c21afd..fb8988d 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -612,9 +612,6 @@ char * ChannelValueToString(ChannelValue * value) { } break; case CHANNEL_ARRAY:{ - size_t i = 0; - size_t n = 0; - size_t (*fmt)(char * buffer, void * value, size_t i); if (ChannelTypeEq(ChannelTypeArrayInner(value->type), &ChannelTypeDouble)) { @@ -635,6 +632,9 @@ char * ChannelValueToString(ChannelValue * value) { } if (mcx_array_num_elements(&value->value.a) > 0) { + size_t i = 0; + size_t n = 0; + n += fmt(buffer + n, value->value.a.data, 0); for (i = 1; i < mcx_array_num_elements(&value->value.a); i++) { n += sprintf(buffer + n, ","); From 0c1e5cc2f639b1088fd57b51bf05ec8adc65b0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 27 Jul 2022 13:00:47 +0200 Subject: [PATCH 248/295] Update element channels prior to exiting init mode in connections --- src/core/Model.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/core/Model.c b/src/core/Model.c index 58c5310..076da2a 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -1363,6 +1363,35 @@ static McxStatus CompUpdateInitOutputs(CompAndGroup * compGroup, void * param) { return retVal; } +static McxStatus CompUpdateInAndOutputs(CompAndGroup * compGroup, void * param) { + Component * comp = compGroup->comp; + double startTime = comp->GetTime(comp); + TimeInterval time = { startTime, startTime }; + McxStatus retVal = RETURN_OK; + + retVal = DatabusTriggerInConnections(comp->GetDatabus(comp), &time); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Updating inports after initialization loop failed"); + return RETURN_ERROR; + } + + if (comp->UpdateInChannels) { + retVal = comp->UpdateInChannels(comp); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Updating inports failed"); + return RETURN_ERROR; + } + } + + retVal = ComponentUpdateOutChannels(comp, &time); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Updating outports after initialization loop failed"); + return RETURN_ERROR; + } + + return retVal; +} + static McxStatus CompUpdateOutputs(CompAndGroup * compGroup, void * param) { Component * comp = compGroup->comp; const Task * task = (const Task *) param; @@ -1417,6 +1446,15 @@ static McxStatus ModelInitialize(Model * model) { return retVal; } + // Additional step for faulty elements which return zeroes as out channel values during initialization. + // This makes sure that after the element exits initialization (CompExitInit), + // the output channels contain good values before they get forwarded to the filters (ModelConnectionsExitInitMode) + retVal = subModel->LoopEvaluationList(subModel, CompUpdateInAndOutputs, (void*)model->task); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Updating element channels failed"); + return RETURN_ERROR; + } + retVal = ModelConnectionsExitInitMode(model->components, model->task->params->time); if (RETURN_ERROR == retVal) { mcx_log(LOG_ERROR, "Model: Exiting initialization mode failed"); From 95302f6783633a2041b96707d981dcd5e5f798f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 25 Jul 2022 15:54:27 +0200 Subject: [PATCH 249/295] Make additional init step configurable via an environment variable --- src/core/Config.c | 13 +++++++++++++ src/core/Config.h | 1 + src/core/Model.c | 16 +++++++++------- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/core/Config.c b/src/core/Config.c index 6842a0b..d94f3b5 100644 --- a/src/core/Config.c +++ b/src/core/Config.c @@ -416,6 +416,18 @@ static McxStatus ConfigSetupFromEnvironment(Config * config) { } } + { + char * wrongInitBehaviorDisabled = NULL; + + wrongInitBehaviorDisabled = mcx_os_get_env_var("MCX_WRONG_INIT_BEHAVIOR"); + if (wrongInitBehaviorDisabled) { + if (is_on(wrongInitBehaviorDisabled)) { + config->patchWrongInitBehavior = FALSE; + } + mcx_free(wrongInitBehaviorDisabled); + } + } + { char * numWarnings = mcx_os_get_env_var("NUM_TIME_SNAP_WARNINGS"); if (numWarnings) { @@ -571,6 +583,7 @@ static Config * ConfigCreate(Config * config) { config->writeAllLogFile = FALSE; config->cosimInitEnabled = FALSE; + config->patchWrongInitBehavior = TRUE; config->maxNumTimeSnapWarnings = MAX_NUM_MSGS; diff --git a/src/core/Config.h b/src/core/Config.h index 7cd97eb..6ae1643 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -72,6 +72,7 @@ struct Config { size_t memFilterHistoryExtra; int cosimInitEnabled; + int patchWrongInitBehavior; int profilingMode; diff --git a/src/core/Model.c b/src/core/Model.c index 076da2a..719ea46 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -1446,13 +1446,15 @@ static McxStatus ModelInitialize(Model * model) { return retVal; } - // Additional step for faulty elements which return zeroes as out channel values during initialization. - // This makes sure that after the element exits initialization (CompExitInit), - // the output channels contain good values before they get forwarded to the filters (ModelConnectionsExitInitMode) - retVal = subModel->LoopEvaluationList(subModel, CompUpdateInAndOutputs, (void*)model->task); - if (RETURN_ERROR == retVal) { - mcx_log(LOG_ERROR, "Model: Updating element channels failed"); - return RETURN_ERROR; + if (model->config->patchWrongInitBehavior) { + // Additional step for faulty elements which return zeroes as out channel values during initialization. + // This makes sure that after the element exits initialization (CompExitInit), + // the output channels contain good values before they get forwarded to the filters (ModelConnectionsExitInitMode) + retVal = subModel->LoopEvaluationList(subModel, CompUpdateInAndOutputs, (void*)model->task); + if (RETURN_ERROR == retVal) { + mcx_log(LOG_ERROR, "Model: Updating element channels failed"); + return RETURN_ERROR; + } } retVal = ModelConnectionsExitInitMode(model->components, model->task->params->time); From 2cb5d63102655335817988e50b9b466f99f9a09e Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 16 Aug 2022 11:44:29 +0200 Subject: [PATCH 250/295] ChannelValue: Return error when failing to allocate memory --- src/core/channels/ChannelValue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index fb8988d..dfcb9e6 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -955,6 +955,8 @@ McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * *(char **) reference = (char *) mcx_calloc(strlen(value->s) + 1, sizeof(char)); if (*(char **) reference) { strncpy(*(char **) reference, value->s, strlen(value->s) + 1); + } else { + return RETURN_ERROR; } } break; From 1cdbcf44dee5164ad419443efa66c098313b095e Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Sat, 4 Sep 2021 13:01:00 +0200 Subject: [PATCH 251/295] Task: Change default of sumTime to TRUE --- src/core/Task.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/Task.c b/src/core/Task.c index 4882a82..85aba87 100644 --- a/src/core/Task.c +++ b/src/core/Task.c @@ -233,12 +233,14 @@ static McxStatus TaskRead(Task * task, TaskInput * taskInput) { task->params->timeStepSize = taskInput->deltaTime.defined ? taskInput->deltaTime.value : 0.01; mcx_log(LOG_INFO, " Synchronization time step: %g s", task->params->timeStepSize); - task->params->sumTime = taskInput->sumTime.defined ? taskInput->sumTime.value : FALSE; + task->params->sumTime = taskInput->sumTime.defined ? taskInput->sumTime.value : TRUE; if (task->config && task->config->sumTimeDefined) { task->params->sumTime = task->config->sumTime; } if (task->params->sumTime) { mcx_log(LOG_DEBUG, " Using summation for time calculation"); + } else { + mcx_log(LOG_DEBUG, " Using multiplication for time calculation"); } task->stepTypeType = taskInput->stepType; From fe56fa43b51ea502af3db1157504dfd51658b232 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Fri, 13 May 2022 11:12:08 +0200 Subject: [PATCH 252/295] task/results: Store RTFactor in Task->Initialize Previously, only local results were written in Initialize. This resulted in no timing data being written at startTime (i.e. the RTFactor results started at startTime + deltaTime). --- src/core/Task.c | 1 + src/storage/ResultsStorage.c | 20 ++++++++++++++++++++ src/storage/ResultsStorage.h | 1 + 3 files changed, 22 insertions(+) diff --git a/src/core/Task.c b/src/core/Task.c index 85aba87..fa63a9f 100644 --- a/src/core/Task.c +++ b/src/core/Task.c @@ -135,6 +135,7 @@ static McxStatus TaskInitialize(Task * task, Model * model) { task->storage->StoreModelOut(task->storage, model->subModel, stepParams->time, STORE_SYNCHRONIZATION); task->storage->StoreModelLocal(task->storage, model->subModel, stepParams->time, STORE_SYNCHRONIZATION); + task->storage->StoreModelRTFactor(task->storage, model->subModel, stepParams->time, STORE_SYNCHRONIZATION); task->stepType->Configure(task->stepType, stepParams, subModel); diff --git a/src/storage/ResultsStorage.c b/src/storage/ResultsStorage.c index 2b9858e..2af07bd 100644 --- a/src/storage/ResultsStorage.c +++ b/src/storage/ResultsStorage.c @@ -161,6 +161,25 @@ static McxStatus StorageStoreModelLocal(ResultsStorage * storage, SubModel * sub return RETURN_OK; } +static McxStatus StorageStoreModelRTFactor(ResultsStorage * storage, SubModel * subModel, double time, StoreLevel level) { + size_t i = 0; + + McxStatus retVal = RETURN_OK; + + // Get values from Components + for (i = 0; i < storage->numComponents; i++) { + ComponentStorage * compStore = storage->componentStorage[i]; + if (subModel->IsElement(subModel, compStore->comp)) { + retVal = compStore->StoreChannels(compStore, CHANNEL_STORE_RTFACTOR, time, level); + if (RETURN_OK != retVal) { + return RETURN_ERROR; + } + } + } + + return RETURN_OK; +} + static McxStatus StorageFinishModel(ResultsStorage * storage, SubModel * subModel) { size_t i = 0; @@ -525,6 +544,7 @@ static ResultsStorage * ResultsStorageCreate(ResultsStorage * storage) { storage->StoreModel = StorageStoreModel; storage->StoreModelOut = StorageStoreModelOut; storage->StoreModelLocal = StorageStoreModelLocal; + storage->StoreModelRTFactor = StorageStoreModelRTFactor; storage->FinishModel = StorageFinishModel; storage->Finished = StorageFinished; diff --git a/src/storage/ResultsStorage.h b/src/storage/ResultsStorage.h index 47ff582..4665128 100644 --- a/src/storage/ResultsStorage.h +++ b/src/storage/ResultsStorage.h @@ -93,6 +93,7 @@ struct ResultsStorage { fResultsStorageStoreModel StoreModel; fResultsStorageStoreModel StoreModelOut; fResultsStorageStoreModel StoreModelLocal; + fResultsStorageStoreModel StoreModelRTFactor; fResultsStorageFinishModel FinishModel; fResultsStorageRegisterComponent RegisterComponent; From c754c71ec4968237885881e6568327452585c3f7 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 4 Oct 2022 17:04:37 +0200 Subject: [PATCH 253/295] util: Convert relative Dll paths to absolute ones --- libs/util/src/win/libs.c | 57 ++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/libs/util/src/win/libs.c b/libs/util/src/win/libs.c index 9f0d20b..cdc1624 100644 --- a/libs/util/src/win/libs.c +++ b/libs/util/src/win/libs.c @@ -10,6 +10,7 @@ #define _WINSOCKAPI_ // stops windows.h including winsock.h #include +#include #include "common/logging.h" #include "common/memory.h" @@ -23,24 +24,12 @@ extern "C" { #endif /* __cplusplus */ -McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { - DllHandleCheck compValue; - - wchar_t * wDllPath = mcx_string_to_widechar(dllPath); - - * handle = LoadLibraryExW(wDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - mcx_free(wDllPath); - - compValue = (DllHandleCheck) * handle; - if (compValue <= HINSTANCE_ERROR) { - LPVOID lpMsgBuf; - DWORD err = GetLastError(); - - mcx_log(LOG_ERROR, "Util: Dll (%s) could not be loaded", dllPath); - - switch (err) { +static void print_last_error() { + LPVOID lpMsgBuf; + DWORD err = GetLastError(); + switch (err) { case ERROR_BAD_EXE_FORMAT: - mcx_log(LOG_ERROR, "Util: There is a mismatch in bitness (32/64) between current Model.CONNECT Execution Engine and the dynamic library", dllPath); + mcx_log(LOG_ERROR, "Util: There is a mismatch in bitness (32/64) between current Model.CONNECT Execution Engine and the dynamic library"); break; default: FormatMessage( @@ -56,7 +45,41 @@ McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { mcx_log(LOG_ERROR, "Util: Error %d: %s", err, lpMsgBuf); LocalFree(lpMsgBuf); break; + } +} + + +McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { + DllHandleCheck compValue; + + wchar_t * wDllPath = mcx_string_to_widechar(dllPath); + + if (PathIsRelativeW(wDllPath)) { + wchar_t * wFullDllPath = NULL; + DWORD length = GetFullPathNameW(wDllPath, 0, NULL, NULL); + if (length == 0) { + mcx_log(LOG_ERROR, "Util: Error retrieving length of absolute path of Dll (%s)", wDllPath); + print_last_error(); + return RETURN_ERROR; } + wFullDllPath = (wchar_t *) mcx_malloc(sizeof(wchar_t) * length); + length = GetFullPathNameW(wDllPath, length, wFullDllPath, NULL); + if (length == 0) { + mcx_log(LOG_ERROR, "Util: Error creating full path for Dll (%s)", wDllPath); + print_last_error(); + return RETURN_ERROR; + } + mcx_free(wDllPath); + wDllPath = wFullDllPath; + } + + * handle = LoadLibraryExW(wDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + mcx_free(wDllPath); + + compValue = (DllHandleCheck) * handle; + if (compValue <= HINSTANCE_ERROR) { + mcx_log(LOG_ERROR, "Util: Dll (%s) could not be loaded", dllPath); + print_last_error(); return RETURN_ERROR; } From 75c167a091c78e85862fcedec08c697f0f5d7a96 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Thu, 13 Oct 2022 12:12:10 +0200 Subject: [PATCH 254/295] util: Use goto cleanup strategy for handling errors --- libs/util/src/win/libs.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/libs/util/src/win/libs.c b/libs/util/src/win/libs.c index cdc1624..112ef25 100644 --- a/libs/util/src/win/libs.c +++ b/libs/util/src/win/libs.c @@ -54,36 +54,51 @@ McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { wchar_t * wDllPath = mcx_string_to_widechar(dllPath); + McxStatus retVal = RETURN_OK; + if (PathIsRelativeW(wDllPath)) { wchar_t * wFullDllPath = NULL; DWORD length = GetFullPathNameW(wDllPath, 0, NULL, NULL); if (length == 0) { mcx_log(LOG_ERROR, "Util: Error retrieving length of absolute path of Dll (%s)", wDllPath); print_last_error(); - return RETURN_ERROR; + retVal = RETURN_ERROR; + goto relpath_cleanup; } wFullDllPath = (wchar_t *) mcx_malloc(sizeof(wchar_t) * length); length = GetFullPathNameW(wDllPath, length, wFullDllPath, NULL); if (length == 0) { mcx_log(LOG_ERROR, "Util: Error creating full path for Dll (%s)", wDllPath); print_last_error(); - return RETURN_ERROR; + retVal = RETURN_ERROR; + goto relpath_cleanup; + } +relpath_cleanup: + if (wDllPath) { + mcx_free(wDllPath); + } + if (retVal != RETURN_OK) { + goto cleanup; } - mcx_free(wDllPath); wDllPath = wFullDllPath; } * handle = LoadLibraryExW(wDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); - mcx_free(wDllPath); compValue = (DllHandleCheck) * handle; if (compValue <= HINSTANCE_ERROR) { mcx_log(LOG_ERROR, "Util: Dll (%s) could not be loaded", dllPath); print_last_error(); - return RETURN_ERROR; + retVal = RETURN_ERROR; + goto cleanup; + } + +cleanup: + if (wDllPath) { + mcx_free(wDllPath); } - return RETURN_OK; + return retVal; } From c91257f57430f40155fe19400a20bb384b9d03a2 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Mon, 10 Oct 2022 10:57:12 +0200 Subject: [PATCH 255/295] util: Log (Debug) absolute path of Dll --- libs/util/src/win/libs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/util/src/win/libs.c b/libs/util/src/win/libs.c index 112ef25..7f6bc34 100644 --- a/libs/util/src/win/libs.c +++ b/libs/util/src/win/libs.c @@ -60,7 +60,7 @@ McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { wchar_t * wFullDllPath = NULL; DWORD length = GetFullPathNameW(wDllPath, 0, NULL, NULL); if (length == 0) { - mcx_log(LOG_ERROR, "Util: Error retrieving length of absolute path of Dll (%s)", wDllPath); + mcx_log(LOG_ERROR, "Util: Error retrieving length of absolute path of Dll (%s)", dllPath); print_last_error(); retVal = RETURN_ERROR; goto relpath_cleanup; @@ -68,7 +68,7 @@ McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { wFullDllPath = (wchar_t *) mcx_malloc(sizeof(wchar_t) * length); length = GetFullPathNameW(wDllPath, length, wFullDllPath, NULL); if (length == 0) { - mcx_log(LOG_ERROR, "Util: Error creating full path for Dll (%s)", wDllPath); + mcx_log(LOG_ERROR, "Util: Error creating absolute path for Dll (%s)", dllPath); print_last_error(); retVal = RETURN_ERROR; goto relpath_cleanup; @@ -83,6 +83,8 @@ McxStatus mcx_dll_load(DllHandle * handle, const char * dllPath) { wDllPath = wFullDllPath; } + mcx_log(LOG_DEBUG, "Util: Loading Dll %S", wDllPath); + * handle = LoadLibraryExW(wDllPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); compValue = (DllHandleCheck) * handle; From cd6d38f6649f79a797efd9c98549d6641c28342a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 10 Oct 2022 10:32:11 +0200 Subject: [PATCH 256/295] Calculate first larger sync time multiple differently depending on SUM_TIME --- src/steptypes/StepTypeParallelMT.c | 1 + src/steptypes/StepTypeParallelMT.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/steptypes/StepTypeParallelMT.c b/src/steptypes/StepTypeParallelMT.c index 23e5bdd..28050f8 100644 --- a/src/steptypes/StepTypeParallelMT.c +++ b/src/steptypes/StepTypeParallelMT.c @@ -103,6 +103,7 @@ static DoStepThreadArg * DoStepThreadArgCreate(DoStepThreadArg * arg) { arg->SetCounter = DoStepThreadArgSetCounter; arg->StartThread = DoStepThreadArgStartThread; + arg->reachedSyncTime = 0.0; arg->comp = NULL; arg->group = 0; arg->params = NULL; diff --git a/src/steptypes/StepTypeParallelMT.h b/src/steptypes/StepTypeParallelMT.h index deb3906..625f834 100644 --- a/src/steptypes/StepTypeParallelMT.h +++ b/src/steptypes/StepTypeParallelMT.h @@ -71,6 +71,9 @@ typedef struct DoStepThreadArg { // last status value McxStatus status; + // last reached synchronization point + double reachedSyncTime; + // flag if thread should stop int finished; From 3afd503904bce31a2b261740e20deadc0c39c48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 17 Oct 2022 13:31:18 +0200 Subject: [PATCH 257/295] util: Expose function for absolute epsilon comparison --- src/util/common/compare.c | 19 +++++++++++++++++++ src/util/compare.h | 8 ++++++++ 2 files changed, 27 insertions(+) diff --git a/src/util/common/compare.c b/src/util/common/compare.c index ebc5a50..c0a7ff5 100644 --- a/src/util/common/compare.c +++ b/src/util/common/compare.c @@ -60,6 +60,12 @@ int double_almost_equal(double a, double b, double eps) { } } +static int double_almost_equal_abs(double a, double b, double eps) { + double diff = (a - b); + diff = (diff < 0) ? -diff : diff; + return diff < eps; +} + cmp double_cmp_eps(double a, double b, double eps) { if (double_almost_equal(a, b, eps)) { return CMP_EQ; @@ -73,6 +79,19 @@ cmp double_cmp_eps(double a, double b, double eps) { } } +cmp double_cmp_eps_abs(double a, double b, double eps) { + if (double_almost_equal_abs(a, b, eps)) { + return CMP_EQ; + } else if (a < b) { + return CMP_LT; + } else if (a > b) { + return CMP_GT; + } else { + // error + return CMP_IN; + } +} + int double_eq(double a, double b) { return (double_cmp(a,b) == CMP_EQ); } diff --git a/src/util/compare.h b/src/util/compare.h index 1a81b67..5d6bb3c 100644 --- a/src/util/compare.h +++ b/src/util/compare.h @@ -46,6 +46,14 @@ cmp double_cmp(double a, double b); */ cmp double_cmp_eps(double a, double b, double eps); +/** + * Returns CMP_LT, CMP_EQ or CMP_GT if a < b, a == b, a > b within eps + * and CMP_IN if a and b are not comparable. + * + * The comparison is done in an absolute manner. + */ +cmp double_cmp_eps_abs(double a, double b, double eps); + /** * Returns if a == b within an epsilon */ From 59f20cc5243d636cb9c01b21593a9d1ed0c45b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 17 Oct 2022 14:21:44 +0200 Subject: [PATCH 258/295] Use absolute epsilon comparison to determine synchronization slots When the step sizes are multiples of one another (sync and coupling), it is possible to use a bigger epsilon (half of the smaller step size) in order to push back the moment when components might fall out of sync due to floating point operation errors. --- src/steptypes/StepType.c | 33 ++++++++++++++++++++++++++++++ src/steptypes/StepType.h | 12 +++++++++++ src/steptypes/StepTypeParallelMT.c | 5 +++++ src/steptypes/StepTypeParallelMT.h | 2 ++ 4 files changed, 52 insertions(+) diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index d675c97..fb7b7d0 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -26,6 +26,39 @@ extern "C" { // ---------------------------------------------------------------------- // Step Type: Common +void StepTypeSynchronizationSetup(StepTypeSynchronization * stepTypes, Component * comp, double syncStepSize) { + double syncToCoupl = 0.0; + double couplToSync = 0.0; + + if (!comp->HasOwnTime(comp)) { + return; + } + + if (comp->GetTimeStep(comp) <= 0.0) { + return; + } + + // If the coupling and synchronization step sizes are multiples of one another + // it is enough to use half the size of the smaller step for absolute time comparisons. + syncToCoupl = syncStepSize / comp->GetTimeStep(comp); + couplToSync = comp->GetTimeStep(comp) / syncStepSize; + + if (double_eq(syncToCoupl, round(syncToCoupl))) { + stepTypes->stepSizesAreMultiples = TRUE; + stepTypes->eps = comp->GetTimeStep(comp) / 2.0; + } + + if (double_eq(couplToSync, round(couplToSync))) { + stepTypes->stepSizesAreMultiples = TRUE; + stepTypes->eps = syncStepSize / 2.0; + } +} + +void StepTypeSynchronizationInit(StepTypeSynchronization * stepTypes) { + stepTypes->stepSizesAreMultiples = FALSE; + stepTypes->eps = -1.0; +} + McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeParams * params) { McxStatus retVal = RETURN_OK; double time = params->time; diff --git a/src/steptypes/StepType.h b/src/steptypes/StepType.h index b5eac5d..b0676d0 100644 --- a/src/steptypes/StepType.h +++ b/src/steptypes/StepType.h @@ -24,6 +24,18 @@ typedef struct SubModel SubModel; typedef struct CompAndGroup CompAndGroup; +typedef struct StepTypeSynchronization { + // flag whether the coupling and synchronization step size are multiples of one another + int stepSizesAreMultiples; + + // epsilon used for time comparisons + double eps; +} StepTypeSynchronization; + +void StepTypeSynchronizationSetup(StepTypeSynchronization * stepTypes, Component * comp, double syncStepSize); +void StepTypeSynchronizationInit(StepTypeSynchronization * stepTypes); + + typedef enum StepTypeType { STEP_TYPE_UNDEFINED = -1, /* "parallel_singlethreaded" */ STEP_TYPE_SEQUENTIAL = 1, /* "sequential" */ diff --git a/src/steptypes/StepTypeParallelMT.c b/src/steptypes/StepTypeParallelMT.c index 28050f8..0eec47a 100644 --- a/src/steptypes/StepTypeParallelMT.c +++ b/src/steptypes/StepTypeParallelMT.c @@ -79,6 +79,8 @@ static void DoStepThreadArgSetup(DoStepThreadArg * arg, Component * comp, size_t arg->comp = comp; arg->group = group; arg->params = params; + + StepTypeSynchronizationSetup(&arg->stepSizes, comp, params->timeStepSize); } static void DoStepThreadArgSetCounter(DoStepThreadArg * arg, DoStepThreadCounter * counter) { @@ -109,6 +111,9 @@ static DoStepThreadArg * DoStepThreadArgCreate(DoStepThreadArg * arg) { arg->params = NULL; arg->status = RETURN_OK; arg->finished = FALSE; + + StepTypeSynchronizationInit(&arg->stepSizes); + status = mcx_event_create(&arg->startDoStepEvent); if (status) { mcx_log(LOG_ERROR, "Simulation: Failed to create DoStep start event"); diff --git a/src/steptypes/StepTypeParallelMT.h b/src/steptypes/StepTypeParallelMT.h index 625f834..362c3a3 100644 --- a/src/steptypes/StepTypeParallelMT.h +++ b/src/steptypes/StepTypeParallelMT.h @@ -74,6 +74,8 @@ typedef struct DoStepThreadArg { // last reached synchronization point double reachedSyncTime; + StepTypeSynchronization stepSizes; + // flag if thread should stop int finished; From 54456a69b71673131c1ad5852c2bc11a4824c0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 17 Oct 2022 14:46:09 +0200 Subject: [PATCH 259/295] Use same way of checking for sync slots both in component and step type --- src/core/Component.c | 2 ++ src/core/Component.h | 4 ++++ src/steptypes/StepType.c | 9 ++++++++- src/steptypes/StepTypeParallelMT.c | 7 ++++--- src/steptypes/StepTypeParallelMT.h | 2 -- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 876f99f..1cc9969 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -1292,6 +1292,8 @@ static Component * ComponentCreate(Component * comp) { comp->data->typeString = NULL; + comp->syncHintsConfigured = FALSE; + StepTypeSynchronizationInit(&comp->syncHints); comp->GetNumObservableChannels = ComponentGetNumObservableChannels; comp->AddObservableChannels = AddObservableChannels; diff --git a/src/core/Component.h b/src/core/Component.h index 3e1493a..d21d181 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -19,6 +19,7 @@ #include "objects/Vector.h" #include "reader/model/components/ComponentInput.h" #include "core/connections/ConnectionInfo.h" +#include "steptypes/StepType.h" #ifdef __cplusplus extern "C" { @@ -228,6 +229,9 @@ struct Component { fOnConnectionsDone OnConnectionsDone; struct ComponentData * data; + + int syncHintsConfigured; + StepTypeSynchronization syncHints; }; /* these functions have to be called by subclasses */ diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index fb7b7d0..79bad88 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -80,9 +80,16 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP level = STORE_SYNCHRONIZATION; + if (!comp->syncHintsConfigured) { + StepTypeSynchronizationSetup(&comp->syncHints, comp, params->timeStepSize); + comp->syncHintsConfigured = TRUE; + } + while ( comp->GetFinishState(comp) != COMP_IS_FINISHED && - double_lt(comp->GetTime(comp), stepEndTime) + comp->syncHints.stepSizesAreMultiples ? + double_cmp_eps_abs(comp->GetTime(comp), stepEndTime, comp->syncHints.eps) == CMP_LT : + double_lt(comp->GetTime(comp), stepEndTime) ) { if (comp->HasOwnTime(comp)) { interval.startTime = comp->GetTime(comp); diff --git a/src/steptypes/StepTypeParallelMT.c b/src/steptypes/StepTypeParallelMT.c index 0eec47a..f89fe3f 100644 --- a/src/steptypes/StepTypeParallelMT.c +++ b/src/steptypes/StepTypeParallelMT.c @@ -80,7 +80,10 @@ static void DoStepThreadArgSetup(DoStepThreadArg * arg, Component * comp, size_t arg->group = group; arg->params = params; - StepTypeSynchronizationSetup(&arg->stepSizes, comp, params->timeStepSize); + if (!comp->syncHintsConfigured) { + StepTypeSynchronizationSetup(&comp->syncHints, comp, params->timeStepSize); + comp->syncHintsConfigured = TRUE; + } } static void DoStepThreadArgSetCounter(DoStepThreadArg * arg, DoStepThreadCounter * counter) { @@ -112,8 +115,6 @@ static DoStepThreadArg * DoStepThreadArgCreate(DoStepThreadArg * arg) { arg->status = RETURN_OK; arg->finished = FALSE; - StepTypeSynchronizationInit(&arg->stepSizes); - status = mcx_event_create(&arg->startDoStepEvent); if (status) { mcx_log(LOG_ERROR, "Simulation: Failed to create DoStep start event"); diff --git a/src/steptypes/StepTypeParallelMT.h b/src/steptypes/StepTypeParallelMT.h index 362c3a3..625f834 100644 --- a/src/steptypes/StepTypeParallelMT.h +++ b/src/steptypes/StepTypeParallelMT.h @@ -74,8 +74,6 @@ typedef struct DoStepThreadArg { // last reached synchronization point double reachedSyncTime; - StepTypeSynchronization stepSizes; - // flag if thread should stop int finished; From c05f57525758e9d19efb34dc37b71ea4d1172b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 19 Oct 2022 09:18:22 +0200 Subject: [PATCH 260/295] Remove obsolete code --- src/core/Component.c | 1 - src/core/Component.h | 1 - src/steptypes/StepType.c | 5 ----- src/steptypes/StepTypeParallelMT.c | 5 +---- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 1cc9969..b8070aa 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -1292,7 +1292,6 @@ static Component * ComponentCreate(Component * comp) { comp->data->typeString = NULL; - comp->syncHintsConfigured = FALSE; StepTypeSynchronizationInit(&comp->syncHints); comp->GetNumObservableChannels = ComponentGetNumObservableChannels; diff --git a/src/core/Component.h b/src/core/Component.h index d21d181..4893dae 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -230,7 +230,6 @@ struct Component { struct ComponentData * data; - int syncHintsConfigured; StepTypeSynchronization syncHints; }; diff --git a/src/steptypes/StepType.c b/src/steptypes/StepType.c index 79bad88..0a1a39d 100644 --- a/src/steptypes/StepType.c +++ b/src/steptypes/StepType.c @@ -80,11 +80,6 @@ McxStatus ComponentDoCommunicationStep(Component * comp, size_t group, StepTypeP level = STORE_SYNCHRONIZATION; - if (!comp->syncHintsConfigured) { - StepTypeSynchronizationSetup(&comp->syncHints, comp, params->timeStepSize); - comp->syncHintsConfigured = TRUE; - } - while ( comp->GetFinishState(comp) != COMP_IS_FINISHED && comp->syncHints.stepSizesAreMultiples ? diff --git a/src/steptypes/StepTypeParallelMT.c b/src/steptypes/StepTypeParallelMT.c index f89fe3f..ee43557 100644 --- a/src/steptypes/StepTypeParallelMT.c +++ b/src/steptypes/StepTypeParallelMT.c @@ -80,10 +80,7 @@ static void DoStepThreadArgSetup(DoStepThreadArg * arg, Component * comp, size_t arg->group = group; arg->params = params; - if (!comp->syncHintsConfigured) { - StepTypeSynchronizationSetup(&comp->syncHints, comp, params->timeStepSize); - comp->syncHintsConfigured = TRUE; - } + StepTypeSynchronizationSetup(&comp->syncHints, comp, params->timeStepSize); } static void DoStepThreadArgSetCounter(DoStepThreadArg * arg, DoStepThreadCounter * counter) { From 0b8f30ce53cc0a80728b15e271e0cdaa8261ed40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 20 Oct 2022 11:33:44 +0200 Subject: [PATCH 261/295] Define a leq comparison function using absolute epsilon comparison --- src/util/common/compare.c | 4 ++++ src/util/compare.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/util/common/compare.c b/src/util/common/compare.c index c0a7ff5..ea21285 100644 --- a/src/util/common/compare.c +++ b/src/util/common/compare.c @@ -114,6 +114,10 @@ int double_geq(double a, double b) { || double_cmp(a,b) == CMP_GT); } +int double_leq_eps_abs(double a, double b, double eps) { + return (double_cmp_eps_abs(a, b, eps) == CMP_EQ || double_cmp_eps_abs(a, b, eps) == CMP_LT); +} + #ifdef __cplusplus } /* closing brace for extern "C" */ #endif /* __cplusplus */ \ No newline at end of file diff --git a/src/util/compare.h b/src/util/compare.h index 5d6bb3c..ae3e084 100644 --- a/src/util/compare.h +++ b/src/util/compare.h @@ -79,6 +79,11 @@ int double_leq(double a, double b); */ int double_geq(double a, double b); +/** + * Returns if a <= b modulo eps + */ +int double_leq_eps_abs(double a, double b, double eps); + #ifdef __cplusplus } /* closing brace for extern "C" */ From c9bd0beae9336d6942a53904d0979fc5dff11ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 5 Sep 2022 15:48:55 +0200 Subject: [PATCH 262/295] Add const qualifiers --- src/core/channels/ChannelValue.c | 8 ++++---- src/core/channels/ChannelValue.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index dfcb9e6..be7d644 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -169,7 +169,7 @@ int ChannelTypeIsBinary(const ChannelType * a) { return a->con == CHANNEL_BINARY || a->con == CHANNEL_BINARY_REFERENCE; } -ChannelType * ChannelTypeBaseType(ChannelType * a) { +ChannelType * ChannelTypeBaseType(const ChannelType * a) { if (ChannelTypeIsArray(a)) { return ChannelTypeBaseType(a->ty.a.inner); } else { @@ -212,7 +212,7 @@ int ChannelTypeConformable(ChannelType * a, ChannelDimension * sliceA, ChannelTy } } -int ChannelTypeEq(ChannelType * a, ChannelType * b) { +int ChannelTypeEq(const ChannelType * a, const ChannelType * b) { if (a->con == CHANNEL_ARRAY && b->con == CHANNEL_ARRAY) { size_t i = 0; if (a->ty.a.numDims != b->ty.a.numDims) { @@ -320,7 +320,7 @@ int mcx_array_dims_match(mcx_array * a, mcx_array * b) { return 1; } -size_t mcx_array_num_elements(mcx_array * a) { +size_t mcx_array_num_elements(const mcx_array * a) { size_t i = 0; size_t n = 1; @@ -348,7 +348,7 @@ McxStatus mcx_array_map(mcx_array * a, mcx_array_map_f_ptr fn, void * ctx) { return RETURN_OK; } -McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element) { +McxStatus mcx_array_get_elem(const mcx_array * a, size_t idx, ChannelValueData * element) { size_t num_elems = mcx_array_num_elements(a); if (idx >= num_elems) { diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 7c8ebdd..6e9bf30 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -73,9 +73,9 @@ size_t ChannelTypeNumElements(const ChannelType * type); ChannelType * ChannelTypeFromDimension(ChannelType * base_type, ChannelDimension * dimension); -ChannelType * ChannelTypeBaseType(ChannelType * a); +ChannelType * ChannelTypeBaseType(const ChannelType * a); -int ChannelTypeEq(ChannelType * a, ChannelType * b); +int ChannelTypeEq(const ChannelType * a, const ChannelType * b); int ChannelTypeConformable(ChannelType * a, ChannelDimension * sliceA, ChannelType * b, ChannelDimension * sliceB); typedef struct MapStringChannelType { @@ -112,12 +112,12 @@ typedef struct { McxStatus mcx_array_init(mcx_array * a, size_t numDims, size_t * dims, ChannelType * type); void mcx_array_destroy(mcx_array * a); int mcx_array_dims_match(mcx_array * a, mcx_array * b); -size_t mcx_array_num_elements(mcx_array * a); +size_t mcx_array_num_elements(const mcx_array * a); typedef int (*mcx_array_map_f_ptr)(void * element, size_t idx, ChannelType * type, void * ctx); McxStatus mcx_array_map(mcx_array * a, mcx_array_map_f_ptr fn, void * ctx); -McxStatus mcx_array_get_elem(mcx_array * a, size_t idx, ChannelValueData * element); +McxStatus mcx_array_get_elem(const mcx_array * a, size_t idx, ChannelValueData * element); McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element); void * mcx_array_get_elem_reference(mcx_array * a, size_t idx); From b002c77290395e777feb19f011bf20d2b96bc9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 16 Sep 2022 14:24:11 +0200 Subject: [PATCH 263/295] Add const qualifier --- src/core/channels/ChannelValue.c | 2 +- src/core/channels/ChannelValue.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index be7d644..82856b8 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -448,7 +448,7 @@ McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * eleme return RETURN_OK; } -void * mcx_array_get_elem_reference(mcx_array * a, size_t idx) { +void * mcx_array_get_elem_reference(const mcx_array * a, size_t idx) { size_t num_elems = mcx_array_num_elements(a); char * data = (char *) a->data; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 6e9bf30..a2936bd 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -120,7 +120,7 @@ McxStatus mcx_array_map(mcx_array * a, mcx_array_map_f_ptr fn, void * ctx); McxStatus mcx_array_get_elem(const mcx_array * a, size_t idx, ChannelValueData * element); McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * element); -void * mcx_array_get_elem_reference(mcx_array * a, size_t idx); +void * mcx_array_get_elem_reference(const mcx_array * a, size_t idx); typedef int (*mcx_array_predicate_f_ptr)(void * element, ChannelType * type); int mcx_array_all(mcx_array * a, mcx_array_predicate_f_ptr predicate); From 29458bfb174a641f393cd3b590d3a4ce204b5d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 26 Sep 2022 15:16:53 +0200 Subject: [PATCH 264/295] FMU2: Correctly use dimensions of naming convention arrays - do not flip dimensions from the asix file (dim0-major) --- src/fmu/common_fmu2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 3a07319..d83ff59 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -361,8 +361,8 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, end2 = input->dims[1]->end; } - for (k = start2; k <= end2; k++) { - for (j = start1; j <= end1; j++, index++) { + for (k = start1; k <= end1; k++) { + for (j = start2; j <= end2; j++, index++) { Fmu2Value * val = NULL; char * varName = (char *) mcx_calloc(stringBufferLength, sizeof(char)); fmi2_import_variable_t * var = NULL; @@ -376,7 +376,7 @@ static ObjectContainer* Fmu2ReadArrayParamValues(const char * name, if (input->numDims == 2) { snprintf(varName, stringBufferLength, "%s[%zu,%zu]", name, k, j); } else { - snprintf(varName, stringBufferLength, "%s[%zu]", name, j); + snprintf(varName, stringBufferLength, "%s[%zu]", name, k); } var = fmi2_import_get_variable_by_name(import, varName); From 53cddb39f859400ae7714db1d4bcd02dd0b2a7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Thu, 27 Oct 2022 13:53:55 +0200 Subject: [PATCH 265/295] Correctly check if cloning was successful --- src/core/connections/Connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/connections/Connection.c b/src/core/connections/Connection.c index ac28c78..01bc80a 100644 --- a/src/core/connections/Connection.c +++ b/src/core/connections/Connection.c @@ -1177,7 +1177,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { ChannelDimension * srcDim = NULL; srcDim = CloneChannelDimension(info->targetDimension); - if (srcDim) { + if (info->targetDimension && !srcDim) { mcx_log(LOG_ERROR, "Could not clone source dimension"); retVal = RETURN_ERROR; goto cleanup_1; @@ -1219,7 +1219,7 @@ static McxStatus ConnectionUpdateInitialValue(Connection * connection) { } } else if (outInfo->initialValue) { ChannelDimension * targetDim = CloneChannelDimension(info->sourceDimension); - if (targetDim) { + if (info->sourceDimension && !targetDim) { mcx_log(LOG_ERROR, "Could not clone target dimension"); retVal = RETURN_ERROR; goto cleanup; From 1251484bd023798f272a1fccb14a95135e5e41e0 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Fri, 15 Jul 2022 12:22:44 +0200 Subject: [PATCH 266/295] fmu: Remove check for valid dimension_1/2 --- src/fmu/common_fmu1.c | 10 ---------- src/fmu/common_fmu2.c | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/src/fmu/common_fmu1.c b/src/fmu/common_fmu1.c index 64c2896..949e66d 100644 --- a/src/fmu/common_fmu1.c +++ b/src/fmu/common_fmu1.c @@ -473,16 +473,6 @@ ObjectContainer * Fmu1ReadParams(ParametersInput * input, fmi1_import_t * import } if (parameterInput->type == PARAMETER_ARRAY) { - // read parameter dimensions (if any) - should only be defined for array parameters - if (parameterInput->parameter.arrayParameter->numDims >= 2 && - parameterInput->parameter.arrayParameter->dims[1] && - !parameterInput->parameter.arrayParameter->dims[0]) { - mcx_log(LOG_ERROR, "FMU: Array parameter %s: Missing definition for the first dimension " - "while the second dimension is defined.", parameterInput->parameter.arrayParameter->name); - ret = NULL; - goto cleanup; - } - // array - split it into scalars vals = Fmu1ReadArrayParamValues(name, parameterInput->parameter.arrayParameter, import, params); if (vals == NULL) { diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index d83ff59..cb8fd8c 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -503,16 +503,6 @@ McxStatus Fmu2ReadParams(ObjectContainer * params, ObjectContainer * arrayParams ArrayParameterProxy * proxy = NULL; size_t j = 0; - // read parameter dimensions (if any) - should only be defined for array parameters - if (parameterInput->parameter.arrayParameter->numDims >=2 && - parameterInput->parameter.arrayParameter->dims[1] && - !parameterInput->parameter.arrayParameter->dims[0]) { - mcx_log(LOG_ERROR, "FMU: Array parameter %s: Missing definition for the first dimension " - "while the second dimension is defined.", parameterInput->parameter.arrayParameter->name); - retVal = RETURN_ERROR; - goto cleanup_1; - } - // array - split it into scalars vals = Fmu2ReadArrayParamValues(name, parameterInput->parameter.arrayParameter, import, params); if (vals == NULL) { From 79a57c0521c29f79296280edc50b707ea81d1c2b Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 5 Mar 2025 18:42:47 +0100 Subject: [PATCH 267/295] Use %zu for size_t --- src/components/comp_vector_integrator.c | 2 +- src/core/Databus.c | 8 ++++---- src/core/Model.c | 22 +++++++++++----------- src/core/SubModel.c | 4 ++-- src/core/channels/ChannelDimension.c | 4 ++-- src/core/channels/ChannelValue.c | 18 +++++++++--------- src/core/connections/FilteredConnection.c | 2 +- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/components/comp_vector_integrator.c b/src/components/comp_vector_integrator.c index 77bc342..efd1ba7 100644 --- a/src/components/comp_vector_integrator.c +++ b/src/components/comp_vector_integrator.c @@ -42,7 +42,7 @@ static McxStatus Read(Component * comp, ComponentInput * input, const struct Con size_t numOut = DatabusGetOutChannelsNum(db); if (numIn != numOut) { - ComponentLog(comp, LOG_ERROR, "#inports (%d) does not match the #outports (%d)", numIn, numOut); + ComponentLog(comp, LOG_ERROR, "#inports (%zu) does not match the #outports (%zu)", numIn, numOut); return RETURN_ERROR; } diff --git a/src/core/Databus.c b/src/core/Databus.c index e5580c9..4385837 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -321,7 +321,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, ChannelInfo * info = DatabusReadPortInput(portInput); if (!info) { - 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); retVal = RETURN_ERROR; goto cleanup; } @@ -330,7 +330,7 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, const char * name = ChannelInfoGetName(info); if (info->dimension) { - mcx_log(LOG_DEBUG, " Port: \"%s[%d:%d]\"", name, info->dimension->startIdxs[0], info->dimension->endIdxs[0]); + mcx_log(LOG_DEBUG, " Port: \"%s[%zu:%zu]\"", name, info->dimension->startIdxs[0], info->dimension->endIdxs[0]); } else { mcx_log(LOG_DEBUG, " Port: \"%s\"", name); } @@ -348,13 +348,13 @@ McxStatus DatabusInfoRead(DatabusInfo * dbInfo, if (SpecificRead) { retVal = SpecificRead(comp, info, portInput, i); 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 read element specific data of port %zu", i); goto cleanup; } } if (RETURN_OK != dbInfos->PushBack(dbInfos, info)) { - mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %d", i); + mcx_log(LOG_ERROR, "Ports: Read port infos: Could not append info of port %zu", i); retVal = RETURN_ERROR; goto cleanup; } diff --git a/src/core/Model.c b/src/core/Model.c index 719ea46..12321cb 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -1525,7 +1525,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, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1543,7 +1543,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, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1567,7 +1567,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); } } } @@ -1609,14 +1609,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\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++) { @@ -1632,7 +1632,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1646,14 +1646,14 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetOutChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\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) { @@ -1668,7 +1668,7 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i mcx_os_fprintf(dotFile, " \n", tableArgs); for (j = 0; (int) j < DatabusGetInChannelsNum(db); j++) { mcx_os_fprintf(dotFile, " \n"); - mcx_os_fprintf(dotFile, " \n", j, j); + mcx_os_fprintf(dotFile, " \n", j, j); mcx_os_fprintf(dotFile, " \n"); } mcx_os_fprintf(dotFile, "
%d%zu
\n"); @@ -1676,13 +1676,13 @@ McxStatus PrintModelGraph(ObjectContainer * comps, Vector * conns, Component * i 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); } diff --git a/src/core/SubModel.c b/src/core/SubModel.c index c2999e0..f55ee35 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -768,13 +768,13 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen if (0 == numOutChannels && (INITIAL_DEPENDENCIES == depType)) { mcx_log(LOG_DEBUG, - "(%s,%d) -> (%s,-)", + "(%s,%zu) -> (%s,-)", sourceComp->GetName(sourceComp), sourceOutGroup, targetComp->GetName(targetComp)); } else { mcx_log(LOG_DEBUG, - "(%s,%d) -> (%s,%d)", + "(%s,%zu) -> (%s,%zu)", sourceComp->GetName(sourceComp), sourceOutGroup, targetComp->GetName(targetComp), diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 986ffc3..03ef23e 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -214,7 +214,7 @@ size_t ChannelDimensionGetIndex(const ChannelDimension * dimension, size_t elem_ return slice_idx_0 * sizes[1] + slice_idx_1; } default: - mcx_log(LOG_ERROR, "ChannelDimensionGetIndex: Number of dimensions not supported (%d)", dimension->num); + mcx_log(LOG_ERROR, "ChannelDimensionGetIndex: Number of dimensions not supported (%zu)", dimension->num); break; } @@ -246,7 +246,7 @@ size_t ChannelDimensionGetSliceIndex(const ChannelDimension * dimension, size_t return slice_idx_0 * dim_1_slice_size * slice_idx_1; } default: - mcx_log(LOG_ERROR, "ChannelDimensionGetSliceIndex: Number of dimensions not supported (%d)", dimension->num); + mcx_log(LOG_ERROR, "ChannelDimensionGetSliceIndex: Number of dimensions not supported (%zu)", dimension->num); break; } diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 82856b8..1e33f03 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -352,7 +352,7 @@ McxStatus mcx_array_get_elem(const mcx_array * a, size_t idx, ChannelValueData * size_t num_elems = mcx_array_num_elements(a); if (idx >= num_elems) { - mcx_log(LOG_ERROR, "mcx_array_get_elem: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); + mcx_log(LOG_ERROR, "mcx_array_get_elem: Array index out of range (idx: %zu, num_elems: %zu)", idx, num_elems); return RETURN_ERROR; } @@ -386,7 +386,7 @@ McxStatus mcx_array_set_elem(mcx_array * a, size_t idx, ChannelValueData * eleme size_t num_elems = mcx_array_num_elements(a); if (idx >= num_elems) { - mcx_log(LOG_ERROR, "mcx_array_set_elem: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); + mcx_log(LOG_ERROR, "mcx_array_set_elem: Array index out of range (idx: %zu, num_elems: %zu)", idx, num_elems); return RETURN_ERROR; } @@ -453,7 +453,7 @@ void * mcx_array_get_elem_reference(const mcx_array * a, size_t idx) { char * data = (char *) a->data; if (idx >= num_elems) { - mcx_log(LOG_ERROR, "mcx_array_get_elem_reference: Array index out of range (idx: %d, num_elems: %d)", idx, num_elems); + mcx_log(LOG_ERROR, "mcx_array_get_elem_reference: Array index out of range (idx: %zu, num_elems: %zu)", idx, num_elems); return NULL; } @@ -662,7 +662,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel case CHANNEL_DOUBLE: length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; if (len < length) { - mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %zu, given: %zu", length, len); return RETURN_ERROR; } sprintf(buffer, doubleFmt, (unsigned)precision, (unsigned)precision, value->d); @@ -671,7 +671,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel length = 1 /* sign */ + mcx_digits10(abs(value->i)) + 1 /* string termination*/; if (len < length) { - mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %zu, given: %zu", length, len); return RETURN_ERROR; } sprintf(buffer, "%d", value->i); @@ -679,7 +679,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel case CHANNEL_BOOL: length = 2; if (len < length) { - mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %zu, given: %zu", length, len); return RETURN_ERROR; } sprintf(buffer, "%1d", (value->i != 0) ? 1 : 0); @@ -691,7 +691,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel } length = strlen(value->s) + 1 /* string termination */; if (len < length) { - mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %zu, given: %zu", length, len); return RETURN_ERROR; } sprintf(buffer, "%s", value->s); @@ -706,7 +706,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel case CHANNEL_BINARY_REFERENCE: length = value->b.len * 4 + 1; if (len < length) { - mcx_log(LOG_DEBUG, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + mcx_log(LOG_DEBUG, "Port value to string: buffer too short. Needed: %zu, given: %zu", length, len); return RETURN_ERROR; } { @@ -722,7 +722,7 @@ McxStatus ChannelValueDataToStringBuffer(const ChannelValueData * value, Channel length = 1 /* sign */ + 1 /* pre decimal place */ + 1 /* dot */ + precision + digits_of_exp + 1 /* string termination */; if (len < length) { - mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %d, given: %d", length, len); + mcx_log(LOG_ERROR, "Port value to string: buffer too short. Needed: %zu, given: %zu", length, len); return RETURN_ERROR; } sprintf(buffer, doubleFmt, (unsigned)precision, (unsigned)precision, *(double *)value->a.data); diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index f4f684e..9815911 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -306,7 +306,7 @@ static McxStatus AddFilter(Connection * connection) { info->targetComponent, connString); if (NULL == filteredConnection->data->filters[i]) { - mcx_log(LOG_DEBUG, "Connection: Array filter creation failed for index %d", i); + mcx_log(LOG_DEBUG, "Connection: Array filter creation failed for index %zu", i); retVal = RETURN_ERROR; goto cleanup; } From edf094dd9b56e8de02bf8e874e922026465303e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 21 Sep 2022 17:34:07 +0200 Subject: [PATCH 268/295] FMI2: Read unit of local values --- src/fmu/common_fmu2.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index cb8fd8c..5484fee 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -1355,8 +1355,17 @@ ObjectContainer * Fmu2ValueScalarListFromVarList(fmi2_import_variable_list_t * v fmi2_import_variable_t * var = fmi2_import_get_variable(vars, i); char * name = (char *)fmi2_import_get_variable_name(var); ChannelType * type = Fmi2TypeToChannelType(fmi2_import_get_variable_base_type(var)); + fmi2_import_unit_t * unit = NULL; + const char * unitName = NULL; + + if (ChannelTypeEq(&ChannelTypeDouble, type)) { + unit = fmi2_import_get_real_variable_unit(fmi2_import_get_variable_as_real(var)); + if (unit) { + unitName = fmi2_import_get_unit_name(unit); + } + } - Fmu2Value * value = Fmu2ValueScalarMake(name, var, NULL, NULL); + Fmu2Value * value = Fmu2ValueScalarMake(name, var, unitName, NULL); if (value) { list->PushBackNamed(list, (Object *) value, name); } else { From 0d367226bbee7a31741a0153d6e3e13dcc614b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 7 Nov 2022 16:52:21 +0100 Subject: [PATCH 269/295] Add error log messages --- src/core/channels/ChannelValue.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 1e33f03..f664755 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -986,16 +986,19 @@ McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * // First Set fixes the dimensions if (value->a.numDims && !a->numDims) { if (RETURN_OK != mcx_array_init(a, value->a.numDims, value->a.dims, value->a.type)) { + mcx_log(LOG_ERROR, "ChannelValueDataSetToReference: Array initialization failed"); return RETURN_ERROR; } } // Arrays do not support multiplexing (yet) if (!mcx_array_dims_match(a, &value->a)) { + mcx_log(LOG_ERROR, "ChannelValueDataSetToReference: Array dimensions do not match"); return RETURN_ERROR; } if (value->a.data == NULL || a->data == NULL) { + mcx_log(LOG_ERROR, "ChannelValueDataSetToReference: No array data available"); return RETURN_ERROR; } From 6cf3233123a8fb2fe8eae97a9195efffe853f605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Mon, 7 Nov 2022 17:04:09 +0100 Subject: [PATCH 270/295] Check the reference only once at the beginning --- src/core/channels/ChannelValue.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index f664755..22f74d0 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -936,6 +936,11 @@ McxStatus ChannelValueSet(ChannelValue * value, const ChannelValue * source) { } McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * type, void * reference) { + if (!reference) { + mcx_log(LOG_ERROR, "ChannelValueDataSetToReference: Reference not defined"); + return RETURN_ERROR; + } + switch (type->con) { case CHANNEL_DOUBLE: *(double *) reference = value->d; @@ -961,10 +966,11 @@ McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * } break; case CHANNEL_BINARY: - if (NULL != reference && NULL != ((binary_string *) reference)->data) { + if (NULL != ((binary_string *) reference)->data) { mcx_free(((binary_string *) reference)->data); ((binary_string *) reference)->data = NULL; } + if (value->b.data) { ((binary_string *) reference)->len = value->b.len; ((binary_string *) reference)->data = (char *) mcx_calloc(value->b.len, 1); @@ -974,13 +980,11 @@ McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * } break; case CHANNEL_BINARY_REFERENCE: - if (NULL != reference) { - ((binary_string *) reference)->len = value->b.len; - ((binary_string *) reference)->data = value->b.data; - } + ((binary_string *) reference)->len = value->b.len; + ((binary_string *) reference)->data = value->b.data; break; case CHANNEL_ARRAY: - if (NULL != reference) { + { mcx_array * a = (mcx_array *) reference; // First Set fixes the dimensions @@ -1003,8 +1007,8 @@ McxStatus ChannelValueDataSetToReference(ChannelValueData * value, ChannelType * } memcpy(a->data, value->a.data, ChannelValueTypeSize(a->type) * mcx_array_num_elements(a)); + break; } - break; case CHANNEL_UNKNOWN: default: break; From 0f7fcf1d011e8eecfa4eb3e55513af483d830f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 9 Nov 2022 16:54:44 +0100 Subject: [PATCH 271/295] Define a typedef for the dimension type --- src/core/channels/ChannelValue.c | 2 +- src/core/channels/ChannelValue.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 22f74d0..610882c 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -117,7 +117,7 @@ ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dim return array; } -ChannelType * ChannelTypeArrayLongDims(ChannelType * inner, size_t numDims, unsigned long * dims) { +ChannelType * ChannelTypeArrayUInt64Dims(ChannelType * inner, size_t numDims, uint64_t * dims) { ChannelType * array = NULL; size_t i = 0; diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index a2936bd..13e1f8c 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -13,6 +13,7 @@ #include "CentralParts.h" #include +#include #ifdef __cplusplus extern "C" { @@ -57,7 +58,7 @@ extern ChannelType ChannelTypeString; extern ChannelType ChannelTypeBinary; extern ChannelType ChannelTypeBinaryReference; ChannelType * ChannelTypeArray(ChannelType * inner, size_t numDims, size_t * dims); -ChannelType * ChannelTypeArrayLongDims(ChannelType * inner, size_t numDims, unsigned long * dims); +ChannelType * ChannelTypeArrayUInt64Dims(ChannelType * inner, size_t numDims, uint64_t * dims); ChannelType * ChannelTypeClone(ChannelType * type); void ChannelTypeDestructor(ChannelType * type); From c260ddc812a4e553ee33e8d10f9f172d2149e6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 9 Nov 2022 17:02:19 +0100 Subject: [PATCH 272/295] Use McxStatus as return type of channel functions --- src/core/channels/Channel.c | 2 +- src/core/channels/ChannelValue.h | 2 +- src/core/connections/FilteredConnection.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 73f945a..fc4c082 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -917,7 +917,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { if (out->GetFunction(out)) { // function value proc * p = (proc *) out->GetFunction(out); - if (p->fn(time, p->env, &out->data->valueFunctionRes) != 0) { + if (RETURN_ERROR == p->fn(time, p->env, &out->data->valueFunctionRes)) { mcx_log(LOG_ERROR, "Port %s: Update outport: Function failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } diff --git a/src/core/channels/ChannelValue.h b/src/core/channels/ChannelValue.h index 13e1f8c..9647c62 100644 --- a/src/core/channels/ChannelValue.h +++ b/src/core/channels/ChannelValue.h @@ -94,7 +94,7 @@ typedef union ChannelValueData ChannelValueData; typedef struct ChannelValue ChannelValue; typedef struct { - int (* fn)(TimeInterval * arg, void * env, ChannelValue * res); + McxStatus (* fn)(TimeInterval * arg, void * env, ChannelValue * res); void * env; } proc; diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 9815911..83ec282 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -217,7 +217,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI proc * p = (proc *) out->GetFunction(out); // TODO: Update functions to only update the slices ? - if (p->fn(time, p->env, &filteredConnection->data->updateBuffer) != 0) { + if (RETURN_ERROR == p->fn(time, p->env, &filteredConnection->data->updateBuffer)) { mcx_log(LOG_ERROR, "FilteredConnection: Function failed"); return RETURN_ERROR; } From d13a9a00995409c78e2f38d75c95a3819b2723c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Nov 2022 13:17:05 +0100 Subject: [PATCH 273/295] Remove obsolete return --- src/core/channels/ChannelValue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 610882c..d131f1d 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -224,7 +224,6 @@ int ChannelTypeEq(const ChannelType * a, const ChannelType * b) { } } return a->ty.a.inner == b->ty.a.inner; - return 1; } else { return a->con == b->con; } From fb7b2cd5425bfae5159d9d4af63bd8352f4d99e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Nov 2022 13:17:33 +0100 Subject: [PATCH 274/295] Calculate for loop bounds outside --- src/core/channels/ChannelValue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index d131f1d..8a08289 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -255,8 +255,9 @@ void mcx_array_destroy(mcx_array * a) { int mcx_array_all(mcx_array * a, mcx_array_predicate_f_ptr predicate) { size_t i = 0; ChannelValueData element = {0}; + size_t numElems = mcx_array_num_elements(a); - for (i = 0; i < mcx_array_num_elements(a); i++) { + for (i = 0; i < numElems; i++) { if (RETURN_OK != mcx_array_get_elem(a, i, &element)) { mcx_log(LOG_WARNING, "mcx_array_all: Getting element %zu failed", i); return 0; From 5f6ddf030a43d0eda7f2e673cff2076c568bc2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Nov 2022 13:38:50 +0100 Subject: [PATCH 275/295] Indentation --- src/core/Conversion.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/core/Conversion.c b/src/core/Conversion.c index 6ccec92..cb1677d 100644 --- a/src/core/Conversion.c +++ b/src/core/Conversion.c @@ -99,23 +99,22 @@ McxStatus RangeConversionMinValueRefConversion(void * element, size_t idx, Chann ChannelValue * min = (ChannelValue *) ctx; void * minElem = mcx_array_get_elem_reference(&min->value.a, idx); if (RangeConversionElemwiseLeq(element, minElem, type)) { - switch (type->con) - { + switch (type->con) { case CHANNEL_DOUBLE: { double * elem = (double *) element; - *elem = *((double *)minElem); + *elem = *((double *) minElem); break; } - case CHANNEL_INTEGER: + case CHANNEL_INTEGER: { int * elem = (int *) element; - *elem = *((int *)minElem); + *elem = *((int *) minElem); break; } - default: - mcx_log(LOG_ERROR, "RangeConversion: Unsupported type"); - return RETURN_ERROR; + default: + mcx_log(LOG_ERROR, "RangeConversion: Unsupported type"); + return RETURN_ERROR; } } From aaae41ddb3d7be29aac04c58be3e64ff79451375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Nov 2022 13:39:01 +0100 Subject: [PATCH 276/295] Add log message --- src/core/channels/ChannelValue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/channels/ChannelValue.c b/src/core/channels/ChannelValue.c index 8a08289..9386b73 100644 --- a/src/core/channels/ChannelValue.c +++ b/src/core/channels/ChannelValue.c @@ -205,6 +205,7 @@ int ChannelTypeConformable(ChannelType * a, ChannelDimension * sliceA, ChannelTy } } else { if (sliceA || sliceB) { + mcx_log(LOG_ERROR, "ChannelTypeConformable: Slice dimensions defined for non-array channels"); return 0; } From accab582dca015335b40907f1cd3d743e716f03e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Nov 2022 13:44:03 +0100 Subject: [PATCH 277/295] Remove rebase artifacts --- src/core/channels/Channel.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index fc4c082..8eb73f7 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -732,8 +732,6 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * static McxStatus ChannelOutRegisterConnection(ChannelOut * out, Connection * connection) { ObjectList * conns = out->data->connections; - ChannelDimension * outDim = ((Channel*)out)->info.dimension; - ChannelDimension * connDim = connection->info.sourceDimension; // TODO: do we have to check that channelout and connection match // in type/dimension? From 5b8f13854e4619ccfc57726324ec235fc7726ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Wed, 16 Nov 2022 15:29:40 +0100 Subject: [PATCH 278/295] Fix indexing formula --- src/core/channels/ChannelDimension.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/ChannelDimension.c b/src/core/channels/ChannelDimension.c index 03ef23e..9596e61 100644 --- a/src/core/channels/ChannelDimension.c +++ b/src/core/channels/ChannelDimension.c @@ -243,7 +243,7 @@ size_t ChannelDimensionGetSliceIndex(const ChannelDimension * dimension, size_t size_t dim_1_slice_size = dimension->endIdxs[1] - dimension->startIdxs[1] + 1; - return slice_idx_0 * dim_1_slice_size * slice_idx_1; + return slice_idx_0 * dim_1_slice_size + slice_idx_1; } default: mcx_log(LOG_ERROR, "ChannelDimensionGetSliceIndex: Number of dimensions not supported (%zu)", dimension->num); From 344f53f0f3d87522c2b391a1b27351fb7fac8859 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Thu, 10 Nov 2022 09:51:17 +0100 Subject: [PATCH 279/295] channel: Inline ChannelInData (Performance!) --- src/core/channels/Channel.c | 108 ++++++++++++++++--------------- src/core/channels/Channel.h | 32 ++++++++- src/core/channels/Channel_impl.h | 29 --------- 3 files changed, 87 insertions(+), 82 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 8eb73f7..626e32b 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -158,36 +158,44 @@ static void DestroyChannelValueReferencePtr(ChannelValueReference ** ptr) { DestroyChannelValueReference(*ptr); } -static ChannelInData * ChannelInDataCreate(ChannelInData * data) { +static McxStatus ChannelInDataInit(ChannelInData * data) { data->connections = (ObjectContainer *) object_create(ObjectContainer); if (!data->connections) { - return NULL; + mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for connections failed"); + return RETURN_ERROR; } data->valueReferences = (Vector *) object_create(Vector); if (!data->valueReferences) { - return NULL; + mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for value references failed"); + return RETURN_ERROR; } data->valueReferences->Setup(data->valueReferences, sizeof(ChannelValueReference *), NULL, NULL, DestroyChannelValueReferencePtr); data->reference = NULL; data->type = ChannelTypeClone(&ChannelTypeUnknown); + if (!data->type) { + mcx_log(LOG_ERROR, "ChannelInDataInit: Cloning ChannelType failed"); + return RETURN_ERROR; + } data->typeConversions = (ObjectContainer *) object_create(ObjectContainer); if (!data->typeConversions) { - return NULL; + mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for type conversion objects failed"); + return RETURN_ERROR; } data->unitConversions = (ObjectContainer *) object_create(ObjectContainer); if (!data->unitConversions) { - return NULL; + mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for unit conversion objects failed"); + return RETURN_ERROR; } data->linearConversion = NULL; data->rangeConversion = NULL; data->isDiscrete = FALSE; - return data; + return RETURN_OK; } static void ChannelInDataDestructor(ChannelInData * data) { @@ -217,10 +225,6 @@ static void ChannelInDataDestructor(ChannelInData * data) { } } -OBJECT_CLASS(ChannelInData, Object); - - - static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, ChannelType * type) { Channel * ch = (Channel *) in; ChannelInfo * info = &ch->info; @@ -229,7 +233,7 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel mcx_log(LOG_ERROR, "Port: Set inport reference: Invalid port"); return RETURN_ERROR; } - if (in->data->reference) { + if (in->data.reference) { mcx_log(LOG_ERROR, "Port %s: Set inport reference: Reference already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -249,8 +253,8 @@ static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, Channel } } - in->data->reference = reference; - in->data->type = ChannelTypeClone(type); + in->data.reference = reference; + in->data.type = ChannelTypeClone(type); return RETURN_OK; } @@ -282,13 +286,13 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { /* if no connection is present we have nothing to update*/ size_t i = 0; - size_t numConns = in->data->connections->Size(in->data->connections); + size_t numConns = in->data.connections->Size(in->data->connections); for (i = 0; i < numConns; i++) { - Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); + Connection * conn = (Connection *) in->data.connections->At(in->data->connections, i); ConnectionInfo * connInfo = &conn->info; - TypeConversion * typeConv = (TypeConversion *) in->data->typeConversions->At(in->data->typeConversions, i); - UnitConversion * unitConv = (UnitConversion *) in->data->unitConversions->At(in->data->unitConversions, i); - ChannelValueReference * valueRef = *(ChannelValueReference **) in->data->valueReferences->At(in->data->valueReferences, i); + TypeConversion * typeConv = (TypeConversion *) in->data.typeConversions->At(in->data.typeConversions, i); + UnitConversion * unitConv = (UnitConversion *) in->data.unitConversions->At(in->data.unitConversions, i); + ChannelValueReference * valueRef = *(ChannelValueReference **) in->data.valueReferences->At(in->data.valueReferences, i); /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { @@ -315,8 +319,8 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ChannelValue * val = &channel->value; // linear - if (in->data->linearConversion) { - Conversion * conversion = (Conversion *) in->data->linearConversion; + 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)); @@ -325,8 +329,8 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { } // range - if (in->data->rangeConversion) { - Conversion * conversion = (Conversion *) in->data->rangeConversion; + 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)); @@ -336,7 +340,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { } /* no reference from the component was set, skip updating*/ - if (!in->data->reference || !channel->GetValueReference(channel)) { + if (!in->data.reference || !channel->GetValueReference(channel)) { return RETURN_OK; } @@ -344,7 +348,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); } - if (RETURN_OK != ChannelValueDataSetFromReference(in->data->reference, in->data->type, channel->GetValueReference(channel))) { + if (RETURN_OK != ChannelValueDataSetFromReference(in->data.reference, in->data.type, channel->GetValueReference(channel))) { return RETURN_ERROR; } @@ -357,8 +361,8 @@ static int ChannelInIsFullyConnected(Channel * channel) { size_t connectedElems = 0; size_t channelNumElems = channel->info.dimension ? ChannelDimensionNumElements(channel->info.dimension) : 1; - for (i = 0; i < in->data->connections->Size(in->data->connections); i++) { - Connection * conn = (Connection *) in->data->connections->At(in->data->connections, i); + for (i = 0; i < in->data.connections->Size(in->data.connections); i++) { + Connection * conn = (Connection *) in->data.connections->At(in->data.connections, i); ConnectionInfo * info = &conn->info; connectedElems += info->targetDimension ? ChannelDimensionNumElements(info->targetDimension) : 1; @@ -384,11 +388,11 @@ static int ChannelInProvidesValue(Channel * channel) { } static void ChannelInSetDiscrete(ChannelIn * in) { - in->data->isDiscrete = TRUE; + in->data.isDiscrete = TRUE; } static int ChannelInIsDiscrete(ChannelIn * in) { - return in->data->isDiscrete; + return in->data.isDiscrete; } static int ChannelInIsConnected(Channel * channel) { @@ -396,7 +400,7 @@ static int ChannelInIsConnected(Channel * channel) { return TRUE; } else { ChannelIn * in = (ChannelIn *) channel; - if (in->data->connections->Size(in->data->connections) > 0) { + if (in->data.connections->Size(in->data->connections) > 0) { return TRUE; } } @@ -406,7 +410,7 @@ static int ChannelInIsConnected(Channel * channel) { static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { Vector * infos = (Vector*) object_create(Vector); - size_t numConns = in->data->connections->Size(in->data->connections); + size_t numConns = in->data.connections->Size(in->data.connections); size_t i = 0; if (!infos) { @@ -416,7 +420,7 @@ static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { infos->Setup(infos, sizeof(ConnectionInfo*), NULL, NULL, NULL); for (i = 0; i < numConns; i++) { - Connection * conn = in->data->connections->At(in->data->connections, i); + Connection * conn = in->data.connections->At(in->data.connections, i); ConnectionInfo * connInfo = &conn->info; if (RETURN_ERROR == infos->PushBack(infos, &connInfo)) { object_destroy(infos); @@ -428,7 +432,7 @@ static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { } static ObjectContainer * ChannelInGetConnections(ChannelIn * in) { - return in->data->connections; + return in->data.connections; } static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType * type) { @@ -439,7 +443,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec McxStatus retVal = RETURN_OK; - retVal = in->data->connections->PushBack(in->data->connections, (Object *) connection); + retVal = in->data.connections->PushBack(in->data.connections, (Object *) connection); if (RETURN_OK != retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not register connection"); } @@ -459,7 +463,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec valRef = MakeChannelValueReference(&channel->value, NULL); } - retVal = in->data->valueReferences->PushBack(in->data->valueReferences, &valRef); + retVal = in->data.valueReferences->PushBack(in->data.valueReferences, &valRef); if (RETURN_ERROR == retVal) { ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Storing value reference failed"); return RETURN_ERROR; @@ -477,12 +481,12 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec object_destroy(conversion); } - retVal = in->data->unitConversions->PushBack(in->data->unitConversions, (Object *) conversion); + retVal = in->data.unitConversions->PushBack(in->data.unitConversions, (Object *) conversion); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add unit conversion"); } } else { - retVal = in->data->unitConversions->PushBack(in->data->unitConversions, NULL); + retVal = in->data.unitConversions->PushBack(in->data.unitConversions, NULL); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add empty unit conversion"); } @@ -500,12 +504,12 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up type conversion"); } - retVal = in->data->typeConversions->PushBack(in->data->typeConversions, (Object *) typeConv); + retVal = in->data.typeConversions->PushBack(in->data.typeConversions, (Object *) typeConv); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add type conversion"); } } else { - retVal = in->data->typeConversions->PushBack(in->data->typeConversions, NULL); + retVal = in->data.typeConversions->PushBack(in->data.typeConversions, NULL); if (RETURN_ERROR == retVal) { return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add empty type conversion"); } @@ -557,27 +561,27 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * 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); + 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", ChannelInfoGetLogName(info)); - object_destroy(in->data->rangeConversion); + object_destroy(in->data.rangeConversion); return RETURN_ERROR; } else { - if (in->data->rangeConversion->IsEmpty(in->data->rangeConversion)) { - object_destroy(in->data->rangeConversion); + if (in->data.rangeConversion->IsEmpty(in->data.rangeConversion)) { + object_destroy(in->data.rangeConversion); } } - in->data->linearConversion = (LinearConversion *) object_create(LinearConversion); - retVal = in->data->linearConversion->Setup(in->data->linearConversion, scale, offset); + 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", ChannelInfoGetLogName(info)); - object_destroy(in->data->linearConversion); + object_destroy(in->data.linearConversion); return RETURN_ERROR; } else { - if (in->data->linearConversion->IsEmpty(in->data->linearConversion)) { - object_destroy(in->data->linearConversion); + if (in->data.linearConversion->IsEmpty(in->data.linearConversion)) { + object_destroy(in->data.linearConversion); } } } @@ -586,14 +590,16 @@ static McxStatus ChannelInSetup(ChannelIn * in, ChannelInfo * info) { } static void ChannelInDestructor(ChannelIn * in) { - object_destroy(in->data); + ChannelInDataDestructor(&in->data); } static ChannelIn * ChannelInCreate(ChannelIn * in) { Channel * channel = (Channel *) in; + McxStatus retVal = RETURN_OK; - in->data = (ChannelInData *) object_create(ChannelInData); - if (!in->data) { + retVal = ChannelInDataInit(&in->data); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "ChannelInCreate: ChannelInDataInit failed"); return NULL; } diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index 52d45d3..cac2bf7 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -13,6 +13,11 @@ #include "CentralParts.h" #include "core/channels/ChannelInfo.h" +#include "core/channels/ChannelValueReference.h" +#include "objects/ObjectContainer.h" +#include "objects/Vector.h" +#include "core/connections/Connection.h" +#include "core/Conversion.h" #ifdef __cplusplus extern "C" { @@ -21,7 +26,6 @@ extern "C" { struct Config; struct Component; -struct ChannelInData; struct ChannelOutData; struct Connection; @@ -116,6 +120,30 @@ struct Channel { typedef struct ChannelIn ChannelIn; +// object that is stored in target component that stores the channel connection +typedef struct ChannelInData { + + ObjectContainer * connections; // connections (non-overlapping) going into the channel + Vector * valueReferences; // references to non-overlapping parts of ChannelData::value, where + // values gotten from connections are going to be stored + + // ---------------------------------------------------------------------- + // Conversions + + ObjectContainer * typeConversions; // conversion objects (or NULL) for each connection in `connections` + ObjectContainer * unitConversions; // conversion objects (or NULL) for each connection in `connections` + struct LinearConversion * linearConversion; + struct RangeConversion * rangeConversion; + + // ---------------------------------------------------------------------- + // Storage in Component + + int isDiscrete; + + void * reference; + ChannelType * type; +} ChannelInData; + typedef McxStatus (* fChannelInSetup)(ChannelIn * in, struct ChannelInfo * info); typedef McxStatus (* fChannelInSetReference) (ChannelIn * in, @@ -174,7 +202,7 @@ struct ChannelIn { */ fChannelInSetDiscrete SetDiscrete; - struct ChannelInData * data; + ChannelInData data; }; diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index 2b330e6..9503411 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -20,35 +20,6 @@ extern "C" { #endif /* __cplusplus */ - -// ---------------------------------------------------------------------- -// ChannelIn - -// object that is stored in target component that stores the channel connection -typedef struct ChannelInData { - Object _; // base class - - ObjectContainer * connections; // connections (non-overlapping) going into the channel - Vector * valueReferences; // references to non-overlapping parts of ChannelData::value, where - // values gotten from connections are going to be stored - - // ---------------------------------------------------------------------- - // Conversions - - ObjectContainer * typeConversions; // conversion objects (or NULL) for each connection in `connections` - ObjectContainer * unitConversions; // conversion objects (or NULL) for each connection in `connections` - struct LinearConversion * linearConversion; - struct RangeConversion * rangeConversion; - - // ---------------------------------------------------------------------- - // Storage in Component - - int isDiscrete; - - void * reference; - ChannelType * type; -} ChannelInData; - // ---------------------------------------------------------------------- // ChannelOut From 856f2b5f08e5f806172c7cb2aaf9d16b2557dff1 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 25 Oct 2022 09:51:57 +0200 Subject: [PATCH 280/295] channel: Inline ChannelOutData (Performance!) --- src/core/channels/Channel.c | 82 ++++++++++++++++---------------- src/core/channels/Channel.h | 36 +++++++++++++- src/core/channels/Channel_impl.h | 38 --------------- 3 files changed, 74 insertions(+), 82 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 626e32b..f33bde1 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -628,7 +628,7 @@ static ChannelIn * ChannelInCreate(ChannelIn * in) { // ---------------------------------------------------------------------- // ChannelOut -static ChannelOutData * ChannelOutDataCreate(ChannelOutData * data) { +static McxStatus ChannelOutDataInit(ChannelOutData * data) { data->valueFunction = NULL; ChannelValueInit(&data->valueFunctionRes, ChannelTypeClone(&ChannelTypeUnknown)); data->rangeConversion = NULL; @@ -644,7 +644,7 @@ static ChannelOutData * ChannelOutDataCreate(ChannelOutData * data) { data->maxNumNaNCheckWarning = 0; - return data; + return RETURN_OK; } static void ChannelOutDataDestructor(ChannelOutData * data) { @@ -666,10 +666,6 @@ static void ChannelOutDataDestructor(ChannelOutData * data) { ChannelValueDestructor(&data->valueFunctionRes); } -OBJECT_CLASS(ChannelOutData, Object); - - - static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * config) { Channel * channel = (Channel *) out; @@ -700,27 +696,27 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * if (ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeDouble) || ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeInteger)) { - out->data->rangeConversion = (RangeConversion *) object_create(RangeConversion); - retVal = out->data->rangeConversion->Setup(out->data->rangeConversion, min, max); + 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", ChannelInfoGetLogName(info)); - object_destroy(out->data->rangeConversion); + object_destroy(out->data.rangeConversion); return RETURN_ERROR; } else { - if (out->data->rangeConversion->IsEmpty(out->data->rangeConversion)) { - object_destroy(out->data->rangeConversion); + if (out->data.rangeConversion->IsEmpty(out->data.rangeConversion)) { + object_destroy(out->data.rangeConversion); } } - out->data->linearConversion = (LinearConversion *) object_create(LinearConversion); - retVal = out->data->linearConversion->Setup(out->data->linearConversion, scale, offset); + 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", ChannelInfoGetLogName(info)); - object_destroy(out->data->linearConversion); + object_destroy(out->data.linearConversion); return RETURN_ERROR; } else { - if (out->data->linearConversion->IsEmpty(out->data->linearConversion)) { - object_destroy(out->data->linearConversion); + if (out->data.linearConversion->IsEmpty(out->data.linearConversion)) { + object_destroy(out->data.linearConversion); } } } @@ -730,8 +726,8 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * return RETURN_ERROR; } - out->data->nanCheck = config->nanCheck; - out->data->maxNumNaNCheckWarning = config->nanCheckNumMessages; + out->data.nanCheck = config->nanCheck; + out->data.maxNumNaNCheckWarning = config->nanCheckNumMessages; return RETURN_OK; } @@ -759,11 +755,11 @@ static const void * ChannelOutGetValueReference(Channel * channel) { } static const proc * ChannelOutGetFunction(ChannelOut * out) { - return out->data->valueFunction; + return out->data.valueFunction; } static ObjectList * ChannelOutGetConnections(ChannelOut * out) { - return out->data->connections; + return out->data.connections; } static int ChannelOutProvidesValue(Channel * channel) { @@ -775,8 +771,8 @@ static int ChannelOutIsConnected(Channel * channel) { return TRUE; } else { ChannelOut * out = (ChannelOut *) channel; - if (NULL != out->data->connections) { - if (out->data->connections->Size(out->data->connections)) { + if (NULL != out->data.connections) { + if (out->data.connections->Size(out->data.connections)) { return TRUE; } } @@ -789,7 +785,7 @@ static int ChannelOutIsFullyConnected(Channel * channel) { ChannelOut * out = (ChannelOut *) channel; if (ChannelTypeIsArray(&channel->info.type)) { - ObjectList* conns = out->data->connections; + ObjectList* conns = out->data.connections; size_t i = 0; size_t num_elems = ChannelDimensionNumElements(channel->info.dimension); @@ -800,7 +796,7 @@ static int ChannelOutIsFullyConnected(Channel * channel) { } for (i = 0; i < conns->Size(conns); i++) { - Connection * conn = (Connection *) out->data->connections->At(out->data->connections, i); + Connection * conn = (Connection *) out->data.connections->At(out->data.connections, i); ConnectionInfo * info = &conn->info; size_t j = 0; @@ -872,16 +868,16 @@ static McxStatus ChannelOutSetReferenceFunction(ChannelOut * out, const proc * r } } - if (out->data->valueFunction) { + if (out->data.valueFunction) { mcx_log(LOG_ERROR, "Port %s: Set outport function: Reference already set", ChannelInfoGetLogName(info)); return RETURN_ERROR; } // Save channel procedure - out->data->valueFunction = (const proc *) reference; + out->data.valueFunction = (const proc *) reference; // Initialize (and allocate necessary memory) - ChannelValueInit(&out->data->valueFunctionRes, ChannelTypeClone(type)); + ChannelValueInit(&out->data.valueFunctionRes, ChannelTypeClone(type)); // Setup value reference to point to internal value channel->internalValue = ChannelValueDataPointer(&channel->value); @@ -909,7 +905,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ChannelOut * out = (ChannelOut *)channel; ChannelInfo * info = &channel->info; - ObjectList * conns = out->data->connections; + ObjectList * conns = out->data.connections; McxStatus retVal = RETURN_OK; @@ -921,7 +917,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { if (out->GetFunction(out)) { // function value proc * p = (proc *) out->GetFunction(out); - if (RETURN_ERROR == p->fn(time, p->env, &out->data->valueFunctionRes)) { + if (RETURN_ERROR == p->fn(time, p->env, &out->data.valueFunctionRes)) { mcx_log(LOG_ERROR, "Port %s: Update outport: Function failed", ChannelInfoGetLogName(info)); return RETURN_ERROR; } @@ -931,10 +927,10 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { time->startTime, ChannelInfoGetLogName(info), time->startTime, - out->data->valueFunctionRes.value.d); + out->data.valueFunctionRes.value.d); } #endif // MCX_DEBUG - if (RETURN_OK != ChannelValueSetFromReference(&channel->value, ChannelValueDataPointer(&out->data->valueFunctionRes))) { + if (RETURN_OK != ChannelValueSetFromReference(&channel->value, ChannelValueDataPointer(&out->data.valueFunctionRes))) { return RETURN_ERROR; } } else { @@ -963,9 +959,9 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ChannelValue * val = &channel->value; // range - if (out->data->rangeConversion) { - if (out->data->rangeConversionIsActive) { - Conversion * conversion = (Conversion *) out->data->rangeConversion; + if (out->data.rangeConversion) { + if (out->data.rangeConversionIsActive) { + 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", ChannelInfoGetLogName(info)); @@ -975,8 +971,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // linear - if (out->data->linearConversion) { - Conversion * conversion = (Conversion *) out->data->linearConversion; + if (out->data.linearConversion) { + 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", ChannelInfoGetLogName(info)); @@ -1004,7 +1000,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { if (isnan(*val)) { - switch (out->data->nanCheck) { + switch (out->data.nanCheck) { case NAN_CHECK_ALWAYS: mcx_log(LOG_ERROR, "Outport %s at time %f is not a number (NaN)", @@ -1017,13 +1013,13 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ChannelInfoGetName(info), time->startTime); return RETURN_ERROR; } else { - WarnAboutNaN(LOG_WARNING, info, time, &out->data->countNaNCheckWarning, &out->data->maxNumNaNCheckWarning); + WarnAboutNaN(LOG_WARNING, info, time, &out->data.countNaNCheckWarning, &out->data.maxNumNaNCheckWarning); break; } case NAN_CHECK_NEVER: WarnAboutNaN((conns->Size(conns) > 0) ? LOG_ERROR : LOG_WARNING, - info, time, &out->data->countNaNCheckWarning, &out->data->maxNumNaNCheckWarning); + info, time, &out->data.countNaNCheckWarning, &out->data.maxNumNaNCheckWarning); break; } } @@ -1034,14 +1030,16 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } static void ChannelOutDestructor(ChannelOut * out) { - object_destroy(out->data); + ChannelOutDataDestructor(&out->data); } static ChannelOut * ChannelOutCreate(ChannelOut * out) { Channel * channel = (Channel *) out; + McxStatus retVal = RETURN_OK; - out->data = (ChannelOutData *) object_create(ChannelOutData); - if (!out->data) { + retVal = ChannelOutDataInit(&out->data); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "ChannelOutCreate: ChannelOutDataInit failed"); return NULL; } diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index cac2bf7..ecc8fbd 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -26,7 +26,6 @@ extern "C" { struct Config; struct Component; -struct ChannelOutData; struct Connection; @@ -210,6 +209,39 @@ struct ChannelIn { // ChannelOut typedef struct ChannelOut ChannelOut; +// object that is provided to consumer of output channel +typedef struct ChannelOutData { + + // Function pointer that provides the value of the channel when called + const proc * valueFunction; + + // Used to store results of channel-internal valueFunction calls + ChannelValue valueFunctionRes; + + // ---------------------------------------------------------------------- + // Conversion + + struct RangeConversion * rangeConversion; + struct LinearConversion * linearConversion; + + int rangeConversionIsActive; + + // ---------------------------------------------------------------------- + // NaN Handling + + NaNCheckLevel nanCheck; + + size_t countNaNCheckWarning; + size_t maxNumNaNCheckWarning; + + // ---------------------------------------------------------------------- + // Connections to Consumers + + // A list of all input channels that are connected to this output channel + ObjectList * connections; + +} ChannelOutData; + typedef McxStatus (* fChannelOutSetup)(ChannelOut * out, struct ChannelInfo * info, struct Config * config); @@ -273,7 +305,7 @@ struct ChannelOut { */ fChannelOutGetConnections GetConnections; - struct ChannelOutData * data; + ChannelOutData data; }; // ---------------------------------------------------------------------- diff --git a/src/core/channels/Channel_impl.h b/src/core/channels/Channel_impl.h index 9503411..9588c99 100644 --- a/src/core/channels/Channel_impl.h +++ b/src/core/channels/Channel_impl.h @@ -19,44 +19,6 @@ extern "C" { #endif /* __cplusplus */ - -// ---------------------------------------------------------------------- -// ChannelOut - -// object that is provided to consumer of output channel -typedef struct ChannelOutData { - Object _; // base class - - // Function pointer that provides the value of the channel when called - const proc * valueFunction; - - // Used to store results of channel-internal valueFunction calls - ChannelValue valueFunctionRes; - - // ---------------------------------------------------------------------- - // Conversion - - struct RangeConversion * rangeConversion; - struct LinearConversion * linearConversion; - - int rangeConversionIsActive; - - // ---------------------------------------------------------------------- - // NaN Handling - - NaNCheckLevel nanCheck; - - size_t countNaNCheckWarning; - size_t maxNumNaNCheckWarning; - - // ---------------------------------------------------------------------- - // Connections to Consumers - - // A list of all input channels that are connected to this output channel - ObjectList * connections; - -} ChannelOutData; - // ---------------------------------------------------------------------- // ChannelLocal From 50852489de20a22ea9087014eabaccda1e163698 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 25 Oct 2022 10:18:37 +0200 Subject: [PATCH 281/295] channel: Reduce redirections on in connections (Performance!) --- src/core/Component.c | 2 +- src/core/Component.h | 2 +- src/core/SubModel.c | 4 ++-- src/core/channels/Channel.c | 43 +++++++++++++++++++++++-------------- src/core/channels/Channel.h | 11 ++++++++-- 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index b8070aa..0efac54 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -851,7 +851,7 @@ Vector * GetInConnectionInfos(const Component * comp, size_t channelID) { return NULL; } -ObjectContainer * GetInConnections(const Component * comp, size_t channelID) { +ConnectionList * GetInConnections(const Component * comp, size_t channelID) { size_t channelNum = DatabusInfoGetChannelNum(DatabusGetInInfo(comp->data->databus)); if (channelID < channelNum) { ChannelIn * in = DatabusGetInChannel(comp->data->databus, channelID); diff --git a/src/core/Component.h b/src/core/Component.h index 4893dae..997d330 100644 --- a/src/core/Component.h +++ b/src/core/Component.h @@ -255,7 +255,7 @@ McxStatus ComponentEnterCommunicationPoint(Component * comp, TimeInterval * time McxStatus ComponentEnterCommunicationPointForConnections(Component * comp, ObjectList * connections, TimeInterval * time); Vector * GetInConnectionInfos(const Component * comp, size_t channelID); -struct ObjectContainer * GetInConnections(const Component * comp, size_t channelID); +struct ConnectionList * GetInConnections(const Component * comp, size_t channelID); size_t ComponentGetNumOutGroups(const Component * comp); size_t ComponentGetNumInitialOutGroups(const Component * comp); diff --git a/src/core/SubModel.c b/src/core/SubModel.c index f55ee35..e2e64d8 100644 --- a/src/core/SubModel.c +++ b/src/core/SubModel.c @@ -716,12 +716,12 @@ static struct Dependencies * SubModelGeneratorCreateDependencyMatrix(SubModelGen if (DEP_INDEPENDENT != dependency) { Vector * infos = GetInConnectionInfos(targetComp, targetInChannelID); - ObjectContainer * conns = GetInConnections(targetComp, targetInChannelID); + ConnectionList * conns = GetInConnections(targetComp, targetInChannelID); size_t i = 0; for (i = 0; i < infos->Size(infos); i++) { ConnectionInfo * info = *(ConnectionInfo**) infos->At(infos, i); - Connection * conn = conns->At(conns, i); + Connection * conn = conns->connections[i]; if (info && (info->decoupleType & (DECOUPLE_NEVER | DECOUPLE_IFNEEDED)) && (!ConnectionInfoIsDecoupled(info)) && conn && conn->IsActiveDependency(conn)) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index f33bde1..01977de 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -159,11 +159,15 @@ static void DestroyChannelValueReferencePtr(ChannelValueReference ** ptr) { } static McxStatus ChannelInDataInit(ChannelInData * data) { - data->connections = (ObjectContainer *) object_create(ObjectContainer); - if (!data->connections) { + data->increment = 2; + + data->connList.connections = (Connection * *) mcx_malloc(sizeof(Connection *)); + if (!data->connList.connections) { mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for connections failed"); return RETURN_ERROR; } + data->connList.capacity = 1; + data->connList.numConnections = 0; data->valueReferences = (Vector *) object_create(Vector); if (!data->valueReferences) { @@ -216,8 +220,8 @@ static void ChannelInDataDestructor(ChannelInData * data) { ChannelTypeDestructor(data->type); } - if (data->connections) { - object_destroy(data->connections); + if (data->connList.connections) { + mcx_free((void *) data->connList.connections); } if (data->valueReferences) { @@ -286,9 +290,9 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { /* if no connection is present we have nothing to update*/ size_t i = 0; - size_t numConns = in->data.connections->Size(in->data->connections); + size_t numConns = in->data.connList.numConnections; for (i = 0; i < numConns; i++) { - Connection * conn = (Connection *) in->data.connections->At(in->data->connections, i); + Connection * conn = (Connection *) in->data.connList.connections[i]; ConnectionInfo * connInfo = &conn->info; TypeConversion * typeConv = (TypeConversion *) in->data.typeConversions->At(in->data.typeConversions, i); UnitConversion * unitConv = (UnitConversion *) in->data.unitConversions->At(in->data.unitConversions, i); @@ -361,8 +365,8 @@ static int ChannelInIsFullyConnected(Channel * channel) { size_t connectedElems = 0; size_t channelNumElems = channel->info.dimension ? ChannelDimensionNumElements(channel->info.dimension) : 1; - for (i = 0; i < in->data.connections->Size(in->data.connections); i++) { - Connection * conn = (Connection *) in->data.connections->At(in->data.connections, i); + for (i = 0; i < in->data.connList.numConnections; i++) { + Connection * conn = (Connection *) in->data.connList.connections[i]; ConnectionInfo * info = &conn->info; connectedElems += info->targetDimension ? ChannelDimensionNumElements(info->targetDimension) : 1; @@ -400,7 +404,7 @@ static int ChannelInIsConnected(Channel * channel) { return TRUE; } else { ChannelIn * in = (ChannelIn *) channel; - if (in->data.connections->Size(in->data->connections) > 0) { + if (in->data.connList.numConnections > 0) { return TRUE; } } @@ -410,7 +414,7 @@ static int ChannelInIsConnected(Channel * channel) { static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { Vector * infos = (Vector*) object_create(Vector); - size_t numConns = in->data.connections->Size(in->data.connections); + size_t numConns = in->data.connList.numConnections; size_t i = 0; if (!infos) { @@ -420,7 +424,7 @@ static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { infos->Setup(infos, sizeof(ConnectionInfo*), NULL, NULL, NULL); for (i = 0; i < numConns; i++) { - Connection * conn = in->data.connections->At(in->data.connections, i); + Connection * conn = in->data.connList.connections[i]; ConnectionInfo * connInfo = &conn->info; if (RETURN_ERROR == infos->PushBack(infos, &connInfo)) { object_destroy(infos); @@ -431,8 +435,8 @@ static Vector * ChannelInGetConnectionInfos(ChannelIn * in) { return infos; } -static ObjectContainer * ChannelInGetConnections(ChannelIn * in) { - return in->data.connections; +static ConnectionList * ChannelInGetConnections(ChannelIn * in) { + return &in->data.connList; } static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connection, const char * unit, ChannelType * type) { @@ -440,13 +444,20 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec Channel * channel = (Channel *) in; ChannelInfo * inInfo = &channel->info; ChannelValueReference * valRef = NULL; + ConnectionList * connList = &in->data.connList; McxStatus retVal = RETURN_OK; - retVal = in->data.connections->PushBack(in->data.connections, (Object *) connection); - if (RETURN_OK != retVal) { - return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not register connection"); + while (connList->capacity <= connList->numConnections) { + connList->capacity *= in->data.increment; + connList->connections = mcx_realloc(connList->connections, sizeof(Connection *) * connList->capacity); + if (!connList->connections) { + mcx_log(LOG_ERROR, "ChannelInRegisterConnection: (Re-)Allocation of connections failed"); + return RETURN_ERROR; + } } + connList->connections[connList->numConnections] = connection; + connList->numConnections++; ChannelDimension * dimension = connInfo->targetDimension; if (dimension && !ChannelDimensionEq(dimension, inInfo->dimension)) { diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index ecc8fbd..dd70dc1 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -119,12 +119,19 @@ struct Channel { typedef struct ChannelIn ChannelIn; +typedef struct ConnectionList { + Connection * * connections; // connections (non-overlapping) going into the channel + size_t numConnections; + size_t capacity; +} ConnectionList; + // object that is stored in target component that stores the channel connection typedef struct ChannelInData { - ObjectContainer * connections; // connections (non-overlapping) going into the channel Vector * valueReferences; // references to non-overlapping parts of ChannelData::value, where // values gotten from connections are going to be stored + ConnectionList connList; + size_t increment; // ---------------------------------------------------------------------- // Conversions @@ -151,7 +158,7 @@ typedef McxStatus (* fChannelInSetReference) (ChannelIn * in, typedef struct Vector * (* fChannelInGetConnectionInfos)(ChannelIn * in); -typedef struct ObjectContainer * (* fChannelInGetConnections)(ChannelIn * in); +typedef ConnectionList * (* fChannelInGetConnections)(ChannelIn * in); typedef McxStatus (*fChannelInRegisterConnection)(ChannelIn * in, struct Connection * connection, const char * unit, ChannelType * type); From 486055120902d8e78020dd234b521561fcdc50ce Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Thu, 10 Nov 2022 10:54:46 +0100 Subject: [PATCH 282/295] channel: Reduce redirections of ValueReferences (Performance!) --- src/core/channels/Channel.c | 23 +++++++++-------------- src/core/channels/Channel.h | 6 ++++-- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 01977de..08e67bf 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -169,14 +169,12 @@ static McxStatus ChannelInDataInit(ChannelInData * data) { data->connList.capacity = 1; data->connList.numConnections = 0; - data->valueReferences = (Vector *) object_create(Vector); + data->valueReferences = (ChannelValueReference * *) mcx_malloc(sizeof(ChannelValueReference *)); if (!data->valueReferences) { mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for value references failed"); return RETURN_ERROR; } - data->valueReferences->Setup(data->valueReferences, sizeof(ChannelValueReference *), NULL, NULL, DestroyChannelValueReferencePtr); - data->reference = NULL; data->type = ChannelTypeClone(&ChannelTypeUnknown); if (!data->type) { @@ -220,12 +218,12 @@ static void ChannelInDataDestructor(ChannelInData * data) { ChannelTypeDestructor(data->type); } - if (data->connList.connections) { - mcx_free((void *) data->connList.connections); + if (data->valueReferences) { + mcx_free((void *) data->valueReferences); } - if (data->valueReferences) { - object_destroy(data->valueReferences); + if (data->connList.connections) { + mcx_free((void *) data->connList.connections); } } @@ -296,7 +294,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { ConnectionInfo * connInfo = &conn->info; TypeConversion * typeConv = (TypeConversion *) in->data.typeConversions->At(in->data.typeConversions, i); UnitConversion * unitConv = (UnitConversion *) in->data.unitConversions->At(in->data.unitConversions, i); - ChannelValueReference * valueRef = *(ChannelValueReference **) in->data.valueReferences->At(in->data.valueReferences, i); + ChannelValueReference * valueRef = in->data.valueReferences[i]; /* Update the connection for the current time */ if (RETURN_OK != conn->UpdateToOutput(conn, time)) { @@ -451,7 +449,8 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec while (connList->capacity <= connList->numConnections) { connList->capacity *= in->data.increment; connList->connections = mcx_realloc(connList->connections, sizeof(Connection *) * connList->capacity); - if (!connList->connections) { + in->data.valueReferences = mcx_realloc(in->data.valueReferences, sizeof(ChannelValueReference *) * connList->capacity); + if (!connList->connections || !in->data.valueReferences) { mcx_log(LOG_ERROR, "ChannelInRegisterConnection: (Re-)Allocation of connections failed"); return RETURN_ERROR; } @@ -474,11 +473,7 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec valRef = MakeChannelValueReference(&channel->value, NULL); } - retVal = in->data.valueReferences->PushBack(in->data.valueReferences, &valRef); - if (RETURN_ERROR == retVal) { - ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Storing value reference failed"); - return RETURN_ERROR; - } + in->data.valueReferences[connList->numConnections - 1] = valRef; if (ChannelTypeEq(ChannelTypeBaseType(inInfo->type), &ChannelTypeDouble)) { UnitConversion * conversion = (UnitConversion *) object_create(UnitConversion); diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index dd70dc1..4d77942 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -128,11 +128,13 @@ typedef struct ConnectionList { // object that is stored in target component that stores the channel connection typedef struct ChannelInData { - Vector * valueReferences; // references to non-overlapping parts of ChannelData::value, where - // values gotten from connections are going to be stored ConnectionList connList; size_t increment; + // references to non-overlapping parts of ChannelData::value, where + // values gotten from connections are going to be stored + ChannelValueReference * * valueReferences; + // ---------------------------------------------------------------------- // Conversions From 192ebb12b5625d063449c61179995fe485e7cbf5 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 25 Oct 2022 10:25:24 +0200 Subject: [PATCH 283/295] channel: Reduce redirections of conversions (Performance!) --- src/core/channels/Channel.c | 52 +++++++++++++++++-------------------- src/core/channels/Channel.h | 5 ++-- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 08e67bf..d4b7c18 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -182,12 +182,12 @@ static McxStatus ChannelInDataInit(ChannelInData * data) { return RETURN_ERROR; } - data->typeConversions = (ObjectContainer *) object_create(ObjectContainer); + data->typeConversions = (TypeConversion * *) mcx_malloc(sizeof(TypeConversion *)); if (!data->typeConversions) { mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for type conversion objects failed"); return RETURN_ERROR; } - data->unitConversions = (ObjectContainer *) object_create(ObjectContainer); + data->unitConversions = (UnitConversion * *) mcx_malloc(sizeof(UnitConversion *)); if (!data->unitConversions) { mcx_log(LOG_ERROR, "ChannelInDataInit: Allocating space for unit conversion objects failed"); return RETURN_ERROR; @@ -201,12 +201,6 @@ static McxStatus ChannelInDataInit(ChannelInData * data) { } static void ChannelInDataDestructor(ChannelInData * data) { - // clean up conversion objects - data->typeConversions->DestroyObjects(data->typeConversions); - object_destroy(data->typeConversions); - - data->unitConversions->DestroyObjects(data->unitConversions); - object_destroy(data->unitConversions); if (data->linearConversion) { object_destroy(data->linearConversion); @@ -225,6 +219,18 @@ static void ChannelInDataDestructor(ChannelInData * data) { if (data->connList.connections) { mcx_free((void *) data->connList.connections); } + if (data->typeConversions) { + for (int j = 0; j < data->connList.numConnections; j++) { + object_destroy(data->typeConversions[j]); + } + mcx_free((void *) data->typeConversions); + } + if (data->unitConversions) { + for (int j = 0; j < data->connList.numConnections; j++) { + object_destroy(data->unitConversions[j]); + } + mcx_free((void *) data->unitConversions); + } } static McxStatus ChannelInSetReference(ChannelIn * in, void * reference, ChannelType * type) { @@ -292,8 +298,8 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { for (i = 0; i < numConns; i++) { Connection * conn = (Connection *) in->data.connList.connections[i]; ConnectionInfo * connInfo = &conn->info; - TypeConversion * typeConv = (TypeConversion *) in->data.typeConversions->At(in->data.typeConversions, i); - UnitConversion * unitConv = (UnitConversion *) in->data.unitConversions->At(in->data.unitConversions, i); + TypeConversion * typeConv = in->data.typeConversions[i]; + UnitConversion * unitConv = in->data.unitConversions[i]; ChannelValueReference * valueRef = in->data.valueReferences[i]; /* Update the connection for the current time */ @@ -449,9 +455,11 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec while (connList->capacity <= connList->numConnections) { connList->capacity *= in->data.increment; connList->connections = mcx_realloc(connList->connections, sizeof(Connection *) * connList->capacity); + in->data.typeConversions = mcx_realloc(in->data.typeConversions, sizeof(TypeConversion *) * connList->capacity); + in->data.unitConversions = mcx_realloc(in->data.unitConversions, sizeof(UnitConversion *) * connList->capacity); in->data.valueReferences = mcx_realloc(in->data.valueReferences, sizeof(ChannelValueReference *) * connList->capacity); - if (!connList->connections || !in->data.valueReferences) { - mcx_log(LOG_ERROR, "ChannelInRegisterConnection: (Re-)Allocation of connections failed"); + if (!connList->connections || !in->data.typeConversions || !in->data.unitConversions || !in->data.valueReferences) { + mcx_log(LOG_ERROR, "ChannelInRegisterConnection: (Re-)Allocation of connection related data failed"); return RETURN_ERROR; } } @@ -487,15 +495,9 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec object_destroy(conversion); } - retVal = in->data.unitConversions->PushBack(in->data.unitConversions, (Object *) conversion); - if (RETURN_ERROR == retVal) { - return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add unit conversion"); - } + in->data.unitConversions[connList->numConnections - 1] = conversion; } else { - retVal = in->data.unitConversions->PushBack(in->data.unitConversions, NULL); - if (RETURN_ERROR == retVal) { - return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add empty unit conversion"); - } + in->data.unitConversions[connList->numConnections - 1] = NULL; } // setup type conversion @@ -510,15 +512,9 @@ static McxStatus ChannelInRegisterConnection(ChannelIn * in, Connection * connec return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not set up type conversion"); } - retVal = in->data.typeConversions->PushBack(in->data.typeConversions, (Object *) typeConv); - if (RETURN_ERROR == retVal) { - return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add type conversion"); - } + in->data.typeConversions[connList->numConnections - 1] = typeConv; } else { - retVal = in->data.typeConversions->PushBack(in->data.typeConversions, NULL); - if (RETURN_ERROR == retVal) { - return ReportConnStringError(inInfo, "Register inport connection %s: ", connInfo, "Could not add empty type conversion"); - } + in->data.typeConversions[connList->numConnections - 1] = NULL; } return retVal; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index 4d77942..7ab78f8 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -137,11 +137,10 @@ typedef struct ChannelInData { // ---------------------------------------------------------------------- // Conversions - - ObjectContainer * typeConversions; // conversion objects (or NULL) for each connection in `connections` - ObjectContainer * unitConversions; // conversion objects (or NULL) for each connection in `connections` struct LinearConversion * linearConversion; struct RangeConversion * rangeConversion; + TypeConversion * * typeConversions; // conversion objects (or NULL) for each connection in `connections` + UnitConversion * * unitConversions; // conversion objects (or NULL) for each connection in `connections` // ---------------------------------------------------------------------- // Storage in Component From 1f65e6c0f8e431756e02df39d77147b4fe53f824 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 25 Oct 2022 10:28:49 +0200 Subject: [PATCH 284/295] channel: Reduce redirections of out connections (Performance!) --- src/core/Component.c | 28 +++++++--------- src/core/Databus.c | 10 +++--- src/core/Model.c | 12 +++---- src/core/channels/Channel.c | 64 ++++++++++++++++++++++++------------- src/core/channels/Channel.h | 5 +-- 5 files changed, 68 insertions(+), 51 deletions(-) diff --git a/src/core/Component.c b/src/core/Component.c index 0efac54..305fee5 100644 --- a/src/core/Component.c +++ b/src/core/Component.c @@ -972,11 +972,10 @@ static ObjectList * ComponentGetConnections(Component * fromComp, Component * to for (i = 0; i < DatabusGetOutChannelsNum(db); i++) { ChannelOut * out = DatabusGetOutChannel(db, i); - ObjectList * conns = out->GetConnections(out); - size_t connSize = conns->Size(conns); + ConnectionList * conns = out->GetConnections(out); - for (j = 0; j < connSize; j++) { - Connection * conn = (Connection *) conns->At(conns, j); + for (j = 0; j < conns->numConnections; j++) { + Connection * conn = conns->connections[j]; ConnectionInfo * info = conn->GetInfo(conn); if (info->targetComponent == toComp) { @@ -1014,11 +1013,10 @@ McxStatus ComponentOutConnectionsEnterInitMode(Component * comp) { for (i = 0; i < numOutChannels; i++) { ChannelOut * out = DatabusGetOutChannel(db, i); - ObjectList * conns = out->GetConnections(out); - size_t connSize = conns->Size(conns); + ConnectionList * conns = out->GetConnections(out); - for (j = 0; j < connSize; j++) { - Connection * connection = (Connection *) conns->At(conns, j); + for (j = 0; j < conns->numConnections; j++) { + Connection * connection = conns->connections[j]; retVal = connection->EnterInitializationMode(connection); if (RETURN_OK != retVal) { // error message in calling function return RETURN_ERROR; @@ -1035,11 +1033,10 @@ McxStatus ComponentDoOutConnectionsInitialization(Component * comp, int onlyIfDe for (i = 0; i < numOutChannels; i++) { ChannelOut * out = DatabusGetOutChannel(db, i); - ObjectList * conns = out->GetConnections(out); - size_t connSize = conns->Size(conns); + ConnectionList * conns = out->GetConnections(out); - for (j = 0; j < connSize; j++) { - Connection * connection = (Connection *) conns->At(conns, j); + for (j = 0; j < conns->numConnections; j++) { + Connection * connection = conns->connections[j]; if (!onlyIfDecoupled || connection->IsDecoupled(connection)) { McxStatus retVal = connection->UpdateInitialValue(connection); @@ -1063,11 +1060,10 @@ McxStatus ComponentOutConnectionsExitInitMode(Component * comp, double time) { for (i = 0; i < numOutChannels; i++) { ChannelOut * out = DatabusGetOutChannel(db, i); - ObjectList * conns = out->GetConnections(out); - size_t connSize = conns->Size(conns); + ConnectionList * conns = out->GetConnections(out); - for (j = 0; j < connSize; j++) { - Connection * connection = (Connection *) conns->At(conns, j); + for (j = 0; j < conns->numConnections; j++) { + Connection * connection = conns->connections[j]; retVal = connection->ExitInitializationMode(connection, time); if (RETURN_OK != retVal) { // error message in calling function return RETURN_ERROR; diff --git a/src/core/Databus.c b/src/core/Databus.c index 4385837..7e920e7 100644 --- a/src/core/Databus.c +++ b/src/core/Databus.c @@ -1303,8 +1303,8 @@ McxStatus DatabusCollectModeSwitchData(Databus * db) { // determine cache size for (i = 0; i < size; i++) { ChannelOut * out = db->data->out[i]; - ObjectList * conns = out->GetConnections(out); - db->modeSwitchDataSize += conns->Size(conns); + ConnectionList * conns = out->GetConnections(out); + db->modeSwitchDataSize += conns->numConnections; } // allocate cache @@ -1316,11 +1316,11 @@ McxStatus DatabusCollectModeSwitchData(Databus * db) { // 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); + ConnectionList * conns = out->GetConnections(out); + size_t connSize = conns->numConnections; for (j = 0; j < connSize; j++, idx++) { - Connection * connection = (Connection*)conns->At(conns, j); + Connection * connection = conns->connections[j]; ConnectionInfo * info = connection->GetInfo(connection); Component * target = info->targetComponent; Component * source = info->sourceComponent; diff --git a/src/core/Model.c b/src/core/Model.c index 12321cb..2b138a8 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -447,10 +447,10 @@ static McxStatus ModelInsertAllFilters(Model * model) { for (j = 0; j < numOutChannels; j++) { ChannelOut * out = DatabusGetOutChannel(db, j); - ObjectList * conns = out->GetConnections(out); + ConnectionList * conns = out->GetConnections(out); - for (k = 0; k < conns->Size(conns); k++) { - Connection * connection = (Connection *) conns->At(conns, k); + for (k = 0; k < conns->numConnections; k++) { + Connection * connection = conns->connections[k]; ConnectionInfo * info = connection->GetInfo(connection); if (connection->AddFilter) { char * connStr = ConnectionInfoConnectionString(info); @@ -700,10 +700,10 @@ static Connection * ModelGetConnectionFromInfo(Model * model, ConnectionInfo * i for (j = 0; j < numOutChannels; j++) { ChannelOut * out = DatabusGetOutChannel(db, j); - ObjectList * conns = out->GetConnections(out); + ConnectionList * conns = out->GetConnections(out); - for (k = 0; k < conns->Size(conns); k++) { - Connection * connection = (Connection *) conns->At(conns, k); + for (k = 0; k < conns->numConnections; k++) { + Connection * connection = conns->connections[k]; if (connection->GetInfo(connection) == info) { return connection; } diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index d4b7c18..efd1166 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -638,7 +638,15 @@ static McxStatus ChannelOutDataInit(ChannelOutData * data) { data->rangeConversionIsActive = TRUE; - data->connections = (ObjectList *) object_create(ObjectList); + data->increment = 2; + + data->connList.numConnections = 0; + data->connList.capacity = 1; + data->connList.connections = (Connection * *) mcx_malloc(sizeof(Connection *)); + if (!data->connList.connections) { + mcx_log(LOG_ERROR, "ChannelOutDataInit: Allocation of connections failed"); + return RETURN_ERROR; + } data->nanCheck = NAN_CHECK_ALWAYS; @@ -650,7 +658,6 @@ static McxStatus ChannelOutDataInit(ChannelOutData * data) { } static void ChannelOutDataDestructor(ChannelOutData * data) { - ObjectList * conns = data->connections; size_t i = 0; if (data->rangeConversion) { @@ -660,10 +667,14 @@ static void ChannelOutDataDestructor(ChannelOutData * data) { object_destroy(data->linearConversion); } - for (i = 0; i < conns->Size(conns); i++) { - object_destroy(conns->elements[i]); + if (data->connList.connections) { + for (i = 0; i < data->connList.numConnections; i++) { + if (data->connList.connections[i]) { + object_destroy(data->connList.connections[i]); + } + } + mcx_free(data->connList.connections); } - object_destroy(data->connections); ChannelValueDestructor(&data->valueFunctionRes); } @@ -735,12 +746,24 @@ static McxStatus ChannelOutSetup(ChannelOut * out, ChannelInfo * info, Config * } static McxStatus ChannelOutRegisterConnection(ChannelOut * out, Connection * connection) { - ObjectList * conns = out->data->connections; + ChannelInfo * outInfo = &((Channel *) out)->info; + ConnectionInfo * connInfo = &connection->info; + ConnectionList * connList = &out->data.connList; // TODO: do we have to check that channelout and connection match // in type/dimension? - return conns->PushBack(conns, (Object *) connection); + while (connList->capacity <= connList->numConnections) { + connList->capacity *= out->data.increment; + connList->connections = mcx_realloc(connList->connections, connList->capacity * sizeof(Connection *)); + if (!connList->connections) { + return ReportConnStringError(outInfo, "Register outport connection %s: ", connInfo, "Could not set up connections (realloc failed)"); + } + } + connList->connections[connList->numConnections] = connection; + connList->numConnections++; + + return RETURN_OK; } static const void * ChannelOutGetValueReference(Channel * channel) { @@ -760,8 +783,8 @@ static const proc * ChannelOutGetFunction(ChannelOut * out) { return out->data.valueFunction; } -static ObjectList * ChannelOutGetConnections(ChannelOut * out) { - return out->data.connections; +static ConnectionList * ChannelOutGetConnections(ChannelOut * out) { + return &out->data.connList; } static int ChannelOutProvidesValue(Channel * channel) { @@ -773,10 +796,8 @@ static int ChannelOutIsConnected(Channel * channel) { return TRUE; } else { ChannelOut * out = (ChannelOut *) channel; - if (NULL != out->data.connections) { - if (out->data.connections->Size(out->data.connections)) { - return TRUE; - } + if (out->data.connList.numConnections) { + return TRUE; } } @@ -787,7 +808,7 @@ static int ChannelOutIsFullyConnected(Channel * channel) { ChannelOut * out = (ChannelOut *) channel; if (ChannelTypeIsArray(&channel->info.type)) { - ObjectList* conns = out->data.connections; + ConnectionList * conns = &out->data.connList; size_t i = 0; size_t num_elems = ChannelDimensionNumElements(channel->info.dimension); @@ -797,8 +818,8 @@ static int ChannelOutIsFullyConnected(Channel * channel) { return -1; } - for (i = 0; i < conns->Size(conns); i++) { - Connection * conn = (Connection *) out->data.connections->At(out->data.connections, i); + for (i = 0; i < conns->numConnections; i++) { + Connection * conn = out->data.connList.connections[i]; ConnectionInfo * info = &conn->info; size_t j = 0; @@ -907,7 +928,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ChannelOut * out = (ChannelOut *)channel; ChannelInfo * info = &channel->info; - ObjectList * conns = out->data.connections; + ConnectionList * conns = &out->data.connList; McxStatus retVal = RETURN_OK; @@ -984,9 +1005,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // Notify connections of new values - size_t connSize = conns->Size(conns); - for (j = 0; j < connSize; j++) { - Connection * connection = (Connection *) conns->At(conns, j); + for (j = 0; j < conns->numConnections; j++) { + Connection * connection = conns->connections[j]; channel->SetDefinedDuringInit(channel); connection->UpdateFromInput(connection, time); } @@ -1010,7 +1030,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { return RETURN_ERROR; case NAN_CHECK_CONNECTED: - if (conns->Size(conns) > 0) { + if (conns->numConnections > 0) { mcx_log(LOG_ERROR, "Outport %s at time %f is not a number (NaN)", ChannelInfoGetName(info), time->startTime); return RETURN_ERROR; @@ -1020,7 +1040,7 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } case NAN_CHECK_NEVER: - WarnAboutNaN((conns->Size(conns) > 0) ? LOG_ERROR : LOG_WARNING, + WarnAboutNaN((conns->numConnections > 0) ? LOG_ERROR : LOG_WARNING, info, time, &out->data.countNaNCheckWarning, &out->data.maxNumNaNCheckWarning); break; } diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index 7ab78f8..a9e19d9 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -246,7 +246,8 @@ typedef struct ChannelOutData { // Connections to Consumers // A list of all input channels that are connected to this output channel - ObjectList * connections; + ConnectionList connList; + size_t increment; } ChannelOutData; @@ -266,7 +267,7 @@ typedef McxStatus (* fChannelOutRegisterConnection)(struct ChannelOut * out, typedef const proc * (* fChannelOutGetFunction)(ChannelOut * out); -typedef ObjectList * (* fChannelOutGetConnections)(ChannelOut * out); +typedef ConnectionList * (* fChannelOutGetConnections)(ChannelOut * out); extern const struct ObjectClass _ChannelOut; From 605e6677b95cfaf6ee7a50c1b3251b4d395c257a Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 25 Oct 2022 10:30:41 +0200 Subject: [PATCH 285/295] channel: Fix datatype of function argument --- src/core/channels/Channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index efd1166..36a8aef 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -807,7 +807,7 @@ static int ChannelOutIsConnected(Channel * channel) { static int ChannelOutIsFullyConnected(Channel * channel) { ChannelOut * out = (ChannelOut *) channel; - if (ChannelTypeIsArray(&channel->info.type)) { + if (ChannelTypeIsArray(channel->info.type)) { ConnectionList * conns = &out->data.connList; size_t i = 0; size_t num_elems = ChannelDimensionNumElements(channel->info.dimension); From ef92ee2db220843d053ddd29c71fab461e890f81 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Tue, 25 Oct 2022 16:40:15 +0200 Subject: [PATCH 286/295] connection: Inline FilteredConnectionData (Performance!) --- src/core/connections/FilteredConnection.c | 71 ++++++++++--------- src/core/connections/FilteredConnection.h | 17 ++++- .../connections/FilteredConnection_impl.h | 43 ----------- 3 files changed, 52 insertions(+), 79 deletions(-) delete mode 100644 src/core/connections/FilteredConnection_impl.h diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index 83ec282..c4319a1 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -9,7 +9,6 @@ ********************************************************************************/ #include "core/connections/FilteredConnection.h" -#include "core/connections/FilteredConnection_impl.h" #include "core/connections/Connection.h" #include "core/connections/ConnectionInfo.h" #include "core/channels/Channel.h" @@ -20,14 +19,14 @@ extern "C" { #endif /* __cplusplus */ -static FilteredConnectionData * FilteredConnectionDataCreate(FilteredConnectionData * data) { +static McxStatus FilteredConnectionDataInit(FilteredConnectionData * data) { data->filters = NULL; data->numFilters = 0; ChannelValueInit(&data->updateBuffer, ChannelTypeClone(&ChannelTypeUnknown)); ChannelValueInit(&data->store, ChannelTypeClone(&ChannelTypeUnknown)); - return data; + return RETURN_OK; } static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { @@ -43,9 +42,6 @@ static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { } } -OBJECT_CLASS(FilteredConnectionData, Object); - - static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * out, ChannelIn * in, ConnectionInfo * info) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; @@ -63,8 +59,8 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o } // filter will be added after model is connected - filteredConnection->data->filters = NULL; - filteredConnection->data->numFilters = 0; + filteredConnection->data.filters = NULL; + filteredConnection->data.numFilters = 0; storeType = ChannelTypeFromDimension(sourceInfo->type, info->sourceDimension); if (!storeType) { @@ -72,13 +68,13 @@ static McxStatus FilteredConnectionSetup(Connection * connection, ChannelOut * o } // value store - ChannelValueInit(&filteredConnection->data->store, storeType); // steals ownership of storeType -> no clone needed + ChannelValueInit(&filteredConnection->data.store, storeType); // steals ownership of storeType -> no clone needed // value reference - connection->value_ = ChannelValueDataPointer(&filteredConnection->data->store); + connection->value_ = ChannelValueDataPointer(&filteredConnection->data.store); // initialize the buffer for channel function calls - ChannelValueInit(&filteredConnection->data->updateBuffer, ChannelTypeClone(storeType)); + ChannelValueInit(&filteredConnection->data.updateBuffer, ChannelTypeClone(storeType)); // Connection::Setup() // this has to be done last as it connects the channels @@ -96,7 +92,7 @@ static McxStatus FilteredConnectionEnterCommunicationMode(Connection * connectio McxStatus retVal = RETURN_OK; size_t i = 0; - for (i = 0; i < filteredConnection->data->numFilters; i++) { + for (i = 0; i < filteredConnection->data.numFilters; i++) { ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, i); if (filter) { if (filter->EnterCommunicationMode) { @@ -120,7 +116,7 @@ static McxStatus FilteredConnectionEnterCouplingStepMode(Connection * connection McxStatus retVal = RETURN_OK; size_t i = 0; - for (i = 0; i < filteredConnection->data->numFilters; i++) { + for (i = 0; i < filteredConnection->data.numFilters; i++) { ChannelFilter * filter = filteredConnection->GetWriteFilter(filteredConnection, i); if (filter) { if (filter->EnterCouplingStepMode) { @@ -137,18 +133,18 @@ static McxStatus FilteredConnectionEnterCouplingStepMode(Connection * connection } static ChannelFilter * FilteredConnectionGetFilter(FilteredConnection * connection, size_t idx) { - if (connection->data->filters && idx < connection->data->numFilters) { - return connection->data->filters[idx]; + if (connection->data.filters && idx < connection->data.numFilters) { + return connection->data.filters[idx]; } return NULL; } static size_t FilteredConnectionGetNumFilters(FilteredConnection *connection) { - return connection->data->numFilters; + return connection->data.numFilters; } static McxStatus FilteredConnectionSetResult(FilteredConnection * connection, const void * value) { - return ChannelValueSetFromReference(&connection->data->store, value); + return ChannelValueSetFromReference(&connection->data.store, value); } static size_t GetSliceShift(Connection * connection) { @@ -217,12 +213,12 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI proc * p = (proc *) out->GetFunction(out); // TODO: Update functions to only update the slices ? - if (RETURN_ERROR == p->fn(time, p->env, &filteredConnection->data->updateBuffer)) { + if (RETURN_ERROR == p->fn(time, p->env, &filteredConnection->data.updateBuffer)) { mcx_log(LOG_ERROR, "FilteredConnection: Function failed"); return RETURN_ERROR; } - if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueDataPointer(&filteredConnection->data->updateBuffer))) { + if (RETURN_OK != filteredConnection->SetResult(filteredConnection, ChannelValueDataPointer(&filteredConnection->data.updateBuffer))) { mcx_log(LOG_ERROR, "FilteredConnection: SetResult failed"); return RETURN_ERROR; } @@ -244,7 +240,7 @@ static McxStatus FilteredConnectionUpdateToOutput(Connection * connection, TimeI size_t numFilters = FilteredConnectionGetNumFilters(filteredConnection); ChannelType * type = info->type; - mcx_array * elements = (mcx_array *) ChannelValueDataPointer(&filteredConnection->data->updateBuffer); + mcx_array * elements = (mcx_array *) ChannelValueDataPointer(&filteredConnection->data.updateBuffer); char * dest = (char *) elements->data; for (i = 0; i < numFilters; i++) { filter = filteredConnection->GetReadFilter(filteredConnection, i); @@ -271,7 +267,7 @@ static McxStatus AddFilter(Connection * connection) { McxStatus retVal = RETURN_OK; - if (filteredConnection->data->filters) { + if (filteredConnection->data.filters) { mcx_log(LOG_DEBUG, "Connection: Not inserting filter"); } else { ConnectionInfo * info = connection->GetInfo(connection); @@ -287,16 +283,16 @@ static McxStatus AddFilter(Connection * connection) { goto cleanup; } - filteredConnection->data->numFilters = dimension->endIdxs[0] - dimension->startIdxs[0] + 1; - filteredConnection->data->filters = (ChannelFilter **) mcx_calloc(filteredConnection->data->numFilters, sizeof(ChannelFilter*)); - if (!filteredConnection->data->filters) { + filteredConnection->data.numFilters = dimension->endIdxs[0] - dimension->startIdxs[0] + 1; + filteredConnection->data.filters = (ChannelFilter **) mcx_calloc(filteredConnection->data.numFilters, sizeof(ChannelFilter*)); + if (!filteredConnection->data.filters) { mcx_log(LOG_ERROR, "Creating array filters failed: no memory"); retVal = RETURN_ERROR; goto cleanup; } - for (i = 0; i < filteredConnection->data->numFilters; i++) { - filteredConnection->data->filters[i] = FilterFactory(&connection->state_, + for (i = 0; i < filteredConnection->data.numFilters; i++) { + filteredConnection->data.filters[i] = FilterFactory(&connection->state_, info->interExtrapolationType, &info->interExtrapolationParams, ChannelTypeBaseType(ConnectionInfoGetType(info)), @@ -305,22 +301,22 @@ static McxStatus AddFilter(Connection * connection) { info->sourceComponent, info->targetComponent, connString); - if (NULL == filteredConnection->data->filters[i]) { + if (NULL == filteredConnection->data.filters[i]) { mcx_log(LOG_DEBUG, "Connection: Array filter creation failed for index %zu", i); retVal = RETURN_ERROR; goto cleanup; } } } else { - filteredConnection->data->filters = (ChannelFilter **) mcx_calloc(1, sizeof(ChannelFilter *)); - if (!filteredConnection->data->filters) { + filteredConnection->data.filters = (ChannelFilter **) mcx_calloc(1, sizeof(ChannelFilter *)); + if (!filteredConnection->data.filters) { mcx_log(LOG_ERROR, "Creating filter failed: no memory"); retVal = RETURN_ERROR; goto cleanup; } - filteredConnection->data->numFilters = 1; - filteredConnection->data->filters[0] = FilterFactory(&connection->state_, + filteredConnection->data.numFilters = 1; + filteredConnection->data.filters[0] = FilterFactory(&connection->state_, info->interExtrapolationType, &info->interExtrapolationParams, ConnectionInfoGetType(info), @@ -329,7 +325,7 @@ static McxStatus AddFilter(Connection * connection) { info->sourceComponent, info->targetComponent, connString); - if (NULL == filteredConnection->data->filters[0]) { + if (NULL == filteredConnection->data.filters[0]) { mcx_log(LOG_DEBUG, "Connection: No Filter created"); retVal = RETURN_ERROR; goto cleanup; @@ -348,15 +344,16 @@ static McxStatus AddFilter(Connection * connection) { static ChannelType * FilteredConnectionGetValueType(Connection * connection) { FilteredConnection * filteredConnection = (FilteredConnection *) connection; - return filteredConnection->data->store.type; + return filteredConnection->data.store.type; } static void FilteredConnectionDestructor(FilteredConnection * filteredConnection) { - object_destroy(filteredConnection->data); + FilteredConnectionDataDestructor(&filteredConnection->data); } static FilteredConnection * FilteredConnectionCreate(FilteredConnection * filteredConnection) { Connection * connection = (Connection *) filteredConnection; + McxStatus retVal = RETURN_OK; connection->Setup = FilteredConnectionSetup; connection->UpdateFromInput = FilteredConnectionUpdateFromInput; @@ -373,7 +370,11 @@ static FilteredConnection * FilteredConnectionCreate(FilteredConnection * filter filteredConnection->SetResult = FilteredConnectionSetResult; - filteredConnection->data = (FilteredConnectionData *) object_create(FilteredConnectionData); + retVal = FilteredConnectionDataInit(&filteredConnection->data); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "FilteredConnectionCreate: FilteredConnectionDataInit failed"); + return NULL; + } return filteredConnection; } diff --git a/src/core/connections/FilteredConnection.h b/src/core/connections/FilteredConnection.h index 01f0f4e..b75e641 100644 --- a/src/core/connections/FilteredConnection.h +++ b/src/core/connections/FilteredConnection.h @@ -13,11 +13,26 @@ #include "core/connections/Connection.h" #include "core/Conversion.h" +#include "core/channels/ChannelValue.h" +#include "core/connections/filters/Filter.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +typedef struct FilteredConnectionData { + + // storage of the filtered value provided by the output channel + ChannelValue store; + + // storage for temporary results during out channel updates + ChannelValue updateBuffer; + + ChannelFilter ** filters; + size_t numFilters; + +} FilteredConnectionData; + typedef struct FilteredConnection FilteredConnection; typedef struct ChannelFilter * (* fConnectionGetFilter)(FilteredConnection * connection, size_t idx); @@ -34,7 +49,7 @@ struct FilteredConnection { fFilteredConnectionSetResult SetResult; - struct FilteredConnectionData * data; + FilteredConnectionData data; } ; #ifdef __cplusplus diff --git a/src/core/connections/FilteredConnection_impl.h b/src/core/connections/FilteredConnection_impl.h deleted file mode 100644 index 8071a00..0000000 --- a/src/core/connections/FilteredConnection_impl.h +++ /dev/null @@ -1,43 +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_FILTEREDCONNECTIONDATA_H -#define MCX_CORE_CONNECTIONS_FILTEREDCONNECTIONDATA_H - -#include "core/Conversion.h" - -// for ExtrapolType -#include "core/connections/filters/Filter.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -extern const struct ObjectClass _FilteredConnectionData; - -typedef struct FilteredConnectionData { - Object _; /* super class */ - - // storage of the filtered value provided by the output channel - ChannelValue store; - - // storage for temporary results during out channel updates - ChannelValue updateBuffer; - - ChannelFilter ** filters; - size_t numFilters; - -} FilteredConnectionData; - -#ifdef __cplusplus -} /* closing brace for extern "C" */ -#endif /* __cplusplus */ - -#endif /* MCX_CORE_CONNECTIONS_FILTEREDCONNECTIONDATA_H */ \ No newline at end of file From fb198e000b623c6acf0dd69ea050f1d8f4a2447e Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Thu, 27 Oct 2022 15:30:59 +0200 Subject: [PATCH 287/295] FilteredConnection: Store single filter pointer directly (Performance!) --- src/core/connections/FilteredConnection.c | 33 +++++++++++------------ src/core/connections/FilteredConnection.h | 1 + 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/core/connections/FilteredConnection.c b/src/core/connections/FilteredConnection.c index c4319a1..dfa516a 100644 --- a/src/core/connections/FilteredConnection.c +++ b/src/core/connections/FilteredConnection.c @@ -21,6 +21,7 @@ extern "C" { static McxStatus FilteredConnectionDataInit(FilteredConnectionData * data) { data->filters = NULL; + data->_filter = NULL; data->numFilters = 0; ChannelValueInit(&data->updateBuffer, ChannelTypeClone(&ChannelTypeUnknown)); @@ -38,7 +39,9 @@ static void FilteredConnectionDataDestructor(FilteredConnectionData * data) { for (i = 0; i < data->numFilters; i++) { object_destroy(data->filters[i]); } - mcx_free(data->filters); + if (data->numFilters != 1) { + mcx_free(data->filters); + } } } @@ -308,28 +311,22 @@ static McxStatus AddFilter(Connection * connection) { } } } else { - filteredConnection->data.filters = (ChannelFilter **) mcx_calloc(1, sizeof(ChannelFilter *)); - if (!filteredConnection->data.filters) { - mcx_log(LOG_ERROR, "Creating filter failed: no memory"); - retVal = RETURN_ERROR; - goto cleanup; - } - filteredConnection->data.numFilters = 1; - filteredConnection->data.filters[0] = FilterFactory(&connection->state_, - info->interExtrapolationType, - &info->interExtrapolationParams, - ConnectionInfoGetType(info), - info->isInterExtrapolating, - ConnectionInfoIsDecoupled(info), - info->sourceComponent, - info->targetComponent, - connString); - if (NULL == filteredConnection->data.filters[0]) { + filteredConnection->data._filter = FilterFactory(&connection->state_, + info->interExtrapolationType, + &info->interExtrapolationParams, + ConnectionInfoGetType(info), + info->isInterExtrapolating, + ConnectionInfoIsDecoupled(info), + info->sourceComponent, + info->targetComponent, + connString); + if (NULL == filteredConnection->data._filter) { mcx_log(LOG_DEBUG, "Connection: No Filter created"); retVal = RETURN_ERROR; goto cleanup; } + filteredConnection->data.filters = &filteredConnection->data._filter; } cleanup: diff --git a/src/core/connections/FilteredConnection.h b/src/core/connections/FilteredConnection.h index b75e641..8a6f546 100644 --- a/src/core/connections/FilteredConnection.h +++ b/src/core/connections/FilteredConnection.h @@ -29,6 +29,7 @@ typedef struct FilteredConnectionData { ChannelValue updateBuffer; ChannelFilter ** filters; + ChannelFilter * _filter; size_t numFilters; } FilteredConnectionData; From 189ca7d2d1b715c1181640120c5b08c510849d72 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Fri, 28 Oct 2022 16:48:43 +0200 Subject: [PATCH 288/295] channel: Write message only in debug (Performance!) --- src/core/channels/Channel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 36a8aef..3765fe6 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -352,9 +352,11 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } +#ifdef MCX_DEBUG if (time->startTime < MCX_DEBUG_LOG_TIME && ChannelTypeEq(info->type, &ChannelTypeDouble)) { MCX_DEBUG_LOG("[%f] CH IN (%s) (%f, %f)", time->startTime, ChannelInfoGetLogName(info), time->startTime, * (double *) channel->GetValueReference(channel)); } +#endif // MCX_DEBUG if (RETURN_OK != ChannelValueDataSetFromReference(in->data.reference, in->data.type, channel->GetValueReference(channel))) { return RETURN_ERROR; From 5bc072825dcb43d70fb2cf29b576f5a88127f066 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Wed, 2 Nov 2022 13:28:40 +0100 Subject: [PATCH 289/295] Fmu2: Create separate SetVariable for Init (Performance!) --- src/components/comp_fmu.c | 10 +++++----- src/core/channels/Channel.c | 2 +- src/fmu/common_fmu2.c | 39 ++++++++++++++++++++++++++++++++----- src/fmu/common_fmu2.h | 2 ++ 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/components/comp_fmu.c b/src/components/comp_fmu.c index 2024c88..8b8cfff 100644 --- a/src/components/comp_fmu.c +++ b/src/components/comp_fmu.c @@ -871,19 +871,19 @@ static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime McxStatus retVal = RETURN_OK; // Set variables - retVal = Fmu2SetVariableArray(fmu2, fmu2->params); + retVal = Fmu2SetVariableArrayInitialize(fmu2, fmu2->params); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Setting params failed"); return RETURN_ERROR; } - retVal = Fmu2SetVariableArray(fmu2, fmu2->initialValues); + retVal = Fmu2SetVariableArrayInitialize(fmu2, fmu2->initialValues); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Setting initialValues failed"); return RETURN_ERROR; } - retVal = Fmu2SetVariableArray(fmu2, fmu2->in); + retVal = Fmu2SetVariableArrayInitialize(fmu2, fmu2->in); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Setting inChannels failed"); return RETURN_ERROR; @@ -916,13 +916,13 @@ static McxStatus Fmu2Initialize(Component * comp, size_t group, double startTime } // Set variables - retVal = Fmu2SetVariableArray(fmu2, fmu2->initialValues); + retVal = Fmu2SetVariableArrayInitialize(fmu2, fmu2->initialValues); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Setting initialValues failed"); return RETURN_ERROR; } - retVal = Fmu2SetVariableArray(fmu2, fmu2->in); + retVal = Fmu2SetVariableArrayInitialize(fmu2, fmu2->in); if (RETURN_OK != retVal) { ComponentLog(comp, LOG_ERROR, "Setting inChannels failed"); return RETURN_ERROR; diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 3765fe6..b68cb7a 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -1007,9 +1007,9 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } // Notify connections of new values + channel->SetDefinedDuringInit(channel); for (j = 0; j < conns->numConnections; j++) { Connection * connection = conns->connections[j]; - channel->SetDefinedDuringInit(channel); connection->UpdateFromInput(connection, time); } } diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index 5484fee..b94e0d3 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -1010,11 +1010,8 @@ McxStatus Fmu2SetDependencies(Fmu2CommonStruct * fmu2, Databus * db, Dependencie } -// TODO: move into fmu2value? -McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { - fmi2_status_t status = fmi2_status_ok; - - char * const name = fmuVal->name; +McxStatus Fmu2SetVariableInitialize(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { + McxStatus status = RETURN_OK; Channel * channel = fmuVal->channel; if (channel && FALSE == channel->IsDefinedDuringInit(channel)) { @@ -1022,6 +1019,15 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { return RETURN_OK; } + return Fmu2SetVariable(fmu, fmuVal); +} + +// TODO: move into fmu2value? +McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { + fmi2_status_t status = fmi2_status_ok; + + char * const name = fmuVal->name; + ChannelValue * const chVal = &fmuVal->val; ChannelType * type = ChannelValueType(chVal); @@ -1145,6 +1151,29 @@ McxStatus Fmu2SetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals) { return RETURN_OK; } +McxStatus Fmu2SetVariableArrayInitialize(Fmu2CommonStruct * fmu, ObjectContainer * vals) { + size_t i = 0; + size_t numVars = vals->Size(vals); + + McxStatus retVal = RETURN_OK; + + mcx_signal_handler_set_this_function(); + + for (i = 0; i < numVars; i++) { + Fmu2Value * const fmuVal = (Fmu2Value *) vals->At(vals, i); + + retVal = Fmu2SetVariableInitialize(fmu, fmuVal); + if (RETURN_ERROR == retVal) { + mcx_signal_handler_unset_function(); + return RETURN_ERROR; + } + } + + mcx_signal_handler_unset_function(); + + return RETURN_OK; +} + McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { fmi2_status_t status = fmi2_status_ok; diff --git a/src/fmu/common_fmu2.h b/src/fmu/common_fmu2.h index 5b19e8a..9624941 100644 --- a/src/fmu/common_fmu2.h +++ b/src/fmu/common_fmu2.h @@ -37,9 +37,11 @@ McxStatus Fmu2ReadParams(ObjectContainer * params, ObjectContainer * arrayParams McxStatus Fmu2SetDependencies(Fmu2CommonStruct * fmu2, Databus * db, Dependencies * deps, int init); // TODO: rename all variablearrays to something better +McxStatus Fmu2SetVariableArrayInitialize(Fmu2CommonStruct * fmu, ObjectContainer * vals); McxStatus Fmu2SetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals); McxStatus Fmu2GetVariableArray(Fmu2CommonStruct * fmu, ObjectContainer * vals); +McxStatus Fmu2SetVariableInitialize(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal); McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal); McxStatus Fmu2GetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal); From 42d3a1aa63dcc0e8a9b68c834d681f824e8a5d7a Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Mon, 31 Oct 2022 11:37:50 +0100 Subject: [PATCH 290/295] channel: Skip unnecessary type checks (Performance!) --- src/core/channels/Channel.c | 38 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index b68cb7a..6f1be09 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -932,6 +932,8 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { ConnectionList * conns = &out->data.connList; + ChannelValue * val = NULL; + McxStatus retVal = RETURN_OK; time->endTime = time->startTime; @@ -978,34 +980,30 @@ static McxStatus ChannelOutUpdate(Channel * channel, TimeInterval * time) { } } - // Apply conversion - if (ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeDouble) || - ChannelTypeEq(ChannelTypeBaseType(info->type), &ChannelTypeInteger)) { - ChannelValue * val = &channel->value; - - // range - if (out->data.rangeConversion) { - if (out->data.rangeConversionIsActive) { - 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", ChannelInfoGetLogName(info)); - return RETURN_ERROR; - } - } - } + val = &channel->value; - // linear - if (out->data.linearConversion) { - Conversion * conversion = (Conversion *) out->data.linearConversion; + // range conversion + if (out->data.rangeConversion) { + if (out->data.rangeConversionIsActive) { + 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 linear conversion", ChannelInfoGetLogName(info)); + mcx_log(LOG_ERROR, "Port %s: Update outport: Could not execute range conversion", ChannelInfoGetLogName(info)); return RETURN_ERROR; } } } + // linear conversion + if (out->data.linearConversion) { + 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", ChannelInfoGetLogName(info)); + return RETURN_ERROR; + } + } + // Notify connections of new values channel->SetDefinedDuringInit(channel); for (j = 0; j < conns->numConnections; j++) { From 061967542fed0222813d862dec18838edbf04136 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Mon, 31 Oct 2022 15:09:37 +0100 Subject: [PATCH 291/295] fmu2: Remove variable only needed for warnings/errors (Performance!) --- src/fmu/common_fmu2.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/fmu/common_fmu2.c b/src/fmu/common_fmu2.c index b94e0d3..d801886 100644 --- a/src/fmu/common_fmu2.c +++ b/src/fmu/common_fmu2.c @@ -1026,8 +1026,6 @@ McxStatus Fmu2SetVariableInitialize(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { fmi2_status_t status = fmi2_status_ok; - char * const name = fmuVal->name; - ChannelValue * const chVal = &fmuVal->val; ChannelType * type = ChannelValueType(chVal); @@ -1114,13 +1112,13 @@ McxStatus Fmu2SetVariable(Fmu2CommonStruct * fmu, Fmu2Value * fmuVal) { if (fmi2_status_ok != status) { if (fmi2_status_error == status || fmi2_status_fatal == status) { fmu->runOk = fmi2_false; - mcx_log(LOG_ERROR, "FMU: Setting of variable %s failed", name); + mcx_log(LOG_ERROR, "FMU: Setting of variable %s failed", fmuVal->name); return RETURN_ERROR; } else { if (fmi2_status_warning == status) { - mcx_log(LOG_WARNING, "FMU: Setting of variable %s return with a warning", name); + mcx_log(LOG_WARNING, "FMU: Setting of variable %s return with a warning", fmuVal->name); } else if (fmi2_status_discard == status) { - mcx_log(LOG_WARNING, "FMU: Setting of variable %s discarded", name); + mcx_log(LOG_WARNING, "FMU: Setting of variable %s discarded", fmuVal->name); } } } From 4533d7950a552c4f12152ea9c82bb948c7054563 Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Mon, 31 Oct 2022 15:14:01 +0100 Subject: [PATCH 292/295] channel: Call IsFullyConnected only once (Performance!) --- src/core/Model.c | 32 ++++++++++++++++++++++++++++++++ src/core/channels/Channel.c | 29 ++++++++++++++--------------- src/core/channels/Channel.h | 8 +++++--- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/core/Model.c b/src/core/Model.c index 2b138a8..e89be67 100644 --- a/src/core/Model.c +++ b/src/core/Model.c @@ -1263,6 +1263,38 @@ static McxStatus ModelSetup(void * self) { } mcx_log(LOG_DEBUG, " "); + // Set isFullyConnected status on all channels + size_t i = 0; + size_t j = 0; + Component * comp = NULL; + Databus * db = NULL; + size_t inNum = 0; + size_t outNum = 0; + Channel * channel = NULL; + ObjectContainer * comps = model->components; + for (i = 0; i < comps->Size(comps); i++) { + comp = (Component *)comps->At(comps, i); + db = comp->GetDatabus(comp); + inNum = DatabusGetInChannelsNum(db); + for (j = 0; j < inNum; j++) { + channel = (Channel *) DatabusGetInChannel(db, j); + retVal = channel->SetIsFullyConnected(channel); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Model: Setting IsFullyConnected state for input %s failed", channel->info.name); + return RETURN_ERROR; + } + } + outNum = DatabusGetOutChannelsNum(db); + for (j = 0; j < outNum; j++) { + channel = (Channel *) DatabusGetOutChannel(db, j); + retVal = channel->SetIsFullyConnected(channel); + if (RETURN_OK != retVal) { + mcx_log(LOG_ERROR, "Model: Setting IsFullyConnected state for output %s failed", channel->info.name); + return RETURN_ERROR; + } + } + } + if (model->config->outputModel) { retVal = ModelPrint(model); if (RETURN_OK != retVal) { diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index 6f1be09..b7135b4 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -142,7 +142,7 @@ static Channel * ChannelCreate(Channel * channel) { channel->ProvidesValue = NULL; channel->IsConnected = NULL; - channel->IsFullyConnected = NULL; + channel->isFullyConnected_ = TRUE; return channel; } @@ -365,7 +365,7 @@ static McxStatus ChannelInUpdate(Channel * channel, TimeInterval * time) { return RETURN_OK; } -static int ChannelInIsFullyConnected(Channel * channel) { +static McxStatus ChannelInSetIsFullyConnected(Channel * channel) { ChannelIn * in = (ChannelIn *) channel; size_t i = 0; size_t connectedElems = 0; @@ -378,15 +378,13 @@ static int ChannelInIsFullyConnected(Channel * channel) { connectedElems += info->targetDimension ? ChannelDimensionNumElements(info->targetDimension) : 1; } - if (connectedElems == channelNumElems) { - return TRUE; - } + channel->isFullyConnected_ = connectedElems == channelNumElems; - return FALSE; + return RETURN_OK; } static int ChannelInProvidesValue(Channel * channel) { - if (ChannelInIsFullyConnected(channel)) { + if (channel->isFullyConnected_) { return TRUE; } else { ChannelInfo * info = &channel->info; @@ -612,7 +610,7 @@ static ChannelIn * ChannelInCreate(ChannelIn * in) { channel->ProvidesValue = ChannelInProvidesValue; channel->Update = ChannelInUpdate; channel->IsConnected = ChannelInIsConnected; - channel->IsFullyConnected = ChannelInIsFullyConnected; + channel->SetIsFullyConnected = ChannelInSetIsFullyConnected; in->Setup = ChannelInSetup; in->SetReference = ChannelInSetReference; @@ -806,7 +804,7 @@ static int ChannelOutIsConnected(Channel * channel) { return FALSE; } -static int ChannelOutIsFullyConnected(Channel * channel) { +static McxStatus ChannelOutSetIsFullyConnected(Channel * channel) { ChannelOut * out = (ChannelOut *) channel; if (ChannelTypeIsArray(channel->info.type)) { @@ -817,7 +815,7 @@ static int ChannelOutIsFullyConnected(Channel * channel) { int * connected = (int *) mcx_calloc(num_elems, sizeof(int)); if (!connected) { mcx_log(LOG_ERROR, "ChannelOutIsFullyConnected: Not enough memory"); - return -1; + return RETURN_ERROR; } for (i = 0; i < conns->numConnections; i++) { @@ -831,16 +829,17 @@ static int ChannelOutIsFullyConnected(Channel * channel) { } } + channel->isFullyConnected_ = TRUE; for (i = 0; i < num_elems; i++) { if (!connected[i]) { - return FALSE; + channel->isFullyConnected_ = FALSE; } } - - return TRUE; } else { - return ChannelOutIsConnected(channel); + channel->isFullyConnected_ = ChannelOutIsConnected(channel); } + + return RETURN_OK; } static McxStatus ChannelOutSetReference(ChannelOut * out, const void * reference, ChannelType * type) { @@ -1070,7 +1069,7 @@ static ChannelOut * ChannelOutCreate(ChannelOut * out) { channel->ProvidesValue = ChannelOutProvidesValue; channel->Update = ChannelOutUpdate; channel->IsConnected = ChannelOutIsConnected; - channel->IsFullyConnected = ChannelOutIsFullyConnected; + channel->SetIsFullyConnected = ChannelOutSetIsFullyConnected; out->Setup = ChannelOutSetup; out->RegisterConnection = ChannelOutRegisterConnection; diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index a9e19d9..d8a8424 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -40,7 +40,7 @@ typedef int (* fChannelIsValid)(Channel * channel); typedef int (* fChannelIsConnected)(Channel * channel); -typedef int (* fChannelIsFullyConnected)(Channel * channel); +typedef McxStatus (* fChannelSetIsFullyConnected)(Channel * channel); typedef int (* fChannelIsDefinedDuringInit)(Channel * channel); @@ -95,9 +95,9 @@ struct Channel { fChannelIsConnected IsConnected; /** - * Returns true if all elements of the channel are connected + * Set the isFullyConnected member to reflect whether all elements of the channel are connected */ - fChannelIsFullyConnected IsFullyConnected; + fChannelSetIsFullyConnected SetIsFullyConnected; /** * Getter for the flag data->isDefinedDuringInit @@ -112,6 +112,8 @@ struct Channel { * Initialize channel with info struct. */ fChannelSetup Setup; + + int isFullyConnected_; }; // ---------------------------------------------------------------------- From d4f891518b3fabd64a379d860eb35a1bac9f7d0a Mon Sep 17 00:00:00 2001 From: Dominic Hirtler Date: Wed, 2 Nov 2022 10:38:28 +0100 Subject: [PATCH 293/295] channel: Only calculate isFullyConnected on demand (Performance!) --- src/core/channels/Channel.c | 15 +++++++++++---- src/core/channels/Channel.h | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index b7135b4..bb44738 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -96,6 +96,12 @@ static McxStatus ReportConnStringError(ChannelInfo * chInfo, const char * prefix // ---------------------------------------------------------------------- // Channel +static int ChannelIsFullyConnected(Channel * channel) { + if (channel->isFullyConnected_ == INVALID_CONNECTION_STATUS) { + channel->SetIsFullyConnected(channel); + } + return channel->isFullyConnected_ == CHANNEL_FULLY_CONNECTED; +} static int ChannelIsDefinedDuringInit(Channel * channel) { return channel->isDefinedDuringInit; @@ -142,7 +148,8 @@ static Channel * ChannelCreate(Channel * channel) { channel->ProvidesValue = NULL; channel->IsConnected = NULL; - channel->isFullyConnected_ = TRUE; + channel->isFullyConnected_ = INVALID_CONNECTION_STATUS; + channel->IsFullyConnected = ChannelIsFullyConnected; return channel; } @@ -384,7 +391,7 @@ static McxStatus ChannelInSetIsFullyConnected(Channel * channel) { } static int ChannelInProvidesValue(Channel * channel) { - if (channel->isFullyConnected_) { + if (channel->IsFullyConnected(channel)) { return TRUE; } else { ChannelInfo * info = &channel->info; @@ -829,10 +836,10 @@ static McxStatus ChannelOutSetIsFullyConnected(Channel * channel) { } } - channel->isFullyConnected_ = TRUE; + channel->isFullyConnected_ = CHANNEL_FULLY_CONNECTED; for (i = 0; i < num_elems; i++) { if (!connected[i]) { - channel->isFullyConnected_ = FALSE; + channel->isFullyConnected_ = CHANNEL_ONLY_PARTIALLY_CONNETED; } } } else { diff --git a/src/core/channels/Channel.h b/src/core/channels/Channel.h index d8a8424..7b53d95 100644 --- a/src/core/channels/Channel.h +++ b/src/core/channels/Channel.h @@ -40,6 +40,8 @@ typedef int (* fChannelIsValid)(Channel * channel); typedef int (* fChannelIsConnected)(Channel * channel); +typedef int (* fChannelIsFullyConnected)(Channel * channel); + typedef McxStatus (* fChannelSetIsFullyConnected)(Channel * channel); typedef int (* fChannelIsDefinedDuringInit)(Channel * channel); @@ -94,6 +96,11 @@ struct Channel { */ fChannelIsConnected IsConnected; + /** + * Returns true if all elements of the channel are connected + */ + fChannelIsFullyConnected IsFullyConnected; + /** * Set the isFullyConnected member to reflect whether all elements of the channel are connected */ @@ -113,7 +120,15 @@ struct Channel { */ fChannelSetup Setup; - int isFullyConnected_; + /** + * Flag storing whether channel is fully connected + * Do not use this directly, but via the member function `IsFullyConnected` + */ + enum { + INVALID_CONNECTION_STATUS = -1, + CHANNEL_ONLY_PARTIALLY_CONNETED = 0, + CHANNEL_FULLY_CONNECTED = 1 + } isFullyConnected_; }; // ---------------------------------------------------------------------- From 3858ee992cf8e4dc3340c63c70e1779b74f84570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C4=8Cau=C5=A1evi=C4=87?= Date: Fri, 18 Nov 2022 09:19:56 +0100 Subject: [PATCH 294/295] channel: Fix Channel dimension index in calculation --- src/core/channels/Channel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/channels/Channel.c b/src/core/channels/Channel.c index bb44738..53a0ad4 100644 --- a/src/core/channels/Channel.c +++ b/src/core/channels/Channel.c @@ -830,9 +830,9 @@ static McxStatus ChannelOutSetIsFullyConnected(Channel * channel) { ConnectionInfo * info = &conn->info; size_t j = 0; - for (j = 0; j < ChannelDimensionNumElements(info->sourceDimension); i++) { + for (j = 0; j < ChannelDimensionNumElements(info->sourceDimension); j++) { size_t idx = ChannelDimensionGetIndex(info->sourceDimension, j, channel->info.type->ty.a.dims); - connected[idx] = 1; + connected[idx - info->sourceDimension->startIdxs[0]] = 1; } } From abe6e214abd4666223255bd047a478a06a221008 Mon Sep 17 00:00:00 2001 From: Klaus Schuch Date: Wed, 5 Mar 2025 19:58:06 +0100 Subject: [PATCH 295/295] Use %zu for size_t --- src/objects/ObjectContainer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objects/ObjectContainer.c b/src/objects/ObjectContainer.c index c7c9cdc..48304d1 100644 --- a/src/objects/ObjectContainer.c +++ b/src/objects/ObjectContainer.c @@ -476,7 +476,7 @@ static McxStatus ObjectContainerSetElementName(ObjectContainer * container, 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); + mcx_log(LOG_ERROR, "ObjectContainer: SetElementName: Position %zu out of bounds, max is %zu", pos, container->size); return RETURN_ERROR; }