Runtime support for arrays of atom2 types.

This handles all of the atom integer types in unpacked arrays.
This commit is contained in:
Stephen Williams 2013-01-03 11:33:47 -08:00
parent 1527b87595
commit fbd2843cad
4 changed files with 99 additions and 25 deletions

View File

@ -35,8 +35,6 @@
# include <cassert> # include <cassert>
# include "ivl_alloc.h" # include "ivl_alloc.h"
class vvp_darray_real;
unsigned long count_net_arrays = 0; unsigned long count_net_arrays = 0;
unsigned long count_net_array_words = 0; unsigned long count_net_array_words = 0;
unsigned long count_var_arrays = 0; unsigned long count_var_arrays = 0;
@ -103,8 +101,8 @@ struct __vpiArray : public __vpiHandle {
// If this is a net array, nets lists the handles. // If this is a net array, nets lists the handles.
vpiHandle*nets; vpiHandle*nets;
// If this is a var array, then these are used instead of nets. // If this is a var array, then these are used instead of nets.
vvp_vector4array_t *vals4; vvp_vector4array_t*vals4;
vvp_darray_real *valsr; vvp_darray *vals;
struct __vpiArrayWord*vals_words; struct __vpiArrayWord*vals_words;
vvp_fun_arrayport*ports_; vvp_fun_arrayport*ports_;
@ -231,13 +229,13 @@ unsigned get_array_word_size(vvp_array_t array)
assert(array->array_count > 0); assert(array->array_count > 0);
/* For a net array we need to get the width from the first element. */ /* For a net array we need to get the width from the first element. */
if (array->nets) { if (array->nets) {
assert(array->vals4 == 0 && array->valsr == 0); assert(array->vals4 == 0 && array->vals == 0);
struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(array->nets[0]); struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(array->nets[0]);
assert(vsig); assert(vsig);
width = vpip_size(vsig); width = vpip_size(vsig);
/* For a variable array we can get the width from vals_width. */ /* For a variable array we can get the width from vals_width. */
} else { } else {
assert(array->vals4 || array->valsr); assert(array->vals4 || array->vals);
width = array->vals_width; width = array->vals_width;
} }
@ -434,7 +432,7 @@ vpiHandle __vpiArrayIterator::vpi_index(int)
if (array->nets) return array->nets[use_index]; if (array->nets) return array->nets[use_index];
assert(array->vals4 || array->valsr); assert(array->vals4 || array->vals);
if (array->vals_words == 0) array_make_vals_words(array); if (array->vals_words == 0) array_make_vals_words(array);
@ -604,7 +602,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
case vpiSize: case vpiSize:
if (parent->vals4) { if (parent->vals4) {
assert(parent->valsr == 0); assert(parent->vals == 0);
return (int) parent->vals4->width(); return (int) parent->vals4->width();
} else { } else {
assert(parent->vals4 == 0); assert(parent->vals4 == 0);
@ -807,9 +805,11 @@ static char*vpi_array_vthr_A_get_str(int code, vpiHandle ref)
static unsigned vpi_array_is_real(vvp_array_t arr) static unsigned vpi_array_is_real(vvp_array_t arr)
{ {
// Check to see if this is a variable/register array. // 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. if (arr->vals4 != 0) return 0U; // A bit based variable/register array.
if (dynamic_cast<vvp_darray_real*> (arr->vals))
return 1U;
// This must be a net array so look at element 0 to find the type. // This must be a net array so look at element 0 to find the type.
assert(arr->nets != 0); assert(arr->nets != 0);
assert(arr->array_count > 0); assert(arr->array_count > 0);
@ -992,6 +992,16 @@ void array_set_word(vvp_array_t arr,
return; return;
} }
if (arr->vals) {
assert(arr->nets == 0);
// FIXME: For now, assume no part select of word?
assert(part_off==0);
assert(val.size() == arr->vals_width);
arr->vals->set_word(address, val);
array_word_change(arr, address);
return;
}
assert(arr->nets != 0); assert(arr->nets != 0);
// Select the word of the array that we affect. // Select the word of the array that we affect.
@ -1005,10 +1015,13 @@ void array_set_word(vvp_array_t arr,
void array_set_word(vvp_array_t arr, unsigned address, double val) void array_set_word(vvp_array_t arr, unsigned address, double val)
{ {
assert(arr->valsr!= 0); assert(arr->vals != 0);
assert(arr->nets == 0); assert(arr->nets == 0);
arr->valsr->set_word(address, val); if (address >= arr->vals->get_size())
return;
arr->vals->set_word(address, val);
array_word_change(arr, address); array_word_change(arr, address);
} }
@ -1016,12 +1029,23 @@ 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); assert(arr->vals == 0);
return arr->vals4->get_word(address); return arr->vals4->get_word(address);
} }
if (arr->vals) {
assert(arr->nets == 0);
assert(arr->vals4== 0);
if (address >= arr->vals->get_size())
return vvp_vector4_t(arr->vals_width, BIT4_X);
vvp_vector4_t val;
arr->vals->get_word(address, val);
return val;
}
assert(arr->vals4 == 0); assert(arr->vals4 == 0);
assert(arr->valsr == 0); assert(arr->vals == 0);
assert(arr->nets != 0); assert(arr->nets != 0);
if (address >= arr->array_count) { if (address >= arr->array_count) {
@ -1050,16 +1074,16 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
double array_get_word_r(vvp_array_t arr, unsigned address) double array_get_word_r(vvp_array_t arr, unsigned address)
{ {
if (arr->valsr) { if (arr->vals) {
assert(arr->vals4 == 0); assert(arr->vals4 == 0);
assert(arr->nets == 0); assert(arr->nets == 0);
// In this context, address out of bounds returns 0.0 // In this context, address out of bounds returns 0.0
// instead of an error. // instead of an error.
if (address >= arr->valsr->get_size()) if (address >= arr->vals->get_size())
return 0.0; return 0.0;
double val; double val;
arr->valsr->get_word(address, val); arr->vals->get_word(address, val);
return val; return val;
} }
@ -1107,7 +1131,7 @@ static vpiHandle vpip_make_array(char*label, const char*name,
// Start off now knowing if we are nets or variables. // Start off now knowing if we are nets or variables.
obj->nets = 0; obj->nets = 0;
obj->vals4 = 0; obj->vals4 = 0;
obj->valsr = 0; obj->vals = 0;
obj->vals_width = 0; obj->vals_width = 0;
obj->vals_words = 0; obj->vals_words = 0;
@ -1201,6 +1225,46 @@ void compile_var_array(char*label, char*name, int last, int first,
delete[] name; delete[] name;
} }
void compile_var2_array(char*label, char*name, int last, int first,
int msb, int lsb, bool signed_flag)
{
vpiHandle obj = vpip_make_array(label, name, first, last, signed_flag);
struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
/* Make the words. */
arr->msb.value = msb;
arr->lsb.value = lsb;
arr->vals_width = labs(msb-lsb) + 1;
assert(! arr->nets);
if (lsb == 0 && msb == 7 && signed_flag) {
arr->vals = new vvp_darray_atom<int8_t>(arr->array_count);
} else if (lsb == 0 && msb == 7 && !signed_flag) {
arr->vals = new vvp_darray_atom<uint8_t>(arr->array_count);
} else if (lsb == 0 && msb == 15 && signed_flag) {
arr->vals = new vvp_darray_atom<int16_t>(arr->array_count);
} else if (lsb == 0 && msb == 15 && !signed_flag) {
arr->vals = new vvp_darray_atom<uint16_t>(arr->array_count);
} else if (lsb == 0 && msb == 31 && signed_flag) {
arr->vals = new vvp_darray_atom<int32_t>(arr->array_count);
} else if (lsb == 0 && msb == 31 && !signed_flag) {
arr->vals = new vvp_darray_atom<uint32_t>(arr->array_count);
} else if (lsb == 0 && msb == 63 && signed_flag) {
arr->vals = new vvp_darray_atom<int64_t>(arr->array_count);
} else if (lsb == 0 && msb == 63 && !signed_flag) {
arr->vals = new vvp_darray_atom<uint64_t>(arr->array_count);
} else {
// For now, only support the atom sizes.
assert(0);
}
count_var_arrays += 1;
count_var_array_words += arr->array_count;
free(label);
delete[] name;
}
void compile_real_array(char*label, char*name, int last, int first, void compile_real_array(char*label, char*name, int last, int first,
int msb, int lsb) int msb, int lsb)
{ {
@ -1209,7 +1273,7 @@ void compile_real_array(char*label, char*name, int last, int first,
struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj);
/* Make the words. */ /* Make the words. */
arr->valsr = new vvp_darray_real(arr->array_count); arr->vals = new vvp_darray_real(arr->array_count);
arr->vals_width = 1; arr->vals_width = 1;
/* For a real array the MSB and LSB must be zero. */ /* For a real array the MSB and LSB must be zero. */
@ -1480,7 +1544,7 @@ static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun)
vvp_vector4_t tmp(array->vals_width, BIT4_X); vvp_vector4_t tmp(array->vals_width, BIT4_X);
schedule_init_propagate(fun->net_, tmp); schedule_init_propagate(fun->net_, tmp);
} }
if (array->valsr) { if (array->vals) {
schedule_init_propagate(fun->net_, 0.0); schedule_init_propagate(fun->net_, 0.0);
} }
} }
@ -1526,8 +1590,8 @@ void array_word_change(vvp_array_t array, unsigned long addr)
if (cur->cb_data.value) { if (cur->cb_data.value) {
if (vpi_array_is_real(array)) { if (vpi_array_is_real(array)) {
double val = 0.0; double val = 0.0;
if (addr < array->valsr->get_size()) if (addr < array->vals->get_size())
array->valsr->get_word(addr, val); array->vals->get_word(addr, val);
vpip_real_get_value(val, cur->cb_data.value); vpip_real_get_value(val, cur->cb_data.value);
} else { } else {
vpip_vec4_get_value(array->vals4->get_word(addr), vpip_vec4_get_value(array->vals4->get_word(addr),
@ -1764,7 +1828,7 @@ void compile_array_alias(char*label, char*name, char*src)
// Share the words with the source array. // Share the words with the source array.
obj->nets = mem->nets; obj->nets = mem->nets;
obj->vals4 = mem->vals4; obj->vals4 = mem->vals4;
obj->valsr = mem->valsr; obj->vals = mem->vals;
obj->vals_width = mem->vals_width; obj->vals_width = mem->vals_width;
obj->vals_words = mem->vals_words; obj->vals_words = mem->vals_words;

View File

@ -344,6 +344,9 @@ extern char **compile_udp_table(char **table, char *row);
extern void compile_var_array(char*label, char*name, extern void compile_var_array(char*label, char*name,
int last, int first, int last, int first,
int msb, int lsb, char signed_flag); int msb, int lsb, char signed_flag);
extern void compile_var2_array(char*label, char*name,
int last, int first,
int msb, int lsb, bool signed_flag);
extern void compile_real_array(char*label, char*name, extern void compile_real_array(char*label, char*name,
int last, int first, int last, int first,
int msb, int lsb); int msb, int lsb);

View File

@ -121,6 +121,8 @@ static char* strdupnew(char const *str)
".arith/sum" { return K_ARITH_SUM; } ".arith/sum" { return K_ARITH_SUM; }
".arith/sum.r" { return K_ARITH_SUM_R; } ".arith/sum.r" { return K_ARITH_SUM_R; }
".array" { return K_ARRAY; } ".array" { return K_ARRAY; }
".array/2s" { return K_ARRAY_2S; }
".array/2u" { return K_ARRAY_2U; }
".array/i" { return K_ARRAY_I; } ".array/i" { return K_ARRAY_I; }
".array/real" { return K_ARRAY_R; } ".array/real" { return K_ARRAY_R; }
".array/s" { return K_ARRAY_S; } ".array/s" { return K_ARRAY_S; }

View File

@ -77,7 +77,7 @@ static struct __vpiModPath*modpath_dst = 0;
%token K_ARITH_MOD_R K_ARITH_MOD_S %token K_ARITH_MOD_R K_ARITH_MOD_S
%token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R %token K_ARITH_MULT K_ARITH_MULT_R K_ARITH_SUB K_ARITH_SUB_R
%token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S %token K_ARITH_SUM K_ARITH_SUM_R K_ARITH_POW K_ARITH_POW_R K_ARITH_POW_S
%token K_ARRAY K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT %token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_R K_ARRAY_S K_ARRAY_PORT
%token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2 %token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2
%token K_CLASS %token K_CLASS
%token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R %token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R
@ -213,6 +213,11 @@ statement
| T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var_array($1, $3, $5, $6, $8, $9, 0); } { compile_var_array($1, $3, $5, $6, $8, $9, 0); }
| T_LABEL K_ARRAY_2U T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var2_array($1, $3, $5, $6, $8, $9, false); }
| T_LABEL K_ARRAY_2S T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var2_array($1, $3, $5, $6, $8, $9, true); }
| T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';' | T_LABEL K_ARRAY_I T_STRING ',' signed_t_number signed_t_number ',' signed_t_number signed_t_number ';'
{ compile_var_array($1, $3, $5, $6, $8, $9, 2); } { compile_var_array($1, $3, $5, $6, $8, $9, 2); }