diff --git a/vvp/array.cc b/vvp/array.cc index 6bffb1248..020e1a28a 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -703,6 +703,26 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref) return generic_get_str(code, &parent->scope->base, parent->name, sidx); } +// This function return true if the underlying array words are real. +static unsigned vpi_array_is_real(vvp_array_t arr) +{ + // Check to see if this is a variable/register array. + if (arr->valsr != 0) return 1U; // A real variable array. + if (arr->vals4 != 0) return 0U; // A bit based variable/register array. + + // This must be a net array so look at element 0 to find the type. + assert(arr->nets != 0); + assert(arr->array_count > 0); + struct __vpiRealVar*rsig = vpip_realvar_from_handle(arr->nets[0]); + if (rsig) { + struct __vpiSignal*vsig = vpip_signal_from_handle(arr->nets[0]); + assert(vsig == 0); + return 1U; + } + + return 0U; +} + static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value) { struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref); @@ -712,8 +732,14 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value) assert(parent); unsigned index = obj->get_address(); - vvp_vector4_t tmp = array_get_word(parent, index); - vpip_vec4_get_value(tmp, parent->vals_width, parent->signed_flag, value); + if (vpi_array_is_real(parent)) { + double tmp = array_get_word_r(parent, index); + vpip_real_get_value(tmp, value); + } else { + vvp_vector4_t tmp = array_get_word(parent, index); + vpip_vec4_get_value(tmp, parent->vals_width, parent->signed_flag, + value); + } } static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) @@ -727,8 +753,13 @@ static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) assert(parent); assert(index < parent->array_count); - vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); - array_set_word(parent, index, 0, val); + if (vpi_array_is_real(parent)) { + double val = real_from_vpi_value(vp); + array_set_word(parent, index, val); + } else { + vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); + array_set_word(parent, index, 0, val); + } return ref; } @@ -815,10 +846,12 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) { if (arr->vals4) { assert(arr->nets == 0); + assert(arr->valsr == 0); return arr->vals4->get_word(address); } assert(arr->vals4 == 0); + assert(arr->valsr == 0); assert(arr->nets != 0); if (address >= arr->array_count) { diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 64203a9ba..82f82ae4a 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -468,16 +468,49 @@ void vpi_set_vlog_info(int argc, char** argv) } } +static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width, + s_vpi_value*vp) +{ + unsigned nchar = width / 8; + unsigned tail = width % 8; + + char*rbuf = need_result_buf(nchar + 1, RBUF_VAL); + char*cp = rbuf; + + if (tail > 0) { + char char_val = 0; + for (unsigned idx = width-tail; idx < width ; idx += 1) { + vvp_bit4_t val = word_val.value(idx); + if (val == BIT4_1) + char_val |= 1 << idx; + } + + if (char_val != 0) + *cp++ = char_val; + } + + for (unsigned idx = 0 ; idx < nchar ; idx += 1) { + unsigned bit = (nchar - idx - 1) * 8; + char char_val = 0; + for (unsigned bdx = 0 ; bdx < 8 ; bdx += 1) { + vvp_bit4_t val = word_val.value(bit+bdx); + if (val == BIT4_1) + char_val |= 1 << bdx; + } + if (char_val != 0) + *cp++ = char_val; + } + + *cp = 0; + vp->value.str = rbuf; +} + /* * This is a generic function to convert a vvp_vector4_t value into a * vpi_value structure. The format is selected by the format of the * value pointer. The width is the real width of the word, in case the * word_val width is not accurate. */ - -static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width, - s_vpi_value*vp); - void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, bool signed_flag, s_vpi_value*vp) { @@ -485,13 +518,9 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, switch (vp->format) { default: - fprintf(stderr, "internal error: Format %d not implemented\n", - vp->format); - assert(0 && "format not implemented"); - - case vpiObjTypeVal: - vp->format = vpiVectorVal; - break; + fprintf(stderr, "sorry: Format %d not implemented for " + "getting vector values.\n", vp->format); + assert(0); case vpiSuppressVal: break; @@ -570,6 +599,10 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, break; } + case vpiObjTypeVal: + // Use the following case to actually set the value! + vp->format = vpiVectorVal; + case vpiVectorVal: { unsigned hwid = (width - 1)/32 + 1; @@ -606,51 +639,126 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, } case vpiStringVal: - vec4_get_value_string(word_val, width, vp); - break; + vec4_get_value_string(word_val, width, vp); + break; - case vpiRealVal: { + case vpiRealVal: vector4_to_value(word_val, vp->value.real, signed_flag); break; - } } } -static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width, - s_vpi_value*vp) +/* + * Convert a real value to the appropriate integer. + */ +static PLI_INT32 get_real_as_int(double real) { - unsigned nchar = width / 8; - unsigned tail = width % 8; + double rtn; - char*rbuf = need_result_buf(nchar + 1, RBUF_VAL); - char*cp = rbuf; - - if (tail > 0) { - char char_val = 0; - for (unsigned idx = width-tail; idx < width ; idx += 1) { - vvp_bit4_t val = word_val.value(idx); - if (val == BIT4_1) - char_val |= 1 << idx; - } - - if (char_val != 0) - *cp++ = char_val; + /* We would normally want to return 'bx for a NaN or + * +/- infinity, but for an integer the standard says + * to convert 'bx to 0, so we just return 0. */ + if (real != real || (real && (real == 0.5*real))) { + return 0; } - for (unsigned idx = 0 ; idx < nchar ; idx += 1) { - unsigned bit = (nchar - idx - 1) * 8; - char char_val = 0; - for (unsigned bdx = 0 ; bdx < 8 ; bdx += 1) { - vvp_bit4_t val = word_val.value(bit+bdx); - if (val == BIT4_1) - char_val |= 1 << bdx; - } - if (char_val != 0) - *cp++ = char_val; + /* Round away from zero. */ + if (real >= 0.0) { + rtn = floor(real); + if (real >= (rtn + 0.5)) rtn += 1.0; + } else { + rtn = ceil(real); + if (real <= (rtn - 0.5)) rtn -= 1.0; } - *cp = 0; - vp->value.str = rbuf; + return (PLI_INT32) rtn; +} + +/* + * This is a generic function to convert a double value into a + * vpi_value structure. The format is selected by the format of the + * value pointer. + */ +void vpip_real_get_value(double real, s_vpi_value*vp) +{ + char *rbuf = 0; + + switch (vp->format) { + default: + fprintf(stderr, "sorry: Format %d not implemented for " + "getting real values.\n", vp->format); + assert(0); + + case vpiSuppressVal: + break; + + case vpiObjTypeVal: + // Use the following case to actually set the value! + vp->format = vpiRealVal; + + case vpiRealVal: + vp->value.real = real; + break; + + case vpiIntVal: + vp->value.integer = get_real_as_int(real); + break; + + case vpiDecStrVal: + rbuf = need_result_buf(1025, RBUF_VAL); + vpip_vec4_to_dec_str(vvp_vector4_t(1024, real), rbuf, 1025, true); + vp->value.str = rbuf; + break; + } +} + +double real_from_vpi_value(s_vpi_value*vp) +{ + vvp_vector4_t vec4(1024); + double result; + bool is_signed = false; + + switch (vp->format) { + default: + fprintf(stderr, "sorry: Format %d not implemented for " + "putting real values.\n", vp->format); + assert(0); + + case vpiRealVal: + result = vp->value.real; + break; + + case vpiIntVal: + result = (double) vp->value.integer; + break; + + case vpiBinStrVal: + vpip_bin_str_to_vec4(vec4, vp->value.str); + if (vp->value.str[0] == '-') is_signed = true; + vector4_to_value(vec4, result, is_signed); + break; + + case vpiOctStrVal: + vpip_oct_str_to_vec4(vec4, vp->value.str); + if (vp->value.str[0] == '-') is_signed = true; + vector4_to_value(vec4, result, is_signed); + break; + + case vpiDecStrVal: + vpip_dec_str_to_vec4(vec4, vp->value.str); + if (vp->value.str[0] == '-') is_signed = true; + vector4_to_value(vec4, result, is_signed); + break; + + case vpiHexStrVal: + vpip_hex_str_to_vec4(vec4, vp->value.str); + if (vp->value.str[0] == '-') is_signed = true; + vector4_to_value(vec4, result, is_signed); + break; + + } + + return result; } void vpi_get_value(vpiHandle expr, s_vpi_value*vp) diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 5442ad9d2..a3a40653a 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -593,9 +593,11 @@ extern void vpip_dec_str_to_vec4(vvp_vector4_t&val, const char*str); extern void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str); extern vvp_vector4_t vec4_from_vpi_value(s_vpi_value*vp, unsigned wid); +extern double real_from_vpi_value(s_vpi_value*vp); extern void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, bool signed_flag, s_vpi_value*vp); +extern void vpip_real_get_value(double real, s_vpi_value*vp); /* * Function defined in vpi_signal.cc to manage vpi_get_* persistent diff --git a/vvp/vpi_real.cc b/vvp/vpi_real.cc index 25414080b..cb8093679 100644 --- a/vvp/vpi_real.cc +++ b/vvp/vpi_real.cc @@ -139,45 +139,9 @@ static void real_var_get_value(vpiHandle ref, s_vpi_value*vp) static vpiHandle real_var_put_value(vpiHandle ref, p_vpi_value vp, int) { - vvp_vector4_t vec4(1024); - double result; - bool is_signed = false; assert(ref->vpi_type->type_code == vpiRealVar); - switch (vp->format) { - case vpiRealVal: - result = vp->value.real; - break; - case vpiIntVal: - result = (double)vp->value.integer; - break; - case vpiBinStrVal: - vpip_bin_str_to_vec4(vec4, vp->value.str); - if (vp->value.str[0] == '-') is_signed = true; - vector4_to_value(vec4, result, is_signed); - break; - case vpiOctStrVal: - vpip_oct_str_to_vec4(vec4, vp->value.str); - if (vp->value.str[0] == '-') is_signed = true; - vector4_to_value(vec4, result, is_signed); - break; - case vpiDecStrVal: - vpip_dec_str_to_vec4(vec4, vp->value.str); - if (vp->value.str[0] == '-') is_signed = true; - vector4_to_value(vec4, result, is_signed); - break; - case vpiHexStrVal: - vpip_hex_str_to_vec4(vec4, vp->value.str); - if (vp->value.str[0] == '-') is_signed = true; - vector4_to_value(vec4, result, is_signed); - break; - - default: - fprintf(stderr, "Cannot convert type %d to a real value.", - vp->format); - assert(0); - break; - } + double result = real_from_vpi_value(vp); struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref; assert(rfp);