Add limited support for getting and putting to real array words
This patch adds basic support for getting and putting values to real array words. This will be finished during the VPI rework.
This commit is contained in:
parent
ad39445eed
commit
1dbc517164
41
vvp/array.cc
41
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) {
|
||||
|
|
|
|||
196
vvp/vpi_priv.cc
196
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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue