Allow VPI callbacks to var array words.

Functions like $monitor need to attach callbacks to array words if
those words are to be monitored. Have the array hold all the callbacks
for words in the array, under the assumption that the monitored words
are sparse.
This commit is contained in:
Stephen Williams 2008-05-20 18:30:56 -07:00
parent 007056d671
commit d1daf6733f
6 changed files with 137 additions and 26 deletions

View File

@ -1122,6 +1122,7 @@ static PLI_INT32 sys_monitor_calltf(PLI_BYTE8*name)
case vpiReg: case vpiReg:
case vpiIntegerVar: case vpiIntegerVar:
case vpiRealVar: case vpiRealVar:
case vpiMemoryWord:
/* Monitoring reg and net values involves setting /* Monitoring reg and net values involves setting
a callback for value changes. Pass the storage a callback for value changes. Pass the storage
pointer for the callback itself as user_data so pointer for the callback itself as user_data so

View File

@ -63,6 +63,7 @@ struct __vpiArray {
struct __vpiArrayWord*vals_words; struct __vpiArrayWord*vals_words;
class vvp_fun_arrayport*ports_; class vvp_fun_arrayport*ports_;
struct __vpiCallback *vpi_callbacks;
}; };
struct __vpiArrayIterator { struct __vpiArrayIterator {
@ -192,11 +193,25 @@ static const struct __vpirt vpip_array_vthr_A_rt = {
# define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \ # define ARRAY_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemory), \
(struct __vpiArray*)ref) (struct __vpiArray*)ref)
# define ARRAY_VAR_WORD(ref) (assert(ref->vpi_type->type_code==vpiMemoryWord), \ static struct __vpiArrayWord* array_var_word_from_handle(vpiHandle ref)
(struct __vpiArrayWord*)ref) {
if (ref == 0)
return 0;
if (ref->vpi_type != &vpip_array_var_word_rt)
return 0;
# define ARRAY_VTHR_A_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemoryWord), \ return (struct __vpiArrayWord*) ref;
(struct __vpiArrayVthrA*)ref) }
static struct __vpiArrayVthrA* array_vthr_a_from_handle(vpiHandle ref)
{
if (ref == 0)
return 0;
if (ref->vpi_type != &vpip_array_vthr_A_rt)
return 0;
return (struct __vpiArrayVthrA*) ref;
}
static void array_make_vals_words(struct __vpiArray*parent) static void array_make_vals_words(struct __vpiArray*parent)
{ {
@ -315,9 +330,10 @@ static vpiHandle vpi_array_index(vpiHandle ref, int index)
static int vpi_array_var_word_get(int code, vpiHandle ref) static int vpi_array_var_word_get(int code, vpiHandle ref)
{ {
struct __vpiArrayWord*obj = ARRAY_VAR_WORD(ref); struct __vpiArrayWord*obj = array_var_word_from_handle(ref);
struct __vpiArray*parent; struct __vpiArray*parent;
assert(obj);
decode_array_word_pointer(obj, parent); decode_array_word_pointer(obj, parent);
switch (code) { switch (code) {
@ -331,9 +347,10 @@ static int vpi_array_var_word_get(int code, vpiHandle ref)
static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value) static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value value)
{ {
struct __vpiArrayWord*obj = ARRAY_VAR_WORD(ref); struct __vpiArrayWord*obj = array_var_word_from_handle(ref);
struct __vpiArray*parent; struct __vpiArray*parent;
assert(obj);
unsigned index = decode_array_word_pointer(obj, parent); unsigned index = decode_array_word_pointer(obj, parent);
vpip_vec4_get_value(parent->vals[index], parent->vals_width, vpip_vec4_get_value(parent->vals[index], parent->vals_width,
@ -342,9 +359,10 @@ static void vpi_array_var_word_get_value(vpiHandle ref, p_vpi_value 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)
{ {
struct __vpiArrayWord*obj = ARRAY_VAR_WORD(ref); struct __vpiArrayWord*obj = array_var_word_from_handle(ref);
struct __vpiArray*parent; struct __vpiArray*parent;
assert(obj);
unsigned index = decode_array_word_pointer(obj, parent); unsigned index = decode_array_word_pointer(obj, parent);
vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width); vvp_vector4_t val = vec4_from_vpi_value(vp, parent->vals_width);
@ -426,7 +444,8 @@ static int array_index_free_object(vpiHandle ref)
static int vpi_array_vthr_A_get(int code, vpiHandle ref) static int vpi_array_vthr_A_get(int code, vpiHandle ref)
{ {
struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref); struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
assert(obj);
struct __vpiArray*parent = obj->array; struct __vpiArray*parent = obj->array;
switch (code) { switch (code) {
@ -443,7 +462,8 @@ static int vpi_array_vthr_A_get(int code, vpiHandle ref)
} }
static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value) static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value)
{ {
struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref); struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
assert(obj);
struct __vpiArray*parent = obj->array; struct __vpiArray*parent = obj->array;
assert(parent); assert(parent);
@ -456,7 +476,8 @@ static void vpi_array_vthr_A_get_value(vpiHandle ref, p_vpi_value value)
static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int) static vpiHandle vpi_array_vthr_A_put_value(vpiHandle ref, p_vpi_value vp, int)
{ {
struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref); struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
assert(obj);
struct __vpiArray*parent = obj->array; struct __vpiArray*parent = obj->array;
unsigned index = obj->address; unsigned index = obj->address;
@ -579,6 +600,7 @@ static vpiHandle vpip_make_array(char*label, const char*name,
// Initialize (clear) the read-ports list. // Initialize (clear) the read-ports list.
obj->ports_ = 0; obj->ports_ = 0;
obj->vpi_callbacks = 0;
/* Add this symbol to the array_symbols table for later lookup. */ /* Add this symbol to the array_symbols table for later lookup. */
if (!array_table) if (!array_table)
@ -745,6 +767,42 @@ void array_word_change(vvp_array_t array, unsigned long addr)
{ {
for (vvp_fun_arrayport*cur = array->ports_; cur; cur = cur->next_) for (vvp_fun_arrayport*cur = array->ports_; cur; cur = cur->next_)
cur->check_word_change(addr); cur->check_word_change(addr);
// Run callbacks attatched to the array itself.
struct __vpiCallback *next = array->vpi_callbacks;
struct __vpiCallback *prev = 0;
while (next) {
struct __vpiCallback*cur = next;
next = cur->next;
// Skip callbacks for callbacks not for me.
if (cur->extra_data != (long)addr) {
prev = cur;
continue;
}
if (cur->cb_data.cb_rtn != 0) {
if (cur->cb_data.value)
vpip_vec4_get_value(array->vals[addr], array->vals_width,
false, cur->cb_data.value);
callback_execute(cur);
prev = cur;
} else if (prev == 0) {
array->vpi_callbacks = next;
cur->next = 0;
delete_vpi_callback(cur);
} else {
assert(prev->next == cur);
prev->next = next;
cur->next = 0;
delete_vpi_callback(cur);
}
}
} }
class array_port_resolv_list_t : public resolv_list_s { class array_port_resolv_list_t : public resolv_list_s {
@ -780,6 +838,23 @@ bool array_port_resolv_list_t::resolve(bool mes)
return true; return true;
} }
void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle obj)
{
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;
} else if (struct __vpiArrayVthrA*word = array_vthr_a_from_handle(obj)) {
parent = word->array;
cb->extra_data = word->address;
}
assert(parent);
cb->next = parent->vpi_callbacks;
parent->vpi_callbacks = cb;
}
void compile_array_port(char*label, char*array, char*addr) void compile_array_port(char*label, char*array, char*addr)
{ {
array_port_resolv_list_t*resolv_mem array_port_resolv_list_t*resolv_mem

View File

@ -45,6 +45,11 @@ extern void array_set_word(vvp_array_t arr,
extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned adddress); extern vvp_vector4_t array_get_word(vvp_array_t array, unsigned adddress);
/* VPI hooks */
extern void vpip_array_word_change(struct __vpiCallback*cb, vpiHandle word);
/* Compile hooks */
extern void compile_variablew(char*label, vvp_array_t array, extern void compile_variablew(char*label, vvp_array_t array,
unsigned long array_addr, unsigned long array_addr,
int msb, int lsb, char signed_flag); int msb, int lsb, char signed_flag);

View File

@ -103,7 +103,7 @@ struct __vpiCallback* new_vpi_callback()
return obj; return obj;
} }
static void delete_vpi_callback(struct __vpiCallback* ref) void delete_vpi_callback(struct __vpiCallback* ref)
{ {
assert(ref); assert(ref);
assert(ref->base.vpi_type); assert(ref->base.vpi_type);
@ -162,6 +162,10 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
nev->callbacks = obj; nev->callbacks = obj;
break; break;
case vpiMemoryWord:
vpip_array_word_change(obj, data->obj);
break;
case vpiModule: case vpiModule:
case vpiConstant: case vpiConstant:
case vpiParameter: case vpiParameter:
@ -461,14 +465,11 @@ void callback_execute(struct __vpiCallback*cur)
vvp_vpi_callback::vvp_vpi_callback() vvp_vpi_callback::vvp_vpi_callback()
{ {
vpi_callbacks_ = 0; vpi_callbacks_ = 0;
array_ = 0;
array_word_ = 0;
} }
vvp_vpi_callback::~vvp_vpi_callback() vvp_vpi_callback::~vvp_vpi_callback()
{ {
assert(vpi_callbacks_ == 0); assert(vpi_callbacks_ == 0);
assert(array_ == 0);
} }
void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb) void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
@ -477,13 +478,6 @@ void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
vpi_callbacks_ = cb; vpi_callbacks_ = cb;
} }
void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
{
assert(array_ == 0);
array_ = arr;
array_word_ = addr;
}
/* /*
* A vvp_fun_signal uses this method to run its callbacks whenever it * A vvp_fun_signal uses this method to run its callbacks whenever it
* has a value change. If the cb_rtn is non-nil, then call the * has a value change. If the cb_rtn is non-nil, then call the
@ -495,8 +489,6 @@ void vvp_vpi_callback::run_vpi_callbacks()
struct __vpiCallback *next = vpi_callbacks_; struct __vpiCallback *next = vpi_callbacks_;
struct __vpiCallback *prev = 0; struct __vpiCallback *prev = 0;
if (array_) array_word_change(array_, array_word_);
while (next) { while (next) {
struct __vpiCallback*cur = next; struct __vpiCallback*cur = next;
next = cur->next; next = cur->next;
@ -523,6 +515,31 @@ void vvp_vpi_callback::run_vpi_callbacks()
} }
} }
vvp_vpi_callback_wordable::vvp_vpi_callback_wordable()
{
array_ = 0;
array_word_ = 0;
}
vvp_vpi_callback_wordable::~vvp_vpi_callback_wordable()
{
assert(array_ == 0);
}
void vvp_vpi_callback_wordable::run_vpi_callbacks()
{
if (array_) array_word_change(array_, array_word_);
vvp_vpi_callback::run_vpi_callbacks();
}
void vvp_vpi_callback_wordable::attach_as_word(vvp_array_t arr, unsigned long addr)
{
assert(array_ == 0);
array_ = arr;
array_word_ = addr;
}
void vvp_fun_signal::get_value(struct t_vpi_value*vp) void vvp_fun_signal::get_value(struct t_vpi_value*vp)
{ {
switch (vp->format) { switch (vp->format) {

View File

@ -141,11 +141,15 @@ struct __vpiCallback {
// scheduled event // scheduled event
struct sync_cb* cb_sync; struct sync_cb* cb_sync;
// The calback holder may use this for various purposes.
long extra_data;
// Used for listing callbacks. // Used for listing callbacks.
struct __vpiCallback*next; struct __vpiCallback*next;
}; };
extern struct __vpiCallback* new_vpi_callback(); extern struct __vpiCallback* new_vpi_callback();
extern void delete_vpi_callback(struct __vpiCallback* ref);
extern void callback_execute(struct __vpiCallback*cur); extern void callback_execute(struct __vpiCallback*cur);
struct __vpiSystemTime { struct __vpiSystemTime {

View File

@ -882,20 +882,29 @@ class vvp_vpi_callback {
vvp_vpi_callback(); vvp_vpi_callback();
virtual ~vvp_vpi_callback(); virtual ~vvp_vpi_callback();
void run_vpi_callbacks(); virtual void run_vpi_callbacks();
void add_vpi_callback(struct __vpiCallback*); void add_vpi_callback(struct __vpiCallback*);
virtual void get_value(struct t_vpi_value*value) =0; virtual void get_value(struct t_vpi_value*value) =0;
private:
struct __vpiCallback*vpi_callbacks_;
};
class vvp_vpi_callback_wordable : public vvp_vpi_callback {
public:
vvp_vpi_callback_wordable();
~vvp_vpi_callback_wordable();
void run_vpi_callbacks();
void attach_as_word(class __vpiArray* arr, unsigned long addr); void attach_as_word(class __vpiArray* arr, unsigned long addr);
private: private:
struct __vpiCallback*vpi_callbacks_;
class __vpiArray* array_; class __vpiArray* array_;
unsigned long array_word_; unsigned long array_word_;
}; };
class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback { class vvp_fun_signal_base : public vvp_net_fun_t, public vvp_vpi_callback_wordable {
public: public:
vvp_fun_signal_base(); vvp_fun_signal_base();