Compare commits

...
29 Commits
Author SHA1 Message Date
steve 38ccb12eb0 Use stringstream in place of sprintf. 2003-01-17 05:49:03 +00:00
steve ca3bf14fb6 Remove useless variable. 2003-01-17 05:48:35 +00:00
steve 982474899b Set proper line text for later bison. 2003-01-17 05:48:02 +00:00
steve ad6ff5562d Missed a case of setting line on an PEident. 2003-01-17 05:47:30 +00:00
steve d4cd1dbd27 Keep some debugging status. 2003-01-16 21:44:46 +00:00
steve 3c1426e631 Detect duplicate module declarations. 2003-01-16 21:44:19 +00:00
steve c3a1a9514f Assert some task definition sanity. 2003-01-16 21:43:52 +00:00
steve f56d763411 Move strstream to ostringstream for compatibility. 2003-01-14 21:16:18 +00:00
steve 4ec91047dd Ignore vvp.exp 2003-01-10 19:02:47 +00:00
steve 0579ae08cd Add missing vpi entry points. 2003-01-10 19:02:21 +00:00
steve 9074999666 Remove thunks from vpi init. 2003-01-10 19:01:38 +00:00
steve 0458ab5a53 Only use libiberty.h if available. 2003-01-10 19:01:04 +00:00
steve 4a3459c87c Spelling fixes. 2003-01-10 03:08:13 +00:00
steve 301cbe31ad Remove vpithunk, and move libvpi to vvp directory. 2003-01-10 03:06:32 +00:00
steve 165dd82bb2 Remove files of vvm directory. 2003-01-10 03:05:05 +00:00
steve 9c3b3246c8 use userdata to save $display argument handles. 2003-01-09 04:10:58 +00:00
steve 6416f8b90e Add vpi_put_userdata 2003-01-09 04:09:44 +00:00
steve e6eae5fd15 Allocate res-buf in bigger chunks 2003-01-07 18:07:50 +00:00
steve aa3a6dba4e Schedule wait lists of threads as a single event,
to save on events. Also, improve efficiency of
 event_s allocation. Add some event statistics to
 get an idea where performance is really going.
2003-01-06 23:57:26 +00:00
steve dedae73761 Account for local units in calculated delays. 2002-12-21 19:42:17 +00:00
steve d7f3d00f5c Rewrite time formatting to account for local scope. 2002-12-21 19:41:49 +00:00
steve c2070777b2 The $time system task returns the integer time
scaled to the local units. Change the internal
 implementation of vpiSystemTime the $time functions
 to properly account for this. Also add $simtime
 to get the simulation time.
2002-12-21 00:55:57 +00:00
steve 42b34c2ce6 Evaluate shift index after shift operand because
the chift operand may use the index register itself.
2002-12-20 01:11:14 +00:00
steve 6fbfdd8f3f Keep bit select subexpression width if it is constant. 2002-12-19 23:11:29 +00:00
steve bee3acfd12 Add tf_message, tf_get/setworkarea, and
ty_typep functions, along with defines
 related to these functions.
2002-12-19 21:37:04 +00:00
steve 2e279b61dd Update to 0.7 release. 2002-12-14 18:20:14 +00:00
steve 8ab909a765 Add vpi_handle_by_name to the VPI interface,
and bump the vpithunk magic number.
2002-12-11 23:55:22 +00:00
steve cca07fa42d Account for bison 1.35 and stack manipulations. 2002-12-10 05:49:51 +00:00
steve 5b81798205 install iverilog-vpi as a script. 2002-12-10 05:45:44 +00:00
95 changed files with 1448 additions and 7808 deletions
+25 -5
View File
@@ -17,13 +17,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.cc,v 1.3 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
#endif
# include "config.h"
# include "LineInfo.h"
# include <cstdio>
# include <sstream>
LineInfo::LineInfo()
: file_(0), lineno_(0)
{
}
LineInfo::~LineInfo()
{
@@ -31,9 +36,11 @@ LineInfo::~LineInfo()
string LineInfo::get_line() const
{
char buf[8];
sprintf(buf, "%u", lineno_);
return string(file_? file_ : "") + ":" + buf;
ostringstream buf;
buf << (file_? file_ : "") << ":" << lineno_;
string res = buf.str();
return res;
}
void LineInfo::set_line(const LineInfo&that)
@@ -42,8 +49,21 @@ void LineInfo::set_line(const LineInfo&that)
lineno_ = that.lineno_;
}
void LineInfo::set_file(const char*f)
{
file_ = f;
}
void LineInfo::set_lineno(unsigned n)
{
lineno_ = n;
}
/*
* $Log: LineInfo.cc,v $
* Revision 1.4 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+7 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.h,v 1.6 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $"
#endif
# include <string>
@@ -35,15 +35,15 @@
class LineInfo {
public:
LineInfo() : file_(0), lineno_(0) { }
LineInfo();
~LineInfo();
string get_line() const;
void set_line(const LineInfo&that);
void set_file(const char*f) { file_ = f; }
void set_lineno(unsigned n) { lineno_ = n; }
void set_file(const char*f);
void set_lineno(unsigned n);
private:
const char* file_;
@@ -52,6 +52,9 @@ class LineInfo {
/*
* $Log: LineInfo.h,v $
* Revision 1.7 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
*
* Revision 1.6 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+4 -21
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.139 2002/12/08 03:06:30 steve Exp $"
#ident "$Id: Makefile.in,v 1.141 2003/01/10 03:06:32 steve Exp $"
#
#
SHELL = /bin/sh
@@ -67,7 +67,7 @@ ifeq ('@HAVE_IPAL@','yes')
TARGETS += tgt-pal
endif
all: ivl@EXEEXT@ libvpi.a
all: ivl@EXEEXT@
for dir in $(SUBDIRS) ; do (cd $$dir ; $(MAKE) all); done
cd vpi ; $(MAKE) all
cd ivlpp ; $(MAKE) all
@@ -141,19 +141,6 @@ Makefile: Makefile.in config.h.in config.status
./config.status
libvpi.a: vpithunk.o
rm -f $@
ar cvq $@ vpithunk.o
ranlib $@
# The vpithunk.c file (that makes up the libvpi.a library) needs to
# be make with PIC flags, because shared objects load it.
vpithunk.o: vpithunk.c
@[ -d dep ] || mkdir dep
$(CC) $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) -MD -c $< -o $*.o
mv $*.d dep/$*.d
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.
# The first step makes an ivl.exe that dlltool can use to make an
@@ -225,7 +212,7 @@ else
WIN32_INSTALL = $(bindir)/iverilog-vpi
endif
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(libdir)/libvpi.a $(WIN32_INSTALL) $(INSTALL_DOC)
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
cd vpi ; $(MAKE) install
cd ivlpp ; $(MAKE) install
cd driver ; $(MAKE) install
@@ -233,10 +220,7 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
$(bindir)/iverilog-vpi: ./iverilog-vpi
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
$(libdir)/libvpi.a : ./libvpi.a
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
@@ -294,7 +278,6 @@ uninstall:
rm -f $(libdir)/ivl/iverilog.conf
rm -f $(libdir)/ivl/ivl
-rmdir $(libdir)/ivl
rm -f $(libdir)/libvpi.a
rm -f $(bindir)/verilog
rm -f $(bindir)/iverilog-vpi
rm -f $(bindir)/gverilog@EXEEXT@
+13
View File
@@ -344,6 +344,19 @@ language that are defined.
The $sizeof function is deprecated in favor of $bits, which is
the same thing, but included in the SystemVerilog definition.
$simtime
The $simtime system function returns as a 64bit value the
simulation time, unscaled by the time units of local
scope. This is different from the $time and $stime functions
which return the scaled times. This function is added for
regression testing of the compiler and run time, but can be
used by applications who really want the simulation time.
Note that the simulation time can be confusing if there are
lots of different `timescales within a design. It is not in
general possible to predict what the simulation precision will
turn out to be.
Builtin system functions
Certain of the system functions have well defined meanings, so
+9 -1
View File
@@ -23,7 +23,7 @@
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.cc,v 1.2 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: StringHeap.cc,v 1.3 2003/01/16 21:44:46 steve Exp $"
#endif
# include "StringHeap.h"
@@ -38,6 +38,7 @@ StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
}
StringHeap::~StringHeap()
@@ -55,6 +56,8 @@ const char* StringHeap::add(const char*text)
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
char*res = cell_base_ + cell_ptr_;
@@ -62,11 +65,16 @@ const char* StringHeap::add(const char*text)
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL);
return res;
}
/*
* $Log: StringHeap.cc,v $
* Revision 1.3 2003/01/16 21:44:46 steve
* Keep some debugging status.
*
* Revision 1.2 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.h,v 1.2 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: StringHeap.h,v 1.3 2003/01/16 21:44:46 steve Exp $"
#endif
class StringHeap {
@@ -35,6 +35,7 @@ class StringHeap {
char*cell_base_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);
@@ -43,6 +44,9 @@ class StringHeap {
/*
* $Log: StringHeap.h,v $
* Revision 1.3 2003/01/16 21:44:46 steve
* Keep some debugging status.
*
* Revision 1.2 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: config.h.in,v 1.5 2002/08/11 23:39:33 steve Exp $"
#ident "$Id: config.h.in,v 1.6 2003/01/10 19:01:04 steve Exp $"
#endif
#if defined(__cplusplus)
@@ -37,6 +37,7 @@
# undef HAVE_TIMES
# undef HAVE_IOSFWD
# undef HAVE_GETOPT_H
# undef HAVE_LIBIBERTY_H
# undef HAVE_MALLOC_H
# undef HAVE_DLFCN_H
# undef HAVE_DL_H
@@ -46,6 +47,9 @@
/*
* $Log: config.h.in,v $
* Revision 1.6 2003/01/10 19:01:04 steve
* Only use libiberty.h if available.
*
* Revision 1.5 2002/08/11 23:39:33 steve
* Remove VVM option.
*
+1 -1
View File
@@ -32,7 +32,7 @@ fi
AC_LANG_CPLUSPLUS
AC_CHECK_HEADERS(getopt.h malloc.h iosfwd sys/wait.h)
AC_CHECK_HEADERS(getopt.h malloc.h libiberty.h iosfwd sys/wait.h)
AC_MSG_CHECKING(for sys/times)
AC_TRY_LINK(
+6 -1
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: main.c,v 1.49 2002/12/04 03:26:59 steve Exp $"
#ident "$Id: main.c,v 1.50 2003/01/10 19:01:04 steve Exp $"
# include "config.h"
@@ -44,8 +44,10 @@ const char HELP[] =
#ifdef __MINGW32__
#include <windows.h>
#ifdef HAVE_LIBIBERTY_H
#include <libiberty.h>
#endif
#endif
#if HAVE_GETOPT_H
#include <getopt.h>
@@ -686,6 +688,9 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.50 2003/01/10 19:01:04 steve
* Only use libiberty.h if available.
*
* Revision 1.49 2002/12/04 03:26:59 steve
* Mingw32 compatible temp file management.
*
+10 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
#ident "$Id: elab_expr.cc,v 1.67 2002/12/21 00:55:57 steve Exp $"
#endif
# include "config.h"
@@ -215,6 +215,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
if (strcmp(path_.peek_name(0), "$time") == 0)
wid = 64;
if (strcmp(path_.peek_name(0), "$simtime") == 0)
wid = 64;
if (strcmp(path_.peek_name(0), "$stime") == 0)
wid = 32;
@@ -885,6 +887,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/*
* $Log: elab_expr.cc,v $
* Revision 1.67 2002/12/21 00:55:57 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.66 2002/09/21 21:28:18 steve
* Allow constant bit selects out of range.
*
+4 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.103 2002/12/06 03:08:19 steve Exp $"
#ident "$Id: elab_net.cc,v 1.104 2003/01/17 05:48:35 steve Exp $"
#endif
# include "config.h"
@@ -1502,8 +1502,6 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
{
string path = scope->name();
NetNet*sig = des->find_signal(scope, path_);
if (sig == 0) {
/* Don't allow memories here. Is it a memory? */
@@ -2278,6 +2276,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.104 2003/01/17 05:48:35 steve
* Remove useless variable.
*
* Revision 1.103 2002/12/06 03:08:19 steve
* Reword some error messages for clarity.
*
+34 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.266 2002/12/05 04:15:14 steve Exp $"
#ident "$Id: elaborate.cc,v 1.268 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -30,7 +30,7 @@
*/
# include <typeinfo>
# include <strstream>
# include <sstream>
# include <list>
# include "pform.h"
# include "PEvent.h"
@@ -314,14 +314,14 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
a unique name, and set the delay times. */
for (unsigned idx = 0 ; idx < count ; idx += 1) {
strstream tmp;
ostringstream tmp;
unsigned index;
if (low < high)
index = low + idx;
else
index = low - idx;
tmp << name << "<" << index << ">" << ends;
tmp << name << "<" << index << ">";
const string inm = tmp.str();
switch (type()) {
@@ -1606,6 +1606,30 @@ NetProc* PDelayStatement::elaborate(Design*des, NetScope*scope) const
/* Ah, the delay is not constant. OK, elaborate the
expression and let the run-time handle it. */
NetExpr*dex = delay_->elaborate_expr(des, scope);
/* If the local scope units are different from the
simulation precision, then extend the expression to
convert the delay to simulation time. */
if (scope->time_unit() != des->get_precision()) {
long scale = 1;
int unit = scope->time_unit();
int prec = des->get_precision();
while (unit > prec) {
scale *= 10;
unit -= 1;
}
verinum scale_v (scale);
NetEConst*scale_e = new NetEConst(scale_v);
NetEBMult*scale_m = new NetEBMult('*', scale_e, dex);
if (NetExpr*tmp = scale_m->eval_tree()) {
dex = tmp;
delete scale_m;
} else {
dex = scale_m;
}
}
if (statement_)
return new NetPDelay(dex, statement_->elaborate(des, scope));
else
@@ -2489,6 +2513,12 @@ Design* elaborate(list<const char*>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.268 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.267 2002/12/21 19:42:17 steve
* Account for local units in calculated delays.
*
* Revision 1.266 2002/12/05 04:15:14 steve
* precalculate r-values of nb assignments and task arguments.
*
+1
View File
@@ -120,6 +120,7 @@ ivl_scope_port
ivl_scope_ports
ivl_scope_sigs
ivl_scope_sig
ivl_scope_time_units
ivl_scope_type
ivl_scope_tname
+14 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: ivl_target.h,v 1.109 2002/12/21 00:55:58 steve Exp $"
#endif
#ifdef __cplusplus
@@ -861,6 +861,11 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* anything that can become and ivl_signal_t, include synthetic
* signals generated by the compiler.
*
* ivl_scope_time_units
* Scopes have their own intrinsic time units, typically from the
* timescale compiler directive. This method returns the units as a
* signed power of 10 value.
*
* ivl_scope_type
* ivl_scope_tname
* Scopes have a type and a type name. For example, if a scope is
@@ -891,6 +896,7 @@ extern unsigned ivl_scope_sigs(ivl_scope_t net);
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
extern ivl_scope_type_t ivl_scope_type(ivl_scope_t net);
extern const char* ivl_scope_tname(ivl_scope_t net);
extern int ivl_scope_time_units(ivl_scope_t net);
/* SIGNALS
@@ -1091,6 +1097,13 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.109 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.108 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.14 2002/06/11 15:19:12 steve Exp $"
#ident "$Id: Makefile.in,v 1.15 2002/12/19 21:37:04 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,7 +50,7 @@ a_initialize.o a_next_topmod.o a_object_of_type.o a_product_version.o \
a_set_value.o a_version.o
O = asynch.o finish.o getcstringp.o getinstance.o getlongp.o \
getp.o getsimtime.o io_print.o mc_scan_plusargs.o nump.o putlongp.o \
putp.o veriusertfs.o $A
putp.o typep.o workarea.o veriusertfs.o $A
all: libveriuser.a
+22 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: io_print.c,v 1.3 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: io_print.c,v 1.4 2002/12/19 21:37:04 steve Exp $"
#endif
# include <vpi_user.h>
@@ -56,8 +56,29 @@ void tf_error(const char *fmt, ...)
va_end(ap);
}
PLI_INT32 tf_message(PLI_INT32 level, char*facility,
char*messno, char*fmt, ...)
{
va_list ap;
vpi_printf("%s[%s] ", facility, messno);
va_start(ap, fmt);
vpi_vprintf(fmt, ap);
va_end(ap);
vpi_printf("\n");
return 0;
}
/*
* $Log: io_print.c,v $
* Revision 1.4 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
* Revision 1.3 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2002 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: typep.c,v 1.1 2002/12/19 21:37:04 steve Exp $"
#endif
#include <assert.h>
#include <veriuser.h>
#include <vpi_user.h>
PLI_INT32 tf_typep(PLI_INT32 narg)
{
vpiHandle sys_h, argv, arg_h = 0;
s_vpi_value value;
int rtn;
assert(narg > 0);
/* get task/func handle */
sys_h = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, sys_h);
/* find nth arg */
while (narg > 0) {
/* Watch that the argument is not out of range. */
if (!(arg_h = vpi_scan(argv)))
return TF_NULLPARAM;
narg -= 1;
}
switch (vpi_get(vpiType, arg_h)) {
case vpiConstant:
switch (vpi_get(vpiConstType, arg_h)) {
case vpiStringConst:
rtn = TF_STRING;
break;
default:
rtn = TF_READONLY;
break;
}
break;
case vpiIntegerVar:
case vpiReg:
case vpiMemoryWord:
rtn = TF_READWRITE;
break;
default:
rtn = TF_READONLY;
break;
}
vpi_free_object(argv);
return rtn;
}
/*
* $Log: typep.c,v $
* Revision 1.1 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
*/
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2002 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: workarea.c,v 1.1 2002/12/19 21:37:04 steve Exp $"
#endif
# include <veriuser.h>
# include <vpi_user.h>
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
/*
* Keep a list of sys handle to work area bindings.
*/
struct workarea_cell {
vpiHandle sys;
void* area;
struct workarea_cell*next;
};
static struct workarea_cell*area_list = 0;
PLI_INT32 tf_setworkarea(void*workarea)
{
vpiHandle sys;
struct workarea_cell*cur;
sys = vpi_handle(vpiSysTfCall, 0);
cur = area_list;
while (cur) {
if (cur->sys == sys) {
cur->area = workarea;
return 0;
}
cur = cur->next;
}
cur = calloc(1, sizeof (struct workarea_cell));
cur->next = area_list;
cur->sys = sys;
cur->area = workarea;
area_list = cur;
return 0;
}
PLI_BYTE8* tf_getworkarea(void)
{
struct workarea_cell*cur;
vpiHandle sys;
sys = vpi_handle(vpiSysTfCall, 0);
cur = area_list;
while (cur) {
if (cur->sys == sys) {
return cur->area;
}
cur = cur->next;
}
return 0;
}
/*
* $Log: workarea.c,v $
* Revision 1.1 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
*/
+9 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_design.cc,v 1.30 2002/12/07 02:49:24 steve Exp $"
#ident "$Id: net_design.cc,v 1.31 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -31,7 +31,7 @@
# include "netlist.h"
# include "util.h"
# include <strstream>
# include <sstream>
Design:: Design()
: errors(0), nodes_(0), procs_(0), lcounter_(0)
@@ -48,10 +48,11 @@ Design::~Design()
string Design::local_symbol(const string&path)
{
strstream res;
res << "_L" << (lcounter_++) << ends;
ostringstream res;
res << path << "." << "_L" << lcounter_;
lcounter_ += 1;
return path + "." + res.str();
return res.str();
}
void Design::set_precision(int val)
@@ -600,6 +601,9 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.31 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.30 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
+9 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
#ident "$Id: net_link.cc,v 1.13 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -25,7 +25,7 @@
# include <iostream>
# include "netlist.h"
# include <strstream>
# include <sstream>
# include <string>
# include <typeinfo>
#ifdef HAVE_MALLOC_H
@@ -363,14 +363,14 @@ const char* Nexus::name() const
}
assert(sig);
ostrstream tmp;
ostringstream tmp;
tmp << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
tmp << ends;
name_ = new char[strlen(tmp.str()) + 1];
strcpy(name_, tmp.str());
const string tmps = tmp.str();
name_ = new char[strlen(tmps.c_str()) + 1];
strcpy(name_, tmps.c_str());
return name_;
}
@@ -499,6 +499,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/*
* $Log: net_link.cc,v $
* Revision 1.13 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.12 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
+7 -4
View File
@@ -17,13 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.21 2002/12/07 02:49:24 steve Exp $"
#ident "$Id: net_scope.cc,v 1.22 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
# include <strstream>
# include <sstream>
/*
* The NetScope class keeps a scope tree organized. Each node of the
@@ -419,8 +419,8 @@ const NetScope* NetScope::parent() const
string NetScope::local_symbol()
{
strstream res;
res << "_s" << (lcounter_++) << ends;
ostringstream res;
res << "_s" << (lcounter_++);
return res.str();
}
@@ -432,6 +432,9 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* Revision 1.22 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.21 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
+19 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: parse.y,v 1.167 2002/12/07 02:49:24 steve Exp $"
#ident "$Id: parse.y,v 1.169 2003/01/17 05:48:02 steve Exp $"
#endif
# include "config.h"
@@ -33,6 +33,24 @@ extern void lex_end_table();
static svector<PExpr*>* active_range = 0;
static bool active_signed = false;
/* Later version of bison (including 1.35) will not compile in stack
extension if the output is compiled with C++ and either the YYSTYPE
or YYLTYPE are provided by the source code. However, I can get the
old behavior back by defining these symbols. */
# define YYSTYPE_IS_TRIVIAL 1
# define YYLTYPE_IS_TRIVIAL 1
/* Recent version of bison expect that the user supply a
YYLLOC_DEFAULT macro that makes up a yylloc value from existing
values. I need to supply an explicit version to account for the
text field, that otherwise won't be copied. */
# define YYLLOC_DEFAULT(Current, Rhs, N) \
Current.first_line = Rhs[1].first_line; \
Current.first_column = Rhs[1].first_column; \
Current.last_line = Rhs[N].last_line; \
Current.last_column = Rhs[N].last_column; \
Current.text = Rhs[1].text;
/*
* These are some common strength pairs that are used as defaults when
* the user is not otherwise specific.
+41 -17
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.102 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: pform.cc,v 1.106 2003/01/17 05:47:30 steve Exp $"
#endif
# include "config.h"
@@ -32,7 +32,7 @@
# include <map>
# include <assert.h>
# include <typeinfo>
# include <strstream>
# include <sstream>
map<string,Module*> pform_modules;
map<string,PUdp*> pform_primitives;
@@ -212,6 +212,16 @@ void pform_endmodule(const char*name)
{
assert(pform_cur_module);
assert(strcmp(name, pform_cur_module->mod_name()) == 0);
map<string,Module*>::const_iterator test = pform_modules.find(name);
if (test != pform_modules.end()) {
ostringstream msg;
msg << "Module " << name << " was already declared here: "
<< (*test).second->get_line() << endl;
VLerror(msg.str().c_str());
pform_cur_module = 0;
return;
}
pform_modules[name] = pform_cur_module;
pform_cur_module = 0;
}
@@ -421,7 +431,7 @@ void pform_make_udp(const char*name, list<string>*parms,
}
/* Verify the "initial" statement, if present, to be sure that
it only assignes to the output and the output is
it only assigns to the output and the output is
registered. Then save the initial value that I get. */
verinum::V init = verinum::Vx;
if (init_expr) {
@@ -608,7 +618,7 @@ void pform_makegates(PGBuiltin::Type type,
/*
* A module is different from a gate in that there are different
* constraints, and sometimes different syntax. The X_modgate
* functions handle the instantaions of modules (and UDP objects) by
* functions handle the instantiations of modules (and UDP objects) by
* making PGModule objects.
*/
static void pform_make_modgate(const char*type,
@@ -767,13 +777,13 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
*
* reg foo = <expr>;
*
* This is equivilent to the combination of statements:
* This is equivalent to the combination of statements:
*
* reg foo;
* initital foo = <expr>;
* initial foo = <expr>;
*
* and that is how it is parsed. This syntax is not part of the
* IEEE1364-1994 standard, but is approved by OVI as enhancement
* IEEE1364-1995 standard, but is approved by OVI as enhancement
* BTF-B14.
*/
void pform_make_reginit(const struct vlltype&li,
@@ -820,11 +830,11 @@ void pform_module_define_port(const struct vlltype&li,
hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur) {
strstream msg;
ostringstream msg;
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< "." << ends;
VLerror(msg.str());
<< ".";
VLerror(msg.str().c_str());
return;
}
@@ -862,7 +872,7 @@ void pform_module_define_port(const struct vlltype&li,
* reg bar;
*
* The output (or other port direction indicator) may or may not have
* been seen already, so I do not do any cheching with it yet. But I
* been seen already, so I do not do any checking with it yet. But I
* do check to see if the name has already been declared, as this
* function is called for every declaration.
*/
@@ -874,18 +884,18 @@ void pform_makewire(const vlltype&li, const char*nm,
if (cur) {
if ((cur->get_wire_type() != NetNet::IMPLICIT)
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
strstream msg;
ostringstream msg;
msg << name << " previously defined at " <<
cur->get_line() << "." << ends;
VLerror(msg.str());
cur->get_line() << ".";
VLerror(msg.str().c_str());
} else {
bool rc = cur->set_wire_type(type);
if (rc == false) {
strstream msg;
ostringstream msg;
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< "." << ends;
VLerror(msg.str());
<< ".";
VLerror(msg.str().c_str());
}
}
@@ -948,6 +958,8 @@ void pform_makewire(const vlltype&li,
PWire*cur = pform_cur_module->get_wire(name);
if (cur != 0) {
PEIdent*lval = new PEIdent(hname_t(first->name));
lval->set_file(li.text);
lval->set_lineno(li.first_line);
pform_make_pgassign(lval, first->expr, delay, str);
}
@@ -1360,6 +1372,18 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* Revision 1.106 2003/01/17 05:47:30 steve
* Missed a case of setting line on an PEident.
*
* Revision 1.105 2003/01/16 21:44:19 steve
* Detect duplicate module declarations.
*
* Revision 1.104 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.103 2003/01/10 03:08:13 steve
* Spelling fixes.
*
* Revision 1.102 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
+1 -1
View File
@@ -1,7 +1,7 @@
PKG="IVLver"
NAME="verilog"
ARCH="sparc"
VERSION="0.6"
VERSION="0.7"
CATEGORY="application"
VENDOR="Icarus.com"
EMAIL="[email protected]"
+14 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.88 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.89 2002/12/21 00:55:58 steve Exp $"
#endif
# include "config.h"
@@ -1157,6 +1157,12 @@ extern "C" ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx)
return net->sigs_[idx];
}
extern "C" int ivl_scope_time_units(ivl_scope_t net)
{
assert(net);
return net->time_units;
}
extern "C" ivl_scope_type_t ivl_scope_type(ivl_scope_t net)
{
assert(net);
@@ -1585,6 +1591,13 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.89 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.88 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+27 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.100 2002/11/05 02:12:35 steve Exp $"
#ident "$Id: t-dll.cc,v 1.102 2003/01/16 21:43:52 steve Exp $"
#endif
# include "config.h"
@@ -435,6 +435,8 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
root_->mem_ = 0;
root_->type_ = IVL_SCT_MODULE;
root_->tname_ = root_->name_;
root_->time_units = s->time_unit();
des_.nroots_++;
if (des_.roots_)
des_.roots_ = (ivl_scope_t *)realloc(des_.roots_, des_.nroots_ * sizeof(ivl_scope_t));
@@ -1766,6 +1768,7 @@ void dll_target::scope(const NetScope*net)
scope->child_ = 0;
scope->sibling_ = 0;
scope->parent = find_scope(des_, net->parent());
assert(scope->parent);
scope->nsigs_ = 0;
scope->sigs_ = 0;
scope->nlog_ = 0;
@@ -1776,16 +1779,25 @@ void dll_target::scope(const NetScope*net)
scope->lpm_ = 0;
scope->nmem_ = 0;
scope->mem_ = 0;
scope->time_units = net->time_unit();
switch (net->type()) {
case NetScope::MODULE:
scope->type_ = IVL_SCT_MODULE;
scope->tname_ = net->module_name();
break;
case NetScope::TASK:
scope->type_ = IVL_SCT_TASK;
scope->tname_ = strings_.add(net->task_def()->name().c_str());
break;
case NetScope::TASK: {
const NetTaskDef*def = net->task_def();
if (def == 0) {
cerr << "?:?" << ": internal error: "
<< "task " << scope->name_
<< " has no definition." << endl;
}
assert(def);
scope->type_ = IVL_SCT_TASK;
scope->tname_ = strings_.add(def->name().c_str());
break;
}
case NetScope::FUNC:
scope->type_ = IVL_SCT_FUNCTION;
scope->tname_ = strings_.add(net->func_def()->name().c_str());
@@ -1981,6 +1993,16 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.102 2003/01/16 21:43:52 steve
* Assert some task definition sanity.
*
* Revision 1.101 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.100 2002/11/05 02:12:35 steve
* Fix the call to FormatMessage under Windows.
*
+10 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.95 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: t-dll.h,v 1.96 2002/12/21 00:55:58 steve Exp $"
#endif
# include "target.h"
@@ -500,6 +500,8 @@ struct ivl_scope_s {
unsigned ports;
ivl_signal_t*port;
signed int time_units :8;
};
/*
@@ -622,6 +624,13 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* Revision 1.96 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.95 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+7 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-xnf.cc,v 1.45 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: t-xnf.cc,v 1.46 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -77,7 +77,7 @@
# include "netlist.h"
# include "target.h"
# include <fstream>
# include <strstream>
# include <sstream>
verinum::V link_get_ival(const Link&lnk)
{
@@ -765,8 +765,8 @@ void target_xnf::lpm_ram_dq(const NetRamDq*ram)
draw_pin(out_, "WE", ram->pin_WE());
draw_pin(out_, "WCLK", ram->pin_InClock());
for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
strstream tmp;
tmp << "A" << adr << ends;
ostringstream tmp;
tmp << "A" << adr;
draw_pin(out_, tmp.str(), ram->pin_Address(adr));
}
@@ -927,6 +927,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
/*
* $Log: t-xnf.cc,v $
* Revision 1.46 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.45 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+16 -7
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.70 2002/10/23 01:45:24 steve Exp $"
#ident "$Id: stub.c,v 1.71 2002/12/21 00:55:58 steve Exp $"
#endif
# include "config.h"
@@ -666,26 +666,28 @@ static int show_scope(ivl_scope_t net, void*x)
switch (ivl_scope_type(net)) {
case IVL_SCT_MODULE:
fprintf(out, " module %s\n", ivl_scope_tname(net));
fprintf(out, " module %s", ivl_scope_tname(net));
break;
case IVL_SCT_FUNCTION:
fprintf(out, " function %s\n", ivl_scope_tname(net));
fprintf(out, " function %s", ivl_scope_tname(net));
break;
case IVL_SCT_BEGIN:
fprintf(out, " begin : %s\n", ivl_scope_tname(net));
fprintf(out, " begin : %s", ivl_scope_tname(net));
break;
case IVL_SCT_FORK:
fprintf(out, " fork : %s\n", ivl_scope_tname(net));
fprintf(out, " fork : %s", ivl_scope_tname(net));
break;
case IVL_SCT_TASK:
fprintf(out, " task %s\n", ivl_scope_tname(net));
fprintf(out, " task %s", ivl_scope_tname(net));
break;
default:
fprintf(out, " type(%u) %s\n", ivl_scope_type(net),
fprintf(out, " type(%u) %s", ivl_scope_type(net),
ivl_scope_tname(net));
break;
}
fprintf(out, " time units = 10e%d\n", ivl_scope_time_units(net));
for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1)
show_event(ivl_scope_event(net, idx));
@@ -728,6 +730,13 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.71 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.70 2002/10/23 01:45:24 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+65 -51
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.86 2002/11/22 00:01:50 steve Exp $"
#ident "$Id: eval_expr.c,v 1.88 2002/12/20 01:11:14 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -618,9 +618,62 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
const char*opcode = "?";
struct vector_info lv;
/* Evaluate the expression that is to be shifted. */
switch (ivl_expr_opcode(exp)) {
case 'l': /* << (left shift) */
lv = draw_eval_expr_wid(le, wid, 0);
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
opcode = "%shiftl";
break;
case 'r': /* >> (unsigned right shift) */
/* with the right shift, there may be high bits that are
shifted into the desired width of the expression, so
we let the expression size itself, if it is bigger
then what is requested of us. */
if (wid > ivl_expr_width(le)) {
lv = draw_eval_expr_wid(le, wid, 0);
} else {
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
}
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
opcode = "%shiftr";
break;
default:
assert(0);
}
/* Figure out the shift amount and load that into the index
register. The value may be a constant, or may need to be
evaluated at run time. */
@@ -662,56 +715,10 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
}
switch (ivl_expr_opcode(exp)) {
fprintf(vvp_out, " %s/i0 %u, %u;\n", opcode, lv.base, lv.wid);
case 'l': /* << (left shift) */
lv = draw_eval_expr_wid(le, wid, 0);
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
break;
case 'r': /* >> (unsigned right shift) */
/* with the right shift, there may be high bits that are
shifted into the desired width of the expression, so
we let the expression size itself, if it is bigger
then what is requested of us. */
if (wid > ivl_expr_width(le)) {
lv = draw_eval_expr_wid(le, wid, 0);
} else {
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
}
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lv.base, lv.wid);
break;
default:
assert(0);
}
if (lv.base >= 8)
save_expression_lookaside(lv.base, exp, lv.wid);
return lv;
}
@@ -1374,7 +1381,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
writeable vector space and work from there instead. */
if (subv.base < 4) {
res.base = allocate_vector(subv.wid);
res.wid = wid;
res.wid = subv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base,
subv.base, res.wid);
subv = res;
@@ -1963,6 +1970,13 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.88 2002/12/20 01:11:14 steve
* Evaluate shift index after shift operand because
* the chift operand may use the index register itself.
*
* Revision 1.87 2002/12/19 23:11:29 steve
* Keep bit select subexpression width if it is constant.
*
* Revision 1.86 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
+14 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.81 2002/11/21 18:08:09 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.82 2002/12/21 00:55:58 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -1547,12 +1547,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
vvp_mangle_id(ivl_scope_name(net)),
type,
vvp_mangle_name(ivl_scope_name(net)));
if (parent) {
fprintf(vvp_out, ", S_%s;\n",
vvp_mangle_id(ivl_scope_name(parent)));
}
else
} else {
fprintf(vvp_out, ";\n");
}
fprintf(vvp_out, " .timescale %d;\n", ivl_scope_time_units(net));
/* Scan the scope for logic devices. For each device, draw out
a functor that connects pin 0 to the output, and the
@@ -1607,6 +1611,13 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.82 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.81 2002/11/21 18:08:09 steve
* Better handling of select width of shifters.
*
+3 -3
View File
@@ -1,10 +1,10 @@
Summary: Icarus Verilog
Name: verilog
Version: 0.6.20021207
Version: 0.7
Release: 0
Copyright: GPL
Group: Applications/Engineering
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20021207.tar.gz
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-0.7.tar.gz
URL: http://www.icarus.com/eda/verilog/index.html
Packager: Stephen Williams <[email protected]>
@@ -20,7 +20,7 @@ engineering formats, including simulation. It strives to be true
to the IEEE-1364 standard.
%prep
%setup -n verilog-20021207
%setup -n verilog-0.7
%build
./configure --prefix=/usr
+134 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: veriuser.h,v 1.17 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: veriuser.h,v 1.18 2002/12/19 21:37:04 steve Exp $"
#endif
/*
@@ -56,6 +56,47 @@
EXTERN_C_START
#ifndef PLI_TYPES
#define PLI_TYPES
typedef signed int PLI_INT32;
typedef unsigned int PLI_UINT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT12;
typedef signed char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
#endif
/*
* defines for tf_message
*/
#define ERR_MESSAGE 1
#define ERR_WARNING 2
#define ERR_ERROR 3
#define ERR_INTERNAL 4
#define ERR_SYSTEM 5
/*
* These are some defines for backwards compatibility. They should not
* be used in new code.
*/
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#ifndef __cplusplus
# ifndef true
# define true 1
# endif
# ifndef false
# define false 0
# endif
# ifndef bool
# define bool int
# endif
#endif
/*
* structure for veriusertfs array
*/
@@ -74,6 +115,20 @@ typedef struct t_tfcell
char reserved[20]; /* reserved */
} s_tfcell, *p_tfcell;
/*
* Normal PLI1.0 modules export a veriusertfs array that contains all
* the function definitions for use by the simulator. The user code is
* expected to supply that array.
*
* However, Icarus Verilog doesn't normally look for the veriusertfs
* array, it instead looks for the vlog_startup_routines array, as
* declared in vpi_user.h. So the veriuser library includes the
* veriusertfs_register function that can be used to do the PLI 1.0
* setup. Create a vlog_startup_routines table like this if you are
* just interested in making your PLI1 functions work:
*
* void (*vlog_startup_routines[])() = { &veriusertfs_register };
*/
extern s_tfcell veriusertfs[];
extern void veriusertfs_register();
@@ -88,6 +143,64 @@ extern void veriusertfs_register();
#define reason_finish 9
#define reason_endofcompile 16
/* These are values returned by tf_typep */
#define tf_nullparam 0
#define TF_NULLPARAM tf_nullparam
#define tf_string 1
#define TF_STRING tf_string
#define tf_readonly 10
#define TF_READONLY tf_readonly
#define tf_readwrite 11
#define TF_READWRITE tf_readwrite
#define tf_rwbitselect 12
#define TF_RWBITSELECT tf_rwbitselect
#define tf_rwpartselect 13
#define TF_RWPARTSELECT tf_rwpartselect
#define tf_rwmemselect 14
#define TF_RWMEMSELECT tf_rwmemselect
#define tf_readonlyreal 15
#define TF_READONLYREAL tf_readonlyreal
#define tf_readwritereal 16
#define TF_READWRITEREAD tf_readwritereal
typedef struct t_tfnodeinfo {
PLI_INT16 node_type;
PLI_INT16 padding;
union {
struct t_vecval *vecval_p;
struct t_strengthval *strengthval_p;
PLI_BYTE8 *memoryval_p;
double *read_value_p;
} node_value;
char* node_symbol;
PLI_INT32 node_ngroups;
PLI_INT32 node_vec_size;
PLI_INT32 node_sign;
PLI_INT32 node_ms_index;
PLI_INT32 node_ls_index;
PLI_INT32 node_mem_size;
PLI_INT32 node_lhs_element;
PLI_INT32 node_rhs_element;
PLI_INT32*node_handle;
} s_tfnodeinfo, *p_tfnodeinfo;
/* values used in the node_type of the tfnodeinfo structure. */
#define tf_null_node 100
#define TF_NULL_NODE tf_null_node
#define tf_reg_node 101
#define TF_REG_NODE tf_reg_node
#define tf_integer_node 102
#define TF_INTEGER_NODE tf_integer_node
#define tf_time_node 103
#define TF_TIME_NODE tf_time_node
#define tf_netvector_node 104
#define TF_NETVECTOR_NODE tf_netvector_node
#define tf_netscalar_node 105
#define TF_NETSCALAR_NODE tf_netscalar_node
#define tf_memory_node 106
#define TF_MEMORY_NODE tf_memory_node
#define tf_real_node 107
#define TF_REAL_NODE tf_real_node
/* Extern functions from the library. */
extern void io_printf (const char *, ...)
@@ -114,6 +227,12 @@ extern int tf_getlongtime(int*high_bits);
extern int tf_getp(int pnum);
extern PLI_BYTE8* tf_getworkarea(void);
extern PLI_INT32 tf_message(PLI_INT32 level, char*facility,
char*messno, char*fmt, ...)
__attribute__((format (printf,4,5)));
extern int tf_nump(void);
/* IEEE1364 NOTE: tf_putlongp is listed as returning in in the header
@@ -123,6 +242,15 @@ extern void tf_putlongp(int pnum, int lowvalue, int highvalue);
extern void tf_putp(int pnum, int value);
/* IEEE1364 NOTE: tf_setworkarea is listed as taking a PLI_BYTE8*, but
that is silly, it really takes any kind of pointer. Taking void* is
compatible with those who pass a PLI_BYTE8*. */
extern PLI_INT32 tf_setworkarea(void*workarea);
extern char* tf_spname(void);
extern PLI_INT32 tf_typep(PLI_INT32 narg);
extern void tf_warning(const char*, ...)
__attribute__((format (printf,1,2)));
@@ -130,6 +258,11 @@ EXTERN_C_END
/*
* $Log: veriuser.h,v $
* Revision 1.18 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
* Revision 1.17 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+3 -3
View File
@@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.31 2002/04/07 04:37:53 steve Exp $"
#ident "$Id: Makefile.in,v 1.32 2003/01/10 03:06:32 steve Exp $"
#
#
SHELL = /bin/sh
@@ -60,12 +60,12 @@ sys_random.o sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \
sys_lxt.o lxt_write.o \
mt19937int.o
SYSTEM_VPI_LDFLAGS = -L.. -lvpi
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@WIN32@,yes)
SYSTEM_VPI_LDFLAGS += -liberty
endif
system.vpi: $O ../libvpi.a
system.vpi: $O ../vvp/libvpi.a
$(CC) @shared@ -o $@ $O $(SYSTEM_VPI_LDFLAGS)
sys_readmem_lex.c: sys_readmem_lex.lex
+158 -80
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_display.c,v 1.46 2002/11/09 06:01:11 steve Exp $"
#ident "$Id: sys_display.c,v 1.48 2003/01/09 04:10:58 steve Exp $"
#endif
# include "config.h"
@@ -113,96 +113,158 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
}
}
static void format_time(unsigned mcd, int fsize, const char*value)
/*
* This function writes the time value into the mcd target with the
* proper format. The mcd is the destination file.
*
* The fsize is the width of the field to use. Normally, this is -1 to
* reflect the format string "%t". It may also be 0 for the format
* string "%0t". This formatter also allows for the nonstandard use of
* positive values to enforce a with to override the width given in
* the $timeformat system task.
*
* The value argument is the time value as a decimal string. There are
* no leading zeros in this string, and the units of the value are
* given in the units argument.
*/
static void format_time(unsigned mcd, int fsize,
const char*value, int time_units)
{
char buf[256];
const char*cp;
char*bp;
unsigned len;
char*bp, *start_address;
int idx, idx_point, idx_start, idx_value;
int idx;
int fraction_chars, fraction_pad, value_chop, whole_fill;
/* This is the time precision for the simulation. */
int prec = vpi_get(vpiTimePrecision, 0);
/* This is the format precision expressed as the power of 10
of the desired precision. The following code uses this
format to be consistent with the units specifications. */
int format_precision = timeformat_info.units - timeformat_info.prec;
/* If the fsize is <0, then use the value from the
$timeformat. If the fsize is >=0, then it overrides the
$timeformat value. */
if (fsize < 0)
fsize = timeformat_info.width;
/* bp starts at the end of the buffer, and works forward as we
build up the output value. */
bp = buf + sizeof buf;
assert(fsize < (sizeof buf - 1));
/* cp points to digits of the value, starting with the least
significant. If the value is only '0', then short circuit
the value by setting cp = value. */
if (value[0] != '0')
cp = value + strlen(value);
/* This is the number of characters to the right of the
decimal point. This is defined completely by the
timeformat. It is legal for the precision to be larger then
the units, and in this case there will be no fraction_chars
at all. */
fraction_chars = timeformat_info.units - format_precision;
if (fraction_chars < 0)
fraction_chars = 0;
/* This is the number of zeros I must add to the value to get
the desired precision within the fraction. If this value is
greater then 0, the value does not have enough characters,
so I will be adding zeros. */
fraction_pad = time_units - format_precision;
if (fraction_pad < 0)
fraction_pad = 0;
if (fraction_pad > fraction_chars)
fraction_pad = fraction_chars;
/* This is the number of characters of excess precision in the
supplied value. This many characters are chopped from the
least significant end. */
value_chop = format_precision - time_units;
if (value_chop < 0)
value_chop = 0;
/* This is the number of zeros that I must add to the integer
part of the output string to pad the value out to the
desired units. This will only have a non-zero value if the
units of the value is greater then the desired units.
Detect the special case where the value is 0. In this case,
do not do any integer filling ever. The output should be
padded with blanks in that case. */
whole_fill = time_units - timeformat_info.units;
if (whole_fill < 0)
whole_fill = 0;
if (strcmp(value,"0") == 0)
whole_fill = 0;
/* This is the expected start address of the output. It
accounts for the fsize value that is chosen. The output
will be filled out to complete the buffer. */
if (fsize == 0)
start_address = buf;
else
start_address = buf + sizeof buf - fsize - 1;
/* Now start the character pointers, ready to start copying
the value into the format. */
cp = value + strlen(value);
if (value_chop > (cp - value))
cp = value;
else
cp -= value_chop;
/* Draw the suffix into the buffer. */
bp = buf + sizeof buf;
*--bp = 0;
/* Write the suffix. */
bp -= strlen(timeformat_info.suff);
strcpy(bp, timeformat_info.suff);
/* This is the precision index where the decimal point goes. */
idx_point = timeformat_info.units;
/* This is the precision index where we start drawing digits. */
idx_start = idx_point - (int)timeformat_info.prec;
/* This is the precision index where the integer time value
digits start. */
idx_value = prec;
idx = idx_start;
if (idx > idx_value)
idx = idx_value;
/* If we want no precision, then set idx_point to a high value
so that the '.' is never printed. */
if (timeformat_info.prec == 0)
idx_point = idx - 1;
/* Now build up the time string, from the least significant
digit up to the last. */
while ((cp > value) || (idx <= idx_point)) {
if (idx == idx_point) {
*--bp = '.';
}
if (idx >= idx_start) {
if (idx < idx_value) {
*--bp = '0';
} else if (cp > value) {
*--bp = cp[-1];
} else {
*--bp = '0';
}
}
if ((idx >= idx_value) && (cp > value))
cp -= 1;
idx += 1;
}
/* Patch up cases that need a leading 0. */
if ((*bp == '.') || (idx == idx_start))
/* Write the padding needed to fill out the fraction. */
for (idx = 0 ; idx < fraction_pad ; idx += 1)
*--bp = '0';
/* Pad the string on the left to the requested minimum
width. Pad with spaces. */
len = strlen(bp);
while (len < fsize) {
*--bp = ' ';
len += 1;
/* Subtract the pad from the needed chars. */
assert(fraction_pad <= fraction_chars);
fraction_chars -= fraction_pad;
fraction_pad = 0;
/* Write the fraction chars. */
for (idx = 0 ; idx < fraction_chars ; idx += 1) {
if (cp > value)
*--bp = *--cp;
else
*--bp = '0';
assert(cp >= value);
}
/* Write the decimal point, if needed. */
if (timeformat_info.prec > 0)
*--bp = '.';
/* Fill the gap between the value and the decimal point. */
for (idx = 0 ; idx < whole_fill ; idx += 1)
*--bp = '0';
/* Write the integer part of the value. */
while (cp > value) {
*--bp = *--cp;
}
/* Fill the leading characters to make up the desired
width. This may require a '0' if the last character
written was the decimal point. */
if (fsize > 0) {
while (bp > start_address) {
if (*bp == '.')
*--bp = '0';
else
*--bp = ' ';
}
} else {
if (*bp == '.')
*--bp = '0';
}
vpi_mcd_printf(mcd, "%s", bp);
}
@@ -305,6 +367,8 @@ static int format_str(vpiHandle scope, unsigned int mcd,
char*cp = fmt;
char format_char = ' ';
int idx;
/* Time units of the current scope. */
int time_units = vpi_get(vpiTimeUnit, scope);
assert(fmt);
@@ -499,7 +563,8 @@ static int format_str(vpiHandle scope, unsigned int mcd,
break;
case 't':
format_time(mcd, fsize, value.value.str);
format_time(mcd, fsize,
value.value.str, time_units);
break;
case 'd':
@@ -725,19 +790,24 @@ static int get_default_format(char *name)
static int sys_display_calltf(char *name)
{
struct strobe_cb_info info;
struct strobe_cb_info*info;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle scope = vpi_handle(vpiScope, sys);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
info = vpi_get_userdata(sys);
if (info == 0) {
vpiHandle scope = vpi_handle(vpiScope, sys);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
assert(scope);
info.default_format = get_default_format(name);
info.scope = scope;
array_from_iterator(&info, argv);
assert(scope);
info = malloc(sizeof (struct strobe_cb_info));
info->default_format = get_default_format(name);
info->scope = scope;
array_from_iterator(info, argv);
do_display(5, &info);
free(info.items);
vpi_put_userdata(sys, info);
}
do_display(5, info);
if (strncmp(name,"$display",8) == 0)
vpi_mcd_printf(5, "\n");
@@ -1229,6 +1299,8 @@ static int sys_timeformat_calltf(char *xx)
static int sys_end_of_compile(p_cb_data cb_data)
{
/* The default timeformat prints times in unit of simulation
precision. */
timeformat_info.suff = strdup("");
timeformat_info.units = vpi_get(vpiTimePrecision, 0);
timeformat_info.prec = 0;
@@ -1484,6 +1556,12 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.48 2003/01/09 04:10:58 steve
* use userdata to save $display argument handles.
*
* Revision 1.47 2002/12/21 19:41:49 steve
* Rewrite time formatting to account for local scope.
*
* Revision 1.46 2002/11/09 06:01:11 steve
* display octal escapes properly.
*
+11 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_lxt.c,v 1.12 2002/11/17 22:28:42 steve Exp $"
#ident "$Id: sys_lxt.c,v 1.13 2002/12/21 00:55:58 steve Exp $"
#endif
# include "config.h"
@@ -343,6 +343,7 @@ static int sys_dumpoff_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
lt_set_time(dump_file, now.low);
@@ -368,6 +369,7 @@ static int sys_dumpon_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
lt_set_time(dump_file, now.low);
@@ -388,6 +390,7 @@ static int sys_dumpall_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
lt_set_time(dump_file, now.low);
@@ -817,6 +820,13 @@ void sys_lxt_register()
/*
* $Log: sys_lxt.c,v $
* Revision 1.13 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.12 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
+52 -1
View File
@@ -17,14 +17,25 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_time.c,v 1.4 2002/08/12 01:35:05 steve Exp $"
#ident "$Id: sys_time.c,v 1.5 2002/12/21 00:55:58 steve Exp $"
#endif
# include "config.h"
# include "vpi_user.h"
# include <string.h>
# include <assert.h>
static vpiHandle module_of_function(vpiHandle obj)
{
while (vpi_get(vpiType, obj) != vpiModule) {
obj = vpi_handle(vpiScope, obj);
assert(obj);
}
return obj;
}
static int sys_time_sizetf(char*x)
{
return 64;
@@ -40,16 +51,39 @@ static int sys_time_calltf(char*name)
s_vpi_value val;
s_vpi_time now;
vpiHandle call_handle;
vpiHandle mod;
int units, prec;
long scale;
call_handle = vpi_handle(vpiSysTfCall, 0);
assert(call_handle);
mod = module_of_function(call_handle);
now.type = vpiSimTime;
vpi_get_time(0, &now);
/* All the variants but $simtime return the time in units of
the local scope. The $simtime function returns the
simulation time. */
if (strcmp(name, "$simtime") == 0)
units = vpi_get(vpiTimePrecision, 0);
else
units = vpi_get(vpiTimeUnit, mod);
prec = vpi_get(vpiTimePrecision, 0);
scale = 1;
while (units > prec) {
scale *= 10;
units -= 1;
}
val.format = vpiIntVal;
val.value.integer = now.low;
assert(now.high == 0);
val.value.integer /= scale;
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
return 0;
@@ -64,6 +98,7 @@ void sys_time_register()
tf_data.calltf = sys_time_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_time_sizetf;
tf_data.user_data = "$time";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
@@ -71,11 +106,27 @@ void sys_time_register()
tf_data.calltf = sys_time_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_stime_sizetf;
tf_data.user_data = "$stime";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
tf_data.tfname = "$simtime";
tf_data.calltf = sys_time_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_time_sizetf;
tf_data.user_data = "$simtime";
vpi_register_systf(&tf_data);
}
/*
* $Log: sys_time.c,v $
* Revision 1.5 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.4 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
+11 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_vcd.c,v 1.39 2002/11/17 22:28:42 steve Exp $"
#ident "$Id: sys_vcd.c,v 1.40 2002/12/21 00:55:58 steve Exp $"
#endif
# include "config.h"
@@ -315,6 +315,7 @@ static int sys_dumpoff_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
@@ -342,6 +343,7 @@ static int sys_dumpon_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
@@ -364,6 +366,7 @@ static int sys_dumpall_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
@@ -849,6 +852,13 @@ void sys_vcd_register()
/*
* $Log: sys_vcd.c,v $
* Revision 1.40 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.39 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
+11 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_user.h,v 1.15 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: vpi_user.h,v 1.16 2003/01/09 04:10:17 steve Exp $"
#endif
@@ -323,6 +323,13 @@ extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
extern int vpi_free_object(vpiHandle ref);
extern int vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p);
/*
* These functions support attaching user data to an instance of a
* system task or function. These functions only apply to
* vpiSysTaskCall or vpiSysFuncCall handles.
*/
extern int vpi_put_userdata(vpiHandle obj, void*data);
extern void*vpi_get_userdata(vpiHandle obj);
/*
* Support for handling errors.
@@ -359,6 +366,9 @@ EXTERN_C_END
/*
* $Log: vpi_user.h,v $
* Revision 1.16 2003/01/09 04:10:17 steve
* Add vpi_put_userdata
*
* Revision 1.15 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
-241
View File
@@ -1,241 +0,0 @@
/*
* Copyright (c) 2001-2002 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.c,v 1.6 2002/08/12 01:35:01 steve Exp $"
#endif
#include <stdio.h>
#include <stdarg.h>
#include "vpi_user.h"
#include "vpithunk.h"
/*
* This code is linked into the VPI module, not the simulator. The
* module uses the symbols defined in here to call implementations
* supplied by the simulator, which loaded this module with dlopen or
* the equivilent.
*
* The vpi_thunk_p pointer points to a table of function pointers that
* point to all the functions that a simulator is expected to provide.
* The vlog_register_sim is a function that the simulator is expected
* to call with a value for the vpi_thunk_p pointer. This is how the
* run time linkage to all the functions in the make program are made.
*
* In Icarus Verilog, the VPI module is also supposed to export a
* vlog_startup_routines table. This is something that the programmer
* does, so the libvpi library, and the vlog_register_sim function,
* are invisible to the user.
*
* The simulator is careful to call the vpi_register_sim function from
* a loaded module before executing the startup routines.
*/
static p_vpi_thunk vpi_thunk_p = 0;
#define VPITV_CALL(fn,args) { \
if (vpi_thunk_p == 0) { \
no_sim(#fn); return; \
} \
if (vpi_thunk_p->fn == 0) { \
no_func(#fn); return; \
} \
vpi_thunk_p->fn args; \
}
#define VPIT_CALL(fn,def,args) { \
if (vpi_thunk_p == 0) { \
no_sim(#fn); return def; \
} \
if (vpi_thunk_p->fn == 0) { \
no_func(#fn); return def; \
} \
return vpi_thunk_p->fn args; \
}
static void no_sim(const char *fn)
{
fprintf(stderr, "No Simulator registered, cannot handle vpi "
"call to %s\n", fn);
}
static void no_func(const char *fn)
{
fprintf(stderr, "Simulator doesn't have a %s function\n",fn);
}
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp)
{
vpi_thunk_p = 0;
if (tp->magic != VPI_THUNK_MAGIC) {
fprintf(stderr, "Thunk Magic Number mismatch. Got %08X, expected %08x\n",
tp->magic, VPI_THUNK_MAGIC);
return 0;
}
vpi_thunk_p = tp;
return 1;
}
void vpi_register_systf(const struct t_vpi_systf_data *ss)
{
VPITV_CALL(vpi_register_systf,(ss));
}
void vpi_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
VPITV_CALL(vpi_vprintf,(fmt,ap));
va_end(ap);
}
unsigned int vpi_mcd_close(unsigned int mcd)
{
VPIT_CALL(vpi_mcd_close,-1,(mcd));
}
char *vpi_mcd_name(unsigned int mcd)
{
VPIT_CALL(vpi_mcd_name,0,(mcd));
}
unsigned int vpi_mcd_open(char *name)
{
VPIT_CALL(vpi_mcd_open,-1,(name));
}
unsigned int vpi_mcd_open_x(char *name, char *mode)
{
VPIT_CALL(vpi_mcd_open_x,-1, (name, mode));
}
int vpi_mcd_printf(unsigned int mcd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
VPIT_CALL(vpi_mcd_vprintf,0,(mcd,fmt,ap));
va_end(ap); /* bad - never hit */
}
int vpi_mcd_fputc(unsigned int mcd, unsigned char x)
{
VPIT_CALL(vpi_mcd_fputc, 0, (mcd, x));
}
int vpi_mcd_fgetc(unsigned int mcd)
{
VPIT_CALL(vpi_mcd_fgetc, -1, (mcd));
}
extern vpiHandle vpi_register_cb(p_cb_data data)
{
VPIT_CALL(vpi_register_cb,0,(data));
}
extern int vpi_remove_cb(vpiHandle ref)
{
VPIT_CALL(vpi_remove_cb,0,(ref));
}
extern void vpi_sim_control(int operation, ...)
{
va_list ap;
va_start(ap, operation);
VPITV_CALL(vpi_sim_vcontrol,(operation,ap));
va_end(ap); /* bad - never hit */
}
extern void vpi_control(int operation, ...)
{
va_list ap;
va_start(ap, operation);
VPITV_CALL(vpi_sim_vcontrol,(operation,ap));
va_end(ap); /* bad - never hit */
}
extern vpiHandle vpi_handle(int type, vpiHandle ref)
{
VPIT_CALL(vpi_handle, 0, (type, ref));
}
extern vpiHandle vpi_iterate(int type, vpiHandle ref)
{
VPIT_CALL(vpi_iterate, 0, (type, ref));
}
extern vpiHandle vpi_scan(vpiHandle iter)
{
VPIT_CALL(vpi_scan, 0, (iter));
}
extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index)
{
VPIT_CALL(vpi_handle_by_index,0,(ref, index));
}
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t)
{
VPITV_CALL(vpi_get_time, (obj,t));
}
extern int vpi_get(int property, vpiHandle ref)
{
VPIT_CALL(vpi_get, 0, (property, ref));
}
extern char* vpi_get_str(int property, vpiHandle ref)
{
VPIT_CALL(vpi_get_str, 0, (property,ref));
}
extern void vpi_get_value(vpiHandle expr, p_vpi_value value)
{
VPITV_CALL(vpi_get_value, (expr, value));
}
extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
p_vpi_time when, int flags)
{
VPIT_CALL(vpi_put_value, 0, (obj, value, when, flags));
}
extern int vpi_free_object(vpiHandle ref)
{
VPIT_CALL(vpi_free_object, -1, (ref));
}
extern int vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
{
VPIT_CALL(vpi_get_vlog_info, 0, (vlog_info_p));
}
extern int vpi_chk_error(p_vpi_error_info info)
{
VPIT_CALL(vpi_chk_error, 0, (info));
}
/*
* $Log: vpithunk.c,v $
* Revision 1.6 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/
-84
View File
@@ -1,84 +0,0 @@
#ifndef _VPI_THUNK_H_
#define _VPI_THUNK_H_ 1
/*
* Copyright (c) 2001-2002 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
#endif
/* These functions are actually defined in lieu of the vpi functions
by the simulator. These prototypes should'nt go into vpi_user.h,
because we don't want the users to be seeing this stuff. They
are non-standard. We have to put them here, so that
including vpi_user.h doesn't require including stdarg.h */
EXTERN_C_START
# include <stdarg.h>
extern void vpi_vprintf(const char*fmt, va_list ap);
extern int vpi_mcd_vprintf(unsigned int mcd, const char*fmt, va_list ap);
extern void vpi_sim_vcontrol(int operation, va_list ap);
EXTERN_C_END
#define VPI_THUNK_MAGIC (0x87836BA4)
typedef struct {
int magic;
void (*vpi_register_systf)(const struct t_vpi_systf_data*ss);
void (*vpi_vprintf)(const char*fmt, va_list ap);
unsigned int (*vpi_mcd_close)(unsigned int mcd);
char *(*vpi_mcd_name)(unsigned int mcd);
unsigned int (*vpi_mcd_open)(char *name);
unsigned int (*vpi_mcd_open_x)(char *name, char *mode);
int (*vpi_mcd_vprintf)(unsigned int mcd, const char*fmt, va_list ap);
int (*vpi_mcd_fputc)(unsigned int mcd, unsigned char x);
int (*vpi_mcd_fgetc)(unsigned int mcd);
vpiHandle (*vpi_register_cb)(p_cb_data data);
int (*vpi_remove_cb)(vpiHandle ref);
void (*vpi_sim_vcontrol)(int operation, va_list ap);
vpiHandle (*vpi_handle)(int type, vpiHandle ref);
vpiHandle (*vpi_iterate)(int type, vpiHandle ref);
vpiHandle (*vpi_scan)(vpiHandle iter);
vpiHandle (*vpi_handle_by_index)(vpiHandle ref, int index);
void (*vpi_get_time)(vpiHandle obj, s_vpi_time*t);
int (*vpi_get)(int property, vpiHandle ref);
char* (*vpi_get_str)(int property, vpiHandle ref);
void (*vpi_get_value)(vpiHandle expr, p_vpi_value value);
vpiHandle (*vpi_put_value)(vpiHandle obj, p_vpi_value value,
p_vpi_time when, int flags);
int (*vpi_free_object)(vpiHandle ref);
int (*vpi_get_vlog_info)(p_vpi_vlog_info vlog_info_p);
int (*vpi_chk_error)(p_vpi_error_info info);
} vpi_thunk, *p_vpi_thunk;
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
#endif
/*
* $Log: vpithunk.h,v $
* Revision 1.4 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/
-121
View File
@@ -1,121 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
#
# 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 Library General Public License for more details.
#
# You should have received a copy of the GNU Library 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
#
#ident "$Id: Makefile.in,v 1.44 2001/06/12 03:53:10 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CC = @CC@ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../vpip
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../vpip
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CXXFLAGS = @CXXFLAGS@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
STRIP = @STRIP@
O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \
vvm_event.o vvm_ff.o vvm_force.o \
vvm_func.o vvm_gates.o vvm_idiv.o vvm_imod.o vvm_memory.o vvm_mult.o \
vvm_mux.o vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o \
vvm_vpi.o
all: libvvm.a
libvvm.a: $O
rm -f $@
ar cvq $@ $O
%.o: %.cc
@[ -d dep ] || mkdir dep
$(CXX) -Wall -fno-exceptions $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
mv $*.d dep
clean:
rm -f *.o dep/*.d libvvm.a
install:: all installdirs \
$(libdir)/libvvm.a \
$(includedir)/vvm.h \
$(includedir)/vvm_func.h \
$(includedir)/vvm_gates.h \
$(includedir)/vvm_nexus.h \
$(includedir)/vvm_signal.h \
$(includedir)/vvm_thread.h \
$(includedir)/vvm_calltf.h
$(libdir)/libvvm.a: ./libvvm.a
$(INSTALL_DATA) ./libvvm.a $(libdir)/libvvm.a
$(includedir)/vvm.h: $(srcdir)/vvm.h
$(INSTALL_DATA) $(srcdir)/vvm.h $(includedir)/vvm.h
$(includedir)/vvm_calltf.h: $(srcdir)/vvm_calltf.h
$(INSTALL_DATA) $(srcdir)/vvm_calltf.h $(includedir)/vvm_calltf.h
$(includedir)/vvm_func.h: $(srcdir)/vvm_func.h
$(INSTALL_DATA) $(srcdir)/vvm_func.h $(includedir)/vvm_func.h
$(includedir)/vvm_gates.h: $(srcdir)/vvm_gates.h
$(INSTALL_DATA) $(srcdir)/vvm_gates.h $(includedir)/vvm_gates.h
$(includedir)/vvm_nexus.h: $(srcdir)/vvm_nexus.h
$(INSTALL_DATA) $(srcdir)/vvm_nexus.h $(includedir)/vvm_nexus.h
$(includedir)/vvm_signal.h: $(srcdir)/vvm_signal.h
$(INSTALL_DATA) $(srcdir)/vvm_signal.h $(includedir)/vvm_signal.h
$(includedir)/vvm_thread.h: $(srcdir)/vvm_thread.h
$(INSTALL_DATA) $(srcdir)/vvm_thread.h $(includedir)/vvm_thread.h
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
uninstall::
rm -f $(libdir)/libvvm.a
rm -f $(includedir)/vvm.h
rm -f $(includedir)/vvm_calltf.h
rm -f $(includedir)/vvm_func.h
rm -f $(includedir)/vvm_gates.h
rm -f $(includedir)/vvm_nexus.h
rm -f $(includedir)/vvm_signal.h
rm -f $(includedir)/vvm_thread.h
-include $(patsubst %.o, dep/%.d, $O $P)
-100
View File
@@ -1,100 +0,0 @@
#ifndef __ivl_dlfcn_H
#define __ivl_dlfcn_H
/*
* 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_dlfcn.h,v 1.5 2002/08/12 01:35:06 steve Exp $"
#endif
#if defined(__MINGW32__)
# include <windows.h>
# include <stdio.h>
typedef void * ivl_dll_t;
#elif defined(HAVE_DLFCN_H)
# include <dlfcn.h>
typedef void* ivl_dll_t;
#elif defined(HAVE_DL_H)
# include <dl.h>
typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
inline ivl_dll_t ivl_dlopen(const char *name)
{ return (void *)LoadLibrary(name); }
inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
inline void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
inline const char *dlerror(void)
{ static char s[30]; sprintf(s,"DLError:%ld", GetLastError()); return s;}
#elif defined(HAVE_DLFCN_H)
inline ivl_dll_t ivl_dlopen(const char*name)
{ return dlopen(name,RTLD_LAZY); }
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{ return dlsym(dll, nm); }
inline void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
inline ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
inline void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
inline const char*dlerror(void)
{ return strerror( errno ); }
#endif
/*
* $Log: ivl_dlfcn.h,v $
* Revision 1.5 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/01/23 04:54:38 steve
* Load modules with RTLD_LAZY
*
* Revision 1.3 2001/05/22 02:14:47 steve
* Update the mingw build to not require cygwin files.
*
* Revision 1.2 2001/05/20 15:09:40 steve
* Mingw32 support (Venkat Iyer)
*
* 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.
*
* Revision 1.1 2001/01/14 17:12:59 steve
* possible HP/UX portability support.
*
*/
#endif
-40
View File
@@ -1,40 +0,0 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <[email protected]>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.1 1999/05/09 01:24:59 steve Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here
-161
View File
@@ -1,161 +0,0 @@
#ifndef __vvm_H
#define __vvm_H
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm.h,v 1.38 2002/08/12 01:35:06 steve Exp $"
#endif
# include <cassert>
# include "vpi_priv.h"
/*
* The Verilog Virtual Machine are definitions for the virtual machine
* that executes models that the simulation generator makes.
*/
typedef unsigned vvm_u32;
class vvm_event;
class vvm_thread;
inline vpip_bit_t B_AND(vpip_bit_t l, vpip_bit_t r)
{
if (B_IS0(l)) return St0;
if (B_IS0(r)) return St0;
if (B_IS1(l) && B_IS1(r)) return St1;
return StX;
}
inline vpip_bit_t B_OR(vpip_bit_t l, vpip_bit_t r)
{
if (B_IS1(l)) return St1;
if (B_IS1(r)) return St1;
if (B_IS0(l) && B_IS0(r)) return St0;
return StX;
}
inline vpip_bit_t B_XOR(vpip_bit_t l, vpip_bit_t r)
{
if (B_ISZ(l)) return StX;
if (B_ISZ(r)) return StX;
if (B_ISX(l)) return StX;
if (B_ISX(r)) return StX;
if (B_IS0(l)) return r;
return B_IS0(r)? St1 : St0;
}
inline vpip_bit_t less_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c)
{
if (B_ISXZ(l)) return StX;
if (B_ISXZ(r)) return StX;
if ((l&0x80) > (r&0x80)) return St0;
if ((l&0x80) < (r&0x80)) return St1;
return c;
}
inline vpip_bit_t greater_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c)
{
if (B_ISXZ(l)) return StX;
if (B_ISXZ(r)) return StX;
if ((l&0x80) > (r&0x80)) return St1;
if ((l&0x80) < (r&0x80)) return St0;
return c;
}
extern vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry);
inline vpip_bit_t B_NOT(vpip_bit_t l)
{
if (B_IS0(l)) return St1;
if (B_IS1(l)) return St0;
return StX;
}
/*
* These functions return true if the transition from A to B is a
* Verilog type of negedge of posedge.
*/
extern bool negedge(vpip_bit_t from, vpip_bit_t to);
extern bool posedge(vpip_bit_t from, vpip_bit_t to);
/*
* Verilog events (update events and nonblocking assign) are derived
* from this abstract class so that the simulation engine can treat
* all of them identically.
*/
class vvm_event {
public:
vvm_event();
virtual ~vvm_event() =0;
virtual void event_function() =0;
void schedule(unsigned long delay =0);
private:
struct vpip_event*event_;
static void callback_(void*);
private: // not implemented
vvm_event(const vvm_event&);
vvm_event& operator= (const vvm_event&);
};
/*
* $Log: vvm.h,v $
* Revision 1.38 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.37 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.36 2000/04/10 05:26:06 steve
* All events now use the NetEvent class.
*
* Revision 1.35 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.34 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.33 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.32 2000/03/13 00:02:34 steve
* Remove unneeded templates.
*
* Revision 1.31 2000/02/23 04:43:43 steve
* Some compilers do not accept the not symbol.
*
* Revision 1.30 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.29 2000/01/08 03:09:14 steve
* Non-blocking memory writes.
*/
#endif
-135
View File
@@ -1,135 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_add_sub.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_add_sub::vvm_add_sub(unsigned wid)
: width_(wid), ndir_(St0)
{
ibits_ = new vpip_bit_t[width_*3];
ro_ = new vvm_nexus::drive_t[width_];
c_ = StX;
for (unsigned idx = 0 ; idx < width_*3 ; idx += 1)
ibits_[idx] = StX;
}
vvm_add_sub::~vvm_add_sub()
{
delete[]ro_;
delete[]ibits_;
}
vvm_nexus::drive_t* vvm_add_sub::config_rout(unsigned idx)
{
assert(idx < width_);
return ro_+idx;
}
vvm_nexus::drive_t* vvm_add_sub::config_cout()
{
return &co_;
}
unsigned vvm_add_sub::key_DataA(unsigned idx) const
{
assert(idx < width_);
return idx;
}
unsigned vvm_add_sub::key_DataB(unsigned idx) const
{
assert(idx < width_);
return idx+width_;
}
void vvm_add_sub::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[idx] = val;
}
void vvm_add_sub::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[width_+idx] = val;
}
void vvm_add_sub::init_Add_Sub(unsigned, vpip_bit_t val)
{
ndir_ = B_NOT(val);
}
void vvm_add_sub::start()
{
compute_();
}
void vvm_add_sub::take_value(unsigned key, vpip_bit_t val)
{
if (ibits_[key] == val) return;
ibits_[key] = val;
compute_();
}
void vvm_add_sub::compute_()
{
vpip_bit_t carry = ndir_;
vpip_bit_t*a = ibits_;
vpip_bit_t*b = ibits_+width_;
vpip_bit_t*r = ibits_+2*width_;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
vpip_bit_t val;
val = add_with_carry(a[idx], B_XOR(b[idx],ndir_), carry);
if (val == r[idx]) continue;
r[idx] = val;
vvm_event*ev = new vvm_out_event(val, ro_+idx);
ev->schedule();
}
if (carry != c_)
(new vvm_out_event(carry, &co_)) -> schedule();
}
/*
* $Log: vvm_add_sub.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/17 17:25:53 steve
* Adder and comparator in nexus style.
*
*/
-133
View File
@@ -1,133 +0,0 @@
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_bit.cc,v 1.15 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
bool negedge(vpip_bit_t from, vpip_bit_t to)
{
if (B_IS0(from))
return false;
if (B_ISX(from) || B_ISZ(from))
return B_IS0(to);
if (B_IS1(from))
return ! B_IS1(to);
return false;
}
bool posedge(vpip_bit_t from, vpip_bit_t to)
{
if (B_IS1(from))
return false;
if (B_ISX(from) || B_ISZ(from))
return B_IS1(to);
if (B_IS0(from))
return ! B_IS0(to);
return false;
}
vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry)
{
unsigned li, ri, ci;
if (B_IS1(l)) {
li = 1;
} else if (B_IS0(l)) {
li = 0;
} else {
carry = StX;
return StX;
}
if (B_IS1(r)) {
ri = 1;
} else if (B_IS0(r)) {
ri = 0;
} else {
carry = StX;
return StX;
}
if (B_IS1(carry)) {
ci = 1;
} else if (B_IS0(carry)) {
ci = 0;
} else {
carry = StX;
return StX;
}
unsigned sum = li + ri + ci;
carry = (sum & 2)? St1 : St0;
return (sum & 1)? St1 : St0;
}
/*
* $Log: vvm_bit.cc,v $
* Revision 1.15 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.14 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.13 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.12 2000/04/10 05:26:07 steve
* All events now use the NetEvent class.
*
* Revision 1.11 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.10 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.9 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.8 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.7 1999/12/02 03:36:01 steve
* shiftl and shiftr take unsized second parameter.
*
* Revision 1.6 1999/11/22 00:30:52 steve
* Detemplate some and, or and nor methods.
*
* Revision 1.5 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*/
-174
View File
@@ -1,174 +0,0 @@
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_calltf.cc,v 1.16 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "machine.h"
# include "vvm_calltf.h"
# include <vpi_user.h>
# include "vpi_priv.h"
# include <new>
# include <iostream>
# include <assert.h>
# include <stdlib.h>
# include <stdarg.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdio.h>
# include "ivl_dlfcn.h"
# include "vpithunk.h"
# define MAX_PATHLEN 1024
static char*module_path = 0;
void vvm_set_module_path(const char*path)
{
if (module_path) free(module_path);
module_path = strdup(path);
}
/*
* The load_vpi_module function attempts to locate and load the named
* vpi module and call the included startup routines. This is invoked
* by the generated C++ code to load all the modules that the
* simulation requires.
*
* If there is a '/' character in the name, or there is no
* VPI_MODULE_PATH, the the name is usd as is. No path is searched for
* the module.
*
* If there is a VPI_MODULE_PATH and there is no '/' in the name, the
* VPI_MODULE_PATH is taken as a ':' separated list of directory
* names. Each directory is searched for a module with the right name
* that will link in. The current working directory is not implicitly
* tried. If you wish '.' be in th search path, include it.
*/
typedef void (*vlog_startup_routines_t)(void);
typedef int (*vpi_register_sim_t)(p_vpi_thunk tp);
void vvm_load_vpi_module(const char*name)
{
ivl_dll_t mod = 0;
const char*path = getenv("VPI_MODULE_PATH");
if (path == 0) path = module_path;
if ((path == 0) || (strchr(name, '/'))) {
mod = ivl_dlopen(name);
if (mod == 0) {
cerr << name << ": " << dlerror() << endl;
return;
}
} else {
const char*cur = path;
const char*ep;
for (cur = path ; cur ; cur = ep? ep+1 : 0) {
char dest[MAX_PATHLEN+1];
ep = strchr(cur, ':');
size_t n = ep? ep-cur : strlen(cur);
if ((n + strlen(name) + 2) > sizeof dest)
continue;
strncpy(dest, cur, n);
dest[n] = '/';
dest[n+1] = 0;
strcat(dest, name);
mod = ivl_dlopen(dest);
if (mod) break;
}
}
if (mod == 0) {
cerr << dlerror() << endl;
return;
}
void *regsub = ivl_dlsym(mod, LU "vpi_register_sim" TU);
vpi_register_sim_t simreg = (vpi_register_sim_t)regsub;
if (regsub == 0) {
cerr << name << ": Unable to locate vpi_register_sim" << endl;
ivl_dlclose(mod);
return;
}
extern vpi_thunk vvmt;
if (((simreg)(&vvmt)) == 0) {
cerr << name << ": vpi_register_sim returned zero" << endl;
ivl_dlclose(mod);
return;
}
void*table = ivl_dlsym(mod, LU "vlog_startup_routines" TU);
vlog_startup_routines_t*routines = (vlog_startup_routines_t*)table;
if (routines == 0) {
cerr << name << ": Unable to locate the vlog_startup_routines"
" table." << endl;
ivl_dlclose(mod);
return;
}
for (unsigned idx = 0 ; routines[idx] ; idx += 1)
(routines[idx])();
}
/*
* $Log: vvm_calltf.cc,v $
* Revision 1.16 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.15 2001/09/15 18:27:04 steve
* Make configure detect malloc.h
*
* Revision 1.14 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.13 2001/06/12 03:53:10 steve
* Change the VPI call process so that loaded .vpi modules
* use a function table instead of implicit binding.
*
* Revision 1.12 2001/01/14 17:12:59 steve
* possible HP/UX portability support.
*
* Revision 1.11 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.10 2000/01/24 00:18:20 steve
* Handle systems that need underscores in symbols.
*
* Revision 1.9 1999/11/28 18:05:37 steve
* Set VPI_MODULE_PATH in the target code, if desired.
*
* 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.
*/
-60
View File
@@ -1,60 +0,0 @@
#ifndef __vvm_vvm_calltf_H
#define __vvm_vvm_calltf_H
/*
* Copyright (c) 1998-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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_calltf.h,v 1.6 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vvm.h"
# include <string>
/*
* This function loads a vpi module by name.
*/
extern void vvm_set_module_path(const char*path);
extern void vvm_load_vpi_module(const char*path);
/*
* $Log: vvm_calltf.h,v $
* Revision 1.6 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/11/28 18:05:37 steve
* Set VPI_MODULE_PATH in the target code, if desired.
*
* 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.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/
#endif
-178
View File
@@ -1,178 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_clshift.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
/*
* This is the implementation of the LMP_CLSHIFT device.
*
* The device has input/output width if width_ bits, and a distance
* input of wdist_ bits. The inputs are stored in the ibits_ array,
* the data bits first, then the select bits.
*/
vvm_clshift::vvm_clshift(unsigned wid, unsigned wid_dist)
: width_(wid), wdist_(wid_dist)
{
ibits_ = new vpip_bit_t[width_ + wdist_];
out_ = new vvm_nexus::drive_t[width_];
dist_val_ = width_;
dir_ = St0;
for (unsigned idx = 0 ; idx < width_+wdist_ ; idx += 1)
ibits_[idx] = StX;
}
vvm_clshift::~vvm_clshift()
{
delete[]out_;
delete[]ibits_;
}
vvm_nexus::drive_t* vvm_clshift::config_rout(unsigned idx)
{
return out_+idx;
}
unsigned vvm_clshift::key_Data(unsigned idx) const
{
return idx;
}
unsigned vvm_clshift::key_Distance(unsigned idx) const
{
return idx+width_;
}
unsigned vvm_clshift::key_Direction(unsigned) const
{
return 0x20000;
}
void vvm_clshift::init_Data(unsigned idx, vpip_bit_t val)
{
ibits_[idx] = val;
}
void vvm_clshift::init_Distance(unsigned idx, vpip_bit_t val)
{
ibits_[width_+idx] = val;
calculate_dist_();
}
void vvm_clshift::init_Direction(unsigned, vpip_bit_t val)
{
dir_ = val;
}
void vvm_clshift::take_value(unsigned key, vpip_bit_t val)
{
if (key == 0x20000) {
if (dir_ == val) return;
dir_ = val;
calculate_dist_();
compute_();
return;
}
if (ibits_[key] == val) return;
ibits_[key] = val;
if (key < width_) {
if ((dist_val_ + key) >= width_) return;
if ((dist_val_ + key) < 0) return;
out_[dist_val_ + key].set_value(val);
} else {
calculate_dist_();
compute_();
}
}
void vvm_clshift::compute_()
{
// The dist_val_ is set to width_ if its value is not fully
// known. In this case, just set the output to unknown.
if (dist_val_ == (int)width_) {
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
out_[idx].set_value(StX);
return;
}
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
vpip_bit_t val;
if ((idx-dist_val_) >= width_) val = St0;
else if ((idx-dist_val_) < 0) val = St0;
else val = ibits_[idx-dist_val_];
out_[idx].set_value(val);
}
}
void vvm_clshift::calculate_dist_()
{
int tmp = 0;
for (unsigned idx = 0 ; idx < wdist_ ; idx += 1) {
if (B_ISX(ibits_[width_+idx]) || B_ISZ(ibits_[width_+idx])) {
tmp = width_;
break;
}
if (B_IS1(ibits_[width_+idx]))
tmp |= 1<<idx;
}
/* If the shift amount is too large (no matter the direction)
then set it to exactly width_ and the compute_ function
will handle the case directly. Otherwise, turn the shift
amount into a signed value that depends on the direction. */
if (tmp > (int)width_)
tmp = width_;
else if (B_IS1(dir_))
tmp = -tmp;
dist_val_ = tmp;
}
/*
* $Log: vvm_clshift.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/17 02:22:03 steve
* vvm_clshift implementation without templates.
*
*/
-137
View File
@@ -1,137 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_compare.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_compare::vvm_compare(unsigned wid)
: width_(wid)
{
gt_ = StX;
lt_ = StX;
ibits_ = new vpip_bit_t[2*width_];
for (unsigned idx = 0 ; idx < 2*width_ ; idx += 1)
ibits_[idx] = StX;
}
vvm_compare::~vvm_compare()
{
delete[]ibits_;
}
void vvm_compare::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[idx] = val;
}
void vvm_compare::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[width_+idx] = val;
}
vvm_nexus::drive_t* vvm_compare::config_ALB_out()
{
return &out_lt_;
}
vvm_nexus::drive_t* vvm_compare::config_ALEB_out()
{
return &out_le_;
}
vvm_nexus::drive_t* vvm_compare::config_AGB_out()
{
return &out_gt_;
}
vvm_nexus::drive_t* vvm_compare::config_AGEB_out()
{
return &out_ge_;
}
unsigned vvm_compare::key_DataA(unsigned idx) const
{
assert(idx < width_);
return idx;
}
unsigned vvm_compare::key_DataB(unsigned idx) const
{
assert(idx < width_);
return width_ + idx;
}
void vvm_compare::take_value(unsigned key, vpip_bit_t val)
{
if (ibits_[key] == val)
return;
ibits_[key] = val;
compute_();
}
void vvm_compare::compute_()
{
vpip_bit_t gt = St0;
vpip_bit_t lt = St0;
vpip_bit_t*a = ibits_;
vpip_bit_t*b = ibits_+width_;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
gt = greater_with_cascade(a[idx], b[idx], gt);
lt = less_with_cascade(a[idx], b[idx], lt);
}
if ((gt_ == gt) && (lt_ == lt)) return;
gt_ = gt;
lt_ = lt;
out_lt_.set_value(lt_);
out_le_.set_value(B_NOT(gt_));
out_gt_.set_value(gt_);
out_ge_.set_value(B_NOT(lt_));
}
/*
* $Log: vvm_compare.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/17 17:25:53 steve
* Adder and comparator in nexus style.
*
*/
-79
View File
@@ -1,79 +0,0 @@
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_event.cc,v 1.7 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
# include <assert.h>
vvm_event::vvm_event()
{
event_ = 0;
}
vvm_event::~vvm_event()
{
assert(event_ == 0);
}
void vvm_event::schedule(unsigned long delay)
{
event_ = vpip_sim_insert_event(delay, this, callback_, 0);
}
void vvm_event::callback_(void*cbd)
{
vvm_event*obj = reinterpret_cast<vvm_event*>(cbd);
obj->event_ = 0;
obj->event_function();
delete obj;
}
/*
* $Log: vvm_event.cc,v $
* Revision 1.7 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 2000/01/06 05:56:22 steve
* Cleanup and some asserts.
*
* Revision 1.3 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* 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.
*
*/
-117
View File
@@ -1,117 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_ff.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
vvm_ff::vvm_ff(unsigned w)
: width_(w)
{
out_ = new vvm_nexus::drive_t[width_];
bits_ = new vpip_bit_t[width_*2];
for (unsigned idx = 0 ; idx < width_*2 ; idx += 1)
bits_[idx] = StX;
}
vvm_ff::~vvm_ff()
{
delete[]bits_;
delete[]out_;
}
vvm_nexus::drive_t* vvm_ff::config_rout(unsigned idx)
{
assert(idx < width_);
return out_+idx;
}
unsigned vvm_ff::key_Data(unsigned idx) const
{
assert(idx < width_);
return idx+width_;
}
unsigned vvm_ff::key_Clock() const
{
return 0;
}
void vvm_ff::init_Data(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
bits_[idx+width_] = val;
}
void vvm_ff::init_Clock(unsigned, vpip_bit_t val)
{
clk_ = val;
}
void vvm_ff::take_value(unsigned key, vpip_bit_t val)
{
if (key == 0) {
if (val == clk_)
return;
bool flag = posedge(clk_, val);
clk_ = val;
if (flag)
latch_();
return;
}
bits_[key] = val;
}
void vvm_ff::latch_()
{
vpip_bit_t*q = bits_;
vpip_bit_t*d = bits_+width_;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
if (q[idx] == d[idx])
continue;
q[idx] = d[idx];
out_[idx].set_value(q[idx]);
}
}
/*
* $Log: vvm_ff.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/18 23:22:37 steve
* Update the FF device to nexus style.
*
*/
-114
View File
@@ -1,114 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_force.cc,v 1.5 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_force::vvm_force(unsigned w)
: width_(w)
{
force_flag_ = true;
bits_ = new vpip_bit_t[width_];
target_ = new vvm_nexus*[width_];
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
target_[idx] = 0;
}
vvm_force::~vvm_force()
{
delete[]bits_;
delete[]target_;
}
void vvm_force::init_I(unsigned key, vpip_bit_t val)
{
assert(key < width_);
bits_[key] = val;
}
void vvm_force::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (bits_[key] == val)
return;
bits_[key] = val;
if (! target_[key]) return;
if (force_flag_)
target_[key]->force_assign(val);
else
target_[key]->cassign(val);
}
void vvm_force::assign(unsigned key, vvm_nexus*tgt)
{
assert(key < width_);
assert(target_[key] == 0);
force_flag_ = false;
target_[key] = tgt;
target_[key]->cassign_set(this, key);
target_[key]->cassign(bits_[key]);
}
void vvm_force::force(unsigned key, vvm_nexus*tgt)
{
assert(key < width_);
assert(target_[key] == 0);
force_flag_ = true;
target_[key] = tgt;
target_[key]->force_set(this, key);
target_[key]->force_assign(bits_[key]);
}
/*
* This method is to be called from the vvm_nexus only when it has
* been told to release me.
*/
void vvm_force::release(unsigned key)
{
assert(target_[key]);
target_[key] = 0;
}
/*
* $Log: vvm_force.cc,v $
* Revision 1.5 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.3 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
* Revision 1.2 2000/04/23 03:45:25 steve
* Add support for the procedural release statement.
*
* Revision 1.1 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
*/
-705
View File
@@ -1,705 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_func.cc,v 1.18 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_func.h"
vpip_bit_t vvm_unop_and(const vvm_bitset_t&r)
{
vpip_bit_t v = r[0];
for (unsigned idx = 1 ; idx < r.get_width() ; idx += 1)
v = B_AND(v, r[idx]);
return v;
}
vpip_bit_t vvm_unop_nand(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_and(r);
return B_NOT(v);
}
vpip_bit_t vvm_unop_lnot(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_or(r);
return B_NOT(v);
}
void vvm_unop_not(vvm_bitset_t&v, const vvm_bitset_t&p)
{
assert(v.nbits <= p.nbits);
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = B_NOT(p[idx]);
}
vpip_bit_t vvm_unop_or(const vvm_bitset_t&r)
{
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_IS1(r.get_bit(idx)))
return St1;
}
return St0;
}
vpip_bit_t vvm_unop_nor(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_or(r);
return B_NOT(v);
}
void vvm_unop_uminus(vvm_bitset_t&v, const vvm_bitset_t&l)
{
vvm_unop_not(v, l);
vpip_bit_t carry = St1;
for (unsigned i = 0 ; i < v.nbits ; i += 1)
v[i] = add_with_carry(v[i], St0, carry);
}
vpip_bit_t vvm_unop_xor(const vvm_bitset_t&r)
{
vpip_bit_t v = St0;
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_IS1(r.get_bit(idx)))
v = B_NOT(v);
}
return v;
}
vpip_bit_t vvm_unop_xnor(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_xor(r);
return B_NOT(v);
}
/*
* Do a bitwise AND into the result. We only need to calculate enough
* bits to fill the result. If I need to extend either value, extend
* it with St0.
*/
void vvm_binop_and(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
unsigned min = v.nbits;
if (r.nbits < min) min = r.nbits;
if (l.nbits < min) min = l.nbits;
for (unsigned idx = 0 ; idx < min ; idx += 1)
v[idx] = B_AND(l[idx], r[idx]);
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
v[idx] = St0;
}
void vvm_binop_minus(vvm_bitset_t&v, const vvm_bitset_t&l,
const vvm_bitset_t&r)
{
vvm_unop_not(v, r);
vpip_bit_t carry = St1;
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = add_with_carry(l[idx], v[idx], carry);
}
void vvm_binop_nor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
unsigned min = v.nbits;
if (r.nbits < min) min = r.nbits;
if (l.nbits < min) min = l.nbits;
for (unsigned idx = 0 ; idx < min ; idx += 1)
v[idx] = B_NOT(B_OR(l[idx], r[idx]));
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
v[idx] = B_NOT(r.nbits > min? r[idx] : l[idx]);
}
void vvm_binop_or(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
unsigned min = v.nbits;
if (r.nbits < min) min = r.nbits;
if (l.nbits < min) min = l.nbits;
for (unsigned idx = 0 ; idx < min ; idx += 1)
v[idx] = B_OR(l[idx], r[idx]);
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
v[idx] = r.nbits > min? r[idx] : l[idx];
}
/*
* This function adds two vectors to make a result vector. The
* operands and the result have their sizes already determined, so we
* take those into account.
*/
void vvm_binop_plus(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t carry = St0;
unsigned top = v.nbits;
if (l.nbits < top)
top = l.nbits;
if (r.nbits < top)
top = r.nbits;
unsigned idx;
/* First do the addition for the part of the vector where we
know that the bits from both inputs are present. */
for (idx = 0 ; idx < top ; idx += 1)
v[idx] = add_with_carry(l[idx], r[idx], carry);
/* Now continue the addition, padding the shorter vector with
St0 until we fill the result vector. */
for ( ; idx < v.nbits ; idx += 1) {
vpip_bit_t lv = (idx < l.nbits) ? l[idx] : St0;
vpip_bit_t rv = (idx < r.nbits) ? r[idx] : St0;
v[idx] = add_with_carry(lv, rv, carry);
}
}
void vvm_binop_shiftl(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r)
{
assert(v.nbits <= l.nbits);
vvm_u32 s = r.as_unsigned();
for (unsigned idx = 0 ; idx < v.nbits; idx += 1)
v[idx] = (idx < s) ? St0 : l[idx-s];
}
void vvm_binop_shiftr(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r)
{
vvm_u32 s = r.as_unsigned();
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = ((idx+s) < l.nbits) ? l[idx+s] : St0;
}
void vvm_binop_xnor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.nbits <= l.nbits);
assert(v.nbits <= r.nbits);
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = B_NOT(B_XOR(l[idx], r[idx]));
}
void vvm_binop_xor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.nbits <= l.nbits);
assert(v.nbits <= r.nbits);
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = B_XOR(l[idx], r[idx]);
}
vpip_bit_t vvm_binop_eq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
return StX;
if (B_ISXZ(r.get_bit(idx)))
return StX;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = lwid ; idx < rwid ; idx += 1) {
if (B_IS0(r.get_bit(idx)))
continue;
if (B_IS1(r.get_bit(idx)))
return St0;
return StX;
}
return St1;
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
return StX;
if (B_ISXZ(r.get_bit(idx)))
return StX;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = rwid ; idx < lwid ; idx += 1) {
if (B_IS0(l.get_bit(idx)))
continue;
if (B_IS1(l.get_bit(idx)))
return St0;
return StX;
}
return St1;
}
}
vpip_bit_t vvm_binop_ne(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = vvm_binop_eq(l,r);
return B_NOT(result);
}
vpip_bit_t vvm_binop_eeq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1)
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
if (! B_IS0(r.get_bit(idx)))
return St0;
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1)
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
if (! B_IS0(l.get_bit(idx)))
return St0;
}
return St1;
}
vpip_bit_t vvm_binop_nee(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = vvm_binop_eeq(l,r);
return B_NOT(result);
}
vpip_bit_t vvm_binop_xeq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
continue;
if (B_ISXZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = lwid ; idx < rwid ; idx += 1) {
if (B_ISXZ(r.get_bit(idx)))
continue;
if (! B_IS0(r.get_bit(idx)))
return St0;
}
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
continue;
if (B_ISXZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = rwid ; idx < lwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
continue;
if (! B_IS0(l.get_bit(idx)))
return St0;
}
}
return St1;
}
vpip_bit_t vvm_binop_zeq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1) {
if (B_ISZ(l.get_bit(idx)) || B_ISZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = lwid ; idx < rwid ; idx += 1) {
if (B_ISZ(r.get_bit(idx)))
continue;
if (! B_IS0(r.get_bit(idx)))
return St0;
}
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1) {
if (B_ISZ(l.get_bit(idx)) || B_ISZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = rwid ; idx < lwid ; idx += 1) {
if (B_ISZ(l.get_bit(idx)))
continue;
if (! B_IS0(l.get_bit(idx)))
return St0;
}
}
return St1;
}
vpip_bit_t vvm_binop_lt(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result;
result = St0;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = less_with_cascade(l.get_bit(idx), r.get_bit(idx), result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = less_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = less_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the < operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_lt_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) < $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_lt(l, r);
/* If l < 0 and r < 0, return $unsigned(r) < $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_lt(r, l);
/* If l >= 0 and r < 0, return false; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St0;
/* if l < 0 and r >= 0, return true; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St1;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_le(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = St1;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = less_with_cascade(l.get_bit(idx), r.get_bit(idx), result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = less_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = less_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the <= operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_le_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) <= $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_le(l, r);
/* If l < 0 and r < 0, return $unsigned(r) <= $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_le(r, l);
/* If l >= 0 and r < 0, return false; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St0;
/* if l < 0 and r >= 0, return true; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St1;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_gt(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = St0;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = greater_with_cascade(l.get_bit(idx),
r.get_bit(idx),
result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = greater_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = greater_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the > operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_gt_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) > $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_gt(l, r);
/* If l < 0 and r < 0, return $unsigned(r) > $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_gt(r, l);
/* If l >= 0 and r < 0, return true; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St1;
/* if l < 0 and r >= 0, return false; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St0;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_ge(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = St1;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = greater_with_cascade(l.get_bit(idx),
r.get_bit(idx), result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = greater_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = greater_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the >= operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_ge_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) >= $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_ge(l, r);
/* If l < 0 and r < 0, return $unsigned(r) >= $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_ge(r, l);
/* If l >= 0 and r < 0, return true; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St1;
/* if l < 0 and r >= 0, return false; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St0;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_land(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t res1 = vvm_unop_or(l);
vpip_bit_t res2 = vvm_unop_or(r);
return B_AND(res1, res2);
}
vpip_bit_t vvm_binop_lor(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t res1 = vvm_unop_or(l);
vpip_bit_t res2 = vvm_unop_or(r);
return B_OR(res1, res2);
}
void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c,
const vvm_bitset_t&t,
const vvm_bitset_t&f)
{
if (B_IS0(c)) {
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = (idx < f.nbits)? f[idx] : St0;
return;
}
if (B_IS1(c)) {
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = (idx < t.nbits)? t[idx] : St0;
return;
}
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1) {
vpip_bit_t tb = (idx < t.nbits)? t[idx] : St0;
vpip_bit_t fb = (idx < f.nbits)? f[idx] : St0;
if (B_EQ(tb, fb))
v[idx] = tb;
else
v[idx] = StX;
}
}
/*
* $Log: vvm_func.cc,v $
* Revision 1.18 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.17 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.16 2001/02/13 03:38:55 steve
* Binary or and nor resilient to bit widths.
*
* Revision 1.15 2001/02/10 01:57:18 steve
* Make the add func resilient to bit widths (PR#141)
*
* Revision 1.14 2001/02/07 21:47:13 steve
* Fix expression widths for rvalues and parameters (PR#131,132)
*
* Revision 1.13 2000/12/11 00:31:44 steve
* Add support for signed reg variables,
* simulate in t-vvm signed comparisons.
*
* Revision 1.12 2000/07/06 18:12:28 steve
* unop_not can take out width same as in width.
*
* Revision 1.11 2000/06/30 15:47:06 steve
* Reduce result is OK in ~ operator.
*
* Revision 1.10 2000/05/18 20:35:08 steve
* Ternary operator handles bit sizes.
*
* Revision 1.9 2000/05/18 20:23:40 steve
* Overcautious assert in shift is removed.
*
* Revision 1.8 2000/04/29 01:19:47 steve
* Proper bounds checking of the left operator of right shift.
*
* Revision 1.7 2000/04/26 03:32:40 steve
* AND handles argument padding if necessary.
*
* Revision 1.6 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.5 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*
* Revision 1.4 2000/03/25 02:43:56 steve
* Remove all remain vvm_bitset_t return values,
* and disallow vvm_bitset_t copying.
*
* Revision 1.3 2000/03/24 02:43:37 steve
* vvm_unop and vvm_binop pass result by reference
* instead of returning a value.
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/13 00:02:34 steve
* Remove unneeded templates.
*
*/
-269
View File
@@ -1,269 +0,0 @@
#ifndef __vvm_vvm_func_H
#define __vvm_vvm_func_H
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_func.h,v 1.31 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vvm.h"
# include "vvm_signal.h"
/*
* Implement the unary NOT operator in the verilog way. This takes a
* vector of a certain width and returns a result of the same width.
*/
extern void vvm_unop_not(vvm_bitset_t&v, const vvm_bitset_t&p);
/*
* The unary AND is the reduction AND. It returns a single bit.
*/
extern vpip_bit_t vvm_unop_and(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_nand(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_lnot(const vvm_bitset_t&r);
/*
* The unary OR is the reduction OR. It returns a single bit.
*/
extern vpip_bit_t vvm_unop_or(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_nor(const vvm_bitset_t&r);
/*
* The unary XOR is the reduction XOR. It returns a single bit.
*/
extern vpip_bit_t vvm_unop_xor(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_xnor(const vvm_bitset_t&r);
/*
* simple-minded unary minus operator (two's complement)
*/
extern void vvm_unop_uminus(vvm_bitset_t&v, const vvm_bitset_t&l);
/*
* Implement the binary AND operator. This is a bitwise and with all
* the parameters and the result having the same width.
*/
extern void vvm_binop_and(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Implement the binary OR operator. This is a bitwise and with all
* the parameters and the result having the same width.
*/
extern void vvm_binop_or(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
extern void vvm_binop_nor(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Implement the binary + operator in the verilog way. This takes
* vectors of identical width and returns another vector of same width
* that contains the arithmetic sum. Z values are converted to X.
*/
extern void vvm_binop_plus(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Integer division and modulus
*/
extern void vvm_binop_idiv(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
extern void vvm_binop_imod(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* The binary - operator is turned into + by doing 2's complement
* arithmetic. l-r == l+~r+1. The "+1" is accomplished by adding in a
* carry of 1 to the 0 bit position.
*/
extern void vvm_binop_minus(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* The multiply binary operator takes an A and B parameter and returns
* the result in the vpip_bit_t array. The template form arranges for
* the right parameters to be passed to the extern form.
*/
extern void vvm_binop_mult(vpip_bit_t*res, unsigned nres,
const vpip_bit_t*a, unsigned na,
const vpip_bit_t*b, unsigned nb);
inline void vvm_binop_mult(vvm_bitset_t&r,
const vvm_bitset_t&a,
const vvm_bitset_t&b)
{
vvm_binop_mult(r.bits, r.nbits,
a.bits, a.nbits,
b.bits, b.nbits);
}
/*
* The binary ^ (xor) operator is a bitwise XOR of equal width inputs
* to generate the corresponsing output.
*/
extern void vvm_binop_xor(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
extern void vvm_binop_xnor(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* the binary 'l' operator is a logic left-shift by the number of positions
* indicated by argument r. r is an unsigned integer, which is represented
* internally as a 32-bit bitvector.
*/
extern void vvm_binop_shiftl(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* The binary 'r' operator is a logic right-shift by the number of positions
* indicated by argument r. r is an unsigned integer, which is represented
* internally by a 32-bit bitvector.
*/
extern void vvm_binop_shiftr(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Tests for equality are a bit tricky, as they allow for the left and
* right subexpressions to have different size. The shorter bitset is
* extended with zeros. Also, if there is Vx or Vz anywhere in either
* vectors, the result is Vx.
*/
extern vpip_bit_t vvm_binop_eq(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_ne(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* This function return true if all the bits are the same. Even x and
* z bites are compared for equality.
*/
extern vpip_bit_t vvm_binop_eeq(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_nee(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* This function return true if all the bits are the same. The x and z
* bits are don't care, s don't make the result false.
*/
extern vpip_bit_t vvm_binop_xeq(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* This function return true if all the bits are the same. The z
* bits are don't care, so don't make the result false.
*/
extern vpip_bit_t vvm_binop_zeq(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* The _s variants are signed versions. That is, it assumes the
* operands are signed values and does the comparison on that basis.
*/
extern vpip_bit_t vvm_binop_lt(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_lt_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_le(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_le_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_gt(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_gt_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_ge(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_ge_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_land(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_lor(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c,
const vvm_bitset_t&t,
const vvm_bitset_t&f);
/*
* $Log: vvm_func.h,v $
* Revision 1.31 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.30 2000/12/11 00:31:44 steve
* Add support for signed reg variables,
* simulate in t-vvm signed comparisons.
*
* Revision 1.29 2000/05/19 04:22:56 steve
* Add the integer modulus function.
*
* Revision 1.28 2000/04/01 21:40:23 steve
* Add support for integer division.
*
* Revision 1.27 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.26 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*
* Revision 1.25 2000/03/25 02:43:57 steve
* Remove all remain vvm_bitset_t return values,
* and disallow vvm_bitset_t copying.
*
* Revision 1.24 2000/03/24 02:43:37 steve
* vvm_unop and vvm_binop pass result by reference
* instead of returning a value.
*
* Revision 1.23 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.22 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.21 2000/03/13 00:02:34 steve
* Remove unneeded templates.
*
* Revision 1.20 2000/02/23 04:43:43 steve
* Some compilers do not accept the not symbol.
*
* Revision 1.19 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.18 2000/01/13 06:05:46 steve
* Add the XNOR operator.
*
* Revision 1.17 2000/01/13 03:35:35 steve
* Multiplication all the way to simulation.
*
* Revision 1.16 1999/12/02 03:36:01 steve
* shiftl and shiftr take unsized second parameter.
*/
#endif
-971
View File
@@ -1,971 +0,0 @@
/*
* Copyright (c) 1999-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_gates.cc,v 1.24 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <stdlib.h>
# include <typeinfo>
# include <string>
# include <map>
# include <sys/time.h>
# include <unistd.h>
vvm_out_event::vvm_out_event(vpip_bit_t v, vvm_nexus::drive_t*o)
: output_(o), val_(v)
{
}
vvm_out_event::~vvm_out_event()
{
}
void vvm_out_event::event_function()
{
output_->set_value(val_);
}
vvm_1bit_out::vvm_1bit_out(unsigned d)
: delay_(d)
{
drive0_ = St0;
drive1_ = St1;
driveX_ = StX;
driveZ_ = HiZ;
}
vvm_1bit_out::~vvm_1bit_out()
{
}
void vvm_1bit_out::drive0(vpip_bit_t v)
{
drive0_ = v;
driveX_ = (drive1_&0xf0) | (drive0_&0x0f);
}
void vvm_1bit_out::drive1(vpip_bit_t v)
{
drive1_ = v;
driveX_ = (drive1_&0xf0) | (drive0_&0x0f);
}
void vvm_1bit_out::driveZ(vpip_bit_t v)
{
driveZ_ = v;
}
void vvm_1bit_out::output(vpip_bit_t val)
{
if (delay_) {
vvm_event*ev = new vvm_out_event(val, this);
ev -> schedule(delay_);
} else {
set_value(val);
}
}
vpip_bit_t compute_and(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1 ; i < count ; i += 1)
outval = B_AND(outval, inp[i]);
return outval;
}
vpip_bit_t compute_or(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1 ; i < count ; i += 1)
outval = B_OR(outval, inp[i]);
return outval;
}
vpip_bit_t compute_nor(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1 ; i < count ; i += 1)
outval = B_OR(outval, inp[i]);
return B_NOT(outval);
}
vpip_bit_t compute_xor(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1; i < count; i++)
outval = B_XOR(outval, inp[i]);
return outval;
}
vpip_bit_t compute_nand(const vpip_bit_t*inp, unsigned count)
{
return B_NOT(compute_and(inp,count));
}
vpip_bit_t compute_xnor(const vpip_bit_t*inp, unsigned count)
{
return B_NOT(compute_xor(inp,count));
}
vpip_bit_t reduce_strength(vpip_bit_t val)
{
if (B_IS0(val)) {
if ((val == Su0) ||
(val == St0))
return(Pu0);
else if (val == Pu0)
return(We0);
else if ((val == We0) ||
(val == La0))
return(Me0);
else if ((val == Me0) ||
(val == Sm0))
return(Sm0);
} else if (B_IS1(val)) {
if ((val == Su1) ||
(val == St1))
return(Pu1);
else if (val == Pu1)
return(We1);
else if ((val == We1) ||
(val == La1))
return(Me1);
else if ((val == Me1) ||
(val == Sm1))
return(Sm1);
} else if (B_ISX(val)) {
if ((val == SuX) ||
(val == StX))
return(PuX);
else if (val == PuX)
return(WeX);
else if ((val == WeX) ||
(val == LaX))
return(MeX);
else if ((val == MeX) ||
(val == SmX))
return(SmX);
}
return(HiZ);
}
vvm_and::vvm_and(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_and::~vvm_and()
{
delete [] input_;
}
void vvm_and::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_and::start()
{
output(compute_and(input_,width_));
}
void vvm_and::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_and(input_,width_));
}
vvm_and2::vvm_and2(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_and2::~vvm_and2()
{
}
void vvm_and2::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < 2);
input_[idx] = val;
}
void vvm_and2::start()
{
output(B_AND(input_[0], input_[1]));
}
void vvm_and2::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val)
return;
input_[key] = val;
output(B_AND(input_[0], input_[1]));
}
vvm_buf::vvm_buf(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_buf::~vvm_buf()
{
}
void vvm_buf::init_I(unsigned, vpip_bit_t)
{
}
void vvm_buf::take_value(unsigned, vpip_bit_t val)
{
vpip_bit_t outval = val;
if (B_ISXZ(val))
outval = StX;
else if (B_IS1(val))
outval = St1;
else
outval = St0;
output(outval);
}
vvm_bufif0::vvm_bufif0(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_bufif0::~vvm_bufif0()
{
}
void vvm_bufif0::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_bufif0::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS0(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_bufif1::vvm_bufif1(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_bufif1::~vvm_bufif1()
{
}
void vvm_bufif1::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_bufif1::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS0(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS1(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_bufz::vvm_bufz(unsigned delay)
: vvm_1bit_out(delay)
{
}
vvm_bufz::~vvm_bufz()
{
}
void vvm_bufz::init_I(unsigned, vpip_bit_t val)
{
output(val);
}
void vvm_bufz::take_value(unsigned, vpip_bit_t val)
{
output(val);
}
vvm_eeq::vvm_eeq(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_eeq::~vvm_eeq()
{
}
void vvm_eeq::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_eeq::start()
{
output(compute_());
}
void vvm_eeq::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val)
return;
input_[key] = val;
output(compute_());
}
vpip_bit_t vvm_eeq::compute_() const
{
vpip_bit_t outval = St0;
if (B_EQ(input_[0], input_[1]))
outval = St1;
return outval;
}
vvm_nand::vvm_nand(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_nand::~vvm_nand()
{
delete [] input_;
}
void vvm_nand::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_nand::start()
{
output(compute_nand(input_,width_));
}
void vvm_nand::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_nand(input_, width_));
}
vvm_nor::vvm_nor(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_nor::~vvm_nor()
{
delete [] input_;
}
void vvm_nor::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_nor::start()
{
output(compute_nor(input_,width_));
}
void vvm_nor::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_nor(input_, width_));
}
vvm_or::vvm_or(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_or::~vvm_or()
{
delete [] input_;
}
void vvm_or::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_or::start()
{
output(compute_or(input_,width_));
}
void vvm_or::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_or(input_, width_));
}
vvm_nmos::vvm_nmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_nmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_nmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) {
return;
}
input_[key] = val;
if ( B_IS0(input_[1])) {
output(HiZ);
} else if (B_ISX(input_[0]))
output(StX);
else if (B_ISZ(input_[0])) {
output(HiZ);
} else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS1(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_rnmos::vvm_rnmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_rnmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_rnmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS0(input_[1]))
output(HiZ);
else if (B_ISX(input_[0]))
output(reduce_strength(input_[0]));
else if (B_ISZ(input_[0]))
output(HiZ);
else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StL);
}
} else {
if (B_IS1(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StH);
}
}
}
vvm_pmos::vvm_pmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_pmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_pmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if (B_ISX(input_[0]))
output(StX);
else if (B_ISZ(input_[0]))
output(HiZ);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS0(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_rpmos::vvm_rpmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_rpmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_rpmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if (B_ISX(input_[0]))
output(reduce_strength(input_[0]));
else if (B_ISZ(input_[0]))
output(HiZ);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StL);
}
} else {
if (B_IS0(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StH);
}
}
}
void vvm_nor2::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < 2);
input_[idx] = val;
}
void vvm_nor2::start()
{
output(B_NOT(B_OR(input_[0], input_[1])));
}
vvm_nor2::vvm_nor2(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_nor2::~vvm_nor2()
{
}
void vvm_nor2::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val)
return;
input_[key] = val;
output(B_NOT(B_OR(input_[0], input_[1])));
}
vvm_not::vvm_not(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_not::~vvm_not()
{
}
void vvm_not::init_I(unsigned, vpip_bit_t)
{
}
void vvm_not::start()
{
}
void vvm_not::take_value(unsigned, vpip_bit_t val)
{
output(B_NOT(val));
}
vvm_notif0::vvm_notif0(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_notif0::~vvm_notif0()
{
}
void vvm_notif0::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_notif0::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(St1);
} else {
output(StH);
}
} else {
if (B_IS0(input_[1])) {
output(St0);
} else {
output(StL);
}
}
}
vvm_notif1::vvm_notif1(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_notif1::~vvm_notif1()
{
}
void vvm_notif1::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_notif1::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS0(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(St1);
} else {
output(StH);
}
} else {
if (B_IS1(input_[1])) {
output(St0);
} else {
output(StL);
}
}
}
vvm_xnor::vvm_xnor(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_xnor::~vvm_xnor()
{
delete [] input_;
}
void vvm_xnor::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_xnor::start()
{
output(compute_xnor(input_,width_));
}
void vvm_xnor::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_xnor(input_, width_));
}
vvm_xor::vvm_xor(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_xor::~vvm_xor()
{
delete [] input_;
}
void vvm_xor::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_xor::start()
{
output(compute_xor(input_,width_));
}
void vvm_xor::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_xor(input_, width_));
}
vvm_pullup::vvm_pullup(unsigned d)
: vvm_1bit_out(d)
{
}
void vvm_pullup::start()
{
output(St1);
}
void vvm_pullup::take_value(unsigned key, vpip_bit_t val)
{
}
vvm_pullup::~vvm_pullup()
{
}
vvm_pulldown::vvm_pulldown(unsigned d)
: vvm_1bit_out(d)
{
}
void vvm_pulldown::start()
{
output(St0);
}
void vvm_pulldown::take_value(unsigned key, vpip_bit_t val)
{
}
vvm_pulldown::~vvm_pulldown()
{
}
/*
* $Log: vvm_gates.cc,v $
* Revision 1.24 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.23 2001/10/14 03:50:53 steve
* vvm support for pullup/down gates (PR#288)
*
* Revision 1.22 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.21 2001/01/16 03:57:46 steve
* Get rid of gate templates.
*
* Revision 1.20 2000/12/10 06:42:00 steve
* Support delays on continuous assignment from idents. (PR#40)
*
* Revision 1.19 2000/11/11 01:52:09 steve
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
* change set to correct behavior of bufif0 and bufif1
* (Tim Leight)
*
* Also includes fix for PR#27
*
* Revision 1.18 2000/07/11 23:08:33 steve
* proper init method for bufz devices.
*
* Revision 1.17 2000/07/08 22:39:32 steve
* pass zero-delay values immediately.
*
* Revision 1.16 2000/05/11 01:37:33 steve
* Calculate the X output value from drive0 and drive1
*
* Revision 1.15 2000/05/09 21:16:35 steve
* Give strengths to logic and bufz devices.
*
* Revision 1.14 2000/05/08 05:27:32 steve
* Restore vvm_bufz to working condition.
*
* Revision 1.13 2000/04/23 21:15:07 steve
* Emit code for the bufif devices.
*
* Revision 1.12 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.11 2000/03/18 02:26:02 steve
* Update bufz to nexus style.
*
* Revision 1.10 2000/03/18 01:27:00 steve
* Generate references into a table of nexus objects instead of
* generating lots of isolated nexus objects. Easier on linkers
* and compilers,
*
* Add missing nexus support for l-value bit selects,
*
* Detemplatize the vvm_mux type.
*
* Fix up the vvm_nexus destructor to disconnect from drivers.
*
* Revision 1.9 2000/03/17 19:24:00 steve
* nor2 and and2 optimized gates.
*
* Revision 1.8 2000/03/17 03:36:07 steve
* Remove some useless template parameters.
*
* Revision 1.7 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.6 2000/02/24 01:56:28 steve
* change not to v_not.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.3 1999/12/02 04:54:11 steve
* Handle mux sel of X, if inputs are equal.
*
* Revision 1.2 1999/11/24 04:38:49 steve
* LT and GT fixes from Eric Aardoom.
*
* Revision 1.1 1999/11/22 00:30:52 steve
* Detemplate some and, or and nor methods.
*
*/
-1069
View File
File diff suppressed because it is too large Load Diff
-157
View File
@@ -1,157 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_idiv.cc,v 1.3 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_func.h"
# include "vvm_gates.h"
# include <assert.h>
void vvm_binop_idiv(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.get_width() <= 8*sizeof(unsigned long));
assert(l.get_width() <= 8*sizeof(unsigned long));
assert(r.get_width() <= 8*sizeof(unsigned long));
unsigned long lv = 0, rv = 0;
unsigned long vv;
for (unsigned idx = 0 ; idx < l.get_width() ; idx += 1) {
if (B_ISXZ(l[idx]))
goto unknown_result;
if (B_IS1(l[idx]))
lv |= 1 << idx;
}
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_ISXZ(r[idx]))
goto unknown_result;
if (B_IS1(r[idx]))
rv |= 1 << idx;
}
if (rv == 0)
goto unknown_result;
vv = lv / rv;
for (unsigned idx = 0 ; idx < v.get_width() ; idx += 1) {
if (vv & 1)
v[idx] = St1;
else
v[idx] = St0;
vv >>= 1;
}
return;
unknown_result:
for (unsigned idx= 0 ; idx < v.get_width() ; idx += 1)
v[idx] = StX;
}
vvm_idiv::vvm_idiv(unsigned rwid, unsigned awid, unsigned bwid)
: rwid_(rwid), awid_(awid), bwid_(bwid)
{
bits_ = new vpip_bit_t[rwid_+awid_+bwid_];
for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_ ; idx += 1)
bits_[idx] = StX;
out_ = new vvm_nexus::drive_t[rwid];
}
vvm_idiv::~vvm_idiv()
{
delete[]out_;
delete[]bits_;
}
void vvm_idiv::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < awid_);
bits_[rwid_+idx] = val;
}
void vvm_idiv::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < bwid_);
bits_[rwid_+awid_+idx] = val;
}
vvm_nexus::drive_t* vvm_idiv::config_rout(unsigned idx)
{
assert(idx < rwid_);
return out_+idx;
}
unsigned vvm_idiv::key_DataA(unsigned idx) const
{
assert(idx < awid_);
return rwid_+idx;
}
unsigned vvm_idiv::key_DataB(unsigned idx) const
{
assert(idx < bwid_);
return rwid_+awid_+idx;
}
void vvm_idiv::take_value(unsigned key, vpip_bit_t val)
{
if (B_EQ(bits_[key], val)) {
bits_[key] = val;
return;
}
bits_[key] = val;
vvm_bitset_t r (bits_, rwid_);
vvm_bitset_t a (bits_+rwid_, awid_);
vvm_bitset_t b (bits_+rwid_+awid_, bwid_);
vvm_binop_idiv(r, a, b);
for (unsigned idx = 0 ; idx < rwid_ ; idx += 1)
out_[idx].set_value(bits_[idx]);
}
/*
* $Log: vvm_idiv.cc,v $
* Revision 1.3 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.1 2000/04/01 21:40:23 steve
* Add support for integer division.
*
*/
-165
View File
@@ -1,165 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@picturel.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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_imod.cc,v 1.5 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_func.h"
# include "vvm_gates.h"
# include <assert.h>
void vvm_binop_imod(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.get_width() <= 8*sizeof(unsigned long));
assert(l.get_width() <= 8*sizeof(unsigned long));
assert(r.get_width() <= 8*sizeof(unsigned long));
unsigned long lv = 0, rv = 0;
unsigned long vv;
for (unsigned idx = 0 ; idx < l.get_width() ; idx += 1) {
if (B_ISXZ(l[idx]))
goto unknown_result;
if (B_IS1(l[idx]))
lv |= 1 << idx;
}
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_ISXZ(r[idx]))
goto unknown_result;
if (B_IS1(r[idx]))
rv |= 1 << idx;
}
if (rv == 0)
goto unknown_result;
vv = lv % rv;
for (unsigned idx = 0 ; idx < v.get_width() ; idx += 1) {
if (vv & 1)
v[idx] = St1;
else
v[idx] = St0;
vv >>= 1;
}
return;
unknown_result:
for (unsigned idx= 0 ; idx < v.get_width() ; idx += 1)
v[idx] = StX;
}
vvm_imod::vvm_imod(unsigned rwid, unsigned awid, unsigned bwid)
: rwid_(rwid), awid_(awid), bwid_(bwid)
{
bits_ = new vpip_bit_t[rwid_+awid_+bwid_];
for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_ ; idx += 1)
bits_[idx] = StX;
out_ = new vvm_nexus::drive_t[rwid];
}
vvm_imod::~vvm_imod()
{
delete[]out_;
delete[]bits_;
}
void vvm_imod::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < awid_);
bits_[rwid_+idx] = val;
}
void vvm_imod::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < bwid_);
bits_[rwid_+awid_+idx] = val;
}
vvm_nexus::drive_t* vvm_imod::config_rout(unsigned idx)
{
assert(idx < rwid_);
return out_+idx;
}
unsigned vvm_imod::key_DataA(unsigned idx) const
{
assert(idx < awid_);
return rwid_+idx;
}
unsigned vvm_imod::key_DataB(unsigned idx) const
{
assert(idx < bwid_);
return rwid_+awid_+idx;
}
void vvm_imod::take_value(unsigned key, vpip_bit_t val)
{
if (B_EQ(bits_[key], val)) {
bits_[key] = val;
return;
}
bits_[key] = val;
vvm_bitset_t r (bits_, rwid_);
vvm_bitset_t a (bits_+rwid_, awid_);
vvm_bitset_t b (bits_+rwid_+awid_, bwid_);
vvm_binop_imod(r, a, b);
for (unsigned idx = 0 ; idx < rwid_ ; idx += 1)
out_[idx].set_value(bits_[idx]);
}
/*
* $Log: vvm_imod.cc,v $
* Revision 1.5 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.3 2000/09/17 21:26:16 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.2 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.1 2000/05/19 04:22:56 steve
* Add the integer modulus function.
*
*/
-122
View File
@@ -1,122 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_memory.cc,v 1.4 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_signal.h"
vvm_memory_t::vvm_memory_t()
{
cb_list_ = 0;
}
void vvm_memory_t::set_word(unsigned addr, const vvm_bitset_t&val)
{
if (addr >= size)
return;
unsigned base = width * addr;
for (unsigned idx = 0 ; idx < width ; idx += 1)
bits[base+idx] = val[idx];
call_list_(addr);
}
void vvm_memory_t::set_word(unsigned addr, const vpip_bit_t*val)
{
if (addr >= size)
return;
unsigned base = width * addr;
for (unsigned idx = 0 ; idx < width ; idx += 1)
bits[base+idx] = val[idx];
call_list_(addr);
}
void vvm_memory_t::get_word(unsigned addr, vvm_bitset_t&val) const
{
if (addr >= size) {
for (unsigned idx = 0 ; idx < width ; idx += 1)
val[idx] = StX;
return;
}
unsigned base = width * addr;
for (unsigned idx = 0 ; idx < width ; idx += 1)
val[idx] = bits[base+idx];
}
void vvm_memory_t::set_callback(vvm_ram_callback*ram)
{
ram->next_ = cb_list_;
cb_list_ = ram;
}
void vvm_memory_t::call_list_(unsigned idx)
{
for (vvm_ram_callback*cur = cb_list_; cur; cur = cur->next_)
cur->handle_write(idx);
}
vvm_memory_t::assign_nb::assign_nb(vvm_memory_t&m, unsigned i,
const vvm_bitset_t&v)
: mem_(m), index_(i), bits_(new vpip_bit_t[m.width]), val_(bits_, m.width)
{
unsigned top = m.width;
if (top > v.nbits)
top = v.nbits;
for (unsigned idx = 0 ; idx < top ; idx += 1)
val_[idx] = v[idx];
for (unsigned idx = top ; idx < m.width ; idx += 1)
val_[idx] = St0;
}
vvm_memory_t::assign_nb::~assign_nb()
{
delete[]bits_;
}
void vvm_memory_t::assign_nb::event_function()
{
mem_.set_word(index_, val_);
}
/*
* $Log: vvm_memory.cc,v $
* Revision 1.4 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/12/15 21:54:43 steve
* Allow non-blocking assign to pad memory word with zeros.
*
* Revision 1.1 2000/12/15 20:05:16 steve
* Fix memory access in vvm. (PR#70)
*
*/
-219
View File
@@ -1,219 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_mult.cc,v 1.8 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
static void add_into_result(vpip_bit_t *r, unsigned nr,
const vpip_bit_t *a, unsigned na) {
unsigned idx;
vpip_bit_t carry_bit = St0;
for (idx = 0; idx < nr && idx < na; idx++) {
vpip_bit_t val;
val = B_XOR(B_XOR(a[idx], r[idx]), carry_bit);
carry_bit = B_OR(B_OR(B_AND(a[idx], r[idx]),
B_AND(a[idx], carry_bit)),
B_AND(r[idx], carry_bit));
r[idx] = val;
}
}
static void vvm_binop_mult_generic(vpip_bit_t*r, unsigned nr,
const vpip_bit_t*a, unsigned na,
const vpip_bit_t*b, unsigned nb) {
unsigned idx;
for (idx = 0 ; idx < na ; idx += 1)
if (B_ISXZ(a[idx]))
goto unknown_result;
for (idx = 0 ; idx < nb ; idx += 1)
if (B_ISXZ(b[idx]))
goto unknown_result;
// Start off initialized to 0...
for (idx = 0 ; idx < nr ; idx += 1)
r[idx] = St0;
for (idx = 0; idx < nb && idx < nr; idx++)
if (B_IS1(b[idx]))
add_into_result(r+idx, nr-idx, a, na);
return;
unknown_result:
for (unsigned idx= 0 ; idx < nr ; idx += 1)
r[idx] = StX;
}
void vvm_binop_mult(vpip_bit_t*r, unsigned nr,
const vpip_bit_t*a, unsigned na,
const vpip_bit_t*b, unsigned nb)
{
if (nr > 8*sizeof(unsigned long) ||
na > 8*sizeof(unsigned long) ||
nb > 8*sizeof(unsigned long)) {
// If we can't use the fast routine, default to
// the slow one...
vvm_binop_mult_generic(r, nr, a, na, b, nb);
return;
}
assert(nr <= 8*sizeof(unsigned long));
assert(na <= 8*sizeof(unsigned long));
assert(nb <= 8*sizeof(unsigned long));
unsigned long av = 0, bv = 0;
unsigned long rv;
for (unsigned idx = 0 ; idx < na ; idx += 1) {
if (B_ISXZ(a[idx]))
goto unknown_result;
if (B_IS1(a[idx]))
av |= 1 << idx;
}
for (unsigned idx = 0 ; idx < nb ; idx += 1) {
if (B_ISXZ(b[idx]))
goto unknown_result;
if (B_IS1(b[idx]))
bv |= 1 << idx;
}
rv = av * bv;
for (unsigned idx = 0 ; idx < nr ; idx += 1) {
if (rv & 1)
r[idx] = St1;
else
r[idx] = St0;
rv >>= 1;
}
return;
unknown_result:
for (unsigned idx= 0 ; idx < nr ; idx += 1)
r[idx] = StX;
}
vvm_mult::vvm_mult(unsigned rwid, unsigned awid,
unsigned bwid, unsigned swid)
: rwid_(rwid), awid_(awid), bwid_(bwid), swid_(swid)
{
bits_ = new vpip_bit_t[rwid_+awid_+bwid_+swid_];
out_ = new vvm_nexus::drive_t[rwid_];
for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_+swid_ ; idx += 1)
bits_[idx] = StX;
}
vvm_mult::~vvm_mult()
{
delete[]bits_;
delete[]out_;
}
vvm_nexus::drive_t* vvm_mult::config_rout(unsigned idx)
{
assert(idx < rwid_);
return out_+idx;
}
unsigned vvm_mult::key_DataA(unsigned idx) const
{
assert(idx < awid_);
return rwid_ + idx;
}
void vvm_mult::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < awid_);
bits_[rwid_+idx] = val;
}
unsigned vvm_mult::key_DataB(unsigned idx) const
{
assert(idx < bwid_);
return rwid_+awid_+idx;
}
void vvm_mult::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < bwid_);
bits_[rwid_+awid_+idx] = val;
}
void vvm_mult::take_value(unsigned key, vpip_bit_t val)
{
bits_[key] = val;
vvm_binop_mult(bits_, rwid_,
bits_+rwid_, awid_,
bits_+rwid_+awid_, bwid_);
for (unsigned idx = 0 ; idx < rwid_ ; idx += 1)
out_[idx].set_value(bits_[idx]);
}
/*
* $Log: vvm_mult.cc,v $
* Revision 1.8 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.7 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.6 2000/04/21 02:30:40 steve
* Generic multiplier (Chris Lattner)
*
* Revision 1.5 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.4 2000/03/17 03:05:13 steve
* Update vvm_mult to nexus style.
*
* Revision 1.3 2000/03/04 01:13:54 steve
* Simpler implementation of multiplication.
*
* Revision 1.2 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 2000/01/13 03:35:36 steve
* Multiplication all the way to simulation.
*
*/
-171
View File
@@ -1,171 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_mux.cc,v 1.4 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
/*
* The array of bits is arranged as:
*
* oooo ss 0000 1111 2222 3333 ...
*
*/
vvm_mux::vvm_mux(unsigned w, unsigned s, unsigned sw)
: width_(w), size_(s), selwid_(sw)
{
bits_ = new vpip_bit_t[width_*size_+selwid_+width_];
out_ = new vvm_nexus::drive_t[width_];
for (unsigned idx = 0 ; idx < width_*size_+selwid_+width_ ; idx += 1)
bits_[idx] = StX;
}
vvm_mux::~vvm_mux()
{
delete[]out_;
delete[]bits_;
}
vvm_nexus::drive_t* vvm_mux::config_rout(unsigned idx)
{
assert(idx < width_);
return out_+idx;
}
unsigned vvm_mux::key_Sel(unsigned idx) const
{
assert(idx < selwid_);
return idx + width_;
}
unsigned vvm_mux::key_Data(unsigned wi, unsigned si) const
{
assert(si < size_);
assert(wi < width_);
return width_ + selwid_ + si*width_ + wi;
}
void vvm_mux::init_Sel(unsigned idx, vpip_bit_t val)
{
assert(idx < selwid_);
bits_[width_+idx] = val;
}
void vvm_mux::init_Data(unsigned idx, vpip_bit_t val)
{
assert(idx < width_*size_);
bits_[width_+selwid_+idx] = val;
}
void vvm_mux::take_value(unsigned key, vpip_bit_t val)
{
if (bits_[key] == val)
return;
bits_[key] = val;
evaluate_();
}
void vvm_mux::evaluate_()
{
vpip_bit_t*tmp = new vpip_bit_t[width_];
vpip_bit_t*sel = bits_+width_;
vpip_bit_t*inp = bits_+width_+selwid_;
compute_mux(tmp, width_, sel, selwid_, inp, size_);
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
if (tmp[idx] != bits_[idx]) {
bits_[idx] = tmp[idx];
out_[idx].set_value(bits_[idx]);
}
delete[]tmp;
}
void compute_mux(vpip_bit_t*out, unsigned wid,
const vpip_bit_t*sel, unsigned swid,
const vpip_bit_t*dat, unsigned size)
{
unsigned tmp = 0;
for (unsigned idx = 0 ; idx < swid ; idx += 1) {
if (B_ISXZ(sel[idx])) {
tmp = size;
break;
}
if (B_IS1(sel[idx]))
tmp |= (1<<idx);
}
if (tmp >= size) {
if (swid > 1) {
for (unsigned idx = 0; idx < wid ; idx += 1)
out[idx] = StX;
} else {
const unsigned b0 = 0;
const unsigned b1 = wid;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (dat[idx+b0] == dat[idx+b1])
out[idx] = dat[idx+b0];
else
out[idx] = StX;
}
}
} else {
unsigned b = tmp * wid;
for (unsigned idx = 0; idx < wid ; idx += 1)
out[idx] = dat[idx+b];
}
}
/*
* $Log: vvm_mux.cc,v $
* Revision 1.4 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/18 01:27:00 steve
* Generate references into a table of nexus objects instead of
* generating lots of isolated nexus objects. Easier on linkers
* and compilers,
*
* Add missing nexus support for l-value bit selects,
*
* Detemplatize the vvm_mux type.
*
* Fix up the vvm_nexus destructor to disconnect from drivers.
*
*/
-386
View File
@@ -1,386 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_nexus.cc,v 1.13 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_nexus.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_nexus::vvm_nexus()
{
drivers_ = 0;
recvrs_ = 0;
ival_ = 0;
nival_ = 0;
value_ = 0;
force_ = 0;
forcer_ = 0;
forcer_key_ = 0;
assigner_ = 0;
assigner_key_ = 0;
resolution_function = &vvm_resolution_wire;
}
vvm_nexus::~vvm_nexus()
{
while (drivers_) {
drive_t*cur = drivers_;
drivers_ = cur->next_;
assert(cur->nexus_ == this);
cur->nexus_ = 0;
cur->next_ = 0;
}
/* assert(recvrs_ == 0); XXXX I really should make a point to
guarantee that all the receivers that I refer to are gone,
but since I know for now that this destructor is only
called when the simulation exist, nevermind. */
}
/*
* Connect a driver to this nexus. The driver needs to know who I am
* (and can only be connected to one nexus) and also I need to keep a
* list of all the drivers connected to me. Arranging the list
* pointers accordingly. Also, keep track of the number of drivers I
* have connected to me, and maintain the ival_ array so that I do not
* need to manage the array at run time.
*/
void vvm_nexus::connect(vvm_nexus::drive_t*drv)
{
// Link the driver into my list of drivers.
assert(drv->nexus_ == 0);
drv->nexus_ = this;
drv->next_ = drivers_;
drivers_ = drv;
nival_ += 1;
if (ival_) delete[]ival_;
ival_ = new vpip_bit_t[nival_];
}
/*
* Connect this receiver to me. Receivers are handled a little
* differently from drivers, a receiver is fully specified by the
* pointer to the receiver AS WELL AS a magic key value. This allows a
* gate to me a receiver with many different input pins.
*/
void vvm_nexus::connect(vvm_nexus::recvr_t*rcv, unsigned key)
{
recvr_cell*cur = new recvr_cell;
cur->dev = rcv;
cur->key = key;
cur->next = recvrs_;
recvrs_ = cur;
}
void vvm_nexus::disconnect(vvm_nexus::drive_t*drv)
{
drive_t*cur = drivers_;
drivers_ = 0;
while (cur) {
drive_t*tmp = cur;
cur = cur->next_;
if (tmp != drv) {
tmp->next_ = drivers_;
drivers_ = tmp;
}
}
}
/*
* This method disconnects a receiver completely by removing every
* access to it. (Remember that a recvr_t object may be connected many
* times with different keys.)
*/
void vvm_nexus::disconnect(vvm_nexus::recvr_t*rcv)
{
recvr_cell*cur = recvrs_;
recvrs_ = 0;
while (cur) {
recvr_cell*tmp = cur;
cur = tmp->next;
if (tmp->dev == rcv) {
delete tmp;
} else {
tmp->next = recvrs_;
recvrs_ = tmp;
}
}
}
/*
* Reg assign (or procedural assignment) does not use the concept of
* drivers. Instead, I skip the resolution function, save the value
* for myself and pass the value to the receivers.
*/
void vvm_nexus::reg_assign(vpip_bit_t val)
{
assert(drivers_ == 0);
value_ = val;
if (forcer_)
return;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::force_set(vvm_force*f, unsigned k)
{
if (forcer_)
forcer_->release(forcer_key_);
forcer_ = f;
forcer_key_ = k;
}
void vvm_nexus::cassign_set(vvm_force*f, unsigned k)
{
assert(drivers_ == 0);
if (assigner_)
assigner_->release(assigner_key_);
assigner_ = f;
assigner_key_ = k;
}
void vvm_nexus::force_assign(vpip_bit_t val)
{
assert(forcer_);
force_ = val;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, force_);
}
void vvm_nexus::cassign(vpip_bit_t val)
{
assert(assigner_);
value_ = val;
if (forcer_) return;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::release()
{
if (forcer_) {
forcer_->release(forcer_key_);
forcer_ = 0;
}
/* Now deliver that output value to all the receivers
connected to this nexus. */
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::deassign()
{
assert(drivers_ == 0);
if (assigner_) {
assigner_->release(assigner_key_);
assigner_ = 0;
}
}
/*
* This method is invoked when something interesting happens at one of
* the drivers. It collects all the driver values, resolves them into
* a signal value, and passed them to all the connected
* receivers. This is the workhorse of the nexus object.
*/
void vvm_nexus::run_values()
{
/* Collect the values from all the signal drivers. We should
have exactly the right size ival_ array for the number of
drives. */
unsigned idx = 0;
for (drive_t*cur = drivers_; cur ; cur = cur->next_) {
assert(idx < nival_);
ival_[idx++] = cur->peek_value();
}
assert(idx == nival_);
/* Use the resolution function to generate the settled value
for this nexus. */
vpip_bit_t val = resolution_function(ival_, nival_);
if (value_ == val) return;
value_ = val;
if (forcer_)
return;
/* Now deliver that output value to all the receivers
connected to this nexus. */
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
vvm_nexus::drive_t::drive_t()
{
value_ = StX;
nexus_ = 0;
}
vvm_nexus::drive_t::~drive_t()
{
if (nexus_) nexus_->disconnect(this);
}
vpip_bit_t vvm_nexus::drive_t::peek_value() const
{
return value_;
}
void vvm_nexus::drive_t::set_value(vpip_bit_t val)
{
if (val == value_) return;
value_ = val;
if (nexus_) nexus_->run_values();
}
vvm_nexus::recvr_t::recvr_t()
{
}
vvm_nexus::recvr_t::~recvr_t()
{
}
vpip_bit_t vvm_resolution_wire(const vpip_bit_t*bits, unsigned nbits)
{
if (nbits == 0) return HiZ;
return vpip_bits_resolve(bits, nbits);
}
vpip_bit_t vvm_resolution_sup0(const vpip_bit_t*, unsigned)
{
return Su0;
}
vpip_bit_t vvm_resolution_sup1(const vpip_bit_t*, unsigned)
{
return Su1;
}
vpip_bit_t vvm_resolution_tri0(const vpip_bit_t*bits, unsigned nbits)
{
if (nbits == 0) return Pu0;
vpip_bit_t res = vpip_bits_resolve(bits, nbits);
if (B_ISZ(res)) return Pu0;
return res;
}
vpip_bit_t vvm_resolution_tri1(const vpip_bit_t*bits, unsigned nbits)
{
if (nbits == 0) return Pu1;
vpip_bit_t res = vpip_bits_resolve(bits, nbits);
if (B_ISZ(res)) return Pu1;
return res;
}
class delayed_assign_event : public vvm_event {
public:
delayed_assign_event(vvm_nexus&l, vpip_bit_t r)
: l_val_(l), r_val_(r) { }
void event_function() { l_val_.reg_assign(r_val_); }
private:
vvm_nexus& l_val_;
vpip_bit_t r_val_;
};
void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
unsigned long delay)
{
delayed_assign_event*ev = new delayed_assign_event(l_val, r_val);
ev->schedule(delay);
}
/*
* $Log: vvm_nexus.cc,v $
* Revision 1.13 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.12 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.11 2000/11/20 00:58:40 steve
* Add support for supply nets (PR#17)
*
* Revision 1.10 2000/10/23 00:32:48 steve
* Nexus value is initially unknown so that it propogates for sure.
*
* Revision 1.9 2000/08/02 00:57:03 steve
* tri01 support in vvm.
*
* Revision 1.8 2000/05/11 23:37:28 steve
* Add support for procedural continuous assignment.
*
* Revision 1.7 2000/04/23 03:45:25 steve
* Add support for the procedural release statement.
*
* Revision 1.6 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.5 2000/03/22 05:16:38 steve
* Integrate drive resolution function.
*
* Revision 1.4 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.3 2000/03/18 01:27:00 steve
* Generate references into a table of nexus objects instead of
* generating lots of isolated nexus objects. Easier on linkers
* and compilers,
*
* Add missing nexus support for l-value bit selects,
*
* Detemplatize the vvm_mux type.
*
* Fix up the vvm_nexus destructor to disconnect from drivers.
*
* Revision 1.2 2000/03/16 21:45:07 steve
* Properly initialize driver and nexus values.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/
-194
View File
@@ -1,194 +0,0 @@
#ifndef __vvm_vvm_nexus_H
#define __vvm_vvm_nexus_H
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_nexus.h,v 1.7 2002/08/12 01:35:07 steve Exp $"
#endif
# include "vvm.h"
class vvm_force;
/*
* The nexus class represents a connection point for drivers and
* receivers of signals. The signal carries a single bit, has drivers,
* has fan_out and has a current value. Classes derive from the nexus
* in order to provide specific kinds of N-driver resolution.
*
* The driver_t and recvr_t classes are the means to connect to a
* nexus. In general, other then to connect the drivers and receivers,
* there should be no cause to manipulate the nexus object directly.
*
* The driver_t class represents a driver on the nexus. There can be
* any number of drivers on a nexus, so long as the
* recolution_function can handle the situation. The drivers are
* normally members of some gate object somewhere. When the driver
* receives a value, it saves the value in itself and tells the
* connected nexus that something has changed.
*
* The nexus object, when it notices that one of its drivers changed,
* collects the values of the drivers and passes the set to the
* resolution function. The resolution function calculates what the
* value of the nexus should be given the values driving it.
*
* When the value of the nexus is ready, it scans the list of
* connected receivers and passes the new value out. The receiver is
* actually a pointer to the recvr_t object and a key. This is so the
* receiver object can receive many different pins worth of data. The
* idea is that a gate can be a single recvr_t object, and the key can
* be used and the number of the affected pin.
*/
class vvm_nexus {
public:
class drive_t {
friend class ::vvm_nexus;
public:
drive_t();
~drive_t();
vpip_bit_t peek_value() const;
void set_value(vpip_bit_t);
private:
vpip_bit_t value_;
vvm_nexus*nexus_;
drive_t*next_;
private: // not implemented
drive_t(const drive_t&);
drive_t& operator= (const drive_t&);
};
class recvr_t {
friend class ::vvm_nexus;
public:
recvr_t();
virtual ~recvr_t() =0;
virtual void take_value(unsigned key, vpip_bit_t val) =0;
private: // not implemented
recvr_t(const recvr_t&);
recvr_t& operator= (const recvr_t&);
};
public:
vvm_nexus();
~vvm_nexus();
// These methods support connecting the receiver and driver to
// the nexus.
void connect(drive_t*drv);
void connect(recvr_t*rcv, unsigned key);
void disconnect(drive_t*drv);
void disconnect(recvr_t*rcv);
// If there are no drivers to this nexus, this can be used to
// to procedural assignments to the node, as if it where a reg.
void reg_assign(vpip_bit_t val);
// These methods support the procedural continuous assign. The
// vvm_force oject will set itself as an assigner, then will
// periodically call the cassign method to do the assign. The
// procedural deassign will call the deassign method to detach
// the vvm_force object.
void cassign_set(class vvm_force*frc, unsigned key);
void cassign(vpip_bit_t val);
void deassign();
// This method causes the specified value to be forced onto
// the nexus. This overrides all drivers that are attached.
void force_set(class vvm_force*frc, unsigned key);
void force_assign(vpip_bit_t val);
void release();
// The run_values() method collects all the current driver
// values and, with the aid of the resolution_function,
// generates the current value for the nexus. It also passes
// that value on to the receuvers.
void run_values();
vpip_bit_t (*resolution_function)(const vpip_bit_t*, unsigned);
private:
vpip_bit_t value_;
drive_t*drivers_;
struct recvr_cell {
recvr_t *dev;
unsigned key;
recvr_cell*next;
} *recvrs_;
vpip_bit_t*ival_;
unsigned nival_;
vvm_force *assigner_;
unsigned assigner_key_;
vpip_bit_t force_;
vvm_force *forcer_;
unsigned forcer_key_;
private: // not implemented
vvm_nexus(const vvm_nexus&);
vvm_nexus& operator= (const vvm_nexus&);
};
extern vpip_bit_t vvm_resolution_wire(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_sup0(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_sup1(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_tri0(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_tri1(const vpip_bit_t*bits, unsigned nbits);
/*
* This function arranges for a non-blocking reg_assign to a nexus. It
* creates all the events needed to make it happen after the specified
* delay.
*/
extern void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
unsigned long delay);
/*
* $Log: vvm_nexus.h,v $
* Revision 1.7 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2000/11/20 00:58:41 steve
* Add support for supply nets (PR#17)
*
* Revision 1.5 2000/08/02 00:57:03 steve
* tri01 support in vvm.
*
* Revision 1.4 2000/05/11 23:37:28 steve
* Add support for procedural continuous assignment.
*
* Revision 1.3 2000/04/23 03:45:25 steve
* Add support for the procedural release statement.
*
* Revision 1.2 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/
#endif
-202
View File
@@ -1,202 +0,0 @@
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_pevent.cc,v 1.11 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
# include "vvm_gates.h"
# include "vvm_thread.h"
vvm_sync::vvm_sync()
: hold_(0), tgt_(0), ntgt_(0)
{
}
void vvm_sync::wait(vvm_thread*thr)
{
assert(thr->sync_back_ == 0);
thr->sync_next_ = hold_;
thr->sync_back_ = this;
hold_ = thr;
}
void vvm_sync::wakeup()
{
while (hold_) {
vvm_thread*tmp = hold_;
hold_ = tmp->sync_next_;
assert(tmp->sync_back_ == this);
tmp->sync_back_ = 0;
tmp->thread_yield();
for (unsigned idx = 0 ; idx < ntgt_ ; idx += 1)
tgt_[idx]->wakeup();
}
}
void vvm_sync::chain_sync(vvm_sync*src)
{
if (src->ntgt_ == 0) {
src->tgt_ = new vvm_sync*[1];
src->tgt_[0] = this;
src->ntgt_ = 1;
} else {
vvm_sync**tmp = new vvm_sync*[src->ntgt_+1];
for (unsigned idx = 0 ; idx < src->ntgt_ ; idx += 1)
tmp[idx] = src->tgt_[idx];
tmp[src->ntgt_] = this;
src->ntgt_ += 1;
delete [] src->tgt_;
src->tgt_ = tmp;
}
}
vvm_posedge::vvm_posedge(vvm_sync*tgt)
: sync_(tgt)
{
val_ = StX;
}
vvm_posedge::~vvm_posedge()
{
}
void vvm_posedge::init_P(int, vpip_bit_t val)
{
val_ = val;
}
void vvm_posedge::take_value(unsigned, vpip_bit_t val)
{
if (val == val_)
return;
if (posedge(val_, val))
sync_->wakeup();
val_ = val;
}
vvm_negedge::vvm_negedge(vvm_sync*tgt)
: sync_(tgt)
{
val_ = StX;
}
vvm_negedge::~vvm_negedge()
{
}
void vvm_negedge::init_P(int, vpip_bit_t val)
{
val_ = val;
}
void vvm_negedge::take_value(unsigned, vpip_bit_t val)
{
if (val == val_)
return;
if (negedge(val_, val))
sync_->wakeup();
val_ = val;
}
vvm_anyedge::vvm_anyedge(vvm_sync*tgt, unsigned n)
: nval_(n), sync_(tgt)
{
val_ = new vpip_bit_t[nval_];
for (unsigned idx = 0 ; idx < nval_ ; idx += 1)
val_[idx] = StX;
}
vvm_anyedge::~vvm_anyedge()
{
delete[]val_;
}
void vvm_anyedge::init_P(unsigned key, vpip_bit_t val)
{
assert(key < nval_);
val_[key] = val;
}
void vvm_anyedge::take_value(unsigned key, vpip_bit_t val)
{
assert(key < nval_);
if (val == val_[key])
return;
if (! B_EQ(val, val_[key]))
sync_->wakeup();
val_[key] = val;
}
/*
* $Log: vvm_pevent.cc,v $
* Revision 1.11 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.10 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.9 2000/04/15 02:25:32 steve
* Support chained events.
*
* Revision 1.8 2000/04/12 16:08:46 steve
* Backwards sense of assert test.
*
* Revision 1.7 2000/04/12 01:53:07 steve
* Multiple thread can block on an event.
*
* Revision 1.6 2000/04/10 05:26:07 steve
* All events now use the NetEvent class.
*
* Revision 1.5 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.3 1999/05/01 20:43:55 steve
* Handle wide events, such as @(a) where a has
* many bits in it.
*
* Add to vvm the binary ^ and unary & operators.
*
* Dump events a bit more completely.
*
* Revision 1.2 1999/05/01 02:57:53 steve
* Handle much more complex event expressions.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/
-134
View File
@@ -1,134 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_signal.cc,v 1.9 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_signal.h"
# include <iostream.h>
vvm_bitset_t::vvm_bitset_t(vpip_bit_t*b, unsigned nb)
: bits(b), nbits(nb)
{
}
vvm_bitset_t::~vvm_bitset_t()
{
}
vpip_bit_t&vvm_bitset_t::operator[] (unsigned idx)
{
assert(idx < nbits);
return bits[idx];
}
vpip_bit_t vvm_bitset_t::operator[] (unsigned idx) const
{
assert(idx < nbits);
return bits[idx];
}
vpip_bit_t vvm_bitset_t::get_bit(unsigned idx) const
{
assert(idx < nbits);
return bits[idx];
}
unsigned vvm_bitset_t::as_unsigned() const
{
unsigned result = 0;
unsigned width = get_width();
for (unsigned idx = width ; idx > 0 ; idx -= 1) {
result <<= 1;
if (B_IS1(get_bit(idx-1)))
result |= 1;
}
return result;
}
vvm_signal_t::vvm_signal_t()
{
bits = 0;
nbits = 0;
}
vvm_signal_t::~vvm_signal_t()
{
}
void vvm_signal_t::init_P(unsigned idx, vpip_bit_t val)
{
assert(idx < nbits);
bits[idx] = val;
}
void vvm_signal_t::take_value(unsigned key, vpip_bit_t val)
{
assert(key < nbits);
bits[key] = val;
vpip_run_value_changes(this);
}
vvm_ram_callback::vvm_ram_callback()
{
}
vvm_ram_callback::~vvm_ram_callback()
{
}
/*
* $Log: vvm_signal.cc,v $
* Revision 1.9 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.8 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.7 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.6 2000/12/12 03:30:25 steve
* out-line vvm_bitset_t methods.
*
* Revision 1.5 2000/04/26 18:35:12 steve
* Handle assigning small values to big registers.
*
* Revision 1.4 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.3 2000/03/25 05:02:25 steve
* signal bits are referenced at run time by the vpiSignal struct.
*
* Revision 1.2 2000/03/17 20:21:14 steve
* Detemplatize the vvm_signal_t class.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/
-169
View File
@@ -1,169 +0,0 @@
#ifndef __vvm_vvm_signal_H
#define __vvm_vvm_signal_H
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_signal.h,v 1.13 2002/08/12 01:35:07 steve Exp $"
#endif
# include "vvm.h"
# include "vvm_nexus.h"
/*
* The vvm_bitset_t is a reference to an array of vpip_bit_t
* values. The space for the value is actually managed elsewhere, this
* object just references it, and attaches operations to it.
*
* The vvm_bitset_t is useful in behavioral situations, to operate on
* vpip_bit_t data vectors.
*/
class vvm_bitset_t {
public:
explicit vvm_bitset_t(vpip_bit_t*b, unsigned nb);
~vvm_bitset_t();
vpip_bit_t operator[] (unsigned idx) const;
vpip_bit_t&operator[] (unsigned idx);
unsigned get_width() const { return nbits; }
vpip_bit_t get_bit(unsigned idx) const;
unsigned as_unsigned() const;
public:
vpip_bit_t*bits;
unsigned nbits;
private: // not implemented
vvm_bitset_t(const vvm_bitset_t&);
vvm_bitset_t& operator= (const vvm_bitset_t&);
};
/*
* The vvm_signal_t template is the real object that handles the
* receiving of assignments and doing whatever is done. It also
* connects VPI to the C++/vvm design. The actual bits are referenced
* by the base vpiSignal structure.
*/
class vvm_signal_t : public __vpiSignal, public vvm_nexus::recvr_t {
public:
vvm_signal_t();
~vvm_signal_t();
void init_P(unsigned idx, vpip_bit_t val);
void take_value(unsigned key, vpip_bit_t val);
private: // not implemented
vvm_signal_t(const vvm_signal_t&);
vvm_signal_t& operator= (const vvm_signal_t&);
};
struct vvm_ram_callback {
vvm_ram_callback();
virtual ~vvm_ram_callback();
virtual void handle_write(unsigned idx) =0;
vvm_ram_callback*next_;
};
class vvm_memory_t : public __vpiMemory {
public:
vvm_memory_t();
void set_word(unsigned addr, const vvm_bitset_t&val);
void set_word(unsigned addr, const vpip_bit_t*val);
void get_word(unsigned addr, vvm_bitset_t&val) const;
void set_callback(vvm_ram_callback*ram);
class assign_nb : public vvm_event {
public:
assign_nb(vvm_memory_t&m, unsigned i, const vvm_bitset_t&v);
~assign_nb();
void event_function();
private:
vvm_memory_t&mem_;
unsigned index_;
vpip_bit_t*bits_;
vvm_bitset_t val_;
};
private:
vvm_ram_callback*cb_list_;
void call_list_(unsigned idx);
};
/*
* $Log: vvm_signal.h,v $
* Revision 1.13 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.12 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.11 2000/12/15 20:05:16 steve
* Fix memory access in vvm. (PR#70)
*
* Revision 1.10 2000/12/12 03:30:25 steve
* out-line vvm_bitset_t methods.
*
* Revision 1.9 2000/04/26 18:35:12 steve
* Handle assigning small values to big registers.
*
* Revision 1.8 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.7 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*
* Revision 1.6 2000/03/25 05:02:25 steve
* signal bits are referenced at run time by the vpiSignal struct.
*
* Revision 1.5 2000/03/25 02:43:57 steve
* Remove all remain vvm_bitset_t return values,
* and disallow vvm_bitset_t copying.
*
* Revision 1.4 2000/03/24 02:43:37 steve
* vvm_unop and vvm_binop pass result by reference
* instead of returning a value.
*
* Revision 1.3 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.2 2000/03/17 20:21:14 steve
* Detemplatize the vvm_signal_t class.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/
#endif
-96
View File
@@ -1,96 +0,0 @@
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_thread.cc,v 1.9 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
# include "vvm_thread.h"
class delay_event : public vvm_event {
public:
delay_event(vvm_thread*thr) : thr_(thr) { }
void event_function()
{
while (thr_->step_(thr_))
/* empty */;
}
private:
vvm_thread*thr_;
};
vvm_thread::vvm_thread()
{
sync_next_ = 0;
sync_back_ = 0;
callee_ = 0;
back_ = 0;
}
vvm_thread::~vvm_thread()
{
}
void vvm_thread::thread_yield(unsigned long delay)
{
delay_event*ev = new delay_event(this);
ev -> schedule(delay);
}
/*
* $Log: vvm_thread.cc,v $
* Revision 1.9 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.8 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.7 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.6 2000/04/14 23:31:53 steve
* No more class derivation from vvm_thread.
*
* Revision 1.5 2000/04/12 01:53:07 steve
* Multiple thread can block on an event.
*
* Revision 1.4 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.3 2000/01/06 05:56:23 steve
* Cleanup and some asserts.
*
* Revision 1.2 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/
-139
View File
@@ -1,139 +0,0 @@
#ifndef __vvm_thread_H
#define __vvm_thread_H
/*
* Copyright (c) 1998-2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_thread.h,v 1.11 2002/08/12 01:35:07 steve Exp $"
#endif
# include "vvm.h"
/*
* A vvm_thread isn't really a thread in the POSIX sense, but a
* representation of the verilog thread. It is implemented as a state
* machine that performs an action, and possibly changes state, every
* time the go method is called. The events and delays that cause a
* thread to block arrange for the go method to be called in the
* future.
*
* THREAD STEPS
* The basic blocks of an executing thread are implemented as C/C++
* functions that take a vvm_thread pointer and return a boolean. The
* thread keeps a pointer to the function that is the current step. It
* is the responsibility of each step to write into the step_ member
* the pointer to the next step, and that is how things like branching
* and looping work.
*
* A thread executes by calling the current step function. When the
* step function returns, it uses the bolean return code to tell the
* scheduler whether the next step should be executed. Thus, a thread
* can give other threads a chance to execute by returning false.
*
* CALLING CONVENTION
* There are a few members in the vvm_thread for supporting calling
* other threads. This is like a function call in other languages, as
* the calling thread blocks until the called thread(s) terminate. It
* is also like functions in that thread calls nest.
*
* A thread is called by creating a new vvm_thread and saving a
* pointer to the new thread in the callee_ member of the calling
* thread. The called thread gets its back_ pointer set to that of the
* calling thread. The new thread is then activated with a call to its
* thread_yield() method, and the caller thread pauses by returning
* from its step function with the value "false".
*
* When the called thread is ready to terminate, it uses its back_
* pointer to find the calling thread, and activates it with the
* thread_yield() method. Then, the called thread finishes by
* returning false from its step method.
*
* When the caller resumes executing, it knows that the called thread
* is done, so it uses the callee_ pointer to delete the now finished
* thread, and the process is finished.
*/
class vvm_sync;
class vvm_thread {
public:
explicit vvm_thread();
~vvm_thread();
void thread_yield(unsigned long delay =0);
// This method executes a setp of the thread. The engine will
// continue to call go as long as it returns true. The thread
// will return false if it is ready to give up the CPU.
bool (*step_)(vvm_thread*);
// These members are used to handle task invocations.
vvm_thread*callee_;
unsigned ncallee_;
vvm_thread*back_;
// The sync class uses this to list all the threads blocked on it.
vvm_sync*sync_back_;
vvm_thread*sync_next_;
struct __vpiScope*scope;
};
/*
* $Log: vvm_thread.h,v $
* Revision 1.11 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.10 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.9 2000/04/15 19:51:30 steve
* fork-join support in vvm.
*
* Revision 1.8 2000/04/15 01:44:59 steve
* Document the calling convention.
*
* Revision 1.7 2000/04/14 23:31:53 steve
* No more class derivation from vvm_thread.
*
* Revision 1.6 2000/04/12 01:53:07 steve
* Multiple thread can block on an event.
*
* Revision 1.5 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 2000/01/06 05:56:23 steve
* Cleanup and some asserts.
*
* Revision 1.3 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.2 1998/11/10 00:48:31 steve
* Add support it vvm target for level-sensitive
* triggers (i.e. the Verilog wait).
* Fix display of $time is format strings.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/
#endif
-218
View File
@@ -1,218 +0,0 @@
/*
* Copyright (c) 2000 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
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_udp.cc,v 1.6 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
#ifdef UDP_DEBUG
#include <iostream>
#endif
vvm_udp_comb::vvm_udp_comb(unsigned w, const char*t)
: vvm_1bit_out(0), width_(w), table_(t)
{
ibits_ = new char[width_];
obit_ = 'x';
}
vvm_udp_comb::~vvm_udp_comb()
{
delete[]ibits_;
}
void vvm_udp_sequ1::init_I(unsigned idx, vpip_bit_t val)
{
vvm_udp_comb::init_I(idx, val);
}
void vvm_udp_comb::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
if (B_IS1(val))
ibits_[idx] = '1';
else if (B_IS0(val))
ibits_[idx] = '0';
else
ibits_[idx] = 'x';
}
void vvm_udp_sequ1::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_ - 1);
ibits_[0] = obit_;
vvm_udp_comb::take_value(key+1, val);
#ifdef UDP_DEBUG
static int max_deb = UDP_DEBUG;
if (max_deb>0)
if (--max_deb<1000)
cerr<<"sUDP(\""<<table_<<"\", \""<<ibits_<<"\")=\""<<obit_<<"\""<<endl;
#endif
}
void vvm_udp_comb::take_value(unsigned key, vpip_bit_t val)
{
char old_bit = ibits_[key];
init_I(key, val);
if (ibits_[key] == old_bit)
return;
for (const char*row = table_ ; row[0] ; row += width_+1) {
unsigned idx;
for (idx = 0 ; idx < width_ ; idx += 1)
{
char new_bit = ibits_[idx];
if (row[idx] != ibits_[idx]
&& row[idx] != '?'
&& (row[idx] != 'b' || new_bit == 'x')
&& (row[idx] != 'l' || new_bit == '1')
&& (row[idx] != 'h' || new_bit == '0') )
{
if (idx == key)
{
switch (row[idx])
{
case '*':
continue;
case '_':
if (new_bit == '0')
continue;
break;
case '+':
if (new_bit == '1')
continue;
break;
case '%':
if (new_bit == 'x')
continue;
break;
case 'B':
if (old_bit == 'x')
continue;
break;
case 'r':
if (old_bit=='0' && new_bit=='1')
continue;
break;
case 'R':
if (old_bit=='x' && new_bit=='1')
continue;
break;
case 'f':
if (old_bit=='1' && new_bit=='0')
continue;
break;
case 'F':
if (old_bit=='x' && new_bit=='0')
continue;
break;
case 'P':
if (old_bit=='0')
continue;
break;
case 'p':
if (old_bit=='0' || new_bit=='1')
continue;
break;
case 'N':
if (old_bit=='1')
continue;
break;
case 'n':
if (old_bit=='1' || new_bit=='0')
continue;
break;
case 'Q':
if (old_bit=='0' && new_bit=='x')
continue;
break;
case 'M':
if (old_bit=='1' && new_bit=='x')
continue;
break;
}
// bad edge
}
break; // bad edge/level
}
}
if (idx == width_)
{
if (row[width_] == '-'
|| row[width_] == obit_)
return;
obit_ = row[width_];
switch (obit_)
{
case '0':
output(St0);
return;
case '1':
output(St1);
return;
case 'z':
output(HiZ);
return;
default:
output(StX);
return;
}
}
}
if (obit_ != 'x')
{
output(StX);
obit_ = 'x';
}
}
/*
* $Log: vvm_udp.cc,v $
* Revision 1.6 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2001/06/18 00:51:23 steve
* Add more UDP edge types, and finish up compile
* and run-time support. (Stephan Boettcher)
*
* Revision 1.3 2001/04/22 23:09:46 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.2 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.1 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
*/
-47
View File
@@ -1,47 +0,0 @@
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_vpi.cc,v 1.3 2002/08/12 01:35:07 steve Exp $"
#endif
#include <stdarg.h>
#include "vpi_user.h"
#include "vpithunk.h"
vpi_thunk vvmt;
void vvm_vpi_init()
{
vvmt.magic = VPI_THUNK_MAGIC;
vvmt.vpi_register_systf = vpi_register_systf;
vvmt.vpi_vprintf = vpi_vprintf;
vvmt.vpi_mcd_close = vpi_mcd_close;
vvmt.vpi_mcd_name = vpi_mcd_name;
vvmt.vpi_mcd_open = vpi_mcd_open;
vvmt.vpi_mcd_open_x = vpi_mcd_open_x;
vvmt.vpi_mcd_vprintf = vpi_mcd_vprintf;
vvmt.vpi_mcd_fputc = vpi_mcd_fputc;
vvmt.vpi_mcd_fgetc = vpi_mcd_fgetc;
vvmt.vpi_register_cb = vpi_register_cb;
vvmt.vpi_remove_cb = vpi_remove_cb;
vvmt.vpi_sim_vcontrol = vpi_sim_vcontrol;
vvmt.vpi_handle = vpi_handle;
vvmt.vpi_iterate = vpi_iterate;
vvmt.vpi_scan = vpi_scan;
vvmt.vpi_handle_by_index = vpi_handle_by_index;
vvmt.vpi_get_time = vpi_get_time;
vvmt.vpi_get = vpi_get;
vvmt.vpi_get_str = vpi_get_str;
vvmt.vpi_get_value = vpi_get_value;
vvmt.vpi_put_value = vpi_put_value;
vvmt.vpi_free_object= vpi_free_object;
vvmt.vpi_get_vlog_info = vpi_get_vlog_info;
}
/*
* $Log: vvm_vpi.cc,v $
* Revision 1.3 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/08/11 23:47:05 steve
* Add missing Log and Ident strings.
*
*/
+1
View File
@@ -14,4 +14,5 @@ parse.output
parse.h
tables.cc
vvp
vvp.exp
vvp.pdf
+28 -8
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.40 2002/08/12 00:27:10 steve Exp $"
#ident "$Id: Makefile.in,v 1.41 2003/01/10 03:06:32 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,10 +50,10 @@ LIBS = @LIBS@ @EXTRALIBS@
dllib=@DLLIB@
rdynamic=@rdynamic@
all: vvp
all: vvp@EXEEXT@ libvpi.a
clean:
rm -rf vvp *.o *~ parse.cc parse.cc.output parse.h lexor.cc dep
rm -rf vvp@EXEEXT@ *.o *~ parse.cc parse.cc.output parse.h lexor.cc dep
distclean: clean
rm -f config.h Makefile config.cache config.log config.status
@@ -70,9 +70,25 @@ functor.o fvectors.o npmos.o resolv.o symbols.o ufunc.o codes.o vthread.o \
schedule.o statistics.o tables.o udp.o memory.o force.o event.o \
logic.o delay.o $V
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.
# The first step makes an ivl.exe that dlltool can use to make an
# export and import library, and the last link makes a, ivl.exe
# that really exports the things that the import library imports.
vvp@EXEEXT@ libvpi.a: $O vvp.def
$(CXX) -o vvp@EXEEXT@ $O $(dllib) @EXTRALIBS@
dlltool --dllname vvp@EXEEXT@ --def vvp.def \
--output-lib libvpi.a --output-exp vvp.exp
$(CXX) -o vvp@EXEEXT@ vvp.exp $O $(dllib) @EXTRALIBS@
else
libvpi.a: libvpi.c
$(CC) -c $(srcdir)/libvpi.c
rm -f libvpi.a
ar cqv libvpi.a libvpi.o
vvp: $O
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(LIBS) $(dllib)
endif
%.o: %.cc
@[ -d dep ] || mkdir dep
@@ -113,10 +129,13 @@ Makefile: Makefile.in config.status
./config.status
install: all installdirs $(bindir)/vvp $(INSTALL_DOC)
install: all installdirs $(bindir)/vvp@EXEEXT@ $(libdir)/libvpi.a $(INSTALL_DOC)
$(bindir)/vvp: ./vvp
$(INSTALL_PROGRAM) ./vvp $(bindir)/vvp
$(bindir)/vvp@EXEEXT@: ./vvp@EXEEXT@
$(INSTALL_PROGRAM) ./vvp@EXEEXT@ $(bindir)/vvp@EXEEXT@
$(libdir)/libvpi.a : ./libvpi.a
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
$(mandir)/man1/vvp.1: $(srcdir)/vvp.man
$(INSTALL_DATA) $(srcdir)/vvp.man $(mandir)/man1/vvp.1
@@ -129,7 +148,8 @@ installdirs: $(srcdir)/mkinstalldirs
uninstall:
rm -f $(bindir)/vvp
rm -f $(bindir)/vvp@EXEEXT@
rm -f $(libdir)/libvpi.a
rm -f $(mandir)/man1/vvp.1
-include $(patsubst %.o, dep/%.d, $O)
+20 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.146 2002/11/21 22:43:13 steve Exp $"
#ident "$Id: compile.cc,v 1.147 2002/12/21 00:55:58 steve Exp $"
#endif
# include "arith.h"
@@ -418,6 +418,18 @@ bool vpi_handle_resolv_list_s::resolve(bool mes)
void compile_vpi_lookup(vpiHandle *handle, char*label)
{
if (strcmp(label, "$time") == 0) {
*handle = vpip_sim_time(vpip_peek_current_scope());
free(label);
return;
}
if (strcmp(label, "$stime") == 0) {
*handle = vpip_sim_time(vpip_peek_current_scope());
free(label);
return;
}
struct vpi_handle_resolv_list_s*res
= new struct vpi_handle_resolv_list_s;
@@ -576,8 +588,6 @@ void compile_vpi_symbol(const char*label, vpiHandle obj)
void compile_init(void)
{
sym_vpi = new_symbol_table();
compile_vpi_symbol("$time", vpip_sim_time());
compile_vpi_symbol("$stime", vpip_sim_time());
sym_functors = new_symbol_table();
functor_init();
@@ -1483,6 +1493,13 @@ void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
/*
* $Log: compile.cc,v $
* Revision 1.147 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.146 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
+9 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.h,v 1.45 2002/08/12 01:35:07 steve Exp $"
#ident "$Id: compile.h,v 1.46 2002/12/21 00:55:58 steve Exp $"
#endif
# include <stdio.h>
@@ -116,6 +116,7 @@ extern void compile_shiftl(char*label, long width,
extern void compile_shiftr(char*label, long width,
unsigned argc, struct symb_s*argv);
extern void compile_timescale(long units);
extern void compile_vpi_symbol(const char*label, vpiHandle obj);
extern void compile_vpi_lookup(vpiHandle *objref, char*label);
@@ -251,6 +252,13 @@ extern void compile_net(char*label, char*name,
/*
* $Log: compile.h,v $
* Revision 1.46 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.45 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
+8 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: event.cc,v 1.10 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: event.cc,v 1.11 2003/01/06 23:57:26 steve Exp $"
#endif
# include "event.h"
@@ -80,7 +80,7 @@ void event_functor_s::set(vvp_ipoint_t ptr, bool, unsigned val, unsigned)
vthread_t tmp = threads;
threads = 0;
vthread_schedule_list(tmp);
if (out) {
functor_set(out, 0, St0, true);
}
@@ -189,6 +189,12 @@ void compile_named_event(char*label, char*name)
/*
* $Log: event.cc,v $
* Revision 1.11 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.10 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+9 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: lexor.lex,v 1.34 2002/06/21 04:58:55 steve Exp $"
#ident "$Id: lexor.lex,v 1.35 2002/12/21 00:55:58 steve Exp $"
#endif
# include "parse_misc.h"
@@ -100,6 +100,7 @@
".shift/l" { return K_SHIFTL; }
".shift/r" { return K_SHIFTR; }
".thread" { return K_THREAD; }
".timescale" { return K_TIMESCALE; }
".ufunc" { return K_UFUNC; }
".var" { return K_VAR; }
".var/s" { return K_VAR_S; }
@@ -173,6 +174,13 @@ int yywrap()
/*
* $Log: lexor.lex,v $
* Revision 1.35 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.34 2002/06/21 04:58:55 steve
* Add support for special integer vectors.
*
+9 -26
View File
@@ -1,7 +1,5 @@
#ifndef __vvm_machine_H
#define __vvm_machine_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003 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
@@ -19,31 +17,16 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: machine.h,v 1.3 2002/08/12 01:35:06 steve Exp $"
#endif
#ifdef NEED_LU
#define LU "_"
#else
#define LU ""
#endif
#ifdef NEED_TU
#define TU "_"
#else
#define TU ""
#ident "$Id: libvpi.c,v 1.1 2003/01/10 03:06:32 steve Exp $"
#endif
/*
* $Log: machine.h,v $
* Revision 1.3 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 2000/01/24 00:18:20 steve
* Handle systems that need underscores in symbols.
* Things that should be statically linked by VPI modules go here.
*/
/*
* $Log: libvpi.c,v $
* Revision 1.1 2003/01/10 03:06:32 steve
* Remove vpithunk, and move libvpi to vvp directory.
*
*/
#endif
+18 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.31 2002/09/18 03:34:07 steve Exp $"
#ident "$Id: main.cc,v 1.32 2003/01/06 23:57:26 steve Exp $"
#endif
# include "config.h"
@@ -273,6 +273,17 @@ int main(int argc, char*argv[])
print_rusage(stderr, cycles+2, cycles+1);
if (logfile && logfile != stderr)
print_rusage(logfile, cycles+2, cycles+1);
fprintf(stderr, "Event counts: (event pool = %lu)\n",
count_event_pool);
fprintf(stderr, " %8lu thread schedule events\n",
count_thread_events);
fprintf(stderr, " %8lu propagation events\n",
count_prop_events);
fprintf(stderr, " %8lu assign events\n",
count_assign_events);
fprintf(stderr, " %8lu other events\n",
count_gen_events);
}
return 0;
@@ -280,6 +291,12 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.32 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.31 2002/09/18 03:34:07 steve
* printf size warning.
*
+15 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: parse.y,v 1.47 2002/06/21 04:58:55 steve Exp $"
#ident "$Id: parse.y,v 1.48 2002/12/21 00:55:58 steve Exp $"
#endif
# include "parse_misc.h"
@@ -60,7 +60,7 @@ extern FILE*yyin;
%token K_ARITH_DIV K_ARITH_MOD K_ARITH_MULT K_ARITH_SUB K_ARITH_SUM
%token K_CMP_GE K_CMP_GT
%token K_EVENT K_EVENT_OR K_FUNCTOR K_NET K_NET_S
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_UFUNC
%token K_RESOLV K_SCOPE K_SHIFTL K_SHIFTR K_THREAD K_TIMESCALE K_UFUNC
%token K_UDP K_UDP_C K_UDP_S
%token K_MEM K_MEM_P K_MEM_I
%token K_FORCE
@@ -295,6 +295,12 @@ statement
| K_SCOPE T_SYMBOL ';'
{ compile_scope_recall($2); }
| K_TIMESCALE T_NUMBER ';'
{ compile_timescale($2); }
| K_TIMESCALE '-' T_NUMBER ';'
{ compile_timescale(-$3); }
/* Thread statements declare a thread with its starting address. The
starting address must already be defined. */
@@ -553,6 +559,13 @@ int compile_design(const char*path)
/*
* $Log: parse.y,v $
* Revision 1.48 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.47 2002/06/21 04:58:55 steve
* Add support for special integer vectors.
*
+55 -27
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: schedule.cc,v 1.20 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: schedule.cc,v 1.21 2003/01/06 23:57:26 steve Exp $"
#endif
# include "schedule.h"
@@ -31,6 +31,13 @@
# include <assert.h>
# include <stdio.h>
unsigned long count_assign_events = 0;
unsigned long count_gen_events = 0;
unsigned long count_prop_events = 0;
unsigned long count_thread_events = 0;
unsigned long count_event_pool = 0;
/*
* The event queue is arranged as a skip list, with the simulation
* time the key to the list. The simulation time is stored in each
@@ -60,6 +67,9 @@ struct event_s {
struct event_s*next;
struct event_s*last;
void* operator new (size_t);
void operator delete(void*obj, size_t s);
};
const unsigned TYPE_GEN = 0;
const unsigned TYPE_THREAD = 1;
@@ -72,27 +82,35 @@ const unsigned TYPE_ASSIGN = 3;
*/
static struct event_s* free_list = 0;
static const unsigned CHUNK_COUNT = 8192 / sizeof(struct event_s);
inline static struct event_s* e_alloc()
inline void* event_s::operator new (size_t size)
{
struct event_s* cur = free_list;
if (!cur)
{
cur = (struct event_s*) malloc(sizeof(struct event_s));
// cur = (struct event_s*) calloc(1, sizeof(struct event_s));
}
else
{
free_list = cur->next;
// memset(cur, 0, sizeof(struct event_s));
}
return cur;
assert(size == sizeof(struct event_s));
struct event_s* cur = free_list;
if (!cur) {
cur = (struct event_s*)
malloc(CHUNK_COUNT * sizeof(struct event_s));
for (unsigned idx = 1 ; idx < CHUNK_COUNT ; idx += 1) {
cur[idx].next = free_list;
free_list = cur + idx;
}
count_event_pool += CHUNK_COUNT;
} else {
free_list = cur->next;
}
return cur;
}
inline static void e_free(struct event_s* cur)
inline void event_s::operator delete(void*obj, size_t size)
{
cur->next = free_list;
free_list = cur;
struct event_s*cur = reinterpret_cast<event_s*>(obj);
cur->next = free_list;
free_list = cur;
}
/*
@@ -246,7 +264,7 @@ static struct event_s* pull_sync_event(void)
void schedule_vthread(vthread_t thr, unsigned delay, bool push_flag)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;
cur->delay = delay;
cur->thr = thr;
@@ -267,7 +285,7 @@ void schedule_vthread(vthread_t thr, unsigned delay, bool push_flag)
void functor_s::schedule(unsigned delay)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;
cur->delay = delay;
cur->funp = this;
@@ -280,7 +298,7 @@ void functor_s::schedule(unsigned delay)
void schedule_assign(vvp_ipoint_t fun, unsigned char val, unsigned delay)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;
cur->delay = delay;
cur->fun = fun;
@@ -292,7 +310,7 @@ void schedule_assign(vvp_ipoint_t fun, unsigned char val, unsigned delay)
void schedule_generic(vvp_gen_event_t obj, unsigned char val, unsigned delay)
{
struct event_s*cur = e_alloc();
struct event_s*cur = new event_s;
cur->delay = delay;
cur->obj = obj;
@@ -339,7 +357,7 @@ void schedule_simulate(void)
assert(sync_cur->obj->sync_flag);
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
}
e_free(sync_cur);
delete sync_cur;
}
@@ -349,17 +367,20 @@ void schedule_simulate(void)
switch (cur->type) {
case TYPE_THREAD:
count_thread_events += 1;
vthread_run(cur->thr);
e_free(cur);
delete cur;
break;
case TYPE_PROP:
//printf("Propagate %p\n", cur->fun);
count_prop_events += 1;
cur->funp->propagate(false);
e_free(cur);
delete(cur);
break;
case TYPE_ASSIGN:
count_assign_events += 1;
switch (cur->val) {
case 0:
functor_set(cur->fun, cur->val, St0, false);
@@ -374,14 +395,15 @@ void schedule_simulate(void)
functor_set(cur->fun, cur->val, HiZ, false);
break;
}
e_free(cur);
delete(cur);
break;
case TYPE_GEN:
count_gen_events += 1;
if (cur->obj && cur->obj->run) {
if (cur->obj->sync_flag == false) {
cur->obj->run(cur->obj, cur->val);
e_free(cur);
delete (cur);
} else {
postpone_sync_event(cur);
@@ -405,7 +427,7 @@ void schedule_simulate(void)
sync_cur->obj->run(sync_cur->obj, sync_cur->val);
}
e_free(sync_cur);
delete (sync_cur);
}
@@ -415,6 +437,12 @@ void schedule_simulate(void)
/*
* $Log: schedule.cc,v $
* Revision 1.21 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.20 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+15 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: schedule.h,v 1.11 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: schedule.h,v 1.12 2003/01/06 23:57:26 steve Exp $"
#endif
# include "vthread.h"
@@ -90,9 +90,23 @@ extern vvp_time64_t schedule_simtime(void);
extern void schedule_finish(int rc);
extern bool schedule_finished(void);
/*
* These are event counters for the sake of performance measurements.
*/
extern unsigned long count_assign_events;
extern unsigned long count_gen_events;
extern unsigned long count_prop_events;
extern unsigned long count_thread_events;
extern unsigned long count_event_pool;
/*
* $Log: schedule.h,v $
* Revision 1.12 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.11 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+6 -1
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams ([email protected])
*
* $Id: vpi.txt,v 1.5 2001/03/20 06:16:24 steve Exp $
* $Id: vpi.txt,v 1.6 2002/12/21 00:55:58 steve Exp $
*/
@@ -103,6 +103,7 @@ placed.
A scope is created with a .scope directive, like so:
<label> .scope "name" [, <parent>];
.timescale <units>;
The scope takes a string name as the first parameter. If there is an
additional parameter, it is a label of the directive for the parent
@@ -114,6 +115,10 @@ scope. The vvp automatically constructs full names from the scope
hierarchy, and runtime VPI code can access that full name with the
vpiFullname reference.
The .timescale directive changes the scope units from the simulation
precision to the specified precision. The .timescale directive affects
the current scope.
Objects that place themselves in a scope place themselves in the
current scope. The current scope is the one that was last mentioned by
a .scope directive. If the wrong scope is current, the label on a
+5 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2003 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
@@ -17,20 +17,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_modules.cc,v 1.12 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_modules.cc,v 1.13 2003/01/10 03:06:32 steve Exp $"
#endif
# include "config.h"
# include "vpi_priv.h"
# include "ivl_dlfcn.h"
# include "vpithunk.h"
# include <stdio.h>
# include <string.h>
# include <sys/types.h>
# include <sys/stat.h>
typedef void (*vlog_startup_routines_t)(void);
typedef int (*vpi_register_sim_t)(p_vpi_thunk tp);
const char* vpip_module_path[64] = {
@@ -107,22 +105,6 @@ void vpip_load_module(const char*name)
}
void *regsub = ivl_dlsym(dll, LU "vpi_register_sim" TU);
vpi_register_sim_t simreg = (vpi_register_sim_t)regsub;
if (regsub == 0) {
fprintf(stderr, "%s: Unable to locate vpi_register_sim", name);
ivl_dlclose(dll);
return;
}
extern vpi_thunk vvpt;
if (((simreg)(&vvpt)) == 0) {
fprintf(stderr, "%s: vpi_register_sim returned zero", name);
ivl_dlclose(dll);
return;
}
void*table = ivl_dlsym(dll, LU "vlog_startup_routines" TU);
if (table == 0) {
fprintf(stderr, "%s: no vlog_startup_routines\n", name);
@@ -139,6 +121,9 @@ void vpip_load_module(const char*name)
/*
* $Log: vpi_modules.cc,v $
* Revision 1.13 2003/01/10 03:06:32 steve
* Remove vpithunk, and move libvpi to vvp directory.
*
* Revision 1.12 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
@@ -162,23 +147,5 @@ void vpip_load_module(const char*name)
*
* Revision 1.6 2001/07/26 03:13:51 steve
* Make the -M flag add module search paths.
*
* 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.
*
* Revision 1.4 2001/05/22 02:14:47 steve
* Update the mingw build to not require cygwin files.
*
* Revision 1.3 2001/03/23 02:40:22 steve
* Add the :module header statement.
*
* Revision 1.2 2001/03/22 05:39:34 steve
* Test print that interferes with output.
*
* 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.
*
*/
+50 -55
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.cc,v 1.24 2002/08/24 05:02:58 steve Exp $"
#ident "$Id: vpi_priv.cc,v 1.28 2003/01/10 19:02:21 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -133,6 +133,12 @@ int vpi_get(int property, vpiHandle ref)
char* vpi_get_str(int property, vpiHandle ref)
{
if (ref == 0) {
fprintf(stderr, "vpi error: vpi_get_str(%d, ...) called "
"with null vpiHandle.\n", property);
return 0;
}
assert(ref);
if (ref->vpi_type->vpi_get_str_ == 0)
return 0;
@@ -144,8 +150,8 @@ void vpi_get_time(vpiHandle obj, s_vpi_time*vp)
{
assert(vp);
// XXXX Cheat. Ignore timescale for the scope.
vp->type = vpiSimTime;
// Only vpiSimTime is supported, for now.
assert(vp->type == vpiSimTime);
vp->high = 0;
vp->low = schedule_simtime();
}
@@ -348,6 +354,14 @@ extern "C" void vpi_vprintf(const char*fmt, va_list ap)
vprintf(fmt, ap);
}
extern "C" void vpi_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vpi_vprintf(fmt, ap);
va_end(ap);
}
extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
{
@@ -361,8 +375,41 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
}
}
extern "C" void vpi_sim_control(int operation, ...)
{
va_list ap;
va_start(ap, operation);
vpi_sim_vcontrol(operation, ap);
va_end(ap);
}
extern "C" void vpi_control(int operation, ...)
{
va_list ap;
va_start(ap, operation);
vpi_sim_vcontrol(operation, ap);
va_end(ap);
}
/*
* $Log: vpi_priv.cc,v $
* Revision 1.28 2003/01/10 19:02:21 steve
* Add missing vpi entry points.
*
* Revision 1.27 2003/01/10 03:06:32 steve
* Remove vpithunk, and move libvpi to vvp directory.
*
* Revision 1.26 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.25 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.24 2002/08/24 05:02:58 steve
* Fix = vs == error.
*
@@ -374,56 +421,4 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
*
* Revision 1.21 2002/07/19 01:12:50 steve
* vpi_iterate returns 0 on error.
*
* Revision 1.20 2002/07/17 05:13:43 steve
* Implementation of vpi_handle_by_name, and
* add the vpiVariables iterator.
*
* Revision 1.19 2002/07/12 02:04:44 steve
* vpi_iterate return null if there is nothing to iterate.
*
* Revision 1.18 2002/07/05 17:14:15 steve
* Names of vpi objects allocated as vpip_strings.
*
* Revision 1.17 2002/06/21 04:58:55 steve
* Add support for special integer vectors.
*
* Revision 1.16 2002/06/02 19:05:50 steve
* Check for null pointers from users.
*
* Revision 1.15 2002/05/18 02:34:11 steve
* Add vpi support for named events.
*
* Add vpi_mode_flag to track the mode of the
* vpi engine. This is for error checking.
*
* Revision 1.14 2002/05/03 15:44:11 steve
* Add vpiModule iterator to vpiScope objects.
*
* Revision 1.13 2002/04/07 00:46:21 steve
* minor cleanup of formatting.
*
* Revision 1.12 2002/01/09 03:15:23 steve
* Add vpi_get_vlog_info support.
*
* Revision 1.11 2002/01/06 00:48:39 steve
* VPI access to root module scopes.
*
* Revision 1.10 2001/10/31 04:27:47 steve
* Rewrite the functor type to have fewer functor modes,
* and use objects to manage the different types.
* (Stephan Boettcher)
*
* Revision 1.9 2001/09/15 18:27:05 steve
* Make configure detect malloc.h
*
* Revision 1.8 2001/07/11 02:27:21 steve
* Add support for REadOnlySync and monitors.
*
* Revision 1.7 2001/06/30 23:03:17 steve
* support fast programming by only writing the bits
* that are listed in the input file.
*
* Revision 1.6 2001/06/21 22:54:12 steve
* Support cbValueChange callbacks.
*/
+26 -5
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.h,v 1.40 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_priv.h,v 1.42 2003/01/09 04:09:44 steve Exp $"
#endif
# include "vpi_user.h"
@@ -128,19 +128,29 @@ struct __vpiCallback {
extern struct __vpiCallback* new_vpi_callback();
extern void callback_execute(struct __vpiCallback*cur);
struct __vpiSystemTime {
struct __vpiHandle base;
struct __vpiScope *scope;
};
/*
* Scopes are created by .scope statements in the source.
* Scopes are created by .scope statements in the source. These
* objects hold the items and properties that are knowably bound to a
* scope.
*/
struct __vpiScope {
struct __vpiHandle base;
struct __vpiScope *scope;
/* The scope has a name. */
const char*name;
/* Keep an array of internal scope items. */
/* The scope has a system time of its own. */
struct __vpiSystemTime scoped_time;
/* Keep an array of internal scope items. */
struct __vpiHandle**intern;
unsigned nintern;
/* Keep a list of threads in the scope. */
vthread_t threads;
signed int time_units :8;
};
extern struct __vpiScope* vpip_peek_current_scope(void);
@@ -230,7 +240,8 @@ struct __vpiSysTaskCall {
struct __vpiUserSystf*defn;
unsigned nargs;
vpiHandle*args;
/* Support for vpi_get_userdata. */
void*userdata;
/* These represent where in the vthread to put the return value. */
unsigned short vbit, vwid;
};
@@ -317,7 +328,7 @@ extern void vpip_execute_vpi_call(vthread_t thr, vpiHandle obj);
* and to finish compilation in preparation for execution.
*/
vpiHandle vpip_sim_time(void);
vpiHandle vpip_sim_time(struct __vpiScope*scope);
extern int vpip_get_time_precision(void);
extern void vpip_set_time_precision(int pres);
@@ -374,6 +385,16 @@ extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type);
/*
* $Log: vpi_priv.h,v $
* Revision 1.42 2003/01/09 04:09:44 steve
* Add vpi_put_userdata
*
* Revision 1.41 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.40 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+55 -7
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_scope.cc,v 1.21 2002/11/15 22:14:12 steve Exp $"
#ident "$Id: vpi_scope.cc,v 1.22 2002/12/21 00:55:58 steve Exp $"
#endif
# include "compile.h"
@@ -43,17 +43,36 @@ vpiHandle vpip_make_root_iterator(void)
vpip_root_table_ptr, false);
}
static bool handle_is_scope(vpiHandle obj)
{
return (obj->vpi_type->type_code == vpiModule)
|| (obj->vpi_type->type_code == vpiFunction)
|| (obj->vpi_type->type_code == vpiTask)
|| (obj->vpi_type->type_code == vpiNamedBegin)
|| (obj->vpi_type->type_code == vpiNamedFork);
}
static int scope_get(int code, vpiHandle obj)
{
struct __vpiScope*ref = (struct __vpiScope*)obj;
assert(handle_is_scope(obj));
switch (code) {
case vpiTimeUnit:
return ref->time_units;
}
return 0;
}
static char* scope_get_str(int code, vpiHandle obj)
{
struct __vpiScope*ref = (struct __vpiScope*)obj;
const char *n, *nn, *name = ref->name;
char *rbuf = need_result_buf(strlen(name) + 1, RBUF_STR);
assert((obj->vpi_type->type_code == vpiModule)
|| (obj->vpi_type->type_code == vpiFunction)
|| (obj->vpi_type->type_code == vpiTask)
|| (obj->vpi_type->type_code == vpiNamedBegin)
|| (obj->vpi_type->type_code == vpiNamedFork));
assert(handle_is_scope(obj));
switch (code) {
case vpiFullName:
@@ -254,7 +273,7 @@ vpiHandle ipoint_get_scope(vvp_ipoint_t ipt)
static const struct __vpirt vpip_scope_module_rt = {
vpiModule,
0,
scope_get,
scope_get_str,
0,
0,
@@ -302,6 +321,11 @@ static const struct __vpirt vpip_scope_fork_rt = {
module_iter
};
/*
* The current_scope is a compile time concept. As the vvp source is
* compiled, items that have scope are placed in the current
* scope. The ".scope" directives select the scope that is current.
*/
static struct __vpiScope*current_scope = 0;
static void attach_to_scope_(struct __vpiScope*scope, vpiHandle obj)
@@ -373,6 +397,10 @@ void compile_scope_decl(char*label, char*type, char*name, char*parent)
struct __vpiScope*sp = (struct __vpiScope*) obj;
attach_to_scope_(sp, &scope->base);
scope->scope = (struct __vpiScope*)obj;
/* Inherit time units from the parent scope. */
scope->time_units = sp->time_units;
} else {
scope->scope = 0x0;
@@ -381,6 +409,9 @@ void compile_scope_decl(char*label, char*type, char*name, char*parent)
realloc(vpip_root_table_ptr, cnt * sizeof(vpiHandle));
vpip_root_table_ptr[vpip_root_table_cnt] = &scope->base;
vpip_root_table_cnt = cnt;
/* Root scopes inherit time_units from system precision. */
scope->time_units = vpip_get_time_precision();
}
functor_set_scope(&current_scope->base);
@@ -393,6 +424,16 @@ void compile_scope_recall(char*symbol)
functor_set_scope(&current_scope->base);
}
/*
* This function handles the ".timescale" directive in the vvp
* source. It sets in the current scope the specified units value.
*/
void compile_timescale(long units)
{
assert(current_scope);
current_scope->time_units = units;
}
struct __vpiScope* vpip_peek_current_scope(void)
{
return current_scope;
@@ -406,6 +447,13 @@ void vpip_attach_to_current_scope(vpiHandle obj)
/*
* $Log: vpi_scope.cc,v $
* Revision 1.22 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.21 2002/11/15 22:14:12 steve
* Add vpiScope iterate on vpiScope objects.
*
+6 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_signal.cc,v 1.50 2002/11/25 23:33:45 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.51 2003/01/07 18:07:50 steve Exp $"
#endif
/*
@@ -57,6 +57,8 @@ extern const char oct_digits[256];
*/
char *need_result_buf(unsigned cnt, vpi_rbuf_t type)
{
cnt = (cnt + 0x0fff) & ~0x0fff;
static char*result_buf[2] = {0, 0};
static size_t result_buf_size[2] = {0, 0};
@@ -761,6 +763,9 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.51 2003/01/07 18:07:50 steve
* Allocate res-buf in bigger chunks
*
* Revision 1.50 2002/11/25 23:33:45 steve
* Support put of vpiStringVal to signals.
*
+33 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_tasks.cc,v 1.16 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_tasks.cc,v 1.18 2003/01/09 04:09:44 steve Exp $"
#endif
/*
@@ -176,7 +176,7 @@ static const struct __vpirt vpip_sysfunc_rt = {
0,
0,
sysfunc_put_value,
0,
systask_handle,
systask_iter
};
@@ -276,6 +276,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, unsigned vwid,
obj->args = argv;
obj->vbit = vbit;
obj->vwid = vwid;
obj->userdata = 0;
/* If there is a compiletf function, call it here. */
if (obj->defn->info.compiletf) {
@@ -342,8 +343,38 @@ void vpi_register_systf(const struct t_vpi_systf_data*ss)
cur->info.tfname = strdup(ss->tfname);
}
int vpi_put_userdata(vpiHandle ref, void*data)
{
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|| (ref->vpi_type->type_code == vpiSysFuncCall));
rfp->userdata = data;
return 0;
}
void* vpi_get_userdata(vpiHandle ref)
{
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|| (ref->vpi_type->type_code == vpiSysFuncCall));
return rfp->userdata;
}
/*
* $Log: vpi_tasks.cc,v $
* Revision 1.18 2003/01/09 04:09:44 steve
* Add vpi_put_userdata
*
* Revision 1.17 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.16 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+41 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2002 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
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_time.cc,v 1.8 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_time.cc,v 1.9 2002/12/21 00:55:58 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -25,7 +25,17 @@
# include <stdio.h>
# include <assert.h>
/*
* The $time system function is supported in VPI contexts (i.e. an
* argument to a system task/function) as a magical time variable. The
* VPI sees it as a vpiTimeVar object, but reads from it get the
* current value instead of some assigned value.
*/
/*
* vpi_time_precision is the precision of the simulation clock. It is
* set by the :vpi_time_precision directive in the vvp source file.
*/
static int vpi_time_precision = 0;
void vpip_time_to_timestruct(struct t_vpi_time*ts, vvp_time64_t ti)
@@ -42,10 +52,6 @@ vvp_time64_t vpip_timestruct_to_time(const struct t_vpi_time*ts)
return ti;
}
static struct __vpiSystemTime {
struct __vpiHandle base;
struct t_vpi_time value;
} time_handle;
static int timevar_get(int code, vpiHandle ref)
{
@@ -66,20 +72,31 @@ static int timevar_get(int code, vpiHandle ref)
static void timevar_get_value(vpiHandle ref, s_vpi_value*vp)
{
static char buf_obj[128];
assert(ref == &time_handle.base);
/* Keep a persistent structure for passing time values back to
the caller. */
static struct t_vpi_time time_value;
struct __vpiSystemTime*rfp = reinterpret_cast<struct __vpiSystemTime*>(ref);
unsigned long x, num_bits;
vvp_time64_t simtime = schedule_simtime();
int units = rfp->scope->time_units;
while (units > vpi_time_precision) {
simtime /= 10;
units -= 1;
}
switch (vp->format) {
case vpiObjTypeVal:
case vpiTimeVal:
vp->value.time = &time_handle.value;
vp->value.time = &time_value;
vp->value.time->type = vpiSimTime;
vpip_time_to_timestruct(vp->value.time, schedule_simtime());
vpip_time_to_timestruct(vp->value.time, simtime);
vp->format = vpiTimeVal;
break;
case vpiBinStrVal:
x = schedule_simtime();
x = simtime;
num_bits = 8 * sizeof(unsigned long);
buf_obj[num_bits] = 0;
@@ -92,17 +109,17 @@ static void timevar_get_value(vpiHandle ref, s_vpi_value*vp)
break;
case vpiDecStrVal:
sprintf(buf_obj, "%lu", schedule_simtime());
sprintf(buf_obj, "%lu", simtime);
vp->value.str = buf_obj;
break;
case vpiOctStrVal:
sprintf(buf_obj, "%lo", schedule_simtime());
sprintf(buf_obj, "%lo", simtime);
vp->value.str = buf_obj;
break;
case vpiHexStrVal:
sprintf(buf_obj, "%lx", schedule_simtime());
sprintf(buf_obj, "%lx", simtime);
vp->value.str = buf_obj;
break;
@@ -123,10 +140,11 @@ static const struct __vpirt vpip_system_time_rt = {
};
vpiHandle vpip_sim_time(void)
vpiHandle vpip_sim_time(struct __vpiScope*scope)
{
time_handle.base.vpi_type = &vpip_system_time_rt;
return &time_handle.base;
scope->scoped_time.base.vpi_type = &vpip_system_time_rt;
scope->scoped_time.scope = scope;
return &scope->scoped_time.base;
}
int vpip_get_time_precision(void)
@@ -142,6 +160,13 @@ void vpip_set_time_precision(int pre)
/*
* $Log: vpi_time.cc,v $
* Revision 1.9 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.8 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+40 -25
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vthread.cc,v 1.95 2002/11/22 00:01:50 steve Exp $"
#ident "$Id: vthread.cc,v 1.96 2003/01/06 23:57:26 steve Exp $"
#endif
# include "vthread.h"
@@ -290,32 +290,43 @@ static void vthread_reap(vthread_t thr)
void vthread_mark_scheduled(vthread_t thr)
{
assert(thr->is_scheduled == 0);
thr->is_scheduled = 1;
while (thr != 0) {
assert(thr->is_scheduled == 0);
thr->is_scheduled = 1;
thr = thr->wait_next;
}
}
/*
* This function runs a thread by fetching an instruction,
* incrementing the PC, and executing the instruction.
* This function runs each thread by fetching an instruction,
* incrementing the PC, and executing the instruction. The thread may
* be the head of a list, so each thread is run so far as possible.
*/
void vthread_run(vthread_t thr)
{
assert(thr->is_scheduled);
thr->is_scheduled = 0;
while (thr != 0) {
vthread_t tmp = thr->wait_next;
thr->wait_next = 0;
for (;;) {
vvp_code_t cp = codespace_index(thr->pc);
thr->pc += 1;
assert(thr->is_scheduled);
thr->is_scheduled = 0;
assert(cp);
assert(cp->opcode);
for (;;) {
vvp_code_t cp = codespace_index(thr->pc);
thr->pc += 1;
/* Run the opcode implementation. If the execution of
the opcode returns false, then the thread is meant to
be paused, so break out of the loop. */
bool rc = (cp->opcode)(thr, cp);
if (rc == false)
return;
assert(cp);
assert(cp->opcode);
/* Run the opcode implementation. If the execution of
the opcode returns false, then the thread is meant to
be paused, so break out of the loop. */
bool rc = (cp->opcode)(thr, cp);
if (rc == false)
break;
}
thr = tmp;
}
}
@@ -326,14 +337,12 @@ void vthread_run(vthread_t thr)
*/
void vthread_schedule_list(vthread_t thr)
{
while (thr) {
vthread_t tmp = thr;
thr = thr->wait_next;
assert(tmp->waiting_for_event);
tmp->waiting_for_event = 0;
tmp->wait_next = 0;
schedule_vthread(tmp, 0);
for (vthread_t cur = thr ; cur ; cur = cur->wait_next) {
assert(cur->waiting_for_event);
cur->waiting_for_event = 0;
}
schedule_vthread(thr, 0);
}
@@ -2496,6 +2505,12 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.96 2003/01/06 23:57:26 steve
* Schedule wait lists of threads as a single event,
* to save on events. Also, improve efficiency of
* event_s allocation. Add some event statistics to
* get an idea where performance is really going.
*
* Revision 1.95 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
+32
View File
@@ -0,0 +1,32 @@
EXPORTS
vpi_chk_error
vpi_control
vpi_free_object
vpi_get
vpi_get_str
vpi_get_time
vpi_get_userdata
vpi_get_value
vpi_get_vlog_info
vpi_handle
vpi_handle_by_index
vpi_handle_by_name
vpi_iterate
vpi_mcd_close
vpi_mcd_fgetc
vpi_mcd_fputc
vpi_mcd_name
vpi_mcd_open
vpi_mcd_open_x
vpi_mcd_printf
vpi_printf
vpi_put_userdata
vpi_put_value
vpi_register_cb
vpi_register_systf
vpi_remove_cb
vpi_scan
vpi_sim_control
vpi_sim_vcontrol
vpi_vprintf
+3 -33
View File
@@ -1,48 +1,18 @@
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_vpi.cc,v 1.5 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vvp_vpi.cc,v 1.8 2003/01/10 19:01:38 steve Exp $"
#endif
#include <stdarg.h>
#include "vpi_user.h"
#include "vpithunk.h"
vpi_thunk vvpt;
void vvp_vpi_init()
{
vvpt.magic = VPI_THUNK_MAGIC;
vvpt.vpi_register_systf = vpi_register_systf;
vvpt.vpi_vprintf = vpi_vprintf;
vvpt.vpi_mcd_close = vpi_mcd_close;
vvpt.vpi_mcd_name = vpi_mcd_name;
vvpt.vpi_mcd_open = vpi_mcd_open;
vvpt.vpi_mcd_open_x = vpi_mcd_open_x;
vvpt.vpi_mcd_vprintf = vpi_mcd_vprintf;
vvpt.vpi_mcd_fputc = vpi_mcd_fputc;
vvpt.vpi_mcd_fgetc = vpi_mcd_fgetc;
vvpt.vpi_register_cb = vpi_register_cb;
vvpt.vpi_remove_cb = vpi_remove_cb;
vvpt.vpi_sim_vcontrol = vpi_sim_vcontrol;
vvpt.vpi_handle = vpi_handle;
vvpt.vpi_iterate = vpi_iterate;
vvpt.vpi_scan = vpi_scan;
vvpt.vpi_handle_by_index = vpi_handle_by_index;
vvpt.vpi_get_time = vpi_get_time;
vvpt.vpi_get = vpi_get;
vvpt.vpi_get_str = vpi_get_str;
vvpt.vpi_get_value = vpi_get_value;
vvpt.vpi_put_value = vpi_put_value;
vvpt.vpi_free_object= vpi_free_object;
vvpt.vpi_get_vlog_info = vpi_get_vlog_info;
vvpt.vpi_chk_error = vpi_chk_error;
}
/*
* $Log: vvp_vpi.cc,v $
* Revision 1.5 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/08/11 23:47:05 steve
* Add missing Log and Ident strings.
* Revision 1.8 2003/01/10 19:01:38 steve
* Remove thunks from vpi init.
*
*/
+4 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: xnfio.cc,v 1.23 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: xnfio.cc,v 1.24 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -27,7 +27,6 @@
# include "functor.h"
# include "netlist.h"
# include "netmisc.h"
# include <strstream>
class xnfio_f : public functor_t {
@@ -363,6 +362,9 @@ void xnfio(Design*des)
/*
* $Log: xnfio.cc,v $
* Revision 1.24 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.23 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*