Permalink
Browse files

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.
  • Loading branch information...
steveicarus committed May 21, 2008
1 parent 007056d commit d1daf6733f0574092e92afe37c39d215b6b1b9be
Showing with 137 additions and 26 deletions.
  1. +1 −0 vpi/sys_display.c
  2. +85 −10 vvp/array.cc
  3. +5 −0 vvp/array.h
  4. +30 −13 vvp/vpi_callback.cc
  5. +4 −0 vvp/vpi_priv.h
  6. +12 −3 vvp/vvp_net.h
View
@@ -1122,6 +1122,7 @@ static PLI_INT32 sys_monitor_calltf(PLI_BYTE8*name)
case vpiReg:
case vpiIntegerVar:
case vpiRealVar:
+ case vpiMemoryWord:
/* Monitoring reg and net values involves setting
a callback for value changes. Pass the storage
pointer for the callback itself as user_data so
View
@@ -63,6 +63,7 @@ struct __vpiArray {
struct __vpiArrayWord*vals_words;
class vvp_fun_arrayport*ports_;
+ struct __vpiCallback *vpi_callbacks;
};
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), \
(struct __vpiArray*)ref)
-# define ARRAY_VAR_WORD(ref) (assert(ref->vpi_type->type_code==vpiMemoryWord), \
- (struct __vpiArrayWord*)ref)
+static struct __vpiArrayWord* array_var_word_from_handle(vpiHandle ref)
+{
+ if (ref == 0)
+ return 0;
+ if (ref->vpi_type != &vpip_array_var_word_rt)
+ return 0;
+
+ return (struct __vpiArrayWord*) ref;
+}
-# define ARRAY_VTHR_A_HANDLE(ref) (assert(ref->vpi_type->type_code==vpiMemoryWord), \
- (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)
{
@@ -315,9 +330,10 @@ static vpiHandle vpi_array_index(vpiHandle ref, int index)
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;
+ assert(obj);
decode_array_word_pointer(obj, parent);
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)
{
- struct __vpiArrayWord*obj = ARRAY_VAR_WORD(ref);
+ struct __vpiArrayWord*obj = array_var_word_from_handle(ref);
struct __vpiArray*parent;
+ assert(obj);
unsigned index = decode_array_word_pointer(obj, parent);
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)
{
- struct __vpiArrayWord*obj = ARRAY_VAR_WORD(ref);
+ struct __vpiArrayWord*obj = array_var_word_from_handle(ref);
struct __vpiArray*parent;
+ assert(obj);
unsigned index = decode_array_word_pointer(obj, parent);
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)
{
- struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref);
+ struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
+ assert(obj);
struct __vpiArray*parent = obj->array;
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)
{
- struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref);
+ struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
+ assert(obj);
struct __vpiArray*parent = obj->array;
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)
{
- struct __vpiArrayVthrA*obj = ARRAY_VTHR_A_HANDLE(ref);
+ struct __vpiArrayVthrA*obj = array_vthr_a_from_handle(ref);
+ assert(obj);
struct __vpiArray*parent = obj->array;
unsigned index = obj->address;
@@ -579,6 +600,7 @@ static vpiHandle vpip_make_array(char*label, const char*name,
// Initialize (clear) the read-ports list.
obj->ports_ = 0;
+ obj->vpi_callbacks = 0;
/* Add this symbol to the array_symbols table for later lookup. */
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_)
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 {
@@ -780,6 +838,23 @@ bool array_port_resolv_list_t::resolve(bool mes)
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)
{
array_port_resolv_list_t*resolv_mem
View
@@ -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);
+/* 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,
unsigned long array_addr,
int msb, int lsb, char signed_flag);
View
@@ -103,7 +103,7 @@ struct __vpiCallback* new_vpi_callback()
return obj;
}
-static void delete_vpi_callback(struct __vpiCallback* ref)
+void delete_vpi_callback(struct __vpiCallback* ref)
{
assert(ref);
assert(ref->base.vpi_type);
@@ -162,6 +162,10 @@ static struct __vpiCallback* make_value_change(p_cb_data data)
nev->callbacks = obj;
break;
+ case vpiMemoryWord:
+ vpip_array_word_change(obj, data->obj);
+ break;
+
case vpiModule:
case vpiConstant:
case vpiParameter:
@@ -461,14 +465,11 @@ void callback_execute(struct __vpiCallback*cur)
vvp_vpi_callback::vvp_vpi_callback()
{
vpi_callbacks_ = 0;
- array_ = 0;
- array_word_ = 0;
}
vvp_vpi_callback::~vvp_vpi_callback()
{
assert(vpi_callbacks_ == 0);
- assert(array_ == 0);
}
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;
}
-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
* 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 *prev = 0;
- if (array_) array_word_change(array_, array_word_);
-
while (next) {
struct __vpiCallback*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)
{
switch (vp->format) {
View
@@ -141,11 +141,15 @@ struct __vpiCallback {
// scheduled event
struct sync_cb* cb_sync;
+ // The calback holder may use this for various purposes.
+ long extra_data;
+
// Used for listing callbacks.
struct __vpiCallback*next;
};
extern struct __vpiCallback* new_vpi_callback();
+extern void delete_vpi_callback(struct __vpiCallback* ref);
extern void callback_execute(struct __vpiCallback*cur);
struct __vpiSystemTime {
View
@@ -882,20 +882,29 @@ class vvp_vpi_callback {
vvp_vpi_callback();
virtual ~vvp_vpi_callback();
- void run_vpi_callbacks();
+ virtual void run_vpi_callbacks();
void add_vpi_callback(struct __vpiCallback*);
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);
private:
- struct __vpiCallback*vpi_callbacks_;
class __vpiArray* array_;
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:
vvp_fun_signal_base();

0 comments on commit d1daf67

Please sign in to comment.