diff --git a/vvp/array.cc b/vvp/array.cc index 75bb22f44..29de4f15d 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -56,6 +56,8 @@ vvp_array_t array_find(const char*label) * represent the words of the array. The vpi_array_t is a pointer to this. */ struct __vpiArray { + __vpiArray() { } + struct __vpiHandle base; struct __vpiScope*scope; const char*name; /* Permanently allocated string */ @@ -64,11 +66,11 @@ struct __vpiArray { struct __vpiDecConst last_addr; struct __vpiDecConst msb; struct __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_vector4_t *vals; - unsigned vals_width; + vvp_vector4array_t *vals; struct __vpiArrayWord*vals_words; class vvp_fun_arrayport*ports_; @@ -411,7 +413,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref) switch (code) { case vpiSize: - return (int) parent->vals_width; + return (int) parent->vals->width(); case vpiLeftRange: return parent->msb.value; @@ -448,14 +450,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value) assert(obj); unsigned index = decode_array_word_pointer(obj, parent); - unsigned width = parent->vals_width; + unsigned width = parent->vals->width(); - /* If we don't have a value yet just return X. */ - if (parent->vals[index].size() == 0) { - vpip_vec4_get_value(vvp_vector4_t(width), width, false, value); - } else { - vpip_vec4_get_value(parent->vals[index], width, false, value); - } + vpip_vec4_get_value(parent->vals->get_word(index), width, false, value); } static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags) @@ -696,18 +693,18 @@ void array_set_word(vvp_array_t arr, if (arr->vals) { assert(arr->nets == 0); if (part_off != 0 || val.size() != arr->vals_width) { - if (arr->vals[address].size() == 0) - arr->vals[address] = vvp_vector4_t(arr->vals_width, BIT4_X); - if ((part_off + val.size()) > arr->vals[address].size()) { + vvp_vector4_t tmp = arr->vals->get_word(address); + if ((part_off + val.size()) > tmp.size()) { cerr << "part_off=" << part_off << " val.size()=" << val.size() - << " arr->vals[address].size()=" << arr->vals[address].size() + << " arr->vals[address].size()=" << tmp.size() << " arr->vals_width=" << arr->vals_width << endl; assert(0); } - arr->vals[address].set_vec(part_off, val); + tmp.set_vec(part_off, val); + arr->vals->set_word(address, tmp); } else { - arr->vals[address] = val; + arr->vals->set_word(address, val); } array_word_change(arr, address); return; @@ -730,14 +727,7 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) if (arr->vals) { assert(arr->nets == 0); - vvp_vector4_t tmp; - if (address < arr->array_count) - tmp = arr->vals[address]; - - if (tmp.size() == 0) - tmp = vvp_vector4_t(arr->vals_width, BIT4_X); - - return tmp; + return arr->vals->get_word(address); } assert(arr->vals == 0); @@ -848,8 +838,8 @@ void compile_var_array(char*label, char*name, int last, int first, struct __vpiArray*arr = ARRAY_HANDLE(obj); /* Make the words. */ - arr->vals = new vvp_vector4_t[arr->array_count]; arr->vals_width = labs(msb-lsb) + 1; + arr->vals = new vvp_vector4array_t(arr->vals_width, arr->array_count); vpip_make_dec_const(&arr->msb, msb); vpip_make_dec_const(&arr->lsb, lsb); @@ -989,7 +979,8 @@ void array_word_change(vvp_array_t array, unsigned long addr) if (cur->cb_data.cb_rtn != 0) { if (cur->cb_data.value) - vpip_vec4_get_value(array->vals[addr], array->vals_width, + vpip_vec4_get_value(array->vals->get_word(addr), + array->vals_width, false, cur->cb_data.value); callback_execute(cur); diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 141ff1f33..9f9a76065 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1177,6 +1177,94 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag) return flag; } +vvp_vector4array_t::vvp_vector4array_t(unsigned width, unsigned words) +: width_(width), words_(words) +{ + array_ = new v4cell[words_]; + + if (width_ <= vvp_vector4_t::BITS_PER_WORD) { + for (unsigned idx = 0 ; idx < words_ ; idx += 1) { + array_[idx].abits_val_ = vvp_vector4_t::WORD_X_ABITS; + array_[idx].bbits_val_ = vvp_vector4_t::WORD_X_BBITS; + } + } else { + for (unsigned idx = 0 ; idx < words_ ; idx += 1) { + array_[idx].abits_ptr_ = 0; + array_[idx].bbits_ptr_ = 0; + } + } +} + +vvp_vector4array_t::~vvp_vector4array_t() +{ + if (array_) { + if (width_ > vvp_vector4_t::BITS_PER_WORD) { + for (unsigned idx = 0 ; idx < words_ ; idx += 1) + if (array_[idx].abits_ptr_) + delete[]array_[idx].abits_ptr_; + } + delete[]array_; + } +} + +void vvp_vector4array_t::set_word(unsigned index, const vvp_vector4_t&that) +{ + assert(index < words_); + assert(that.size_ == width_); + + v4cell&cell = array_[index]; + + if (width_ <= vvp_vector4_t::BITS_PER_WORD) { + cell.abits_val_ = that.abits_val_; + cell.bbits_val_ = that.bbits_val_; + return; + } + + unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD; + + if (cell.abits_ptr_ == 0) { + cell.abits_ptr_ = new unsigned long[2*cnt]; + cell.bbits_ptr_ = cell.abits_ptr_ + cnt; + } + + for (unsigned idx = 0 ; idx < cnt ; idx += 1) + cell.abits_ptr_[idx] = that.abits_ptr_[idx]; + for (unsigned idx = 0 ; idx < cnt ; idx += 1) + cell.bbits_ptr_[idx] = that.bbits_ptr_[idx]; +} + +vvp_vector4_t vvp_vector4array_t::get_word(unsigned index) const +{ + if (index >= words_) + return vvp_vector4_t(width_, BIT4_X); + + assert(index < words_); + + v4cell&cell = array_[index]; + + if (width_ <= vvp_vector4_t::BITS_PER_WORD) { + vvp_vector4_t res; + res.size_ = width_; + res.abits_val_ = cell.abits_val_; + res.bbits_val_ = cell.bbits_val_; + return res; + } + + vvp_vector4_t res (width_, BIT4_X); + if (cell.abits_ptr_ == 0) + return res; + + unsigned cnt = (width_ + vvp_vector4_t::BITS_PER_WORD-1)/vvp_vector4_t::BITS_PER_WORD; + + for (unsigned idx = 0 ; idx < cnt ; idx += 1) + res.abits_ptr_[idx] = cell.abits_ptr_[idx]; + for (unsigned idx = 0 ; idx < cnt ; idx += 1) + res.bbits_ptr_[idx] = cell.bbits_ptr_[idx]; + + return res; + +} + template T coerce_to_width(const T&that, unsigned width) { if (that.size() == width) diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index 928bfb3a9..604f4b65d 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -122,6 +122,7 @@ extern int edge(vvp_bit4_t from, vvp_bit4_t to); class vvp_vector4_t { friend vvp_vector4_t operator ~(const vvp_vector4_t&that); + friend class vvp_vector4array_t; public: explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X); @@ -383,6 +384,42 @@ extern bool vector4_to_value(const vvp_vector4_t&a, long&val, bool is_signed); extern bool vector4_to_value(const vvp_vector4_t&a, unsigned long&val); extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed); +/* + * vvp_vector4array_t + */ +class vvp_vector4array_t { + + public: + vvp_vector4array_t(unsigned width, unsigned words); + ~vvp_vector4array_t(); + + unsigned width() const { return width_; } + unsigned words() const { return words_; } + + vvp_vector4_t get_word(unsigned idx) const; + void set_word(unsigned idx, const vvp_vector4_t&that); + + private: + struct v4cell { + union { + unsigned long abits_val_; + unsigned long*abits_ptr_; + }; + union { + unsigned long bbits_val_; + unsigned long*bbits_ptr_; + }; + }; + + unsigned width_; + unsigned words_; + v4cell* array_; + + private: // Not implemented + vvp_vector4array_t(const vvp_vector4array_t&); + vvp_vector4array_t& operator = (const vvp_vector4array_t&); +}; + /* vvp_vector2_t */ class vvp_vector2_t {