diff --git a/Makefile b/Makefile index 746cb58..45570cd 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ export DSE_CLIB_VERSION ?= 1.0.17 ############### ## DSE Model C Library -export DSE_MODELC_VERSION ?= 2.0.25 +export DSE_MODELC_VERSION ?= 2.0.27 ############### diff --git a/dse/CMakeLists.txt b/dse/CMakeLists.txt index 6cc15c1..1583b0f 100644 --- a/dse/CMakeLists.txt +++ b/dse/CMakeLists.txt @@ -58,6 +58,7 @@ FetchContent_Declare(dse_modelc ) FetchContent_MakeAvailable(dse_modelc) set(DSE_MODELC_SOURCE_DIR ${dse_modelc_SOURCE_DIR}/dse/modelc) +set(DSE_MODELC_SOURCE_INCLUDE_DIR "${dse_modelc_SOURCE_DIR}") # External Project - DSE ModelC LIB diff --git a/dse/fmimodelc/CMakeLists.txt b/dse/fmimodelc/CMakeLists.txt index d40e5e1..013557f 100644 --- a/dse/fmimodelc/CMakeLists.txt +++ b/dse/fmimodelc/CMakeLists.txt @@ -36,6 +36,7 @@ target_include_directories(fmi2modelcfmu PRIVATE ${DSE_CLIB_INCLUDE_DIR} ${DSE_MODELC_INCLUDE_DIR} + ${DSE_MODELC_SOURCE_INCLUDE_DIR} ${FMI2_INCLUDE_DIR} ../.. ) diff --git a/dse/fmimodelc/fmi2fmu.c b/dse/fmimodelc/fmi2fmu.c index 474003e..ff2fe1e 100644 --- a/dse/fmimodelc/fmi2fmu.c +++ b/dse/fmimodelc/fmi2fmu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -30,14 +31,15 @@ static void _log(const char* format, ...) fflush(stdout); } -static void _log_binary_signal(SignalVector* sv, uint32_t index) +static void _log_binary_signal(SimbusVectorIndex* idx) { - _log(" - name : %s", sv->signal[index]); - _log(" length : %d", sv->length[index]); - _log(" buffer len : %d", sv->buffer_size[index]); - _log(" mime_type : %s", sv->mime_type[index]); - uint8_t* buffer = sv->binary[index]; - for (uint32_t j = 0; j + 16 < sv->length[index]; j += 16) { + if (idx == NULL || idx->sbv == NULL) return; + uint32_t index = idx->vi; + _log(" - name : %s", idx->sbv->signal[index]); + _log(" length : %d", idx->sbv->length[index]); + _log(" buffer len : %d", idx->sbv->buffer_size[index]); + uint8_t* buffer = idx->sbv->binary[index]; + for (uint32_t j = 0; j + 16 < idx->sbv->length[index]; j += 16) { _log(" %02x %02x %02x %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x %02x %02x %02x", buffer[j + 0], buffer[j + 1], buffer[j + 2], buffer[j + 3], @@ -283,7 +285,7 @@ fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], assert(c); Fmu2InstanceData* fmu = (Fmu2InstanceData*)c; - /* Free items on the lazy fre list. */ + /* Free items on the lazy free list. */ hashmap_clear(&fmu->runtime.binary.free_list.hash_map); for (size_t i = 0; i < nvr; i++) { @@ -293,15 +295,15 @@ fmi2Status fmi2GetString(fmi2Component c, const fmi2ValueReference vr[], /* Lookup the binary signal, by VRef. */ static char vr_idx[VREF_KEY_LEN]; snprintf(vr_idx, VREF_KEY_LEN, "%i", vr[i]); - ModelSignalIndex* idx = hashmap_get(&fmu->runtime.binary.tx, vr_idx); + SimbusVectorIndex* idx = hashmap_get(&fmu->runtime.binary.tx, vr_idx); if (idx == NULL) continue; - if (idx->sv == NULL || idx->binary == NULL) continue; - uint8_t* data = idx->sv->binary[idx->signal]; - uint32_t data_len = idx->sv->length[idx->signal]; + if (idx->sbv == NULL) continue; + uint8_t* data = idx->sbv->binary[idx->vi]; + uint32_t data_len = idx->sbv->length[idx->vi]; if (data == NULL || data_len == 0) continue; /* Write the requested string, encode if configured. */ - _log_binary_signal(idx->sv, idx->signal); + _log_binary_signal(idx); EncodeFunc ef = hashmap_get(&fmu->runtime.binary.encode_func, vr_idx); if (ef) { value[i] = ef((char*)data, data_len); @@ -411,9 +413,9 @@ fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], /* Lookup the binary signal, by VRef. */ static char vr_idx[VREF_KEY_LEN]; snprintf(vr_idx, VREF_KEY_LEN, "%i", vr[i]); - ModelSignalIndex* idx = hashmap_get(&fmu->runtime.binary.rx, vr_idx); + SimbusVectorIndex* idx = hashmap_get(&fmu->runtime.binary.rx, vr_idx); if (idx == NULL) continue; - if (idx->sv == NULL || idx->binary == NULL) continue; + if (idx->sbv == NULL) continue; /* Get the input binary string, decode if configured. */ char* data = (char*)value[i]; @@ -423,9 +425,11 @@ fmi2Status fmi2SetString(fmi2Component c, const fmi2ValueReference vr[], data = df((char*)data, &data_len); } - /* Append the binary string to the Network Binary Signal. */ - signal_append(idx->sv, idx->signal, (void*)data, data_len); - _log_binary_signal(idx->sv, idx->signal); + /* Append the binary string to the Binary Signal. */ + dse_buffer_append(&idx->sbv->binary[idx->vi], + &idx->sbv->length[idx->vi], &idx->sbv->buffer_size[idx->vi], + (void*)data, data_len); + _log_binary_signal(idx); /* Release the decode string/memory. Caller owns value[]. */ if (data != value[i]) free(data); @@ -486,8 +490,8 @@ fmi2Status fmi2DoStep(fmi2Component c, fmi2Real currentCommunicationPoint, int rc = model_runtime_step( m, &model_time, currentCommunicationPoint + communicationStepSize); - /* Reset the tracking on binary variables. */ - fmimodelc_clear_reset_called(m); + /* Reset the binary signal reset mechanism. */ + m->runtime.binary_signals_reset = false; /* return final status. */ return (rc == 0 ? fmi2OK : fmi2Error); diff --git a/dse/fmimodelc/fmimodelc.h b/dse/fmimodelc/fmimodelc.h index 8bbd933..41c80c0 100644 --- a/dse/fmimodelc/fmimodelc.h +++ b/dse/fmimodelc/fmimodelc.h @@ -7,6 +7,7 @@ #include #include +#include #include @@ -60,7 +61,6 @@ DLL_PRIVATE void fmimodelc_index_binary_signals( DLL_PRIVATE void fmimodelc_index_text_encoding( RuntimeModelDesc* m, HashMap* encode_func, HashMap* decode_func); DLL_PRIVATE void fmimodelc_reset_binary_signals(RuntimeModelDesc* m); -DLL_PRIVATE void fmimodelc_clear_reset_called(RuntimeModelDesc* m); /* ascii85.h */ diff --git a/dse/fmimodelc/runtime.c b/dse/fmimodelc/runtime.c index aeb2bcf..1c8d688 100644 --- a/dse/fmimodelc/runtime.c +++ b/dse/fmimodelc/runtime.c @@ -2,9 +2,11 @@ // // SPDX-License-Identifier: Apache-2.0 +#include #include #include #include +#include #include #include @@ -15,6 +17,19 @@ extern uint8_t __log_level__; static SchemaSignalObject* __signal_match; static const char* __signal_match_name; + +static void _log(const char* format, ...) +{ + printf("ModelCFmu: "); + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + printf("\n"); + fflush(stdout); +} + + static int _signal_group_match_handler( ModelInstanceSpec* model_instance, SchemaObject* object) { @@ -74,82 +89,102 @@ static const char** _signal_annotation_list(ModelInstanceSpec* mi, void fmimodelc_index_scalar_signals( RuntimeModelDesc* m, HashMap* input, HashMap* output) { - for (SignalVector* sv = m->model.sv; sv && sv->name; sv++) { - if (sv->is_binary == true) continue; - - for (uint32_t i = 0; i < sv->count; i++) { - /* Value Reference. */ - const char* vref = signal_annotation(sv, i, "fmi_value_reference"); - if (vref == NULL) continue; - - /* Index based on causality. */ - const char* causality = - signal_annotation(sv, i, "fmi_variable_causality"); - if (strcmp(causality, "output") == 0) { - hashmap_set(output, vref, &sv->scalar[i]); - } else if (strcmp(causality, "input") == 0) { - hashmap_set(input, vref, &sv->scalar[i]); + for (ModelInstanceSpec* mi = m->model.sim->instance_list; mi && mi->name; + mi++) { + for (SignalVector* sv = mi->model_desc->sv; sv && sv->name; sv++) { + if (sv->is_binary == true) continue; + + for (uint32_t i = 0; i < sv->count; i++) { + /* Value Reference. */ + const char* vref = + signal_annotation(sv, i, "fmi_value_reference"); + if (vref == NULL) continue; + + /* Locate the SimBus variable. */ + SimbusVectorIndex index = + simbus_vector_lookup(m->model.sim, sv->name, sv->signal[i]); + if (index.sbv == NULL) continue; + double* scalar = &index.sbv->scalar[index.vi]; + if (scalar == NULL) continue; + + /* Index based on causality. */ + const char* causality = + signal_annotation(sv, i, "fmi_variable_causality"); + if (strcmp(causality, "output") == 0) { + hashmap_set(output, vref, scalar); + } else if (strcmp(causality, "input") == 0) { + hashmap_set(input, vref, scalar); + } } } } + _log( + " Scalar: input=%u, output=%u", input->used_nodes, output->used_nodes); } void fmimodelc_index_binary_signals( RuntimeModelDesc* m, HashMap* rx, HashMap* tx) { - for (SignalVector* sv = m->model.sv; sv && sv->name; sv++) { - if (sv->is_binary == false) continue; - - for (uint32_t i = 0; i < sv->count; i++) { - /* Value Reference. */ - const char* vref = signal_annotation(sv, i, "fmi_value_reference"); - if (vref == NULL) continue; - - /* Index according to bus topology. */ - // dse.standards.fmi-ls-bus-topology.rx_vref: [2,4,6,8] - const char** rx_list = _signal_annotation_list(sv->mi, sv, - sv->signal[i], "dse.standards.fmi-ls-bus-topology.rx_vref"); - if (rx_list) { - for (size_t j = 0; rx_list[j]; j++) { - /* Value Reference for the RX variable. */ - const char* rx_vref = rx_list[j]; - - /* Binary signal index object. */ - ModelSignalIndex idx = - m->model.index((ModelDesc*)m, sv->alias, sv->signal[i]); - if (idx.binary == NULL) continue; - - /* Complete the index entry. */ - ModelSignalIndex* _ = calloc(1, sizeof(ModelSignalIndex)); - *_ = idx; - hashmap_set_alt(rx, rx_vref, _); + for (ModelInstanceSpec* mi = m->model.sim->instance_list; mi && mi->name; + mi++) { + for (SignalVector* sv = mi->model_desc->sv; sv && sv->name; sv++) { + if (sv->is_binary == false) continue; + + for (uint32_t i = 0; i < sv->count; i++) { + /* Value Reference. */ + const char* vref = + signal_annotation(sv, i, "fmi_value_reference"); + if (vref == NULL) continue; + + /* Index according to bus topology. */ + // dse.standards.fmi-ls-bus-topology.rx_vref: [2,4,6,8] + const char** rx_list = _signal_annotation_list(sv->mi, sv, + sv->signal[i], "dse.standards.fmi-ls-bus-topology.rx_vref"); + if (rx_list) { + for (size_t j = 0; rx_list[j]; j++) { + /* Value Reference for the RX variable. */ + const char* rx_vref = rx_list[j]; + + /* Locate the SimBus variable. */ + SimbusVectorIndex idx = simbus_vector_lookup( + m->model.sim, sv->name, sv->signal[i]); + if (idx.sbv == NULL) continue; + + /* Complete the index entry. */ + SimbusVectorIndex* _ = + calloc(1, sizeof(SimbusVectorIndex)); + *_ = idx; + hashmap_set_alt(rx, rx_vref, _); + } + free(rx_list); } - free(rx_list); - } - // dse.standards.fmi-ls-bus-topology.tx_vref: [3,5,7,9] - const char** tx_list = _signal_annotation_list(sv->mi, sv, - sv->signal[i], "dse.standards.fmi-ls-bus-topology.tx_vref"); - if (tx_list) { - for (size_t j = 0; tx_list[j]; j++) { - /* Value Reference for the TX variable. */ - const char* tx_vref = tx_list[j]; - - /* Binary signal index object. */ - ModelSignalIndex idx = - m->model.index((ModelDesc*)m, sv->alias, sv->signal[i]); - if (idx.binary == NULL) continue; - - /* Complete the index entry. */ - ModelSignalIndex* _ = calloc(1, sizeof(ModelSignalIndex)); - *_ = idx; - hashmap_set_alt(tx, tx_vref, _); + // dse.standards.fmi-ls-bus-topology.tx_vref: [3,5,7,9] + const char** tx_list = _signal_annotation_list(sv->mi, sv, + sv->signal[i], "dse.standards.fmi-ls-bus-topology.tx_vref"); + if (tx_list) { + for (size_t j = 0; tx_list[j]; j++) { + /* Value Reference for the TX variable. */ + const char* tx_vref = tx_list[j]; + + /* Locate the SimBus variable. */ + SimbusVectorIndex idx = simbus_vector_lookup( + m->model.sim, sv->name, sv->signal[i]); + if (idx.sbv == NULL) continue; + + /* Complete the index entry. */ + SimbusVectorIndex* _ = + calloc(1, sizeof(SimbusVectorIndex)); + *_ = idx; + hashmap_set_alt(tx, tx_vref, _); + } + free(tx_list); } - free(tx_list); } } } + _log(" Binary: rx=%u, tx=%u", rx->used_nodes, tx->used_nodes); } @@ -158,60 +193,48 @@ void fmimodelc_index_text_encoding( { // dse.standards.fmi-ls-text-encoding.encoding: ascii85 - for (SignalVector* sv = m->model.sv; sv && sv->name; sv++) { - if (sv->is_binary == false) continue; - - for (uint32_t i = 0; i < sv->count; i++) { - /* Value Reference. */ - const char* _ = signal_annotation(sv, i, "fmi_value_reference"); - if (_ == NULL) continue; - - /* Encoding. */ - const char* encoding = signal_annotation( - sv, i, "dse.standards.fmi-ls-text-encoding.encoding"); - if (strcmp(encoding, "ascii85") != 0) continue; - - /* Index, all with same encoding (for now). */ - // dse.standards.fmi-ls-text-encoding.vref: [[2,3,4,5,6,7,8,9] - const char** vref_list = _signal_annotation_list(sv->mi, sv, - sv->signal[i], "dse.standards.fmi-ls-text-encoding.vref"); - if (vref_list) { - for (size_t j = 0; vref_list[j]; j++) { - /* Value Reference for the RX variable. */ - const char* vref = vref_list[j]; - - /* Encoding. */ - hashmap_set(encode_func, vref, ascii85_encode); - hashmap_set(decode_func, vref, ascii85_decode); + for (ModelInstanceSpec* mi = m->model.sim->instance_list; mi && mi->name; + mi++) { + for (SignalVector* sv = mi->model_desc->sv; sv && sv->name; sv++) { + if (sv->is_binary == false) continue; + + for (uint32_t i = 0; i < sv->count; i++) { + /* Value Reference. */ + const char* _ = signal_annotation(sv, i, "fmi_value_reference"); + if (_ == NULL) continue; + + /* Encoding. */ + const char* encoding = signal_annotation( + sv, i, "dse.standards.fmi-ls-text-encoding.encoding"); + if (strcmp(encoding, "ascii85") != 0) continue; + + /* Index, all with same encoding (for now). */ + // dse.standards.fmi-ls-text-encoding.vref: [[2,3,4,5,6,7,8,9] + const char** vref_list = _signal_annotation_list(sv->mi, sv, + sv->signal[i], "dse.standards.fmi-ls-text-encoding.vref"); + if (vref_list) { + for (size_t j = 0; vref_list[j]; j++) { + /* Value Reference for the RX variable. */ + const char* vref = vref_list[j]; + + /* Encoding. */ + hashmap_set(encode_func, vref, ascii85_encode); + hashmap_set(decode_func, vref, ascii85_decode); + } + free(vref_list); } - free(vref_list); } } } + _log(" Encoding: enc=%u, dec=%u", encode_func->used_nodes, + decode_func->used_nodes); } void fmimodelc_reset_binary_signals(RuntimeModelDesc* m) { - for (SignalVector* sv = m->model.sv; sv && sv->name; sv++) { - if (sv->is_binary == false) continue; - - for (uint32_t i = 0; i < sv->count; i++) { - if (sv->reset_called[i] == false) { - signal_reset(sv, i); - } - } - } -} - - -void fmimodelc_clear_reset_called(RuntimeModelDesc* m) -{ - for (SignalVector* sv = m->model.sv; sv && sv->name; sv++) { - if (sv->is_binary == false) continue; - - for (uint32_t i = 0; i < sv->count; i++) { - sv->reset_called[i] = false; - } + if (m->runtime.binary_signals_reset == false) { + simbus_vector_binary_reset(m->model.sim); + m->runtime.binary_signals_reset = true; } } diff --git a/tests/cmocka/fmimodelc/test_index.c b/tests/cmocka/fmimodelc/test_index.c index 14472bb..3aa6136 100644 --- a/tests/cmocka/fmimodelc/test_index.c +++ b/tests/cmocka/fmimodelc/test_index.c @@ -56,13 +56,10 @@ void test_index__scalar(void** state) m = model_runtime_create(m); - /* Locate the scalar SV. */ - SignalVector* sv = m->model.sv; - for (; sv && sv->name; sv++) { - if (strcmp(sv->alias, "scalar_vector") == 0) break; - } - assert_non_null(sv); - assert_string_equal("scalar_vector", sv->alias); + /* Locate the SimBus scalar SV. */ + SimbusVectorIndex index = simbus_vector_lookup( + m->model.sim, "scalar", "counter"); + assert_non_null(index.sbv); /* Index the scalar signals. */ fmimodelc_index_scalar_signals(m, &input, &output); @@ -71,8 +68,8 @@ void test_index__scalar(void** state) double* sig_counter = NULL; sig_counter = hashmap_get(&output, "1"); assert_non_null(sig_counter); - assert_string_equal("counter", sv->signal[0]); - assert_ptr_equal(sig_counter, &sv->scalar[0]); + assert_string_equal("counter", index.sbv->signal[index.vi]); + assert_ptr_equal(sig_counter, &index.sbv->scalar[index.vi]); /* Cleanup. */ model_runtime_destroy(m); @@ -90,35 +87,17 @@ void test_index__binary(void** state) hashmap_init(&tx); m = model_runtime_create(m); - assert_non_null(m); - assert_non_null(m->model.mi); - assert_non_null(m->model.mi->model_desc); - assert_non_null(m->model.mi->model_desc->index); - - assert_non_null(m->model.index); - /* Locate the network SV. */ - SignalVector* sv = m->model.sv; - for (; sv && sv->name; sv++) { - if (strcmp(sv->alias, "network_vector") == 0) break; - } - assert_non_null(sv); - assert_string_equal("network_vector", sv->alias); + /* Locate the SimBus network SV. */ + SimbusVectorIndex index = simbus_vector_lookup( + m->model.sim, "network", "can"); + assert_non_null(index.sbv); /* Index the network signals. */ fmimodelc_index_binary_signals(m, &rx, &tx); assert_int_equal(rx.used_nodes, 4); assert_int_equal(tx.used_nodes, 4); - /* Get the reference index object. */ - ModelSignalIndex sig_can = - m->model.index((ModelDesc*)m, "network_vector", "can"); - assert_non_null(sig_can.sv); - assert_null(sig_can.scalar); - assert_non_null(sig_can.binary); - assert_string_equal("can", sig_can.sv->signal[sig_can.signal]); - assert_ptr_equal(sig_can.binary, &sig_can.sv->binary[sig_can.signal]); - /* Check the RX index. */ const char* rx_vref[] = { "2", @@ -128,10 +107,10 @@ void test_index__binary(void** state) }; for (size_t i = 0; i < ARRAY_SIZE(rx_vref); i++) { // Each index should have a ModelSignalIndex with the same content. - ModelSignalIndex* var = NULL; + SimbusVectorIndex* var = NULL; var = hashmap_get(&rx, rx_vref[i]); assert_non_null(var); - assert_memory_equal(var, &sig_can, sizeof(ModelSignalIndex)); + assert_memory_equal(var, &index, sizeof(SimbusVectorIndex)); } /* Check the TX index. */ @@ -143,10 +122,10 @@ void test_index__binary(void** state) }; for (size_t i = 0; i < ARRAY_SIZE(tx_vref); i++) { // Each index should have a ModelSignalIndex with the same content. - ModelSignalIndex* var = NULL; + SimbusVectorIndex* var = NULL; var = hashmap_get(&tx, tx_vref[i]); assert_non_null(var); - assert_memory_equal(var, &sig_can, sizeof(ModelSignalIndex)); + assert_memory_equal(var, &index, sizeof(SimbusVectorIndex)); } /* Cleanup. */