From 1e2237436cfbb4bde2f7a15ac8a70623a4319d6f Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Sun, 11 Jun 2023 12:11:48 -0400 Subject: [PATCH] vhpi: Support getting/putting reals Add support for getting/putting reals (aka doubles). --- src/vhpi/vhpi-model.c | 33 ++++++++++++++++++++ src/vhpi/vhpi-util.c | 6 ++++ test/regress/testlist.txt | 2 +- test/regress/vhpi8.vhd | 1 + test/vhpi/vhpi8.c | 63 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/src/vhpi/vhpi-model.c b/src/vhpi/vhpi-model.c index 80e3442e..351d87f6 100644 --- a/src/vhpi/vhpi-model.c +++ b/src/vhpi/vhpi-model.c @@ -1771,6 +1771,10 @@ int vhpi_get_value(vhpiHandleT expr, vhpiValueT *value_p) value_p->value.intg = ((const uint32_t *)signal_value(signal))[offset]; return 0; + case vhpiRealVal: + value_p->value.real = ((const double *)signal_value(signal))[offset]; + return 0; + case vhpiLogicVecVal: { const int max = value_p->bufSize / sizeof(vhpiEnumT); @@ -1826,6 +1830,19 @@ int vhpi_get_value(vhpiHandleT expr, vhpiValueT *value_p) return 0; } + case vhpiRealVecVal: + { + const int max = value_p->bufSize / sizeof(vhpiRealT); + if (max < value_p->numElems) + return value_p->numElems * sizeof(vhpiRealT); + + const double *p = ((const double *)signal_value(signal)) + offset; + for (int i = 0; i < value_p->numElems; i++) + value_p->value.reals[i] = *p++; + + return 0; + } + default: fatal_trace("unsupported format %d", value_p->format); } @@ -1878,6 +1895,7 @@ int vhpi_put_value(vhpiHandleT handle, uint64_t uint64_t_val; vhpiIntT vhpiIntT_val; } scalar; + double real; int num_elems = 0; if (!model_can_create_delta(model)) { @@ -1922,6 +1940,12 @@ int vhpi_put_value(vhpiHandleT handle, ptr = &scalar; // Assume little endian break; + case vhpiRealVal: + num_elems = 1; + real = value_p->value.real; + ptr = ℜ + break; + case vhpiLogicVecVal: num_elems = value_p->bufSize / sizeof(vhpiEnumT); ext = ptr = xmalloc(num_elems); @@ -1958,6 +1982,15 @@ int vhpi_put_value(vhpiHandleT handle, ((vhpiCharT *)ext)[i] = value_p->value.str[i]; break; + case vhpiRealVecVal: + { + num_elems = value_p->bufSize / sizeof(vhpiRealT); + ext = ptr = xmalloc_array(num_elems, sizeof(double)); + for (int i = 0; i < num_elems; i++) + ((double *)ext)[i] = value_p->value.reals[i]; + break; + } + default: vhpi_error(vhpiFailure, &(obj->loc), "value format " "%d not supported in vhpi_put_value", diff --git a/src/vhpi/vhpi-util.c b/src/vhpi/vhpi-util.c index 054c4181..dadd8e27 100644 --- a/src/vhpi/vhpi-util.c +++ b/src/vhpi/vhpi-util.c @@ -243,6 +243,9 @@ vhpiFormatT vhpi_format_for_type(type_t type, const char **map_str) case T_INTEGER: return vhpiIntVal; + case T_REAL: + return vhpiRealVal; + case T_ARRAY: { type_t elem = type_base_recur(type_elem(base)); @@ -268,6 +271,9 @@ vhpiFormatT vhpi_format_for_type(type_t type, const char **map_str) break; } + case T_REAL: + return vhpiRealVecVal; + default: break; } diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index 211dc95c..438fb792 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -795,7 +795,7 @@ array17 normal,2008 stdenv5 normal,2019 assert7 fail,2008 vhpi7 normal,2008,vhpi -vhpi8 normal,vhpi +vhpi8 normal,2008,vhpi issue704 wave,no-collapse real5 normal,2019 assign9 normal,2008 diff --git a/test/regress/vhpi8.vhd b/test/regress/vhpi8.vhd index c46d06cc..f0379290 100644 --- a/test/regress/vhpi8.vhd +++ b/test/regress/vhpi8.vhd @@ -45,5 +45,6 @@ architecture test of vhpi8 is signal ev: enum_vector(0 to 3) := (e000, e001, e002, e003); signal bv: bit_vector(3 to 0); signal cv: string(1 to 4) := "NVC!"; + signal rv: real_vector(0 to 3) := (0.0, 0.5, 1.0, -1.0); begin end architecture; diff --git a/test/vhpi/vhpi8.c b/test/vhpi/vhpi8.c index 7a1f87cd..2f894cc9 100644 --- a/test/vhpi/vhpi8.c +++ b/test/vhpi/vhpi8.c @@ -1,9 +1,11 @@ #include "vhpi_test.h" +#include +#include #include #include -static vhpiHandleT lv, sv, ev, bv, cv, lv2, sv2, ev2, cv2; +static vhpiHandleT lv, sv, ev, bv, cv, rv, lv2, sv2, ev2, cv2, rv2; static void last_delta(const vhpiCbDataT *cb_data) { @@ -86,6 +88,28 @@ static void last_delta(const vhpiCbDataT *cb_data) vhpi_get_value(cv2, &cval2); check_error(); fail_unless(cval2.value.ch == 254); + + vhpiRealT r[4]; + vhpiValueT rval = { + .format = vhpiRealVecVal, + .bufSize = sizeof(r), + .value.reals = r, + }; + + vhpi_get_value(rv, &rval); + check_error(); + fail_unless(isnan(r[0])); + fail_unless(r[1] == DBL_TRUE_MIN); + fail_unless(r[2] == DBL_MAX); + fail_unless(r[3] == HUGE_VAL); + + vhpiValueT rval2 = { + .format = vhpiRealVal, + }; + + vhpi_get_value(rv2, &rval2); + check_error(); + fail_unless(rval2.value.real == DBL_MAX); } static void start_of_sim(const vhpiCbDataT *cb_data) @@ -212,6 +236,35 @@ static void start_of_sim(const vhpiCbDataT *cb_data) c[3] = 255; vhpi_put_value(cv, &cval, vhpiDepositPropagate); check_error(); + + vhpiRealT r[4]; + vhpiValueT rval = { + .format = vhpiRealVecVal, + .bufSize = sizeof(r), + .value.reals = r, + }; + + vhpi_get_value(rv, &rval); + check_error(); + fail_unless(r[0] == 0.0); + fail_unless(r[1] == 0.5); + fail_unless(r[2] == 1.0); + fail_unless(r[3] == -1.0); + + vhpiValueT rval2 = { + .format = vhpiRealVal, + }; + + vhpi_get_value(rv2, &rval2); + check_error(); + fail_unless(rval2.value.real == 1.0); + + r[0] = NAN; + r[1] = DBL_TRUE_MIN; + r[2] = DBL_MAX; + r[3] = HUGE_VAL; + vhpi_put_value(rv, &rval, vhpiDepositPropagate); + check_error(); } void vhpi8_startup(void) @@ -274,5 +327,13 @@ void vhpi8_startup(void) check_error(); fail_if(cv2 == NULL); + rv = vhpi_handle_by_name("rv", root); + check_error(); + fail_if(rv == NULL); + + rv2 = vhpi_handle_by_index(vhpiIndexedNames, rv, 2); + check_error(); + fail_if(rv2 == NULL); + vhpi_release_handle(root); } -- 2.39.2