Compare commits

...
88 Commits
Author SHA1 Message Date
steve 2e279b61dd Update to 0.7 release. 2002-12-14 18:20:14 +00:00
steve 8ab909a765 Add vpi_handle_by_name to the VPI interface,
and bump the vpithunk magic number.
2002-12-11 23:55:22 +00:00
steve cca07fa42d Account for bison 1.35 and stack manipulations. 2002-12-10 05:49:51 +00:00
steve 5b81798205 install iverilog-vpi as a script. 2002-12-10 05:45:44 +00:00
steve a8a82df47d Prepare for 20021207 snapshot 2002-12-08 03:06:30 +00:00
steve e62e1d89b6 Named event triggers can take hierarchical names. 2002-12-07 02:49:24 +00:00
steve c032186133 Reword some error messages for clarity. 2002-12-06 03:08:19 +00:00
steve b89e138404 precalculate r-values of nb assignments and task arguments. 2002-12-05 04:15:14 +00:00
steve 9f80ed32b6 Support bit select in constant expressions. 2002-12-05 02:14:33 +00:00
steve c16a4a3950 distclean target. 2002-12-04 03:33:38 +00:00
steve 90fa90a508 Mingw32 compatible temp file management. 2002-12-04 03:26:59 +00:00
steve aaa734690f Use O_EXCL when opening temp files. 2002-12-04 02:29:36 +00:00
steve 88da7804c4 Improve the bad character error message. 2002-12-04 02:07:00 +00:00
steve 8604f922a5 specify delay can take an unbracketed simple value. 2002-11-26 03:56:10 +00:00
steve 807a758f7c Do not set width if width is already OK. 2002-11-26 03:35:13 +00:00
steve ef55086543 Support put of vpiStringVal to signals. 2002-11-25 23:33:45 +00:00
steve 2001903c89 Cygwin doesnot need driver-vpi sibdirectory. 2002-11-24 02:27:28 +00:00
steve 751e4e4c79 Fix instanceRef spelling. 2002-11-24 02:26:14 +00:00
steve 9d91b5db4c Document the Windows specific flags. 2002-11-23 00:51:53 +00:00
steve 9a3c9507ed Handle wide AND/NOR devices with Virtex carry logic. 2002-11-22 05:46:06 +00:00
steve d71d52bfe9 Implement bufif1 as BUFT 2002-11-22 01:45:40 +00:00
steve 8e30bc9f9e Careful of left operands to shift that are constant. 2002-11-22 00:01:50 +00:00
steve 412518d1ca Precalculate indices to l-value arrays. 2002-11-21 23:27:51 +00:00
steve 03afbf157b %set/x0 instruction to support bounds checking. 2002-11-21 22:43:13 +00:00
steve 00b2d467e4 Allow right values of right shift to shift in. 2002-11-21 22:42:48 +00:00
steve 856829d299 Fix const test of msb in assignment l-values. 2002-11-21 18:15:40 +00:00
steve 2fafe6866f Better handling of select width of shifters. 2002-11-21 18:08:09 +00:00
steve b9188ad0ca PATHPULSE specparam assignment syntax. 2002-11-21 17:40:11 +00:00
steve 0ccb9139c9 Magnitude compare to 0. 2002-11-17 23:37:55 +00:00
steve 18e402ddc8 Close old file if $dumpfile is called again. 2002-11-17 22:28:42 +00:00
steve b82d3165da Update version strings in spec flie. 2002-11-17 18:38:03 +00:00
steve 91580d1fcc Generate unique labels for force functors. 2002-11-17 18:31:09 +00:00
steve 35d7384903 Handle default: case in net_inputs for NetCase. 2002-11-16 05:45:41 +00:00
steve 4539632f34 Add vpiScope iterate on vpiScope objects. 2002-11-15 22:14:12 +00:00
steve 0651f246b2 Save vpiFullName results. 2002-11-14 22:43:58 +00:00
steve 6d0dee9341 Add version resources to the Windows binary. 2002-11-13 17:25:10 +00:00
steve c692f1708c Allow -mingw and -ivl flags to stand alone. 2002-11-13 17:03:49 +00:00
steve d91733d32c Spell the iverilog-vpi target correctly. 2002-11-13 16:57:25 +00:00
steve cd7378ff3f Do not truncate high bits of right shift. 2002-11-13 03:03:08 +00:00
steve c98ce4a029 Add Windows version of iverilog-vpi. 2002-11-13 01:50:11 +00:00
steve d035a7e92c spelling error. 2002-11-13 01:49:43 +00:00
steve 6db6359363 Update Solaris packaging to to realities. 2002-11-11 15:49:03 +00:00
steve 5c07a29e46 Install sqrt-virtex.v under Windows. 2002-11-11 01:12:41 +00:00
steve 42d9094e9b Snapshot 20021109 2002-11-09 23:41:15 +00:00
steve 1742231eba Handle nested-if chip enables. 2002-11-09 23:29:29 +00:00
steve 3178f886b7 XNF target uses only legacy functors. 2002-11-09 23:29:02 +00:00
steve cbc4a0ab52 Detect synthesis conflicts blocks statements share outputs. 2002-11-09 20:22:57 +00:00
steve cfd8cbf850 Port expressions for output ports are lnets, not nets. 2002-11-09 19:20:48 +00:00
steve 013b18b3dc leading underscore test for Windows more robust. 2002-11-09 06:03:57 +00:00
steve db9f20b21a Macos install notes. 2002-11-09 06:03:38 +00:00
steve f611260089 display octal escapes properly. 2002-11-09 06:01:11 +00:00
steve e34e3a4875 spelling in a comment. 2002-11-09 02:22:07 +00:00
steve aa8869a3c7 Postpone parameter width check to evaluation. 2002-11-09 01:40:19 +00:00
steve 588931fcf2 Add dup_expr for user defined function calls. 2002-11-09 00:25:27 +00:00
steve 07e49e215e Use the vectorized %assign where appropriate. 2002-11-08 05:00:31 +00:00
steve 1b84893ccb Add the %assign/v0 instruction. 2002-11-08 04:59:57 +00:00
steve 6445bb6915 Handle comments in suppressed code. 2002-11-08 00:04:16 +00:00
steve db899bd1b5 Use Vector %set to set constants in variables. 2002-11-07 05:19:55 +00:00
steve c6dcc38fe0 Vectorize load from REG variables. 2002-11-07 03:12:17 +00:00
steve b0a7909162 functor_set takes bit and strength, not 2 strengths. 2002-11-07 03:11:43 +00:00
steve d7ae85a13a Add vector set and load instructions. 2002-11-07 02:32:39 +00:00
steve 46ee38b466 Concatenation can evaluate sub-expressions in place. 2002-11-06 05:41:37 +00:00
steve bc6a958a50 More reliable iverilog.conf install dependency. 2002-11-06 03:42:40 +00:00
steve 0e751ad975 More forgiving about assignment rval width mismatch. 2002-11-06 03:22:28 +00:00
steve de94d09706 No need to keep excess width from an
unsigned constant value, if it can
 be trimmed safely.
2002-11-06 02:25:13 +00:00
steve 2f88a631df Run output with the vvp command. 2002-11-05 03:49:21 +00:00
steve 4e5dd49a37 Fix mask calculate when MOV_b is right on the word boundary. 2002-11-05 03:46:44 +00:00
steve 8463dcc878 ignore parse.output 2002-11-05 02:19:37 +00:00
steve 18bc2f65b3 Misspelled name. 2002-11-05 02:18:53 +00:00
steve b4e8ea5a0c Install shared objects as programs, not data. 2002-11-05 02:14:41 +00:00
steve 06a8087cb5 Do not need _leading underscore on Windows. 2002-11-05 02:14:16 +00:00
steve a9dfef0f55 Fix the call to FormatMessage under Windows. 2002-11-05 02:12:35 +00:00
steve e4540c3d0d Better error message for load failure on Windows. 2002-11-05 02:11:56 +00:00
steve 0cc8396244 Cast for gcc convenience. 2002-11-03 22:44:19 +00:00
steve 946693ad4d New output files from new bison. 2002-11-03 20:50:33 +00:00
steve f014d4c533 Update instructions, now that Cygwin handles X:/path strings. 2002-11-03 20:49:57 +00:00
steve 6a1e3f7e27 Slightly more verbose load fail message. 2002-11-03 20:47:23 +00:00
steve 7ad66b0725 Support old/new bison yylloc. 2002-11-03 20:36:53 +00:00
steve 0341c0c727 Error message for mising code generator type. 2002-11-03 20:36:10 +00:00
steve 20c8550139 Compiler error wrt ptrdiff_t. 2002-11-03 20:33:43 +00:00
steve 39aa90ce59 Snapshot 20021102 2002-11-03 02:12:00 +00:00
steve 6c67a64fc3 Get VectorVals from constant values. 2002-11-03 02:07:24 +00:00
steve 86032c0aa5 Allow named events to be referenced by
hierarchical names.
2002-11-02 03:27:51 +00:00
steve f243f694b4 Detect memories without work index in l-value. 2002-11-02 01:10:49 +00:00
steve 276ae3e228 Add the sqrt-virtex example. 2002-11-01 03:29:43 +00:00
steve fe6756eb07 Fix bottom bit of ADD/SUB device. 2002-11-01 02:36:34 +00:00
steve 539e494bc0 Give nets better names, if available. 2002-11-01 02:36:22 +00:00
steve 1298656c22 Fix up left shift to pass compile,
fix up ADD/SUB to generate missing pieces,
 Add the asynch set/reset to DFF devices.
2002-10-30 03:58:45 +00:00
72 changed files with 3051 additions and 514 deletions
+4
View File
@@ -2,10 +2,14 @@ lexor_keyword.cc
parse.h
parse.cc
parse.cc.output
parse.output
syn-rules.cc
syn-rules.cc.output
syn-rules.output
lexor.cc
iverilog-vpi
iverilog-vpi.pdf
iverilog-vpi.ps
ivl
ivl.exp
dep
+10 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.cc,v 1.4 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: HName.cc,v 1.5 2002/11/02 03:27:52 steve Exp $"
#endif
# include "config.h"
@@ -75,6 +75,11 @@ hname_t::~hname_t()
}
}
unsigned hname_t::component_count() const
{
return count_;
}
void hname_t::append(const char*text)
{
char**tmp;
@@ -253,6 +258,10 @@ ostream& operator<< (ostream&out, const hname_t&that)
/*
* $Log: HName.cc,v $
* Revision 1.5 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.4 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+9 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.h,v 1.3 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
#endif
# include <iostream>
@@ -61,6 +61,10 @@ class hname_t {
const char*peek_name(unsigned idx) const;
const char*peek_tail_name() const;
// Return the number of components in the hierarchical
// name. If this is a simple name, this will return 1.
unsigned component_count() const;
friend ostream& operator<< (ostream&, const hname_t&);
private:
@@ -79,6 +83,10 @@ extern bool operator == (const hname_t&, const hname_t&);
/*
* $Log: HName.h,v $
* Revision 1.4 2002/11/02 03:27:51 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+16 -5
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.134 2002/09/16 00:30:33 steve Exp $"
#ident "$Id: Makefile.in,v 1.140 2002/12/10 05:45:44 steve Exp $"
#
#
SHELL = /bin/sh
@@ -25,7 +25,7 @@ SHELL = /bin/sh
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well.
VERSION = 0.6
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -83,6 +83,10 @@ all: dosify.exe
dosify.exe: dosify.c
$(CC) -o dosify.exe dosify.c
ifeq (@MINGW32@,yes)
SUBDIRS += driver-vpi
endif
else
all: iverilog-vpi
endif
@@ -216,7 +220,7 @@ INSTALL_DOCDIR = $(mandir)/man1
endif
ifeq (@WIN32@,yes)
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
else
WIN32_INSTALL = $(bindir)/iverilog-vpi
endif
@@ -229,7 +233,7 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
$(bindir)/iverilog-vpi: ./iverilog-vpi
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
$(libdir)/libvpi.a : ./libvpi.a
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
@@ -238,7 +242,10 @@ $(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
$(libdir)/ivl/iverilog.conf: $(srcdir)/iverilog.conf
# Install iverilog.conf whenever ivl.exe is installed. This
# forces iverilog.conf to be treated similarly, in spite of
# dates in the source bundle.
$(libdir)/ivl/iverilog.conf: $(libdir)/ivl/ivl@EXEEXT@
$(INSTALL_DATA) $(srcdir)/iverilog.conf $(libdir)/ivl/iverilog.conf
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
@@ -270,6 +277,10 @@ $(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
mv tmp.vl $(prefix)/sqrt.vl
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
mv tmp.vl $(prefix)/sqrt-virtex.v
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
mv tmp.txt $(prefix)/QUICK_START.txt
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.cc,v 1.31 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: PExpr.cc,v 1.32 2002/11/09 19:20:48 steve Exp $"
#endif
# include "config.h"
@@ -46,7 +46,7 @@ bool PExpr::is_constant(Module*) const
return false;
}
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
{
cerr << get_line() << ": error: expression not valid in assign l-value: "
<< *this << endl;
@@ -256,6 +256,9 @@ bool PEUnary::is_constant(Module*m) const
/*
* $Log: PExpr.cc,v $
* Revision 1.32 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.31 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
+10 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.62 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: PExpr.h,v 1.63 2002/11/09 19:20:48 steve Exp $"
#endif
# include <string>
@@ -80,7 +80,8 @@ class PExpr : public LineInfo {
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method.
@@ -126,7 +127,8 @@ class PEConcat : public PExpr {
// continuous assignments.
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
@@ -216,7 +218,8 @@ class PEIdent : public PExpr {
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
// Identifiers are also allowed as procedural assignment l-values.
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
@@ -501,6 +504,9 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
* Revision 1.63 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.62 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+11
View File
@@ -396,6 +396,17 @@ language that are defined.
Icarus Verilog will override the $timeformat minimum width and
use the explicit minimum width.
vpiScope iterator on vpiScope objects.
In the VPI, the normal way to iterate over vpiScope objects
contained within a vpiScope object, is the vpiInternalScope
iterator. Icarus Verilog adds support for the vpiScope
iterator of a vpiScope object, that iterates over *everything*
the is contained in the current scope. This is useful in cases
where one wants to iterate over all the objects in a scope
without iterating over all the contained types explicitly.
6.0 CREDITS
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
+4 -2
View File
@@ -190,6 +190,8 @@ if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
then
WIN32=yes
fi
AC_SUBST(MINGW32)
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
AC_SUBST(EXEEXT)
@@ -206,7 +208,7 @@ CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -o $WIN32 = "yes"; then
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
@@ -255,4 +257,4 @@ AC_MSG_RESULT($ident_support)
AC_CONFIG_SUBDIRS(vvp tgt-vvp tgt-fpga libveriuser)
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
+2
View File
@@ -0,0 +1,2 @@
Makefile
iverilog-vpi.exe
+82
View File
@@ -0,0 +1,82 @@
#
# 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.
#
# 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.5 2002/12/08 03:06:30 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
mandir = @mandir@
dllib=@DLLIB@
CC = @CC@
CXX = @CXX@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"'
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)/..
LDFLAGS = @LDFLAGS@
all: iverilog-vpi@EXEEXT@
clean:
rm -f *.o
rm -f iverilog-vpi@EXEEXT@
distclean: clean
rm -f Makefile
O = main.o res.o
iverilog-vpi@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
main.o: main.c
$(CC) $(CFLAGS) -c $(srcdir)/main.c
# Windows specific...
res.o: res.rc
windres -i res.rc -o res.o
#
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(bindir)
uninstall:
rm -f $(bindir)/iverilog-vpi@EXEEXT@
+565
View File
@@ -0,0 +1,565 @@
/*
* Copyright (c) 2002 Gus Baldauf ([email protected])
*
* 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
*/
/*
* iverilog-vpi.c
*
* this program provides the functionality of iverilog-vpi.sh under Win32
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
/* Macros used for compiling and linking */
#define IVERILOG_VPI_CC "gcc" /* no .exe extension */
#define IVERILOG_VPI_CXX "gcc" /* no .exe extension */
#define IVERILOG_VPI_CFLAGS "-O" /* -I appended later */
#define IVERILOG_VPI_LD "gcc" /* no .exe extension */
#define IVERILOG_VPI_LDFLAGS "-shared -Wl,--enable-auto-image-base"
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi" /* -L prepended later */
/* pointers to global strings */
static struct global_strings {
char *pCCSRC; /* list of C source files */
char *pCXSRC; /* list of C++ source files */
char *pOBJ; /* list of object files */
char *pLIB; /* list of library files */
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
char *pMINGW; /* path to MinGW directory */
char *pIVL; /* path to IVL directory */
char *pCFLAGS; /* CFLAGS option */
char *pLDLIBS; /* LDLIBS option */
char *pNewPath; /* new PATH environment variable setting */
} gstr;
static void deInitDynString(char *str)
{
free(str);
}
/* when finished, free allocated memory and return error code */
static void myExit(int exitVal)
{
deInitDynString(gstr.pCCSRC);
deInitDynString(gstr.pCXSRC);
deInitDynString(gstr.pOBJ);
deInitDynString(gstr.pLIB);
deInitDynString(gstr.pOUT);
deInitDynString(gstr.pMINGW);
deInitDynString(gstr.pIVL);
deInitDynString(gstr.pCFLAGS);
deInitDynString(gstr.pLDLIBS);
deInitDynString(gstr.pNewPath);
exit(exitVal);
}
/* display usage summary and exit */
static void usage()
{
fprintf(stderr,"usage: iverilog-vpi [--name=name] [-llibrary] [-mingw=dir] [-ivl=dir] sourcefile...\n");
fprintf(stderr," or iverilog-vpi -mingw=dir\n");
fprintf(stderr," or iverilog-vpi -ivl=dir\n");
myExit(1);
}
static void initDynString(char **str)
{
*str = (char *) malloc(1);
if (!*str) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
*str[0] = 0;
}
/* initialize dynamic memory buffers */
static void init()
{
initDynString(&gstr.pCCSRC);
initDynString(&gstr.pCXSRC);
initDynString(&gstr.pOBJ);
initDynString(&gstr.pLIB);
initDynString(&gstr.pOUT);
initDynString(&gstr.pMINGW);
initDynString(&gstr.pIVL);
initDynString(&gstr.pCFLAGS);
initDynString(&gstr.pLDLIBS);
initDynString(&gstr.pNewPath);
}
/* return true if "str" is terminated with with "end", case insensitive */
static int endsIn (char *end, char *str)
{
char *ext;
if (strlen(end) >= strlen(str))
return 0;
ext = str + (strlen(str) - strlen(end));
return stricmp(end,ext) ? 0 : 1;
}
/* return true if "str" begins with "prefix", case insensitive */
static int startsWith (char *prefix, char *str)
{
if (strlen(prefix) >= strlen(str))
return 0;
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
}
/* append "app" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "app" */
static void appendn (char **ptr, char *app, int count)
{
*ptr = (char *) realloc(*ptr,strlen(*ptr)+(count?count:strlen(app))+1);
if (*ptr == NULL) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
if (count)
strncat(*ptr,app,count);
else
strcat(*ptr,app);
}
/* append "app" to "ptr", allocating memory as needed */
static void append (char **ptr, char *app)
{
appendn(ptr,app,0);
}
/* if the string does not end with a backslash, add one */
static void appendBackSlash(char **str)
{
if ((*str)[strlen(*str)-1] != '\\')
append(str,"\\");
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "str" */
static void assignn (char **ptr, char *str, int count)
{
*ptr = (char *) realloc(*ptr,(count?count:strlen(str))+1);
if (*ptr == NULL) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
if (count) {
strncpy(*ptr,str,count);
(*ptr)[count] = 0;
}
else
strcpy(*ptr,str);
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
static void assign (char **ptr, char *str)
{
assignn(ptr,str,0);
}
/* get a copy of a Icarus Verilog registry string key */
static int GetRegistryKey(char *key, char **value)
{
long lrv;
HKEY hkKey;
char *regKeyBuffer;
DWORD regKeyType, regKeySize;
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
if (lrv != ERROR_SUCCESS)
return 0;
lrv = RegQueryValueEx(hkKey,key,NULL,&regKeyType,NULL,&regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
return 0;
}
regKeyBuffer = (char *) malloc(regKeySize+1);
if (!regKeyBuffer) {
lrv = RegCloseKey(hkKey);
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
lrv = RegQueryValueEx(hkKey,key,NULL,&regKeyType,regKeyBuffer,&regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
free(regKeyBuffer);
return 0;
}
RegCloseKey(hkKey);
assign(value,regKeyBuffer);
free(regKeyBuffer);
return 1;
}
/* store a copy of a Icarus Verilog registry string key */
static void SetRegistryKey(char *key, char *value)
{
HKEY hkKey;
DWORD res;
if (RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
"Software\\Icarus Verilog",
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,NULL,
&hkKey,
&res) != ERROR_SUCCESS)
return;
RegSetValueEx(hkKey,key,0,REG_SZ,value,strlen(value)+1);
RegCloseKey(hkKey);
printf("info: storing %s in Windows' registry entry\n",value);
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
}
/* parse the command line, assign results to global variable strings */
static int parse(int argc, char *argv[])
{
int idx, srcFileCnt=0;
char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc";
char dot_o_ext[] = ".o";
char name_option[] = "--name=";
char lib_option[] = "-l";
char mingw_option[] = "-mingw=";
char ivl_option[] = "-ivl=";
if (argc == 1)
return 0;
for (idx=1; idx<argc; ++idx) {
if (endsIn(dot_c_ext,argv[idx])) { /* check for C source files */
++srcFileCnt;
append(&gstr.pCCSRC,argv[idx]);
append(&gstr.pCCSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_c_ext));
}
else if (endsIn(dot_cc_ext,argv[idx])) { /* check for C++ source files */
++srcFileCnt;
append(&gstr.pCXSRC,argv[idx]);
append(&gstr.pCXSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
}
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
++srcFileCnt;
append(&gstr.pOBJ,argv[idx]);
append(&gstr.pOBJ," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_o_ext));
}
else if (startsWith(name_option,argv[idx])) { /* check for --name option */
assignn(&gstr.pOUT,argv[idx]+sizeof(name_option)-1,strlen(argv[idx])-(sizeof(name_option)-1));
}
else if (startsWith(lib_option,argv[idx])) { /* check for -l option */
append(&gstr.pLIB,argv[idx]);
append(&gstr.pLIB," ");
}
else if (startsWith(mingw_option,argv[idx])) /* check for -mingw option */
assignn(&gstr.pMINGW,argv[idx]+sizeof(mingw_option)-1,strlen(argv[idx])-(sizeof(mingw_option)-1));
else if (startsWith(ivl_option,argv[idx])) /* check for -ivl option */
assignn(&gstr.pIVL,argv[idx]+sizeof(ivl_option)-1,strlen(argv[idx])-(sizeof(ivl_option)-1));
else
return 0; /* different from iverilog-vpi.sh, we don't ignore accept arguments */
}
if (0 == srcFileCnt)
assign(&gstr.pOUT,""); /* in case they used --name with no source files */
if (!*gstr.pOUT) { /* normally it's an error if there are no *.c,*.cc,*.o files */
if (!*gstr.pMINGW && !*gstr.pIVL) /* unless they are just setting the IVL or MinGW registry entries */
usage();
}
else {
append(&gstr.pOUT,".vpi"); /* the result file should have a .vpi extension */
append(&gstr.pOUT," ");
}
return 1;
}
/* do minimal check that the MinGW root directory looks valid */
static void checkMingwDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path;
initDynString(&path);
assign(&path,gstr.pMINGW);
appendBackSlash(&path);
append(&path,"bin\\" IVERILOG_VPI_CC ".exe");
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\\\mingw\n");
myExit(5);
}
}
/* do minimal check that the Icarus Verilog root directory looks valid */
static void checkIvlDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path;
initDynString(&path);
assign(&path,gstr.pIVL);
appendBackSlash(&path);
append(&path,"bin\\vvp.exe");
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\\\iverilog\n");
myExit(6);
}
}
/* see if we can find mingw root */
#define IVL_REGKEY_MINGW "MingwDir"
static void setup_mingw_environment()
{
char *pOldPATH = getenv("PATH"); /* get current path */
if (*gstr.pMINGW) {
checkMingwDir(gstr.pMINGW);
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
}
else
if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
fprintf(stderr," a Windows command shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
myExit(5);
}
assign(&gstr.pNewPath,"PATH="); /* create new path */
append(&gstr.pNewPath,gstr.pMINGW);
appendBackSlash(&gstr.pNewPath);
append(&gstr.pNewPath,"bin;");
append(&gstr.pNewPath,pOldPATH);
_putenv(gstr.pNewPath); /* place new path in environment variable */
}
/* see if we can find iverilog root */
#define IVL_REGKEY_IVL "InstallDir"
static void setup_ivl_environment()
{
if (*gstr.pIVL) {
checkIvlDir(gstr.pIVL);
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
}
else
if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\n");
fprintf(stderr," For a Windows command shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
myExit(6);
}
/* build up the CFLAGS option string */
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS);
append(&gstr.pCFLAGS," -I");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"include");
/* build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L");
append(&gstr.pLDLIBS,gstr.pIVL);
appendBackSlash(&gstr.pLDLIBS);
append(&gstr.pLDLIBS,"lib ");
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
}
/* compile source modules */
static void compile(char *pSource, char **pObject, char *ext, int *compile_errors, char *compiler)
{
char *ptr1 = pSource;
char *ptr2 = strchr(pSource,' ');
char *buf=0,*src=0,*obj=0;
while (ptr2) {
int len = ptr2 - ptr1;
assignn(&src,ptr1,len);
assignn(&obj,ptr1,len-strlen(ext)); /* strip off the extension */
append (&obj,".o");
assign (&buf,compiler);
append (&buf," -c -o ");
append (&buf,obj);
append (&buf," ");
append (&buf,gstr.pCFLAGS);
append (&buf," ");
append (&buf,src);
append (pObject,obj);
append (pObject," ");
printf("%s\n",buf);
if (system(buf))
++*compile_errors;
ptr1 = ptr2 + 1; /* advance to next token */
ptr2 = strchr(ptr1,' ');
}
free(buf);
free(src);
free(obj);
}
/* using the global strings, compile and link */
static void compile_and_link()
{
char *buf=0;
int iRet, compile_errors = 0;
/* print out the mingw and ivl directories to help the user debug problems */
printf("info: %s will be used as the MinGW root directory.\n",gstr.pMINGW);
checkMingwDir(gstr.pMINGW);
printf("info: %s will be used as the Icarus Verilog root directory.\n",gstr.pIVL);
checkIvlDir(gstr.pIVL);
/* compile */
compile(gstr.pCCSRC,&gstr.pOBJ,".c" ,&compile_errors,IVERILOG_VPI_CC ); /* compile the C source files */
compile(gstr.pCXSRC,&gstr.pOBJ,".cc",&compile_errors,IVERILOG_VPI_CXX); /* compile the C++ source files */
if (compile_errors) {
fprintf(stderr,"iverilog-vpi: Some %d files failed to compile.\n",compile_errors);
myExit(2);
}
/* link */
assign(&buf,IVERILOG_VPI_LD);
append(&buf," -o ");
append(&buf,gstr.pOUT); /* has a trailing space */
append(&buf,IVERILOG_VPI_LDFLAGS);
append(&buf," ");
append(&buf,gstr.pOBJ) /* has a trailing space */;
append(&buf,gstr.pLIB); /* has a trailing space */
append(&buf,gstr.pLDLIBS);
printf("%s\n",buf);
iRet = system(buf);
free(buf);
if (iRet)
myExit(3);
}
/* program execution starts here */
int main(int argc, char *argv[])
{
init();
if (!parse(argc,argv))
usage();
setup_mingw_environment();
setup_ivl_environment();
if (*gstr.pOUT) /* are there any *.c,*.cc,*.o files specified */
compile_and_link();
myExit(0);
}
+38
View File
@@ -0,0 +1,38 @@
// LANGUAGE ENGLISH
LANGUAGE 9, 4
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
1 VERSIONINFO
FILEVERSION 2002,11,13,0
PRODUCTVERSION 0,7,0,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x2L
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Icarus Verilog\0"
VALUE "FileDescription", "Icarus Veriog VPI Tool\0"
VALUE "FileVersion", "2002, 11, 13, 0\0"
VALUE "InternalName", "iverilog-vpi\0"
VALUE "LegalCopyright", "Copyright 2002 Gus Baldauf\0"
VALUE "OriginalFilename", "iverilog-vpi.exe\0"
VALUE "ProductName", "Icarus Verilog\0"
VALUE "ProductVersion", "0, 7, 0, 0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
+3 -5
View File
@@ -3,9 +3,7 @@
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,12 +16,12 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.15 2002/08/10 22:36:59 steve Exp $"
#ident "$Id: Makefile.in,v 1.16 2002/12/08 03:06:30 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.6
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
+37 -2
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: main.c,v 1.47 2002/08/12 01:27:48 steve Exp $"
#ident "$Id: main.c,v 1.49 2002/12/04 03:26:59 steve Exp $"
# include "config.h"
@@ -119,6 +119,35 @@ char tmp[MAXSIZE];
static char ivl_root[MAXSIZE];
#ifdef __MINGW32__
# include <io.h>
# include <fcntl.h>
static FILE*fopen_safe(const char*path)
{
FILE*file = 0;
int fd;
fd = _open(path, _O_WRONLY|_O_CREAT|_O_EXCL, 0700);
if (fd != -1)
file = _fdopen(fd, "w");
return file;
}
#else
# include <fcntl.h>
static FILE*fopen_safe(const char*path)
{
FILE*file = 0;
int fd;
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0700);
if (fd != -1)
file = fdopen(fd, "w");
return file;
}
#endif
static const char*my_tempfile(const char*str, FILE**fout)
{
FILE*file;
@@ -148,7 +177,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
while ((retry > 0) && (file == NULL)) {
unsigned code = rand();
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
file = fopen(pathbuf, "w");
file = fopen_safe(pathbuf);
retry -= 1;
}
@@ -657,6 +686,12 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.49 2002/12/04 03:26:59 steve
* Mingw32 compatible temp file management.
*
* Revision 1.48 2002/12/04 02:29:36 steve
* Use O_EXCL when opening temp files.
*
* Revision 1.47 2002/08/12 01:27:48 steve
* Escape the backslash in the windows file name.
*
+20 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 Stephen Williams ([email protected])
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.8 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: dup_expr.cc,v 1.9 2002/11/09 00:25:27 steve Exp $"
#endif
# include "config.h"
@@ -65,6 +65,21 @@ NetETernary* NetETernary::dup_expr() const
return tmp;
}
NetEUFunc* NetEUFunc::dup_expr() const
{
NetEUFunc*tmp;
svector<NetExpr*> tmp_parms (parms_.count());
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
assert(parms_[idx]);
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(func_, result_->dup_expr(), tmp_parms);
return tmp;
}
NetEUnary* NetEUnary::dup_expr() const
{
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
@@ -74,6 +89,9 @@ NetEUnary* NetEUnary::dup_expr() const
/*
* $Log: dup_expr.cc,v $
* Revision 1.9 2002/11/09 00:25:27 steve
* Add dup_expr for user defined function calls.
*
* Revision 1.8 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
@@ -97,12 +115,5 @@ NetEUnary* NetEUnary::dup_expr() const
* Revision 1.3 2000/05/04 03:37:58 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.2 2000/02/23 02:56:54 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
*/
+45 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_lval.cc,v 1.20 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.23 2002/11/21 23:27:51 steve Exp $"
#endif
# include "config.h"
@@ -170,16 +170,20 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
verinum*vl = lsb_->eval_const(des, scope);
if (vl == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant: "
<< *lsb_;
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return 0;
}
verinum*vm = msb_->eval_const(des, scope);
if (vl == 0) {
if (vm == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant: "
<< *msb_;
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return 0;
}
@@ -277,12 +281,38 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
{
if (msb_ == 0) {
cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index."
<< endl;
des->errors += 1;
return 0;
}
if (msb_ && lsb_) {
cerr << get_line() << ": error: Cannot use part select on "
<< "memory \"" << mem->name() << ".\"" << endl;
des->errors += 1;
return 0;
}
assert(msb_ && !lsb_);
NetExpr*ix = msb_->elaborate_expr(des, scope);
if (ix == 0)
return 0;
/* Evaluate the memory index expression down as must as
possible. Ideally, we can get it down to a constant. */
if (! dynamic_cast<NetEConst*>(ix)) {
NetExpr*tmp = ix->eval_tree();
if (tmp) {
tmp->set_line(*ix);
delete ix;
ix = tmp;
}
}
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
lv->set_part(0, mem->width());
@@ -299,6 +329,15 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.23 2002/11/21 23:27:51 steve
* Precalculate indices to l-value arrays.
*
* Revision 1.22 2002/11/21 18:15:40 steve
* Fix const test of msb in assignment l-values.
*
* Revision 1.21 2002/11/02 01:10:49 steve
* Detect memories without work index in l-value.
*
* Revision 1.20 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+91 -14
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.101 2002/09/18 04:29:55 steve Exp $"
#ident "$Id: elab_net.cc,v 1.103 2002/12/06 03:08:19 steve Exp $"
#endif
# include "config.h"
@@ -1437,11 +1437,70 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
return osig;
}
/*
* The concatenation is also OK an an l-value. This method elaborates
* it as a structural l-value.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
{
assert(scope);
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned errors = 0;
if (repeat_) {
cerr << get_line() << ": sorry: I do not know how to"
" elaborate repeat concatenation nets." << endl;
return 0;
}
/* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
implicit_net_ok);
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
}
/* If any of the sub expressions failed to elaborate, then
delete all those that did and abort myself. */
if (errors) {
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (nets[idx]) delete nets[idx];
}
des->errors += 1;
return 0;
}
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list. */
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
NetNet::IMPLICIT, pins);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
}
osig->local_flag(true);
return osig;
}
/*
* Identifiers in continuous assignment l-values are limited to wires
* and that ilk. Detect registers and memories here and report errors.
*/
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
{
string path = scope->name();
@@ -1455,29 +1514,41 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
return 0;
}
cerr << get_line() << ": error: Net " << path_
<< " is not defined in this context." << endl;
cerr << get_line() << ": : Do you mean this? wire "
<< path_ << " = <expr>;" << endl;
return 0;
if (implicit_net_ok && !error_implicit) {
sig = new NetNet(scope, scope->name()+"."+path_.peek_name(0),
NetNet::IMPLICIT, 1);
if (warn_implicit) {
cerr << get_line() << ": warning: implicit "
"definition of wire " << scope->name()
<< "." << path_.peek_name(0) << "." << endl;
}
} else {
cerr << get_line() << ": error: Net " << path_
<< " is not defined in this context." << endl;
cerr << get_line() << ": : Do you mean this? wire "
<< path_ << " = <expr>;" << endl;
return 0;
}
}
assert(sig);
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_line() << ": error: registers (" << sig->name()
<< ") cannot be l-values in continuous"
cerr << get_line() << ": error: reg " << sig->name()
<< "; cannot be an L-value in continuous"
<< " assignments." << endl;
return 0;
}
if (sig->port_type() == NetNet::PINPUT) {
cerr << get_line() << ": warning: assign l-value ``"
<< sig->name() << "'' is also an input to "
<< sig->scope()->name() << "." << endl;
cerr << sig->get_line() << ": warning: input ``"
<< sig->name() << "'' is coerced to inout." << endl;
cerr << get_line() << ": warning: L-value ``"
<< sig->name() << "'' is also an input port." << endl;
cerr << sig->get_line() << ": warning: input "
<< sig->name() << "; is coerced to inout." << endl;
sig->port_type(NetNet::PINOUT);
}
@@ -2207,6 +2278,12 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.103 2002/12/06 03:08:19 steve
* Reword some error messages for clarity.
*
* Revision 1.102 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.101 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
+24 -12
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_pexpr.cc,v 1.16 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.18 2002/12/05 02:14:33 steve Exp $"
#endif
# include "config.h"
@@ -108,11 +108,6 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
<< *ex << endl;
des->errors += 1;
} else if (ex->expr_width() == 0) {
cerr << ex->get_line() << ": internal error: "
<< "Operand of concatenation has no width: "
<< *ex << endl;
des->errors += 1;
}
tmp->set(idx, ex);
@@ -150,15 +145,26 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
return 0;
}
if (msb_ || lsb_ || idx_) {
cerr << get_line() << ": error: Cannot bit/part select "
"bits of parameters." << endl;
des->errors += 1;
}
NetExpr*res = new NetEParam(des, pscope, hname_t(name));
assert(res);
delete name;
assert(idx_ == 0);
if (msb_ && lsb_) {
cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl;
des->errors += 1;
} else if (msb_) {
/* We have here a bit select. Insert a NetESelect node
to handle it. */
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
if (tmp != 0) {
res = new NetESelect(res, tmp, 1);
}
}
return res;
}
@@ -222,6 +228,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/*
* $Log: elab_pexpr.cc,v $
* Revision 1.18 2002/12/05 02:14:33 steve
* Support bit select in constant expressions.
*
* Revision 1.17 2002/11/09 01:40:19 steve
* Postpone parameter width check to evaluation.
*
* Revision 1.16 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+54 -78
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.263 2002/08/28 18:54:36 steve Exp $"
#ident "$Id: elaborate.cc,v 1.266 2002/12/05 04:15:14 steve Exp $"
#endif
# include "config.h"
@@ -612,33 +612,38 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// port. sig is the thing outside the module that
// connects to the port.
NetNet*sig = (*pins)[idx]->elaborate_net(des, scope,
prts_pin_count,
0, 0, 0);
if (sig == 0) {
cerr << "internal error: Expression too complicated "
"for elaboration." << endl;
continue;
NetNet*sig;
if ((prts.count() >= 1)
&& (prts[0]->port_type() != NetNet::PINPUT)) {
sig = (*pins)[idx]->elaborate_lnet(des, scope, true);
if (sig == 0) {
cerr << (*pins)[idx]->get_line() << ": error: "
<< "Output port expression must support "
<< "continuous assignment." << endl;
des->errors += 1;
continue;
}
} else {
sig = (*pins)[idx]->elaborate_net(des, scope,
prts_pin_count,
0, 0, 0);
if (sig == 0) {
cerr << "internal error: Expression too complicated "
"for elaboration." << endl;
continue;
}
}
assert(sig);
// Check that a reg is not passed as an output or inout
// port of the module. sig is the elaborated signal in
// the outside that is to be passed, and prts is a
// concatenation of signals on the input that receive a
// reg value.
if ((sig->type() == NetNet::REG)
&& (prts.count() >= 1)
#ifndef NDEBUG
if ((prts.count() >= 1)
&& (prts[0]->port_type() != NetNet::PINPUT)) {
cerr << get_line() << ": error: reg/variable "
<< sig->name() << " cannot connect to "
<< "output port " << (idx+1) << " of "
<< my_scope->name() << "." << endl;
des->errors += 1;
continue;
assert(sig->type() != NetNet::REG);
}
#endif
// Check that the parts have matching pin counts. If
// not, they are different widths. Note that idx is 0
@@ -838,61 +843,6 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
des->errors += 1;
}
/*
* The concatenation is also OK an an l-value. This method elaborates
* it as a structural l-value.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
{
assert(scope);
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned errors = 0;
if (repeat_) {
cerr << get_line() << ": sorry: I do not know how to"
" elaborate repeat concatenation nets." << endl;
return 0;
}
/* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
}
/* If any of the sub expressions failed to elaborate, then
delete all those that did and abort myself. */
if (errors) {
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (nets[idx]) delete nets[idx];
}
des->errors += 1;
return 0;
}
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list. */
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
NetNet::IMPLICIT, pins);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
}
osig->local_flag(true);
return osig;
}
NetProc* Statement::elaborate(Design*des, NetScope*) const
{
@@ -1025,7 +975,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
rv->set_width(wid);
rv = pad_to_width(rv, wid);
if (! rv->set_width(wid)) {
if (wid != rv->expr_width()) {
cerr << get_line() << ": error: Unable to match "
"expression width of " << rv->expr_width() <<
" to l-value width of " << wid << "." << endl;
@@ -1126,6 +1076,12 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
assert(rv);
/* Try to evaluate the expression, at least as far as possible. */
if (NetExpr*tmp = rv->eval_tree()) {
delete rv;
rv = tmp;
}
{ unsigned wid = count_lval_width(lv);
rv->set_width(wid);
rv = pad_to_width(rv, wid);
@@ -1401,6 +1357,17 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parm(idx);
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
/* Attempt to pre-evaluate the parameters. It may be
possible to at least partially reduce the
expression. */
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
NetExpr*tmp = eparms[idx]->eval_tree();
if (tmp != 0) {
delete eparms[idx];
eparms[idx] = tmp;
}
}
}
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
@@ -2522,6 +2489,15 @@ Design* elaborate(list<const char*>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.266 2002/12/05 04:15:14 steve
* precalculate r-values of nb assignments and task arguments.
*
* Revision 1.265 2002/11/26 03:35:13 steve
* Do not set width if width is already OK.
*
* Revision 1.264 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.263 2002/08/28 18:54:36 steve
* Evaluate nonblocking assign r-values.
*
+8 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: emit.cc,v 1.69 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: emit.cc,v 1.70 2002/11/03 20:36:10 steve Exp $"
#endif
# include "config.h"
@@ -470,11 +470,18 @@ bool emit(const Design*des, const char*type)
return des->emit(tgt->meth);
}
cerr << "error: Code generator type " << type
<< " not found." << endl;
return false;
}
/*
* $Log: emit.cc,v $
* Revision 1.70 2002/11/03 20:36:10 steve
* Error message for mising code generator type.
*
* Revision 1.69 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+60 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_tree.cc,v 1.42 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.44 2002/12/05 02:14:33 steve Exp $"
#endif
# include "config.h"
@@ -752,7 +752,13 @@ NetEConst* NetEConcat::eval_tree()
<< "operand has indefinite width: "
<< *parms_[idx] << endl;
local_errors += 1;
} else if (expr->expr_width() == 0) {
cerr << expr->get_line() << ": internal error: "
<< "Operand of concatenation has no width: "
<< *expr << endl;
local_errors += 1;
}
gap += expr->expr_width();
}
@@ -888,6 +894,53 @@ NetExpr* NetEParam::eval_tree()
return res->dup_expr();
}
NetEConst* NetESelect::eval_tree()
{
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
if (expr == 0) {
NetExpr*tmp = expr_->eval_tree();
if (tmp != 0) {
delete expr_;
expr_ = tmp;
}
expr = dynamic_cast<NetEConst*>(expr_);
}
NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) {
NetExpr*tmp = base_->eval_tree();
if (tmp != 0) {
delete base_;
base_ = tmp;
}
base = dynamic_cast<NetEConst*>(base_);
}
if (expr == 0)
return 0;
if (base == 0)
return 0;
verinum eval = expr->value();
verinum oval (verinum::V0, expr_width(), true);
long bval = base->value().as_long();
for (long idx = 0 ; idx < expr_width() ; idx += 1) {
if ((bval >= eval.len()) || (bval < 0))
oval.set(idx, verinum::Vx);
else
oval.set(idx, eval.get(bval));
bval += 1;
}
NetEConst*res = new NetEConst(oval);
return res;
}
/*
* A ternary expression evaluation is controlled by the condition
* expression. If the condition evaluates to true or false, then
@@ -1134,6 +1187,12 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.44 2002/12/05 02:14:33 steve
* Support bit select in constant expressions.
*
* Revision 1.43 2002/11/09 01:40:19 steve
* Postpone parameter width check to evaluation.
*
* Revision 1.42 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+1 -1
View File
@@ -31,7 +31,7 @@
* file "hello" which is compiled, linked and ready to run. Run this
* program like so:
*
* ./hello
* vvp hello
*
* and the program will print the message to its output. Easy! For
* more on how to make the iverilog command work, see the iverilog
+377
View File
@@ -0,0 +1,377 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: sqrt-virtex.v,v 1.2 2002/11/13 01:49:43 steve Exp $"
*/
/*
* This module is a synthesizeable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other then to
* be excessively specific, I will step through the process of
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
* generate a generic library part for larger Virtex designs.
*
* In addition to Icarus Verilog, you will need implementation
* software from Xilinx. As of this writing, this example was tested
* with Foundation 4.2i, but it should work the same with ISE and
* Webpack software.
*
* This example source contains all the Verilog needed to do
* everything described below. We use conditional compilation to
* select the bits of Verilog that are needed to perform each specific
* task.
*
* SIMULATE THE DESIGN
*
* This source file includes a simulation test bench. To compile the
* program to include this test bench, use the command line:
*
* iverilog -DSIMULATE=1 -oa.out sqrt-virtex.v
*
* This generates the file "a.out" that can then be executed with the
* command:
*
* vvp a.out
*
* This causes the simulation to run a long set of example sqrt
* calculations. Each result is checked by the test bench to assure
* that the result is valid. When it is done, the program prints
* "PASSED" and finishes the simulation.
*
* When you take a close look at the "main" module below, you will see
* that it uses Verilog constructs that are not synthesizeable. This
* is fine, as we will never try to synthesize it.
*
* LIBRARY PARTS
*
* One can use the sqrt32 module to generate an EDIF file suitable for
* use as a library part. This part can be imported to the Xilinx
* schematic editor, then placed like any other pre-existing
* macro. One can also pass the generated EDIF as a precompiled macro
* that other designers may use as they see fit.
*
* To make an EDIF file from the sqrt32 module, execute the command:
*
* iverilog -osqrt32.edf -tfpga -parch=virtex sqrt-virtex.v
*
* The -parch=virtex tells the code generator to generate code for the
* virtex architecture family (we don't yet care what specific part)
* and the -osqrt32.edf places the output into the file
* sqrt32.edf.
*
* Without any preprocessor directives, the only module is the sqrt32
* module, so sqrt32 is compiled as the root. The ports of the module
* are automatically made into ports of the sqrt32.edf netlist, and
* the contents of the sqrt32 module are connected approprately.
*
* COMPLETE CHIP DESIGNS
*
* To make a complete chip design, there are other bits that need to
* be accounted for. Signals must be assigned to pins, and some
* special devices may need to be created. We also want to write into
* the EDIF file complete part information so that the implementation
* tools know how to route the complete design. The command to compile
* for our target part is:
*
* iverilog -ochip.edf -tfpga \
* -parch=virtex -ppart=XC2S15-VQ100 \
* -DMAKE_CHIP=1 sqrt-virtex.v
*
* This command uses the "chip" module as the root. This module in
* turn has ports that are destined to be the pins of the completed
* part. The -ppart= option gives complete part information, that is
* in turn written into the EDIF file. This saves us the drudgery of
* repeating that part number for later commands.
*
* The next steps involve Xilinx software, and to talk to Xilinx
* software, the netlist must be in the form of an "ngd" file, a
* binary netlist format. The command:
*
* ngdbuild chip.edf chip.ngd
*
* does the trick. The input to ngdbuild is the chip.edf file created
* by Icarus Verilog, and the output is the chip.ngd file that the
* implementation tools may read. From this point, it is best to refer
* to Xilinx documentation for the software you are using, but the
* quick summary is:
*
* map -o map.ncd chip.ngd
* par -w map.ncd chip.ncd
*
* The result of this sequence of commands is the chip.ncd file that
* is ready to be viewed by FPGA Edit, or converted to a bit stream,
* or whatever.
*
* POST MAP SIMULATION
*
* Warm fuzzies are good, and retesting your design after the part
* is mapped by the Xilinx backend tools is a cheap source of fuzzies.
* The command to make a Verilog file out of the mapped design is:
*
* ngd2ver chip.ngd chip_root.v
*
* This command creates from the chip.ngd the file "chip_root.v" that
* contains Verilog code that simulates the mapped design. This output
* Verilog has the single root module "chip_root", which came from the
* name of the root module when we were making hte EDIF file in the
* first place. The module has ports named just line the ports of the
* chip_root module below.
*
* The generated Verilog uses the library in the directory
* $(XILINX)/verilog/src/simprims. This directory comes with the ISE
* WebPACK installation that you are using. Icarus Verilog is able to
* simulate using that library.
*
* To compile a post-map simulation of the chip_root.v, use the
* command:
*
* iverilog -DSIMULATE -DPOST_MAP -ob.out \
* -y $(XILINX)/verilog/src/simprims \
* sqrt-virtex.v chip_root.v \
* $(XILINX)/verilog/src/glbl.v
*
* This command line generates b.out from the source files
* sqrt-virtex.v and chip_root.v (the latter from ngd2ver)
* and the "-y <path>" flag specifies the library directory that will
* be needed. The glbl.v source file is also included to provide the
* GSR and related signals.
*
* The POST_MAP compiler directive causes the GSR manipulations
* included in the test bench to be compiled in, to simulate the chip
* startup. Other then that, the test bench runs the post-map design
* the same way the pre-synthesis design works.
*
* Run this design with the command:
*
* vvp b.out
*
* And there you go.
*/
`ifndef POST_MAP
/*
* This module approximates the square root of an unsigned 32bit
* number. The algorithm works by doing a bit-wise binary search.
* Starting from the most significant bit, the accumulated value
* tries to put a 1 in the bit position. If that makes the square
* too big for the input, the bit is left zero, otherwise it is set
* in the result. This continues for each bit, decreasing in
* significance, until all the bits are calculated or all the
* remaining bits are zero.
*
* Since the result is an integer, this function really calculates
* value of the expression:
*
* x = floor(sqrt(y))
*
* where sqrt(y) is the exact square root of y and floor(N) is the
* largest integer <= N.
*
* For 32bit numbers, this will never run more then 16 iterations,
* which amounts to 16 clocks.
*/
module sqrt32(clk, rdy, reset, x, .y(acc));
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] acc;
// acc holds the accumulated result, and acc2 is the accumulated
// square of the accumulated result.
reg [15:0] acc;
reg [31:0] acc2;
// Keep track of which bit I'm working on.
reg [4:0] bitl;
wire [15:0] bit = 1 << bitl;
wire [31:0] bit2 = 1 << (bitl << 1);
// The output is ready when the bitl counter underflows.
wire rdy = bitl[4];
// guess holds the potential next values for acc, and guess2 holds
// the square of that guess. The guess2 calculation is a little bit
// subtle. The idea is that:
//
// guess2 = (acc + bit) * (acc + bit)
// = (acc * acc) + 2*acc*bit + bit*bit
// = acc2 + 2*acc*bit + bit2
// = acc2 + 2 * (acc<<bitl) + bit
//
// This works out using shifts because bit and bit2 are known to
// have only a single bit in them.
wire [15:0] guess = acc | bit;
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
(* ivl_synthesis_on *)
always @(posedge clk or posedge reset)
if (reset) begin
acc = 0;
acc2 = 0;
bitl = 15;
end else begin
if (guess2 <= x) begin
acc <= guess;
acc2 <= guess2;
end
bitl <= bitl - 5'd1;
end
endmodule // sqrt32
`endif // `ifndef POST_MAP
`ifdef SIMULATE
/*
* This module is a test bench for the sqrt32 module. It runs some
* test input values through the sqrt32 module, and checks that the
* output is valid. If an invalid output is generated, print and
* error message and stop immediately. If all the tested values pass,
* then print PASSED after the test is complete.
*/
module main;
reg [31:0] x;
reg clk, reset;
wire [15:0] y;
wire rdy;
`ifdef POST_MAP
chip_root dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
`else
sqrt32 dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
`endif
(* ivl_synthesis_off *)
always #5 clk = !clk;
task reset_dut;
begin
reset = 1;
#1 reset = 0;
@(negedge clk) ;
end
endtask // reset_dut
task crank_dut;
begin
while (rdy == 0) begin
@(posedge clk) /* wait */;
end
end
endtask // crank_dut
`ifdef POST_MAP
reg GSR;
assign glbl.GSR = GSR;
`endif
integer idx;
(* ivl_synthesis_off *)
initial begin
reset = 0;
clk = 0;
/* If doing a post-map simulation, when we need to wiggle
The GSR bit to simulate chip power-up. */
`ifdef POST_MAP
GSR = 1;
#100 GSR = 0;
`endif
#100 x = 1;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
x = 3;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
x = 4;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
for (idx = 0 ; idx < 200 ; idx = idx + 1) begin
x = $random;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
if (x < (y * y)) begin
$display("ERROR: y is too big");
$finish;
end
if (x > ((y + 1)*(y + 1))) begin
$display("ERROR: y is too small");
$finish;
end
end
$display("PASSED");
$finish;
end
endmodule // main
`endif
`ifdef MAKE_CHIP
/*
* This module represents the chip packaging that we intend to
* generate. We bind pins here, and route the clock to the global
* clock buffer.
*/
module chip_root(clk, rdy, reset, x, y);
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] y;
wire clk_int;
(* cellref="BUFG:O,I" *)
buf gbuf (clk_int, clk);
sqrt32 dut(.clk(clk_int), .reset(reset), .rdy(rdy), .x(x), .y(y));
/* Assign the clk to GCLK0, which is on pin P39. */
$attribute(clk, "PAD", "39");
// We don't care where the remaining pins go, so set the pin number
// to 0. This tells the implementation tools that we want a PAD,
// but we don't care which. Also note the use of a comma (,)
// separated list to assign pins to the bits of a vector.
$attribute(rdy, "PAD", "0");
$attribute(reset, "PAD", "0");
$attribute(x, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
$attribute(y, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
endmodule // chip_root
`endif
+31 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.36 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.37 2002/11/17 23:37:55 steve Exp $"
#endif
# include "config.h"
@@ -192,6 +192,33 @@ NetNet* NetEBComp::synthesize(Design*des)
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::OR);
break;
case '>':
/* sig > 0 is true if any bit in sig is set. This
is very much like sig != 0. (0 > sig) shouldn't
happen. */
if (rcon) {
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::OR);
} else {
assert(0);
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::NOR);
}
break;
case '<':
/* 0 < sig is handled like sig > 0. */
if (! rcon) {
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::OR);
} else {
assert(0);
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::NOR);
}
break;
default:
assert(0);
}
@@ -608,6 +635,9 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.37 2002/11/17 23:37:55 steve
* Magnitude compare to 0.
*
* Revision 1.36 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+26 -2
View File
@@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "$Date: 2002/07/05 17:17:20 $" Version "$Date: 2002/07/05 17:17:20 $"
.TH iverilog-vpi 1 "$Date: 2002/11/23 00:51:53 $" Version "$Date: 2002/11/23 00:51:53 $"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
@@ -32,13 +32,37 @@ VPI modules to further reference external libraries.
Normally, the output VPI module will be named after the first source
file passed to the command. This flag sets the name (without the .vpi
suffix) of the output vpi module.
.SH "PC-ONLY OPTIONS"
The PC port of \fIiverilog-vpi\fP includes two special flags needed to
support the more intractable development environment. These flags help
the program locate parts that it needs.
.TP 8
.B -mingw=\fIpath\fP
Tell the program the root of the Mingw compiler tool suite. The
\fBvvp\fP runtime is compiled with this compiler, and this is the
compiler that \fIiverilog-vpi\fP expects to use to compile your source
code. This is notmally not needed, and if you do use it, it is only
needed once. The compiler will save the \fIpath\fP in the registry for
use later.
.TP 8
.B -ivl=\fIpath\fP
Set for the use during compilation the root if the Icarus Verilog
install. This is the place where you installed Icarus Verilog when you
ran the installer. This flag is also only needed once, and the path is
stored in the registry for future use.
.SH "AUTHOR"
.nf
Steve Williams ([email protected])
.SH SEE ALSO
iverilog(1), vvp(1),
.BR "<http://www.icarus.com/eda/verilog/>"
.BR "<http://www.icarus.com/eda/verilog/>",
.BR "<http://www.mingw.org>",
.SH COPYRIGHT
.nf
+1 -1
View File
@@ -80,7 +80,7 @@
# This is the XNF code generator.
[-txnf]
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] -txnf -Fsynth2 -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] -txnf -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
# And this is another XNF code generator, under development.
[-tfpga]
+2 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: lexor.lex,v 1.35 2002/09/25 02:23:08 steve Exp $"
#ident "$Id: lexor.lex,v 1.36 2002/11/08 00:04:16 steve Exp $"
#endif
# include "config.h"
@@ -239,6 +239,7 @@ W [ \t\b\f]+
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else { }
<IFDEF_FALSE,IFDEF_SUPR>"//".* { }
<IFDEF_FALSE,IFDEF_SUPR>. { }
<IFDEF_FALSE,IFDEF_SUPR>\n { istack->lineno += 1; fputc('\n', yyout); }
+2 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: lexor.lex,v 1.73 2002/06/06 18:57:18 steve Exp $"
#ident "$Id: lexor.lex,v 1.74 2002/12/04 02:07:00 steve Exp $"
#endif
# include "config.h"
@@ -375,7 +375,7 @@ W [ \t\b\f\r]+
if (isgraph(yytext[0]))
cerr << yytext[0];
else
cerr << (unsigned)yytext[0];
cerr << "hex " << hex << (0xffU & ((unsigned) (yytext[0])));
cerr << ")" << endl; }
+20 -2
View File
@@ -33,7 +33,16 @@ install software from source form.
then just make sure the distributed lexor_keyword.cc is newer then
lexor_keyword.gperf, and use that.
3) Configure, build and install the Icarus Verilog sources as normal.
3) If working with a CVS snapshot, you must run autoconf in several
directories. This is aided by the 'autoconf.sh' script at the
top of the source tree:
sh ./autoconf.sh
This will also run the gperf command, so make sure you'd completed
step #2 first.
4) Configure, build and install the Icarus Verilog sources as normal.
The only change you need to make here is to use a configure command like:
@@ -47,8 +56,17 @@ install software from source form.
You can, of course, add other configure options.
6) NOTE: 'make check' will not work until after 'make install' has been run
since dynamically loaded code is searched for in the install location
rather than the build location. The dlopen emulation library doesn't
support a search path option.
4) Done!
If you are worried about overwriting a working installation with a new,
potentially broken one, you can always configure using --prefix="/some/path",
and install there to make sure everything is working and then re-configure
with the real path you want to install at, make clean, and make install.
5) Done!
GPERF FOR MACOSX
+7 -2
View File
@@ -76,13 +76,18 @@ without white space.
Now, configure the source to make the makefiles and configuration
details. Run this command:
$ ./configure --prefix=/cygdrive/d/iverilog
$ ./configure --prefix=d:/iverilog
Substitute your chosen directory for the prefix. This will cause the
makefiles to build and the source code to configure. The configure
program will detect that this is a mingw environment and set things up
to build properly.
(For a prefix, use the drive letter notation, the mingw compiled parts
require it, and the Cygwin tools should be able to handle it. You may
need to check or upgrade your Cygwin installation if this causes
problems for you.)
* Compile Icarus Verilog
@@ -108,7 +113,7 @@ window.
When you are ready, install like this:
$ /usr/bin/make STRIP=/usr/bin/strip.exe install
$ /usr/bin/make install
This is part of what the configure program did for you. The Makefiles
now know to put the files under the D:\iverilog (or whatever directory
+17 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_design.cc,v 1.28 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: net_design.cc,v 1.30 2002/12/07 02:49:24 steve Exp $"
#endif
# include "config.h"
@@ -501,12 +501,18 @@ NetScope* Design::find_task(const hname_t&key)
return 0;
}
NetEvent* Design::find_event(NetScope*scope, hname_t path)
NetEvent* Design::find_event(NetScope*scope, const hname_t&p)
{
hname_t path = p;
assert(scope);
char*key = path.remove_tail_name();
if (path.peek_name(0))
scope = find_scope(scope, path);
while (scope) {
if (NetEvent*ev = scope->find_event(path)) {
if (NetEvent*ev = scope->find_event(key)) {
delete key;
return ev;
}
@@ -515,6 +521,7 @@ NetEvent* Design::find_event(NetScope*scope, hname_t path)
scope = scope->parent();
}
delete key;
return 0;
}
@@ -593,6 +600,13 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.30 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.29 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.28 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+80 -1
View File
@@ -17,13 +17,79 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_expr.cc,v 1.8 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: net_expr.cc,v 1.10 2002/11/09 01:40:19 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
# include <iostream>
/*
* Create an add/sub node from the two operands. Make a best guess of
* the
*/
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
NetEConst* tmp;
/* Catch the special case that one of the operands is an
unsized constant number. If so, then we should set the
width of that number to the size of the other operand, plus
one. This expands the expression to account for the largest
possible result.
The set_width applied to a constant value will only
truncate the constant so far as it can still hold its
logical value, so this is safe to do. */
if ( (tmp = dynamic_cast<NetEConst*>(r))
&& (! tmp->has_width())
&& (tmp->expr_width() > l->expr_width()) ) {
unsigned target_width = l->expr_width() + 1;
r->set_width(target_width);
/* Note: This constant value will not gain a defined
with from this. Make sure. */
assert(! r->has_width() );
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
&& (! tmp->has_width())
&& (tmp->expr_width() > r->expr_width()) ) {
unsigned target_width = r->expr_width() + 1;
l->set_width(target_width);
/* Note: This constant value will not gain a defined
with from this. Make sure. */
assert(! l->has_width() );
}
/* Now that we have the operand sizes the way we like, or as
good as we are going to get them, set the size of myself. */
if (r->expr_width() > l->expr_width()) {
expr_width(r->expr_width());
} else {
expr_width(l->expr_width());
}
cast_signed(l->has_sign() && r->has_sign());
}
NetEBAdd::~NetEBAdd()
{
}
NetEBAdd* NetEBAdd::dup_expr() const
{
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
: parms_(cnt), repeat_(r)
{
@@ -43,6 +109,11 @@ NetEConcat::~NetEConcat()
delete parms_[idx];
}
bool NetEConcat::has_width() const
{
return true;
}
void NetEConcat::set(unsigned idx, NetExpr*e)
{
assert(idx < parms_.count());
@@ -171,6 +242,14 @@ bool NetESelect::set_width(unsigned w)
/*
* $Log: net_expr.cc,v $
* Revision 1.10 2002/11/09 01:40:19 steve
* Postpone parameter width check to evaluation.
*
* Revision 1.9 2002/11/06 02:25:13 steve
* No need to keep excess width from an
* unsigned constant value, if it can
* be trimmed safely.
*
* Revision 1.8 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+13 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_input.cc,v 1.6 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.7 2002/11/16 05:45:41 steve Exp $"
#endif
# include "config.h"
@@ -250,11 +250,15 @@ NexusSet* NetCase::nex_input()
result->add(*tmp);
delete tmp;
assert(items_[idx].guard);
tmp = items_[idx].guard->nex_input();
assert(tmp);
result->add(*tmp);
delete tmp;
/* Usually, this is the guard expression. The default
case is special and is identified by a null
guard. The default guard obviously has no input. */
if (items_[idx].guard) {
tmp = items_[idx].guard->nex_input();
assert(tmp);
result->add(*tmp);
delete tmp;
}
}
return result;
@@ -358,6 +362,9 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* Revision 1.7 2002/11/16 05:45:41 steve
* Handle default: case in net_inputs for NetCase.
*
* Revision 1.6 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
+6 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.20 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: net_scope.cc,v 1.21 2002/12/07 02:49:24 steve Exp $"
#endif
# include "config.h"
@@ -255,10 +255,10 @@ void NetScope::rem_event(NetEvent*ev)
}
NetEvent* NetScope::find_event(const hname_t&name)
NetEvent* NetScope::find_event(const char*name)
{
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
if (strcmp(cur->name(), name.peek_tail_name()) == 0)
if (strcmp(cur->name(), name) == 0)
return cur;
return 0;
@@ -432,6 +432,9 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* Revision 1.21 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.20 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+10 -36
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.201 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: netlist.cc,v 1.203 2002/11/09 00:25:27 steve Exp $"
#endif
# include "config.h"
@@ -1707,12 +1707,6 @@ const NetScope* NetEUFunc::func() const
return func_;
}
NetEUFunc* NetEUFunc::dup_expr() const
{
assert(0);
return 0;
}
NetUTask::NetUTask(NetScope*def)
: task_(def)
{
@@ -1756,34 +1750,6 @@ bool NetExpr::has_width() const
return true;
}
/*
* Create a bitwise operator node from the opcode and the left and
* right expressions. Don't worry about the width of the expression
* yet, we'll get that from the l-value, whatever that turns out to
* be.
*/
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
if (r->expr_width() > l->expr_width())
expr_width(r->expr_width());
else
expr_width(l->expr_width());
cast_signed(l->has_sign() && r->has_sign());
}
NetEBAdd::~NetEBAdd()
{
}
NetEBAdd* NetEBAdd::dup_expr() const
{
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
/*
* Create a bitwise operator node from the opcode and the left and
* right expressions. Don't worry about the width of the expression
@@ -2320,6 +2286,14 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.203 2002/11/09 00:25:27 steve
* Add dup_expr for user defined function calls.
*
* Revision 1.202 2002/11/06 02:25:13 steve
* No need to keep excess width from an
* unsigned constant value, if it can
* be trimmed safely.
*
* Revision 1.201 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+18 -3
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.267 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: netlist.h,v 1.271 2002/12/07 02:49:24 steve Exp $"
#endif
/*
@@ -2428,6 +2428,7 @@ class NetEConcat : public NetExpr {
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
virtual NexusSet* nex_input();
virtual bool has_width() const;
virtual bool set_width(unsigned w);
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree();
@@ -2493,6 +2494,7 @@ class NetESelect : public NetExpr {
virtual bool set_width(unsigned w);
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree();
virtual NetESelect* dup_expr() const;
private:
@@ -2793,7 +2795,7 @@ class NetScope {
void add_event(NetEvent*);
void rem_event(NetEvent*);
NetEvent*find_event(const hname_t&name);
NetEvent*find_event(const char*name);
/* These methods manage signals. The add_ and rem_signal
@@ -2995,7 +2997,7 @@ class Design {
NetScope* find_task(const hname_t&key);
// Events
NetEvent* find_event(NetScope*scope, const hname_t path);
NetEvent* find_event(NetScope*scope, const hname_t&path);
// NODES
void add_node(NetNode*);
@@ -3083,6 +3085,19 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.271 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.270 2002/12/05 02:14:33 steve
* Support bit select in constant expressions.
*
* Revision 1.269 2002/11/09 01:40:19 steve
* Postpone parameter width check to evaluation.
*
* Revision 1.268 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.267 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+17 -9
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: parse.y,v 1.162 2002/10/13 05:01:44 steve Exp $"
#ident "$Id: parse.y,v 1.168 2002/12/10 05:49:51 steve Exp $"
#endif
# include "config.h"
@@ -33,6 +33,13 @@ extern void lex_end_table();
static svector<PExpr*>* active_range = 0;
static bool active_signed = false;
/* Later version of bison (including 1.35) will not compile in stack
extension if the output is compiled with C++ and either the YYSTYPE
or YYLTYPE are provided by the source code. However, I can get the
old behavior back by defining these symbols. */
# define YYSTYPE_IS_TRIVIAL 1
# define YYLTYPE_IS_TRIVIAL 1
/*
* These are some common strength pairs that are used as defaults when
* the user is not otherwise specific.
@@ -551,11 +558,11 @@ dr_strength1
;
event_control
: '@' IDENTIFIER
{ PEIdent*tmpi = new PEIdent(hname_t($2));
: '@' identifier
{ PEIdent*tmpi = new PEIdent(*$2);
tmpi->set_file(@2.text);
tmpi->set_lineno(@2.first_line);
delete[]$2;
delete $2;
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
PEventStatement*tmps = new PEventStatement(tmpe);
tmps->set_file(@1.text);
@@ -1684,7 +1691,7 @@ localparam_assign_list
/* The parameters of a module instance can be overridden by writing
a list of expressions in a syntax much line a delay list. (The
a list of expressions in a syntax much like a delay list. (The
difference being the list can have any length.) The pform that
attaches the expression list to the module checks that the
expressions are constant.
@@ -2084,6 +2091,7 @@ specify_item_list
specify_edge_path_decl
: specify_edge_path '=' '(' specify_delay_value_list ')'
| specify_edge_path '=' delay_value_simple
;
specify_edge_path
@@ -2139,9 +2147,9 @@ specparam
delete $5;
delete $7;
}
| PATHPULSE_IDENTIFIER '=' '(' expression ')'
| PATHPULSE_IDENTIFIER '=' expression
{ delete $1;
delete $4;
delete $3;
}
| PATHPULSE_IDENTIFIER '=' '(' expression ',' expression ')'
{ delete $1;
@@ -2315,8 +2323,8 @@ statement
delete $2;
$$ = tmp;
}
| K_TRIGGER IDENTIFIER ';'
{ PTrigger*tmp = new PTrigger(hname_t($2));
| K_TRIGGER identifier ';'
{ PTrigger*tmp = new PTrigger(*$2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
delete $2;
+9 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: parse_misc.h,v 1.5 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: parse_misc.h,v 1.6 2002/11/03 20:36:53 steve Exp $"
#endif
# include <list>
@@ -38,6 +38,11 @@ struct vlltype {
const char*text;
};
# define YYLTYPE vlltype
/* This for compatibility with new and older bison versions. */
#ifndef yylloc
# define yylloc VLlloc
#endif
extern YYLTYPE yylloc;
/*
@@ -53,6 +58,9 @@ extern unsigned error_count, warn_count;
/*
* $Log: parse_misc.h,v $
* Revision 1.6 2002/11/03 20:36:53 steve
* Support old/new bison yylloc.
*
* Revision 1.5 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+27 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: set_width.cc,v 1.23 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: set_width.cc,v 1.25 2002/11/13 03:03:08 steve Exp $"
#endif
# include "config.h"
@@ -193,9 +193,22 @@ bool NetEBShift::set_width(unsigned w)
{
bool flag = true;
left_->set_width(w);
if (left_->expr_width() < w)
left_ = pad_to_width(left_, w);
switch (op()) {
case 'l':
left_->set_width(w);
if (left_->expr_width() < w)
left_ = pad_to_width(left_, w);
break;
case 'r':
if (left_->expr_width() < w)
left_ = pad_to_width(left_, w);
break;
default:
assert(0);
}
expr_width(left_->expr_width());
flag = expr_width() == w;
@@ -238,7 +251,7 @@ bool NetEConst::set_width(unsigned w)
if (value_.has_sign())
pad = value_.get(value_.len()-1);
verinum tmp (verinum::V0, w);
verinum tmp (verinum::V0, w, has_width());
for (unsigned idx = 0 ; idx < value_.len() ; idx += 1)
tmp.set(idx, value_[idx]);
for (unsigned idx = value_.len() ; idx < w ; idx += 1)
@@ -259,7 +272,7 @@ bool NetEConst::set_width(unsigned w)
if (value_[idx] != verinum::V0)
use_w = idx+1;
verinum tmp (verinum::V0, use_w);
verinum tmp (verinum::V0, use_w, has_width());
for (unsigned idx = 0 ; idx < use_w ; idx += 1)
tmp.set(idx, value_[idx]);
@@ -357,6 +370,14 @@ bool NetEUReduce::set_width(unsigned w)
/*
* $Log: set_width.cc,v $
* Revision 1.25 2002/11/13 03:03:08 steve
* Do not truncate high bits of right shift.
*
* Revision 1.24 2002/11/06 02:25:13 steve
* No need to keep excess width from an
* unsigned constant value, if it can
* be trimmed safely.
*
* Revision 1.23 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+1 -1
View File
@@ -1,7 +1,7 @@
PKG="IVLver"
NAME="verilog"
ARCH="sparc"
VERSION="0.6"
VERSION="0.7"
CATEGORY="application"
VENDOR="Icarus.com"
EMAIL="[email protected]"
+5 -10
View File
@@ -1,18 +1,13 @@
i pkginfo=./pkginfo
d none bin 0755 bin bin
f none bin/iverilog 0755 bin bin
f none bin/iverilog-vpi 0755 bin bin
f none bin/vvp 0755 bin bin
d none include 0755 bin bin
f none include/acc_user.h 0644 bin bin
f none include/ivl_target.h 0644 bin bin
f none include/vpi_priv.h 0644 bin bin
f none include/veriuser.h 0644 bin bin
f none include/vpi_user.h 0644 bin bin
f none include/vvm.h 0644 bin bin
f none include/vvm_calltf.h 0644 bin bin
f none include/vvm_func.h 0644 bin bin
f none include/vvm_gates.h 0644 bin bin
f none include/vvm_nexus.h 0644 bin bin
f none include/vvm_signal.h 0644 bin bin
f none include/vvm_thread.h 0644 bin bin
d none lib 0755 bin bin
d none lib/ivl 0755 bin bin
f none lib/ivl/fpga.tgt 0644 bin bin
@@ -22,10 +17,10 @@ f none lib/ivl/ivlpp 0755 bin bin
f none lib/ivl/null.tgt 0644 bin bin
f none lib/ivl/system.vpi 0644 bin bin
f none lib/ivl/vvp.tgt 0644 bin bin
f none lib/libveriuser.a 0644 bin bin
f none lib/libvpi.a 0644 bin bin
f none lib/libvpip.a 0644 bin bin
f none lib/libvvm.a 0644 bin bin
d none man 0755 bin bin
d none man/man1 0755 bin bin
f none man/man1/iverilog.1 0644 bin bin
f none man/man1/iverilog-vpi.1 0644 bin bin
f none man/man1/vvp.1 0644 bin bin
+82 -24
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.17 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: synth2.cc,v 1.20 2002/11/09 23:29:29 steve Exp $"
#endif
# include "config.h"
@@ -315,8 +315,13 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
bool flag = true;
/* Keep an accounting of which statement accounts for which
bit slice of the FF bank. This is used for error checking. */
NetProc**pin_accounting = new NetProc* [ff->pin_count()];
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1)
pin_accounting[idx] = 0;
NetProc*cur = last_;
unsigned offset = 0;
do {
cur = cur->next_;
@@ -329,7 +334,9 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
connect(tmp_set[idx], tmp_map->pin(idx));
/* Create also a temporary net_out to collect the
output. */
output. The tmp1 and tmp2 map and out sets together
are used to collect the outputs from the substatement
for the inputs of the FF bank. */
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
tmp_set.count());
@@ -351,6 +358,17 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
if (ptr < tmp_aset.len())
aset_value2.set(idx, tmp_aset[ptr]);
if (pin_accounting[ptr] != 0) {
cerr << cur->get_line() << ": error: "
<< "Synchronous output conflicts with "
<< pin_accounting[ptr]->get_line()
<< "." << endl;
flag = false;
} else {
pin_accounting[ptr] = cur;
}
}
if (ff->pin_Aclr().is_linked())
connect(ff->pin_Aclr(), ff2->pin_Aclr());
@@ -388,21 +406,25 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
continue;
/* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */
substatement to the output of the block as a
whole. It is occasionally possible to have outputs
beyond the input set, for example when the l-value of
an assignment is smaller then the r-value. */
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(nex_out->pin(ptr), tmp_out->pin(idx));
if (ptr < nex_out->pin_count())
connect(nex_out->pin(ptr), tmp_out->pin(idx));
}
delete tmp_map;
delete tmp_out;
offset += ff2->width();
} while (cur != last_);
delete[]pin_accounting;
/* Done. The large NetFF is no longer needed, as it has been
taken up by the smaller NetFF devices. */
assert(offset == ff->width());
delete ff;
return flag;
@@ -418,6 +440,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events_in)
{
/* Synthesize the enable expression. */
NetNet*ce = expr_->synthesize(des);
assert(ce->pin_count() == 1);
@@ -430,6 +453,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
if (connected(ce->pin(0), ev->pin(0))) {
bool flag = true;
assert(ev->edge() == NetEvProbe::POSEDGE);
/* Synthesize the true clause to figure out what
@@ -437,7 +461,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
NetNet*asig = new NetNet(scope, scope->local_hsymbol(),
NetNet::WIRE, nex_map->pin_count());
asig->local_flag(true);
if_->synth_async(des, scope, nex_map, asig);
flag = if_->synth_async(des, scope, nex_map, asig) && flag;
assert(asig->pin_count() == ff->width());
@@ -465,7 +489,8 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
assert(events_in.count() == 1);
return else_->synth_sync(des, scope, ff, nex_map,
nex_out, svector<NetEvProbe*>(0));
nex_out, svector<NetEvProbe*>(0))
&& flag;
}
}
@@ -487,15 +512,48 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
assert(if_);
assert(!else_);
/* Synthesize the input to the DFF. */
bool flag = if_->synth_async(des, scope, nex_map, nex_out);
/* What's left, is a synchronous CE statement like this:
if (expr_) <true statement>;
The expr_ expression has alreacy been synthesized to the ce
net, so we connect it here to the FF. What's left is to
synthesize the substatement as a combinational
statement.
Watch out for the special case that there is already a CE
connected to this FF. This can be caused by code like this:
if (a) if (b) <statement>;
In this case, we are working on the inner IF, so we AND the
a and b expressions to make a new CE. */
if (ff->pin_Enable().is_linked()) {
NetLogic*ce_and = new NetLogic(scope,
scope->local_hsymbol(), 3,
NetLogic::AND);
des->add_node(ce_and);
connect(ff->pin_Enable(), ce_and->pin(1));
connect(ce->pin(0), ce_and->pin(2));
ff->pin_Enable().unlink();
connect(ff->pin_Enable(), ce_and->pin(0));
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
NetNet::IMPLICIT, 1);
tmp->local_flag(true);
connect(ff->pin_Enable(), tmp->pin(0));
} else {
connect(ff->pin_Enable(), ce->pin(0));
}
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
if (flag == false)
return flag;
assert(expr_);
connect(ff->pin_Enable(), ce->pin(0));
return true;
}
@@ -561,15 +619,6 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
if (pclk->edge() == NetEvProbe::NEGEDGE)
ff->attribute("Clock:LPM_Polarity", verinum("INVERT"));
#if 0
if (ev->nprobe() > 1) {
cerr << get_line() << ": sorry: I don't know how "
<< "to synthesize asynchronous DFF controls."
<< endl;
return false;
}
#endif
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope, ff,
nex_map, nex_out, events);
@@ -689,6 +738,15 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.20 2002/11/09 23:29:29 steve
* Handle nested-if chip enables.
*
* Revision 1.19 2002/11/09 20:22:57 steve
* Detect synthesis conflicts blocks statements share outputs.
*
* Revision 1.18 2002/11/06 03:22:28 steve
* More forgiving about assignment rval width mismatch.
*
* Revision 1.17 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+20 -9
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.97 2002/10/23 01:47:18 steve Exp $"
#ident "$Id: t-dll.cc,v 1.100 2002/11/05 02:12:35 steve Exp $"
#endif
# include "config.h"
@@ -36,32 +36,33 @@
inline ivl_dll_t ivl_dlopen(const char *name)
{
return (ivl_dll_t) LoadLibrary(name);
ivl_dll_t res = (ivl_dll_t) LoadLibrary(name);
return res;
}
inline void * ivl_dlsym(ivl_dll_t dll, const char *nm)
{
FARPROC sym;
return GetProcAddress((HMODULE)dll, nm);
FARPROC sym;
return (void*)GetProcAddress((HMODULE)dll, nm);
}
inline void ivl_dlclose(ivl_dll_t dll)
{
FreeLibrary((HMODULE)dll);
FreeLibrary((HMODULE)dll);
}
const char *dlerror(void)
{
static char msg[255];
static char msg[256];
unsigned long err = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
0,
sizeof(msg) - 1,
NULL
);
return msg;
@@ -448,6 +449,7 @@ bool dll_target::start_design(const Design*des)
dll_path_ = des->get_flag("DLL");
dll_ = ivl_dlopen(dll_path_.c_str());
if (dll_ == 0) {
cerr << "error: " << dll_path_ << " failed to load." << endl;
cerr << dll_path_ << ": " << dlerror() << endl;
return false;
}
@@ -1979,6 +1981,15 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.100 2002/11/05 02:12:35 steve
* Fix the call to FormatMessage under Windows.
*
* Revision 1.99 2002/11/03 22:44:19 steve
* Cast for gcc convenience.
*
* Revision 1.98 2002/11/03 20:47:23 steve
* Slightly more verbose load fail message.
*
* Revision 1.97 2002/10/23 01:47:18 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.5 2002/08/12 00:27:10 steve Exp $"
#ident "$Id: Makefile.in,v 1.6 2002/11/05 02:14:41 steve Exp $"
#
#
SHELL = /bin/sh
@@ -79,7 +79,7 @@ check: all
install: all installdirs $(libdir)/ivl/fpga.tgt
$(libdir)/ivl/fpga.tgt: ./fpga.tgt
$(INSTALL_DATA) ./fpga.tgt $(libdir)/ivl/fpga.tgt
$(INSTALL_PROGRAM) ./fpga.tgt $(libdir)/ivl/fpga.tgt
installdirs: ../mkinstalldirs
+59 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-generic-edif.c,v 1.10 2002/10/28 02:05:56 steve Exp $"
#ident "$Id: d-generic-edif.c,v 1.12 2002/11/01 02:36:22 steve Exp $"
#endif
# include "device.h"
@@ -174,7 +174,18 @@ static const char*external_library_text =
" (port Q (direction OUTPUT))\n"
" (port D (direction INPUT))\n"
" (port C (direction INPUT))\n"
" (port CE (direction INPUT)))))\n"
" (port CE (direction INPUT))\n"
" (port CLR (direction INPUT)))))\n"
" (cell FDCPE (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
" (interface\n"
" (port Q (direction OUTPUT))\n"
" (port D (direction INPUT))\n"
" (port C (direction INPUT))\n"
" (port CE (direction INPUT))\n"
" (port PRE (direction INPUT))\n"
" (port CLR (direction INPUT)))))\n"
" (cell GND (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
@@ -226,11 +237,11 @@ static void edif_show_consts(ivl_design_t des)
switch (val[pin]) {
case '0':
name = "GND";
port = "G";
port = "GROUND";
break;
case '1':
name = "VCC";
port = "P";
port = "VCC";
break;
default:
name = "???";
@@ -260,7 +271,8 @@ void edif_show_footer(ivl_design_t des)
edif_show_consts(des);
for (cur = net_list ; cur ; cur = cur->next) {
fprintf(xnf, "(net N%u (joined %s))\n", nref, cur->joined);
fprintf(xnf, "(net (rename N%u \"%s\") (joined %s))\n",
nref, ivl_nexus_name(cur->nex), cur->joined);
nref += 1;
}
@@ -355,6 +367,19 @@ void edif_show_generic_dff(ivl_lpm_t net)
ivl_nexus_t nex;
char jbuf[1024];
unsigned idx;
ivl_nexus_t aclr = ivl_lpm_async_clr(net);
ivl_nexus_t aset = ivl_lpm_async_set(net);
ivl_expr_t avalue = 0;
const char*abits = 0;
const char*fdcell = "FDCE";
if (aset != 0) {
fdcell = "FDCPE";
avalue = ivl_lpm_aset_value(net);
assert(avalue);
abits = ivl_expr_bits(avalue);
assert(abits);
}
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
@@ -363,7 +388,8 @@ void edif_show_generic_dff(ivl_lpm_t net)
fprintf(xnf, "(instance (rename U%u \"%s[%u]\")",
edif_uref, ivl_lpm_name(net), idx);
fprintf(xnf, " (viewRef net"
" (cellRef FDCE (libraryRef VIRTEX))))\n");
" (cellRef %s (libraryRef VIRTEX))))\n",
fdcell);
nex = ivl_lpm_q(net, idx);
sprintf(jbuf, "(portRef Q (instanceRef U%u))", edif_uref);
@@ -381,6 +407,25 @@ void edif_show_generic_dff(ivl_lpm_t net)
sprintf(jbuf, "(portRef CE (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(nex, jbuf);
}
if (aclr) {
sprintf(jbuf, "(portRef CLR (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(aclr, jbuf);
}
if (aset) {
if (abits[idx] == '1') {
sprintf(jbuf, "(portRef PRE (instanceRef U%u))",
edif_uref);
edif_set_nexus_joint(aset, jbuf);
} else {
assert(aclr == 0);
sprintf(jbuf, "(portRef CLR (instanceRef U%u))",
edif_uref);
edif_set_nexus_joint(aset, jbuf);
}
}
}
}
@@ -404,6 +449,14 @@ const struct device_s d_generic_edif = {
/*
* $Log: d-generic-edif.c,v $
* Revision 1.12 2002/11/01 02:36:22 steve
* Give nets better names, if available.
*
* Revision 1.11 2002/10/30 03:58:45 steve
* Fix up left shift to pass compile,
* fix up ADD/SUB to generate missing pieces,
* Add the asynch set/reset to DFF devices.
*
* Revision 1.10 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
+416 -93
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-virtex.c,v 1.16 2002/10/28 02:05:56 steve Exp $"
#ident "$Id: d-virtex.c,v 1.21 2002/11/24 02:26:14 steve Exp $"
#endif
# include "device.h"
@@ -38,6 +38,8 @@
* place-and-route step, as it is not normally needed within an
* FPGA net.
*
* BUFT O, I, T
*
* INV O, I
* Inverting buffer.
*
@@ -68,6 +70,19 @@ static const char*virtex_library_text =
" (interface\n"
" (port O (direction OUTPUT))\n"
" (port I (direction INPUT)))))\n"
" (cell BUFG (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
" (interface\n"
" (port O (direction OUTPUT))\n"
" (port I (direction INPUT)))))\n"
" (cell BUFT (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
" (interface\n"
" (port O (direction OUTPUT))\n"
" (port I (direction OUTPUT))\n"
" (port T (direction INPUT)))))\n"
" (cell FDCE (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
@@ -75,13 +90,18 @@ static const char*virtex_library_text =
" (port Q (direction OUTPUT))\n"
" (port D (direction INPUT))\n"
" (port C (direction INPUT))\n"
" (port CE (direction INPUT)))))\n"
" (cell GBUF (cellType GENERIC)\n"
" (port CE (direction INPUT))\n"
" (port CLR (direction INPUT)))))\n"
" (cell FDCPE (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
" (interface\n"
" (port O (direction OUTPUT))\n"
" (port I (direction INPUT)))))\n"
" (port Q (direction OUTPUT))\n"
" (port D (direction INPUT))\n"
" (port C (direction INPUT))\n"
" (port CE (direction INPUT))\n"
" (port PRE (direction INPUT))\n"
" (port CLR (direction INPUT)))))\n"
" (cell GND (cellType GENERIC)\n"
" (view net\n"
" (viewType NETLIST)\n"
@@ -215,9 +235,23 @@ static void edif_show_virtex_pad(ivl_signal_t sig, const char*str)
}
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
char port_name[256];
edif_uref += 1;
/* Calculate the name of the net that connects the
pad to the I/OBUF. This leads to more humane
names in the mapped netlist. */
if (ivl_signal_pins(sig) == 1)
sprintf(port_name, "(rename U%uN \"%s\")",
edif_uref, ivl_signal_basename(sig));
else
sprintf(port_name, "(rename U%uN \"%s[%u]\")",
edif_uref, ivl_signal_basename(sig), idx);
/* Draw the PAD and the I/O BUF, and connect the buffer
to the logic that we are generating. */
switch (ivl_signal_port(sig)) {
case IVL_SIP_INPUT:
fprintf(xnf, "(instance U%uPAD"
@@ -232,10 +266,11 @@ static void edif_show_virtex_pad(ivl_signal_t sig, const char*str)
" (viewRef net "
" (cellRef IBUF (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%uN (joined"
fprintf(xnf, "(net %s (joined"
" (portRef IPAD (instanceRef U%uPAD))"
" (portRef I (instanceRef U%u))))\n",
edif_uref, edif_uref, edif_uref);
port_name, edif_uref, edif_uref);
sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(ivl_signal_pin(sig, idx), jbuf);
@@ -254,10 +289,11 @@ static void edif_show_virtex_pad(ivl_signal_t sig, const char*str)
" (viewRef net "
" (cellRef OBUF (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%uN (joined"
fprintf(xnf, "(net %s (joined"
" (portRef OPAD (instanceRef U%uPAD))"
" (portRef O (instanceRef U%u))))\n",
edif_uref, edif_uref, edif_uref);
port_name, edif_uref, edif_uref);
sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(ivl_signal_pin(sig, idx), jbuf);
@@ -367,7 +403,7 @@ void edif_show_cellref_logic(ivl_net_logic_t net, const char*cellref)
strncpy(tmpname, cellref, cp-cellref);
tmpname[cp-cellref] = 0;
fprintf(xnf, "(instance (rename U%u (string \"%s\"))"
fprintf(xnf, "(instance (rename U%u \"%s\")"
" (viewRef net (cellRef %s (libraryRef VIRTEX))))\n",
edif_uref, ivl_logic_name(net), tmpname);
@@ -395,6 +431,227 @@ void edif_show_cellref_logic(ivl_net_logic_t net, const char*cellref)
}
}
/*
* This function draw wide AND-like devices. The input must have at
* least 5 bits.
*/
static void wide_AND_logic(ivl_net_logic_t net, unsigned edif_uref)
{
char jbuf[1024];
/* This is the number of input bits left to connect. */
unsigned ibits = ivl_logic_pins(net) - 1;
/* Index to the next input bit. */
unsigned idx = 1;
unsigned slice = 0;
const char*lut4_init;
const char*lut3_init;
const char*lut2_init;
const char*lut1_dev;
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
lut4_init = "\"8000\"";
lut3_init = "\"80\"";
lut2_init = "\"8\"";
lut1_dev = "BUF";
break;
case IVL_LO_NOR:
lut4_init = "\"0001\"";
lut3_init = "\"01\"";
lut2_init = "\"1\"";
lut1_dev = "INV";
break;
default:
assert(0);
}
assert(ibits > 4);
while (ibits >= 4) {
/* The least significant bits are ANDed together 4 at a
time with LUT4 devices. The output of the LUT4 device
connects to a MUXCY device that passes its output
up to the next stage.
The DI input of the MUXCY (S==0) is connected to
ground, so that the ouput of the chain is pinned to 0
if this slice does not AND to 1.
If the LUT emits 1, S==1 and this slice passes the
compare from below. So the CI of the MUXCY gets the O
of the MUXCY one slice back. */
fprintf(xnf, "(instance U%uL%u"
" (viewRef net"
" (cellRef LUT4 (libraryRef VIRTEX)))"
" (property INIT (string %s)))\n",
edif_uref, slice, lut4_init);
fprintf(xnf, "(instance U%uM%u"
" (viewRef net"
" (cellRef MUXCY (libraryRef VIRTEX))))\n",
edif_uref, slice);
fprintf(xnf, "(instance U%uG%u"
" (viewRef net"
" (cellRef GND (libraryRef VIRTEX))))\n",
edif_uref, slice);
fprintf(xnf, "(net U%uLM%u (joined"
" (portRef O (instanceRef U%uL%u))"
" (portRef S (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice,
edif_uref, slice);
fprintf(xnf, "(net U%uGM%u (joined"
" (portRef GROUND (instanceRef U%uG%u))"
" (portRef DI (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice,
edif_uref, slice);
if (slice == 0) {
fprintf(xnf, "(instance U%uV%u"
" (viewRef net"
" (cellRef VCC (libraryRef VIRTEX))))\n",
edif_uref, slice);
fprintf(xnf, "(net U%uMM%u (joined"
" (portRef VCC (instanceRef U%uG%u))"
" (portRef CI (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice,
edif_uref, slice);
} else {
fprintf(xnf, "(net U%uMM%u (joined"
" (portRef O (instanceRef U%uM%u))"
" (portReg CI (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice-1,
edif_uref, slice);
}
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
sprintf(jbuf, "(portRef I2 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+2), jbuf);
sprintf(jbuf, "(portRef I3 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+3), jbuf);
ibits -= 4;
idx += 4;
slice += 1;
}
if (ibits == 0) {
sprintf(jbuf, "(portRef O (instanceRef U%uM%u))",
edif_uref, slice-1);
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
return;
}
switch (ibits) {
case 1:
fprintf(xnf, "(instance U%uL%u"
" (viewRef net"
" (cellRef %s (libraryRef VIRTEX))))\n",
edif_uref, slice, lut1_dev);
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
break;
case 2:
fprintf(xnf, "(instance U%uL%u"
" (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX)))"
" (property INIT (string %s)))\n",
edif_uref, slice, lut2_init);
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
break;
case 3:
fprintf(xnf, "(instance U%uL%u"
" (viewRef net"
" (cellRef LUT3 (libraryRef VIRTEX)))"
" (property INIT (string %s)))\n",
edif_uref, slice, lut3_init);
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
sprintf(jbuf, "(portRef I2 (instanceRef U%uL%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, idx+2), jbuf);
break;
default:
assert(0);
}
fprintf(xnf, "(instance U%uM%u"
" (viewRef net"
" (cellRef MUXCY (libraryRef VIRTEX))))\n",
edif_uref, slice);
fprintf(xnf, "(instance U%uG%u"
" (viewRef net"
" (cellRef GND (libraryRef VIRTEX))))\n",
edif_uref, slice);
fprintf(xnf, "(net U%uLM%u (joined"
" (portRef O (instanceRef U%uL%u))"
" (portRef S (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice,
edif_uref, slice);
fprintf(xnf, "(net U%uGM%u (joined"
" (portRef GROUND (instanceRef U%uG%u))"
" (portRef DI (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice,
edif_uref, slice);
fprintf(xnf, "(net U%uMM%u (joined"
" (portRef O (instanceRef U%uM%u))"
" (portReg CI (instanceRef U%uM%u))))\n",
edif_uref, slice,
edif_uref, slice-1,
edif_uref, slice);
sprintf(jbuf, "(portRef O (instanceRef U%uM%u))",
edif_uref, slice);
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
}
static void edif_show_virtex_logic(ivl_net_logic_t net)
{
char jbuf[1024];
@@ -411,7 +668,6 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
switch (ivl_logic_type(net)) {
case IVL_LO_AND:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
switch (ivl_logic_pins(net)) {
@@ -436,6 +692,9 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
ivl_logic_pin(net, 3),
ivl_logic_pin(net, 4), "8000");
break;
default:
wide_AND_logic(net, edif_uref);
break;
}
break;
@@ -454,8 +713,24 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
break;
case IVL_LO_BUFIF1:
assert(ivl_logic_pins(net) == 3);
fprintf(xnf, "(instance (rename U%u \"%s\")",
edif_uref, ivl_logic_name(net));
fprintf(xnf, " (viewRef net"
" (cellRef TBUF (libraryRef VIRTEX))))\n");
sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
sprintf(jbuf, "(portRef T (instanceRef U%u))", edif_uref);
edif_set_nexus_joint(ivl_logic_pin(net, 2), jbuf);
break;
case IVL_LO_NOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
switch (ivl_logic_pins(net)) {
@@ -480,6 +755,9 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
ivl_logic_pin(net, 3),
ivl_logic_pin(net, 4), "0001");
break;
default:
wide_AND_logic(net, edif_uref);
break;
}
break;
@@ -1161,12 +1439,18 @@ static void edif_show_virtex_add(ivl_lpm_t net)
unsigned nref = 0;
unsigned ha_init = 6;
edif_uref += 1;
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
ha_init = 6;
fprintf(xnf, "(comment \"U%u implements %u bit ADD.\")\n",
edif_uref, ivl_lpm_width(net));
break;
case IVL_LPM_SUB:
ha_init = 9;
fprintf(xnf, "(comment \"U%u implements %u bit SUB.\")\n",
edif_uref, ivl_lpm_width(net));
break;
default:
assert(0);
@@ -1175,7 +1459,6 @@ static void edif_show_virtex_add(ivl_lpm_t net)
/* Handle the special case that the adder is only one bit
wide. Generate an XOR gate to perform the half-add. */
if (ivl_lpm_width(net) == 1) {
edif_uref += 1;
edif_show_lut2(ivl_lpm_name(net), edif_uref,
ivl_lpm_q(net, 0),
@@ -1186,30 +1469,74 @@ static void edif_show_virtex_add(ivl_lpm_t net)
}
assert(ivl_lpm_width(net) > 1);
edif_uref += 1;
/* First, draw the bottom bit slice of the adder. This
includes the LUT2 device to perform the addition, and a
MUXCY_L device to send the carry up to the next bit. */
fprintf(xnf, "(instance (rename U%u_L0 \"%s\"[0])"
" (property INIT (string \"%u\"))", edif_uref,
ivl_lpm_name(net), ha_init);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
includes the LUT2 device to perform the addition, a
MUXCY_L device to send the carry up to the next bit,
and an XORCY to make the output bit[0]. The latter is not
always needed, but it is free, because the XORCY is this
slice cannot otherwise be used anyhow. */
fprintf(xnf, "(instance U%u_L0"
" (viewRef net (cellRef LUT2 (libraryRef VIRTEX)))"
" (property INIT (string \"%u\")))\n",
edif_uref, ha_init);
fprintf(xnf, "(instance (rename U%u_X0 \"%s[0]\")"
" (viewRef net"
" (cellRef XORCY (libraryRef VIRTEX))))\n",
edif_uref, ivl_lpm_name(net));
fprintf(xnf, "(instance U%u_M0", edif_uref);
fprintf(xnf, " (viewRef net"
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))", edif_uref);
/* If the device is an ADD, then the CI is set to 0. If the
device is really a SUB, then tie the CI to 1. This adds in
the (+1) of the two's complement. */
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
fprintf(xnf, "(instance U%u_FILL"
" (viewRef net"
" (cellRef GND (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%u_FILLN (joined"
" (portRef GROUND (instanceRef U%u_FILL))"
" (portRef CI (instanceRef U%u_M0))"
" (portRef CI (instanceRef U%u_X0))))\n",
edif_uref, edif_uref, edif_uref, edif_uref);
break;
case IVL_LPM_SUB:
fprintf(xnf, "(instance U%u_FILL"
" (viewRef net"
" (cellRef VCC (libraryRef VIRTEX))))\n",
edif_uref);
fprintf(xnf, "(net U%u_FILLN (joined"
" (portRef VCC (instanceRef U%u_FILL))"
" (portRef CI (instanceRef U%u_M0))"
" (portRef CI (instanceRef U%u_X0))))\n",
edif_uref, edif_uref, edif_uref, edif_uref);
break;
default:
assert(0);
}
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))"
" (portRef DI (instanceRef U%u_M0))",
edif_uref, edif_uref);
edif_set_nexus_joint(ivl_lpm_data(net, 0), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L0))", edif_uref);
edif_set_nexus_joint(ivl_lpm_datab(net, 0), jbuf);
sprintf(jbuf, "(portRef O (instanceRef U%u_L0))"
" (portRef S (instanceRef U%u_M0))",
edif_uref, edif_uref);
fprintf(xnf, "(net U%uN%u (joined"
" (portRef O (instanceRef U%u_L0))"
" (portRef S (instanceRef U%u_M0))"
" (portRef LI (instanceRef U%u_X0))))\n",
edif_uref, nref++, edif_uref, edif_uref, edif_uref);
sprintf(jbuf, "(portRef O (instanceRef U%u_X0))", edif_uref);
edif_set_nexus_joint(ivl_lpm_q(net, 0), jbuf);
/* Now draw all the inside bit slices. These include the LUT2
@@ -1219,19 +1546,20 @@ static void edif_show_virtex_add(ivl_lpm_t net)
device, the other devices have local names. */
for (idx = 1 ; idx < (ivl_lpm_width(net)-1) ; idx += 1) {
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"%u\"))",
fprintf(xnf, "(instance U%u_L%u"
" (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX)))"
" (property INIT (string \"%u\")))\n",
edif_uref, idx, ha_init);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance U%u_M%u", edif_uref, idx);
fprintf(xnf, " (viewRef net"
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance (rename U%u_X%u \"%s[%u]\")",
fprintf(xnf, "(instance (rename U%u_X%u \"%s[%u]\")"
" (viewRef net"
" (cellRef XORCY (libraryRef VIRTEX))))\n",
edif_uref, idx, ivl_lpm_name(net), idx);
fprintf(xnf, " (viewRef net"
" (cellRef XORCY (libraryRef VIRTEX))))\n");
fprintf(xnf, "(net U%uN%u (joined"
" (portRef O (instanceRef U%u_L%u))"
@@ -1247,8 +1575,9 @@ static void edif_show_virtex_add(ivl_lpm_t net)
edif_uref, nref++, edif_uref, idx, edif_uref, idx,
edif_uref, idx-1);
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))",
edif_uref, idx);
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))"
" (portRef DI (instanceRef U%u_M%u))",
edif_uref, idx, edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L%u))",
@@ -1261,10 +1590,11 @@ static void edif_show_virtex_add(ivl_lpm_t net)
}
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"%u\"))",
fprintf(xnf, "(instance U%u_L%u"
" (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX)))"
" (property INIT (string \"%u\")))\n",
edif_uref, idx, ha_init);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance (rename U%u_X%u \"%s[%u]\")",
edif_uref, idx, ivl_lpm_name(net), idx);
@@ -1319,16 +1649,20 @@ static void virtex_show_cmp_ge(ivl_lpm_t net)
/* First, draw the bottom bit slice of the comparator. This
includes the LUT2 device to perform the addition, and a
MUXCY_L device to send the carry up to the next bit. */
fprintf(xnf, "(instance (rename U%u_L0 \"%s\"[0])"
" (property INIT (string \"9\"))", edif_uref,
fprintf(xnf, "(instance (rename U%u_L0 \"%s[0]\")"
" (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX)))"
" (property INIT (string \"9\")))\n", edif_uref,
ivl_lpm_name(net));
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance U%u_M0", edif_uref);
fprintf(xnf, " (viewRef net"
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
fprintf(xnf, "(net U%uN%u (joined"
" (portRef O (instanceRef U%u_L0))"
" (portRef S (instanceRef U%u_M0))))\n",
edif_uref, nref++, edif_uref, edif_uref);
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))", edif_uref);
edif_set_nexus_joint(ivl_lpm_data(net, 0), jbuf);
@@ -1366,16 +1700,15 @@ static void virtex_show_cmp_ge(ivl_lpm_t net)
}
/* Now draw all the inside bit slices. These include the LUT2
device for the basic add, the MUXCY_L device to propagate
the carry, and an XORCY device to generate the real
output. The XORCY device carries the name of the LPM
device, the other devices have local names. */
for (idx = 1 ; idx < (ivl_lpm_width(net)-1) ; idx += 1) {
device for the NOR2 and the MUXCY_L device to propagate
the result. */
for (idx = 1 ; idx < (ivl_lpm_width(net)) ; idx += 1) {
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"9\"))",
fprintf(xnf, "(instance U%u_L%u"
" (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX)))"
" (property INIT (string \"9\")))\n",
edif_uref, idx);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(instance U%u_M%u", edif_uref, idx);
fprintf(xnf, " (viewRef net"
@@ -1406,35 +1739,8 @@ static void virtex_show_cmp_ge(ivl_lpm_t net)
}
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"9\"))",
edif_uref, idx);
fprintf(xnf, " (viewRef net"
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
fprintf(xnf, "(net U%uN%u (joined"
" (portRef O (instanceRef U%u_L%u))"
" (portRef LI (instanceRef U%u_X%u))))\n",
edif_uref, nref++, edif_uref, idx, edif_uref, idx);
fprintf(xnf, "(net U%uN%u (joined"
" (portRef CI (instanceRef U%u_X%u))"
" (portRef LO (instanceRef U%u_M%u))))\n",
edif_uref, nref++, edif_uref, idx, edif_uref, idx-1);
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_datab(net, idx), jbuf);
sprintf(jbuf, "(portRef DI (instanceRef U%u_M%u))",
edif_uref, idx);
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
sprintf(jbuf, "(portRef LO (instanceRef U%u_M%u))",
edif_uref, idx);
edif_uref, idx-1);
edif_set_nexus_joint(ivl_lpm_q(net, 0), jbuf);
}
@@ -1546,14 +1852,25 @@ static void virtex_show_shiftl(ivl_lpm_t net)
through, and the B side which is shifted based on the
selector identity. */
for (sdx = 0 ; sdx < (nsel-1) ; sdx += 1) {
unsigned shift = 1 << sdx;
unsigned shift = 2 << sdx;
for (qdx = 0 ; qdx < shift ; qdx += 1) {
for (qdx = 0 ; qdx < (width-shift) ; qdx += 1) {
fprintf(xnf, "(net U%uC%uR%uN (joined"
" (portRef O (instanceRef U%uC%uR%u))"
" (portRef I0 (instanceRef U%uC%uR%u))"
" (portRef I1 (instanceRef U%uC%uR%u))))\n",
edif_uref, sdx, qdx,
edif_uref, sdx, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx + shift);
}
for (qdx = (width-shift) ; qdx < width ; qdx += 1) {
fprintf(xnf, "(net U%uC%uR%uN (joined"
" (portRef O (instanceRef U%uC%uR%u))"
" (portRef I0 (instanceRef U%uC%uR%u))))\n",
edif_uref, sdx, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx, qdx,
edif_uref, sdx+1, qdx);
fprintf(xnf, "(instance U%uC%uR%uG"
@@ -1565,20 +1882,9 @@ static void virtex_show_shiftl(ivl_lpm_t net)
" (portRef I1 (instanceRef U%uC%uR%u))"
" (portRef GROUND (instanceRef U%uC%uR%uG))))\n",
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, (qdx+shift)%width,
edif_uref, sdx+1, qdx);
}
for (qdx = shift ; qdx < width ; qdx += 1) {
fprintf(xnf, "(net U%uC%uR%uN (joined"
" (portRef O (instanceRef U%uC%uR%u))"
" (portRef I0 (instanceRef U%uC%uR%u))"
" (portRef I1 (instancdRef U%uC%uR%u))))\n",
edif_uref, sdx, qdx,
edif_uref, sdx, qdx,
edif_uref, sdx+1, qdx,
edif_uref, sdx+1, qdx - shift);
}
}
}
@@ -1602,6 +1908,23 @@ const struct device_s d_virtex_edif = {
/*
* $Log: d-virtex.c,v $
* Revision 1.21 2002/11/24 02:26:14 steve
* Fix instanceRef spelling.
*
* Revision 1.20 2002/11/22 05:46:06 steve
* Handle wide AND/NOR devices with Virtex carry logic.
*
* Revision 1.19 2002/11/22 01:45:40 steve
* Implement bufif1 as BUFT
*
* Revision 1.18 2002/11/01 02:36:34 steve
* Fix bottom bit of ADD/SUB device.
*
* Revision 1.17 2002/10/30 03:58:45 steve
* Fix up left shift to pass compile,
* fix up ADD/SUB to generate missing pieces,
* Add the asynch set/reset to DFF devices.
*
* Revision 1.16 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.6 2001/11/17 17:57:58 steve Exp $"
#ident "$Id: Makefile.in,v 1.7 2002/11/05 02:14:41 steve Exp $"
#
#
SHELL = /bin/sh
@@ -74,7 +74,7 @@ distclean: clean
install: all installdirs $(libdir)/ivl/null.tgt
$(libdir)/ivl/null.tgt: ./null.tgt
$(INSTALL_DATA) ./null.tgt $(libdir)/ivl/null.tgt
$(INSTALL_PROGRAM) ./null.tgt $(libdir)/ivl/null.tgt
installdirs: ../mkinstalldirs
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.8 2001/11/17 17:57:58 steve Exp $"
#ident "$Id: Makefile.in,v 1.9 2002/11/05 02:14:41 steve Exp $"
#
#
SHELL = /bin/sh
@@ -71,7 +71,7 @@ clean:
install: all installdirs $(libdir)/ivl/pal.tgt
$(libdir)/ivl/pal.tgt: ./pal.tgt
$(INSTALL_DATA) ./pal.tgt $(libdir)/ivl/pal.tgt
$(INSTALL_PROGRAM) ./pal.tgt $(libdir)/ivl/pal.tgt
installdirs: ../mkinstalldirs
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.9 2001/11/17 17:57:58 steve Exp $"
#ident "$Id: Makefile.in,v 1.10 2002/11/05 02:14:41 steve Exp $"
#
#
SHELL = /bin/sh
@@ -72,7 +72,7 @@ install: all installdirs $(libdir)/ivl/stub.tgt \
$(includedir)/vpi_user.h
$(libdir)/ivl/stub.tgt: ./stub.tgt
$(INSTALL_DATA) ./stub.tgt $(libdir)/ivl/stub.tgt
$(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt
installdirs: ../mkinstalldirs
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.8 2001/11/17 17:57:58 steve Exp $"
#ident "$Id: Makefile.in,v 1.9 2002/11/05 02:14:41 steve Exp $"
#
#
SHELL = /bin/sh
@@ -71,7 +71,7 @@ install: all installdirs $(libdir)/ivl/verilog.tgt \
$(includedir)/vpi_user.h
$(libdir)/ivl/verilog.tgt: ./verilog.tgt
$(INSTALL_DATA) ./verilog.tgt $(libdir)/ivl/verilog.tgt
$(INSTALL_PROGRAM) ./verilog.tgt $(libdir)/ivl/verilog.tgt
installdirs: ../mkinstalldirs
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.11 2002/09/27 16:33:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.12 2002/11/05 02:14:41 steve Exp $"
#
#
SHELL = /bin/sh
@@ -78,7 +78,7 @@ check: all
install: all installdirs $(libdir)/ivl/vvp.tgt
$(libdir)/ivl/vvp.tgt: ./vvp.tgt
$(INSTALL_DATA) ./vvp.tgt $(libdir)/ivl/vvp.tgt
$(INSTALL_PROGRAM) ./vvp.tgt $(libdir)/ivl/vvp.tgt
installdirs: ../mkinstalldirs
+137 -30
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.82 2002/10/20 02:55:37 steve Exp $"
#ident "$Id: eval_expr.c,v 1.86 2002/11/22 00:01:50 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -28,6 +28,8 @@
# include <stdlib.h>
# include <assert.h>
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
int ok_flags);
int number_is_unknown(ivl_expr_t ex)
{
@@ -659,15 +661,51 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
}
}
lv = draw_eval_expr_wid(le, wid, 0);
switch (ivl_expr_opcode(exp)) {
case 'l': /* << (left shift) */
lv = draw_eval_expr_wid(le, wid, 0);
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
break;
case 'r': /* >> (unsigned right shift) */
/* with the right shift, there may be high bits that are
shifted into the desired width of the expression, so
we let the expression size itself, if it is bigger
then what is requested of us. */
if (wid > ivl_expr_width(le)) {
lv = draw_eval_expr_wid(le, wid, 0);
} else {
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
}
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lv.base, lv.wid);
break;
@@ -990,22 +1028,26 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
avec.base = allocate_vector_exp(arg, awid);
avec.wid = awid;
/* If it's not in the lookaside map, then
evaluate the expression here. */
if (avec.base == 0) {
/* Evaluate this sub expression. */
avec = draw_eval_expr_wid(arg, awid, 0);
}
trans = awid;
if ((off + awid) > wid)
trans = wid - off;
assert(awid == avec.wid);
if (avec.base != 0) {
assert(awid == avec.wid);
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
res.base+off,
avec.base, trans);
clr_vector(avec);
} else {
struct vector_info dest;
dest.base = res.base+off;
dest.wid = trans;
draw_eval_expr_dest(arg, dest, 0);
}
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base+off,
avec.base, trans);
clr_vector(avec);
idx -= 1;
off += trans;
@@ -1171,36 +1213,54 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
* offsetting the read from the lsi (least significant index) of the
* signal.
*/
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
{
unsigned idx;
unsigned lsi = ivl_expr_lsi(exp);
unsigned swid = ivl_expr_width(exp);
ivl_signal_t sig = ivl_expr_signal(exp);
if (swid > res.wid)
swid = res.wid;
if (ivl_signal_type(sig) == IVL_SIT_REG) {
/* If this is a REG (a variable) then I can do a vector
read. */
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
res.base, vvp_signal_label(sig), lsi, swid);
} else {
/* Vector reads of nets do not in general work because
they are not really functors but references to
scattered functors. So generate an array of loads. */
for (idx = 0 ; idx < swid ; idx += 1) {
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx, vvp_signal_label(sig), idx+lsi);
}
}
/* Pad the signal value with zeros. */
if (swid < res.wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, res.wid-swid);
}
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
if (swid > wid)
swid = wid;
/* Already in the vector lookaside? */
res.base = allocate_vector_exp(exp, wid);
res.wid = wid;
if (res.base != 0)
return res;
if (res.base == 0) {
res.base = allocate_vector(wid);
res.wid = wid;
save_expression_lookaside(res.base, exp, wid);
}
res.base = allocate_vector(wid);
res.wid = wid;
save_expression_lookaside(res.base, exp, wid);
for (idx = 0 ; idx < swid ; idx += 1)
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx, vvp_signal_label(sig), idx+lsi);
/* Pad the signal value with zeros. */
if (swid < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
draw_signal_dest(exp, res);
return res;
}
@@ -1794,6 +1854,41 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
return res;
}
/*
* Sometimes we know ahead of time where we want the expression value
* to go. In that case, call this function. It will check to see if
* the expression can be preplaced, and if so it will evaluate it in
* place.
*/
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
int stuff_ok_flag)
{
struct vector_info tmp;
switch (ivl_expr_type(exp)) {
case IVL_EX_SIGNAL:
draw_signal_dest(exp, dest);
return;
default:
break;
}
/* Fallback, is to draw the expression by width, and mov it to
the required dest. */
tmp = draw_eval_expr_wid(exp, dest.wid, stuff_ok_flag);
assert(tmp.wid == dest.wid);
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
dest.base, tmp.base, dest.wid);
if (tmp.base >= 8)
save_expression_lookaside(tmp.base, exp, tmp.wid);
clr_vector(tmp);
}
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
int stuff_ok_flag)
{
@@ -1868,6 +1963,18 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.86 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
* Revision 1.85 2002/11/21 22:42:48 steve
* Allow right values of right shift to shift in.
*
* Revision 1.84 2002/11/07 03:12:17 steve
* Vectorize load from REG variables.
*
* Revision 1.83 2002/11/06 05:41:37 steve
* Concatenation can evaluate sub-expressions in place.
*
* Revision 1.82 2002/10/20 02:55:37 steve
* Properly set or clear expression lookaside for binary expressions.
*
+164 -45
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_process.c,v 1.71 2002/09/27 20:24:42 steve Exp $"
#ident "$Id: vvp_process.c,v 1.76 2002/11/21 22:43:13 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -71,17 +71,25 @@ unsigned bitchar_to_idx(char bit)
* nexus.
*/
static void set_to_lvariable(ivl_lval_t lval, unsigned idx, unsigned bit)
static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
unsigned bit, unsigned wid)
{
ivl_signal_t sig = ivl_lval_sig(lval);
unsigned part_off = ivl_lval_part_off(lval);
if (ivl_lval_mux(lval))
fprintf(vvp_out, " %%set/x V_%s, %u, 0;\n",
vvp_signal_label(sig), bit);
else
if (ivl_lval_mux(lval)) {
assert(wid == 1);
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
vvp_signal_label(sig), bit, ivl_signal_pins(sig)-1);
} else if (wid == 1) {
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
vvp_signal_label(sig), idx+part_off, bit);
} else {
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n",
vvp_signal_label(sig), idx+part_off, bit, wid);
}
}
static void set_to_memory(ivl_memory_t mem, unsigned idx, unsigned bit)
@@ -116,6 +124,19 @@ static void assign_to_lvariable(ivl_lval_t lval, unsigned idx,
idx+part_off, delay, bit);
}
static void assign_to_lvector(ivl_lval_t lval, unsigned idx,
unsigned bit, unsigned delay, unsigned width)
{
ivl_signal_t sig = ivl_lval_sig(lval);
unsigned part_off = ivl_lval_part_off(lval);
assert(ivl_lval_mux(lval) == 0);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n",
vvp_signal_label(sig), part_off+idx, delay, bit);
}
static void assign_to_memory(ivl_memory_t mem, unsigned idx,
unsigned bit, unsigned delay)
{
@@ -170,6 +191,8 @@ static int show_stmt_assign(ivl_statement_t net)
value and write it into index0. */
if (ivl_lval_mux(lval)) {
calculate_into_x0(ivl_lval_mux(lval));
/* Generate code to skip around the set
if the index has X values. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
skip_set_flag = 1;
}
@@ -177,6 +200,8 @@ static int show_stmt_assign(ivl_statement_t net)
mem = ivl_lval_mem(lval);
if (mem) {
draw_memory_index_expr(mem, ivl_lval_idx(lval));
/* Generate code to skip around the set
if the index has X values. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
skip_set_flag = 1;
}
@@ -198,16 +223,26 @@ static int show_stmt_assign(ivl_statement_t net)
} else {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
set_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]));
idx = 0;
while (idx < bit_limit) {
unsigned cnt = 1;
while (((idx + cnt) < bit_limit)
&& (bits[cur_rbit] == bits[cur_rbit+cnt]))
cnt += 1;
cur_rbit += 1;
set_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
cnt);
cur_rbit += cnt;
idx += cnt;
}
for (idx = bit_limit
; idx < ivl_lval_pins(lval) ; idx += 1)
set_to_lvariable(lval, idx, 0);
if (bit_limit < ivl_lval_pins(lval)) {
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
set_to_lvariable(lval, bit_limit, 0, cnt);
}
}
if (skip_set_flag) {
@@ -249,23 +284,32 @@ static int show_stmt_assign(ivl_statement_t net)
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
for (idx = 0 ; idx < bit_limit ; idx += 1) {
if (mem) {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
unsigned bidx = res.base < 4
? res.base
: (res.base+cur_rbit);
set_to_memory(mem, idx, bidx);
cur_rbit += 1;
}
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
set_to_memory(mem, idx, 0);
} else {
unsigned bidx = res.base < 4
? res.base
: (res.base+cur_rbit);
if (mem)
set_to_memory(mem, idx, bidx);
else
set_to_lvariable(lval, idx, bidx);
set_to_lvariable(lval, 0, bidx, bit_limit);
cur_rbit += bit_limit;
cur_rbit += 1;
if (bit_limit < ivl_lval_pins(lval)) {
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
set_to_lvariable(lval, bit_limit, 0, cnt);
}
}
for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1)
if (mem)
set_to_memory(mem, idx, 0);
else
set_to_lvariable(lval, idx, 0);
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
@@ -345,6 +389,54 @@ static int show_stmt_assign_nb(ivl_statement_t net)
; idx += 1) {
assign_to_memory(mem, idx, 0, delay);
}
} else if ((del == 0) && (bit_limit > 2)) {
/* We have a vector, but no runtime
calculated delays, to try to use vector
assign instructions. */
idx = 0;
while (idx < bit_limit) {
unsigned wid = 0;
do {
wid += 1;
if ((idx + wid) == bit_limit)
break;
} while (bits[cur_rbit] == bits[cur_rbit+wid]);
switch (wid) {
case 1:
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
break;
case 2:
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
assign_to_lvariable(lval, idx+1,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
break;
default:
assign_to_lvector(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, wid);
break;
}
idx += wid;
cur_rbit += wid;
}
if (bit_limit < ivl_lval_pins(lval)) {
unsigned wid = ivl_lval_pins(lval) - bit_limit;
assign_to_lvector(lval, bit_limit,
0, delay, wid);
}
} else {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
if (del != 0)
@@ -412,29 +504,39 @@ static int show_stmt_assign_nb(ivl_statement_t net)
if (bit_limit > ivl_lval_pins(lval))
bit_limit = ivl_lval_pins(lval);
for (idx = 0 ; idx < bit_limit ; idx += 1) {
if ((bit_limit > 2) && (mem == 0) && (del == 0)) {
unsigned bidx = res.base < 4
? res.base
: (res.base+cur_rbit);
if (mem)
assign_to_memory(mem, idx, bidx, delay);
else if (del != 0)
assign_to_lvariable(lval, idx, bidx,
1, 1);
else
assign_to_lvariable(lval, idx, bidx,
delay, 0);
assign_to_lvector(lval, 0, bidx, delay, bit_limit);
cur_rbit += bit_limit;
cur_rbit += 1;
} else {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
unsigned bidx = res.base < 4
? res.base
: (res.base+cur_rbit);
if (mem)
assign_to_memory(mem, idx, bidx, delay);
else if (del != 0)
assign_to_lvariable(lval, idx, bidx,
1, 1);
else
assign_to_lvariable(lval, idx, bidx,
delay, 0);
cur_rbit += 1;
}
}
for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1)
if (mem)
assign_to_memory(mem, idx, 0, delay);
else if (del != 0)
assign_to_lvariable(lval, idx, 0, 1, 1);
else
assign_to_lvariable(lval, idx, 0, delay, 0);
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
if (mem)
assign_to_memory(mem, idx, 0, delay);
else if (del != 0)
assign_to_lvariable(lval, idx, 0, 1, 1);
else
assign_to_lvariable(lval, idx, 0, delay, 0);
if (skip_set_flag) {
@@ -761,6 +863,7 @@ static int show_stmt_force(ivl_statement_t net)
ivl_lval_t lval;
ivl_signal_t lsig;
unsigned idx;
static unsigned force_functor_label = 0;
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
@@ -770,16 +873,17 @@ static int show_stmt_force(ivl_statement_t net)
assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0);
force_functor_label += 1;
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
fprintf(vvp_out, "f_%s.%u .force V_%s[%u], %s;\n",
vvp_signal_label(lsig), idx,
fprintf(vvp_out, "f_%u.%u .force V_%s[%u], %s;\n",
force_functor_label, idx,
vvp_signal_label(lsig), idx,
draw_net_input(ivl_stmt_nexus(net, idx)));
}
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
fprintf(vvp_out, " %%force f_%s.%u, 1;\n",
vvp_signal_label(lsig), idx);
fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
force_functor_label, idx);
}
return 0;
}
@@ -1345,6 +1449,21 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.76 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.75 2002/11/17 18:31:09 steve
* Generate unique labels for force functors.
*
* Revision 1.74 2002/11/08 05:00:31 steve
* Use the vectorized %assign where appropriate.
*
* Revision 1.73 2002/11/07 05:19:55 steve
* Use Vector %set to set constants in variables.
*
* Revision 1.72 2002/11/07 03:12:18 steve
* Vectorize load from REG variables.
*
* Revision 1.71 2002/09/27 20:24:42 steve
* Allow expression lookaside map to spam statements.
*
+20 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.80 2002/10/23 04:39:35 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.81 2002/11/21 18:08:09 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -1367,10 +1367,21 @@ static void draw_lpm_ff(ivl_lpm_t net)
static void draw_lpm_shiftl(ivl_lpm_t net)
{
unsigned idx, width, selects;
unsigned selwid;
width = ivl_lpm_width(net);
selects = ivl_lpm_selects(net);
/* The .shift device can only take as many select inputs as
the width of the device.
XXXX I should make some sort of overflow gate for this? If
any high bits are set, then the shift is certain to be
*way* beyond the width of the left shifted value. XXXX */
selwid = selects;
if (selwid > width)
selwid = width;
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
fprintf(vvp_out, "L_%s .shift/r %u",
vvp_mangle_id(ivl_lpm_name(net)), width);
@@ -1383,11 +1394,15 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
draw_input_from_net(ivl_lpm_data(net, idx));
}
for (idx = 0 ; idx < selects ; idx += 1) {
for (idx = 0 ; idx < selwid ; idx += 1) {
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_select(net, idx));
}
for (idx = selwid ; idx < width ; idx += 1) {
fprintf(vvp_out, ", C<0>");
}
fprintf(vvp_out, ";\n");
}
@@ -1592,6 +1607,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.81 2002/11/21 18:08:09 steve
* Better handling of select width of shifters.
*
* Revision 1.80 2002/10/23 04:39:35 steve
* draw lpm ff with aset_expr taken into account.
*
+3 -3
View File
@@ -1,10 +1,10 @@
Summary: Icarus Verilog
Name: verilog
Version: 0.6.20021027
Version: 0.7
Release: 0
Copyright: GPL
Group: Applications/Engineering
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20021027.tar.gz
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-0.7.tar.gz
URL: http://www.icarus.com/eda/verilog/index.html
Packager: Stephen Williams <[email protected]>
@@ -20,7 +20,7 @@ engineering formats, including simulation. It strives to be true
to the IEEE-1364 standard.
%prep
%setup -n verilog-20021027
%setup -n verilog-0.7
%build
./configure --prefix=/usr
+27 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_display.c,v 1.45 2002/09/06 04:56:28 steve Exp $"
#ident "$Id: sys_display.c,v 1.46 2002/11/09 06:01:11 steve Exp $"
#endif
# include "config.h"
@@ -609,6 +609,29 @@ static int format_str(vpiHandle scope, unsigned int mcd,
cp += 1;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
if (isdigit(cp[0])
&& isdigit(cp[1])
&& isdigit(cp[2])) {
/* handle octal escapes (e.g. "\015" is CR)*/
vpi_mcd_printf(mcd, "%c",
(cp[2] - '0') +
8 * ((cp[1] - '0') +
8 * (cp[0] - '0')));
cp += 3;
} else {
vpi_mcd_printf(mcd, "%c", *cp);
cp += 1;
}
break;
default:
vpi_mcd_printf(mcd, "%c", *cp);
cp += 1;
@@ -1461,6 +1484,9 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.46 2002/11/09 06:01:11 steve
* display octal escapes properly.
*
* Revision 1.45 2002/09/06 04:56:28 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
+7 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_lxt.c,v 1.11 2002/08/15 02:12:20 steve Exp $"
#ident "$Id: sys_lxt.c,v 1.12 2002/11/17 22:28:42 steve Exp $"
#endif
# include "config.h"
@@ -460,6 +460,9 @@ static int sys_dumpfile_calltf(char*name)
path = strdup("dumpfile.lxt");
}
if (dump_file)
close_dumpfile();
assert(dump_file == 0);
open_dumpfile(path);
@@ -814,6 +817,9 @@ void sys_lxt_register()
/*
* $Log: sys_lxt.c,v $
* Revision 1.12 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
* Revision 1.11 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
+13 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_vcd.c,v 1.37 2002/08/15 02:12:20 steve Exp $"
#ident "$Id: sys_vcd.c,v 1.39 2002/11/17 22:28:42 steve Exp $"
#endif
# include "config.h"
@@ -146,7 +146,7 @@ inline static void vcd_names_add(const char *name)
struct vcd_names_s *nl = (struct vcd_names_s *)
malloc(sizeof(struct vcd_names_s));
assert(nl);
nl->name = name;
nl->name = strdup(name);
nl->next = vcd_names_list;
vcd_names_list = nl;
listed_names ++;
@@ -449,6 +449,11 @@ static int sys_dumpfile_calltf(char*name)
path = strdup("dumpfile.vcd");
}
if (dump_file) {
fclose(dump_file);
dump_file = 0;
}
assert(dump_file == 0);
open_dumpfile(path);
@@ -844,6 +849,12 @@ void sys_vcd_register()
/*
* $Log: sys_vcd.c,v $
* Revision 1.39 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
* Revision 1.38 2002/11/14 22:43:58 steve
* Save vpiFullName results.
*
* Revision 1.37 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
+10 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.c,v 1.6 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: vpithunk.c,v 1.7 2002/12/11 23:55:22 steve Exp $"
#endif
#include <stdio.h>
@@ -188,6 +188,11 @@ extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index)
VPIT_CALL(vpi_handle_by_index,0,(ref, index));
}
extern vpiHandle vpi_handle_by_name(char *name, vpiHandle scope)
{
VPIT_CALL(vpi_handle_by_name,0,(name, scope));
}
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t)
{
VPITV_CALL(vpi_get_time, (obj,t));
@@ -232,6 +237,10 @@ extern int vpi_chk_error(p_vpi_error_info info)
/*
* $Log: vpithunk.c,v $
* Revision 1.7 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.6 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+9 -2
View File
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: vpithunk.h,v 1.5 2002/12/11 23:55:22 steve Exp $"
#endif
/* These functions are actually defined in lieu of the vpi functions
@@ -38,7 +38,9 @@ extern void vpi_sim_vcontrol(int operation, va_list ap);
EXTERN_C_END
#define VPI_THUNK_MAGIC (0x87836BA4)
/* before v0.7: 0x87836BA4 */
/* v0.7 thunk magic is 0x87836BA5 */
#define VPI_THUNK_MAGIC (0x87836BA5)
typedef struct {
int magic;
@@ -67,6 +69,7 @@ typedef struct {
int (*vpi_free_object)(vpiHandle ref);
int (*vpi_get_vlog_info)(p_vpi_vlog_info vlog_info_p);
int (*vpi_chk_error)(p_vpi_error_info info);
vpiHandle (*vpi_handle_by_name)(char *name, vpiHandle scope);
} vpi_thunk, *p_vpi_thunk;
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
@@ -75,6 +78,10 @@ DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
/*
* $Log: vpithunk.h,v $
* Revision 1.5 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.4 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+1
View File
@@ -10,6 +10,7 @@ Makefile
lexor.cc
parse.cc
parse.cc.output
parse.output
parse.h
tables.cc
vvp
+14 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: codes.h,v 1.51 2002/09/18 04:29:55 steve Exp $"
#ident "$Id: codes.h,v 1.54 2002/11/21 22:43:13 steve Exp $"
#endif
@@ -42,6 +42,7 @@ extern bool of_ANDR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_BLEND(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
@@ -74,6 +75,7 @@ extern bool of_JOIN(vthread_t thr, vvp_code_t code);
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_MEM(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_X(vthread_t thr, vvp_code_t code);
extern bool of_MOD(vthread_t thr, vvp_code_t code);
extern bool of_MOV(vthread_t thr, vvp_code_t code);
@@ -89,7 +91,8 @@ extern bool of_ORR(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
extern bool of_SET(vthread_t thr, vvp_code_t code);
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
extern bool of_SET_X(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
extern bool of_SET_X0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code);
@@ -157,6 +160,15 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
/*
* $Log: codes.h,v $
* Revision 1.54 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.53 2002/11/08 04:59:57 steve
* Add the %assign/v0 instruction.
*
* Revision 1.52 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.51 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
+15 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.143 2002/09/18 04:29:55 steve Exp $"
#ident "$Id: compile.cc,v 1.146 2002/11/21 22:43:13 steve Exp $"
#endif
# include "arith.h"
@@ -87,8 +87,9 @@ const static struct opcode_table_s opcode_table[] = {
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
@@ -119,6 +120,7 @@ const static struct opcode_table_s opcode_table[] = {
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%load/m", of_LOAD_MEM,2, {OA_BIT1, OA_MEM_PTR, OA_NONE} },
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/x", of_LOAD_X, 3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%mod", of_MOD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@@ -134,7 +136,8 @@ const static struct opcode_table_s opcode_table[] = {
{ "%release",of_RELEASE,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
{ "%set/x", of_SET_X, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@@ -1480,6 +1483,15 @@ void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
/*
* $Log: compile.cc,v $
* Revision 1.146 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.145 2002/11/08 04:59:58 steve
* Add the %assign/v0 instruction.
*
* Revision 1.144 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.143 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
+1 -1
View File
@@ -146,7 +146,7 @@ CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
+18 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_dlfcn.h,v 1.5 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: ivl_dlfcn.h,v 1.6 2002/11/05 02:11:56 steve Exp $"
#endif
#if defined(__MINGW32__)
@@ -45,7 +45,20 @@ 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;}
{
static char msg[256];
unsigned long err = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
sizeof(msg) - 1,
NULL
);
return msg;
}
#elif defined(HAVE_DLFCN_H)
inline ivl_dll_t ivl_dlopen(const char*name)
@@ -77,6 +90,9 @@ inline const char*dlerror(void)
/*
* $Log: ivl_dlfcn.h,v $
* Revision 1.6 2002/11/05 02:11:56 steve
* Better error message for load failure on Windows.
*
* Revision 1.5 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+21 -7
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams ([email protected])
*
* $Id: opcodes.txt,v 1.42 2002/09/18 04:29:55 steve Exp $
* $Id: opcodes.txt,v 1.45 2002/11/21 22:43:13 steve Exp $
*/
@@ -49,6 +49,7 @@ means the following:
* %assign <var-label>, <delay>, <bit>
* %assign/d <var-label>, <delay>, <bit>
* %assign/v0 <var-label>, <delay>, <bit>
This does a non-blocking assignment to a variable. The <label>
identifies the affected variable, and the <delay> gives the delay when
@@ -60,6 +61,8 @@ The %assign/d instruction is exactly the same as the %assign
instruction, except that the <delay> specifies one of the index
registers, that contain a calculated delay.
The %assign/v0 instruction is a vector version of %assign, with the
vector width in index register 0.
* %assign/m <memory-label>, <delay>, <bit>
@@ -297,6 +300,7 @@ ended, then the %join does not block or yield the thread.
* %load <bit>, <functor-label>
* %load/v <bit>, <functor-label>, <wid>
This instruction loads a value from the given functor output into the
specified thread register bit. The functor-label can refer to a .net,
@@ -304,6 +308,8 @@ a .var or a .functor, and may be indexed with array syntax to get at a
functor within a vector of functors. This instruction loads only a
single bit.
THe %load/v instruction is a vector version, that loads an entire
vector, starting at the given <bit> and functor.
* %load/m <bit>, <memory-label>
@@ -431,6 +437,7 @@ semantics. Like:
* %set <var-label>, <bit>
* %set/v <var-label>, <bit>, <wid>
This sets a bit of a variable, and is used to implement blocking
assignments. The <label> identifies the variable to receive the new
@@ -438,6 +445,11 @@ value. Once the set completes, the value is immediately available to
be read out of the variable. The <bit> is the address of the thread
register that contains the bit value to assign.
The %set/v instrunction is the same as the %set, but it adds a width
for a vector. The bits are written out in order, starting at the
addressed variable bit and working up. If the <bit> is one of the
constant bits, then the value is repeated for the width. Otherwise,
the vector is taken from increasing thread bit addresses.
* %set/m <memory-label>, <bit>
@@ -447,15 +459,17 @@ address zero is the LSB of the first memory word. This instruction
sets only a single bit.
* %set/x <var-label>, <bit>, <idx>
* %set/x0 <var-label>, <bit>, <top>
This sets the bit of a variable functor, the address calculated by
using the index register <idx> (0, 1, 2 or 3) to index the functor
address of <var-label>.
using the index register 0 to index the functor address of
<var-label>.
If the index value in index register <idx> is <0 (for example if
%ix/get converted an unknown value into the register) then the set is
not performed.
If the index value in index register is <0 (for example if %ix/get
converted an unknown value into the register) then the set is not
performed. Also, if the index value is > the immediate top value, then
the set is not performed. The 0 and <top> values suffice to provide
complete bounds checking.
* %shiftl/i0 <bit>, <wid>
+50 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_const.cc,v 1.19 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: vpi_const.cc,v 1.21 2002/11/03 20:33:43 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -335,6 +335,49 @@ static void binary_value(vpiHandle ref, p_vpi_value vp)
break;
}
case vpiVectorVal: {
unsigned int obit = 0;
unsigned hwid = (rfp->nbits - 1)/32 + 1;
char*rbuf = need_result_buf(hwid*sizeof(s_vpi_vecval), RBUF_VAL);
s_vpi_vecval *op = (p_vpi_vecval)rbuf;
vp->value.vector = op;
op->aval = op->bval = 0;
for (unsigned idx = 0 ; idx < rfp->nbits ; idx += 1) {
unsigned nibble = idx/4;
unsigned shift = 2 * (idx%4);
unsigned bit_val = (rfp->bits[nibble] >> shift) & 3;
switch (bit_val) {
case 0:
op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit);
break;
case 1:
op->aval |= (1 << obit);
op->bval &= ~(1 << obit);
break;
case 2:
op->aval |= (1 << obit);
op->bval |= (1 << obit);
break;
case 3:
op->aval &= ~(1 << obit);
op->bval |= (1 << obit);
break;
}
obit++;
if (!(obit % 32)) {
op += 1;
if ((op - vp->value.vector) < (long)hwid)
op->aval = op->bval = 0;
obit = 0;
}
}
break;
}
case vpiStringVal:
binary_vpiStringVal(rfp, vp);
break;
@@ -514,6 +557,12 @@ vpiHandle vpip_make_dec_const(int value)
/*
* $Log: vpi_const.cc,v $
* Revision 1.21 2002/11/03 20:33:43 steve
* Compiler error wrt ptrdiff_t.
*
* Revision 1.20 2002/11/03 02:07:24 steve
* Get VectorVals from constant values.
*
* Revision 1.19 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+11 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.cc,v 1.24 2002/08/24 05:02:58 steve Exp $"
#ident "$Id: vpi_priv.cc,v 1.25 2002/12/11 23:55:22 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -133,6 +133,12 @@ int vpi_get(int property, vpiHandle ref)
char* vpi_get_str(int property, vpiHandle ref)
{
if (ref == 0) {
fprintf(stderr, "vpi error: vpi_get_str(%d, ...) called "
"with null vpiHandle.\n", property);
return 0;
}
assert(ref);
if (ref->vpi_type->vpi_get_str_ == 0)
return 0;
@@ -363,6 +369,10 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
/*
* $Log: vpi_priv.cc,v $
* Revision 1.25 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.24 2002/08/24 05:02:58 steve
* Fix = vs == error.
*
+22 -20
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_scope.cc,v 1.20 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_scope.cc,v 1.21 2002/11/15 22:14:12 steve Exp $"
#endif
# include "compile.h"
@@ -100,20 +100,29 @@ static vpiHandle scope_get_handle(int code, vpiHandle obj)
/* compares vpiType's considering object classes */
static int compare_types(int code, int type)
{
if ( code == type
|| (code == vpiInternalScope &&
/* NOTE: The Verilog VPI does not for any object support
vpiScope as an iterator parameter, so it is used here as a
means to scan everything in the *current* scope. */
if (code == vpiScope)
return 1;
if (code == type)
return 1;
if ( code == vpiInternalScope &&
(type == vpiModule ||
type == vpiFunction ||
type == vpiTask ||
type == vpiNamedBegin ||
type == vpiNamedFork))
|| (code == vpiVariables &&
type == vpiNamedFork) )
return 1;
if ( code == vpiVariables &&
(type == vpiIntegerVar ||
type == vpiTimeVar))
)
return 1;
else
return 0;
return 1;
return 0;
}
static vpiHandle module_iter_subset(int code, struct __vpiScope*ref)
@@ -153,17 +162,7 @@ static vpiHandle module_iter(int code, vpiHandle obj)
|| (obj->vpi_type->type_code == vpiNamedBegin)
|| (obj->vpi_type->type_code == vpiNamedFork));
switch (code) {
case vpiInternalScope:
case vpiMemory:
case vpiModule:
case vpiNamedEvent:
case vpiNet:
case vpiReg:
return module_iter_subset(code, ref);
}
return 0;
return module_iter_subset(code, ref);
}
/*
@@ -407,6 +406,9 @@ void vpip_attach_to_current_scope(vpiHandle obj)
/*
* $Log: vpi_scope.cc,v $
* Revision 1.21 2002/11/15 22:14:12 steve
* Add vpiScope iterate on vpiScope objects.
*
* Revision 1.20 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+46 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_signal.cc,v 1.49 2002/09/11 16:06:57 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.50 2002/11/25 23:33:45 steve Exp $"
#endif
/*
@@ -428,9 +428,10 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
}
default:
fprintf(stderr, "vvp internal error: signal_get_value: "
"value type %u not implemented.\n", vp->format);
fprintf(stderr, "vvp internal error: get_value: "
"value type %u not implemented."
" Signal is %s in scope %s\n",
vp->format, rfp->name, rfp->scope->name);
assert(0);
}
}
@@ -450,6 +451,36 @@ static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
fu->put_ostr(val, str, true);
}
static void signal_put_stringval(struct __vpiSignal*rfp, unsigned wid,
const char*str)
{
unsigned idx;
const char*cp;
cp = str + strlen(str);
idx = 0;
while ((idx < wid) && (cp > str)) {
unsigned byte = *--cp;
int bit;
for (bit = 0 ; bit < 8 ; bit += 1) {
if (byte & 1)
functor_poke(rfp, idx, 1, St1);
else
functor_poke(rfp, idx, 0, St0);
byte >>= 1;
idx += 1;
}
}
while (idx < wid) {
functor_poke(rfp, 0, 0, St0);
idx += 1;
}
}
static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
p_vpi_time when, int flags)
{
@@ -641,7 +672,15 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
break;
}
case vpiStringVal:
signal_put_stringval(rfp, wid, vp->value.str);
break;
default:
fprintf(stderr, "vvp internal error: put_value: "
"value type %u not implemented."
" Signal is %s in scope %s\n",
vp->format, rfp->name, rfp->scope->name);
assert(0);
}
@@ -722,6 +761,9 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.50 2002/11/25 23:33:45 steve
* Support put of vpiStringVal to signals.
*
* Revision 1.49 2002/09/11 16:06:57 steve
* Fix wrecked rbuf in vpi_get_str of signals and memories.
*
+99 -7
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vthread.cc,v 1.89 2002/09/21 23:47:30 steve Exp $"
#ident "$Id: vthread.cc,v 1.95 2002/11/22 00:01:50 steve Exp $"
#endif
# include "vthread.h"
@@ -487,6 +487,32 @@ bool of_ASSIGN_D(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* This is %assign/v0 <label>, <delay>, <bit>
* Index register 0 contains a vector width.
*/
bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->index[0];
assert(wid > 0);
assert(wid < 0x10000);
unsigned delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
unsigned char bit_val = thr_get_bit(thr, bit);
schedule_assign(iptr, bit_val, delay);
if (bit >= 4)
bit += 1;
}
return true;
}
bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
@@ -1414,6 +1440,21 @@ bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0];
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
thr_put_bit(thr, bit, functor_get(iptr));
}
return true;
}
bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
@@ -1632,9 +1673,15 @@ bool of_MOV(vthread_t thr, vvp_code_t cp)
unsigned addr2 = (test_addr) / (CPU_WORD_BITS/2);
if (addr1 == addr2) {
unsigned sh1 = cp->bit_idx[0] % (CPU_WORD_BITS/2);
unsigned sh2 = (test_addr+1) % (CPU_WORD_BITS/2);
unsigned sh2 = (test_addr % (CPU_WORD_BITS/2)) + 1;
unsigned long mask;
if ( (sh2-sh1) == CPU_WORD_BITS/2)
mask = 0UL;
else
mask = ULONG_MAX << ((sh2 - sh1) * 2UL);
unsigned long mask = ULONG_MAX << ((sh2 - sh1) * 2UL);
mask = (~mask) << sh1*2UL;
cp->number = ~mask;
@@ -2113,6 +2160,29 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0];
if (bit >= 4) {
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
unsigned char bit_val = thr_get_bit(thr, bit);
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
functor_set(iptr, bit_val, strong_values[bit_val], true);
}
} else {
unsigned char bit_val = strong_values[bit];
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
functor_set(iptr, bit, bit_val, true);
}
}
return true;
}
/*
* Implement the %set/x instruction:
*
@@ -2121,17 +2191,19 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
* The single bit goes into the indexed functor. Abort the instruction
* if the index is <0.
*/
bool of_SET_X(vthread_t thr, vvp_code_t cp)
bool of_SET_X0(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
long idx = thr->index[cp->bit_idx[1]&3];
long idx = thr->index[0];
/* If idx < 0, then the index value is probably generated from
an undefined value. At any rate, this is defined to have no
effect so quit now. */
if (idx < 0) {
if (idx < 0)
return true;
if (idx > cp->bit_idx[1])
return true;
}
/* Form the functor pointer from the base pointer and the
index from the index register. */
@@ -2149,6 +2221,8 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
unsigned wid = cp->number;
unsigned long shift = thr->index[0];
assert(base >= 4);
if (shift >= wid) {
for (unsigned idx = 0 ; idx < wid ; idx += 1)
thr_put_bit(thr, base+idx, 0);
@@ -2422,6 +2496,24 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.95 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
* Revision 1.94 2002/11/21 22:43:14 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.93 2002/11/08 04:59:58 steve
* Add the %assign/v0 instruction.
*
* Revision 1.92 2002/11/07 03:11:43 steve
* functor_set takes bit and strength, not 2 strengths.
*
* Revision 1.91 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.90 2002/11/05 03:46:44 steve
* Fix mask calculate when MOV_b is right on the word boundary.
*
* Revision 1.89 2002/09/21 23:47:30 steve
* Remove some now useless asserts.
*
+6 -1
View File
@@ -1,5 +1,5 @@
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_vpi.cc,v 1.5 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vvp_vpi.cc,v 1.6 2002/12/11 23:55:22 steve Exp $"
#endif
#include <stdarg.h>
@@ -27,6 +27,7 @@ void vvp_vpi_init()
vvpt.vpi_iterate = vpi_iterate;
vvpt.vpi_scan = vpi_scan;
vvpt.vpi_handle_by_index = vpi_handle_by_index;
vvpt.vpi_handle_by_name = vpi_handle_by_name;
vvpt.vpi_get_time = vpi_get_time;
vvpt.vpi_get = vpi_get;
vvpt.vpi_get_str = vpi_get_str;
@@ -39,6 +40,10 @@ void vvp_vpi_init()
/*
* $Log: vvp_vpi.cc,v $
* Revision 1.6 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.5 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*