From 553bb0355f61ecf49667112a62e7a06cfb1c015c Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Sun, 11 Jun 2023 11:02:42 -0400 Subject: [PATCH] vhpi: Support char and string values The native format for character types is vhpiCharVal. Similarly, the native format for 1-d character arrays is vhpiStrVal. Use these formats instead of the short enum formats. Note that vhpiStrVals are nul-terminated, and the terminator is not included in the numElems (but it is included in bufSize). --- src/vhpi/vhpi-model.c | 30 ++++++++++++++++++++ src/vhpi/vhpi-util.c | 4 +++ test/regress/vhpi8.vhd | 1 + test/vhpi/vhpi8.c | 63 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/vhpi/vhpi-model.c b/src/vhpi/vhpi-model.c index cb51e601..80e3442e 100644 --- a/src/vhpi/vhpi-model.c +++ b/src/vhpi/vhpi-model.c @@ -1763,6 +1763,10 @@ int vhpi_get_value(vhpiHandleT expr, vhpiValueT *value_p) FOR_ALL_SIZES(signal_size(signal), SIGNAL_READ_ENUM); return 0; + case vhpiCharVal: + value_p->value.ch = signal_value_u8(signal)[offset]; + return 0; + case vhpiIntVal: value_p->value.intg = ((const uint32_t *)signal_value(signal))[offset]; return 0; @@ -1809,6 +1813,19 @@ int vhpi_get_value(vhpiHandleT expr, vhpiValueT *value_p) return 0; } + case vhpiStrVal: + { + if (value_p->bufSize + 1 < value_p->numElems) + return value_p->numElems + 1; + + const vhpiCharT *p = signal_value_u8(signal) + offset; + for (int i = 0; i < value_p->numElems; i++) + value_p->value.str[i] = *p++; + + value_p->value.str[value_p->numElems] = '\0'; + return 0; + } + default: fatal_trace("unsupported format %d", value_p->format); } @@ -1893,6 +1910,12 @@ int vhpi_put_value(vhpiHandleT handle, FOR_ALL_SIZES(signal_size(signal), SIGNAL_WRITE_ENUM); break; + case vhpiCharVal: + num_elems = 1; + byte = value_p->value.ch; + ptr = &byte; + break; + case vhpiIntVal: num_elems = 1; scalar.vhpiIntT_val = value_p->value.intg; @@ -1928,6 +1951,13 @@ int vhpi_put_value(vhpiHandleT handle, break; } + case vhpiStrVal: + num_elems = value_p->bufSize - 1; + ext = ptr = xmalloc(num_elems); + for (int i = 0; i < num_elems; i++) + ((vhpiCharT *)ext)[i] = value_p->value.str[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 9ba775c3..054c4181 100644 --- a/src/vhpi/vhpi-util.c +++ b/src/vhpi/vhpi-util.c @@ -230,6 +230,8 @@ vhpiFormatT vhpi_format_for_type(type_t type, const char **map_str) case W_STD_BIT: *map_str = "01"; return vhpiLogicVal; + case W_STD_CHAR: + return vhpiCharVal; default: if (type_enum_literals(base) <= 256) return vhpiSmallEnumVal; @@ -255,6 +257,8 @@ vhpiFormatT vhpi_format_for_type(type_t type, const char **map_str) case W_STD_BIT: *map_str = "01"; return vhpiLogicVecVal; + case W_STD_CHAR: + return vhpiStrVal; default: if (type_enum_literals(elem) <= 256) return vhpiSmallEnumVecVal; diff --git a/test/regress/vhpi8.vhd b/test/regress/vhpi8.vhd index a70751d7..c46d06cc 100644 --- a/test/regress/vhpi8.vhd +++ b/test/regress/vhpi8.vhd @@ -44,5 +44,6 @@ architecture test of vhpi8 is signal sv: severity_vector(0 to 3) := (note, warning, error, failure); 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!"; begin end architecture; diff --git a/test/vhpi/vhpi8.c b/test/vhpi/vhpi8.c index 2f90afe5..7a1f87cd 100644 --- a/test/vhpi/vhpi8.c +++ b/test/vhpi/vhpi8.c @@ -3,7 +3,7 @@ #include #include -static vhpiHandleT lv, sv, ev, bv, lv2, sv2, ev2; +static vhpiHandleT lv, sv, ev, bv, cv, lv2, sv2, ev2, cv2; static void last_delta(const vhpiCbDataT *cb_data) { @@ -63,6 +63,29 @@ static void last_delta(const vhpiCbDataT *cb_data) vhpi_get_value(lv2, &lval2); check_error(); fail_unless(lval2.value.enumv == 6); + + vhpiCharT c[5]; + vhpiValueT cval = { + .format = vhpiStrVal, + .bufSize = sizeof(c), + .value.str = c, + }; + + vhpi_get_value(cv, &cval); + check_error(); + fail_unless(c[0] == 0); + fail_unless(c[1] == 1); + fail_unless(c[2] == 254); + fail_unless(c[3] == 255); + fail_unless(c[4] == 0); + + vhpiValueT cval2 = { + .format = vhpiCharVal, + }; + + vhpi_get_value(cv2, &cval2); + check_error(); + fail_unless(cval2.value.ch == 254); } static void start_of_sim(const vhpiCbDataT *cb_data) @@ -159,6 +182,36 @@ static void start_of_sim(const vhpiCbDataT *cb_data) lval.bufSize = sizeof(l); fail_unless(vhpi_put_value(lv, &lval, vhpiDepositPropagate)); + + vhpiCharT c[5]; + vhpiValueT cval = { + .format = vhpiStrVal, + .bufSize = sizeof(c), + .value.str = c, + }; + + vhpi_get_value(cv, &cval); + check_error(); + fail_unless(c[0] == 'N'); + fail_unless(c[1] == 'V'); + fail_unless(c[2] == 'C'); + fail_unless(c[3] == '!'); + fail_unless(c[4] == '\0'); + + vhpiValueT cval2 = { + .format = vhpiCharVal, + }; + + vhpi_get_value(cv2, &cval2); + check_error(); + fail_unless(cval2.value.ch == 'C'); + + c[0] = 0; + c[1] = 1; + c[2] = 254; + c[3] = 255; + vhpi_put_value(cv, &cval, vhpiDepositPropagate); + check_error(); } void vhpi8_startup(void) @@ -213,5 +266,13 @@ void vhpi8_startup(void) fail_if(bv_names == NULL); fail_unless(vhpi_scan(bv_names) == NULL); + cv = vhpi_handle_by_name("cv", root); + check_error(); + fail_if(cv == NULL); + + cv2 = vhpi_handle_by_index(vhpiIndexedNames, cv, 2); + check_error(); + fail_if(cv2 == NULL); + vhpi_release_handle(root); } -- 2.39.2