diff --git a/vvp/event.cc b/vvp/event.cc index c454bb5e7..3fb5769dc 100644 --- a/vvp/event.cc +++ b/vvp/event.cc @@ -17,13 +17,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: event.cc,v 1.6 2002/05/18 02:34:11 steve Exp $" +#ident "$Id: event.cc,v 1.7 2002/05/19 05:18:16 steve Exp $" #endif # include "event.h" # include "compile.h" # include "vthread.h" # include "schedule.h" +# include "vpi_priv.h" # include # include @@ -33,8 +34,10 @@ #endif event_functor_s::event_functor_s(edge_t e) - : edge(e), threads(0) -{} +: edge(e) +{ + threads = 0; +} event_functor_s::~event_functor_s() {} @@ -87,6 +90,24 @@ void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned) } } +named_event_functor_s::~named_event_functor_s() +{ +} + +void named_event_functor_s::set(vvp_ipoint_t ptr, bool push, + unsigned val, unsigned str) +{ + put(ptr, val); + + if (threads) { + vthread_t tmp = threads; + threads = 0; + vthread_schedule_list(tmp); + } + + vpip_run_named_event_callbacks(handle); +} + /* ** Create an event functor ** edge: compile_event(label, type, argc, argv) @@ -148,20 +169,23 @@ void compile_event(char*label, char*type, */ void compile_named_event(char*label, char*name) { - functor_t obj = new event_functor_s(vvp_edge_none); + named_event_functor_s* obj = new named_event_functor_s; vvp_ipoint_t fdx = functor_allocate(1); functor_define(fdx, obj); define_functor_symbol(label, fdx); - vpiHandle vpi = vpip_make_named_event(name); - vpip_attach_to_current_scope(vpi); + obj->handle = vpip_make_named_event(name); + vpip_attach_to_current_scope(obj->handle); free(label); } /* * $Log: event.cc,v $ + * Revision 1.7 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.6 2002/05/18 02:34:11 steve * Add vpi support for named events. * diff --git a/vvp/event.h b/vvp/event.h index 3e9a1b413..5b6074a72 100644 --- a/vvp/event.h +++ b/vvp/event.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: event.h,v 1.1 2001/11/06 03:07:22 steve Exp $" +#ident "$Id: event.h,v 1.2 2002/05/19 05:18:16 steve Exp $" #endif # include "functor.h" @@ -28,13 +28,12 @@ * Event / edge detection functors */ -struct event_functor_s: public edge_inputs_functor_s { +struct event_functor_s: public edge_inputs_functor_s, public waitable_hooks_s { typedef unsigned short edge_t; explicit event_functor_s(edge_t e); virtual ~event_functor_s(); virtual void set(vvp_ipoint_t i, bool push, unsigned val, unsigned str); edge_t edge; - vthread_t threads; }; #define VVP_EDGE(a,b) (1<<(((a)<<2)|(b))) @@ -58,6 +57,20 @@ const event_functor_s::edge_t vvp_edge_negedge const event_functor_s::edge_t vvp_edge_anyedge = 0x7bde; const event_functor_s::edge_t vvp_edge_none = 0; +/* + * This is a functor to represent named events. This functor has no + * inputs, and no output. It is a functor so that the %wait and %set + * instructions can get at it. + */ +struct named_event_functor_s : public waitable_hooks_s, public functor_s { + + public: + ~named_event_functor_s(); + void set(vvp_ipoint_t ipt, bool push, unsigned val, unsigned str =0); + + struct __vpiHandle* handle; +}; + /* * Callback functors. */ @@ -66,6 +79,9 @@ struct callback_functor_s *vvp_fvector_make_callback /* * $Log: event.h,v $ + * Revision 1.2 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.1 2001/11/06 03:07:22 steve * Code rearrange. (Stephan Boettcher) * diff --git a/vvp/functor.h b/vvp/functor.h index e2e2dfd7a..55db6f15b 100644 --- a/vvp/functor.h +++ b/vvp/functor.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.h,v 1.45 2002/03/17 03:23:10 steve Exp $" +#ident "$Id: functor.h,v 1.46 2002/05/19 05:18:16 steve Exp $" #endif # include "pointers.h" @@ -328,6 +328,14 @@ unsigned functor_get(vvp_ipoint_t ptr) // Special infrastructure functor types +/* + * A "waitable" functor is one that the %wait instruction can wait + * on. This includes the infrastructure needed to hold threads. + */ +struct waitable_hooks_s { + vthread_t threads; +}; + // The extra_outputs_functor_s class is for devices that require // multiple inputs and outputs. @@ -386,6 +394,9 @@ extern vvp_fvector_t vvp_fvector_continuous_new(unsigned size, vvp_ipoint_t p); /* * $Log: functor.h,v $ + * Revision 1.46 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.45 2002/03/17 03:23:10 steve * Force the push flags to be explicit. * diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 15fa5f45a..e5f155817 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_callback.cc,v 1.16 2002/05/18 02:34:11 steve Exp $" +#ident "$Id: vpi_callback.cc,v 1.17 2002/05/19 05:18:16 steve Exp $" #endif /* @@ -78,26 +78,12 @@ const struct __vpirt callback_rt = { * event. This member is only used for things like cbReadOnlySync. */ -struct __vpiCallback { - struct __vpiHandle base; - - // user supplied callback data - struct t_cb_data cb_data; - struct t_vpi_time cb_time; - - // scheduled event - struct sync_cb* cb_sync; - - // Used for listing callbacks. - struct __vpiCallback*next; -}; - struct sync_cb : public vvp_gen_event_s { struct __vpiCallback*handle; }; -inline static struct __vpiCallback* new_vpi_callback() +struct __vpiCallback* new_vpi_callback() { struct __vpiCallback* obj; @@ -209,22 +195,40 @@ static struct __vpiCallback* make_value_change(p_cb_data data) assert(data->obj); assert(data->obj->vpi_type); - assert((data->obj->vpi_type->type_code == vpiReg) - || (data->obj->vpi_type->type_code == vpiNet)); - struct __vpiSignal*sig = reinterpret_cast<__vpiSignal*>(data->obj); - /* Create callback functors, if necessary, to do the value - change detection and carry the callback objects. */ - if (sig->callback == 0) { - sig->callback = vvp_fvector_make_callback(sig->bits); - assert(sig->callback); + switch (data->obj->vpi_type->type_code) { + + case vpiReg: + case vpiNet: + struct __vpiSignal*sig; + sig = reinterpret_cast<__vpiSignal*>(data->obj); + + /* Create callback functors, if necessary, to do the + value change detection and carry the callback + objects. */ + if (sig->callback == 0) { + sig->callback = vvp_fvector_make_callback(sig->bits); + assert(sig->callback); + } + + /* Attach the __vpiCallback object to the signals + callback functors. */ + obj->next = sig->callback->cb_handle; + sig->callback->cb_handle = obj; + break; + + case vpiNamedEvent: + struct __vpiNamedEvent*nev; + nev = reinterpret_cast<__vpiNamedEvent*>(data->obj); + obj->next = nev->callbacks; + nev->callbacks = obj; + break; + + default: + assert(0); + break; } - /* Attach the __vpiCallback object to the signals callback - functors. */ - obj->next = sig->callback->cb_handle; - sig->callback->cb_handle = obj; - return obj; } @@ -410,6 +414,18 @@ int vpi_remove_cb(vpiHandle ref) return 0; } +void callback_execute(struct __vpiCallback*cur) +{ + assert(vpi_mode_flag == VPI_MODE_NONE); + vpi_mode_flag = VPI_MODE_RWSYNC; + + cur->cb_data.time->type = vpiSimTime; + vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime()); + (cur->cb_data.cb_rtn)(&cur->cb_data); + + vpi_mode_flag = VPI_MODE_NONE; +} + /* * A callback_functor_s functor uses its set method to detect value * changes. When a value comes in, the __vpiCallback objects that are @@ -435,14 +451,7 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned) } } - assert(vpi_mode_flag == VPI_MODE_NONE); - vpi_mode_flag = VPI_MODE_RWSYNC; - - cur->cb_data.time->type = vpiSimTime; - vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime()); - (cur->cb_data.cb_rtn)(&cur->cb_data); - - vpi_mode_flag = VPI_MODE_NONE; + callback_execute(cur); } } @@ -450,6 +459,9 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned) /* * $Log: vpi_callback.cc,v $ + * Revision 1.17 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.16 2002/05/18 02:34:11 steve * Add vpi support for named events. * diff --git a/vvp/vpi_event.cc b/vvp/vpi_event.cc index bcf452645..d33df654a 100644 --- a/vvp/vpi_event.cc +++ b/vvp/vpi_event.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_event.cc,v 1.1 2002/05/18 02:34:11 steve Exp $" +#ident "$Id: vpi_event.cc,v 1.2 2002/05/19 05:18:16 steve Exp $" #endif # include "vpi_priv.h" @@ -30,27 +30,59 @@ # include # include -struct __vpiNamedEvent { - struct __vpiHandle base; - /* base name of the event object */ - char*name; - /* Parent scope of this object. */ - struct __vpiScope*scope; -}; +static char* named_event_str(int code, vpiHandle ref) +{ + assert((ref->vpi_type->type_code==vpiNamedEvent)); + + struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)ref; + + switch (code) { + + case vpiName: + return obj->name; + + } + + return 0; +} + +static vpiHandle named_event_get_handle(int code, vpiHandle ref) +{ + assert((ref->vpi_type->type_code==vpiNamedEvent)); + + struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)ref; + + switch (code) { + + case vpiScope: + return &obj->scope->base; + } + + return 0; +} + +/* + * We keep the object around, in case we need it again. It's all we + * can do, because it cannot be recreated. + */ +static int named_event_free_object(vpiHandle) +{ + return 0; +} static const struct __vpirt vpip_named_event_rt = { vpiNamedEvent, 0, - 0, + named_event_str, 0, 0, - 0, + named_event_get_handle, 0, 0, - 0 + named_event_free_object }; vpiHandle vpip_make_named_event(char*name) @@ -61,12 +93,30 @@ vpiHandle vpip_make_named_event(char*name) obj->base.vpi_type = &vpip_named_event_rt; obj->name = name; obj->scope = vpip_peek_current_scope(); + obj->callbacks = 0; return &obj->base; } +void vpip_run_named_event_callbacks(vpiHandle ref) +{ + assert((ref->vpi_type->type_code==vpiNamedEvent)); + + struct __vpiNamedEvent*obj = (struct __vpiNamedEvent*)ref; + + struct __vpiCallback*cur = obj->callbacks; + while (cur) { + struct __vpiCallback*next = cur->next; + callback_execute(cur); + cur = next; + } +} + /* * $Log: vpi_event.cc,v $ + * Revision 1.2 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.1 2002/05/18 02:34:11 steve * Add vpi support for named events. * diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 767e3b283..665990544 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_priv.h,v 1.35 2002/05/18 02:34:11 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.36 2002/05/19 05:18:16 steve Exp $" #endif # include "vpi_user.h" @@ -107,6 +107,27 @@ struct __vpiIterator { extern vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args, bool free_args_flag); +/* + * This represents callback handles. There are some privat types that + * are defined and used in vpi_callback.cc. + */ +struct __vpiCallback { + struct __vpiHandle base; + + // user supplied callback data + struct t_cb_data cb_data; + struct t_vpi_time cb_time; + + // scheduled event + struct sync_cb* cb_sync; + + // Used for listing callbacks. + struct __vpiCallback*next; +}; + +extern struct __vpiCallback* new_vpi_callback(); +extern void callback_execute(struct __vpiCallback*cur); + /* * Scopes are created by .scope statements in the source. */ @@ -155,7 +176,18 @@ extern vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag, * passed in will be saved, so the caller must allocate it (or not * free it) after it is handed to this function. */ +struct __vpiNamedEvent { + struct __vpiHandle base; + /* base name of the event object */ + char*name; + /* Parent scope of this object. */ + struct __vpiScope*scope; + /* List of callbacks interested in this event. */ + struct __vpiCallback*callbacks; +}; + extern vpiHandle vpip_make_named_event(char*name); +extern void vpip_run_named_event_callbacks(vpiHandle ref); /* * Memory is an array of bits that is accessible in N-bit chunks, with @@ -326,6 +358,9 @@ extern void vpip_oct_str_to_bits(unsigned char*bits, unsigned nbits, /* * $Log: vpi_priv.h,v $ + * Revision 1.36 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.35 2002/05/18 02:34:11 steve * Add vpi support for named events. * diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 8fe371c79..674c52cd5 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vthread.cc,v 1.70 2002/05/12 23:44:41 steve Exp $" +#ident "$Id: vthread.cc,v 1.71 2002/05/19 05:18:16 steve Exp $" #endif # include "vthread.h" @@ -1760,7 +1760,7 @@ bool of_WAIT(vthread_t thr, vvp_code_t cp) { assert(! thr->waiting_for_event); thr->waiting_for_event = 1; - vvp_event_t ep = dynamic_cast(functor_index(cp->iptr)); + waitable_hooks_s* ep = dynamic_cast(functor_index(cp->iptr)); assert(ep); thr->wait_next = ep->threads; ep->threads = thr; @@ -1884,6 +1884,9 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp) /* * $Log: vthread.cc,v $ + * Revision 1.71 2002/05/19 05:18:16 steve + * Add callbacks for vpiNamedEvent objects. + * * Revision 1.70 2002/05/12 23:44:41 steve * task calls and forks push the thread event in the queue. *