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:
parent
49363c660c
commit
86e5762b1c
43
vvp/array.cc
43
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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue