Remove files of vvm directory.

This commit is contained in:
steve 2003-01-10 03:05:05 +00:00
parent 9c3b3246c8
commit 165dd82bb2
32 changed files with 0 additions and 7031 deletions

View File

@ -1,121 +0,0 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.44 2001/06/12 03:53:10 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CC = @CC@ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../vpip
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../vpip
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CXXFLAGS = @CXXFLAGS@
CFLAGS = @CFLAGS@
LDFLAGS = @LDFLAGS@
STRIP = @STRIP@
O = vvm_add_sub.o vvm_bit.o vvm_calltf.o vvm_clshift.o vvm_compare.o \
vvm_event.o vvm_ff.o vvm_force.o \
vvm_func.o vvm_gates.o vvm_idiv.o vvm_imod.o vvm_memory.o vvm_mult.o \
vvm_mux.o vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o \
vvm_vpi.o
all: libvvm.a
libvvm.a: $O
rm -f $@
ar cvq $@ $O
%.o: %.cc
@[ -d dep ] || mkdir dep
$(CXX) -Wall -fno-exceptions $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
mv $*.d dep
clean:
rm -f *.o dep/*.d libvvm.a
install:: all installdirs \
$(libdir)/libvvm.a \
$(includedir)/vvm.h \
$(includedir)/vvm_func.h \
$(includedir)/vvm_gates.h \
$(includedir)/vvm_nexus.h \
$(includedir)/vvm_signal.h \
$(includedir)/vvm_thread.h \
$(includedir)/vvm_calltf.h
$(libdir)/libvvm.a: ./libvvm.a
$(INSTALL_DATA) ./libvvm.a $(libdir)/libvvm.a
$(includedir)/vvm.h: $(srcdir)/vvm.h
$(INSTALL_DATA) $(srcdir)/vvm.h $(includedir)/vvm.h
$(includedir)/vvm_calltf.h: $(srcdir)/vvm_calltf.h
$(INSTALL_DATA) $(srcdir)/vvm_calltf.h $(includedir)/vvm_calltf.h
$(includedir)/vvm_func.h: $(srcdir)/vvm_func.h
$(INSTALL_DATA) $(srcdir)/vvm_func.h $(includedir)/vvm_func.h
$(includedir)/vvm_gates.h: $(srcdir)/vvm_gates.h
$(INSTALL_DATA) $(srcdir)/vvm_gates.h $(includedir)/vvm_gates.h
$(includedir)/vvm_nexus.h: $(srcdir)/vvm_nexus.h
$(INSTALL_DATA) $(srcdir)/vvm_nexus.h $(includedir)/vvm_nexus.h
$(includedir)/vvm_signal.h: $(srcdir)/vvm_signal.h
$(INSTALL_DATA) $(srcdir)/vvm_signal.h $(includedir)/vvm_signal.h
$(includedir)/vvm_thread.h: $(srcdir)/vvm_thread.h
$(INSTALL_DATA) $(srcdir)/vvm_thread.h $(includedir)/vvm_thread.h
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
uninstall::
rm -f $(libdir)/libvvm.a
rm -f $(includedir)/vvm.h
rm -f $(includedir)/vvm_calltf.h
rm -f $(includedir)/vvm_func.h
rm -f $(includedir)/vvm_gates.h
rm -f $(includedir)/vvm_nexus.h
rm -f $(includedir)/vvm_signal.h
rm -f $(includedir)/vvm_thread.h
-include $(patsubst %.o, dep/%.d, $O $P)

View File

@ -1,100 +0,0 @@
#ifndef __ivl_dlfcn_H
#define __ivl_dlfcn_H
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_dlfcn.h,v 1.5 2002/08/12 01:35:06 steve Exp $"
#endif
#if defined(__MINGW32__)
# include <windows.h>
# include <stdio.h>
typedef void * ivl_dll_t;
#elif defined(HAVE_DLFCN_H)
# include <dlfcn.h>
typedef void* ivl_dll_t;
#elif defined(HAVE_DL_H)
# include <dl.h>
typedef shl_t ivl_dll_t;
#endif
#if defined(__MINGW32__)
inline ivl_dll_t ivl_dlopen(const char *name)
{ return (void *)LoadLibrary(name); }
inline void *ivl_dlsym(ivl_dll_t dll, const char *nm)
{ return (void *)GetProcAddress((HINSTANCE)dll,nm);}
inline void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
inline const char *dlerror(void)
{ static char s[30]; sprintf(s,"DLError:%ld", GetLastError()); return s;}
#elif defined(HAVE_DLFCN_H)
inline ivl_dll_t ivl_dlopen(const char*name)
{ return dlopen(name,RTLD_LAZY); }
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{ return dlsym(dll, nm); }
inline void ivl_dlclose(ivl_dll_t dll)
{ dlclose(dll); }
#elif defined(HAVE_DL_H)
inline ivl_dll_t ivl_dlopen(const char*name)
{ return shl_load(name, BIND_IMMEDIATE, 0); }
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
{
void*sym;
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
return (rc == 0) ? sym : 0;
}
inline void ivl_dlclose(ivl_dll_t dll)
{ shl_unload(dll); }
inline const char*dlerror(void)
{ return strerror( errno ); }
#endif
/*
* $Log: ivl_dlfcn.h,v $
* Revision 1.5 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2002/01/23 04:54:38 steve
* Load modules with RTLD_LAZY
*
* Revision 1.3 2001/05/22 02:14:47 steve
* Update the mingw build to not require cygwin files.
*
* Revision 1.2 2001/05/20 15:09:40 steve
* Mingw32 support (Venkat Iyer)
*
* Revision 1.1 2001/03/16 01:44:34 steve
* Add structures for VPI support, and all the %vpi_call
* instruction. Get linking of VPI modules to work.
*
* Revision 1.1 2001/01/14 17:12:59 steve
* possible HP/UX portability support.
*
*/
#endif

View File

@ -1,49 +0,0 @@
#ifndef __vvm_machine_H
#define __vvm_machine_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: 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 ""
#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.
*
*/
#endif

View File

@ -1,40 +0,0 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.1 1999/05/09 01:24:59 steve Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp" 1>&2
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here

161
vvm/vvm.h
View File

@ -1,161 +0,0 @@
#ifndef __vvm_H
#define __vvm_H
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm.h,v 1.38 2002/08/12 01:35:06 steve Exp $"
#endif
# include <cassert>
# include "vpi_priv.h"
/*
* The Verilog Virtual Machine are definitions for the virtual machine
* that executes models that the simulation generator makes.
*/
typedef unsigned vvm_u32;
class vvm_event;
class vvm_thread;
inline vpip_bit_t B_AND(vpip_bit_t l, vpip_bit_t r)
{
if (B_IS0(l)) return St0;
if (B_IS0(r)) return St0;
if (B_IS1(l) && B_IS1(r)) return St1;
return StX;
}
inline vpip_bit_t B_OR(vpip_bit_t l, vpip_bit_t r)
{
if (B_IS1(l)) return St1;
if (B_IS1(r)) return St1;
if (B_IS0(l) && B_IS0(r)) return St0;
return StX;
}
inline vpip_bit_t B_XOR(vpip_bit_t l, vpip_bit_t r)
{
if (B_ISZ(l)) return StX;
if (B_ISZ(r)) return StX;
if (B_ISX(l)) return StX;
if (B_ISX(r)) return StX;
if (B_IS0(l)) return r;
return B_IS0(r)? St1 : St0;
}
inline vpip_bit_t less_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c)
{
if (B_ISXZ(l)) return StX;
if (B_ISXZ(r)) return StX;
if ((l&0x80) > (r&0x80)) return St0;
if ((l&0x80) < (r&0x80)) return St1;
return c;
}
inline vpip_bit_t greater_with_cascade(vpip_bit_t l, vpip_bit_t r, vpip_bit_t c)
{
if (B_ISXZ(l)) return StX;
if (B_ISXZ(r)) return StX;
if ((l&0x80) > (r&0x80)) return St1;
if ((l&0x80) < (r&0x80)) return St0;
return c;
}
extern vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry);
inline vpip_bit_t B_NOT(vpip_bit_t l)
{
if (B_IS0(l)) return St1;
if (B_IS1(l)) return St0;
return StX;
}
/*
* These functions return true if the transition from A to B is a
* Verilog type of negedge of posedge.
*/
extern bool negedge(vpip_bit_t from, vpip_bit_t to);
extern bool posedge(vpip_bit_t from, vpip_bit_t to);
/*
* Verilog events (update events and nonblocking assign) are derived
* from this abstract class so that the simulation engine can treat
* all of them identically.
*/
class vvm_event {
public:
vvm_event();
virtual ~vvm_event() =0;
virtual void event_function() =0;
void schedule(unsigned long delay =0);
private:
struct vpip_event*event_;
static void callback_(void*);
private: // not implemented
vvm_event(const vvm_event&);
vvm_event& operator= (const vvm_event&);
};
/*
* $Log: vvm.h,v $
* Revision 1.38 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.37 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.36 2000/04/10 05:26:06 steve
* All events now use the NetEvent class.
*
* Revision 1.35 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.34 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.33 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.32 2000/03/13 00:02:34 steve
* Remove unneeded templates.
*
* Revision 1.31 2000/02/23 04:43:43 steve
* Some compilers do not accept the not symbol.
*
* Revision 1.30 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.29 2000/01/08 03:09:14 steve
* Non-blocking memory writes.
*/
#endif

View File

@ -1,135 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_add_sub.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_add_sub::vvm_add_sub(unsigned wid)
: width_(wid), ndir_(St0)
{
ibits_ = new vpip_bit_t[width_*3];
ro_ = new vvm_nexus::drive_t[width_];
c_ = StX;
for (unsigned idx = 0 ; idx < width_*3 ; idx += 1)
ibits_[idx] = StX;
}
vvm_add_sub::~vvm_add_sub()
{
delete[]ro_;
delete[]ibits_;
}
vvm_nexus::drive_t* vvm_add_sub::config_rout(unsigned idx)
{
assert(idx < width_);
return ro_+idx;
}
vvm_nexus::drive_t* vvm_add_sub::config_cout()
{
return &co_;
}
unsigned vvm_add_sub::key_DataA(unsigned idx) const
{
assert(idx < width_);
return idx;
}
unsigned vvm_add_sub::key_DataB(unsigned idx) const
{
assert(idx < width_);
return idx+width_;
}
void vvm_add_sub::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[idx] = val;
}
void vvm_add_sub::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[width_+idx] = val;
}
void vvm_add_sub::init_Add_Sub(unsigned, vpip_bit_t val)
{
ndir_ = B_NOT(val);
}
void vvm_add_sub::start()
{
compute_();
}
void vvm_add_sub::take_value(unsigned key, vpip_bit_t val)
{
if (ibits_[key] == val) return;
ibits_[key] = val;
compute_();
}
void vvm_add_sub::compute_()
{
vpip_bit_t carry = ndir_;
vpip_bit_t*a = ibits_;
vpip_bit_t*b = ibits_+width_;
vpip_bit_t*r = ibits_+2*width_;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
vpip_bit_t val;
val = add_with_carry(a[idx], B_XOR(b[idx],ndir_), carry);
if (val == r[idx]) continue;
r[idx] = val;
vvm_event*ev = new vvm_out_event(val, ro_+idx);
ev->schedule();
}
if (carry != c_)
(new vvm_out_event(carry, &co_)) -> schedule();
}
/*
* $Log: vvm_add_sub.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/17 17:25:53 steve
* Adder and comparator in nexus style.
*
*/

View File

@ -1,133 +0,0 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_bit.cc,v 1.15 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
bool negedge(vpip_bit_t from, vpip_bit_t to)
{
if (B_IS0(from))
return false;
if (B_ISX(from) || B_ISZ(from))
return B_IS0(to);
if (B_IS1(from))
return ! B_IS1(to);
return false;
}
bool posedge(vpip_bit_t from, vpip_bit_t to)
{
if (B_IS1(from))
return false;
if (B_ISX(from) || B_ISZ(from))
return B_IS1(to);
if (B_IS0(from))
return ! B_IS0(to);
return false;
}
vpip_bit_t add_with_carry(vpip_bit_t l, vpip_bit_t r, vpip_bit_t&carry)
{
unsigned li, ri, ci;
if (B_IS1(l)) {
li = 1;
} else if (B_IS0(l)) {
li = 0;
} else {
carry = StX;
return StX;
}
if (B_IS1(r)) {
ri = 1;
} else if (B_IS0(r)) {
ri = 0;
} else {
carry = StX;
return StX;
}
if (B_IS1(carry)) {
ci = 1;
} else if (B_IS0(carry)) {
ci = 0;
} else {
carry = StX;
return StX;
}
unsigned sum = li + ri + ci;
carry = (sum & 2)? St1 : St0;
return (sum & 1)? St1 : St0;
}
/*
* $Log: vvm_bit.cc,v $
* Revision 1.15 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.14 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.13 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.12 2000/04/10 05:26:07 steve
* All events now use the NetEvent class.
*
* Revision 1.11 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.10 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.9 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.8 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.7 1999/12/02 03:36:01 steve
* shiftl and shiftr take unsized second parameter.
*
* Revision 1.6 1999/11/22 00:30:52 steve
* Detemplate some and, or and nor methods.
*
* Revision 1.5 1999/11/21 00:13:09 steve
* Support memories in continuous assignments.
*/

View File

@ -1,174 +0,0 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_calltf.cc,v 1.16 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "machine.h"
# include "vvm_calltf.h"
# include <vpi_user.h>
# include "vpi_priv.h"
# include <new>
# include <iostream>
# include <assert.h>
# include <stdlib.h>
# include <stdarg.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdio.h>
# include "ivl_dlfcn.h"
# include "vpithunk.h"
# define MAX_PATHLEN 1024
static char*module_path = 0;
void vvm_set_module_path(const char*path)
{
if (module_path) free(module_path);
module_path = strdup(path);
}
/*
* The load_vpi_module function attempts to locate and load the named
* vpi module and call the included startup routines. This is invoked
* by the generated C++ code to load all the modules that the
* simulation requires.
*
* If there is a '/' character in the name, or there is no
* VPI_MODULE_PATH, the the name is usd as is. No path is searched for
* the module.
*
* If there is a VPI_MODULE_PATH and there is no '/' in the name, the
* VPI_MODULE_PATH is taken as a ':' separated list of directory
* names. Each directory is searched for a module with the right name
* that will link in. The current working directory is not implicitly
* tried. If you wish '.' be in th search path, include it.
*/
typedef void (*vlog_startup_routines_t)(void);
typedef int (*vpi_register_sim_t)(p_vpi_thunk tp);
void vvm_load_vpi_module(const char*name)
{
ivl_dll_t mod = 0;
const char*path = getenv("VPI_MODULE_PATH");
if (path == 0) path = module_path;
if ((path == 0) || (strchr(name, '/'))) {
mod = ivl_dlopen(name);
if (mod == 0) {
cerr << name << ": " << dlerror() << endl;
return;
}
} else {
const char*cur = path;
const char*ep;
for (cur = path ; cur ; cur = ep? ep+1 : 0) {
char dest[MAX_PATHLEN+1];
ep = strchr(cur, ':');
size_t n = ep? ep-cur : strlen(cur);
if ((n + strlen(name) + 2) > sizeof dest)
continue;
strncpy(dest, cur, n);
dest[n] = '/';
dest[n+1] = 0;
strcat(dest, name);
mod = ivl_dlopen(dest);
if (mod) break;
}
}
if (mod == 0) {
cerr << dlerror() << endl;
return;
}
void *regsub = ivl_dlsym(mod, LU "vpi_register_sim" TU);
vpi_register_sim_t simreg = (vpi_register_sim_t)regsub;
if (regsub == 0) {
cerr << name << ": Unable to locate vpi_register_sim" << endl;
ivl_dlclose(mod);
return;
}
extern vpi_thunk vvmt;
if (((simreg)(&vvmt)) == 0) {
cerr << name << ": vpi_register_sim returned zero" << endl;
ivl_dlclose(mod);
return;
}
void*table = ivl_dlsym(mod, LU "vlog_startup_routines" TU);
vlog_startup_routines_t*routines = (vlog_startup_routines_t*)table;
if (routines == 0) {
cerr << name << ": Unable to locate the vlog_startup_routines"
" table." << endl;
ivl_dlclose(mod);
return;
}
for (unsigned idx = 0 ; routines[idx] ; idx += 1)
(routines[idx])();
}
/*
* $Log: vvm_calltf.cc,v $
* Revision 1.16 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.15 2001/09/15 18:27:04 steve
* Make configure detect malloc.h
*
* Revision 1.14 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.13 2001/06/12 03:53:10 steve
* Change the VPI call process so that loaded .vpi modules
* use a function table instead of implicit binding.
*
* Revision 1.12 2001/01/14 17:12:59 steve
* possible HP/UX portability support.
*
* Revision 1.11 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.10 2000/01/24 00:18:20 steve
* Handle systems that need underscores in symbols.
*
* Revision 1.9 1999/11/28 18:05:37 steve
* Set VPI_MODULE_PATH in the target code, if desired.
*
* Revision 1.8 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*/

View File

@ -1,60 +0,0 @@
#ifndef __vvm_vvm_calltf_H
#define __vvm_vvm_calltf_H
/*
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_calltf.h,v 1.6 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vvm.h"
# include <string>
/*
* This function loads a vpi module by name.
*/
extern void vvm_set_module_path(const char*path);
extern void vvm_load_vpi_module(const char*path);
/*
* $Log: vvm_calltf.h,v $
* Revision 1.6 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/11/28 18:05:37 steve
* Set VPI_MODULE_PATH in the target code, if desired.
*
* Revision 1.3 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
* Revision 1.2 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/
#endif

View File

@ -1,178 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_clshift.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
/*
* This is the implementation of the LMP_CLSHIFT device.
*
* The device has input/output width if width_ bits, and a distance
* input of wdist_ bits. The inputs are stored in the ibits_ array,
* the data bits first, then the select bits.
*/
vvm_clshift::vvm_clshift(unsigned wid, unsigned wid_dist)
: width_(wid), wdist_(wid_dist)
{
ibits_ = new vpip_bit_t[width_ + wdist_];
out_ = new vvm_nexus::drive_t[width_];
dist_val_ = width_;
dir_ = St0;
for (unsigned idx = 0 ; idx < width_+wdist_ ; idx += 1)
ibits_[idx] = StX;
}
vvm_clshift::~vvm_clshift()
{
delete[]out_;
delete[]ibits_;
}
vvm_nexus::drive_t* vvm_clshift::config_rout(unsigned idx)
{
return out_+idx;
}
unsigned vvm_clshift::key_Data(unsigned idx) const
{
return idx;
}
unsigned vvm_clshift::key_Distance(unsigned idx) const
{
return idx+width_;
}
unsigned vvm_clshift::key_Direction(unsigned) const
{
return 0x20000;
}
void vvm_clshift::init_Data(unsigned idx, vpip_bit_t val)
{
ibits_[idx] = val;
}
void vvm_clshift::init_Distance(unsigned idx, vpip_bit_t val)
{
ibits_[width_+idx] = val;
calculate_dist_();
}
void vvm_clshift::init_Direction(unsigned, vpip_bit_t val)
{
dir_ = val;
}
void vvm_clshift::take_value(unsigned key, vpip_bit_t val)
{
if (key == 0x20000) {
if (dir_ == val) return;
dir_ = val;
calculate_dist_();
compute_();
return;
}
if (ibits_[key] == val) return;
ibits_[key] = val;
if (key < width_) {
if ((dist_val_ + key) >= width_) return;
if ((dist_val_ + key) < 0) return;
out_[dist_val_ + key].set_value(val);
} else {
calculate_dist_();
compute_();
}
}
void vvm_clshift::compute_()
{
// The dist_val_ is set to width_ if its value is not fully
// known. In this case, just set the output to unknown.
if (dist_val_ == (int)width_) {
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
out_[idx].set_value(StX);
return;
}
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
vpip_bit_t val;
if ((idx-dist_val_) >= width_) val = St0;
else if ((idx-dist_val_) < 0) val = St0;
else val = ibits_[idx-dist_val_];
out_[idx].set_value(val);
}
}
void vvm_clshift::calculate_dist_()
{
int tmp = 0;
for (unsigned idx = 0 ; idx < wdist_ ; idx += 1) {
if (B_ISX(ibits_[width_+idx]) || B_ISZ(ibits_[width_+idx])) {
tmp = width_;
break;
}
if (B_IS1(ibits_[width_+idx]))
tmp |= 1<<idx;
}
/* If the shift amount is too large (no matter the direction)
then set it to exactly width_ and the compute_ function
will handle the case directly. Otherwise, turn the shift
amount into a signed value that depends on the direction. */
if (tmp > (int)width_)
tmp = width_;
else if (B_IS1(dir_))
tmp = -tmp;
dist_val_ = tmp;
}
/*
* $Log: vvm_clshift.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/17 02:22:03 steve
* vvm_clshift implementation without templates.
*
*/

View File

@ -1,137 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_compare.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_compare::vvm_compare(unsigned wid)
: width_(wid)
{
gt_ = StX;
lt_ = StX;
ibits_ = new vpip_bit_t[2*width_];
for (unsigned idx = 0 ; idx < 2*width_ ; idx += 1)
ibits_[idx] = StX;
}
vvm_compare::~vvm_compare()
{
delete[]ibits_;
}
void vvm_compare::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[idx] = val;
}
void vvm_compare::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
ibits_[width_+idx] = val;
}
vvm_nexus::drive_t* vvm_compare::config_ALB_out()
{
return &out_lt_;
}
vvm_nexus::drive_t* vvm_compare::config_ALEB_out()
{
return &out_le_;
}
vvm_nexus::drive_t* vvm_compare::config_AGB_out()
{
return &out_gt_;
}
vvm_nexus::drive_t* vvm_compare::config_AGEB_out()
{
return &out_ge_;
}
unsigned vvm_compare::key_DataA(unsigned idx) const
{
assert(idx < width_);
return idx;
}
unsigned vvm_compare::key_DataB(unsigned idx) const
{
assert(idx < width_);
return width_ + idx;
}
void vvm_compare::take_value(unsigned key, vpip_bit_t val)
{
if (ibits_[key] == val)
return;
ibits_[key] = val;
compute_();
}
void vvm_compare::compute_()
{
vpip_bit_t gt = St0;
vpip_bit_t lt = St0;
vpip_bit_t*a = ibits_;
vpip_bit_t*b = ibits_+width_;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
gt = greater_with_cascade(a[idx], b[idx], gt);
lt = less_with_cascade(a[idx], b[idx], lt);
}
if ((gt_ == gt) && (lt_ == lt)) return;
gt_ = gt;
lt_ = lt;
out_lt_.set_value(lt_);
out_le_.set_value(B_NOT(gt_));
out_gt_.set_value(gt_);
out_ge_.set_value(B_NOT(lt_));
}
/*
* $Log: vvm_compare.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/17 17:25:53 steve
* Adder and comparator in nexus style.
*
*/

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_event.cc,v 1.7 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
# include <assert.h>
vvm_event::vvm_event()
{
event_ = 0;
}
vvm_event::~vvm_event()
{
assert(event_ == 0);
}
void vvm_event::schedule(unsigned long delay)
{
event_ = vpip_sim_insert_event(delay, this, callback_, 0);
}
void vvm_event::callback_(void*cbd)
{
vvm_event*obj = reinterpret_cast<vvm_event*>(cbd);
obj->event_ = 0;
obj->event_function();
delete obj;
}
/*
* $Log: vvm_event.cc,v $
* Revision 1.7 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 2000/01/06 05:56:22 steve
* Cleanup and some asserts.
*
* Revision 1.3 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.2 1999/10/28 00:47:25 steve
* Rewrite vvm VPI support to make objects more
* persistent, rewrite the simulation scheduler
* in C (to interface with VPI) and add VPI support
* for callbacks.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_ff.cc,v 1.4 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
vvm_ff::vvm_ff(unsigned w)
: width_(w)
{
out_ = new vvm_nexus::drive_t[width_];
bits_ = new vpip_bit_t[width_*2];
for (unsigned idx = 0 ; idx < width_*2 ; idx += 1)
bits_[idx] = StX;
}
vvm_ff::~vvm_ff()
{
delete[]bits_;
delete[]out_;
}
vvm_nexus::drive_t* vvm_ff::config_rout(unsigned idx)
{
assert(idx < width_);
return out_+idx;
}
unsigned vvm_ff::key_Data(unsigned idx) const
{
assert(idx < width_);
return idx+width_;
}
unsigned vvm_ff::key_Clock() const
{
return 0;
}
void vvm_ff::init_Data(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
bits_[idx+width_] = val;
}
void vvm_ff::init_Clock(unsigned, vpip_bit_t val)
{
clk_ = val;
}
void vvm_ff::take_value(unsigned key, vpip_bit_t val)
{
if (key == 0) {
if (val == clk_)
return;
bool flag = posedge(clk_, val);
clk_ = val;
if (flag)
latch_();
return;
}
bits_[key] = val;
}
void vvm_ff::latch_()
{
vpip_bit_t*q = bits_;
vpip_bit_t*d = bits_+width_;
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
if (q[idx] == d[idx])
continue;
q[idx] = d[idx];
out_[idx].set_value(q[idx]);
}
}
/*
* $Log: vvm_ff.cc,v $
* Revision 1.4 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/18 23:22:37 steve
* Update the FF device to nexus style.
*
*/

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_force.cc,v 1.5 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_force::vvm_force(unsigned w)
: width_(w)
{
force_flag_ = true;
bits_ = new vpip_bit_t[width_];
target_ = new vvm_nexus*[width_];
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
target_[idx] = 0;
}
vvm_force::~vvm_force()
{
delete[]bits_;
delete[]target_;
}
void vvm_force::init_I(unsigned key, vpip_bit_t val)
{
assert(key < width_);
bits_[key] = val;
}
void vvm_force::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (bits_[key] == val)
return;
bits_[key] = val;
if (! target_[key]) return;
if (force_flag_)
target_[key]->force_assign(val);
else
target_[key]->cassign(val);
}
void vvm_force::assign(unsigned key, vvm_nexus*tgt)
{
assert(key < width_);
assert(target_[key] == 0);
force_flag_ = false;
target_[key] = tgt;
target_[key]->cassign_set(this, key);
target_[key]->cassign(bits_[key]);
}
void vvm_force::force(unsigned key, vvm_nexus*tgt)
{
assert(key < width_);
assert(target_[key] == 0);
force_flag_ = true;
target_[key] = tgt;
target_[key]->force_set(this, key);
target_[key]->force_assign(bits_[key]);
}
/*
* This method is to be called from the vvm_nexus only when it has
* been told to release me.
*/
void vvm_force::release(unsigned key)
{
assert(target_[key]);
target_[key] = 0;
}
/*
* $Log: vvm_force.cc,v $
* Revision 1.5 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.3 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
* Revision 1.2 2000/04/23 03:45:25 steve
* Add support for the procedural release statement.
*
* Revision 1.1 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
*/

View File

@ -1,705 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_func.cc,v 1.18 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_func.h"
vpip_bit_t vvm_unop_and(const vvm_bitset_t&r)
{
vpip_bit_t v = r[0];
for (unsigned idx = 1 ; idx < r.get_width() ; idx += 1)
v = B_AND(v, r[idx]);
return v;
}
vpip_bit_t vvm_unop_nand(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_and(r);
return B_NOT(v);
}
vpip_bit_t vvm_unop_lnot(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_or(r);
return B_NOT(v);
}
void vvm_unop_not(vvm_bitset_t&v, const vvm_bitset_t&p)
{
assert(v.nbits <= p.nbits);
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = B_NOT(p[idx]);
}
vpip_bit_t vvm_unop_or(const vvm_bitset_t&r)
{
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_IS1(r.get_bit(idx)))
return St1;
}
return St0;
}
vpip_bit_t vvm_unop_nor(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_or(r);
return B_NOT(v);
}
void vvm_unop_uminus(vvm_bitset_t&v, const vvm_bitset_t&l)
{
vvm_unop_not(v, l);
vpip_bit_t carry = St1;
for (unsigned i = 0 ; i < v.nbits ; i += 1)
v[i] = add_with_carry(v[i], St0, carry);
}
vpip_bit_t vvm_unop_xor(const vvm_bitset_t&r)
{
vpip_bit_t v = St0;
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_IS1(r.get_bit(idx)))
v = B_NOT(v);
}
return v;
}
vpip_bit_t vvm_unop_xnor(const vvm_bitset_t&r)
{
vpip_bit_t v = vvm_unop_xor(r);
return B_NOT(v);
}
/*
* Do a bitwise AND into the result. We only need to calculate enough
* bits to fill the result. If I need to extend either value, extend
* it with St0.
*/
void vvm_binop_and(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
unsigned min = v.nbits;
if (r.nbits < min) min = r.nbits;
if (l.nbits < min) min = l.nbits;
for (unsigned idx = 0 ; idx < min ; idx += 1)
v[idx] = B_AND(l[idx], r[idx]);
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
v[idx] = St0;
}
void vvm_binop_minus(vvm_bitset_t&v, const vvm_bitset_t&l,
const vvm_bitset_t&r)
{
vvm_unop_not(v, r);
vpip_bit_t carry = St1;
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = add_with_carry(l[idx], v[idx], carry);
}
void vvm_binop_nor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
unsigned min = v.nbits;
if (r.nbits < min) min = r.nbits;
if (l.nbits < min) min = l.nbits;
for (unsigned idx = 0 ; idx < min ; idx += 1)
v[idx] = B_NOT(B_OR(l[idx], r[idx]));
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
v[idx] = B_NOT(r.nbits > min? r[idx] : l[idx]);
}
void vvm_binop_or(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
unsigned min = v.nbits;
if (r.nbits < min) min = r.nbits;
if (l.nbits < min) min = l.nbits;
for (unsigned idx = 0 ; idx < min ; idx += 1)
v[idx] = B_OR(l[idx], r[idx]);
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
v[idx] = r.nbits > min? r[idx] : l[idx];
}
/*
* This function adds two vectors to make a result vector. The
* operands and the result have their sizes already determined, so we
* take those into account.
*/
void vvm_binop_plus(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t carry = St0;
unsigned top = v.nbits;
if (l.nbits < top)
top = l.nbits;
if (r.nbits < top)
top = r.nbits;
unsigned idx;
/* First do the addition for the part of the vector where we
know that the bits from both inputs are present. */
for (idx = 0 ; idx < top ; idx += 1)
v[idx] = add_with_carry(l[idx], r[idx], carry);
/* Now continue the addition, padding the shorter vector with
St0 until we fill the result vector. */
for ( ; idx < v.nbits ; idx += 1) {
vpip_bit_t lv = (idx < l.nbits) ? l[idx] : St0;
vpip_bit_t rv = (idx < r.nbits) ? r[idx] : St0;
v[idx] = add_with_carry(lv, rv, carry);
}
}
void vvm_binop_shiftl(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r)
{
assert(v.nbits <= l.nbits);
vvm_u32 s = r.as_unsigned();
for (unsigned idx = 0 ; idx < v.nbits; idx += 1)
v[idx] = (idx < s) ? St0 : l[idx-s];
}
void vvm_binop_shiftr(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r)
{
vvm_u32 s = r.as_unsigned();
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = ((idx+s) < l.nbits) ? l[idx+s] : St0;
}
void vvm_binop_xnor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.nbits <= l.nbits);
assert(v.nbits <= r.nbits);
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = B_NOT(B_XOR(l[idx], r[idx]));
}
void vvm_binop_xor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.nbits <= l.nbits);
assert(v.nbits <= r.nbits);
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = B_XOR(l[idx], r[idx]);
}
vpip_bit_t vvm_binop_eq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
return StX;
if (B_ISXZ(r.get_bit(idx)))
return StX;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = lwid ; idx < rwid ; idx += 1) {
if (B_IS0(r.get_bit(idx)))
continue;
if (B_IS1(r.get_bit(idx)))
return St0;
return StX;
}
return St1;
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
return StX;
if (B_ISXZ(r.get_bit(idx)))
return StX;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = rwid ; idx < lwid ; idx += 1) {
if (B_IS0(l.get_bit(idx)))
continue;
if (B_IS1(l.get_bit(idx)))
return St0;
return StX;
}
return St1;
}
}
vpip_bit_t vvm_binop_ne(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = vvm_binop_eq(l,r);
return B_NOT(result);
}
vpip_bit_t vvm_binop_eeq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1)
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
if (! B_IS0(r.get_bit(idx)))
return St0;
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1)
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
if (! B_IS0(l.get_bit(idx)))
return St0;
}
return St1;
}
vpip_bit_t vvm_binop_nee(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = vvm_binop_eeq(l,r);
return B_NOT(result);
}
vpip_bit_t vvm_binop_xeq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
continue;
if (B_ISXZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = lwid ; idx < rwid ; idx += 1) {
if (B_ISXZ(r.get_bit(idx)))
continue;
if (! B_IS0(r.get_bit(idx)))
return St0;
}
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
continue;
if (B_ISXZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = rwid ; idx < lwid ; idx += 1) {
if (B_ISXZ(l.get_bit(idx)))
continue;
if (! B_IS0(l.get_bit(idx)))
return St0;
}
}
return St1;
}
vpip_bit_t vvm_binop_zeq(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
if (lwid <= rwid) {
for (unsigned idx = 0 ; idx < lwid ; idx += 1) {
if (B_ISZ(l.get_bit(idx)) || B_ISZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = lwid ; idx < rwid ; idx += 1) {
if (B_ISZ(r.get_bit(idx)))
continue;
if (! B_IS0(r.get_bit(idx)))
return St0;
}
} else {
for (unsigned idx = 0 ; idx < rwid ; idx += 1) {
if (B_ISZ(l.get_bit(idx)) || B_ISZ(r.get_bit(idx)))
continue;
if (! B_EQ(l.get_bit(idx), r.get_bit(idx)))
return St0;
}
for (unsigned idx = rwid ; idx < lwid ; idx += 1) {
if (B_ISZ(l.get_bit(idx)))
continue;
if (! B_IS0(l.get_bit(idx)))
return St0;
}
}
return St1;
}
vpip_bit_t vvm_binop_lt(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result;
result = St0;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = less_with_cascade(l.get_bit(idx), r.get_bit(idx), result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = less_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = less_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the < operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_lt_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) < $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_lt(l, r);
/* If l < 0 and r < 0, return $unsigned(r) < $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_lt(r, l);
/* If l >= 0 and r < 0, return false; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St0;
/* if l < 0 and r >= 0, return true; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St1;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_le(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = St1;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = less_with_cascade(l.get_bit(idx), r.get_bit(idx), result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = less_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = less_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the <= operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_le_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) <= $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_le(l, r);
/* If l < 0 and r < 0, return $unsigned(r) <= $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_le(r, l);
/* If l >= 0 and r < 0, return false; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St0;
/* if l < 0 and r >= 0, return true; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St1;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_gt(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = St0;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = greater_with_cascade(l.get_bit(idx),
r.get_bit(idx),
result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = greater_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = greater_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the > operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_gt_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) > $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_gt(l, r);
/* If l < 0 and r < 0, return $unsigned(r) > $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_gt(r, l);
/* If l >= 0 and r < 0, return true; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St1;
/* if l < 0 and r >= 0, return false; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St0;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_ge(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t result = St1;
const unsigned lwid = l.get_width();
const unsigned rwid = r.get_width();
const unsigned common = (lwid < rwid)? lwid : rwid;
for (unsigned idx = 0 ; idx < common ; idx += 1)
result = greater_with_cascade(l.get_bit(idx),
r.get_bit(idx), result);
if (lwid > rwid) {
for (unsigned idx = rwid ; idx < lwid ; idx += 1)
result = greater_with_cascade(l.get_bit(idx), St0, result);
} else {
for (unsigned idx = lwid ; idx < rwid ; idx += 1)
result = greater_with_cascade(St0, r.get_bit(idx), result);
}
return result;
}
/*
* This is the >= operator that applies to signed operands.
*/
vpip_bit_t vvm_binop_ge_s(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t l_pad = l.get_bit(l.get_width()-1);
vpip_bit_t r_pad = r.get_bit(r.get_width()-1);
/* If l>=0 and r>=0, return $unsigned(l) >= $unsigned(r) */
if (B_IS0(l_pad) && B_IS0(r_pad))
return vvm_binop_ge(l, r);
/* If l < 0 and r < 0, return $unsigned(r) >= $unsigned(l) */
if (B_IS1(l_pad) && B_IS1(r_pad))
return vvm_binop_ge(r, l);
/* If l >= 0 and r < 0, return true; */
if (B_IS0(l_pad) && B_IS1(r_pad))
return St1;
/* if l < 0 and r >= 0, return false; */
if (B_IS1(l_pad) && B_IS0(r_pad))
return St0;
/* Otherwise, one or the other side is unknown. Return X. */
return StX;
}
vpip_bit_t vvm_binop_land(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t res1 = vvm_unop_or(l);
vpip_bit_t res2 = vvm_unop_or(r);
return B_AND(res1, res2);
}
vpip_bit_t vvm_binop_lor(const vvm_bitset_t&l, const vvm_bitset_t&r)
{
vpip_bit_t res1 = vvm_unop_or(l);
vpip_bit_t res2 = vvm_unop_or(r);
return B_OR(res1, res2);
}
void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c,
const vvm_bitset_t&t,
const vvm_bitset_t&f)
{
if (B_IS0(c)) {
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = (idx < f.nbits)? f[idx] : St0;
return;
}
if (B_IS1(c)) {
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
v[idx] = (idx < t.nbits)? t[idx] : St0;
return;
}
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1) {
vpip_bit_t tb = (idx < t.nbits)? t[idx] : St0;
vpip_bit_t fb = (idx < f.nbits)? f[idx] : St0;
if (B_EQ(tb, fb))
v[idx] = tb;
else
v[idx] = StX;
}
}
/*
* $Log: vvm_func.cc,v $
* Revision 1.18 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.17 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.16 2001/02/13 03:38:55 steve
* Binary or and nor resilient to bit widths.
*
* Revision 1.15 2001/02/10 01:57:18 steve
* Make the add func resilient to bit widths (PR#141)
*
* Revision 1.14 2001/02/07 21:47:13 steve
* Fix expression widths for rvalues and parameters (PR#131,132)
*
* Revision 1.13 2000/12/11 00:31:44 steve
* Add support for signed reg variables,
* simulate in t-vvm signed comparisons.
*
* Revision 1.12 2000/07/06 18:12:28 steve
* unop_not can take out width same as in width.
*
* Revision 1.11 2000/06/30 15:47:06 steve
* Reduce result is OK in ~ operator.
*
* Revision 1.10 2000/05/18 20:35:08 steve
* Ternary operator handles bit sizes.
*
* Revision 1.9 2000/05/18 20:23:40 steve
* Overcautious assert in shift is removed.
*
* Revision 1.8 2000/04/29 01:19:47 steve
* Proper bounds checking of the left operator of right shift.
*
* Revision 1.7 2000/04/26 03:32:40 steve
* AND handles argument padding if necessary.
*
* Revision 1.6 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.5 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*
* Revision 1.4 2000/03/25 02:43:56 steve
* Remove all remain vvm_bitset_t return values,
* and disallow vvm_bitset_t copying.
*
* Revision 1.3 2000/03/24 02:43:37 steve
* vvm_unop and vvm_binop pass result by reference
* instead of returning a value.
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/13 00:02:34 steve
* Remove unneeded templates.
*
*/

View File

@ -1,269 +0,0 @@
#ifndef __vvm_vvm_func_H
#define __vvm_vvm_func_H
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_func.h,v 1.31 2002/08/12 01:35:06 steve Exp $"
#endif
# include "vvm.h"
# include "vvm_signal.h"
/*
* Implement the unary NOT operator in the verilog way. This takes a
* vector of a certain width and returns a result of the same width.
*/
extern void vvm_unop_not(vvm_bitset_t&v, const vvm_bitset_t&p);
/*
* The unary AND is the reduction AND. It returns a single bit.
*/
extern vpip_bit_t vvm_unop_and(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_nand(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_lnot(const vvm_bitset_t&r);
/*
* The unary OR is the reduction OR. It returns a single bit.
*/
extern vpip_bit_t vvm_unop_or(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_nor(const vvm_bitset_t&r);
/*
* The unary XOR is the reduction XOR. It returns a single bit.
*/
extern vpip_bit_t vvm_unop_xor(const vvm_bitset_t&r);
extern vpip_bit_t vvm_unop_xnor(const vvm_bitset_t&r);
/*
* simple-minded unary minus operator (two's complement)
*/
extern void vvm_unop_uminus(vvm_bitset_t&v, const vvm_bitset_t&l);
/*
* Implement the binary AND operator. This is a bitwise and with all
* the parameters and the result having the same width.
*/
extern void vvm_binop_and(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Implement the binary OR operator. This is a bitwise and with all
* the parameters and the result having the same width.
*/
extern void vvm_binop_or(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
extern void vvm_binop_nor(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Implement the binary + operator in the verilog way. This takes
* vectors of identical width and returns another vector of same width
* that contains the arithmetic sum. Z values are converted to X.
*/
extern void vvm_binop_plus(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Integer division and modulus
*/
extern void vvm_binop_idiv(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
extern void vvm_binop_imod(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* The binary - operator is turned into + by doing 2's complement
* arithmetic. l-r == l+~r+1. The "+1" is accomplished by adding in a
* carry of 1 to the 0 bit position.
*/
extern void vvm_binop_minus(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* The multiply binary operator takes an A and B parameter and returns
* the result in the vpip_bit_t array. The template form arranges for
* the right parameters to be passed to the extern form.
*/
extern void vvm_binop_mult(vpip_bit_t*res, unsigned nres,
const vpip_bit_t*a, unsigned na,
const vpip_bit_t*b, unsigned nb);
inline void vvm_binop_mult(vvm_bitset_t&r,
const vvm_bitset_t&a,
const vvm_bitset_t&b)
{
vvm_binop_mult(r.bits, r.nbits,
a.bits, a.nbits,
b.bits, b.nbits);
}
/*
* The binary ^ (xor) operator is a bitwise XOR of equal width inputs
* to generate the corresponsing output.
*/
extern void vvm_binop_xor(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
extern void vvm_binop_xnor(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* the binary 'l' operator is a logic left-shift by the number of positions
* indicated by argument r. r is an unsigned integer, which is represented
* internally as a 32-bit bitvector.
*/
extern void vvm_binop_shiftl(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* The binary 'r' operator is a logic right-shift by the number of positions
* indicated by argument r. r is an unsigned integer, which is represented
* internally by a 32-bit bitvector.
*/
extern void vvm_binop_shiftr(vvm_bitset_t&v,
const vvm_bitset_t&l,
const vvm_bitset_t&r);
/*
* Tests for equality are a bit tricky, as they allow for the left and
* right subexpressions to have different size. The shorter bitset is
* extended with zeros. Also, if there is Vx or Vz anywhere in either
* vectors, the result is Vx.
*/
extern vpip_bit_t vvm_binop_eq(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_ne(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* This function return true if all the bits are the same. Even x and
* z bites are compared for equality.
*/
extern vpip_bit_t vvm_binop_eeq(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_nee(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* This function return true if all the bits are the same. The x and z
* bits are don't care, s don't make the result false.
*/
extern vpip_bit_t vvm_binop_xeq(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* This function return true if all the bits are the same. The z
* bits are don't care, so don't make the result false.
*/
extern vpip_bit_t vvm_binop_zeq(const vvm_bitset_t&l, const vvm_bitset_t&r);
/*
* The _s variants are signed versions. That is, it assumes the
* operands are signed values and does the comparison on that basis.
*/
extern vpip_bit_t vvm_binop_lt(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_lt_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_le(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_le_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_gt(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_gt_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_ge(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_ge_s(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_land(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern vpip_bit_t vvm_binop_lor(const vvm_bitset_t&l, const vvm_bitset_t&r);
extern void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c,
const vvm_bitset_t&t,
const vvm_bitset_t&f);
/*
* $Log: vvm_func.h,v $
* Revision 1.31 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.30 2000/12/11 00:31:44 steve
* Add support for signed reg variables,
* simulate in t-vvm signed comparisons.
*
* Revision 1.29 2000/05/19 04:22:56 steve
* Add the integer modulus function.
*
* Revision 1.28 2000/04/01 21:40:23 steve
* Add support for integer division.
*
* Revision 1.27 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.26 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*
* Revision 1.25 2000/03/25 02:43:57 steve
* Remove all remain vvm_bitset_t return values,
* and disallow vvm_bitset_t copying.
*
* Revision 1.24 2000/03/24 02:43:37 steve
* vvm_unop and vvm_binop pass result by reference
* instead of returning a value.
*
* Revision 1.23 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.22 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.21 2000/03/13 00:02:34 steve
* Remove unneeded templates.
*
* Revision 1.20 2000/02/23 04:43:43 steve
* Some compilers do not accept the not symbol.
*
* Revision 1.19 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.18 2000/01/13 06:05:46 steve
* Add the XNOR operator.
*
* Revision 1.17 2000/01/13 03:35:35 steve
* Multiplication all the way to simulation.
*
* Revision 1.16 1999/12/02 03:36:01 steve
* shiftl and shiftr take unsized second parameter.
*/
#endif

View File

@ -1,971 +0,0 @@
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_gates.cc,v 1.24 2002/08/12 01:35:06 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <stdlib.h>
# include <typeinfo>
# include <string>
# include <map>
# include <sys/time.h>
# include <unistd.h>
vvm_out_event::vvm_out_event(vpip_bit_t v, vvm_nexus::drive_t*o)
: output_(o), val_(v)
{
}
vvm_out_event::~vvm_out_event()
{
}
void vvm_out_event::event_function()
{
output_->set_value(val_);
}
vvm_1bit_out::vvm_1bit_out(unsigned d)
: delay_(d)
{
drive0_ = St0;
drive1_ = St1;
driveX_ = StX;
driveZ_ = HiZ;
}
vvm_1bit_out::~vvm_1bit_out()
{
}
void vvm_1bit_out::drive0(vpip_bit_t v)
{
drive0_ = v;
driveX_ = (drive1_&0xf0) | (drive0_&0x0f);
}
void vvm_1bit_out::drive1(vpip_bit_t v)
{
drive1_ = v;
driveX_ = (drive1_&0xf0) | (drive0_&0x0f);
}
void vvm_1bit_out::driveZ(vpip_bit_t v)
{
driveZ_ = v;
}
void vvm_1bit_out::output(vpip_bit_t val)
{
if (delay_) {
vvm_event*ev = new vvm_out_event(val, this);
ev -> schedule(delay_);
} else {
set_value(val);
}
}
vpip_bit_t compute_and(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1 ; i < count ; i += 1)
outval = B_AND(outval, inp[i]);
return outval;
}
vpip_bit_t compute_or(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1 ; i < count ; i += 1)
outval = B_OR(outval, inp[i]);
return outval;
}
vpip_bit_t compute_nor(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1 ; i < count ; i += 1)
outval = B_OR(outval, inp[i]);
return B_NOT(outval);
}
vpip_bit_t compute_xor(const vpip_bit_t*inp, unsigned count)
{
vpip_bit_t outval = inp[0];
for (unsigned i = 1; i < count; i++)
outval = B_XOR(outval, inp[i]);
return outval;
}
vpip_bit_t compute_nand(const vpip_bit_t*inp, unsigned count)
{
return B_NOT(compute_and(inp,count));
}
vpip_bit_t compute_xnor(const vpip_bit_t*inp, unsigned count)
{
return B_NOT(compute_xor(inp,count));
}
vpip_bit_t reduce_strength(vpip_bit_t val)
{
if (B_IS0(val)) {
if ((val == Su0) ||
(val == St0))
return(Pu0);
else if (val == Pu0)
return(We0);
else if ((val == We0) ||
(val == La0))
return(Me0);
else if ((val == Me0) ||
(val == Sm0))
return(Sm0);
} else if (B_IS1(val)) {
if ((val == Su1) ||
(val == St1))
return(Pu1);
else if (val == Pu1)
return(We1);
else if ((val == We1) ||
(val == La1))
return(Me1);
else if ((val == Me1) ||
(val == Sm1))
return(Sm1);
} else if (B_ISX(val)) {
if ((val == SuX) ||
(val == StX))
return(PuX);
else if (val == PuX)
return(WeX);
else if ((val == WeX) ||
(val == LaX))
return(MeX);
else if ((val == MeX) ||
(val == SmX))
return(SmX);
}
return(HiZ);
}
vvm_and::vvm_and(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_and::~vvm_and()
{
delete [] input_;
}
void vvm_and::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_and::start()
{
output(compute_and(input_,width_));
}
void vvm_and::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_and(input_,width_));
}
vvm_and2::vvm_and2(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_and2::~vvm_and2()
{
}
void vvm_and2::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < 2);
input_[idx] = val;
}
void vvm_and2::start()
{
output(B_AND(input_[0], input_[1]));
}
void vvm_and2::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val)
return;
input_[key] = val;
output(B_AND(input_[0], input_[1]));
}
vvm_buf::vvm_buf(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_buf::~vvm_buf()
{
}
void vvm_buf::init_I(unsigned, vpip_bit_t)
{
}
void vvm_buf::take_value(unsigned, vpip_bit_t val)
{
vpip_bit_t outval = val;
if (B_ISXZ(val))
outval = StX;
else if (B_IS1(val))
outval = St1;
else
outval = St0;
output(outval);
}
vvm_bufif0::vvm_bufif0(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_bufif0::~vvm_bufif0()
{
}
void vvm_bufif0::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_bufif0::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS0(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_bufif1::vvm_bufif1(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_bufif1::~vvm_bufif1()
{
}
void vvm_bufif1::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_bufif1::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS0(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS1(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_bufz::vvm_bufz(unsigned delay)
: vvm_1bit_out(delay)
{
}
vvm_bufz::~vvm_bufz()
{
}
void vvm_bufz::init_I(unsigned, vpip_bit_t val)
{
output(val);
}
void vvm_bufz::take_value(unsigned, vpip_bit_t val)
{
output(val);
}
vvm_eeq::vvm_eeq(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_eeq::~vvm_eeq()
{
}
void vvm_eeq::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_eeq::start()
{
output(compute_());
}
void vvm_eeq::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val)
return;
input_[key] = val;
output(compute_());
}
vpip_bit_t vvm_eeq::compute_() const
{
vpip_bit_t outval = St0;
if (B_EQ(input_[0], input_[1]))
outval = St1;
return outval;
}
vvm_nand::vvm_nand(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_nand::~vvm_nand()
{
delete [] input_;
}
void vvm_nand::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_nand::start()
{
output(compute_nand(input_,width_));
}
void vvm_nand::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_nand(input_, width_));
}
vvm_nor::vvm_nor(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_nor::~vvm_nor()
{
delete [] input_;
}
void vvm_nor::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_nor::start()
{
output(compute_nor(input_,width_));
}
void vvm_nor::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_nor(input_, width_));
}
vvm_or::vvm_or(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_or::~vvm_or()
{
delete [] input_;
}
void vvm_or::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_or::start()
{
output(compute_or(input_,width_));
}
void vvm_or::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_or(input_, width_));
}
vvm_nmos::vvm_nmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_nmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_nmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) {
return;
}
input_[key] = val;
if ( B_IS0(input_[1])) {
output(HiZ);
} else if (B_ISX(input_[0]))
output(StX);
else if (B_ISZ(input_[0])) {
output(HiZ);
} else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS1(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_rnmos::vvm_rnmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_rnmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_rnmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS0(input_[1]))
output(HiZ);
else if (B_ISX(input_[0]))
output(reduce_strength(input_[0]));
else if (B_ISZ(input_[0]))
output(HiZ);
else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StL);
}
} else {
if (B_IS1(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StH);
}
}
}
vvm_pmos::vvm_pmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_pmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_pmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if (B_ISX(input_[0]))
output(StX);
else if (B_ISZ(input_[0]))
output(HiZ);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(St0);
} else {
output(StL);
}
} else {
if (B_IS0(input_[1])) {
output(St1);
} else {
output(StH);
}
}
}
vvm_rpmos::vvm_rpmos(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
void vvm_rpmos::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_rpmos::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if (B_ISX(input_[0]))
output(reduce_strength(input_[0]));
else if (B_ISZ(input_[0]))
output(HiZ);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StL);
}
} else {
if (B_IS0(input_[1])) {
output(reduce_strength(input_[0]));
} else {
output(StH);
}
}
}
void vvm_nor2::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < 2);
input_[idx] = val;
}
void vvm_nor2::start()
{
output(B_NOT(B_OR(input_[0], input_[1])));
}
vvm_nor2::vvm_nor2(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_nor2::~vvm_nor2()
{
}
void vvm_nor2::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val)
return;
input_[key] = val;
output(B_NOT(B_OR(input_[0], input_[1])));
}
vvm_not::vvm_not(unsigned long d)
: vvm_1bit_out(d)
{
}
vvm_not::~vvm_not()
{
}
void vvm_not::init_I(unsigned, vpip_bit_t)
{
}
void vvm_not::start()
{
}
void vvm_not::take_value(unsigned, vpip_bit_t val)
{
output(B_NOT(val));
}
vvm_notif0::vvm_notif0(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_notif0::~vvm_notif0()
{
}
void vvm_notif0::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_notif0::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS1(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS0(input_[1])) {
output(St1);
} else {
output(StH);
}
} else {
if (B_IS0(input_[1])) {
output(St0);
} else {
output(StL);
}
}
}
vvm_notif1::vvm_notif1(unsigned long d)
: vvm_1bit_out(d)
{
input_[0] = StX;
input_[1] = StX;
}
vvm_notif1::~vvm_notif1()
{
}
void vvm_notif1::init_I(unsigned key, vpip_bit_t val)
{
assert(key < 2);
input_[key] = val;
}
void vvm_notif1::take_value(unsigned key, vpip_bit_t val)
{
if (input_[key] == val) return;
input_[key] = val;
if ( B_IS0(input_[1]))
output(HiZ);
else if ( B_ISX(input_[0]) ||
B_ISZ(input_[0]))
output(StX);
else if (B_IS0(input_[0])) {
if (B_IS1(input_[1])) {
output(St1);
} else {
output(StH);
}
} else {
if (B_IS1(input_[1])) {
output(St0);
} else {
output(StL);
}
}
}
vvm_xnor::vvm_xnor(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_xnor::~vvm_xnor()
{
delete [] input_;
}
void vvm_xnor::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_xnor::start()
{
output(compute_xnor(input_,width_));
}
void vvm_xnor::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_xnor(input_, width_));
}
vvm_xor::vvm_xor(unsigned wid, unsigned long d)
: vvm_1bit_out(d), width_(wid)
{
input_ = new vpip_bit_t[wid];
}
vvm_xor::~vvm_xor()
{
delete [] input_;
}
void vvm_xor::init_I(unsigned idx, vpip_bit_t val)
{
input_[idx] = val;
}
void vvm_xor::start()
{
output(compute_xor(input_,width_));
}
void vvm_xor::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_);
if (input_[key] == val) return;
input_[key] = val;
output(compute_xor(input_, width_));
}
vvm_pullup::vvm_pullup(unsigned d)
: vvm_1bit_out(d)
{
}
void vvm_pullup::start()
{
output(St1);
}
void vvm_pullup::take_value(unsigned key, vpip_bit_t val)
{
}
vvm_pullup::~vvm_pullup()
{
}
vvm_pulldown::vvm_pulldown(unsigned d)
: vvm_1bit_out(d)
{
}
void vvm_pulldown::start()
{
output(St0);
}
void vvm_pulldown::take_value(unsigned key, vpip_bit_t val)
{
}
vvm_pulldown::~vvm_pulldown()
{
}
/*
* $Log: vvm_gates.cc,v $
* Revision 1.24 2002/08/12 01:35:06 steve
* conditional ident string using autoconfig.
*
* Revision 1.23 2001/10/14 03:50:53 steve
* vvm support for pullup/down gates (PR#288)
*
* Revision 1.22 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.21 2001/01/16 03:57:46 steve
* Get rid of gate templates.
*
* Revision 1.20 2000/12/10 06:42:00 steve
* Support delays on continuous assignment from idents. (PR#40)
*
* Revision 1.19 2000/11/11 01:52:09 steve
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
* change set to correct behavior of bufif0 and bufif1
* (Tim Leight)
*
* Also includes fix for PR#27
*
* Revision 1.18 2000/07/11 23:08:33 steve
* proper init method for bufz devices.
*
* Revision 1.17 2000/07/08 22:39:32 steve
* pass zero-delay values immediately.
*
* Revision 1.16 2000/05/11 01:37:33 steve
* Calculate the X output value from drive0 and drive1
*
* Revision 1.15 2000/05/09 21:16:35 steve
* Give strengths to logic and bufz devices.
*
* Revision 1.14 2000/05/08 05:27:32 steve
* Restore vvm_bufz to working condition.
*
* Revision 1.13 2000/04/23 21:15:07 steve
* Emit code for the bufif devices.
*
* Revision 1.12 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.11 2000/03/18 02:26:02 steve
* Update bufz to nexus style.
*
* Revision 1.10 2000/03/18 01:27:00 steve
* Generate references into a table of nexus objects instead of
* generating lots of isolated nexus objects. Easier on linkers
* and compilers,
*
* Add missing nexus support for l-value bit selects,
*
* Detemplatize the vvm_mux type.
*
* Fix up the vvm_nexus destructor to disconnect from drivers.
*
* Revision 1.9 2000/03/17 19:24:00 steve
* nor2 and and2 optimized gates.
*
* Revision 1.8 2000/03/17 03:36:07 steve
* Remove some useless template parameters.
*
* Revision 1.7 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
* Revision 1.6 2000/02/24 01:56:28 steve
* change not to v_not.
*
* Revision 1.5 2000/02/23 02:56:56 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.3 1999/12/02 04:54:11 steve
* Handle mux sel of X, if inputs are equal.
*
* Revision 1.2 1999/11/24 04:38:49 steve
* LT and GT fixes from Eric Aardoom.
*
* Revision 1.1 1999/11/22 00:30:52 steve
* Detemplate some and, or and nor methods.
*
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,157 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_idiv.cc,v 1.3 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_func.h"
# include "vvm_gates.h"
# include <assert.h>
void vvm_binop_idiv(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.get_width() <= 8*sizeof(unsigned long));
assert(l.get_width() <= 8*sizeof(unsigned long));
assert(r.get_width() <= 8*sizeof(unsigned long));
unsigned long lv = 0, rv = 0;
unsigned long vv;
for (unsigned idx = 0 ; idx < l.get_width() ; idx += 1) {
if (B_ISXZ(l[idx]))
goto unknown_result;
if (B_IS1(l[idx]))
lv |= 1 << idx;
}
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_ISXZ(r[idx]))
goto unknown_result;
if (B_IS1(r[idx]))
rv |= 1 << idx;
}
if (rv == 0)
goto unknown_result;
vv = lv / rv;
for (unsigned idx = 0 ; idx < v.get_width() ; idx += 1) {
if (vv & 1)
v[idx] = St1;
else
v[idx] = St0;
vv >>= 1;
}
return;
unknown_result:
for (unsigned idx= 0 ; idx < v.get_width() ; idx += 1)
v[idx] = StX;
}
vvm_idiv::vvm_idiv(unsigned rwid, unsigned awid, unsigned bwid)
: rwid_(rwid), awid_(awid), bwid_(bwid)
{
bits_ = new vpip_bit_t[rwid_+awid_+bwid_];
for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_ ; idx += 1)
bits_[idx] = StX;
out_ = new vvm_nexus::drive_t[rwid];
}
vvm_idiv::~vvm_idiv()
{
delete[]out_;
delete[]bits_;
}
void vvm_idiv::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < awid_);
bits_[rwid_+idx] = val;
}
void vvm_idiv::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < bwid_);
bits_[rwid_+awid_+idx] = val;
}
vvm_nexus::drive_t* vvm_idiv::config_rout(unsigned idx)
{
assert(idx < rwid_);
return out_+idx;
}
unsigned vvm_idiv::key_DataA(unsigned idx) const
{
assert(idx < awid_);
return rwid_+idx;
}
unsigned vvm_idiv::key_DataB(unsigned idx) const
{
assert(idx < bwid_);
return rwid_+awid_+idx;
}
void vvm_idiv::take_value(unsigned key, vpip_bit_t val)
{
if (B_EQ(bits_[key], val)) {
bits_[key] = val;
return;
}
bits_[key] = val;
vvm_bitset_t r (bits_, rwid_);
vvm_bitset_t a (bits_+rwid_, awid_);
vvm_bitset_t b (bits_+rwid_+awid_, bwid_);
vvm_binop_idiv(r, a, b);
for (unsigned idx = 0 ; idx < rwid_ ; idx += 1)
out_[idx].set_value(bits_[idx]);
}
/*
* $Log: vvm_idiv.cc,v $
* Revision 1.3 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.1 2000/04/01 21:40:23 steve
* Add support for integer division.
*
*/

View File

@ -1,165 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@picturel.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_imod.cc,v 1.5 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_func.h"
# include "vvm_gates.h"
# include <assert.h>
void vvm_binop_imod(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
{
assert(v.get_width() <= 8*sizeof(unsigned long));
assert(l.get_width() <= 8*sizeof(unsigned long));
assert(r.get_width() <= 8*sizeof(unsigned long));
unsigned long lv = 0, rv = 0;
unsigned long vv;
for (unsigned idx = 0 ; idx < l.get_width() ; idx += 1) {
if (B_ISXZ(l[idx]))
goto unknown_result;
if (B_IS1(l[idx]))
lv |= 1 << idx;
}
for (unsigned idx = 0 ; idx < r.get_width() ; idx += 1) {
if (B_ISXZ(r[idx]))
goto unknown_result;
if (B_IS1(r[idx]))
rv |= 1 << idx;
}
if (rv == 0)
goto unknown_result;
vv = lv % rv;
for (unsigned idx = 0 ; idx < v.get_width() ; idx += 1) {
if (vv & 1)
v[idx] = St1;
else
v[idx] = St0;
vv >>= 1;
}
return;
unknown_result:
for (unsigned idx= 0 ; idx < v.get_width() ; idx += 1)
v[idx] = StX;
}
vvm_imod::vvm_imod(unsigned rwid, unsigned awid, unsigned bwid)
: rwid_(rwid), awid_(awid), bwid_(bwid)
{
bits_ = new vpip_bit_t[rwid_+awid_+bwid_];
for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_ ; idx += 1)
bits_[idx] = StX;
out_ = new vvm_nexus::drive_t[rwid];
}
vvm_imod::~vvm_imod()
{
delete[]out_;
delete[]bits_;
}
void vvm_imod::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < awid_);
bits_[rwid_+idx] = val;
}
void vvm_imod::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < bwid_);
bits_[rwid_+awid_+idx] = val;
}
vvm_nexus::drive_t* vvm_imod::config_rout(unsigned idx)
{
assert(idx < rwid_);
return out_+idx;
}
unsigned vvm_imod::key_DataA(unsigned idx) const
{
assert(idx < awid_);
return rwid_+idx;
}
unsigned vvm_imod::key_DataB(unsigned idx) const
{
assert(idx < bwid_);
return rwid_+awid_+idx;
}
void vvm_imod::take_value(unsigned key, vpip_bit_t val)
{
if (B_EQ(bits_[key], val)) {
bits_[key] = val;
return;
}
bits_[key] = val;
vvm_bitset_t r (bits_, rwid_);
vvm_bitset_t a (bits_+rwid_, awid_);
vvm_bitset_t b (bits_+rwid_+awid_, bwid_);
vvm_binop_imod(r, a, b);
for (unsigned idx = 0 ; idx < rwid_ ; idx += 1)
out_[idx].set_value(bits_[idx]);
}
/*
* $Log: vvm_imod.cc,v $
* Revision 1.5 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.4 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.3 2000/09/17 21:26:16 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.2 2000/08/20 17:49:05 steve
* Clean up warnings and portability issues.
*
* Revision 1.1 2000/05/19 04:22:56 steve
* Add the integer modulus function.
*
*/

View File

@ -1,122 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_memory.cc,v 1.4 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_signal.h"
vvm_memory_t::vvm_memory_t()
{
cb_list_ = 0;
}
void vvm_memory_t::set_word(unsigned addr, const vvm_bitset_t&val)
{
if (addr >= size)
return;
unsigned base = width * addr;
for (unsigned idx = 0 ; idx < width ; idx += 1)
bits[base+idx] = val[idx];
call_list_(addr);
}
void vvm_memory_t::set_word(unsigned addr, const vpip_bit_t*val)
{
if (addr >= size)
return;
unsigned base = width * addr;
for (unsigned idx = 0 ; idx < width ; idx += 1)
bits[base+idx] = val[idx];
call_list_(addr);
}
void vvm_memory_t::get_word(unsigned addr, vvm_bitset_t&val) const
{
if (addr >= size) {
for (unsigned idx = 0 ; idx < width ; idx += 1)
val[idx] = StX;
return;
}
unsigned base = width * addr;
for (unsigned idx = 0 ; idx < width ; idx += 1)
val[idx] = bits[base+idx];
}
void vvm_memory_t::set_callback(vvm_ram_callback*ram)
{
ram->next_ = cb_list_;
cb_list_ = ram;
}
void vvm_memory_t::call_list_(unsigned idx)
{
for (vvm_ram_callback*cur = cb_list_; cur; cur = cur->next_)
cur->handle_write(idx);
}
vvm_memory_t::assign_nb::assign_nb(vvm_memory_t&m, unsigned i,
const vvm_bitset_t&v)
: mem_(m), index_(i), bits_(new vpip_bit_t[m.width]), val_(bits_, m.width)
{
unsigned top = m.width;
if (top > v.nbits)
top = v.nbits;
for (unsigned idx = 0 ; idx < top ; idx += 1)
val_[idx] = v[idx];
for (unsigned idx = top ; idx < m.width ; idx += 1)
val_[idx] = St0;
}
vvm_memory_t::assign_nb::~assign_nb()
{
delete[]bits_;
}
void vvm_memory_t::assign_nb::event_function()
{
mem_.set_word(index_, val_);
}
/*
* $Log: vvm_memory.cc,v $
* Revision 1.4 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/12/15 21:54:43 steve
* Allow non-blocking assign to pad memory word with zeros.
*
* Revision 1.1 2000/12/15 20:05:16 steve
* Fix memory access in vvm. (PR#70)
*
*/

View File

@ -1,219 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_mult.cc,v 1.8 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
static void add_into_result(vpip_bit_t *r, unsigned nr,
const vpip_bit_t *a, unsigned na) {
unsigned idx;
vpip_bit_t carry_bit = St0;
for (idx = 0; idx < nr && idx < na; idx++) {
vpip_bit_t val;
val = B_XOR(B_XOR(a[idx], r[idx]), carry_bit);
carry_bit = B_OR(B_OR(B_AND(a[idx], r[idx]),
B_AND(a[idx], carry_bit)),
B_AND(r[idx], carry_bit));
r[idx] = val;
}
}
static void vvm_binop_mult_generic(vpip_bit_t*r, unsigned nr,
const vpip_bit_t*a, unsigned na,
const vpip_bit_t*b, unsigned nb) {
unsigned idx;
for (idx = 0 ; idx < na ; idx += 1)
if (B_ISXZ(a[idx]))
goto unknown_result;
for (idx = 0 ; idx < nb ; idx += 1)
if (B_ISXZ(b[idx]))
goto unknown_result;
// Start off initialized to 0...
for (idx = 0 ; idx < nr ; idx += 1)
r[idx] = St0;
for (idx = 0; idx < nb && idx < nr; idx++)
if (B_IS1(b[idx]))
add_into_result(r+idx, nr-idx, a, na);
return;
unknown_result:
for (unsigned idx= 0 ; idx < nr ; idx += 1)
r[idx] = StX;
}
void vvm_binop_mult(vpip_bit_t*r, unsigned nr,
const vpip_bit_t*a, unsigned na,
const vpip_bit_t*b, unsigned nb)
{
if (nr > 8*sizeof(unsigned long) ||
na > 8*sizeof(unsigned long) ||
nb > 8*sizeof(unsigned long)) {
// If we can't use the fast routine, default to
// the slow one...
vvm_binop_mult_generic(r, nr, a, na, b, nb);
return;
}
assert(nr <= 8*sizeof(unsigned long));
assert(na <= 8*sizeof(unsigned long));
assert(nb <= 8*sizeof(unsigned long));
unsigned long av = 0, bv = 0;
unsigned long rv;
for (unsigned idx = 0 ; idx < na ; idx += 1) {
if (B_ISXZ(a[idx]))
goto unknown_result;
if (B_IS1(a[idx]))
av |= 1 << idx;
}
for (unsigned idx = 0 ; idx < nb ; idx += 1) {
if (B_ISXZ(b[idx]))
goto unknown_result;
if (B_IS1(b[idx]))
bv |= 1 << idx;
}
rv = av * bv;
for (unsigned idx = 0 ; idx < nr ; idx += 1) {
if (rv & 1)
r[idx] = St1;
else
r[idx] = St0;
rv >>= 1;
}
return;
unknown_result:
for (unsigned idx= 0 ; idx < nr ; idx += 1)
r[idx] = StX;
}
vvm_mult::vvm_mult(unsigned rwid, unsigned awid,
unsigned bwid, unsigned swid)
: rwid_(rwid), awid_(awid), bwid_(bwid), swid_(swid)
{
bits_ = new vpip_bit_t[rwid_+awid_+bwid_+swid_];
out_ = new vvm_nexus::drive_t[rwid_];
for (unsigned idx = 0 ; idx < rwid_+awid_+bwid_+swid_ ; idx += 1)
bits_[idx] = StX;
}
vvm_mult::~vvm_mult()
{
delete[]bits_;
delete[]out_;
}
vvm_nexus::drive_t* vvm_mult::config_rout(unsigned idx)
{
assert(idx < rwid_);
return out_+idx;
}
unsigned vvm_mult::key_DataA(unsigned idx) const
{
assert(idx < awid_);
return rwid_ + idx;
}
void vvm_mult::init_DataA(unsigned idx, vpip_bit_t val)
{
assert(idx < awid_);
bits_[rwid_+idx] = val;
}
unsigned vvm_mult::key_DataB(unsigned idx) const
{
assert(idx < bwid_);
return rwid_+awid_+idx;
}
void vvm_mult::init_DataB(unsigned idx, vpip_bit_t val)
{
assert(idx < bwid_);
bits_[rwid_+awid_+idx] = val;
}
void vvm_mult::take_value(unsigned key, vpip_bit_t val)
{
bits_[key] = val;
vvm_binop_mult(bits_, rwid_,
bits_+rwid_, awid_,
bits_+rwid_+awid_, bwid_);
for (unsigned idx = 0 ; idx < rwid_ ; idx += 1)
out_[idx].set_value(bits_[idx]);
}
/*
* $Log: vvm_mult.cc,v $
* Revision 1.8 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.7 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.6 2000/04/21 02:30:40 steve
* Generic multiplier (Chris Lattner)
*
* Revision 1.5 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.4 2000/03/17 03:05:13 steve
* Update vvm_mult to nexus style.
*
* Revision 1.3 2000/03/04 01:13:54 steve
* Simpler implementation of multiplication.
*
* Revision 1.2 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 2000/01/13 03:35:36 steve
* Multiplication all the way to simulation.
*
*/

View File

@ -1,171 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_mux.cc,v 1.4 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
# include <assert.h>
/*
* The array of bits is arranged as:
*
* oooo ss 0000 1111 2222 3333 ...
*
*/
vvm_mux::vvm_mux(unsigned w, unsigned s, unsigned sw)
: width_(w), size_(s), selwid_(sw)
{
bits_ = new vpip_bit_t[width_*size_+selwid_+width_];
out_ = new vvm_nexus::drive_t[width_];
for (unsigned idx = 0 ; idx < width_*size_+selwid_+width_ ; idx += 1)
bits_[idx] = StX;
}
vvm_mux::~vvm_mux()
{
delete[]out_;
delete[]bits_;
}
vvm_nexus::drive_t* vvm_mux::config_rout(unsigned idx)
{
assert(idx < width_);
return out_+idx;
}
unsigned vvm_mux::key_Sel(unsigned idx) const
{
assert(idx < selwid_);
return idx + width_;
}
unsigned vvm_mux::key_Data(unsigned wi, unsigned si) const
{
assert(si < size_);
assert(wi < width_);
return width_ + selwid_ + si*width_ + wi;
}
void vvm_mux::init_Sel(unsigned idx, vpip_bit_t val)
{
assert(idx < selwid_);
bits_[width_+idx] = val;
}
void vvm_mux::init_Data(unsigned idx, vpip_bit_t val)
{
assert(idx < width_*size_);
bits_[width_+selwid_+idx] = val;
}
void vvm_mux::take_value(unsigned key, vpip_bit_t val)
{
if (bits_[key] == val)
return;
bits_[key] = val;
evaluate_();
}
void vvm_mux::evaluate_()
{
vpip_bit_t*tmp = new vpip_bit_t[width_];
vpip_bit_t*sel = bits_+width_;
vpip_bit_t*inp = bits_+width_+selwid_;
compute_mux(tmp, width_, sel, selwid_, inp, size_);
for (unsigned idx = 0 ; idx < width_ ; idx += 1)
if (tmp[idx] != bits_[idx]) {
bits_[idx] = tmp[idx];
out_[idx].set_value(bits_[idx]);
}
delete[]tmp;
}
void compute_mux(vpip_bit_t*out, unsigned wid,
const vpip_bit_t*sel, unsigned swid,
const vpip_bit_t*dat, unsigned size)
{
unsigned tmp = 0;
for (unsigned idx = 0 ; idx < swid ; idx += 1) {
if (B_ISXZ(sel[idx])) {
tmp = size;
break;
}
if (B_IS1(sel[idx]))
tmp |= (1<<idx);
}
if (tmp >= size) {
if (swid > 1) {
for (unsigned idx = 0; idx < wid ; idx += 1)
out[idx] = StX;
} else {
const unsigned b0 = 0;
const unsigned b1 = wid;
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
if (dat[idx+b0] == dat[idx+b1])
out[idx] = dat[idx+b0];
else
out[idx] = StX;
}
}
} else {
unsigned b = tmp * wid;
for (unsigned idx = 0; idx < wid ; idx += 1)
out[idx] = dat[idx+b];
}
}
/*
* $Log: vvm_mux.cc,v $
* Revision 1.4 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.2 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.1 2000/03/18 01:27:00 steve
* Generate references into a table of nexus objects instead of
* generating lots of isolated nexus objects. Easier on linkers
* and compilers,
*
* Add missing nexus support for l-value bit selects,
*
* Detemplatize the vvm_mux type.
*
* Fix up the vvm_nexus destructor to disconnect from drivers.
*
*/

View File

@ -1,386 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_nexus.cc,v 1.13 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_nexus.h"
# include "vvm_gates.h"
# include <assert.h>
vvm_nexus::vvm_nexus()
{
drivers_ = 0;
recvrs_ = 0;
ival_ = 0;
nival_ = 0;
value_ = 0;
force_ = 0;
forcer_ = 0;
forcer_key_ = 0;
assigner_ = 0;
assigner_key_ = 0;
resolution_function = &vvm_resolution_wire;
}
vvm_nexus::~vvm_nexus()
{
while (drivers_) {
drive_t*cur = drivers_;
drivers_ = cur->next_;
assert(cur->nexus_ == this);
cur->nexus_ = 0;
cur->next_ = 0;
}
/* assert(recvrs_ == 0); XXXX I really should make a point to
guarantee that all the receivers that I refer to are gone,
but since I know for now that this destructor is only
called when the simulation exist, nevermind. */
}
/*
* Connect a driver to this nexus. The driver needs to know who I am
* (and can only be connected to one nexus) and also I need to keep a
* list of all the drivers connected to me. Arranging the list
* pointers accordingly. Also, keep track of the number of drivers I
* have connected to me, and maintain the ival_ array so that I do not
* need to manage the array at run time.
*/
void vvm_nexus::connect(vvm_nexus::drive_t*drv)
{
// Link the driver into my list of drivers.
assert(drv->nexus_ == 0);
drv->nexus_ = this;
drv->next_ = drivers_;
drivers_ = drv;
nival_ += 1;
if (ival_) delete[]ival_;
ival_ = new vpip_bit_t[nival_];
}
/*
* Connect this receiver to me. Receivers are handled a little
* differently from drivers, a receiver is fully specified by the
* pointer to the receiver AS WELL AS a magic key value. This allows a
* gate to me a receiver with many different input pins.
*/
void vvm_nexus::connect(vvm_nexus::recvr_t*rcv, unsigned key)
{
recvr_cell*cur = new recvr_cell;
cur->dev = rcv;
cur->key = key;
cur->next = recvrs_;
recvrs_ = cur;
}
void vvm_nexus::disconnect(vvm_nexus::drive_t*drv)
{
drive_t*cur = drivers_;
drivers_ = 0;
while (cur) {
drive_t*tmp = cur;
cur = cur->next_;
if (tmp != drv) {
tmp->next_ = drivers_;
drivers_ = tmp;
}
}
}
/*
* This method disconnects a receiver completely by removing every
* access to it. (Remember that a recvr_t object may be connected many
* times with different keys.)
*/
void vvm_nexus::disconnect(vvm_nexus::recvr_t*rcv)
{
recvr_cell*cur = recvrs_;
recvrs_ = 0;
while (cur) {
recvr_cell*tmp = cur;
cur = tmp->next;
if (tmp->dev == rcv) {
delete tmp;
} else {
tmp->next = recvrs_;
recvrs_ = tmp;
}
}
}
/*
* Reg assign (or procedural assignment) does not use the concept of
* drivers. Instead, I skip the resolution function, save the value
* for myself and pass the value to the receivers.
*/
void vvm_nexus::reg_assign(vpip_bit_t val)
{
assert(drivers_ == 0);
value_ = val;
if (forcer_)
return;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::force_set(vvm_force*f, unsigned k)
{
if (forcer_)
forcer_->release(forcer_key_);
forcer_ = f;
forcer_key_ = k;
}
void vvm_nexus::cassign_set(vvm_force*f, unsigned k)
{
assert(drivers_ == 0);
if (assigner_)
assigner_->release(assigner_key_);
assigner_ = f;
assigner_key_ = k;
}
void vvm_nexus::force_assign(vpip_bit_t val)
{
assert(forcer_);
force_ = val;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, force_);
}
void vvm_nexus::cassign(vpip_bit_t val)
{
assert(assigner_);
value_ = val;
if (forcer_) return;
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::release()
{
if (forcer_) {
forcer_->release(forcer_key_);
forcer_ = 0;
}
/* Now deliver that output value to all the receivers
connected to this nexus. */
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
void vvm_nexus::deassign()
{
assert(drivers_ == 0);
if (assigner_) {
assigner_->release(assigner_key_);
assigner_ = 0;
}
}
/*
* This method is invoked when something interesting happens at one of
* the drivers. It collects all the driver values, resolves them into
* a signal value, and passed them to all the connected
* receivers. This is the workhorse of the nexus object.
*/
void vvm_nexus::run_values()
{
/* Collect the values from all the signal drivers. We should
have exactly the right size ival_ array for the number of
drives. */
unsigned idx = 0;
for (drive_t*cur = drivers_; cur ; cur = cur->next_) {
assert(idx < nival_);
ival_[idx++] = cur->peek_value();
}
assert(idx == nival_);
/* Use the resolution function to generate the settled value
for this nexus. */
vpip_bit_t val = resolution_function(ival_, nival_);
if (value_ == val) return;
value_ = val;
if (forcer_)
return;
/* Now deliver that output value to all the receivers
connected to this nexus. */
for (recvr_cell*cur = recvrs_; cur ; cur = cur->next)
cur->dev->take_value(cur->key, value_);
}
vvm_nexus::drive_t::drive_t()
{
value_ = StX;
nexus_ = 0;
}
vvm_nexus::drive_t::~drive_t()
{
if (nexus_) nexus_->disconnect(this);
}
vpip_bit_t vvm_nexus::drive_t::peek_value() const
{
return value_;
}
void vvm_nexus::drive_t::set_value(vpip_bit_t val)
{
if (val == value_) return;
value_ = val;
if (nexus_) nexus_->run_values();
}
vvm_nexus::recvr_t::recvr_t()
{
}
vvm_nexus::recvr_t::~recvr_t()
{
}
vpip_bit_t vvm_resolution_wire(const vpip_bit_t*bits, unsigned nbits)
{
if (nbits == 0) return HiZ;
return vpip_bits_resolve(bits, nbits);
}
vpip_bit_t vvm_resolution_sup0(const vpip_bit_t*, unsigned)
{
return Su0;
}
vpip_bit_t vvm_resolution_sup1(const vpip_bit_t*, unsigned)
{
return Su1;
}
vpip_bit_t vvm_resolution_tri0(const vpip_bit_t*bits, unsigned nbits)
{
if (nbits == 0) return Pu0;
vpip_bit_t res = vpip_bits_resolve(bits, nbits);
if (B_ISZ(res)) return Pu0;
return res;
}
vpip_bit_t vvm_resolution_tri1(const vpip_bit_t*bits, unsigned nbits)
{
if (nbits == 0) return Pu1;
vpip_bit_t res = vpip_bits_resolve(bits, nbits);
if (B_ISZ(res)) return Pu1;
return res;
}
class delayed_assign_event : public vvm_event {
public:
delayed_assign_event(vvm_nexus&l, vpip_bit_t r)
: l_val_(l), r_val_(r) { }
void event_function() { l_val_.reg_assign(r_val_); }
private:
vvm_nexus& l_val_;
vpip_bit_t r_val_;
};
void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
unsigned long delay)
{
delayed_assign_event*ev = new delayed_assign_event(l_val, r_val);
ev->schedule(delay);
}
/*
* $Log: vvm_nexus.cc,v $
* Revision 1.13 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.12 2001/07/25 03:10:50 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.11 2000/11/20 00:58:40 steve
* Add support for supply nets (PR#17)
*
* Revision 1.10 2000/10/23 00:32:48 steve
* Nexus value is initially unknown so that it propogates for sure.
*
* Revision 1.9 2000/08/02 00:57:03 steve
* tri01 support in vvm.
*
* Revision 1.8 2000/05/11 23:37:28 steve
* Add support for procedural continuous assignment.
*
* Revision 1.7 2000/04/23 03:45:25 steve
* Add support for the procedural release statement.
*
* Revision 1.6 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.5 2000/03/22 05:16:38 steve
* Integrate drive resolution function.
*
* Revision 1.4 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.3 2000/03/18 01:27:00 steve
* Generate references into a table of nexus objects instead of
* generating lots of isolated nexus objects. Easier on linkers
* and compilers,
*
* Add missing nexus support for l-value bit selects,
*
* Detemplatize the vvm_mux type.
*
* Fix up the vvm_nexus destructor to disconnect from drivers.
*
* Revision 1.2 2000/03/16 21:45:07 steve
* Properly initialize driver and nexus values.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/

View File

@ -1,194 +0,0 @@
#ifndef __vvm_vvm_nexus_H
#define __vvm_vvm_nexus_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_nexus.h,v 1.7 2002/08/12 01:35:07 steve Exp $"
#endif
# include "vvm.h"
class vvm_force;
/*
* The nexus class represents a connection point for drivers and
* receivers of signals. The signal carries a single bit, has drivers,
* has fan_out and has a current value. Classes derive from the nexus
* in order to provide specific kinds of N-driver resolution.
*
* The driver_t and recvr_t classes are the means to connect to a
* nexus. In general, other then to connect the drivers and receivers,
* there should be no cause to manipulate the nexus object directly.
*
* The driver_t class represents a driver on the nexus. There can be
* any number of drivers on a nexus, so long as the
* recolution_function can handle the situation. The drivers are
* normally members of some gate object somewhere. When the driver
* receives a value, it saves the value in itself and tells the
* connected nexus that something has changed.
*
* The nexus object, when it notices that one of its drivers changed,
* collects the values of the drivers and passes the set to the
* resolution function. The resolution function calculates what the
* value of the nexus should be given the values driving it.
*
* When the value of the nexus is ready, it scans the list of
* connected receivers and passes the new value out. The receiver is
* actually a pointer to the recvr_t object and a key. This is so the
* receiver object can receive many different pins worth of data. The
* idea is that a gate can be a single recvr_t object, and the key can
* be used and the number of the affected pin.
*/
class vvm_nexus {
public:
class drive_t {
friend class ::vvm_nexus;
public:
drive_t();
~drive_t();
vpip_bit_t peek_value() const;
void set_value(vpip_bit_t);
private:
vpip_bit_t value_;
vvm_nexus*nexus_;
drive_t*next_;
private: // not implemented
drive_t(const drive_t&);
drive_t& operator= (const drive_t&);
};
class recvr_t {
friend class ::vvm_nexus;
public:
recvr_t();
virtual ~recvr_t() =0;
virtual void take_value(unsigned key, vpip_bit_t val) =0;
private: // not implemented
recvr_t(const recvr_t&);
recvr_t& operator= (const recvr_t&);
};
public:
vvm_nexus();
~vvm_nexus();
// These methods support connecting the receiver and driver to
// the nexus.
void connect(drive_t*drv);
void connect(recvr_t*rcv, unsigned key);
void disconnect(drive_t*drv);
void disconnect(recvr_t*rcv);
// If there are no drivers to this nexus, this can be used to
// to procedural assignments to the node, as if it where a reg.
void reg_assign(vpip_bit_t val);
// These methods support the procedural continuous assign. The
// vvm_force oject will set itself as an assigner, then will
// periodically call the cassign method to do the assign. The
// procedural deassign will call the deassign method to detach
// the vvm_force object.
void cassign_set(class vvm_force*frc, unsigned key);
void cassign(vpip_bit_t val);
void deassign();
// This method causes the specified value to be forced onto
// the nexus. This overrides all drivers that are attached.
void force_set(class vvm_force*frc, unsigned key);
void force_assign(vpip_bit_t val);
void release();
// The run_values() method collects all the current driver
// values and, with the aid of the resolution_function,
// generates the current value for the nexus. It also passes
// that value on to the receuvers.
void run_values();
vpip_bit_t (*resolution_function)(const vpip_bit_t*, unsigned);
private:
vpip_bit_t value_;
drive_t*drivers_;
struct recvr_cell {
recvr_t *dev;
unsigned key;
recvr_cell*next;
} *recvrs_;
vpip_bit_t*ival_;
unsigned nival_;
vvm_force *assigner_;
unsigned assigner_key_;
vpip_bit_t force_;
vvm_force *forcer_;
unsigned forcer_key_;
private: // not implemented
vvm_nexus(const vvm_nexus&);
vvm_nexus& operator= (const vvm_nexus&);
};
extern vpip_bit_t vvm_resolution_wire(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_sup0(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_sup1(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_tri0(const vpip_bit_t*bits, unsigned nbits);
extern vpip_bit_t vvm_resolution_tri1(const vpip_bit_t*bits, unsigned nbits);
/*
* This function arranges for a non-blocking reg_assign to a nexus. It
* creates all the events needed to make it happen after the specified
* delay.
*/
extern void vvm_delayed_assign(vvm_nexus&l_val, vpip_bit_t r_val,
unsigned long delay);
/*
* $Log: vvm_nexus.h,v $
* Revision 1.7 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.6 2000/11/20 00:58:41 steve
* Add support for supply nets (PR#17)
*
* Revision 1.5 2000/08/02 00:57:03 steve
* tri01 support in vvm.
*
* Revision 1.4 2000/05/11 23:37:28 steve
* Add support for procedural continuous assignment.
*
* Revision 1.3 2000/04/23 03:45:25 steve
* Add support for the procedural release statement.
*
* Revision 1.2 2000/04/22 04:20:20 steve
* Add support for force assignment.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/
#endif

View File

@ -1,202 +0,0 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_pevent.cc,v 1.11 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
# include "vvm_gates.h"
# include "vvm_thread.h"
vvm_sync::vvm_sync()
: hold_(0), tgt_(0), ntgt_(0)
{
}
void vvm_sync::wait(vvm_thread*thr)
{
assert(thr->sync_back_ == 0);
thr->sync_next_ = hold_;
thr->sync_back_ = this;
hold_ = thr;
}
void vvm_sync::wakeup()
{
while (hold_) {
vvm_thread*tmp = hold_;
hold_ = tmp->sync_next_;
assert(tmp->sync_back_ == this);
tmp->sync_back_ = 0;
tmp->thread_yield();
for (unsigned idx = 0 ; idx < ntgt_ ; idx += 1)
tgt_[idx]->wakeup();
}
}
void vvm_sync::chain_sync(vvm_sync*src)
{
if (src->ntgt_ == 0) {
src->tgt_ = new vvm_sync*[1];
src->tgt_[0] = this;
src->ntgt_ = 1;
} else {
vvm_sync**tmp = new vvm_sync*[src->ntgt_+1];
for (unsigned idx = 0 ; idx < src->ntgt_ ; idx += 1)
tmp[idx] = src->tgt_[idx];
tmp[src->ntgt_] = this;
src->ntgt_ += 1;
delete [] src->tgt_;
src->tgt_ = tmp;
}
}
vvm_posedge::vvm_posedge(vvm_sync*tgt)
: sync_(tgt)
{
val_ = StX;
}
vvm_posedge::~vvm_posedge()
{
}
void vvm_posedge::init_P(int, vpip_bit_t val)
{
val_ = val;
}
void vvm_posedge::take_value(unsigned, vpip_bit_t val)
{
if (val == val_)
return;
if (posedge(val_, val))
sync_->wakeup();
val_ = val;
}
vvm_negedge::vvm_negedge(vvm_sync*tgt)
: sync_(tgt)
{
val_ = StX;
}
vvm_negedge::~vvm_negedge()
{
}
void vvm_negedge::init_P(int, vpip_bit_t val)
{
val_ = val;
}
void vvm_negedge::take_value(unsigned, vpip_bit_t val)
{
if (val == val_)
return;
if (negedge(val_, val))
sync_->wakeup();
val_ = val;
}
vvm_anyedge::vvm_anyedge(vvm_sync*tgt, unsigned n)
: nval_(n), sync_(tgt)
{
val_ = new vpip_bit_t[nval_];
for (unsigned idx = 0 ; idx < nval_ ; idx += 1)
val_[idx] = StX;
}
vvm_anyedge::~vvm_anyedge()
{
delete[]val_;
}
void vvm_anyedge::init_P(unsigned key, vpip_bit_t val)
{
assert(key < nval_);
val_[key] = val;
}
void vvm_anyedge::take_value(unsigned key, vpip_bit_t val)
{
assert(key < nval_);
if (val == val_[key])
return;
if (! B_EQ(val, val_[key]))
sync_->wakeup();
val_[key] = val;
}
/*
* $Log: vvm_pevent.cc,v $
* Revision 1.11 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.10 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.9 2000/04/15 02:25:32 steve
* Support chained events.
*
* Revision 1.8 2000/04/12 16:08:46 steve
* Backwards sense of assert test.
*
* Revision 1.7 2000/04/12 01:53:07 steve
* Multiple thread can block on an event.
*
* Revision 1.6 2000/04/10 05:26:07 steve
* All events now use the NetEvent class.
*
* Revision 1.5 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.3 1999/05/01 20:43:55 steve
* Handle wide events, such as @(a) where a has
* many bits in it.
*
* Add to vvm the binary ^ and unary & operators.
*
* Dump events a bit more completely.
*
* Revision 1.2 1999/05/01 02:57:53 steve
* Handle much more complex event expressions.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/

View File

@ -1,134 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_signal.cc,v 1.9 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_signal.h"
# include <iostream.h>
vvm_bitset_t::vvm_bitset_t(vpip_bit_t*b, unsigned nb)
: bits(b), nbits(nb)
{
}
vvm_bitset_t::~vvm_bitset_t()
{
}
vpip_bit_t&vvm_bitset_t::operator[] (unsigned idx)
{
assert(idx < nbits);
return bits[idx];
}
vpip_bit_t vvm_bitset_t::operator[] (unsigned idx) const
{
assert(idx < nbits);
return bits[idx];
}
vpip_bit_t vvm_bitset_t::get_bit(unsigned idx) const
{
assert(idx < nbits);
return bits[idx];
}
unsigned vvm_bitset_t::as_unsigned() const
{
unsigned result = 0;
unsigned width = get_width();
for (unsigned idx = width ; idx > 0 ; idx -= 1) {
result <<= 1;
if (B_IS1(get_bit(idx-1)))
result |= 1;
}
return result;
}
vvm_signal_t::vvm_signal_t()
{
bits = 0;
nbits = 0;
}
vvm_signal_t::~vvm_signal_t()
{
}
void vvm_signal_t::init_P(unsigned idx, vpip_bit_t val)
{
assert(idx < nbits);
bits[idx] = val;
}
void vvm_signal_t::take_value(unsigned key, vpip_bit_t val)
{
assert(key < nbits);
bits[key] = val;
vpip_run_value_changes(this);
}
vvm_ram_callback::vvm_ram_callback()
{
}
vvm_ram_callback::~vvm_ram_callback()
{
}
/*
* $Log: vvm_signal.cc,v $
* Revision 1.9 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.8 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.7 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.6 2000/12/12 03:30:25 steve
* out-line vvm_bitset_t methods.
*
* Revision 1.5 2000/04/26 18:35:12 steve
* Handle assigning small values to big registers.
*
* Revision 1.4 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.3 2000/03/25 05:02:25 steve
* signal bits are referenced at run time by the vpiSignal struct.
*
* Revision 1.2 2000/03/17 20:21:14 steve
* Detemplatize the vvm_signal_t class.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/

View File

@ -1,169 +0,0 @@
#ifndef __vvm_vvm_signal_H
#define __vvm_vvm_signal_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_signal.h,v 1.13 2002/08/12 01:35:07 steve Exp $"
#endif
# include "vvm.h"
# include "vvm_nexus.h"
/*
* The vvm_bitset_t is a reference to an array of vpip_bit_t
* values. The space for the value is actually managed elsewhere, this
* object just references it, and attaches operations to it.
*
* The vvm_bitset_t is useful in behavioral situations, to operate on
* vpip_bit_t data vectors.
*/
class vvm_bitset_t {
public:
explicit vvm_bitset_t(vpip_bit_t*b, unsigned nb);
~vvm_bitset_t();
vpip_bit_t operator[] (unsigned idx) const;
vpip_bit_t&operator[] (unsigned idx);
unsigned get_width() const { return nbits; }
vpip_bit_t get_bit(unsigned idx) const;
unsigned as_unsigned() const;
public:
vpip_bit_t*bits;
unsigned nbits;
private: // not implemented
vvm_bitset_t(const vvm_bitset_t&);
vvm_bitset_t& operator= (const vvm_bitset_t&);
};
/*
* The vvm_signal_t template is the real object that handles the
* receiving of assignments and doing whatever is done. It also
* connects VPI to the C++/vvm design. The actual bits are referenced
* by the base vpiSignal structure.
*/
class vvm_signal_t : public __vpiSignal, public vvm_nexus::recvr_t {
public:
vvm_signal_t();
~vvm_signal_t();
void init_P(unsigned idx, vpip_bit_t val);
void take_value(unsigned key, vpip_bit_t val);
private: // not implemented
vvm_signal_t(const vvm_signal_t&);
vvm_signal_t& operator= (const vvm_signal_t&);
};
struct vvm_ram_callback {
vvm_ram_callback();
virtual ~vvm_ram_callback();
virtual void handle_write(unsigned idx) =0;
vvm_ram_callback*next_;
};
class vvm_memory_t : public __vpiMemory {
public:
vvm_memory_t();
void set_word(unsigned addr, const vvm_bitset_t&val);
void set_word(unsigned addr, const vpip_bit_t*val);
void get_word(unsigned addr, vvm_bitset_t&val) const;
void set_callback(vvm_ram_callback*ram);
class assign_nb : public vvm_event {
public:
assign_nb(vvm_memory_t&m, unsigned i, const vvm_bitset_t&v);
~assign_nb();
void event_function();
private:
vvm_memory_t&mem_;
unsigned index_;
vpip_bit_t*bits_;
vvm_bitset_t val_;
};
private:
vvm_ram_callback*cb_list_;
void call_list_(unsigned idx);
};
/*
* $Log: vvm_signal.h,v $
* Revision 1.13 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.12 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.11 2000/12/15 20:05:16 steve
* Fix memory access in vvm. (PR#70)
*
* Revision 1.10 2000/12/12 03:30:25 steve
* out-line vvm_bitset_t methods.
*
* Revision 1.9 2000/04/26 18:35:12 steve
* Handle assigning small values to big registers.
*
* Revision 1.8 2000/03/26 16:55:41 steve
* Remove the vvm_bits_t abstract class.
*
* Revision 1.7 2000/03/26 16:28:31 steve
* vvm_bitset_t is no longer a template.
*
* Revision 1.6 2000/03/25 05:02:25 steve
* signal bits are referenced at run time by the vpiSignal struct.
*
* Revision 1.5 2000/03/25 02:43:57 steve
* Remove all remain vvm_bitset_t return values,
* and disallow vvm_bitset_t copying.
*
* Revision 1.4 2000/03/24 02:43:37 steve
* vvm_unop and vvm_binop pass result by reference
* instead of returning a value.
*
* Revision 1.3 2000/03/22 04:26:41 steve
* Replace the vpip_bit_t with a typedef and
* define values for all the different bit
* values, including strengths.
*
* Revision 1.2 2000/03/17 20:21:14 steve
* Detemplatize the vvm_signal_t class.
*
* Revision 1.1 2000/03/16 19:03:04 steve
* Revise the VVM backend to use nexus objects so that
* drivers and resolution functions can be used, and
* the t-vvm module doesn't need to write a zillion
* output functions.
*
*/
#endif

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_thread.cc,v 1.9 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm.h"
# include "vvm_thread.h"
class delay_event : public vvm_event {
public:
delay_event(vvm_thread*thr) : thr_(thr) { }
void event_function()
{
while (thr_->step_(thr_))
/* empty */;
}
private:
vvm_thread*thr_;
};
vvm_thread::vvm_thread()
{
sync_next_ = 0;
sync_back_ = 0;
callee_ = 0;
back_ = 0;
}
vvm_thread::~vvm_thread()
{
}
void vvm_thread::thread_yield(unsigned long delay)
{
delay_event*ev = new delay_event(this);
ev -> schedule(delay);
}
/*
* $Log: vvm_thread.cc,v $
* Revision 1.9 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.8 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.7 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.6 2000/04/14 23:31:53 steve
* No more class derivation from vvm_thread.
*
* Revision 1.5 2000/04/12 01:53:07 steve
* Multiple thread can block on an event.
*
* Revision 1.4 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.3 2000/01/06 05:56:23 steve
* Cleanup and some asserts.
*
* Revision 1.2 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/

View File

@ -1,139 +0,0 @@
#ifndef __vvm_thread_H
#define __vvm_thread_H
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_thread.h,v 1.11 2002/08/12 01:35:07 steve Exp $"
#endif
# include "vvm.h"
/*
* A vvm_thread isn't really a thread in the POSIX sense, but a
* representation of the verilog thread. It is implemented as a state
* machine that performs an action, and possibly changes state, every
* time the go method is called. The events and delays that cause a
* thread to block arrange for the go method to be called in the
* future.
*
* THREAD STEPS
* The basic blocks of an executing thread are implemented as C/C++
* functions that take a vvm_thread pointer and return a boolean. The
* thread keeps a pointer to the function that is the current step. It
* is the responsibility of each step to write into the step_ member
* the pointer to the next step, and that is how things like branching
* and looping work.
*
* A thread executes by calling the current step function. When the
* step function returns, it uses the bolean return code to tell the
* scheduler whether the next step should be executed. Thus, a thread
* can give other threads a chance to execute by returning false.
*
* CALLING CONVENTION
* There are a few members in the vvm_thread for supporting calling
* other threads. This is like a function call in other languages, as
* the calling thread blocks until the called thread(s) terminate. It
* is also like functions in that thread calls nest.
*
* A thread is called by creating a new vvm_thread and saving a
* pointer to the new thread in the callee_ member of the calling
* thread. The called thread gets its back_ pointer set to that of the
* calling thread. The new thread is then activated with a call to its
* thread_yield() method, and the caller thread pauses by returning
* from its step function with the value "false".
*
* When the called thread is ready to terminate, it uses its back_
* pointer to find the calling thread, and activates it with the
* thread_yield() method. Then, the called thread finishes by
* returning false from its step method.
*
* When the caller resumes executing, it knows that the called thread
* is done, so it uses the callee_ pointer to delete the now finished
* thread, and the process is finished.
*/
class vvm_sync;
class vvm_thread {
public:
explicit vvm_thread();
~vvm_thread();
void thread_yield(unsigned long delay =0);
// This method executes a setp of the thread. The engine will
// continue to call go as long as it returns true. The thread
// will return false if it is ready to give up the CPU.
bool (*step_)(vvm_thread*);
// These members are used to handle task invocations.
vvm_thread*callee_;
unsigned ncallee_;
vvm_thread*back_;
// The sync class uses this to list all the threads blocked on it.
vvm_sync*sync_back_;
vvm_thread*sync_next_;
struct __vpiScope*scope;
};
/*
* $Log: vvm_thread.h,v $
* Revision 1.11 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.10 2000/10/28 00:51:42 steve
* Add scope to threads in vvm, pass that scope
* to vpi sysTaskFunc objects, and add vpi calls
* to access that information.
*
* $display displays scope in %m (PR#1)
*
* Revision 1.9 2000/04/15 19:51:30 steve
* fork-join support in vvm.
*
* Revision 1.8 2000/04/15 01:44:59 steve
* Document the calling convention.
*
* Revision 1.7 2000/04/14 23:31:53 steve
* No more class derivation from vvm_thread.
*
* Revision 1.6 2000/04/12 01:53:07 steve
* Multiple thread can block on an event.
*
* Revision 1.5 2000/02/23 02:56:57 steve
* Macintosh compilers do not support ident.
*
* Revision 1.4 2000/01/06 05:56:23 steve
* Cleanup and some asserts.
*
* Revision 1.3 1999/12/12 19:47:54 steve
* Remove the useless vvm_simulation class.
*
* Revision 1.2 1998/11/10 00:48:31 steve
* Add support it vvm target for level-sensitive
* triggers (i.e. the Verilog wait).
* Fix display of $time is format strings.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*
*/
#endif

View File

@ -1,218 +0,0 @@
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_udp.cc,v 1.6 2002/08/12 01:35:07 steve Exp $"
#endif
# include "config.h"
# include "vvm_gates.h"
#ifdef UDP_DEBUG
#include <iostream>
#endif
vvm_udp_comb::vvm_udp_comb(unsigned w, const char*t)
: vvm_1bit_out(0), width_(w), table_(t)
{
ibits_ = new char[width_];
obit_ = 'x';
}
vvm_udp_comb::~vvm_udp_comb()
{
delete[]ibits_;
}
void vvm_udp_sequ1::init_I(unsigned idx, vpip_bit_t val)
{
vvm_udp_comb::init_I(idx, val);
}
void vvm_udp_comb::init_I(unsigned idx, vpip_bit_t val)
{
assert(idx < width_);
if (B_IS1(val))
ibits_[idx] = '1';
else if (B_IS0(val))
ibits_[idx] = '0';
else
ibits_[idx] = 'x';
}
void vvm_udp_sequ1::take_value(unsigned key, vpip_bit_t val)
{
assert(key < width_ - 1);
ibits_[0] = obit_;
vvm_udp_comb::take_value(key+1, val);
#ifdef UDP_DEBUG
static int max_deb = UDP_DEBUG;
if (max_deb>0)
if (--max_deb<1000)
cerr<<"sUDP(\""<<table_<<"\", \""<<ibits_<<"\")=\""<<obit_<<"\""<<endl;
#endif
}
void vvm_udp_comb::take_value(unsigned key, vpip_bit_t val)
{
char old_bit = ibits_[key];
init_I(key, val);
if (ibits_[key] == old_bit)
return;
for (const char*row = table_ ; row[0] ; row += width_+1) {
unsigned idx;
for (idx = 0 ; idx < width_ ; idx += 1)
{
char new_bit = ibits_[idx];
if (row[idx] != ibits_[idx]
&& row[idx] != '?'
&& (row[idx] != 'b' || new_bit == 'x')
&& (row[idx] != 'l' || new_bit == '1')
&& (row[idx] != 'h' || new_bit == '0') )
{
if (idx == key)
{
switch (row[idx])
{
case '*':
continue;
case '_':
if (new_bit == '0')
continue;
break;
case '+':
if (new_bit == '1')
continue;
break;
case '%':
if (new_bit == 'x')
continue;
break;
case 'B':
if (old_bit == 'x')
continue;
break;
case 'r':
if (old_bit=='0' && new_bit=='1')
continue;
break;
case 'R':
if (old_bit=='x' && new_bit=='1')
continue;
break;
case 'f':
if (old_bit=='1' && new_bit=='0')
continue;
break;
case 'F':
if (old_bit=='x' && new_bit=='0')
continue;
break;
case 'P':
if (old_bit=='0')
continue;
break;
case 'p':
if (old_bit=='0' || new_bit=='1')
continue;
break;
case 'N':
if (old_bit=='1')
continue;
break;
case 'n':
if (old_bit=='1' || new_bit=='0')
continue;
break;
case 'Q':
if (old_bit=='0' && new_bit=='x')
continue;
break;
case 'M':
if (old_bit=='1' && new_bit=='x')
continue;
break;
}
// bad edge
}
break; // bad edge/level
}
}
if (idx == width_)
{
if (row[width_] == '-'
|| row[width_] == obit_)
return;
obit_ = row[width_];
switch (obit_)
{
case '0':
output(St0);
return;
case '1':
output(St1);
return;
case 'z':
output(HiZ);
return;
default:
output(StX);
return;
}
}
}
if (obit_ != 'x')
{
output(StX);
obit_ = 'x';
}
}
/*
* $Log: vvm_udp.cc,v $
* Revision 1.6 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2001/07/25 03:10:51 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2001/06/18 00:51:23 steve
* Add more UDP edge types, and finish up compile
* and run-time support. (Stephan Boettcher)
*
* Revision 1.3 2001/04/22 23:09:46 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.2 2000/11/04 06:36:24 steve
* Apply sequential UDP rework from Stephan Boettcher (PR#39)
*
* Revision 1.1 2000/03/29 04:37:11 steve
* New and improved combinational primitives.
*
*/

View File

@ -1,47 +0,0 @@
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvm_vpi.cc,v 1.3 2002/08/12 01:35:07 steve Exp $"
#endif
#include <stdarg.h>
#include "vpi_user.h"
#include "vpithunk.h"
vpi_thunk vvmt;
void vvm_vpi_init()
{
vvmt.magic = VPI_THUNK_MAGIC;
vvmt.vpi_register_systf = vpi_register_systf;
vvmt.vpi_vprintf = vpi_vprintf;
vvmt.vpi_mcd_close = vpi_mcd_close;
vvmt.vpi_mcd_name = vpi_mcd_name;
vvmt.vpi_mcd_open = vpi_mcd_open;
vvmt.vpi_mcd_open_x = vpi_mcd_open_x;
vvmt.vpi_mcd_vprintf = vpi_mcd_vprintf;
vvmt.vpi_mcd_fputc = vpi_mcd_fputc;
vvmt.vpi_mcd_fgetc = vpi_mcd_fgetc;
vvmt.vpi_register_cb = vpi_register_cb;
vvmt.vpi_remove_cb = vpi_remove_cb;
vvmt.vpi_sim_vcontrol = vpi_sim_vcontrol;
vvmt.vpi_handle = vpi_handle;
vvmt.vpi_iterate = vpi_iterate;
vvmt.vpi_scan = vpi_scan;
vvmt.vpi_handle_by_index = vpi_handle_by_index;
vvmt.vpi_get_time = vpi_get_time;
vvmt.vpi_get = vpi_get;
vvmt.vpi_get_str = vpi_get_str;
vvmt.vpi_get_value = vpi_get_value;
vvmt.vpi_put_value = vpi_put_value;
vvmt.vpi_free_object= vpi_free_object;
vvmt.vpi_get_vlog_info = vpi_get_vlog_info;
}
/*
* $Log: vvm_vpi.cc,v $
* Revision 1.3 2002/08/12 01:35:07 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2002/08/11 23:47:05 steve
* Add missing Log and Ident strings.
*
*/