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
35
vvp/array.cc
35
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);
|
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)
|
static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value)
|
||||||
{
|
{
|
||||||
struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
|
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);
|
assert(parent);
|
||||||
|
|
||||||
unsigned index = obj->get_address();
|
unsigned index = obj->get_address();
|
||||||
|
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);
|
vvp_vector4_t tmp = array_get_word(parent, index);
|
||||||
vpip_vec4_get_value(tmp, parent->vals_width, parent->signed_flag, value);
|
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)
|
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(parent);
|
||||||
assert(index < parent->array_count);
|
assert(index < parent->array_count);
|
||||||
|
|
||||||
|
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);
|
vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width);
|
||||||
array_set_word(parent, index, 0, val);
|
array_set_word(parent, index, 0, val);
|
||||||
|
}
|
||||||
|
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
@ -815,10 +846,12 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
{
|
{
|
||||||
if (arr->vals4) {
|
if (arr->vals4) {
|
||||||
assert(arr->nets == 0);
|
assert(arr->nets == 0);
|
||||||
|
assert(arr->valsr == 0);
|
||||||
return arr->vals4->get_word(address);
|
return arr->vals4->get_word(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(arr->vals4 == 0);
|
assert(arr->vals4 == 0);
|
||||||
|
assert(arr->valsr == 0);
|
||||||
assert(arr->nets != 0);
|
assert(arr->nets != 0);
|
||||||
|
|
||||||
if (address >= arr->array_count) {
|
if (address >= arr->array_count) {
|
||||||
|
|
|
||||||
186
vvp/vpi_priv.cc
186
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
|
* 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
|
* 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
|
* value pointer. The width is the real width of the word, in case the
|
||||||
* word_val width is not accurate.
|
* 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,
|
void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
|
||||||
bool signed_flag, s_vpi_value*vp)
|
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) {
|
switch (vp->format) {
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "internal error: Format %d not implemented\n",
|
fprintf(stderr, "sorry: Format %d not implemented for "
|
||||||
vp->format);
|
"getting vector values.\n", vp->format);
|
||||||
assert(0 && "format not implemented");
|
assert(0);
|
||||||
|
|
||||||
case vpiObjTypeVal:
|
|
||||||
vp->format = vpiVectorVal;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case vpiSuppressVal:
|
case vpiSuppressVal:
|
||||||
break;
|
break;
|
||||||
|
|
@ -570,6 +599,10 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case vpiObjTypeVal:
|
||||||
|
// Use the following case to actually set the value!
|
||||||
|
vp->format = vpiVectorVal;
|
||||||
|
|
||||||
case vpiVectorVal: {
|
case vpiVectorVal: {
|
||||||
unsigned hwid = (width - 1)/32 + 1;
|
unsigned hwid = (width - 1)/32 + 1;
|
||||||
|
|
||||||
|
|
@ -609,48 +642,123 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
|
||||||
vec4_get_value_string(word_val, width, vp);
|
vec4_get_value_string(word_val, width, vp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiRealVal: {
|
case vpiRealVal:
|
||||||
vector4_to_value(word_val, vp->value.real, signed_flag);
|
vector4_to_value(word_val, vp->value.real, signed_flag);
|
||||||
break;
|
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;
|
double rtn;
|
||||||
unsigned tail = width % 8;
|
|
||||||
|
|
||||||
char*rbuf = need_result_buf(nchar + 1, RBUF_VAL);
|
/* We would normally want to return 'bx for a NaN or
|
||||||
char*cp = rbuf;
|
* +/- infinity, but for an integer the standard says
|
||||||
|
* to convert 'bx to 0, so we just return 0. */
|
||||||
if (tail > 0) {
|
if (real != real || (real && (real == 0.5*real))) {
|
||||||
char char_val = 0;
|
return 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)
|
/* Round away from zero. */
|
||||||
*cp++ = char_val;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned idx = 0 ; idx < nchar ; idx += 1) {
|
return (PLI_INT32) rtn;
|
||||||
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;
|
/*
|
||||||
|
* 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;
|
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)
|
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 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 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,
|
extern void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width,
|
||||||
bool signed_flag, s_vpi_value*vp);
|
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
|
* 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)
|
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);
|
assert(ref->vpi_type->type_code == vpiRealVar);
|
||||||
|
|
||||||
switch (vp->format) {
|
double result = real_from_vpi_value(vp);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
struct __vpiRealVar*rfp = (struct __vpiRealVar*)ref;
|
||||||
assert(rfp);
|
assert(rfp);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue