diff --git a/vvp/array.cc b/vvp/array.cc index ebfca39dd..67c68e8a5 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -57,78 +57,6 @@ vvp_array_t array_find(const char*label) return v; } -/* -* The vpiArray object holds an array of vpi objects that themselves -* represent the words of the array. The vpi_array_t is a pointer to -* a struct __vpiArray. -* -* The details of the implementation depends on what this is an array -* of. The easiest case is if this is an array of nets. -* -* - Array of Nets: -* If this represents an array of nets, then the nets member points to -* an array of vpiHandle objects. Each vpiHandle is a word. This is -* done because typically each word of a net array is simultaneously -* driven and accessed by other means, so there is no advantage to -* compacting the array in any other way. -* -* - Array of vector4 words. -* In this case, the nets pointer is nil, and the vals4 member points -* to a vvl_vector4array_t object that is a compact representation of -* an array of vvp_vector4_t vectors. -* -* - Array of real variables -* The vals member points to a dynamic array objects that has an -* array of double variables. This is very much like the way the -* vector4 array works. -*/ -struct __vpiArray : public __vpiArrayBase, public __vpiHandle { - int get_type_code(void) const { return vpiMemory; } - unsigned get_size() const { return array_count; } - vpiHandle get_left_range() { assert(nets == 0); return &msb; } - vpiHandle get_right_range() { assert(nets == 0); return &lsb; } - struct __vpiScope*get_scope() const { return scope; } - - int get_word_size() const; - char*get_word_str(struct __vpiArrayWord*word, int code); - void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); - void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); - - vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); - - int vpi_get(int code); - char* vpi_get_str(int code); - vpiHandle vpi_handle(int code); - inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } - vpiHandle vpi_index(int idx); - - const char*name; /* Permanently allocated string */ - __vpiDecConst first_addr; - __vpiDecConst last_addr; - __vpiDecConst msb; - __vpiDecConst lsb; - unsigned vals_width; - // If this is a net array, nets lists the handles. - vpiHandle*nets; - // If this is a var array, then these are used instead of nets. - vvp_vector4array_t*vals4; - vvp_darray *vals; - - vvp_fun_arrayport*ports_; - struct __vpiCallback *vpi_callbacks; - bool signed_flag; - bool swap_addr; - -private: - unsigned array_count; - struct __vpiScope*scope; - -friend vpiHandle vpip_make_array(char*label, const char*name, - int first_addr, int last_addr, - bool signed_flag); -friend void compile_array_alias(char*label, char*name, char*src); -}; - struct __vpiArrayVthrA : public __vpiHandle { __vpiArrayVthrA(); @@ -217,27 +145,6 @@ struct __vpiArrayVthrAPV : public __vpiHandle { unsigned part_wid; }; -/* Get the array word size. */ -unsigned get_array_word_size(vvp_array_t array) -{ - unsigned width; - - assert(array->get_size() > 0); - /* For a net array we need to get the width from the first element. */ - if (array->nets) { - assert(array->vals4 == 0 && array->vals == 0); - struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(array->nets[0]); - assert(vsig); - width = vpip_size(vsig); - /* For a variable array we can get the width from vals_width. */ - } else { - assert(array->vals4 || array->vals); - width = array->vals_width; - } - - return width; -} - bool is_net_array(vpiHandle obj) { struct __vpiArray*rfp = dynamic_cast<__vpiArray*> (obj); @@ -296,18 +203,22 @@ static bool vpi_array_is_string(const vvp_array_t arr) int __vpiArray::get_word_size() const { - assert(nets == 0); + unsigned width; - if (vals4) { - assert(vals == 0); - return (int) vals4->width(); - } else { - assert(vals4 == 0); - return 1; - } + assert(get_size() > 0); + /* For a net array we need to get the width from the first element. */ + if (nets) { + assert(vals4 == 0 && vals == 0); + struct __vpiSignal*vsig = dynamic_cast<__vpiSignal*>(nets[0]); + assert(vsig); + width = vpip_size(vsig); + /* For a variable array we can get the width from vals_width. */ + } else { + assert(vals4 || vals); + width = vals_width; + } - assert(false); - return 0; + return width; } char*__vpiArray::get_word_str(struct __vpiArrayWord*word, int code) @@ -561,7 +472,7 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref) return 0; // Not implemented for now! case vpiSize: - return get_array_word_size(parent); + return parent->get_word_size(); case vpiLeftRange: return parent->msb.get_value(); @@ -625,7 +536,7 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value vp) vpip_string_get_value(tmp, vp); } else { vvp_vector4_t tmp = array_get_word(parent, index); - unsigned width = get_array_word_size(parent); + unsigned width = parent->get_word_size(); vpip_vec4_get_value(tmp, width, parent->signed_flag, vp); } } @@ -645,7 +556,7 @@ static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) double val = real_from_vpi_value(vp); array_set_word(parent, index, val); } else { - unsigned width = get_array_word_size(parent); + unsigned width = parent->get_word_size(); vvp_vector4_t val = vec4_from_vpi_value(vp, width); array_set_word(parent, index, 0, val); } diff --git a/vvp/array.h b/vvp/array.h index b4aba35c1..1016580ff 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -30,7 +30,6 @@ class value_callback; * table of all the arrays in the design. */ extern vvp_array_t array_find(const char*label); -extern unsigned get_array_word_size(vvp_array_t array); extern void array_word_change(vvp_array_t array, unsigned long addr); diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index bd803492a..1bdb5d64e 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -36,6 +36,7 @@ class class_type; class vvp_darray; +class vvp_fun_arrayport; typedef struct __vpiArray* vvp_array_t; @@ -562,6 +563,78 @@ struct __vpiArrayBase { struct __vpiArrayWord*vals_words; }; +/* +* The vpiArray object holds an array of vpi objects that themselves +* represent the words of the array. The vpi_array_t is a pointer to +* a struct __vpiArray. +* +* The details of the implementation depends on what this is an array +* of. The easiest case is if this is an array of nets. +* +* - Array of Nets: +* If this represents an array of nets, then the nets member points to +* an array of vpiHandle objects. Each vpiHandle is a word. This is +* done because typically each word of a net array is simultaneously +* driven and accessed by other means, so there is no advantage to +* compacting the array in any other way. +* +* - Array of vector4 words. +* In this case, the nets pointer is nil, and the vals4 member points +* to a vvl_vector4array_t object that is a compact representation of +* an array of vvp_vector4_t vectors. +* +* - Array of real variables +* The vals member points to a dynamic array objects that has an +* array of double variables. This is very much like the way the +* vector4 array works. +*/ +struct __vpiArray : public __vpiArrayBase, public __vpiHandle { + int get_type_code(void) const { return vpiMemory; } + unsigned get_size() const { return array_count; } + vpiHandle get_left_range() { assert(nets == 0); return &msb; } + vpiHandle get_right_range() { assert(nets == 0); return &lsb; } + struct __vpiScope*get_scope() const { return scope; } + + int get_word_size() const; + char*get_word_str(struct __vpiArrayWord*word, int code); + void get_word_value(struct __vpiArrayWord*word, p_vpi_value vp); + void put_word_value(struct __vpiArrayWord*word, p_vpi_value vp, int flags); + + vpiHandle get_iter_index(struct __vpiArrayIterator*iter, int idx); + + int vpi_get(int code); + char* vpi_get_str(int code); + vpiHandle vpi_handle(int code); + inline vpiHandle vpi_iterate(int code) { return vpi_array_base_iterate(code); } + vpiHandle vpi_index(int idx); + + const char*name; /* Permanently allocated string */ + __vpiDecConst first_addr; + __vpiDecConst last_addr; + __vpiDecConst msb; + __vpiDecConst lsb; + unsigned vals_width; + // If this is a net array, nets lists the handles. + vpiHandle*nets; + // If this is a var array, then these are used instead of nets. + vvp_vector4array_t*vals4; + vvp_darray *vals; + + vvp_fun_arrayport*ports_; + struct __vpiCallback *vpi_callbacks; + bool signed_flag; + bool swap_addr; + +private: + unsigned array_count; + struct __vpiScope*scope; + +friend vpiHandle vpip_make_array(char*label, const char*name, + int first_addr, int last_addr, + bool signed_flag); +friend void compile_array_alias(char*label, char*name, char*src); +}; + class __vpiDarrayVar : public __vpiBaseVar, public __vpiArrayBase { public: __vpiDarrayVar(__vpiScope*scope, const char*name, vvp_net_t*net); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index db0111773..1ebe5afc0 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1020,7 +1020,7 @@ bool of_ASSIGN_AV(vthread_t thr, vvp_code_t cp) if (adr < 0) return true; - long vwidth = get_array_word_size(cp->array); + long vwidth = cp->array->get_word_size(); // We fell off the MSB end. if (off >= vwidth) return true; // Trim the bits after the MSB @@ -1059,7 +1059,7 @@ bool of_ASSIGN_AVD(vthread_t thr, vvp_code_t cp) if (adr < 0) return true; - long vwidth = get_array_word_size(cp->array); + long vwidth = cp->array->get_word_size(); // We fell off the MSB end. if (off >= vwidth) return true; // Trim the bits after the MSB @@ -1091,7 +1091,7 @@ bool of_ASSIGN_AVE(vthread_t thr, vvp_code_t cp) if (adr < 0) return true; - long vwidth = get_array_word_size(cp->array); + long vwidth = cp->array->get_word_size(); // We fell off the MSB end. if (off >= vwidth) return true; // Trim the bits after the MSB