diff --git a/t-vvm.cc b/t-vvm.cc index b7053435d..5bbcd889a 100644 --- a/t-vvm.cc +++ b/t-vvm.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: t-vvm.cc,v 1.64 1999/10/23 16:27:53 steve Exp $" +#ident "$Id: t-vvm.cc,v 1.65 1999/10/28 00:47:24 steve Exp $" #endif # include @@ -40,6 +40,9 @@ static string make_temp() } class target_vvm : public target_t { + + friend class vvm_parm_rval; + public: target_vvm(); @@ -105,6 +108,10 @@ class target_vvm : public target_t { // of things that may be scanned multiple times. mapesignal_printed_flag; mappevent_printed_flag; + + // String constants that are made into vpiHandles have th + // handle name mapped by this. + mapstring_constants; }; @@ -454,8 +461,8 @@ static string emit_proc_rval(ostream&os, unsigned indent, const NetExpr*expr) class vvm_parm_rval : public expr_scan_t { public: - explicit vvm_parm_rval(ostream&os) - : result(""), os_(os) { } + explicit vvm_parm_rval(ostream&o, target_vvm*t) + : result(""), os_(o), tgt_(t) { } string result; @@ -466,54 +473,64 @@ class vvm_parm_rval : public expr_scan_t { private: ostream&os_; + target_vvm*tgt_; }; void vvm_parm_rval::expr_const(const NetEConst*expr) { if (expr->value().is_string()) { - result = make_temp(); - os_ << " struct __vpiHandle " << result << ";" << endl; - os_ << " vvm_make_vpi_parm(&" << result << ", \"" - << expr->value().as_string() << "\");" << endl; - result = "&" + result; + + string& res = tgt_->string_constants[expr->value().as_string()]; + if (res != "") { + result = "&" + res + ".base"; + return; + } + + res = make_temp(); + tgt_->delayed << "struct __vpiStringConst " << res + << ";" << endl; + tgt_->init_code << " vpip_make_string_const(&" << res + << ", \"" << expr->value().as_string() + << "\");" << endl; + tgt_->defn << " extern struct __vpiStringConst " << res + << ";" << endl; + result = "&" + res + ".base"; return; } string tname = make_temp(); - os_ << " vvm_bitset_t<" << + tgt_->defn << " vvm_bitset_t<" << expr->expr_width() << "> " << tname << ";" << endl; for (unsigned idx = 0 ; idx < expr->expr_width() ; idx += 1) { - os_ << " " << tname << "[" << idx << "] = "; + tgt_->defn << " " << tname << "[" << idx << "] = "; switch (expr->value().get(idx)) { case verinum::V0: - os_ << "V0"; + tgt_->defn << "V0"; break; case verinum::V1: - os_ << "V1"; + tgt_->defn << "V1"; break; case verinum::Vx: - os_ << "Vx"; + tgt_->defn << "Vx"; break; case verinum::Vz: - os_ << "Vz"; + tgt_->defn << "Vz"; break; } - os_ << ";" << endl; + tgt_->defn << ";" << endl; } result = make_temp(); - os_ << " struct __vpiHandle " << result << ";" << endl; - os_ << " vvm_make_vpi_parm(&" << result << ", &" << tname - << ");" << endl; + tgt_->defn << " struct __vpiHandle " << result << ";" << endl; + tgt_->defn << " vvm_make_vpi_parm(&" << result << ", &" + << tname << ");" << endl; result = "&" + result; } void vvm_parm_rval::expr_ident(const NetEIdent*expr) { if (expr->name() == "$time") { - os_ << " system_time.val.time.low " - "= sim_->get_sim_time();" << endl; - result = string("&system_time"); + result = string("vpip_sim_time()"); } else { cerr << "Unhandled identifier: " << expr->name() << endl; } @@ -521,13 +538,13 @@ void vvm_parm_rval::expr_ident(const NetEIdent*expr) void vvm_parm_rval::expr_signal(const NetESignal*expr) { - string res = string("&") + mangle(expr->name()) + "_vpi"; + string res = string("&") + mangle(expr->name()) + "_vpi.base"; result = res; } -static string emit_parm_rval(ostream&os, const NetExpr*expr) +static string emit_parm_rval(ostream&os, target_vvm*tgt, const NetExpr*expr) { - vvm_parm_rval scan (os); + vvm_parm_rval scan (os, tgt); expr->expr_scan(&scan); return scan.result; } @@ -554,12 +571,11 @@ void target_vvm::start_design(ostream&os, const Design*mod) os << "# include \"vpi_user.h\"" << endl; os << "# include \"vpi_priv.h\"" << endl; - os << "static struct __vpiHandle system_time;" << endl; process_counter = 0; init_code << "static void design_init(vvm_simulation&sim)" << endl; init_code << "{" << endl; - init_code << " vvm_init_vpi_timevar(&system_time, \"$time\");" + init_code << " vpip_init_simulation();" << endl; start_code << "static void design_start(vvm_simulation&sim)" << endl; start_code << "{" << endl; @@ -1074,13 +1090,16 @@ void target_vvm::net_esignal(ostream&os, const NetESignal*net) mangle(net->name()) << "(\"" << net->name() << "\", &" << mangle(net->name()) << "_bits);" << endl; - os << "static struct __vpiHandle " << mangle(net->name()) << + os << "static struct __vpiSignal " << mangle(net->name()) << "_vpi;" << endl; - init_code << " vvm_init_vpi_handle(&" << - mangle(net->name()) << "_vpi, &" << mangle(net->name()) << - "_bits, &" << mangle(net->name()) << ");" << endl; - + string vpi_name = mangle(net->name()) + "_vpi"; + init_code << " vpip_make_reg(&" << vpi_name << ", \"" << + net->name() << "\");" << endl; + init_code << " " << vpi_name << ".bits = " << + mangle(net->name()) << "_bits.bits;" << endl; + init_code << " " << vpi_name << ".nbits = " << + net->pin_count() << ";" << endl; } /* @@ -1551,22 +1570,19 @@ void target_vvm::proc_stask(ostream&os, const NetSTask*net) for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1) { string val; if (net->parm(idx)) { - val = emit_parm_rval(defn, net->parm(idx)); + val = emit_parm_rval(os, this, net->parm(idx)); } else { - val = make_temp(); - defn << " struct __vpiHandle " << val << ";" << endl; - defn << " vvm_make_vpi_parm(&" << val << ");" << endl; - val = string("&") + val; + val = string("&vpip_null.base"); } defn << " " << ptmp << "[" << idx << "] = " << val << ";" << endl; } - defn << " vvm_calltask(sim_, \"" << net->name() << "\", " << + defn << " vpip_calltask(\"" << net->name() << "\", " << net->nparms() << ", " << ptmp << ");" << endl; - defn << " if (sim_->finished()) return false;" << endl; + defn << " if (vpip_finished()) return false;" << endl; } void target_vvm::proc_utask(ostream&os, const NetUTask*net) @@ -1746,6 +1762,12 @@ extern const struct target tgt_vvm = { }; /* * $Log: t-vvm.cc,v $ + * Revision 1.65 1999/10/28 00:47:24 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.64 1999/10/23 16:27:53 steve * assignment to bit select is aa single bit. * diff --git a/vpi/sys_display.c b/vpi/sys_display.c index d8a59896b..891639cde 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: sys_display.c,v 1.4 1999/10/10 14:50:50 steve Exp $" +#ident "$Id: sys_display.c,v 1.5 1999/10/28 00:47:25 steve Exp $" #endif # include "vpi_user.h" @@ -236,6 +236,30 @@ static int sys_display_calltf(char *name) return 0; } +static int strobe_cb(p_cb_data cb) +{ + vpi_printf("%s NOT IMPLEMENTED YET\n", cb->user_data); + return 0; +} + +static int sys_strobe_calltf(char*name) +{ + struct t_cb_data cb; + struct t_vpi_time time; + + time.type = vpiSimTime; + time.low = 0; + time.high = 0; + + cb.reason = cbReadOnlySynch; + cb.cb_rtn = strobe_cb; + cb.time = &time; + cb.obj = 0; + cb.user_data = name; + vpi_register_cb(&cb); + return 0; +} + void sys_display_register() { s_vpi_systf_data tf_data; @@ -255,11 +279,25 @@ void sys_display_register() tf_data.sizetf = 0; tf_data.user_data = "$write"; vpi_register_systf(&tf_data); + + tf_data.type = vpiSysTask; + tf_data.tfname = "$strobe"; + tf_data.calltf = sys_strobe_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + tf_data.user_data = "$strobe"; + vpi_register_systf(&tf_data); } /* * $Log: sys_display.c,v $ + * Revision 1.5 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.4 1999/10/10 14:50:50 steve * Add Octal dump format. * diff --git a/vpi/vpi_user.h b/vpi/vpi_user.h index f9061ecd9..be05f1fa3 100644 --- a/vpi/vpi_user.h +++ b/vpi/vpi_user.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_user.h,v 1.3 1999/08/19 02:51:03 steve Exp $" +#ident "$Id: vpi_user.h,v 1.4 1999/10/28 00:47:25 steve Exp $" #endif #ifdef __cplusplus @@ -95,6 +95,7 @@ typedef struct t_vpi_value { /* OBJECT CODES */ #define vpiConstant 7 +#define vpiIterator 27 #define vpiNet 36 #define vpiReg 48 #define vpiSysTaskCall 57 @@ -102,6 +103,7 @@ typedef struct t_vpi_value { #define vpiSysTfCall 85 #define vpiArgument 89 +#define vpiCallback 1000 /* PROPERTIES */ #define vpiType 1 @@ -120,6 +122,46 @@ typedef struct t_vpi_value { extern void vpi_register_systf(const struct t_vpi_systf_data*ss); extern void vpi_printf(const char*fmt, ...); +/* + * support for VPI callback functions. + */ +typedef struct t_cb_data { + int reason; + int (*cb_rtn)(struct t_cb_data*cb); + vpiHandle obj; + p_vpi_time time; + p_vpi_value value; + int index; + char*user_data; +} s_cb_data, *p_cb_data; + +#define cbValueChange 1 +#define cbStmt 2 +#define cbForce 3 +#define cbRelease 4 +#define cbAtStartOfSimTime 5 +#define cbReadWriteSynch 6 +#define cbReadOnlySynch 7 +#define cbNextSimTime 8 +#define cbAfterDelay 9 +#define cbEndOfCompile 10 +#define cbStartOfSimulation 11 +#define cbEndOfSimulation 12 +#define cbError 13 +#define cbTchkViolation 14 +#define cbStartOfSave 15 +#define cbEndOfSave 16 +#define cbStartOfRestart 17 +#define cbEndOfRestart 18 +#define cbStartOfReset 19 +#define cbEndOfReset 20 +#define cbEnterInteractive 21 +#define cbExitInteractive 22 +#define cbInteractiveScopeChange 23 +#define cbUnresolvedSystf 24 + +extern vpiHandle vpi_register_cb(p_cb_data data); + /* * This function allows a vpi application to control the simulation * engine. The operation parameter specifies the function to @@ -161,6 +203,12 @@ extern void (*vlog_startup_routines[])(); /* * $Log: vpi_user.h,v $ + * Revision 1.4 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.3 1999/08/19 02:51:03 steve * Add vpi_sim_control * diff --git a/vvm/Makefile.in b/vvm/Makefile.in index eab2a9fd5..39fbbdab0 100644 --- a/vvm/Makefile.in +++ b/vvm/Makefile.in @@ -18,7 +18,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.8 1999/10/22 23:58:13 steve Exp $" +#ident "$Id: Makefile.in,v 1.9 1999/10/28 00:47:25 steve Exp $" # # SHELL = /bin/sh @@ -35,7 +35,7 @@ bindir = $(exec_prefix)/bin libdir = $(exec_prefix)/lib includedir = $(prefix)/include -CC = @CC@ +CC = @CC@ -I$(srcdir) -I$(srcdir)/../vpi CXX = @CXX@ -I$(srcdir) -I$(srcdir)/../vpi INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -43,6 +43,7 @@ INSTALL_DATA = @INSTALL_DATA@ CPPFLAGS = @CPPFLAGS@ @DEFS@ CXXFLAGS = @CXXFLAGS@ +CFLAGS = @CFLAGS@ LDFLAGS = @LDFLAGS@ all: libvvm.a @@ -52,13 +53,25 @@ all: libvvm.a $(CXX) -Wall -fno-exceptions $(CXXFLAGS) -MD -c $< -o $*.o mv $*.d dep +%.o dep/%.d: %.c + @[ -d dep ] || mkdir dep + $(CC) -Wall -fno-exceptions $(CFLAGS) -MD -c $< -o $*.o + mv $*.d dep + O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_monitor.o vvm_pevent.o \ -vvm_simulation.o vvm_thread.o +vvm_simulation.o vvm_thread.o vpip.o + +P = vpi_callback.o \ +vpi_const.o vpi_iter.o vpi_null.o \ +vpi_priv.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o libvvm.a: $O rm -f $@ ar cvq $@ $O +vpip.o: $P + $(LD) -r -o vpip.o $P + clean: rm -f *.o dep/*.d diff --git a/vvm/vpi_callback.c b/vvm/vpi_callback.c new file mode 100644 index 000000000..fea051c45 --- /dev/null +++ b/vvm/vpi_callback.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1999 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.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include + +static struct __vpirt vpip_callback_rt = { + vpiCallback, + 0, + 0, + 0, + 0, + 0 +}; + + +static void vpip_call_callback(void*cp) +{ + struct __vpiCallback*rfp = (struct __vpiCallback*)cp; + assert(rfp->base.vpi_type->type_code == vpiCallback); + rfp->cb_data.cb_rtn(&rfp->cb_data); + free(rfp); +} + +/* + * XXXX This currently does not support (or pay any attention to) the + * delay parameter. Yikes! + */ +vpiHandle vpi_register_cb(p_cb_data data) +{ + struct __vpiCallback*rfp = calloc(1, sizeof(struct __vpiCallback)); + rfp->base.vpi_type = &vpip_callback_rt; + rfp->cb_data = *data; + + switch (data->reason) { + case cbReadOnlySynch: + assert(data->time); + assert(data->time->type == vpiSimTime); + assert(data->time->low == 0); + assert(data->time->high == 0); + rfp->ev = vpip_sim_insert_event(0, rfp, vpip_call_callback, 1); + break; + + default: + assert(0); + } + + return &(rfp->base); +} + + +int vpi_remove_cb(vpiHandle ref) +{ + struct __vpiCallback*rfp = (struct __vpiCallback*)ref; + assert(ref->vpi_type->type_code == vpiCallback); + vpip_sim_cancel_event(rfp->ev); + free(rfp); + return 0; +} + +/* + * $Log: vpi_callback.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_const.c b/vvm/vpi_const.c new file mode 100644 index 000000000..7eb708bad --- /dev/null +++ b/vvm/vpi_const.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1999 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_const.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include + + +static void string_value(vpiHandle ref, p_vpi_value vp) +{ + struct __vpiStringConst*rfp = (struct __vpiStringConst*)ref; + assert(ref->vpi_type->type_code == vpiConstant); + + switch (vp->format) { + case vpiObjTypeVal: + case vpiStringVal: + vp->value.str = rfp->value; + vp->format = vpiStringVal; + break; + + default: + vp->format = vpiSuppressVal; + break; + } +} + +static const struct __vpirt vpip_string_rt = { + vpiConstant, + 0, + 0, + string_value, + 0, + 0 +}; + +vpiHandle vpip_make_string_const(struct __vpiStringConst*ref, const char*val) +{ + ref->base.vpi_type = &vpip_string_rt; + ref->value = val; + return &(ref->base); +} + +/* + * $Log: vpi_const.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_iter.c b/vvm/vpi_iter.c new file mode 100644 index 000000000..6a0478677 --- /dev/null +++ b/vvm/vpi_iter.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999 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_iter.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +/* + * Find here the methods functions in support of iterator objects. + */ + +# include "vpi_priv.h" +# include +# include + +static const struct __vpirt vpip_iterator_rt = { + vpiIterator, + 0, + 0, + 0, + 0, + 0 +}; + +vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args) +{ + struct __vpiIterator*res = calloc(1, sizeof(struct __vpiIterator)); + res->base.vpi_type = &vpip_iterator_rt; + res->args = args; + res->nargs = nargs; + res->next = 0; + + return &(res->base); +} + +/* + * The vpi_scan function only applies to iterators. It returns the + * next vpiHandle in the iterated list. + */ +vpiHandle vpi_scan(vpiHandle ref) +{ + struct __vpiIterator*hp = (struct __vpiIterator*)ref; + assert(ref->vpi_type->type_code == vpiIterator); + + if (hp->next == hp->nargs) { + vpi_free_object(ref); + return 0; + } + + return hp->args[hp->next++]; +} + +/* + * $Log: vpi_iter.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_null.c b/vvm/vpi_null.c new file mode 100644 index 000000000..58a5a5bb6 --- /dev/null +++ b/vvm/vpi_null.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1999 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_null.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" + +static const struct __vpirt vpip_null_rt = { + 0, + 0, + 0, + 0, + 0, + 0 +}; + +struct __vpiNull vpip_null = { + { &vpip_null_rt } +}; + +/* + * $Log: vpi_null.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_priv.c b/vvm/vpi_priv.c new file mode 100644 index 000000000..fb97da427 --- /dev/null +++ b/vvm/vpi_priv.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999 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_priv.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include +# include +# include +# include + +/* + * Keep a list of vpi_systf_data structures. This list is searched + * forward whenever a function is invoked by name, and items are + * pushed in front of the list whenever they are registered. This + * allows entries to override older entries. + */ +struct systf_entry { + struct systf_entry* next; + s_vpi_systf_data systf_data; +}; + +static struct systf_entry*systf_list = 0; + +/* This is the handle of the task currently being called. */ +static struct __vpiSysTaskCall*vpip_cur_task; + + +void vpip_calltask(const char*fname, unsigned nparms, vpiHandle*parms) +{ + struct systf_entry*idx; + struct __vpiSysTaskCall cur_task; + cur_task.base.vpi_type = &vpip_systask_rt; + cur_task.args = parms; + cur_task.nargs = nparms; + + vpip_cur_task = &cur_task; + + /* Look for a systf function to invoke. */ + for (idx = systf_list ; idx ; idx = idx->next) + if (strcmp(fname, idx->systf_data.tfname) == 0) { + cur_task.info = &idx->systf_data; + idx->systf_data.calltf(idx->systf_data.user_data); + return; + } + + + /* Finally, if nothing is found then something is not + right. Print out the function name all the parameters + passed, so that someone can deal with it. */ + vpi_printf("Call %s\n", fname); +} + + +int vpi_free_object(vpiHandle ref) +{ + free(ref); + return 0; +} + +int vpi_get(int property, vpiHandle ref) +{ + if (property == vpiType) + return ref->vpi_type->type_code; + + if (ref->vpi_type->vpi_get_ == 0) + return -1; + + return (ref->vpi_type->vpi_get_)(property, ref); +} + +char* vpi_get_str(int property, vpiHandle ref) +{ + if (ref->vpi_type->vpi_get_str_ == 0) + return 0; + + return (ref->vpi_type->vpi_get_str_)(property, ref); +} + +void vpi_get_value(vpiHandle expr, s_vpi_value*vp) +{ + if (expr->vpi_type->vpi_get_value_) { + (expr->vpi_type->vpi_get_value_)(expr, vp); + return; + } + + vp->format = vpiSuppressVal; +} + +vpiHandle vpi_handle(int type, vpiHandle ref) +{ + if (type == vpiSysTfCall) { + assert(ref == 0); + return &vpip_cur_task->base; + } + + assert(ref->vpi_type->handle_); + return (ref->vpi_type->handle_)(type, ref); +} + +/* + * This function asks the object to return an iterator for + * the specified reference. It is up to the iterate_ method to + * allocate a properly formed iterator. + */ +vpiHandle vpi_iterate(int type, vpiHandle ref) +{ + assert(ref->vpi_type->iterate_); + return (ref->vpi_type->iterate_)(type, ref); +} + +void vpi_printf(const char*fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} + +/* + * This function adds the information that the user supplies to a list + * that I keep. + */ +void vpi_register_systf(const struct t_vpi_systf_data*systf) +{ + struct systf_entry*cur = calloc(1, sizeof(struct systf_entry)); + cur->systf_data = *systf; + cur->systf_data.tfname = strdup(systf->tfname); + cur->next = systf_list; + systf_list = cur; +} + +/* + * $Log: vpi_priv.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_priv.h b/vvm/vpi_priv.h index 9b4ce55b9..c71f207bd 100644 --- a/vvm/vpi_priv.h +++ b/vvm/vpi_priv.h @@ -19,70 +19,200 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_priv.h,v 1.1 1999/08/15 01:23:56 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.2 1999/10/28 00:47:25 steve Exp $" #endif +/* + * This header file describes the "back side" of the VPI + * interface. The product that offers the VPI interface uses types and + * methods declared here to manage the VPI structures and provide the + * needed behaviors. + */ +# include + #ifdef __cplusplus extern "C" { #endif +struct __vpirt; +enum vpip_bit_t { V0 = 0, V1, Vx, Vz }; + /* - * This is the most basic type in the vpi implementation. A handle can - * exist to refer to most any of the supported vpi objects. The - * interpretation of the parts depends in general on the type of the - * object. + * This structure is the very base of a vpiHandle. Every handle + * structure starts with this structure, so that the library can + * internally pass the derived types as pointers to one of these. */ struct __vpiHandle { - int type; - int subtype; + const struct __vpirt *vpi_type; +}; - /* These are property values. */ - char*full_name; +/* + * Objects with this structure are used to represent a type of + * vpiHandle. A specific object becomes of this type by holding a + * pointer to an instance of this structure. + */ +struct __vpirt { + int type_code; - /* This pointer is used for to-one references. */ - struct __vpiHandle*referent; + /* These methods extract information from the handle. */ + int (*vpi_get_)(int, vpiHandle); + char* (*vpi_get_str_)(int, vpiHandle); + void (*vpi_get_value_)(vpiHandle, p_vpi_value); - /* This pointer table is used for to-many refrences to - arguments, and is used by the vpiArgument iterator. */ - struct __vpiHandle**arguments; - unsigned narguments; + /* These methods follow references. */ + vpiHandle (*handle_)(int, vpiHandle); + vpiHandle (*iterate_)(int, vpiHandle); +}; - /* These methods support the various vpi_get() functions. */ - int (*get_)(int property, vpiHandle ref); - char* (*get_str_)(int property, vpiHandle ref); +/* + * This is a private handle type that doesn't seem to be well defined + * by the VPI standard. + */ +struct __vpiCallback { + struct __vpiHandle base; + struct t_cb_data cb_data; + struct vpip_event*ev; +}; - /* This method is used to get a value. */ - void (*get_value_)(struct __vpiHandle*expr, s_vpi_value*vp); +/* + * This type is occasionally useful. Really! And while we're at it, + * create a single instance of the null object. (This is all we need.) + */ +struct __vpiNull { + struct __vpiHandle base; +}; +extern struct __vpiNull vpip_null; - /* This is a value union, that reflect state or the value of a - handle. */ - union { - unsigned unum; - struct vvm_bits_t*bits; - struct t_vpi_time time; - } val; +/* + * The vpiHandle for an iterator has this structure. The definition of + * the methods lives in vpi_iter.c + */ +struct __vpiIterator { + struct __vpiHandle base; + + vpiHandle *args; + unsigned nargs; + unsigned next; +}; + +/* + * This structure represents nets and registers. You can tell which by + * the type_code in the base. The bits member points to the actual + * array of bits that the environment provides. The bits must persist + * as long as this object persists. + */ +struct __vpiSignal { + struct __vpiHandle base; + + const char*name; + enum vpip_bit_t*bits; + unsigned nbits; }; -/* TYPE MEANINGS: - * - * vpiArgument - * This type of handle contains a single referent, the item that has - * many arguments. It is an iterator. - * - * vpiConstant - * Constant values, such as strings and numbers, are this type. - * - * vpiSysTaskCall - * This handle type represents a call to a system task. It has a - * to-many reference to argument expressions, and a to-one reference - * to a vpiUserSystf object. - * - * vpiTimeVar - * This type is a special kind of variable, that holds a time. The - * time value is a more complex structure then a single number. The - * type really seems to exist to implement the $time system variable. +extern const struct __vpirt vpip_systask_rt; +struct __vpiSysTaskCall { + struct __vpiHandle base; + + s_vpi_systf_data*info; + vpiHandle*args; + unsigned nargs; + + const char*file; + unsigned lineno; + int subtype; +}; + +/* + * Represent a TimeVar variable. The actual time is stored in the + * "time" member for fast manipulation by various bits of the + * simulation engine. The time_obj member is used as persistent + * storage of the time value when get_value is used (on the opaque + * handle) to the get time. */ +struct __vpiTimeVar { + struct __vpiHandle base; + + const char*name; + unsigned long time; + struct t_vpi_time time_obj; +}; + + +struct __vpiStringConst { + struct __vpiHandle base; + + const char*value; +}; + +/* + * These are methods to initialize specific handle types. Except for + * vpip_make_iterator, all the vpi_make_* functions expect the caller + * to allocate the memory for the handle. The result is the vpiHandle + * of the constructed object. + */ +extern vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args); +extern vpiHandle vpip_make_net(struct __vpiSignal*ref, const char*name); +extern vpiHandle vpip_make_string_const(struct __vpiStringConst*ref, + const char*val); +extern vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name); +extern vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref, + const char*val); + +/* Use this function to call a registered task. */ +extern void vpip_calltask(const char*name, unsigned nparms, vpiHandle*parms); + + +/* + * The simulation object holds the current state of the + * simulation. There is a single global variable that is the + * simulation. + */ + +struct vpip_simulation_cycle; +struct vpip_event; +struct vpip_simulation { + /* Current simulation time. */ + struct __vpiTimeVar sim_time; + + /* List of cbReadOnlySynch callbacks. */ + struct __vpiCallback*read_sync_list; + + /* List of simulation cycles, starting with the next time. */ + struct vpip_simulation_cycle*sim; + int going_flag; +}; + +extern struct vpip_simulation vpip_simulation_obj; + +extern void vpip_init_simulation(); +extern void vpip_simulation_run(); + +/* + * Schedule an event to be run sometime in the future. The d parmater + * is the delay in simulation units before the event is processed. If + * the non-block flag is set, the event is scheduled to happen at the + * end of the time step. + * + * The return value from the insert method is a cookie that can be + * used to manipulate the event before it is executed. + */ +extern struct vpip_event* vpip_sim_insert_event(unsigned long d, + void*user_data, + void (*sim_fun)(void*), + int nonblock_flag); +extern void vpip_sim_cancel_event(struct vpip_event*cookie); + +/* + * This function returns a handle to the vpiTimeVar that is th main + * simulation time clock. + */ +extern vpiHandle vpip_sim_time(); + +/* + * Return true if the going_flag is false. + */ +extern int vpip_finished(); #ifdef __cplusplus } @@ -90,6 +220,12 @@ struct __vpiHandle { /* * $Log: vpi_priv.h,v $ + * Revision 1.2 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.1 1999/08/15 01:23:56 steve * Convert vvm to implement system tasks with vpi. * diff --git a/vvm/vpi_signal.c b/vvm/vpi_signal.c new file mode 100644 index 000000000..60caaf0ae --- /dev/null +++ b/vvm/vpi_signal.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 1999 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_signal.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include +# include + + +static char* signal_get_str(int code, vpiHandle ref) +{ + struct __vpiSignal*rfp = (struct __vpiSignal*)ref; + + switch (code) { + + case vpiFullName: + return (char*)rfp->name; + } + + return 0; +} + +/* + * This function is a get_value_ method of a vpiHandle, that supports + * reading bits as a string. + */ +static void signal_get_value(vpiHandle ref, s_vpi_value*vp) +{ + static char buff[1024]; + char*cp; + unsigned width; + unsigned val; + unsigned idx; + struct __vpiSignal*rfp = (struct __vpiSignal*)ref; + + assert(rfp->bits); + width = rfp->nbits; + cp = buff; + + switch (vp->format) { + case vpiObjTypeVal: + case vpiBinStrVal: + for (idx = 0 ; idx < width ; idx += 1) + switch (rfp->bits[width-idx-1]) { + case V0: + *cp++ = '0'; + break; + case V1: + *cp++ = '1'; + break; + case Vx: + *cp++ = 'x'; + break; + case Vz: + *cp++ = 'z'; + break; + } + vp->format = vpiBinStrVal; + break; + + case vpiDecStrVal: + val = 0; + for (idx = 0 ; idx < width ; idx += 1) { + val *= 2; + switch (rfp->bits[width-idx-1]) { + case V0: + case Vx: + case Vz: + break; + case V1: + val += 1; + break; + } + } + sprintf(cp, "%u", val); + cp += strlen(cp); + break; + + case vpiOctStrVal: + if (width%3) { + unsigned x = 0; + unsigned z = 0; + unsigned v = 0; + unsigned i; + for (i = 0 ; i < width%3 ; i += 1) { + v *= 2; + switch (rfp->bits[width-i-1]) { + case V0: + break; + case V1: + v += 1; + break; + case Vx: + x += 1; + break; + case Vz: + z += 1; + break; + } + } + if (x == width%3) + *cp++ = 'x'; + else if (x > 0) + *cp++ = 'X'; + else if (z == width%3) + *cp++ = 'z'; + else if (z > 0) + *cp++ = 'Z'; + else + *cp++ = "01234567"[v]; + } + + for (idx = width%3 ; idx < width ; idx += 3) { + unsigned x = 0; + unsigned z = 0; + unsigned v = 0; + unsigned i; + for (i = idx ; i < idx+3 ; i += 1) { + v *= 2; + switch (rfp->bits[width-i-1]) { + case V0: + break; + case V1: + v += 1; + break; + case Vx: + x += 1; + break; + case Vz: + z += 1; + break; + } + } + if (x == 3) + *cp++ = 'x'; + else if (x > 0) + *cp++ = 'X'; + else if (z == 3) + *cp++ = 'z'; + else if (z > 0) + *cp++ = 'Z'; + else + *cp++ = "01234567"[v]; + } + break; + + case vpiHexStrVal: + if (width%4) { + unsigned x = 0; + unsigned z = 0; + unsigned v = 0; + unsigned i; + for (i = 0 ; i < width%4 ; i += 1) { + v *= 2; + switch (rfp->bits[width-i-1]) { + case V0: + break; + case V1: + v += 1; + break; + case Vx: + x += 1; + break; + case Vz: + z += 1; + break; + } + } + if (x == width%4) + *cp++ = 'x'; + else if (x > 0) + *cp++ = 'X'; + else if (z == width%4) + *cp++ = 'z'; + else if (z > 0) + *cp++ = 'Z'; + else + *cp++ = "0123456789abcdef"[v]; + } + + for (idx = width%4 ; idx < width ; idx += 4) { + unsigned x = 0; + unsigned z = 0; + unsigned v = 0; + unsigned i; + for (i = idx ; i < idx+4 ; i += 1) { + v *= 2; + switch (rfp->bits[width-i-1]) { + case V0: + break; + case V1: + v += 1; + break; + case Vx: + x += 1; + break; + case Vz: + z += 1; + break; + } + } + if (x == 4) + *cp++ = 'x'; + else if (x > 0) + *cp++ = 'X'; + else if (z == 4) + *cp++ = 'z'; + else if (z > 0) + *cp++ = 'Z'; + else + *cp++ = "0123456789abcdef"[v]; + } + break; + + default: + *cp++ = '('; + *cp++ = '?'; + *cp++ = ')'; + break; + } + + *cp++ = 0; + vp->value.str = buff; +} + +static const struct __vpirt vpip_net_rt = { + vpiNet, + 0, + signal_get_str, + signal_get_value, + 0, + 0 +}; + +vpiHandle vpip_make_net(struct __vpiSignal*ref, const char*name) +{ + ref->base.vpi_type = &vpip_net_rt; + ref->name = name; + return &(ref->base); +} + +static const struct __vpirt vpip_reg_rt = { + vpiReg, + 0, + signal_get_str, + signal_get_value, + 0, + 0 +}; + +vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name) +{ + ref->base.vpi_type = &vpip_reg_rt; + ref->name = name; + return &(ref->base); +} + +/* + * $Log: vpi_signal.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_simulation.c b/vvm/vpi_simulation.c new file mode 100644 index 000000000..9ec0d6a2d --- /dev/null +++ b/vvm/vpi_simulation.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1999 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_simulation.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include + +struct vpip_event { + void*user_data; + void (*sim_fun)(void*); + struct vpip_event*next; +}; + +struct vpip_simulation vpip_simulation_obj; + +void vpi_sim_control(int func, ...) +{ + switch (func) { + case vpiFinish: + vpip_simulation_obj.going_flag = 0; + break; + } +} + +/* + * The simulation event queue is a list of simulation cycles that in + * turn contain lists of simulation events. The simulation cycle + * represents the happening at some simulation time. + */ +struct vpip_simulation_cycle { + unsigned long delay; + + struct vpip_simulation_cycle*next; + struct vpip_simulation_cycle*prev; + + struct vpip_event*event_list; + struct vpip_event*event_last; + struct vpip_event*nonblock_list; + struct vpip_event*nonblock_last; +}; + +void vpip_init_simulation() +{ + struct vpip_simulation_cycle*cur; + + vpip_make_time_var(&vpip_simulation_obj.sim_time, "$time"); + vpip_simulation_obj.read_sync_list = 0; + + /* Allocate a header cell for the simulation event list. */ + cur = calloc(1, sizeof(struct vpip_simulation_cycle)); + cur->delay = 0; + cur->next = cur->prev = cur; + vpip_simulation_obj.sim = cur; +} + +vpiHandle vpip_sim_time() +{ + return &vpip_simulation_obj.sim_time.base; +} + +struct vpip_event* vpip_sim_insert_event(unsigned long delay, + void*user_data, + void (*sim_fun)(void*), + int nonblock_flag) +{ + struct vpip_event*event; + struct vpip_simulation_cycle*cur; + + event = calloc(1, sizeof(struct vpip_event)); + event->user_data = user_data; + event->sim_fun = sim_fun; + + cur = vpip_simulation_obj.sim->next; + while ((cur != vpip_simulation_obj.sim) && (cur->delay < delay)) { + delay -= cur->delay; + cur = cur->next; + } + + /* If there is no cycle cell for the specified time, create one. */ + if ((cur == vpip_simulation_obj.sim) || (cur->delay > delay)) { + struct vpip_simulation_cycle*cell + = calloc(1,sizeof(struct vpip_simulation_cycle)); + cell->delay = delay; + if (cur != vpip_simulation_obj.sim) + cur->delay -= delay; + cell->next = cur; + cell->prev = cur->prev; + cell->next->prev = cell; + cell->prev->next = cell; + cur = cell; + } + + /* Put the event into the end of the cycle list. */ + event->next = 0; + if (nonblock_flag) { + if (cur->nonblock_list == 0) { + cur->nonblock_list = cur->nonblock_last = event; + + } else { + cur->nonblock_last->next = event; + cur->nonblock_last = event; + } + } else { + if (cur->event_list == 0) { + cur->event_list = cur->event_last = event; + + } else { + cur->event_last->next = event; + cur->event_last = event; + } + } + + return event; +} + +void vpip_sim_cancel_event(struct vpip_event*ev) +{ + assert(0); +} + +int vpip_finished() +{ + return ! vpip_simulation_obj.going_flag; +} + +void vpip_simulation_run() +{ + vpip_simulation_obj.sim_time.time = 0; + vpip_simulation_obj.going_flag = !0; + + while (vpip_simulation_obj.going_flag) { + struct vpip_simulation_cycle*sim = vpip_simulation_obj.sim; + + /* Step the time forward to the next time cycle. */ + vpip_simulation_obj.sim_time.time += sim->delay; + sim->delay = 0; + + while (vpip_simulation_obj.going_flag) { + struct vpip_event*active = sim->event_list; + sim->event_list = 0; + sim->event_last = 0; + + if (active == 0) { + active = sim->nonblock_list; + sim->nonblock_list = 0; + sim->nonblock_last = 0; + } + + if (active == 0) + break; + + while (active && vpip_simulation_obj.going_flag) { + struct vpip_event*cur = active; + active = cur->next; + (cur->sim_fun)(cur->user_data); + free(cur); + } + } + + if (! vpip_simulation_obj.going_flag) + break; + + { struct vpip_simulation_cycle*next = sim->next; + if (next == sim) { + vpip_simulation_obj.going_flag = 0; + break; + } + sim->next->prev = sim->prev; + sim->prev->next = sim->next; + free(sim); + vpip_simulation_obj.sim = next; + } + + } +} + +/* + * $Log: vpi_simulation.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_systask.c b/vvm/vpi_systask.c new file mode 100644 index 000000000..bc970ab96 --- /dev/null +++ b/vvm/vpi_systask.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1999 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_systask.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include + +static vpiHandle systask_iter(int type, vpiHandle ref) +{ + struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref; + assert(ref->vpi_type->type_code == vpiSysTaskCall); + + if (rfp->nargs == 0) + return 0; + + return vpip_make_iterator(rfp->nargs, rfp->args); +} + +const struct __vpirt vpip_systask_rt = { + vpiSysTaskCall, + 0, + 0, + 0, + 0, + systask_iter +}; + +/* + * $Log: vpi_systask.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vpi_time.c b/vvm/vpi_time.c new file mode 100644 index 000000000..7536e9a53 --- /dev/null +++ b/vvm/vpi_time.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1999 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_time.c,v 1.1 1999/10/28 00:47:25 steve Exp $" +#endif + +# include "vpi_priv.h" +# include +# include + +/* + * IEEE-1364 VPI pretty much mandates the existance of this sort of + * thing. (Either this or a huge memory leak.) Sorry. + */ +static char buf_obj[128]; + +static void timevar_get_value(vpiHandle ref, s_vpi_value*vp) +{ + struct __vpiTimeVar*rfp = (struct __vpiTimeVar*)ref; + assert(ref->vpi_type->type_code == vpiTimeVar); + + switch (vp->format) { + case vpiObjTypeVal: + case vpiTimeVal: + rfp->time_obj.low = rfp->time; + vp->value.time = &rfp->time_obj; + vp->format = vpiTimeVal; + break; + + case vpiDecStrVal: + sprintf(buf_obj, "%lu", rfp->time); + vp->value.str = buf_obj; + break; + + default: + vp->format = vpiSuppressVal; + vp->value.str = 0; + break; + } +} + + +static const struct __vpirt vpip_time_var_rt = { + vpiTimeVar, + 0, + 0, + timevar_get_value, + 0, + 0 +}; + +vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref, const char*val) +{ + ref->base.vpi_type = &vpip_time_var_rt; + ref->name = val; + return &(ref->base); +} + +/* + * $Log: vpi_time.c,v $ + * Revision 1.1 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * + */ + diff --git a/vvm/vvm.h b/vvm/vvm.h index 7c53431c9..9581c9b19 100644 --- a/vvm/vvm.h +++ b/vvm/vvm.h @@ -19,12 +19,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm.h,v 1.15 1999/10/13 03:15:51 steve Exp $" +#ident "$Id: vvm.h,v 1.16 1999/10/28 00:47:25 steve Exp $" #endif # include # include # include +# include "vpi_priv.h" /* * The Verilog Virtual Machine are definitions for the virtual machine @@ -38,14 +39,8 @@ class vvm_simulation; class vvm_simulation_cycle; class vvm_thread; -/* The vvm_bit_t is the basic unit of value for a scalar signal in - Verilog. It represents all the possible values. The vvm_bitstring_t - is a vector of vvm_bit_t and is used when variable-length bit - arrays are needed. */ -enum vvm_bit_t { V0 = 0, V1, Vx, Vz }; - -inline vvm_bit_t operator & (vvm_bit_t l, vvm_bit_t r) +inline vpip_bit_t operator & (vpip_bit_t l, vpip_bit_t r) { if (l == V0) return V0; if (r == V0) return V0; @@ -53,7 +48,7 @@ inline vvm_bit_t operator & (vvm_bit_t l, vvm_bit_t r) return Vx; } -inline vvm_bit_t operator | (vvm_bit_t l, vvm_bit_t r) +inline vpip_bit_t operator | (vpip_bit_t l, vpip_bit_t r) { if (l == V1) return V1; if (r == V1) return V1; @@ -61,7 +56,7 @@ inline vvm_bit_t operator | (vvm_bit_t l, vvm_bit_t r) return Vx; } -inline vvm_bit_t operator ^ (vvm_bit_t l, vvm_bit_t r) +inline vpip_bit_t operator ^ (vpip_bit_t l, vpip_bit_t r) { if (l == Vx) return Vx; if (l == Vz) return Vx; @@ -71,7 +66,7 @@ inline vvm_bit_t operator ^ (vvm_bit_t l, vvm_bit_t r) return (r == V0)? V1 : V0; } -inline vvm_bit_t less_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c) +inline vpip_bit_t less_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c) { if (l == Vx) return Vx; if (r == Vx) return Vx; @@ -80,7 +75,7 @@ inline vvm_bit_t less_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c) return c; } -inline vvm_bit_t greater_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c) +inline vpip_bit_t greater_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c) { if (l == Vx) return Vx; if (r == Vx) return Vx; @@ -89,9 +84,9 @@ inline vvm_bit_t greater_with_cascade(vvm_bit_t l, vvm_bit_t r, vvm_bit_t c) return c; } -extern vvm_bit_t add_with_carry(vvm_bit_t l, vvm_bit_t r, vvm_bit_t&carry); +extern vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry); -inline vvm_bit_t not(vvm_bit_t l) +inline vpip_bit_t not(vpip_bit_t l) { switch (l) { case V0: @@ -107,14 +102,14 @@ class vvm_bits_t { public: virtual ~vvm_bits_t() =0; virtual unsigned get_width() const =0; - virtual vvm_bit_t get_bit(unsigned idx) const =0; + virtual vpip_bit_t get_bit(unsigned idx) const =0; }; -extern ostream& operator << (ostream&os, vvm_bit_t); +extern ostream& operator << (ostream&os, vpip_bit_t); extern ostream& operator << (ostream&os, const vvm_bits_t&str); /* - * The vvm_bitset_t is a fixed width array-like set of vvm_bit_t + * The vvm_bitset_t is a fixed width array-like set of vpip_bit_t * items. A number is often times made up of bit sets instead of * single bits. The fixed array is used when possible because of the * more thorough type checking and (hopefully) better optimization. @@ -124,44 +119,38 @@ template class vvm_bitset_t : public vvm_bits_t { public: vvm_bitset_t() { for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) - bits_[idx] = Vz; + bits[idx] = Vz; } - //vvm_bitset_t(const vvm_bitset_t&that) - // { bits_ = that.bits_; } + vvm_bitset_t(const vvm_bits_t&that) { unsigned wid = WIDTH; if (that.get_width() < WIDTH) wid = that.get_width(); for (unsigned idx = 0 ; idx < wid ; idx += 1) - bits_[idx] = that.get_bit(idx); + bits[idx] = that.get_bit(idx); for (unsigned idx = wid ; idx < WIDTH ; idx += 1) - bits_[idx] = V0; + bits[idx] = V0; } - vvm_bit_t operator[] (unsigned idx) const { return bits_[idx]; } - vvm_bit_t&operator[] (unsigned idx) { return bits_[idx]; } + vpip_bit_t operator[] (unsigned idx) const { return bits[idx]; } + vpip_bit_t&operator[] (unsigned idx) { return bits[idx]; } unsigned get_width() const { return WIDTH; } - vvm_bit_t get_bit(unsigned idx) const { return bits_[idx]; } + vpip_bit_t get_bit(unsigned idx) const { return bits[idx]; } unsigned as_unsigned() const { unsigned result = 0; for (unsigned idx = WIDTH ; idx > 0 ; idx -= 1) { result <<= 1; - if (bits_[idx-1]) result |= 1; + if (bits[idx-1]) result |= 1; } return result; } - //vvm_bitset_t& operator= (const vvm_bitset_t&that) - // { if (this == &that) return *this; - // bits_ = that.bits_; - // return *this; - // } - private: - vvm_bit_t bits_[WIDTH]; + public: + vpip_bit_t bits[WIDTH]; }; /* @@ -174,12 +163,14 @@ class vvm_event { friend class vvm_simulation; public: - vvm_event() { } + vvm_event(); virtual ~vvm_event() =0; virtual void event_function() =0; + static void callback_(void*); + private: - vvm_event*next_; + struct vpip_event*event_; private: // not implemented vvm_event(const vvm_event&); @@ -225,72 +216,47 @@ class vvm_simulation { // only one event can be a monitor. void monitor_event(vvm_event*); - unsigned long get_sim_time() const { return time_; } - - // The s_finish() method marks the simulation as finished and - // prevents more events being executed. The finished() method - // returns true if the s_finish() method has been called. - void s_finish(); bool finished() const; - private: - bool going_; - vvm_simulation_cycle*sim_; - - // Triggered monitor event. - vvm_event*mon_; - - unsigned long time_; - private: // not implemented vvm_simulation(const vvm_simulation&); vvm_simulation& operator= (const vvm_simulation&); }; /* - * The vvm_monitor_t is usually associated with a vvm_bitset_t that - * represents a signal. The VVM code generator generates calls to the - * trigger method whenever an assignment or output value is set on - * the associated signal. The trigger, if enabled, then causes the - * monitor event to be scheduled in the simulation. + * The vvm_monitor_t is a way of attaching a name to the signal, for + * use by the vpi_ functions. I need to make a base type so that I can + * avoid the casting problems with the vvm_signal_t template below. * - * This object also carries the canonical signal name, for the use of - * %m display patterns. + * The vvm_signal_t template is the real object that handles the + * receiving of assignments and doing whatever is done. */ class vvm_monitor_t { public: vvm_monitor_t(const char*); - - void trigger(vvm_simulation*sim) - { if (event_) sim->monitor_event(event_); } - - const char* name() const { return name_; } - - void enable(vvm_event*e) { event_ = e; } - + ~vvm_monitor_t(); + const char* name() const; private: const char* name_; - vvm_event*event_; private: // not implemented vvm_monitor_t(const vvm_monitor_t&); vvm_monitor_t& operator= (const vvm_monitor_t&); }; - -template class vvm_signal_t : public vvm_monitor_t { +template class vvm_signal_t : public vvm_monitor_t { public: vvm_signal_t(const char*n, vvm_bitset_t*b) - : vvm_monitor_t(n), bits_(b) - { } + : vvm_monitor_t(n), bits_(b) { } - void init(unsigned idx, vvm_bit_t val) + ~vvm_signal_t() { } + + void init(unsigned idx, vpip_bit_t val) { (*bits_)[idx] = val; } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { (*bits_)[idx] = val; - trigger(sim); } void set(vvm_simulation*sim, const vvm_bitset_t&val) @@ -304,6 +270,12 @@ template class vvm_signal_t : public vvm_monitor_t { /* * $Log: vvm.h,v $ + * Revision 1.16 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.15 1999/10/13 03:15:51 steve * Remove useless operator=. * diff --git a/vvm/vvm_bit.cc b/vvm/vvm_bit.cc index d6e942a49..08c8619cf 100644 --- a/vvm/vvm_bit.cc +++ b/vvm/vvm_bit.cc @@ -17,12 +17,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_bit.cc,v 1.2 1998/11/10 00:48:31 steve Exp $" +#ident "$Id: vvm_bit.cc,v 1.3 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" -ostream& operator << (ostream&os, vvm_bit_t bit) +ostream& operator << (ostream&os, vpip_bit_t bit) { switch (bit) { case V0: @@ -54,7 +54,7 @@ vvm_bits_t::~vvm_bits_t() { } -vvm_bit_t add_with_carry(vvm_bit_t l, vvm_bit_t r, vvm_bit_t&carry) +vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry) { unsigned li, ri, ci; switch (l) { @@ -100,6 +100,12 @@ vvm_bit_t add_with_carry(vvm_bit_t l, vvm_bit_t r, vvm_bit_t&carry) /* * $Log: vvm_bit.cc,v $ + * Revision 1.3 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.2 1998/11/10 00:48:31 steve * Add support it vvm target for level-sensitive * triggers (i.e. the Verilog wait). diff --git a/vvm/vvm_calltf.cc b/vvm/vvm_calltf.cc index 9df4be77c..190f7badd 100644 --- a/vvm/vvm_calltf.cc +++ b/vvm/vvm_calltf.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_calltf.cc,v 1.7 1999/10/10 14:57:38 steve Exp $" +#ident "$Id: vvm_calltf.cc,v 1.8 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm_calltf.h" @@ -34,359 +34,6 @@ # define MAX_PATHLEN 1024 -/* This simulation pointer is used by vpi functions to get back to the - simulation. */ -static vvm_simulation*vpi_sim; - -static vpiHandle vvm_vpi_cur_task; - -/* - * Keep a list of vpi_systf_data structures. This list is searched - * forward whenever a function is invoked by name, and items are - * pushed in front of the list whenever they are registered. This - * allows entries to override older entries. - */ -struct systf_entry { - struct systf_entry* next; - s_vpi_systf_data systf_data; -}; - -static struct systf_entry*systf_list = 0; - -extern "C" void vpi_register_systf(const struct t_vpi_systf_data*systf) -{ - struct systf_entry*cur = new struct systf_entry; - cur->systf_data = *systf; - cur->systf_data.tfname = strdup(systf->tfname); - cur->next = systf_list; - systf_list = cur; -} - -extern "C" void vpi_printf(const char*fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); -} - -extern "C" void vpi_sim_control(int func, ...) -{ - switch (func) { - case vpiFinish: - vpi_sim->s_finish(); - break; - } -} - -extern "C" vpiHandle vpi_handle(int type, vpiHandle ref) -{ - switch (type) { - case vpiSysTfCall: - return vvm_vpi_cur_task; - - default: - return 0; - } -} - -extern "C" vpiHandle vpi_iterate(int type, vpiHandle ref) -{ - vpiHandle res = (vpiHandle)calloc(1, sizeof (struct __vpiHandle)); - res->type = type; - res->referent = ref; - res->val.unum = 0; - - return res; -} - -extern "C" vpiHandle vpi_scan(vpiHandle ref) -{ - assert(ref->type == vpiArgument); - if (ref->val.unum >= ref->referent->narguments) { - vpi_free_object(ref); - return 0; - } - - return ref->referent->arguments[ref->val.unum++]; -} - -extern "C" int vpi_get(int property, vpiHandle ref) -{ - if (property == vpiType) - return ref->type; - - if (ref->get_ == 0) - return -1; - - return (ref->get_)(property, ref); -} - -extern "C" char* vpi_get_str(int property, vpiHandle ref) -{ - if (property == vpiFullName) - return ref->full_name; - - if (ref->get_str_ == 0) - return 0; - - return (ref->get_str_)(property, ref); - - switch (property) { - case vpiName: - return ref->full_name; - } - return 0; -} - -extern "C" void vpi_get_value(vpiHandle expr, s_vpi_value*vp) -{ - if (expr->get_value_) { - expr->get_value_(expr, vp); - return; - } - - vp->format = vpiSuppressVal; -} - -extern "C" int vpi_free_object(vpiHandle ref) -{ - free(ref); - return 0; -} - -/* - * This function is a get_value_ method of a vpiHandle, that supports - * reading bits as a string. - */ -static void get_value_bits(vpiHandle ref, s_vpi_value*vp) -{ - static char buff[1024]; - char*cp; - unsigned width; - unsigned val; - assert(ref->val.bits); - width = ref->val.bits->get_width(); - cp = buff; - - switch (vp->format) { - case vpiObjTypeVal: - case vpiBinStrVal: - for (unsigned idx = 0 ; idx < width ; idx += 1) - switch (ref->val.bits->get_bit(width-idx-1)) { - case V0: - *cp++ = '0'; - break; - case V1: - *cp++ = '1'; - break; - case Vx: - *cp++ = 'x'; - break; - case Vz: - *cp++ = 'z'; - break; - } - vp->format = vpiBinStrVal; - break; - - case vpiDecStrVal: - val = 0; - for (unsigned idx = 0 ; idx < width ; idx += 1) { - val *= 2; - switch (ref->val.bits->get_bit(width-idx-1)) { - case V0: - case Vx: - case Vz: - break; - case V1: - val += 1; - break; - } - } - sprintf(cp, "%u", val); - cp += strlen(cp); - break; - - case vpiOctStrVal: - if (width%3) { - unsigned x = 0; - unsigned z = 0; - unsigned v = 0; - for (unsigned i = 0 ; i < width%3 ; i += 1) { - v *= 2; - switch (ref->val.bits->get_bit(width-i-1)) { - case V0: - break; - case V1: - v += 1; - break; - case Vx: - x += 1; - break; - case Vz: - z += 1; - break; - } - } - if (x == width%3) - *cp++ = 'x'; - else if (x > 0) - *cp++ = 'X'; - else if (z == width%3) - *cp++ = 'z'; - else if (z > 0) - *cp++ = 'Z'; - else - *cp++ = "01234567"[v]; - } - - for (unsigned idx = width%3 ; idx < width ; idx += 3) { - unsigned x = 0; - unsigned z = 0; - unsigned v = 0; - for (unsigned i = idx ; i < idx+3 ; i += 1) { - v *= 2; - switch (ref->val.bits->get_bit(width-i-1)) { - case V0: - break; - case V1: - v += 1; - break; - case Vx: - x += 1; - break; - case Vz: - z += 1; - break; - } - } - if (x == 3) - *cp++ = 'x'; - else if (x > 0) - *cp++ = 'X'; - else if (z == 3) - *cp++ = 'z'; - else if (z > 0) - *cp++ = 'Z'; - else - *cp++ = "01234567"[v]; - } - break; - - case vpiHexStrVal: - if (width%4) { - unsigned x = 0; - unsigned z = 0; - unsigned v = 0; - for (unsigned i = 0 ; i < width%4 ; i += 1) { - v *= 2; - switch (ref->val.bits->get_bit(width-i-1)) { - case V0: - break; - case V1: - v += 1; - break; - case Vx: - x += 1; - break; - case Vz: - z += 1; - break; - } - } - if (x == width%4) - *cp++ = 'x'; - else if (x > 0) - *cp++ = 'X'; - else if (z == width%4) - *cp++ = 'z'; - else if (z > 0) - *cp++ = 'Z'; - else - *cp++ = "0123456789abcdef"[v]; - } - - for (unsigned idx = width%4 ; idx < width ; idx += 4) { - unsigned x = 0; - unsigned z = 0; - unsigned v = 0; - for (unsigned i = idx ; i < idx+4 ; i += 1) { - v *= 2; - switch (ref->val.bits->get_bit(width-i-1)) { - case V0: - break; - case V1: - v += 1; - break; - case Vx: - x += 1; - break; - case Vz: - z += 1; - break; - } - } - if (x == 4) - *cp++ = 'x'; - else if (x > 0) - *cp++ = 'X'; - else if (z == 4) - *cp++ = 'z'; - else if (z > 0) - *cp++ = 'Z'; - else - *cp++ = "0123456789abcdef"[v]; - } - break; - - default: - *cp++ = '('; - *cp++ = '?'; - *cp++ = ')'; - break; - } - - *cp++ = 0; - vp->value.str = buff; -} - -static void get_value_strconst(vpiHandle ref, s_vpi_value*vp) -{ - switch (vp->format) { - case vpiObjTypeVal: - case vpiStringVal: - vp->value.str = ref->full_name; - vp->format = vpiStringVal; - break; - - default: - vp->format = vpiSuppressVal; - break; - } -} - -static void get_value_timevar(vpiHandle ref, s_vpi_value*vp) -{ - static char buf[128]; - switch (vp->format) { - case vpiObjTypeVal: - case vpiTimeVal: - vp->value.time = &ref->val.time; - vp->format = vpiTimeVal; - break; - - case vpiDecStrVal: - sprintf(buf, "%u", ref->val.time.low); - vp->value.str = buf; - break; - - default: - vp->format = vpiSuppressVal; - vp->value.str = 0; - break; - } -} /* * The load_vpi_module function attempts to locate and load the named @@ -457,80 +104,16 @@ void vvm_load_vpi_module(const char*name) (routines[idx])(); } -void vvm_make_vpi_parm(vpiHandle ref, const char*val) -{ - memset(ref, 0, sizeof*ref); - ref->type = vpiConstant; - ref->subtype = vpiStringConst; - ref->full_name = const_cast(val); - ref->get_value_ = &get_value_strconst; -} - -void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val) -{ - memset(ref, 0, sizeof*ref); - ref->type = vpiConstant; - ref->subtype = vpiBinaryConst; - ref->full_name = ""; - ref->val.bits = val; - ref->get_value_ = &get_value_bits; -} - -void vvm_init_vpi_handle(vpiHandle ref, vvm_bits_t*bits, vvm_monitor_t*mon) -{ - memset(ref, 0, sizeof*ref); - ref->type = vpiReg; - ref->full_name = const_cast(mon->name()); - ref->val.bits = bits; - ref->get_value_ = &get_value_bits; -} - -void vvm_init_vpi_timevar(vpiHandle ref, const char*name) -{ - memset(ref, 0, sizeof*ref); - ref->type = vpiTimeVar; - ref->full_name = const_cast(name); - ref->get_value_ = &get_value_timevar; -} - -void vvm_make_vpi_parm(vpiHandle ref) -{ - memset(ref, 0, sizeof*ref); - ref->type = 0; -} - -void vvm_calltask(vvm_simulation*sim, const string&fname, - unsigned nparms, vpiHandle*parms) -{ - vpi_sim = sim; - - struct __vpiHandle cur_task; - cur_task.type = vpiSysTaskCall; - cur_task.full_name = 0; - cur_task.referent = 0; - cur_task.arguments = parms; - cur_task.narguments = nparms; - - vvm_vpi_cur_task = &cur_task; - - /* Look for a systf function to invoke. */ - for (systf_entry*idx = systf_list ; idx ; idx = idx->next) - if (fname == idx->systf_data.tfname) { - cur_task.full_name = idx->systf_data.tfname; - idx->systf_data.calltf(idx->systf_data.user_data); - return; - } - - - /* Finally, if nothing is found then something is not - right. Print out the function name all the parameters - passed, so that someone can deal with it. */ - cout << "Call " << fname << endl; -} /* * $Log: vvm_calltf.cc,v $ + * Revision 1.8 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.7 1999/10/10 14:57:38 steve * Handle display of odd octal/hex widths (Eric Ardoom) * diff --git a/vvm/vvm_calltf.h b/vvm/vvm_calltf.h index e7979144c..f6d9ce61f 100644 --- a/vvm/vvm_calltf.h +++ b/vvm/vvm_calltf.h @@ -19,13 +19,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_calltf.h,v 1.2 1999/08/15 01:23:56 steve Exp $" +#ident "$Id: vvm_calltf.h,v 1.3 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" # include -typedef struct __vpiHandle*vpiHandle; /* * This function loads a vpi module by name. @@ -33,34 +32,14 @@ typedef struct __vpiHandle*vpiHandle; extern void vvm_load_vpi_module(const char*path); -/* - * The vvm_init_vpi_handle functions initialize statis VPI handles - * that may be used many places within the program. - */ -extern void vvm_init_vpi_handle(vpiHandle, vvm_bits_t*, vvm_monitor_t*); -extern void vvm_init_vpi_timevar(vpiHandle, const char*name); - -/* - * The vvm_make_vpi_parm functions initialize the vpiHandles to - * represent objects suitable for use as vvm_calltask parameters. - */ -extern void vvm_make_vpi_parm(vpiHandle ref, const char*val); -extern void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val); -extern void vvm_make_vpi_parm(vpiHandle ref); - -/* - * The vvm environment supports external calls to C++ by - * vvm_calltask. The code generator generates calls to vvm_calltask - * that corresponds to the system call in the Verilog source. The - * vvm_calltask in turn locates the vpi implementation (by name) and - * calls the VPI that implements the task. - */ - -extern void vvm_calltask(vvm_simulation*sim, const string&name, - unsigned nparms, vpiHandle*parms); - /* * $Log: vvm_calltf.h,v $ + * Revision 1.3 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.2 1999/08/15 01:23:56 steve * Convert vvm to implement system tasks with vpi. * diff --git a/vvm/vvm_event.cc b/vvm/vvm_event.cc index 2cc6c1a2d..b1ee2cf87 100644 --- a/vvm/vvm_event.cc +++ b/vvm/vvm_event.cc @@ -17,18 +17,36 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_event.cc,v 1.1 1998/11/09 23:44:11 steve Exp $" +#ident "$Id: vvm_event.cc,v 1.2 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" # include +vvm_event::vvm_event() +{ + event_ = 0; +} + vvm_event::~vvm_event() { } +void vvm_event::callback_(void*cbd) +{ + vvm_event*obj = reinterpret_cast(cbd); + obj->event_function(); + delete obj; +} + /* * $Log: vvm_event.cc,v $ + * Revision 1.2 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.1 1998/11/09 23:44:11 steve * Add vvm library. * diff --git a/vvm/vvm_func.h b/vvm/vvm_func.h index bc408d61b..c70d02bd6 100644 --- a/vvm/vvm_func.h +++ b/vvm/vvm_func.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_func.h,v 1.14 1999/10/05 06:19:47 steve Exp $" +#ident "$Id: vvm_func.h,v 1.15 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" @@ -123,7 +123,7 @@ vvm_bitset_t vvm_unop_uminus(const vvm_bitset_t&l) { vvm_bitset_t res; res = vvm_unop_not(l); - vvm_bit_t carry = V1; + vpip_bit_t carry = V1; for (int i = 0; i < WIDTH; i++) res[i] = add_with_carry(res[i], V0, carry); @@ -170,7 +170,7 @@ vvm_bitset_t vvm_binop_plus(const vvm_bitset_t&l, const vvm_bitset_t&r) { vvm_bitset_t result; - vvm_bit_t carry = V0; + vpip_bit_t carry = V0; for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) result[idx] = add_with_carry(l[idx], r[idx], carry); @@ -188,7 +188,7 @@ vvm_bitset_t vvm_binop_minus(const vvm_bitset_t&l, { vvm_bitset_t res; res = vvm_unop_not(r); - vvm_bit_t carry = V1; + vpip_bit_t carry = V1; for (unsigned idx = 0 ; idx < WIDTH ; idx += 1) res[idx] = add_with_carry(l[idx], res[idx], carry); @@ -593,7 +593,7 @@ vvm_bitset_t<1> vvm_binop_lor(const vvm_bitset_t&l, } template -vvm_bitset_t vvm_ternary(vvm_bit_t c, const vvm_bitset_t&t, +vvm_bitset_t vvm_ternary(vpip_bit_t c, const vvm_bitset_t&t, const vvm_bitset_t&f) { switch (c) { @@ -608,6 +608,12 @@ vvm_bitset_t vvm_ternary(vvm_bit_t c, const vvm_bitset_t&t, /* * $Log: vvm_func.h,v $ + * Revision 1.15 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.14 1999/10/05 06:19:47 steve * Add support for reduction NOR. * diff --git a/vvm/vvm_gates.h b/vvm/vvm_gates.h index f38571b1e..5d958cd28 100644 --- a/vvm/vvm_gates.h +++ b/vvm/vvm_gates.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_gates.h,v 1.14 1999/10/10 01:59:55 steve Exp $" +#ident "$Id: vvm_gates.h,v 1.15 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" @@ -36,8 +36,8 @@ class vvm_out_event : public vvm_event { public: - typedef void (*action_t)(vvm_simulation*, vvm_bit_t); - vvm_out_event(vvm_simulation*s, vvm_bit_t v, action_t o) + typedef void (*action_t)(vvm_simulation*, vpip_bit_t); + vvm_out_event(vvm_simulation*s, vpip_bit_t v, action_t o) : output_(o), sim_(s), val_(v) { } void event_function() @@ -46,7 +46,7 @@ class vvm_out_event : public vvm_event { private: const action_t output_; vvm_simulation*const sim_; - const vvm_bit_t val_; + const vpip_bit_t val_; }; template class vvm_and { @@ -55,7 +55,7 @@ template class vvm_and { explicit vvm_and(vvm_out_event::action_t o) : output_(o) { } - void init(unsigned idx, vvm_bit_t val) + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } void start(vvm_simulation*sim) @@ -66,7 +66,7 @@ template class vvm_and { sim->active_event(ev); } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; @@ -79,14 +79,14 @@ template class vvm_and { } private: - vvm_bit_t compute_() const - { vvm_bit_t outval = input_[0]; + vpip_bit_t compute_() const + { vpip_bit_t outval = input_[0]; for (unsigned i = 1 ; i < WIDTH ; i += 1) outval = outval & input_[i]; return outval; } - vvm_bit_t input_[WIDTH]; + vpip_bit_t input_[WIDTH]; vvm_out_event::action_t output_; }; @@ -96,7 +96,7 @@ template class vvm_or { explicit vvm_or(vvm_out_event::action_t o) : output_(o) { } - void init(unsigned idx, vvm_bit_t val) + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } void start(vvm_simulation*sim) @@ -107,7 +107,7 @@ template class vvm_or { sim->active_event(ev); } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; @@ -120,14 +120,14 @@ template class vvm_or { } private: - vvm_bit_t compute_() const - { vvm_bit_t outval = input_[0]; + vpip_bit_t compute_() const + { vpip_bit_t outval = input_[0]; for (unsigned i = 1 ; i < WIDTH ; i += 1) outval = outval | input_[i]; return outval; } - vvm_bit_t input_[WIDTH]; + vpip_bit_t input_[WIDTH]; vvm_out_event::action_t output_; }; @@ -137,7 +137,7 @@ template class vvm_nor { explicit vvm_nor(vvm_out_event::action_t o) : output_(o) { } - void init(unsigned idx, vvm_bit_t val) + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } void start(vvm_simulation*sim) @@ -148,7 +148,7 @@ template class vvm_nor { sim->active_event(ev); } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; @@ -161,14 +161,14 @@ template class vvm_nor { } private: - vvm_bit_t compute_() const - { vvm_bit_t outval = input_[0]; + vpip_bit_t compute_() const + { vpip_bit_t outval = input_[0]; for (unsigned i = 1 ; i < WIDTH ; i += 1) outval = outval | input_[i]; return not(outval); } - vvm_bit_t input_[WIDTH]; + vpip_bit_t input_[WIDTH]; vvm_out_event::action_t output_; }; @@ -181,7 +181,7 @@ template class vvm_bufif1 { input_[1] = Vx; } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; @@ -197,10 +197,10 @@ template class vvm_bufif1 { } private: - vvm_bit_t input_[2]; + vpip_bit_t input_[2]; vvm_out_event::action_t output_; - vvm_bit_t compute_() const + vpip_bit_t compute_() const { if (input_[1] != V1) return Vz; if (input_[0] == Vz) return Vx; return input_[0]; @@ -216,16 +216,16 @@ template class vvm_nand { input_[idx] = V0; } - void init(unsigned idx, vvm_bit_t val) { input_[idx-1] = val; } + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } // Set an input of the NAND gate causes a new output value to // be calculated and an event generated to make the output // happen. The input pins are numbered from 1 - WIDTH. - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; - vvm_bit_t outval = input_[0]; + vpip_bit_t outval = input_[0]; for (unsigned i = 1 ; i < WIDTH ; i += 1) outval = outval & input_[i]; @@ -237,7 +237,7 @@ template class vvm_nand { } private: - vvm_bit_t input_[WIDTH]; + vpip_bit_t input_[WIDTH]; vvm_out_event::action_t output_; }; @@ -251,11 +251,11 @@ template class vvm_not { : output_(o) { } - void init(unsigned, vvm_bit_t) { } + void init(unsigned, vpip_bit_t) { } void start(vvm_simulation*) { } - void set(vvm_simulation*sim, unsigned, vvm_bit_t val) - { vvm_bit_t outval = not(val); + void set(vvm_simulation*sim, unsigned, vpip_bit_t val) + { vpip_bit_t outval = not(val); vvm_event*ev = new vvm_out_event(sim, outval, output_); if (DELAY > 0) sim->insert_event(DELAY, ev); @@ -273,7 +273,7 @@ template class vvm_xnor { explicit vvm_xnor(vvm_out_event::action_t o) : output_(o) { } - void init(unsigned idx, vvm_bit_t val) { input_[idx-1] = val; } + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } void start(vvm_simulation*sim) { vvm_event*ev = new vvm_out_event(sim, compute_(), output_); if (DELAY > 0) @@ -284,11 +284,11 @@ template class vvm_xnor { - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; - vvm_bit_t outval = compute_(); + vpip_bit_t outval = compute_(); vvm_event*ev = new vvm_out_event(sim, outval, output_); if (DELAY > 0) sim->insert_event(DELAY, ev); @@ -297,15 +297,15 @@ template class vvm_xnor { } private: - vvm_bit_t compute_() const - { vvm_bit_t outval = input_[0]; + vpip_bit_t compute_() const + { vpip_bit_t outval = input_[0]; for (unsigned i = 1 ; i < WIDTH ; i += 1) outval = outval ^ input_[i]; outval = not(outval); return outval; } - vvm_bit_t input_[WIDTH]; + vpip_bit_t input_[WIDTH]; vvm_out_event::action_t output_; }; @@ -315,7 +315,7 @@ template class vvm_xor { explicit vvm_xor(vvm_out_event::action_t o) : output_(o) { } - void init(unsigned idx, vvm_bit_t val) + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } void start(vvm_simulation*sim) @@ -326,7 +326,7 @@ template class vvm_xor { sim->active_event(ev); } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; @@ -335,14 +335,14 @@ template class vvm_xor { private: - vvm_bit_t compute_() const - { vvm_bit_t outval = input_[0]; + vpip_bit_t compute_() const + { vpip_bit_t outval = input_[0]; for (unsigned i = 1 ; i < WIDTH ; i += 1) outval = outval ^ input_[i]; return outval; } - vvm_bit_t input_[WIDTH]; + vpip_bit_t input_[WIDTH]; vvm_out_event::action_t output_; }; @@ -356,7 +356,7 @@ template class vvm_eeq { explicit vvm_eeq(vvm_out_event::action_t o) : output_(o) { } - void init(unsigned idx, vvm_bit_t val) + void init(unsigned idx, vpip_bit_t val) { input_[idx-1] = val; } void start(vvm_simulation*sim) @@ -367,7 +367,7 @@ template class vvm_eeq { sim->active_event(ev); } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (input_[idx-1] == val) return; input_[idx-1] = val; @@ -376,14 +376,14 @@ template class vvm_eeq { private: - vvm_bit_t compute_() const - { vvm_bit_t outval = V0; + vpip_bit_t compute_() const + { vpip_bit_t outval = V0; if (input_[0] == input_[1]) outval = V1; return outval; } - vvm_bit_t input_[2]; + vpip_bit_t input_[2]; vvm_out_event::action_t output_; }; @@ -397,7 +397,7 @@ template class vvm_eeq { template class vvm_udp_ssequ { public: - explicit vvm_udp_ssequ(vvm_out_event::action_t o, vvm_bit_t i, + explicit vvm_udp_ssequ(vvm_out_event::action_t o, vpip_bit_t i, const vvm_u32*tab) : output_(o), table_(tab) { state_[0] = i; @@ -405,10 +405,10 @@ template class vvm_udp_ssequ { state_[idx] = Vx; } - void init(unsigned pin, vvm_bit_t val) + void init(unsigned pin, vpip_bit_t val) { state_[pin] = val; } - void set(vvm_simulation*sim, unsigned pin, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned pin, vpip_bit_t val) { assert(pin > 0); assert(pin < WIDTH+1); if (val == Vz) val = Vx; @@ -435,8 +435,8 @@ template class vvm_udp_ssequ { code &= 3; break; } - // Convert the code to a vvm_bit_t and run with it. - vvm_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx; + // Convert the code to a vpip_bit_t and run with it. + vpip_bit_t outval = (code == 0)? V0 : (code == 1)? V1 : Vx; state_[0] = outval; state_[pin] = val; vvm_event*ev = new vvm_out_event(sim, outval, output_); @@ -446,7 +446,7 @@ template class vvm_udp_ssequ { private: vvm_out_event::action_t output_; const vvm_u32*const table_; - vvm_bit_t state_[WIDTH+1]; + vpip_bit_t state_[WIDTH+1]; }; class vvm_bufz { @@ -455,9 +455,9 @@ class vvm_bufz { : output_(o) { } - void init(unsigned idx, vvm_bit_t val) { } + void init(unsigned idx, vpip_bit_t val) { } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { output_(sim, val); } private: @@ -502,7 +502,7 @@ template class vvm_pevent { vvm_bitset_t get() const { return value_; } - void set(vvm_simulation*sim, unsigned idx, vvm_bit_t val) + void set(vvm_simulation*sim, unsigned idx, vpip_bit_t val) { if (value_[idx] == val) return; switch (edge_) { case ANYEDGE: @@ -520,7 +520,7 @@ template class vvm_pevent { value_[idx] = val; } - void init(int idx, vvm_bit_t val) + void init(int idx, vpip_bit_t val) { assert(idx < WIDTH); value_[idx] = val; } @@ -537,6 +537,12 @@ template class vvm_pevent { /* * $Log: vvm_gates.h,v $ + * Revision 1.15 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.14 1999/10/10 01:59:55 steve * Structural case equals device. * diff --git a/vvm/vvm_monitor.cc b/vvm/vvm_monitor.cc index 9d9234e42..78676f344 100644 --- a/vvm/vvm_monitor.cc +++ b/vvm/vvm_monitor.cc @@ -17,20 +17,34 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_monitor.cc,v 1.2 1999/08/15 01:23:56 steve Exp $" +#ident "$Id: vvm_monitor.cc,v 1.3 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" - vvm_monitor_t::vvm_monitor_t(const char*n) : name_(n) { } +vvm_monitor_t::~vvm_monitor_t() +{ +} + +const char*vvm_monitor_t::name() const +{ + return name_; +} + /* * $Log: vvm_monitor.cc,v $ + * Revision 1.3 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.2 1999/08/15 01:23:56 steve * Convert vvm to implement system tasks with vpi. * diff --git a/vvm/vvm_simulation.cc b/vvm/vvm_simulation.cc index a018d8ddd..6f8668b80 100644 --- a/vvm/vvm_simulation.cc +++ b/vvm/vvm_simulation.cc @@ -17,101 +17,37 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vvm_simulation.cc,v 1.6 1999/10/06 01:28:18 steve Exp $" +#ident "$Id: vvm_simulation.cc,v 1.7 1999/10/28 00:47:25 steve Exp $" #endif # include "vvm.h" # include "vvm_thread.h" +# include "vpi_priv.h" # include -/* - * The state of the simulation is stored as a list of simulation - * times. Each simulation time contains the delay to get to it, and - * also a list of events that are to execute here. - * - * The "events" member points to a list of inactive events to be made - * active as a group. Update events go into this list. - * - * The "nonblock" member points to a list of events to be executed - * only after ordinary events run out. This is intended to support the - * semantics of nonblocking assignment. - */ -struct vvm_simulation_cycle { - unsigned long delay; - - struct vvm_simulation_cycle*next; - struct vvm_simulation_cycle*prev; - - struct vvm_event*event_list; - struct vvm_event*event_last; - struct vvm_event*nonblock_list; - struct vvm_event*nonblock_last; - - vvm_simulation_cycle() - : event_list(0), event_last(0), nonblock_list(0), - nonblock_last(0) - { } -}; - vvm_simulation::vvm_simulation() { - sim_ = new vvm_simulation_cycle; - sim_->delay = 0; - sim_->next = sim_->prev = sim_; - mon_ = 0; } vvm_simulation::~vvm_simulation() { } -void vvm_simulation::insert_event(unsigned long delay, vvm_event*event) +void vvm_simulation::monitor_event(vvm_event*) { - vvm_simulation_cycle*cur = sim_->next; - - while ((cur != sim_) && (cur->delay < delay)) { - delay -= cur->delay; - cur = cur->next; - } - - - if ((cur == sim_) || (cur->delay > delay)) { - vvm_simulation_cycle*cell = new vvm_simulation_cycle; - cell->delay = delay; - if (cur != sim_) - cur->delay -= delay; - cell->next = cur; - cell->prev = cur->prev; - cell->next->prev = cell; - cell->prev->next = cell; - cur = cell; - } - - event->next_ = 0; - if (cur->event_list == 0) { - cur->event_list = cur->event_last = event; - - } else { - cur->event_last->next_ = event; - cur->event_last = event; - } + assert(0); } -void vvm_simulation::monitor_event(vvm_event*event) +void vvm_simulation::insert_event(unsigned long delay, vvm_event*event) { - mon_ = event; + event->event_ = vpip_sim_insert_event(delay, event, + vvm_event::callback_, 0); } void vvm_simulation::active_event(vvm_event*event) { - event->next_ = 0; - if (sim_->event_list == 0) { - sim_->event_list = sim_->event_last = event; - - } else { - sim_->event_last->next_ = event; - sim_->event_last = event; - } + event->event_ = vpip_sim_insert_event(0, event, + vvm_event::callback_, 0); } /* @@ -121,68 +57,7 @@ void vvm_simulation::active_event(vvm_event*event) */ void vvm_simulation::run() { - assert(sim_); - time_ = 0; - going_ = true; - - while (going_) { - - /* Step the time forward to the cycle I am about to - execute. */ - time_ += sim_->delay; - sim_->delay = 0; - - while (going_) { - /* Look for some events to make active. If the - main event list is empty, then activate the - nonblock list. */ - vvm_event*active = sim_->event_list; - sim_->event_list = 0; - sim_->event_last = 0; - - if (active == 0) { - active = sim_->nonblock_list; - sim_->nonblock_list = 0; - sim_->nonblock_last = 0; - } - - /* Oops, no events left. Break out of this time cycle. */ - if (active == 0) - break; - - while (active && going_) { - vvm_event*cur = active; - active = cur->next_; - cur->event_function(); - delete cur; - } - } - - /* If the simulation was stopped by one of the events, - then break out of the loop before doing any monitor - events, and before clearing the current time. */ - if (!going_) - break; - - /* XXXX Execute monitor events here. */ - if (mon_) { - mon_->event_function(); - mon_ = 0; - } - - /* The time cycle is done, delete it from the list and - step to the next time. */ - struct vvm_simulation_cycle*next = sim_->next; - if (next == sim_) { - going_ = false; - break; - } - - sim_->next->prev = sim_->prev; - sim_->prev->next = sim_->next; - delete sim_; - sim_ = next; - } + vpip_simulation_run(); } class delay_event : public vvm_event { @@ -194,15 +69,6 @@ class delay_event : public vvm_event { vvm_thread*thr_; }; -void vvm_simulation::s_finish() -{ - going_ = false; -} - -bool vvm_simulation::finished() const -{ - return !going_; -} void vvm_simulation::thread_delay(unsigned long delay, vvm_thread*thr) { @@ -219,6 +85,12 @@ void vvm_simulation::thread_active(vvm_thread*thr) /* * $Log: vvm_simulation.cc,v $ + * Revision 1.7 1999/10/28 00:47:25 steve + * Rewrite vvm VPI support to make objects more + * persistent, rewrite the simulation scheduler + * in C (to interface with VPI) and add VPI support + * for callbacks. + * * Revision 1.6 1999/10/06 01:28:18 steve * The $finish task should work immediately. *