mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 22:36:54 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38ccb12eb0 | ||
|
|
ca3bf14fb6 | ||
|
|
982474899b | ||
|
|
ad6ff5562d | ||
|
|
d4cd1dbd27 | ||
|
|
3c1426e631 | ||
|
|
c3a1a9514f | ||
|
|
f56d763411 | ||
|
|
4ec91047dd | ||
|
|
0579ae08cd | ||
|
|
9074999666 | ||
|
|
0458ab5a53 | ||
|
|
4a3459c87c | ||
|
|
301cbe31ad | ||
|
|
165dd82bb2 | ||
|
|
9c3b3246c8 | ||
|
|
6416f8b90e | ||
|
|
e6eae5fd15 | ||
|
|
aa3a6dba4e | ||
|
|
dedae73761 | ||
|
|
d7f3d00f5c | ||
|
|
c2070777b2 | ||
|
|
42b34c2ce6 | ||
|
|
6fbfdd8f3f | ||
|
|
bee3acfd12 | ||
|
|
2e279b61dd | ||
|
|
8ab909a765 | ||
|
|
cca07fa42d | ||
|
|
5b81798205 | ||
|
|
a8a82df47d | ||
|
|
e62e1d89b6 | ||
|
|
c032186133 | ||
|
|
b89e138404 | ||
|
|
9f80ed32b6 | ||
|
|
c16a4a3950 | ||
|
|
90fa90a508 | ||
|
|
aaa734690f | ||
|
|
88da7804c4 | ||
|
|
8604f922a5 | ||
|
|
807a758f7c | ||
|
|
ef55086543 | ||
|
|
2001903c89 | ||
|
|
751e4e4c79 | ||
|
|
9d91b5db4c | ||
|
|
9a3c9507ed | ||
|
|
d71d52bfe9 | ||
|
|
8e30bc9f9e | ||
|
|
412518d1ca | ||
|
|
03afbf157b | ||
|
|
00b2d467e4 | ||
|
|
856829d299 | ||
|
|
2fafe6866f | ||
|
|
b9188ad0ca | ||
|
|
0ccb9139c9 | ||
|
|
18e402ddc8 |
+25
-5
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
+8
-22
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.137 2002/11/13 01:50:11 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.141 2003/01/10 03:06:32 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -25,7 +25,7 @@ SHELL = /bin/sh
|
||||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -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
|
||||
@@ -83,7 +83,10 @@ all: dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
SUBDIRS += driver-vpi
|
||||
endif
|
||||
|
||||
else
|
||||
all: iverilog-vpi
|
||||
endif
|
||||
@@ -138,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
|
||||
@@ -222,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
|
||||
@@ -230,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@
|
||||
@@ -291,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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
+3
-1
@@ -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(
|
||||
@@ -190,6 +190,8 @@ if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
|
||||
AC_SUBST(MINGW32)
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
# 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.
|
||||
# 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
|
||||
@@ -18,12 +16,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.3 2002/11/13 17:25:10 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.5 2002/12/08 03:06:30 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -55,6 +53,9 @@ clean:
|
||||
rm -f *.o
|
||||
rm -f iverilog-vpi@EXEEXT@
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
O = main.o res.o
|
||||
|
||||
iverilog-vpi@EXEEXT@: $O
|
||||
|
||||
+3
-5
@@ -3,9 +3,7 @@
|
||||
# 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.
|
||||
# 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
|
||||
@@ -18,12 +16,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.15 2002/08/10 22:36:59 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.16 2002/12/08 03:06:30 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
+42
-2
@@ -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.47 2002/08/12 01:27:48 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>
|
||||
@@ -119,6 +121,35 @@ char tmp[MAXSIZE];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
#ifdef __MINGW32__
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
static FILE*fopen_safe(const char*path)
|
||||
{
|
||||
FILE*file = 0;
|
||||
int fd;
|
||||
|
||||
fd = _open(path, _O_WRONLY|_O_CREAT|_O_EXCL, 0700);
|
||||
if (fd != -1)
|
||||
file = _fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
}
|
||||
#else
|
||||
# include <fcntl.h>
|
||||
static FILE*fopen_safe(const char*path)
|
||||
{
|
||||
FILE*file = 0;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0700);
|
||||
if (fd != -1)
|
||||
file = fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char*my_tempfile(const char*str, FILE**fout)
|
||||
{
|
||||
FILE*file;
|
||||
@@ -148,7 +179,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
|
||||
while ((retry > 0) && (file == NULL)) {
|
||||
unsigned code = rand();
|
||||
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
|
||||
file = fopen(pathbuf, "w");
|
||||
file = fopen_safe(pathbuf);
|
||||
retry -= 1;
|
||||
}
|
||||
|
||||
@@ -657,6 +688,15 @@ 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.
|
||||
*
|
||||
* Revision 1.48 2002/12/04 02:29:36 steve
|
||||
* Use O_EXCL when opening temp files.
|
||||
*
|
||||
* Revision 1.47 2002/08/12 01:27:48 steve
|
||||
* Escape the backslash in the windows file name.
|
||||
*
|
||||
|
||||
+10
-1
@@ -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.
|
||||
*
|
||||
|
||||
+27
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.21 2002/11/02 01:10:49 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.23 2002/11/21 23:27:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -170,16 +170,20 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
verinum*vl = lsb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *lsb_;
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
verinum*vm = msb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
if (vm == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *msb_;
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -298,6 +302,17 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
/* Evaluate the memory index expression down as must as
|
||||
possible. Ideally, we can get it down to a constant. */
|
||||
if (! dynamic_cast<NetEConst*>(ix)) {
|
||||
NetExpr*tmp = ix->eval_tree();
|
||||
if (tmp) {
|
||||
tmp->set_line(*ix);
|
||||
delete ix;
|
||||
ix = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
@@ -314,6 +329,12 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.23 2002/11/21 23:27:51 steve
|
||||
* Precalculate indices to l-value arrays.
|
||||
*
|
||||
* Revision 1.22 2002/11/21 18:15:40 steve
|
||||
* Fix const test of msb in assignment l-values.
|
||||
*
|
||||
* Revision 1.21 2002/11/02 01:10:49 steve
|
||||
* Detect memories without work index in l-value.
|
||||
*
|
||||
|
||||
+13
-10
@@ -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.102 2002/11/09 19:20:48 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? */
|
||||
@@ -1538,18 +1536,17 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
|
||||
|
||||
/* Don't allow registers as assign l-values. */
|
||||
if (sig->type() == NetNet::REG) {
|
||||
cerr << get_line() << ": error: registers (" << sig->name()
|
||||
<< ") cannot be l-values in continuous"
|
||||
cerr << get_line() << ": error: reg " << sig->name()
|
||||
<< "; cannot be an L-value in continuous"
|
||||
<< " assignments." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig->port_type() == NetNet::PINPUT) {
|
||||
cerr << get_line() << ": warning: assign l-value ``"
|
||||
<< sig->name() << "'' is also an input to "
|
||||
<< sig->scope()->name() << "." << endl;
|
||||
cerr << sig->get_line() << ": warning: input ``"
|
||||
<< sig->name() << "'' is coerced to inout." << endl;
|
||||
cerr << get_line() << ": warning: L-value ``"
|
||||
<< sig->name() << "'' is also an input port." << endl;
|
||||
cerr << sig->get_line() << ": warning: input "
|
||||
<< sig->name() << "; is coerced to inout." << endl;
|
||||
sig->port_type(NetNet::PINOUT);
|
||||
}
|
||||
|
||||
@@ -2279,6 +2276,12 @@ 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.
|
||||
*
|
||||
* Revision 1.102 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
|
||||
+21
-7
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.17 2002/11/09 01:40:19 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.18 2002/12/05 02:14:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -145,15 +145,26 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_ || idx_) {
|
||||
cerr << get_line() << ": error: Cannot bit/part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, hname_t(name));
|
||||
assert(res);
|
||||
delete name;
|
||||
|
||||
assert(idx_ == 0);
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (msb_) {
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -217,6 +228,9 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.18 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.17 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
|
||||
+58
-5
@@ -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.264 2002/11/09 19:20:48 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()) {
|
||||
@@ -975,7 +975,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
|
||||
if (! rv->set_width(wid)) {
|
||||
if (wid != rv->expr_width()) {
|
||||
cerr << get_line() << ": error: Unable to match "
|
||||
"expression width of " << rv->expr_width() <<
|
||||
" to l-value width of " << wid << "." << endl;
|
||||
@@ -1076,6 +1076,12 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
assert(rv);
|
||||
|
||||
/* Try to evaluate the expression, at least as far as possible. */
|
||||
if (NetExpr*tmp = rv->eval_tree()) {
|
||||
delete rv;
|
||||
rv = tmp;
|
||||
}
|
||||
|
||||
{ unsigned wid = count_lval_width(lv);
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
@@ -1351,6 +1357,17 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
|
||||
|
||||
/* Attempt to pre-evaluate the parameters. It may be
|
||||
possible to at least partially reduce the
|
||||
expression. */
|
||||
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
|
||||
NetExpr*tmp = eparms[idx]->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete eparms[idx];
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
|
||||
@@ -1589,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
|
||||
@@ -2472,6 +2513,18 @@ 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.
|
||||
*
|
||||
* Revision 1.265 2002/11/26 03:35:13 steve
|
||||
* Do not set width if width is already OK.
|
||||
*
|
||||
* Revision 1.264 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
|
||||
+51
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.43 2002/11/09 01:40:19 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.44 2002/12/05 02:14:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -894,6 +894,53 @@ NetExpr* NetEParam::eval_tree()
|
||||
return res->dup_expr();
|
||||
}
|
||||
|
||||
NetEConst* NetESelect::eval_tree()
|
||||
{
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
|
||||
if (expr == 0) {
|
||||
NetExpr*tmp = expr_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete expr_;
|
||||
expr_ = tmp;
|
||||
}
|
||||
|
||||
expr = dynamic_cast<NetEConst*>(expr_);
|
||||
}
|
||||
|
||||
NetEConst*base = dynamic_cast<NetEConst*>(base_);
|
||||
if (base == 0) {
|
||||
NetExpr*tmp = base_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete base_;
|
||||
base_ = tmp;
|
||||
}
|
||||
|
||||
base = dynamic_cast<NetEConst*>(base_);
|
||||
}
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
verinum eval = expr->value();
|
||||
verinum oval (verinum::V0, expr_width(), true);
|
||||
long bval = base->value().as_long();
|
||||
|
||||
for (long idx = 0 ; idx < expr_width() ; idx += 1) {
|
||||
if ((bval >= eval.len()) || (bval < 0))
|
||||
oval.set(idx, verinum::Vx);
|
||||
else
|
||||
oval.set(idx, eval.get(bval));
|
||||
|
||||
bval += 1;
|
||||
}
|
||||
|
||||
NetEConst*res = new NetEConst(oval);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A ternary expression evaluation is controlled by the condition
|
||||
* expression. If the condition evaluates to true or false, then
|
||||
@@ -1140,6 +1187,9 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.44 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.43 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
|
||||
+31
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.36 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.37 2002/11/17 23:37:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -192,6 +192,33 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
/* sig > 0 is true if any bit in sig is set. This
|
||||
is very much like sig != 0. (0 > sig) shouldn't
|
||||
happen. */
|
||||
if (rcon) {
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
/* 0 < sig is handled like sig > 0. */
|
||||
if (! rcon) {
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -608,6 +635,9 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.37 2002/11/17 23:37:55 steve
|
||||
* Magnitude compare to 0.
|
||||
*
|
||||
* Revision 1.36 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+26
-2
@@ -1,4 +1,4 @@
|
||||
.TH iverilog-vpi 1 "$Date: 2002/07/05 17:17:20 $" Version "$Date: 2002/07/05 17:17:20 $"
|
||||
.TH iverilog-vpi 1 "$Date: 2002/11/23 00:51:53 $" Version "$Date: 2002/11/23 00:51:53 $"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
@@ -32,13 +32,37 @@ VPI modules to further reference external libraries.
|
||||
Normally, the output VPI module will be named after the first source
|
||||
file passed to the command. This flag sets the name (without the .vpi
|
||||
suffix) of the output vpi module.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog-vpi\fP includes two special flags needed to
|
||||
support the more intractable development environment. These flags help
|
||||
the program locate parts that it needs.
|
||||
|
||||
.TP 8
|
||||
.B -mingw=\fIpath\fP
|
||||
Tell the program the root of the Mingw compiler tool suite. The
|
||||
\fBvvp\fP runtime is compiled with this compiler, and this is the
|
||||
compiler that \fIiverilog-vpi\fP expects to use to compile your source
|
||||
code. This is notmally not needed, and if you do use it, it is only
|
||||
needed once. The compiler will save the \fIpath\fP in the registry for
|
||||
use later.
|
||||
|
||||
.TP 8
|
||||
.B -ivl=\fIpath\fP
|
||||
Set for the use during compilation the root if the Icarus Verilog
|
||||
install. This is the place where you installed Icarus Verilog when you
|
||||
ran the installer. This flag is also only needed once, and the path is
|
||||
stored in the registry for future use.
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
.BR "<http://www.icarus.com/eda/verilog/>",
|
||||
.BR "<http://www.mingw.org>",
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.73 2002/06/06 18:57:18 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.74 2002/12/04 02:07:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -375,7 +375,7 @@ W [ \t\b\f\r]+
|
||||
if (isgraph(yytext[0]))
|
||||
cerr << yytext[0];
|
||||
else
|
||||
cerr << (unsigned)yytext[0];
|
||||
cerr << "hex " << hex << (0xffU & ((unsigned) (yytext[0])));
|
||||
|
||||
cerr << ")" << endl; }
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
+22
-12
@@ -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.29 2002/11/02 03:27:52 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)
|
||||
@@ -501,24 +502,27 @@ NetScope* Design::find_task(const hname_t&key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEvent* Design::find_event(NetScope*scope, const hname_t&path)
|
||||
NetEvent* Design::find_event(NetScope*scope, const hname_t&p)
|
||||
{
|
||||
hname_t path = p;
|
||||
assert(scope);
|
||||
|
||||
char*key = path.remove_tail_name();
|
||||
if (path.peek_name(0))
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
while (scope) {
|
||||
if (NetEvent*ev = scope->find_event(path)) {
|
||||
if (NetEvent*ev = scope->find_event(key)) {
|
||||
delete key;
|
||||
return ev;
|
||||
}
|
||||
|
||||
// If this is a simple name, then do not scan up scopes
|
||||
// past a module scope. This is a Verilog scoping rule.
|
||||
if ((path.component_count() == 1)
|
||||
&& (scope->type() == NetScope::MODULE))
|
||||
if (scope->type() == NetScope::MODULE)
|
||||
break;
|
||||
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -597,6 +601,12 @@ 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.
|
||||
*
|
||||
* Revision 1.29 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
|
||||
+9
-6
@@ -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.
|
||||
*
|
||||
|
||||
+12
-6
@@ -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.20 2002/10/19 22:59:49 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
|
||||
@@ -255,10 +255,10 @@ void NetScope::rem_event(NetEvent*ev)
|
||||
}
|
||||
|
||||
|
||||
NetEvent* NetScope::find_event(const hname_t&name)
|
||||
NetEvent* NetScope::find_event(const char*name)
|
||||
{
|
||||
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->name(), name.peek_tail_name()) == 0)
|
||||
if (strcmp(cur->name(), name) == 0)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
@@ -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,12 @@ 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.
|
||||
*
|
||||
* Revision 1.20 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.269 2002/11/09 01:40:19 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.271 2002/12/07 02:49:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2494,6 +2494,7 @@ class NetESelect : public NetExpr {
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetESelect* dup_expr() const;
|
||||
|
||||
private:
|
||||
@@ -2794,7 +2795,7 @@ class NetScope {
|
||||
|
||||
void add_event(NetEvent*);
|
||||
void rem_event(NetEvent*);
|
||||
NetEvent*find_event(const hname_t&name);
|
||||
NetEvent*find_event(const char*name);
|
||||
|
||||
|
||||
/* These methods manage signals. The add_ and rem_signal
|
||||
@@ -3084,6 +3085,12 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.271 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.270 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.269 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
|
||||
@@ -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.164 2002/11/09 02:22:07 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.
|
||||
@@ -2084,6 +2102,7 @@ specify_item_list
|
||||
|
||||
specify_edge_path_decl
|
||||
: specify_edge_path '=' '(' specify_delay_value_list ')'
|
||||
| specify_edge_path '=' delay_value_simple
|
||||
;
|
||||
|
||||
specify_edge_path
|
||||
@@ -2139,9 +2158,9 @@ specparam
|
||||
delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' '(' expression ')'
|
||||
| PATHPULSE_IDENTIFIER '=' expression
|
||||
{ delete $1;
|
||||
delete $4;
|
||||
delete $3;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' '(' expression ',' expression ')'
|
||||
{ delete $1;
|
||||
@@ -2315,8 +2334,8 @@ statement
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_TRIGGER IDENTIFIER ';'
|
||||
{ PTrigger*tmp = new PTrigger(hname_t($2));
|
||||
| K_TRIGGER identifier ';'
|
||||
{ PTrigger*tmp = new PTrigger(*$2);
|
||||
tmp->set_file(@2.text);
|
||||
tmp->set_lineno(@2.first_line);
|
||||
delete $2;
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
+263
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-virtex.c,v 1.18 2002/11/01 02:36:34 steve Exp $"
|
||||
#ident "$Id: d-virtex.c,v 1.21 2002/11/24 02:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
@@ -38,6 +38,8 @@
|
||||
* place-and-route step, as it is not normally needed within an
|
||||
* FPGA net.
|
||||
*
|
||||
* BUFT O, I, T
|
||||
*
|
||||
* INV O, I
|
||||
* Inverting buffer.
|
||||
*
|
||||
@@ -74,6 +76,13 @@ static const char*virtex_library_text =
|
||||
" (interface\n"
|
||||
" (port O (direction OUTPUT))\n"
|
||||
" (port I (direction INPUT)))))\n"
|
||||
" (cell BUFT (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface\n"
|
||||
" (port O (direction OUTPUT))\n"
|
||||
" (port I (direction OUTPUT))\n"
|
||||
" (port T (direction INPUT)))))\n"
|
||||
" (cell FDCE (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
@@ -422,6 +431,227 @@ void edif_show_cellref_logic(ivl_net_logic_t net, const char*cellref)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function draw wide AND-like devices. The input must have at
|
||||
* least 5 bits.
|
||||
*/
|
||||
static void wide_AND_logic(ivl_net_logic_t net, unsigned edif_uref)
|
||||
{
|
||||
char jbuf[1024];
|
||||
|
||||
/* This is the number of input bits left to connect. */
|
||||
unsigned ibits = ivl_logic_pins(net) - 1;
|
||||
/* Index to the next input bit. */
|
||||
unsigned idx = 1;
|
||||
unsigned slice = 0;
|
||||
|
||||
const char*lut4_init;
|
||||
const char*lut3_init;
|
||||
const char*lut2_init;
|
||||
const char*lut1_dev;
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
case IVL_LO_AND:
|
||||
lut4_init = "\"8000\"";
|
||||
lut3_init = "\"80\"";
|
||||
lut2_init = "\"8\"";
|
||||
lut1_dev = "BUF";
|
||||
break;
|
||||
case IVL_LO_NOR:
|
||||
lut4_init = "\"0001\"";
|
||||
lut3_init = "\"01\"";
|
||||
lut2_init = "\"1\"";
|
||||
lut1_dev = "INV";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
assert(ibits > 4);
|
||||
|
||||
while (ibits >= 4) {
|
||||
|
||||
/* The least significant bits are ANDed together 4 at a
|
||||
time with LUT4 devices. The output of the LUT4 device
|
||||
connects to a MUXCY device that passes its output
|
||||
up to the next stage.
|
||||
|
||||
The DI input of the MUXCY (S==0) is connected to
|
||||
ground, so that the ouput of the chain is pinned to 0
|
||||
if this slice does not AND to 1.
|
||||
|
||||
If the LUT emits 1, S==1 and this slice passes the
|
||||
compare from below. So the CI of the MUXCY gets the O
|
||||
of the MUXCY one slice back. */
|
||||
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT4 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string %s)))\n",
|
||||
edif_uref, slice, lut4_init);
|
||||
|
||||
fprintf(xnf, "(instance U%uM%u"
|
||||
" (viewRef net"
|
||||
" (cellRef MUXCY (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(instance U%uG%u"
|
||||
" (viewRef net"
|
||||
" (cellRef GND (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uLM%u (joined"
|
||||
" (portRef O (instanceRef U%uL%u))"
|
||||
" (portRef S (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uGM%u (joined"
|
||||
" (portRef GROUND (instanceRef U%uG%u))"
|
||||
" (portRef DI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
if (slice == 0) {
|
||||
fprintf(xnf, "(instance U%uV%u"
|
||||
" (viewRef net"
|
||||
" (cellRef VCC (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uMM%u (joined"
|
||||
" (portRef VCC (instanceRef U%uG%u))"
|
||||
" (portRef CI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
} else {
|
||||
fprintf(xnf, "(net U%uMM%u (joined"
|
||||
" (portRef O (instanceRef U%uM%u))"
|
||||
" (portReg CI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice-1,
|
||||
edif_uref, slice);
|
||||
}
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I2 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+2), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I3 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+3), jbuf);
|
||||
|
||||
ibits -= 4;
|
||||
idx += 4;
|
||||
slice += 1;
|
||||
}
|
||||
|
||||
if (ibits == 0) {
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%uM%u))",
|
||||
edif_uref, slice-1);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ibits) {
|
||||
|
||||
case 1:
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef %s (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice, lut1_dev);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string %s)))\n",
|
||||
edif_uref, slice, lut2_init);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT3 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string %s)))\n",
|
||||
edif_uref, slice, lut3_init);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I2 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+2), jbuf);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
fprintf(xnf, "(instance U%uM%u"
|
||||
" (viewRef net"
|
||||
" (cellRef MUXCY (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(instance U%uG%u"
|
||||
" (viewRef net"
|
||||
" (cellRef GND (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uLM%u (joined"
|
||||
" (portRef O (instanceRef U%uL%u))"
|
||||
" (portRef S (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uGM%u (joined"
|
||||
" (portRef GROUND (instanceRef U%uG%u))"
|
||||
" (portRef DI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uMM%u (joined"
|
||||
" (portRef O (instanceRef U%uM%u))"
|
||||
" (portReg CI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice-1,
|
||||
edif_uref, slice);
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%uM%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
|
||||
}
|
||||
|
||||
static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
{
|
||||
char jbuf[1024];
|
||||
@@ -438,7 +668,6 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_AND:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
@@ -463,6 +692,9 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
ivl_logic_pin(net, 3),
|
||||
ivl_logic_pin(net, 4), "8000");
|
||||
break;
|
||||
default:
|
||||
wide_AND_logic(net, edif_uref);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -481,8 +713,24 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF1:
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
fprintf(xnf, "(instance (rename U%u \"%s\")",
|
||||
edif_uref, ivl_logic_name(net));
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef TBUF (libraryRef VIRTEX))))\n");
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef T (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 2), jbuf);
|
||||
break;
|
||||
|
||||
case IVL_LO_NOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
@@ -507,6 +755,9 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
ivl_logic_pin(net, 3),
|
||||
ivl_logic_pin(net, 4), "0001");
|
||||
break;
|
||||
default:
|
||||
wide_AND_logic(net, edif_uref);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1657,6 +1908,15 @@ const struct device_s d_virtex_edif = {
|
||||
|
||||
/*
|
||||
* $Log: d-virtex.c,v $
|
||||
* Revision 1.21 2002/11/24 02:26:14 steve
|
||||
* Fix instanceRef spelling.
|
||||
*
|
||||
* Revision 1.20 2002/11/22 05:46:06 steve
|
||||
* Handle wide AND/NOR devices with Virtex carry logic.
|
||||
*
|
||||
* Revision 1.19 2002/11/22 01:45:40 steve
|
||||
* Implement bufif1 as BUFT
|
||||
*
|
||||
* Revision 1.18 2002/11/01 02:36:34 steve
|
||||
* Fix bottom bit of ADD/SUB device.
|
||||
*
|
||||
|
||||
+16
-7
@@ -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.
|
||||
|
||||
+71
-15
@@ -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.84 2002/11/07 03:12:17 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. */
|
||||
@@ -661,21 +714,11 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
||||
}
|
||||
}
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
fprintf(vvp_out, " %s/i0 %u, %u;\n", opcode, lv.base, lv.wid);
|
||||
|
||||
case 'l': /* << (left shift) */
|
||||
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
|
||||
break;
|
||||
|
||||
case 'r': /* >> (unsigned right shift) */
|
||||
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;
|
||||
}
|
||||
@@ -1338,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;
|
||||
@@ -1927,6 +1970,19 @@ 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.
|
||||
*
|
||||
* Revision 1.85 2002/11/21 22:42:48 steve
|
||||
* Allow right values of right shift to shift in.
|
||||
*
|
||||
* Revision 1.84 2002/11/07 03:12:17 steve
|
||||
* Vectorize load from REG variables.
|
||||
*
|
||||
|
||||
+10
-10
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_process.c,v 1.75 2002/11/17 18:31:09 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.76 2002/11/21 22:43:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -79,8 +79,8 @@ static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
|
||||
|
||||
if (ivl_lval_mux(lval)) {
|
||||
assert(wid == 1);
|
||||
fprintf(vvp_out, " %%set/x V_%s, %u, 0;\n",
|
||||
vvp_signal_label(sig), bit);
|
||||
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), bit, ivl_signal_pins(sig)-1);
|
||||
} else if (wid == 1) {
|
||||
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit);
|
||||
@@ -191,6 +191,8 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
value and write it into index0. */
|
||||
if (ivl_lval_mux(lval)) {
|
||||
calculate_into_x0(ivl_lval_mux(lval));
|
||||
/* Generate code to skip around the set
|
||||
if the index has X values. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
@@ -198,6 +200,8 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
mem = ivl_lval_mem(lval);
|
||||
if (mem) {
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
/* Generate code to skip around the set
|
||||
if the index has X values. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
@@ -234,14 +238,7 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
idx += cnt;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
set_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]), 1);
|
||||
|
||||
cur_rbit += 1;
|
||||
}
|
||||
#endif
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
@@ -1452,6 +1449,9 @@ int draw_func_definition(ivl_scope_t scope)
|
||||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.76 2002/11/21 22:43:13 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.75 2002/11/17 18:31:09 steve
|
||||
* Generate unique labels for force functors.
|
||||
*
|
||||
|
||||
+33
-4
@@ -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.80 2002/10/23 04:39:35 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.82 2002/12/21 00:55:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -1367,10 +1367,21 @@ static void draw_lpm_ff(ivl_lpm_t net)
|
||||
static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx, width, selects;
|
||||
unsigned selwid;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
selects = ivl_lpm_selects(net);
|
||||
|
||||
/* The .shift device can only take as many select inputs as
|
||||
the width of the device.
|
||||
|
||||
XXXX I should make some sort of overflow gate for this? If
|
||||
any high bits are set, then the shift is certain to be
|
||||
*way* beyond the width of the left shifted value. XXXX */
|
||||
selwid = selects;
|
||||
if (selwid > width)
|
||||
selwid = width;
|
||||
|
||||
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
|
||||
fprintf(vvp_out, "L_%s .shift/r %u",
|
||||
vvp_mangle_id(ivl_lpm_name(net)), width);
|
||||
@@ -1383,11 +1394,15 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
draw_input_from_net(ivl_lpm_data(net, idx));
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < selects ; idx += 1) {
|
||||
for (idx = 0 ; idx < selwid ; idx += 1) {
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(ivl_lpm_select(net, idx));
|
||||
}
|
||||
|
||||
for (idx = selwid ; idx < width ; idx += 1) {
|
||||
fprintf(vvp_out, ", C<0>");
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
@@ -1532,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
|
||||
@@ -1592,6 +1611,16 @@ 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.
|
||||
*
|
||||
* Revision 1.80 2002/10/23 04:39:35 steve
|
||||
* draw lpm ff with aset_expr taken into account.
|
||||
*
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog
|
||||
Version: 0.6.20021117
|
||||
Version: 0.7
|
||||
Release: 0
|
||||
Copyright: GPL
|
||||
Group: Applications/Engineering
|
||||
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20021117.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-20021117
|
||||
%setup -n verilog-0.7
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
|
||||
+134
-1
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
+17
-1
@@ -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.11 2002/08/15 02:12:20 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);
|
||||
@@ -460,6 +463,9 @@ static int sys_dumpfile_calltf(char*name)
|
||||
path = strdup("dumpfile.lxt");
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
close_dumpfile();
|
||||
|
||||
assert(dump_file == 0);
|
||||
open_dumpfile(path);
|
||||
|
||||
@@ -814,6 +820,16 @@ 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.
|
||||
*
|
||||
* Revision 1.11 2002/08/15 02:12:20 steve
|
||||
* add dumpvars_compiletf to check first argument.
|
||||
*
|
||||
|
||||
+52
-1
@@ -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.
|
||||
*
|
||||
|
||||
+19
-1
@@ -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.38 2002/11/14 22:43:58 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);
|
||||
@@ -449,6 +452,11 @@ static int sys_dumpfile_calltf(char*name)
|
||||
path = strdup("dumpfile.vcd");
|
||||
}
|
||||
|
||||
if (dump_file) {
|
||||
fclose(dump_file);
|
||||
dump_file = 0;
|
||||
}
|
||||
|
||||
assert(dump_file == 0);
|
||||
open_dumpfile(path);
|
||||
|
||||
@@ -844,6 +852,16 @@ 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.
|
||||
*
|
||||
* Revision 1.38 2002/11/14 22:43:58 steve
|
||||
* Save vpiFullName results.
|
||||
*
|
||||
|
||||
+11
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
-157
@@ -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
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
@@ -14,4 +14,5 @@ parse.output
|
||||
parse.h
|
||||
tables.cc
|
||||
vvp
|
||||
vvp.exp
|
||||
vvp.pdf
|
||||
|
||||
+28
-8
@@ -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)
|
||||
|
||||
+5
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: codes.h,v 1.53 2002/11/08 04:59:57 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.54 2002/11/21 22:43:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SUB(vthread_t thr, vvp_code_t code);
|
||||
@@ -160,6 +160,9 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
|
||||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.54 2002/11/21 22:43:13 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.53 2002/11/08 04:59:57 steve
|
||||
* Add the %assign/v0 instruction.
|
||||
*
|
||||
|
||||
+24
-4
@@ -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.145 2002/11/08 04:59:58 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.147 2002/12/21 00:55:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
@@ -137,7 +137,7 @@ const static struct opcode_table_s opcode_table[] = {
|
||||
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/x", of_SET_X, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
@@ -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,16 @@ 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.
|
||||
*
|
||||
* Revision 1.145 2002/11/08 04:59:58 steve
|
||||
* Add the %assign/v0 instruction.
|
||||
*
|
||||
|
||||
+9
-1
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
+9
-7
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams ([email protected])
|
||||
*
|
||||
* $Id: opcodes.txt,v 1.44 2002/11/08 04:59:58 steve Exp $
|
||||
* $Id: opcodes.txt,v 1.45 2002/11/21 22:43:13 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -459,15 +459,17 @@ address zero is the LSB of the first memory word. This instruction
|
||||
sets only a single bit.
|
||||
|
||||
|
||||
* %set/x <var-label>, <bit>, <idx>
|
||||
* %set/x0 <var-label>, <bit>, <top>
|
||||
|
||||
This sets the bit of a variable functor, the address calculated by
|
||||
using the index register <idx> (0, 1, 2 or 3) to index the functor
|
||||
address of <var-label>.
|
||||
using the index register 0 to index the functor address of
|
||||
<var-label>.
|
||||
|
||||
If the index value in index register <idx> is <0 (for example if
|
||||
%ix/get converted an unknown value into the register) then the set is
|
||||
not performed.
|
||||
If the index value in index register is <0 (for example if %ix/get
|
||||
converted an unknown value into the register) then the set is not
|
||||
performed. Also, if the index value is > the immediate top value, then
|
||||
the set is not performed. The 0 and <top> values suffice to provide
|
||||
complete bounds checking.
|
||||
|
||||
|
||||
* %shiftl/i0 <bit>, <wid>
|
||||
|
||||
+15
-2
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user