diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 0dd437501..3958a871b 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.23 2001/06/12 03:53:11 steve Exp $" +#ident "$Id: Makefile.in,v 1.24 2001/06/21 22:54:12 steve Exp $" # # SHELL = /bin/sh @@ -58,8 +58,8 @@ distclean: clean check: all ./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.' -V = vpi_modules.o vpi_const.o vpi_iter.o vpi_mcd.o vpi_priv.o \ -vpi_scope.o vpi_signal.o vpi_tasks.o vpi_time.o vpi_memory.o \ +V = vpi_modules.o vpi_callback.o vpi_const.o vpi_iter.o vpi_mcd.o \ +vpi_priv.o vpi_scope.o vpi_signal.o vpi_tasks.o vpi_time.o vpi_memory.o \ vpi_vthr_vector.o vvp_vpi.o O = main.o parse.o parse_misc.o lexor.o arith.o bufif.o compile.o debug.o \ diff --git a/vvp/functor.cc b/vvp/functor.cc index b15ae0802..b26425da6 100644 --- a/vvp/functor.cc +++ b/vvp/functor.cc @@ -17,13 +17,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: functor.cc,v 1.22 2001/05/31 04:12:43 steve Exp $" +#ident "$Id: functor.cc,v 1.23 2001/06/21 22:54:12 steve Exp $" #endif # include "functor.h" # include "udp.h" # include "schedule.h" # include "vthread.h" +# include "vpi_priv.h" # include "debug.h" # include @@ -290,6 +291,11 @@ void functor_set(vvp_ipoint_t ptr, unsigned bit, unsigned str, bool push) break; } + if (fp->callback) { + fp->callback = 0; + vpip_trip_functor_callbacks(ptr); + } + #if defined(WITH_DEBUG) if (fp->breakpoint) breakpoint(); @@ -359,6 +365,9 @@ const unsigned char ft_var[16] = { /* * $Log: functor.cc,v $ + * Revision 1.23 2001/06/21 22:54:12 steve + * Support cbValueChange callbacks. + * * Revision 1.22 2001/05/31 04:12:43 steve * Make the bufif0 and bufif1 gates strength aware, * and accurately propagate strengths of outputs. diff --git a/vvp/functor.h b/vvp/functor.h index 9d8c6a345..38b5791a6 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.25 2001/06/19 03:01:10 steve Exp $" +#ident "$Id: functor.h,v 1.26 2001/06/21 22:54:12 steve Exp $" #endif # include "pointers.h" @@ -140,7 +140,8 @@ struct functor_s { unsigned odrive1 : 3; /* Strength form of the output value. */ unsigned ostr : 8; - + /* set this flag if there might be a waiting callback. */ + unsigned callback : 1; #if defined(WITH_DEBUG) /* True if this functor triggers a breakpoint. */ unsigned breakpoint : 1; @@ -294,6 +295,9 @@ extern const unsigned char ft_var[]; /* * $Log: functor.h,v $ + * Revision 1.26 2001/06/21 22:54:12 steve + * Support cbValueChange callbacks. + * * Revision 1.25 2001/06/19 03:01:10 steve * Add structural EEQ gates (Stephan Boettcher) * diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc new file mode 100644 index 000000000..dbef2eed6 --- /dev/null +++ b/vvp/vpi_callback.cc @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined(WINNT) +#ident "$Id: vpi_callback.cc,v 1.1 2001/06/21 22:54:12 steve Exp $" +#endif + +/* + * Callbacks are objects that carry a function to be called when some + * event in the simulation occurs. The VPI code create a __vpiCallback + * object, and that object is put in some location that the simulation + * can look when the event in question is tripped. + */ + +# include +# include "vpi_priv.h" +# include "schedule.h" +# include +# include + + +const struct __vpirt callback_rt = { + vpiCallback, + + 0, + 0, + 0, + 0, + + 0, + 0, + 0 +}; + +/* + * A value change callback is tripped when a bit of a signal + * changes. This function creates that value change callback and + * attaches it to the relevent vpiSignal object. Also flag the + * functors associated with the signal so that they know to trip. + */ +static struct __vpiCallback* make_value_change(p_cb_data data) +{ + struct __vpiCallback*obj = new __vpiCallback; + obj->base.vpi_type = &callback_rt; + obj->cb_data = *data; + + assert((data->obj->vpi_type->type_code == vpiReg) + || (data->obj->vpi_type->type_code == vpiNet)); + struct __vpiSignal*sig = reinterpret_cast<__vpiSignal*>(data->obj); + + /* Attach the callback to the signal who's value I'm waiting for. */ + obj->next = sig->callbacks; + sig->callbacks = obj; + + unsigned wid = (sig->msb >= sig->lsb) + ? sig->msb - sig->lsb + 1 + : sig->lsb - sig->msb + 1; + + /* Make sure the functors are tickled to trigger a callback. */ + for (unsigned idx = 0 ; idx < wid ; idx += 1) { + vvp_ipoint_t ptr = ipoint_index(sig->bits, idx); + functor_t fun = functor_index(ptr); + fun->callback |= 1; + } + + return obj; +} + +vpiHandle vpi_register_cb(p_cb_data data) +{ + struct __vpiCallback*obj = 0; + + switch (data->reason) { + + case cbValueChange: + obj = make_value_change(data); + break; + + default: + fprintf(stderr, "vpi error: vpi_register_cb invalid or " + "unsupported callback reason: %d\n", + data->reason); + break; + } + + return obj? &obj->base : 0; +} + + +int vpi_remove_cb(vpiHandle ref) +{ + assert(ref->vpi_type->type_code == vpiCallback); + + struct __vpiCallback*obj = reinterpret_cast<__vpiCallback*>(ref); + + fprintf(stderr, "vpi error: vpi_remove_cb not supported\n"); + + return 0; +} + +void vpip_trip_functor_callbacks(vvp_ipoint_t ptr) +{ + struct __vpiSignal*sig = vpip_sig_from_ptr(ptr); + assert(sig); + + struct __vpiCallback*callbacks = sig->callbacks; + sig->callbacks = 0; + + while (callbacks) { + struct __vpiCallback*cur = callbacks; + callbacks = cur->next; + + cur->cb_data.time->type = vpiSimTime; + cur->cb_data.time->low = schedule_simtime(); + cur->cb_data.time->high = 0; + (cur->cb_data.cb_rtn)(&cur->cb_data); + delete cur; + } +} + +void vpip_trip_monitor_callbacks(void) +{ +} + + +/* + * $Log: vpi_callback.cc,v $ + * Revision 1.1 2001/06/21 22:54:12 steve + * Support cbValueChange callbacks. + * + */ + diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index dfe5e1e47..4f5260fe4 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_priv.cc,v 1.5 2001/06/12 03:53:11 steve Exp $" +#ident "$Id: vpi_priv.cc,v 1.6 2001/06/21 22:54:12 steve Exp $" #endif # include "vpi_priv.h" @@ -137,20 +137,6 @@ extern "C" void vpi_vprintf(const char*fmt, va_list ap) vprintf(fmt, ap); } -/* STUBS */ - -vpiHandle vpi_register_cb(p_cb_data data) -{ - fprintf(stderr, "vpi Sorry: vpi_register_cb not supported\n"); - return 0; -} - - -int vpi_remove_cb(vpiHandle ref) -{ - assert(0); - return 0; -} extern "C" void vpi_sim_vcontrol(int operation, va_list ap) { @@ -166,6 +152,9 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap) /* * $Log: vpi_priv.cc,v $ + * Revision 1.6 2001/06/21 22:54:12 steve + * Support cbValueChange callbacks. + * * Revision 1.5 2001/06/12 03:53:11 steve * Change the VPI call process so that loaded .vpi modules * use a function table instead of implicit binding. diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index d60b38a43..be8b22d03 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.16 2001/05/20 00:46:12 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.17 2001/06/21 22:54:12 steve Exp $" #endif # include "vpi_user.h" @@ -109,11 +109,31 @@ struct __vpiSignal { unsigned signed_flag : 1; /* The represented value is here. */ vvp_ipoint_t bits; + /* Call these items on a callback event. */ + struct __vpiCallback*callbacks; + /* Keep in a binary tree, ordered by bits member. */ + struct __vpiSignal* by_bits[2]; }; extern vpiHandle vpip_make_reg(char*name, int msb, int lsb, bool signed_flag, vvp_ipoint_t base); extern vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag, vvp_ipoint_t base); +extern struct __vpiSignal*vpip_sig_from_ptr(vvp_ipoint_t ptr); + +/* + * Callback handles are created when the VPI function registers a + * callback. The handle is stored by the run time, and it triggered + * when the run-time thing that it is waiting for happens. + */ +struct __vpiCallback { + struct __vpiHandle base; + + struct t_cb_data cb_data; + + struct __vpiCallback*next; +}; + +extern void vpip_trip_functor_callbacks(vvp_ipoint_t ptr); /* * Memory is an array of bits that is accessible in N-bit chunks, with @@ -231,6 +251,9 @@ vpiHandle vpip_sim_time(void); /* * $Log: vpi_priv.h,v $ + * Revision 1.17 2001/06/21 22:54:12 steve + * Support cbValueChange callbacks. + * * Revision 1.16 2001/05/20 00:46:12 steve * Add support for system function calls. * @@ -243,46 +266,5 @@ vpiHandle vpip_sim_time(void); * Revision 1.14 2001/05/08 23:59:33 steve * Add ivl and vvp.tgt support for memories in * expressions and l-values. (Stephan Boettcher) - * - * Revision 1.13 2001/04/18 04:21:23 steve - * Put threads into scopes. - * - * Revision 1.12 2001/04/05 01:34:26 steve - * Add the .var/s and .net/s statements for VPI support. - * - * Revision 1.11 2001/04/04 17:43:19 steve - * support decimal strings from signals. - * - * Revision 1.10 2001/04/04 04:33:09 steve - * Take vector form as parameters to vpi_call. - * - * Revision 1.9 2001/04/02 00:24:31 steve - * Take numbers as system task parameters. - * - * Revision 1.8 2001/03/31 19:00:44 steve - * Add VPI support for the simulation time. - * - * Revision 1.7 2001/03/25 00:35:35 steve - * Add the .net statement. - * - * Revision 1.6 2001/03/23 02:40:23 steve - * Add the :module header statement. - * - * Revision 1.5 2001/03/21 05:13:03 steve - * Allow var objects as vpiHandle arguments to %vpi_call. - * - * Revision 1.4 2001/03/20 06:16:24 steve - * Add support for variable vectors. - * - * Revision 1.3 2001/03/18 04:35:18 steve - * Add support for string constants to VPI. - * - * Revision 1.2 2001/03/18 00:37:55 steve - * Add support for vpi scopes. - * - * Revision 1.1 2001/03/16 01:44:34 steve - * Add structures for VPI support, and all the %vpi_call - * instruction. Get linking of VPI modules to work. - * */ #endif diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 447ee6b7f..48ba124a2 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_signal.cc,v 1.15 2001/05/30 03:02:35 steve Exp $" +#ident "$Id: vpi_signal.cc,v 1.16 2001/06/21 22:54:12 steve Exp $" #endif /* @@ -366,6 +366,58 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp, } +static struct __vpiSignal*by_bits_root = 0; +static void by_bits_insert(struct __vpiSignal*sig) +{ + if (by_bits_root == 0) { + by_bits_root = sig; + return; + } + + struct __vpiSignal*cur = by_bits_root; + for (;;) { + if (cur->bits > sig->bits) { + if (cur->by_bits[0] == 0) { + cur->by_bits[0] = sig; + break; + } + cur = cur->by_bits[0]; + + } else { + if (cur->by_bits[1] == 0) { + cur->by_bits[1] = sig; + break; + } + cur = cur->by_bits[1]; + } + } +} + +struct __vpiSignal* vpip_sig_from_ptr(vvp_ipoint_t ptr) +{ + struct __vpiSignal*cur = by_bits_root; + + while (cur) { + if (ptr < cur->bits) { + cur = cur->by_bits[0]; + continue; + } + + unsigned wid = (cur->msb > cur->lsb) + ? cur->msb - cur->lsb + : cur->lsb - cur->msb; + + if (ptr > ipoint_index(cur->bits, wid)) { + cur = cur->by_bits[1]; + continue; + } + + return cur; + } + + return cur; +} + static const struct __vpirt vpip_reg_rt = { vpiReg, signal_get, @@ -401,9 +453,14 @@ vpiHandle vpip_make_reg(char*name, int msb, int lsb, bool signed_flag, obj->lsb = lsb; obj->signed_flag = signed_flag? 1 : 0; obj->bits = base; + obj->callbacks = 0; + obj->by_bits[0] = 0; + obj->by_bits[1] = 0; obj->scope = vpip_peek_current_scope(); + by_bits_insert(obj); + return &obj->base; } @@ -423,15 +480,23 @@ vpiHandle vpip_make_net(char*name, int msb, int lsb, bool signed_flag, obj->lsb = lsb; obj->signed_flag = signed_flag? 1 : 0; obj->bits = base; + obj->callbacks = 0; + obj->by_bits[0] = 0; + obj->by_bits[1] = 0; obj->scope = vpip_peek_current_scope(); + by_bits_insert(obj); + return &obj->base; } /* * $Log: vpi_signal.cc,v $ + * Revision 1.16 2001/06/21 22:54:12 steve + * Support cbValueChange callbacks. + * * Revision 1.15 2001/05/30 03:02:35 steve * Propagate strength-values instead of drive strengths. *