From 5677efdfe647e432907abab51e0eb33f465170e3 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 2 Feb 2012 10:49:59 -0800 Subject: [PATCH] Filter callbacks of value changes to array words. When looking for a value change on a part select of an array word, the callback handle has to save the current value and test it with the new value to see if there is an actual change. If not, then suppress the callback. --- vvp/array.cc | 142 +++++++++++++++++++++++++++++++++----------- vvp/array.h | 5 +- vvp/vpi_callback.cc | 26 ++------ vvp/vpi_priv.h | 13 +++- 4 files changed, 128 insertions(+), 58 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index a13d85dfe..78d2e54d2 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -1471,6 +1471,16 @@ static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun) } } +class array_word_value_callback : public value_callback { + public: + inline explicit array_word_value_callback(p_cb_data data) + : value_callback(data) + { } + + public: + long word_addr; +}; + void array_word_change(vvp_array_t array, unsigned long addr) { for (vvp_fun_arrayport*cur = array->ports_; cur; cur = cur->next_) @@ -1481,35 +1491,38 @@ void array_word_change(vvp_array_t array, unsigned long addr) struct __vpiCallback *prev = 0; while (next) { - struct __vpiCallback*cur = next; + array_word_value_callback*cur = dynamic_cast(next); next = cur->next; // Skip callbacks that are not for me. -1 is for every element. - if (cur->extra_data != (long)addr && cur->extra_data != -1) { + if (cur->word_addr != (long)addr && cur->word_addr != -1) { prev = cur; continue; } // For whole array callbacks we need to set the index. - if (cur->extra_data == -1) { + if (cur->word_addr == -1) { cur->cb_data.index = (PLI_INT32) ((int)addr + array->first_addr.value); } if (cur->cb_data.cb_rtn != 0) { - if (cur->cb_data.value) { - if (vpi_array_is_real(array)) { - vpip_real_get_value(array->valsr->get_word(addr), - cur->cb_data.value); - } else { - vpip_vec4_get_value(array->vals4->get_word(addr), - array->vals_width, - array->signed_flag, - cur->cb_data.value); + if (cur->test_value_callback_ready()) { + if (cur->cb_data.value) { + if (vpi_array_is_real(array)) { + vpip_real_get_value(array->valsr->get_word(addr), + cur->cb_data.value); + } else { + vpip_vec4_get_value(array->vals4->get_word(addr), + array->vals_width, + array->signed_flag, + cur->cb_data.value); + } } + + callback_execute(cur); } - callback_execute(cur); prev = cur; } else if (prev == 0) { @@ -1597,33 +1610,94 @@ bool array_port_resolv_list_t::resolve(bool mes) return true; } -void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle obj) +class array_word_part_callback : public array_word_value_callback { + public: + explicit array_word_part_callback(p_cb_data data); + ~array_word_part_callback(); + + bool test_value_callback_ready(void); + + private: + char*value_bits_; +}; + +array_word_part_callback::array_word_part_callback(p_cb_data data) +: array_word_value_callback(data) { - struct __vpiArray*parent = 0; - if (struct __vpiArrayWord*word = array_var_word_from_handle(obj)) { - unsigned addr = decode_array_word_pointer(word, parent); - cb->extra_data = addr; + // Get the initial value of the part, to use as a reference. + struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(data->obj); + s_vpi_value tmp_value; + tmp_value.format = vpiBinStrVal; + apvword->vpi_get_value(&tmp_value); - } else if (struct __vpiArrayVthrA*tword = dynamic_cast<__vpiArrayVthrA*>(obj)) { - parent = tword->array; - cb->extra_data = tword->address; + value_bits_ = new char[apvword->part_wid+1]; - } else if (struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(obj)) { - parent = apvword->array; - cb->extra_data = apvword->word_sel; - } - - assert(parent); - cb->next = parent->vpi_callbacks; - parent->vpi_callbacks = cb; + memcpy(value_bits_, tmp_value.value.str, apvword->part_wid); + value_bits_[apvword->part_wid] = 0; } -void vpip_array_change(struct __vpiCallback*cb, vpiHandle obj) +array_word_part_callback::~array_word_part_callback() { - struct __vpiArray*arr = dynamic_cast<__vpiArray*>(obj); - cb->extra_data = -1; // This is a callback for every element. - cb->next = arr->vpi_callbacks; - arr->vpi_callbacks = cb; + delete[]value_bits_; +} + +bool array_word_part_callback::test_value_callback_ready(void) +{ + struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(cb_data.obj); + assert(apvword); + + // Get a reference value that can be used to compare with an + // updated value. + s_vpi_value tmp_value; + tmp_value.format = vpiBinStrVal; + apvword->vpi_get_value(&tmp_value); + + if (memcmp(value_bits_, tmp_value.value.str, apvword->part_wid) == 0) + return false; + + memcpy(value_bits_, tmp_value.value.str, apvword->part_wid); + return true; + +} + +value_callback*vpip_array_word_change(p_cb_data data) +{ + struct __vpiArray*parent = 0; + array_word_value_callback*cbh = 0; + if (struct __vpiArrayWord*word = array_var_word_from_handle(data->obj)) { + unsigned addr = decode_array_word_pointer(word, parent); + cbh = new array_word_value_callback(data); + cbh->word_addr = addr; + + } else if (struct __vpiArrayVthrA*tword = dynamic_cast<__vpiArrayVthrA*>(data->obj)) { + parent = tword->array; + cbh = new array_word_value_callback(data); + cbh->word_addr = tword->address; + + } else if (struct __vpiArrayVthrAPV*apvword = dynamic_cast<__vpiArrayVthrAPV*>(data->obj)) { + parent = apvword->array; + cbh = new array_word_part_callback(data); + cbh->word_addr = apvword->word_sel; + } + + assert(cbh); + assert(parent); + cbh->next = parent->vpi_callbacks; + parent->vpi_callbacks = cbh; + + return cbh; +} + +value_callback* vpip_array_change(p_cb_data data) +{ + array_word_value_callback*cbh = new array_word_value_callback(data); + assert(data->obj); + + struct __vpiArray*arr = dynamic_cast<__vpiArray*>(data->obj); + cbh->word_addr = -1; // This is a callback for every element. + cbh->next = arr->vpi_callbacks; + arr->vpi_callbacks = cbh; + return cbh; } void compile_array_port(char*label, char*array, char*addr) diff --git a/vvp/array.h b/vvp/array.h index d5c1e15a3..567dfe40c 100644 --- a/vvp/array.h +++ b/vvp/array.h @@ -23,6 +23,7 @@ #include "vpi_user.h" typedef struct __vpiArray* vvp_array_t; +class value_callback; /* * This function tries to find the array (by label) in the global @@ -48,8 +49,8 @@ extern double array_get_word_r(vvp_array_t array, unsigned address); /* VPI hooks */ -extern void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle word); -extern void vpip_array_change(struct __vpiCallback*cb, vpiHandle word); +extern value_callback* vpip_array_word_change(p_cb_data data); +extern value_callback* vpip_array_change(p_cb_data data); /* Compile hooks */ extern void compile_varw_real(char*label, vvp_array_t array, diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 1f8804fb2..5b05d48b4 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -71,18 +71,6 @@ int __vpiCallback::get_type_code(void) const { return vpiCallback; } -class value_callback : public __vpiCallback { - public: - explicit value_callback(p_cb_data data); - // Return true if the callback really is ready to be called - virtual bool test_value_callback_ready(void); - - public: - // user supplied callback data - struct t_vpi_time cb_time; - struct t_vpi_value cb_value; -}; - value_callback::value_callback(p_cb_data data) { cb_data = *data; @@ -219,6 +207,12 @@ static value_callback* make_value_change(p_cb_data data) if (data->obj->get_type_code() == vpiPartSelect) return make_value_change_part(data); + if (data->obj->get_type_code() == vpiMemoryWord) + return vpip_array_word_change(data); + + if (data->obj->get_type_code() == vpiMemory) + return vpip_array_change(data); + value_callback*obj = new value_callback(data); assert(data->obj); @@ -255,14 +249,6 @@ static value_callback* make_value_change(p_cb_data data) nev->add_vpi_callback(obj); break; - case vpiMemoryWord: - vpip_array_word_change(obj, data->obj); - break; - - case vpiMemory: - vpip_array_change(obj, data->obj); - break; - case vpiModule: case vpiConstant: case vpiParameter: diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 4fa287cc9..2f4237957 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -155,9 +155,18 @@ struct __vpiCallback : public __vpiHandle { // user supplied callback data struct t_cb_data cb_data; +}; - // The callback holder may use this for various purposes. - long extra_data; +class value_callback : public __vpiCallback { + public: + explicit value_callback(p_cb_data data); + // Return true if the callback really is ready to be called + virtual bool test_value_callback_ready(void); + + public: + // user supplied callback data + struct t_vpi_time cb_time; + struct t_vpi_value cb_value; }; extern void callback_execute(struct __vpiCallback*cur);