Compact of vvp_vector4_t in arrays.

Arrays of vvp_vector4_t values redundantly store some fields in every
word. Create a special type that stores vvp_vector4_t values in a form
that does not duplicate the width of all the items. This can save a lot
of space when big memories are simulated.
This commit is contained in:
Stephen Williams 2008-06-16 15:02:07 -07:00
parent 49363c660c
commit 86e5762b1c
3 changed files with 142 additions and 26 deletions

View File

@ -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);

View File

@ -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 <class T> T coerce_to_width(const T&that, unsigned width)
{
if (that.size() == width)

View File

@ -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 {