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.
|
* represent the words of the array. The vpi_array_t is a pointer to this.
|
||||||
*/
|
*/
|
||||||
struct __vpiArray {
|
struct __vpiArray {
|
||||||
|
__vpiArray() { }
|
||||||
|
|
||||||
struct __vpiHandle base;
|
struct __vpiHandle base;
|
||||||
struct __vpiScope*scope;
|
struct __vpiScope*scope;
|
||||||
const char*name; /* Permanently allocated string */
|
const char*name; /* Permanently allocated string */
|
||||||
|
|
@ -64,11 +66,11 @@ struct __vpiArray {
|
||||||
struct __vpiDecConst last_addr;
|
struct __vpiDecConst last_addr;
|
||||||
struct __vpiDecConst msb;
|
struct __vpiDecConst msb;
|
||||||
struct __vpiDecConst lsb;
|
struct __vpiDecConst lsb;
|
||||||
|
unsigned vals_width;
|
||||||
// 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_vector4_t *vals;
|
vvp_vector4array_t *vals;
|
||||||
unsigned vals_width;
|
|
||||||
struct __vpiArrayWord*vals_words;
|
struct __vpiArrayWord*vals_words;
|
||||||
|
|
||||||
class vvp_fun_arrayport*ports_;
|
class vvp_fun_arrayport*ports_;
|
||||||
|
|
@ -411,7 +413,7 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
|
||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case vpiSize:
|
case vpiSize:
|
||||||
return (int) parent->vals_width;
|
return (int) parent->vals->width();
|
||||||
|
|
||||||
case vpiLeftRange:
|
case vpiLeftRange:
|
||||||
return parent->msb.value;
|
return parent->msb.value;
|
||||||
|
|
@ -448,14 +450,9 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
|
||||||
|
|
||||||
assert(obj);
|
assert(obj);
|
||||||
unsigned index = decode_array_word_pointer(obj, parent);
|
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. */
|
vpip_vec4_get_value(parent->vals->get_word(index), width, false, value);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static vpiHandle vpi_array_var_word_put_value(vpiHandle ref, p_vpi_value vp, int flags)
|
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) {
|
if (arr->vals) {
|
||||||
assert(arr->nets == 0);
|
assert(arr->nets == 0);
|
||||||
if (part_off != 0 || val.size() != arr->vals_width) {
|
if (part_off != 0 || val.size() != arr->vals_width) {
|
||||||
if (arr->vals[address].size() == 0)
|
vvp_vector4_t tmp = arr->vals->get_word(address);
|
||||||
arr->vals[address] = vvp_vector4_t(arr->vals_width, BIT4_X);
|
if ((part_off + val.size()) > tmp.size()) {
|
||||||
if ((part_off + val.size()) > arr->vals[address].size()) {
|
|
||||||
cerr << "part_off=" << part_off
|
cerr << "part_off=" << part_off
|
||||||
<< " val.size()=" << val.size()
|
<< " 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;
|
<< " arr->vals_width=" << arr->vals_width << endl;
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
arr->vals[address].set_vec(part_off, val);
|
tmp.set_vec(part_off, val);
|
||||||
|
arr->vals->set_word(address, tmp);
|
||||||
} else {
|
} else {
|
||||||
arr->vals[address] = val;
|
arr->vals->set_word(address, val);
|
||||||
}
|
}
|
||||||
array_word_change(arr, address);
|
array_word_change(arr, address);
|
||||||
return;
|
return;
|
||||||
|
|
@ -730,14 +727,7 @@ vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address)
|
||||||
if (arr->vals) {
|
if (arr->vals) {
|
||||||
assert(arr->nets == 0);
|
assert(arr->nets == 0);
|
||||||
|
|
||||||
vvp_vector4_t tmp;
|
return arr->vals->get_word(address);
|
||||||
if (address < arr->array_count)
|
|
||||||
tmp = arr->vals[address];
|
|
||||||
|
|
||||||
if (tmp.size() == 0)
|
|
||||||
tmp = vvp_vector4_t(arr->vals_width, BIT4_X);
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(arr->vals == 0);
|
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);
|
struct __vpiArray*arr = ARRAY_HANDLE(obj);
|
||||||
|
|
||||||
/* Make the words. */
|
/* Make the words. */
|
||||||
arr->vals = new vvp_vector4_t[arr->array_count];
|
|
||||||
arr->vals_width = labs(msb-lsb) + 1;
|
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->msb, msb);
|
||||||
vpip_make_dec_const(&arr->lsb, lsb);
|
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.cb_rtn != 0) {
|
||||||
if (cur->cb_data.value)
|
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);
|
false, cur->cb_data.value);
|
||||||
|
|
||||||
callback_execute(cur);
|
callback_execute(cur);
|
||||||
|
|
|
||||||
|
|
@ -1177,6 +1177,94 @@ bool vector4_to_value(const vvp_vector4_t&vec, double&val, bool signed_flag)
|
||||||
return 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)
|
template <class T> T coerce_to_width(const T&that, unsigned width)
|
||||||
{
|
{
|
||||||
if (that.size() == width)
|
if (that.size() == width)
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ extern int edge(vvp_bit4_t from, vvp_bit4_t to);
|
||||||
class vvp_vector4_t {
|
class vvp_vector4_t {
|
||||||
|
|
||||||
friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
|
friend vvp_vector4_t operator ~(const vvp_vector4_t&that);
|
||||||
|
friend class vvp_vector4array_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit vvp_vector4_t(unsigned size =0, vvp_bit4_t bits =BIT4_X);
|
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, unsigned long&val);
|
||||||
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
|
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
|
/* vvp_vector2_t
|
||||||
*/
|
*/
|
||||||
class vvp_vector2_t {
|
class vvp_vector2_t {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue