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 01/84] 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 02/84] 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 03/84] 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 04/84] 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 05/84] 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 06/84] 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 07/84] 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 08/84] 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 09/84] 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 10/84] 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 11/84] 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 12/84] 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 13/84] 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 14/84] 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 15/84] 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 16/84] 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 17/84] 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 18/84] 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 19/84] 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 20/84] 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 21/84] 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 22/84] 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 23/84] 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 24/84] 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 25/84] 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 26/84] 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 27/84] 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 28/84] 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 29/84] 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 30/84] 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 31/84] 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 32/84] 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 33/84] 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 34/84] 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 35/84] 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 36/84] 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 37/84] 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 38/84] 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 39/84] 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 40/84] 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 41/84] 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 42/84] 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 43/84] 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 44/84] 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 45/84] 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 46/84] 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 47/84] 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 48/84] 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 49/84] 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 50/84] 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 51/84] 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 52/84] 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 53/84] 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 54/84] 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 55/84] 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 56/84] 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 57/84] 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 58/84] 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 59/84] 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 60/84] 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 61/84] 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 62/84] 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 63/84] 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 64/84] 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 65/84] 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 66/84] 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 67/84] 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 68/84] 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 69/84] 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 70/84] 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 71/84] 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 72/84] 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 73/84] 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 74/84] 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 75/84] 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 76/84] 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 77/84] 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 78/84] 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 79/84] 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 80/84] 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 81/84] 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 82/84] 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 83/84] 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 84/84] 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;