Compare commits

...
123 Commits
Author SHA1 Message Date
steve 04ada23119 Support in various contexts the $realtime
system task.
2003-01-27 00:14:37 +00:00
steve 46253ed873 Rework expression parsing and elaboration to
accommodate real/realtime values and expressions.
2003-01-26 21:15:58 +00:00
steve 1a9ab8ec84 Remember to save signedness of number. 2003-01-26 21:02:21 +00:00
steve 47db309d30 Support display of real values and constants. 2003-01-26 18:18:36 +00:00
steve 7de4108bad Add %cvt/ir and %cvt/ri instructions, and support
real values passed as arguments to VPI tasks.
2003-01-26 18:16:22 +00:00
steve 9a5a00f836 Add thread word array, and add the instructions,
%add/wr, %cmp/wr, %load/wr, %mul/wr and %set/wr.
2003-01-25 23:48:05 +00:00
steve 07a427bf28 Detect null arguments to concatenation operator. 2003-01-19 00:35:39 +00:00
steve dfc9a9474a Add a dummy function to reduce confusion on some systems. 2003-01-19 00:03:23 +00:00
steve 54206ef92b Make sure to use local system.vpi. 2003-01-18 23:56:06 +00:00
steve ddd43f1378 Add a means to clear the module search path. 2003-01-18 23:55:35 +00:00
steve 38ccb12eb0 Use stringstream in place of sprintf. 2003-01-17 05:49:03 +00:00
steve ca3bf14fb6 Remove useless variable. 2003-01-17 05:48:35 +00:00
steve 982474899b Set proper line text for later bison. 2003-01-17 05:48:02 +00:00
steve ad6ff5562d Missed a case of setting line on an PEident. 2003-01-17 05:47:30 +00:00
steve d4cd1dbd27 Keep some debugging status. 2003-01-16 21:44:46 +00:00
steve 3c1426e631 Detect duplicate module declarations. 2003-01-16 21:44:19 +00:00
steve c3a1a9514f Assert some task definition sanity. 2003-01-16 21:43:52 +00:00
steve f56d763411 Move strstream to ostringstream for compatibility. 2003-01-14 21:16:18 +00:00
steve 4ec91047dd Ignore vvp.exp 2003-01-10 19:02:47 +00:00
steve 0579ae08cd Add missing vpi entry points. 2003-01-10 19:02:21 +00:00
steve 9074999666 Remove thunks from vpi init. 2003-01-10 19:01:38 +00:00
steve 0458ab5a53 Only use libiberty.h if available. 2003-01-10 19:01:04 +00:00
steve 4a3459c87c Spelling fixes. 2003-01-10 03:08:13 +00:00
steve 301cbe31ad Remove vpithunk, and move libvpi to vvp directory. 2003-01-10 03:06:32 +00:00
steve 165dd82bb2 Remove files of vvm directory. 2003-01-10 03:05:05 +00:00
steve 9c3b3246c8 use userdata to save $display argument handles. 2003-01-09 04:10:58 +00:00
steve 6416f8b90e Add vpi_put_userdata 2003-01-09 04:09:44 +00:00
steve e6eae5fd15 Allocate res-buf in bigger chunks 2003-01-07 18:07:50 +00:00
steve aa3a6dba4e Schedule wait lists of threads as a single event,
to save on events. Also, improve efficiency of
 event_s allocation. Add some event statistics to
 get an idea where performance is really going.
2003-01-06 23:57:26 +00:00
steve dedae73761 Account for local units in calculated delays. 2002-12-21 19:42:17 +00:00
steve d7f3d00f5c Rewrite time formatting to account for local scope. 2002-12-21 19:41:49 +00:00
steve c2070777b2 The $time system task returns the integer time
scaled to the local units. Change the internal
 implementation of vpiSystemTime the $time functions
 to properly account for this. Also add $simtime
 to get the simulation time.
2002-12-21 00:55:57 +00:00
steve 42b34c2ce6 Evaluate shift index after shift operand because
the chift operand may use the index register itself.
2002-12-20 01:11:14 +00:00
steve 6fbfdd8f3f Keep bit select subexpression width if it is constant. 2002-12-19 23:11:29 +00:00
steve bee3acfd12 Add tf_message, tf_get/setworkarea, and
ty_typep functions, along with defines
 related to these functions.
2002-12-19 21:37:04 +00:00
steve 2e279b61dd Update to 0.7 release. 2002-12-14 18:20:14 +00:00
steve 8ab909a765 Add vpi_handle_by_name to the VPI interface,
and bump the vpithunk magic number.
2002-12-11 23:55:22 +00:00
steve cca07fa42d Account for bison 1.35 and stack manipulations. 2002-12-10 05:49:51 +00:00
steve 5b81798205 install iverilog-vpi as a script. 2002-12-10 05:45:44 +00:00
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
164 changed files with 6769 additions and 9345 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.
*
+25 -5
View File
@@ -17,13 +17,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.cc,v 1.3 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
#endif
# include "config.h"
# include "LineInfo.h"
# include <cstdio>
# include <sstream>
LineInfo::LineInfo()
: file_(0), lineno_(0)
{
}
LineInfo::~LineInfo()
{
@@ -31,9 +36,11 @@ LineInfo::~LineInfo()
string LineInfo::get_line() const
{
char buf[8];
sprintf(buf, "%u", lineno_);
return string(file_? file_ : "") + ":" + buf;
ostringstream buf;
buf << (file_? file_ : "") << ":" << lineno_;
string res = buf.str();
return res;
}
void LineInfo::set_line(const LineInfo&that)
@@ -42,8 +49,21 @@ void LineInfo::set_line(const LineInfo&that)
lineno_ = that.lineno_;
}
void LineInfo::set_file(const char*f)
{
file_ = f;
}
void LineInfo::set_lineno(unsigned n)
{
lineno_ = n;
}
/*
* $Log: LineInfo.cc,v $
* Revision 1.4 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
*
* Revision 1.3 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+7 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.h,v 1.6 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $"
#endif
# include <string>
@@ -35,15 +35,15 @@
class LineInfo {
public:
LineInfo() : file_(0), lineno_(0) { }
LineInfo();
~LineInfo();
string get_line() const;
void set_line(const LineInfo&that);
void set_file(const char*f) { file_ = f; }
void set_lineno(unsigned n) { lineno_ = n; }
void set_file(const char*f);
void set_lineno(unsigned n);
private:
const char* file_;
@@ -52,6 +52,9 @@ class LineInfo {
/*
* $Log: LineInfo.h,v $
* Revision 1.7 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
*
* Revision 1.6 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+21 -27
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.143 2003/01/26 21:15:58 steve Exp $"
#
#
SHELL = /bin/sh
@@ -25,7 +25,7 @@ SHELL = /bin/sh
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well.
VERSION = 0.6
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -67,7 +67,7 @@ ifeq ('@HAVE_IPAL@','yes')
TARGETS += tgt-pal
endif
all: ivl@EXEEXT@ libvpi.a
all: ivl@EXEEXT@
for dir in $(SUBDIRS) ; do (cd $$dir ; $(MAKE) all); done
cd vpi ; $(MAKE) all
cd ivlpp ; $(MAKE) all
@@ -83,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
@@ -92,7 +96,7 @@ endif
check: all
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) check); done
driver/iverilog -Ccheck.conf -ocheck.vvp -tvvp-check -B./ivlpp $(srcdir)/examples/hello.vl
vvp/vvp -M./vpi ./check.vvp | grep 'Hello, World'
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
clean:
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc lexor_keyword.cc ivl@EXEEXT@ libivl.a libvpi.a iverilog-vpi
@@ -124,11 +128,11 @@ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_udp.o pad_to_width.o \
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o sync.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \
PExpr.o PGate.o \
PTask.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
@@ -137,19 +141,6 @@ Makefile: Makefile.in config.h.in config.status
./config.status
libvpi.a: vpithunk.o
rm -f $@
ar cvq $@ vpithunk.o
ranlib $@
# The vpithunk.c file (that makes up the libvpi.a library) needs to
# be make with PIC flags, because shared objects load it.
vpithunk.o: vpithunk.c
@[ -d dep ] || mkdir dep
$(CC) $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) -MD -c $< -o $*.o
mv $*.d dep/$*.d
ifeq (@WIN32@,yes)
# Under Windows (mingw) I need to make the ivl.exe in two steps.
# The first step makes an ivl.exe that dlltool can use to make an
@@ -216,12 +207,12 @@ 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
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(libdir)/libvpi.a $(WIN32_INSTALL) $(INSTALL_DOC)
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
cd vpi ; $(MAKE) install
cd ivlpp ; $(MAKE) install
cd driver ; $(MAKE) install
@@ -229,16 +220,16 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
$(bindir)/iverilog-vpi: ./iverilog-vpi
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
$(libdir)/libvpi.a : ./libvpi.a
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
$(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 +261,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
@@ -283,7 +278,6 @@ uninstall:
rm -f $(libdir)/ivl/iverilog.conf
rm -f $(libdir)/ivl/ivl
-rmdir $(libdir)/ivl
rm -f $(libdir)/libvpi.a
rm -f $(bindir)/verilog
rm -f $(bindir)/iverilog-vpi
rm -f $(bindir)/gverilog@EXEEXT@
+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: Module.h,v 1.27 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: Module.h,v 1.28 2003/01/26 21:15:58 steve Exp $"
#endif
# include <list>
@@ -29,6 +29,7 @@
# include "named.h"
# include "LineInfo.h"
# include <string>
class PData;
class PEvent;
class PExpr;
class PEIdent;
@@ -97,6 +98,9 @@ class Module : public LineInfo {
/* Keep a table of named events declared in the module. */
map<string,PEvent*>events;
/* Keep a table of datum variables declared in the module. */
map<string,PData*>datum;
/* These are the timescale for this module. The default is
set by the `timescale directive. */
int time_unit, time_precision;
@@ -151,6 +155,10 @@ class Module : public LineInfo {
/*
* $Log: Module.h,v $
* Revision 1.28 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.27 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2003 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PData.cc,v 1.1 2003/01/26 21:15:58 steve Exp $"
#endif
# include "PData.h"
PData::PData(const hname_t&h)
: hname_(h)
{
}
PData::~PData()
{
}
const hname_t&PData::name() const
{
return hname_;
}
/*
* $Log: PData.cc,v $
* Revision 1.1 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
+63
View File
@@ -0,0 +1,63 @@
#ifndef __PData_H
#define __PData_H
/*
* Copyright (c) 2003 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
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $"
#endif
# include "HName.h"
# include "netlist.h"
# include "LineInfo.h"
/*
* The PData object represents declaration of atomic datum such as
* real and realtime variables. These are variables that cannot be bit
* or part selected, but can be used in expressions.
*/
class PData : public LineInfo {
public:
PData(const hname_t&hname);
~PData();
// Return a hierarchical name.
const hname_t&name() const;
void elaborate_scope(Design*des, NetScope*scope) const;
map<string,PExpr*> attributes;
private:
hname_t hname_;
private:
PData(const PData&);
PData& operator= (const PData&);
};
/*
* $Log: PData.h,v $
* Revision 1.1 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
#endif
+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.
*
+5 -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: PWire.h,v 1.14 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: PWire.h,v 1.15 2003/01/26 21:15:58 steve Exp $"
#endif
# include "netlist.h"
@@ -53,7 +53,6 @@ class PWire : public LineInfo {
PWire(char*name, NetNet::Type t, NetNet::PortType pt);
// Return a hierarchical name.
//const string name() const;
const hname_t&path() const;
NetNet::Type get_wire_type() const;
@@ -101,6 +100,10 @@ class PWire : public LineInfo {
/*
* $Log: PWire.h,v $
* Revision 1.15 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.14 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+24
View File
@@ -344,6 +344,19 @@ language that are defined.
The $sizeof function is deprecated in favor of $bits, which is
the same thing, but included in the SystemVerilog definition.
$simtime
The $simtime system function returns as a 64bit value the
simulation time, unscaled by the time units of local
scope. This is different from the $time and $stime functions
which return the scaled times. This function is added for
regression testing of the compiler and run time, but can be
used by applications who really want the simulation time.
Note that the simulation time can be confusing if there are
lots of different `timescales within a design. It is not in
general possible to predict what the simulation precision will
turn out to be.
Builtin system functions
Certain of the system functions have well defined meanings, so
@@ -396,6 +409,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
+9 -1
View File
@@ -23,7 +23,7 @@
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.cc,v 1.2 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: StringHeap.cc,v 1.3 2003/01/16 21:44:46 steve Exp $"
#endif
# include "StringHeap.h"
@@ -38,6 +38,7 @@ StringHeap::StringHeap()
{
cell_base_ = 0;
cell_ptr_ = HEAPCELL;
cell_count_ = 0;
}
StringHeap::~StringHeap()
@@ -55,6 +56,8 @@ const char* StringHeap::add(const char*text)
if (rem < (len+1)) {
cell_base_ = (char*)malloc(HEAPCELL);
cell_ptr_ = 0;
cell_count_ += 1;
assert(cell_base_ != 0);
}
char*res = cell_base_ + cell_ptr_;
@@ -62,11 +65,16 @@ const char* StringHeap::add(const char*text)
cell_ptr_ += len;
cell_base_[cell_ptr_++] = 0;
assert(cell_ptr_ <= HEAPCELL);
return res;
}
/*
* $Log: StringHeap.cc,v $
* Revision 1.3 2003/01/16 21:44:46 steve
* Keep some debugging status.
*
* Revision 1.2 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.h,v 1.2 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: StringHeap.h,v 1.3 2003/01/16 21:44:46 steve Exp $"
#endif
class StringHeap {
@@ -35,6 +35,7 @@ class StringHeap {
char*cell_base_;
unsigned cell_ptr_;
unsigned cell_count_;
private: // not implemented
StringHeap(const StringHeap&);
@@ -43,6 +44,9 @@ class StringHeap {
/*
* $Log: StringHeap.h,v $
* Revision 1.3 2003/01/16 21:44:46 steve
* Keep some debugging status.
*
* Revision 1.2 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+5 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: config.h.in,v 1.5 2002/08/11 23:39:33 steve Exp $"
#ident "$Id: config.h.in,v 1.6 2003/01/10 19:01:04 steve Exp $"
#endif
#if defined(__cplusplus)
@@ -37,6 +37,7 @@
# undef HAVE_TIMES
# undef HAVE_IOSFWD
# undef HAVE_GETOPT_H
# undef HAVE_LIBIBERTY_H
# undef HAVE_MALLOC_H
# undef HAVE_DLFCN_H
# undef HAVE_DL_H
@@ -46,6 +47,9 @@
/*
* $Log: config.h.in,v $
* Revision 1.6 2003/01/10 19:01:04 steve
* Only use libiberty.h if available.
*
* Revision 1.5 2002/08/11 23:39:33 steve
* Remove VVM option.
*
+5 -3
View File
@@ -32,7 +32,7 @@ fi
AC_LANG_CPLUSPLUS
AC_CHECK_HEADERS(getopt.h malloc.h iosfwd sys/wait.h)
AC_CHECK_HEADERS(getopt.h malloc.h libiberty.h iosfwd sys/wait.h)
AC_MSG_CHECKING(for sys/times)
AC_TRY_LINK(
@@ -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)
+22 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: design_dump.cc,v 1.136 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -447,6 +447,8 @@ void NetAssign_::dump_lval(ostream&o) const
if (bmux_) o << *bmux_;
else o << "**oops**";
o << "]";
} else if (var_) {
o << "<real " << var_->basename() << ">";
} else {
o << "";
}
@@ -733,6 +735,11 @@ void NetScope::dump(ostream&o) const
}
}
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) {
o << " real " << cur->basename() << " // "
<< cur->get_line() << endl;
}
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
@@ -896,6 +903,11 @@ void NetEConst::dump(ostream&o) const
o << value_;
}
void NetECReal::dump(ostream&o) const
{
o << value_;
}
void NetEScope::dump(ostream&o) const
{
o << "<scope=" << scope_->name() << ">";
@@ -975,6 +987,11 @@ void NetEUnary::dump(ostream&o) const
o << ")";
}
void NetEVariable::dump(ostream&o) const
{
o << var_->basename();
}
void Design::dump(ostream&o) const
{
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
@@ -1004,6 +1021,10 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.136 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.135 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+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@
+42 -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.50 2003/01/10 19:01:04 steve Exp $"
# include "config.h"
@@ -44,8 +44,10 @@ const char HELP[] =
#ifdef __MINGW32__
#include <windows.h>
#ifdef HAVE_LIBIBERTY_H
#include <libiberty.h>
#endif
#endif
#if HAVE_GETOPT_H
#include <getopt.h>
@@ -119,6 +121,35 @@ char tmp[MAXSIZE];
static char ivl_root[MAXSIZE];
#ifdef __MINGW32__
# include <io.h>
# include <fcntl.h>
static FILE*fopen_safe(const char*path)
{
FILE*file = 0;
int fd;
fd = _open(path, _O_WRONLY|_O_CREAT|_O_EXCL, 0700);
if (fd != -1)
file = _fdopen(fd, "w");
return file;
}
#else
# include <fcntl.h>
static FILE*fopen_safe(const char*path)
{
FILE*file = 0;
int fd;
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0700);
if (fd != -1)
file = fdopen(fd, "w");
return file;
}
#endif
static const char*my_tempfile(const char*str, FILE**fout)
{
FILE*file;
@@ -148,7 +179,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
while ((retry > 0) && (file == NULL)) {
unsigned code = rand();
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
file = fopen(pathbuf, "w");
file = fopen_safe(pathbuf);
retry -= 1;
}
@@ -657,6 +688,15 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.50 2003/01/10 19:01:04 steve
* Only use libiberty.h if available.
*
* Revision 1.49 2002/12/04 03:26:59 steve
* Mingw32 compatible temp file management.
*
* Revision 1.48 2002/12/04 02:29:36 steve
* Use O_EXCL when opening temp files.
*
* Revision 1.47 2002/08/12 01:27:48 steve
* Escape the backslash in the windows file name.
*
+30 -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.10 2003/01/26 21:15:58 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());
@@ -72,8 +87,21 @@ NetEUnary* NetEUnary::dup_expr() const
return tmp;
}
NetEVariable* NetEVariable::dup_expr() const
{
NetEVariable*tmp = new NetEVariable(var_);
return tmp;
}
/*
* $Log: dup_expr.cc,v $
* Revision 1.10 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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 +125,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.
*
*/
+32 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
* Copyright (c) 1999-2003 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: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
#ident "$Id: elab_expr.cc,v 1.68 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -215,6 +215,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
if (strcmp(path_.peek_name(0), "$time") == 0)
wid = 64;
if (strcmp(path_.peek_name(0), "$simtime") == 0)
wid = 64;
if (strcmp(path_.peek_name(0), "$stime") == 0)
wid = 32;
@@ -404,8 +406,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, bool) const
{
long val = value_->as_long();
return new NetEConst(verinum(val));
NetECReal*tmp = new NetECReal(*value_);
tmp->set_line(*this);
return tmp;
}
/*
@@ -719,6 +722,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
return node;
}
// If the identifier names a variable of some sort, then this
// is a variable reference.
if (NetVariable*var = des->find_variable(scope, path_)) {
NetEVariable*node = new NetEVariable(var);
node->set_line(*this);
return node;
}
// Finally, if this is a scope name, then return that. Look
// first to see if this is a name of a local scope. Failing
// that, search globally for a heirarchical name.
@@ -810,10 +822,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
case '-':
if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
/* When taking the - of a number, turn it into a
signed expression and extend it one bit to
accommodate a possible sign bit. */
verinum val = ipc->value();
verinum zero (verinum::V0, val.len(), val.has_len());
verinum zero (verinum::V0, val.len()+1, val.has_len());
val = zero - val;
val.has_sign(ipc->has_sign());
val.has_sign(true);
tmp = new NetEConst(val);
delete ip;
} else {
@@ -885,6 +900,17 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/*
* $Log: elab_expr.cc,v $
* Revision 1.68 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.67 2002/12/21 00:55:57 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.66 2002/09/21 21:28:18 steve
* Allow constant bit selects out of range.
*
+74 -10
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.25 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -103,6 +103,14 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_*res = 0;
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
if (parms_[idx] == 0) {
cerr << get_line() << ": error: Empty expressions "
<< "not allowed in concatenations." << endl;
des->errors += 1;
continue;
}
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
/* If the l-value doesn't elaborate, the error was
@@ -130,17 +138,24 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
/*
* Handle the ident as an l-value. This includes bit and part selects
* of that ident.
*
* XXXX FIXME: The search order looks for signals all the way up the
* scope tree, then looks for memories then variables. It should be
* looking for signals, memories and variables in parallel.
*/
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
{
/* Get the signal referenced by the identifier, and make sure
it is a register. (Wires are not allows in this context. */
NetNet*reg = des->find_signal(scope, path_);
if (reg == 0) {
NetMemory*mem = des->find_memory(scope, path_);
if (mem != 0)
if (NetMemory*mem = des->find_memory(scope, path_)) {
return elaborate_mem_lval_(des, scope, mem);
}
if (NetVariable*var = des->find_variable(scope, path_)) {
NetAssign_*cur = new NetAssign_(var);
return cur;
}
cerr << get_line() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope->name() <<
@@ -149,8 +164,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
des->errors += 1;
return 0;
}
assert(reg);
/* Get the signal referenced by the identifier, and make sure
it is a register. (Wires are not allows in this context. */
if (reg->type() != NetNet::REG) {
cerr << get_line() << ": error: " << path_ <<
" is not a reg/integer/time in " << scope->name() <<
@@ -170,16 +188,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 +299,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 +347,22 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.25 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.24 2003/01/19 00:35:39 steve
* Detect null arguments to concatenation operator.
*
* 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.
*
+105 -16
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.105 2003/01/19 00:35:39 steve Exp $"
#endif
# include "config.h"
@@ -1437,14 +1437,79 @@ 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) {
if (parms_[idx] == 0) {
cerr << get_line() << ": error: Empty expressions "
<< "not allowed in concatenations." << endl;
errors += 1;
continue;
}
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();
NetNet*sig = des->find_signal(scope, path_);
if (sig == 0) {
/* Don't allow memories here. Is it a memory? */
@@ -1455,29 +1520,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 +2284,18 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.105 2003/01/19 00:35:39 steve
* Detect null arguments to concatenation operator.
*
* Revision 1.104 2003/01/17 05:48:35 steve
* Remove useless variable.
*
* Revision 1.103 2002/12/06 03:08:19 steve
* Reword some error messages for clarity.
*
* Revision 1.102 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* 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.
*
+21 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.18 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -32,6 +32,7 @@
*/
# include "Module.h"
# include "PData.h"
# include "PEvent.h"
# include "PExpr.h"
# include "PGate.h"
@@ -40,6 +41,7 @@
# include "Statement.h"
# include "netlist.h"
# include <typeinfo>
# include <assert.h>
bool Module::elaborate_scope(Design*des, NetScope*scope) const
{
@@ -217,6 +219,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
(*et).second->elaborate_scope(des, scope);
}
for (map<string,PData*>::const_iterator cur = datum.begin()
; cur != datum.end() ; cur ++ ) {
(*cur).second->elaborate_scope(des, scope);
}
return des->errors == 0;
}
@@ -341,6 +349,14 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
}
}
void PData::elaborate_scope(Design*des, NetScope*scope) const
{
assert(hname_.component_count() == 1);
NetVariable*tmp = new NetVariable(hname_.peek_tail_name());
tmp->set_line(*this);
scope->add_variable(tmp);
}
/*
* The isn't really able to create new scopes, but it does create the
* event name in the current scope, so can be done during the
@@ -496,6 +512,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.18 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.17 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+104 -100
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.269 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -30,7 +30,7 @@
*/
# include <typeinfo>
# include <strstream>
# include <sstream>
# include <list>
# include "pform.h"
# include "PEvent.h"
@@ -314,14 +314,14 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
a unique name, and set the delay times. */
for (unsigned idx = 0 ; idx < count ; idx += 1) {
strstream tmp;
ostringstream tmp;
unsigned index;
if (low < high)
index = low + idx;
else
index = low - idx;
tmp << name << "<" << index << ">" << ends;
tmp << name << "<" << index << ">";
const string inm = tmp.str();
switch (type()) {
@@ -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
{
@@ -976,23 +926,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
delay = elaborate_delay_expr(delay_, des, scope);
/* Elaborate the r-value expression. */
/* Elaborate the r-value expression, then try to evaluate it. */
assert(rval());
NetExpr*rv;
if (verinum*val = rval()->eval_const(des, scope)) {
rv = new NetEConst(*val);
delete val;
} else if (rv = rval()->elaborate_expr(des, scope)) {
/* OK, go on. */
} else {
/* Unable to elaborate expression. Retreat. */
NetExpr*rv = rval()->elaborate_expr(des, scope);
if (rv == 0)
return 0;
}
assert(rv);
@@ -1025,7 +964,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;
@@ -1078,10 +1017,15 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
return bl;
}
{ unsigned wid = count_lval_width(lv);
rv->set_width(wid);
rv = pad_to_width(rv, wid);
assert(rv->expr_width() >= wid);
/* Based on the specific type of the l-value, do cleanup
processing on the r-value. */
if (NetVariable*tmp = lv->var()) {
} else {
unsigned wid = count_lval_width(lv);
rv->set_width(wid);
rv = pad_to_width(rv, wid);
assert(rv->expr_width() >= wid);
}
NetAssign*cur = new NetAssign(lv, rv);
@@ -1126,6 +1070,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 +1351,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);
@@ -1639,6 +1600,30 @@ NetProc* PDelayStatement::elaborate(Design*des, NetScope*scope) const
/* Ah, the delay is not constant. OK, elaborate the
expression and let the run-time handle it. */
NetExpr*dex = delay_->elaborate_expr(des, scope);
/* If the local scope units are different from the
simulation precision, then extend the expression to
convert the delay to simulation time. */
if (scope->time_unit() != des->get_precision()) {
long scale = 1;
int unit = scope->time_unit();
int prec = des->get_precision();
while (unit > prec) {
scale *= 10;
unit -= 1;
}
verinum scale_v (scale);
NetEConst*scale_e = new NetEConst(scale_v);
NetEBMult*scale_m = new NetEBMult('*', scale_e, dex);
if (NetExpr*tmp = scale_m->eval_tree()) {
dex = tmp;
delete scale_m;
} else {
dex = scale_m;
}
}
if (statement_)
return new NetPDelay(dex, statement_->elaborate(des, scope));
else
@@ -2522,6 +2507,25 @@ Design* elaborate(list<const char*>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.269 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.268 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.267 2002/12/21 19:42:17 steve
* Account for local units in calculated delays.
*
* Revision 1.266 2002/12/05 04:15:14 steve
* precalculate r-values of nb assignments and task arguments.
*
* Revision 1.265 2002/11/26 03:35:13 steve
* Do not set width if width is already OK.
*
* Revision 1.264 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.263 2002/08/28 18:54:36 steve
* Evaluate nonblocking assign r-values.
*
+25 -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.71 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -312,6 +312,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
tgt->event(cur);
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_)
tgt->variable(cur);
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
cur->emit_scope(tgt);
@@ -411,6 +414,11 @@ void NetEConst::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_const(this);
}
void NetECReal::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_creal(this);
}
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_memory(this);
@@ -462,6 +470,11 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_unary(this);
}
void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_variable(this);
}
bool emit(const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
@@ -470,11 +483,22 @@ 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.71 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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
+43 -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.38 2003/01/26 21:15:58 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);
}
@@ -425,6 +452,14 @@ NetNet* NetEConst::synthesize(Design*des)
return osig;
}
NetNet* NetECReal::synthesize(Design*des)
{
cerr << get_line() << ": error: Real constants are "
<< "not synthesizeable." << endl;
des->errors += 1;
return 0;
}
/*
* The bitwise unary logic operator (there is only one) is turned
* into discrete gates just as easily as the binary ones above.
@@ -608,6 +643,13 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.38 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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]
+1
View File
@@ -120,6 +120,7 @@ ivl_scope_port
ivl_scope_ports
ivl_scope_sigs
ivl_scope_sig
ivl_scope_time_units
ivl_scope_type
ivl_scope_tname
+67 -4
View File
@@ -1,7 +1,7 @@
#ifndef __ivl_target_H
#define __ivl_target_H
/*
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: ivl_target.h,v 1.110 2003/01/26 21:15:58 steve Exp $"
#endif
#ifdef __cplusplus
@@ -137,6 +137,7 @@ typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_signal_s *ivl_signal_t;
typedef struct ivl_memory_s *ivl_memory_t;
typedef struct ivl_statement_s*ivl_statement_t;
typedef struct ivl_variable_s *ivl_variable_t;
/*
* These are types that are defined as enumerations. These have
@@ -171,7 +172,9 @@ typedef enum ivl_expr_type_e {
IVL_EX_TERNARY,
IVL_EX_UFUNC,
IVL_EX_ULONG,
IVL_EX_UNARY
IVL_EX_UNARY,
IVL_EX_VARIABLE,
IVL_EX_REALNUM
} ivl_expr_type_t;
/* This is the type code for an ivl_net_logic_t object. */
@@ -292,6 +295,14 @@ typedef enum ivl_statement_type_e {
IVL_ST_WHILE
} ivl_statement_type_t;
/* This is the type of a variable, and also used as the type for an
expression. */
typedef enum ivl_variable_type_e {
IVL_VT_VOID = 0, /* Not used */
IVL_VT_REAL,
IVL_VT_VECTOR
} ivl_variable_type_t;
/* This is the type of the function to apply to a process. */
typedef int (*ivl_process_f)(ivl_process_t net, void*cd);
@@ -416,6 +427,10 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
* type, which can affect how some of the other expression methods
* operate on the node
*
* ivl_expr_value
* Get the data type of the expression node. This uses the variable
* type enum to express the type of the expression node.
*
* ivl_expr_width
* This method returns the bit width of the expression at this
* node. It can be applied to any expression node, and returns the
@@ -430,14 +445,17 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
extern ivl_variable_type_t ivl_expr_value(ivl_expr_t net);
/* IVL_EX_NUMBER */
extern const char* ivl_expr_bits(ivl_expr_t net);
/* IVL_EX_UFUNC */
extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
/* IVL_EX_REALNUM */
extern double ivl_expr_dvalue(ivl_expr_t net);
/* IVL_EX_SIGNAL */
extern unsigned ivl_expr_lsi(ivl_expr_t net);
/* IVL_EX_SIGNAL, IVL_EX_SFUNC */
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
extern const char* ivl_expr_name(ivl_expr_t net);
/* IVL_EX_BINARY IVL_EX_UNARY */
extern char ivl_expr_opcode(ivl_expr_t net);
@@ -463,6 +481,8 @@ extern int ivl_expr_signed(ivl_expr_t net);
extern const char* ivl_expr_string(ivl_expr_t net);
/* IVL_EX_ULONG */
extern unsigned long ivl_expr_uvalue(ivl_expr_t net);
/* IVL_EX_VARIABLE */
extern ivl_variable_t ivl_expr_variable(ivl_expr_t net);
/* any expression */
extern unsigned ivl_expr_width(ivl_expr_t net);
@@ -671,6 +691,12 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
* If the l-value is a variable, this method returns the signal
* object that is the target of the assign.
*
* ivl_lval_var
* If the l-value is a non-signal variable (i.e. a real) this
* method returns the ivl_variable_t object that represents it.
* If the lval is this sort of variable, then the part_off, idx and
* pin methods do not apply.
*
* ivl_lval_part_off
* The part select of the signal is based here. This is the
* canonical index of bit-0 of the part select.
@@ -690,6 +716,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net);
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
extern ivl_variable_t ivl_lval_var(ivl_lval_t net);
extern unsigned ivl_lval_part_off(ivl_lval_t net);
extern unsigned ivl_lval_pins(ivl_lval_t net);
extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx);
@@ -825,6 +852,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* ivl_scope_events
* Scopes have 0 or more event objects in them.
*
* ivl_scope_var
* ivl_scope_vars
* Scopes have 0 or more variable objects in them.
*
* ivl_scope_log
* ivl_scope_logs
* Scopes have 0 or more logic devices in them. A logic device is
@@ -861,6 +892,11 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
* anything that can become and ivl_signal_t, include synthetic
* signals generated by the compiler.
*
* ivl_scope_time_units
* Scopes have their own intrinsic time units, typically from the
* timescale compiler directive. This method returns the units as a
* signed power of 10 value.
*
* ivl_scope_type
* ivl_scope_tname
* Scopes have a type and a type name. For example, if a scope is
@@ -882,6 +918,8 @@ extern unsigned ivl_scope_lpms(ivl_scope_t net);
extern ivl_lpm_t ivl_scope_lpm(ivl_scope_t, unsigned idx);
extern unsigned ivl_scope_mems(ivl_scope_t net);
extern ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_vars(ivl_scope_t net);
extern ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx);
extern const char* ivl_scope_name(ivl_scope_t net);
extern const char* ivl_scope_basename(ivl_scope_t net);
extern ivl_scope_t ivl_scope_parent(ivl_scope_t net);
@@ -891,6 +929,7 @@ extern unsigned ivl_scope_sigs(ivl_scope_t net);
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
extern ivl_scope_type_t ivl_scope_type(ivl_scope_t net);
extern const char* ivl_scope_tname(ivl_scope_t net);
extern int ivl_scope_time_units(ivl_scope_t net);
/* SIGNALS
@@ -1065,6 +1104,19 @@ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
IVL_ST_WAIT, IVL_ST_WHILE */
extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
/*
* These functions manipulate variable objects.
*
* ivl_variable_name
* Return the base name of the variable.
*
* ivl_variable_type
* Return the type of the variable. The ivl_variable_type_t is an
* enumeration that is defined earlier.
*/
extern const char* ivl_variable_name(ivl_variable_t net);
extern ivl_variable_type_t ivl_variable_type(ivl_variable_t net);
#if defined(__MINGW32__) || defined (__CYGWIN32__)
# define DLLEXPORT __declspec(dllexport)
@@ -1091,6 +1143,17 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.110 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.109 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.108 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+2 -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); }
+4 -3
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.75 2003/01/26 21:15:58 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; }
@@ -974,7 +974,8 @@ static verinum*make_sized_dec(const char*txt)
static verinum*make_unsized_dec(const char*txt)
{
return make_dec_with_size(INTEGER_WIDTH, false, txt+1);
verinum*tmp = make_dec_with_size(INTEGER_WIDTH, false, txt+1);
tmp->has_sign(true);
}
/*
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.14 2002/06/11 15:19:12 steve Exp $"
#ident "$Id: Makefile.in,v 1.15 2002/12/19 21:37:04 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,7 +50,7 @@ a_initialize.o a_next_topmod.o a_object_of_type.o a_product_version.o \
a_set_value.o a_version.o
O = asynch.o finish.o getcstringp.o getinstance.o getlongp.o \
getp.o getsimtime.o io_print.o mc_scan_plusargs.o nump.o putlongp.o \
putp.o veriusertfs.o $A
putp.o typep.o workarea.o veriusertfs.o $A
all: libveriuser.a
+22 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: io_print.c,v 1.3 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: io_print.c,v 1.4 2002/12/19 21:37:04 steve Exp $"
#endif
# include <vpi_user.h>
@@ -56,8 +56,29 @@ void tf_error(const char *fmt, ...)
va_end(ap);
}
PLI_INT32 tf_message(PLI_INT32 level, char*facility,
char*messno, char*fmt, ...)
{
va_list ap;
vpi_printf("%s[%s] ", facility, messno);
va_start(ap, fmt);
vpi_vprintf(fmt, ap);
va_end(ap);
vpi_printf("\n");
return 0;
}
/*
* $Log: io_print.c,v $
* Revision 1.4 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
* Revision 1.3 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: typep.c,v 1.1 2002/12/19 21:37:04 steve Exp $"
#endif
#include <assert.h>
#include <veriuser.h>
#include <vpi_user.h>
PLI_INT32 tf_typep(PLI_INT32 narg)
{
vpiHandle sys_h, argv, arg_h = 0;
s_vpi_value value;
int rtn;
assert(narg > 0);
/* get task/func handle */
sys_h = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, sys_h);
/* find nth arg */
while (narg > 0) {
/* Watch that the argument is not out of range. */
if (!(arg_h = vpi_scan(argv)))
return TF_NULLPARAM;
narg -= 1;
}
switch (vpi_get(vpiType, arg_h)) {
case vpiConstant:
switch (vpi_get(vpiConstType, arg_h)) {
case vpiStringConst:
rtn = TF_STRING;
break;
default:
rtn = TF_READONLY;
break;
}
break;
case vpiIntegerVar:
case vpiReg:
case vpiMemoryWord:
rtn = TF_READWRITE;
break;
default:
rtn = TF_READONLY;
break;
}
vpi_free_object(argv);
return rtn;
}
/*
* $Log: typep.c,v $
* Revision 1.1 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
*/
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: workarea.c,v 1.1 2002/12/19 21:37:04 steve Exp $"
#endif
# include <veriuser.h>
# include <vpi_user.h>
# include <stdlib.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
/*
* Keep a list of sys handle to work area bindings.
*/
struct workarea_cell {
vpiHandle sys;
void* area;
struct workarea_cell*next;
};
static struct workarea_cell*area_list = 0;
PLI_INT32 tf_setworkarea(void*workarea)
{
vpiHandle sys;
struct workarea_cell*cur;
sys = vpi_handle(vpiSysTfCall, 0);
cur = area_list;
while (cur) {
if (cur->sys == sys) {
cur->area = workarea;
return 0;
}
cur = cur->next;
}
cur = calloc(1, sizeof (struct workarea_cell));
cur->next = area_list;
cur->sys = sys;
cur->area = workarea;
area_list = cur;
return 0;
}
PLI_BYTE8* tf_getworkarea(void)
{
struct workarea_cell*cur;
vpiHandle sys;
sys = vpi_handle(vpiSysTfCall, 0);
cur = area_list;
while (cur) {
if (cur->sys == sys) {
return cur->area;
}
cur = cur->next;
}
return 0;
}
/*
* $Log: workarea.c,v $
* Revision 1.1 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
*/
+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
+20 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.15 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_assign.cc,v 1.16 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -39,7 +39,7 @@ unsigned count_lval_width(const NetAssign_*idx)
}
NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), bmux_(0)
: sig_(s), mem_(0), var_(0), bmux_(0)
{
loff_ = 0;
lwid_ = sig_->pin_count();
@@ -48,13 +48,21 @@ NetAssign_::NetAssign_(NetNet*s)
}
NetAssign_::NetAssign_(NetMemory*s)
: sig_(0), mem_(s), bmux_(0)
: sig_(0), mem_(s), var_(0), bmux_(0)
{
loff_ = 0;
lwid_ = mem_->width();
more = 0;
}
NetAssign_::NetAssign_(NetVariable*s)
: sig_(0), mem_(0), var_(s), bmux_(0)
{
loff_ = 0;
lwid_ = 0;
more = 0;
}
NetAssign_::~NetAssign_()
{
if (sig_) {
@@ -111,6 +119,11 @@ NetMemory* NetAssign_::mem() const
return mem_;
}
NetVariable* NetAssign_::var() const
{
return var_;
}
void NetAssign_::set_part(unsigned lo, unsigned lw)
{
@@ -241,6 +254,10 @@ NetAssignNB::~NetAssignNB()
/*
* $Log: net_assign.cc,v $
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.15 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+53 -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: net_design.cc,v 1.28 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: net_design.cc,v 1.32 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -31,7 +31,7 @@
# include "netlist.h"
# include "util.h"
# include <strstream>
# include <sstream>
Design:: Design()
: errors(0), nodes_(0), procs_(0), lcounter_(0)
@@ -48,10 +48,11 @@ Design::~Design()
string Design::local_symbol(const string&path)
{
strstream res;
res << "_L" << (lcounter_++) << ends;
ostringstream res;
res << path << "." << "_L" << lcounter_;
lcounter_ += 1;
return path + "." + res.str();
return res.str();
}
void Design::set_precision(int val)
@@ -501,12 +502,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 +522,31 @@ NetEvent* Design::find_event(NetScope*scope, hname_t path)
scope = scope->parent();
}
delete key;
return 0;
}
NetVariable* Design::find_variable(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 (NetVariable*ev = scope->find_variable(key)) {
delete key;
return ev;
}
if (scope->type() == NetScope::MODULE)
break;
scope = scope->parent();
}
delete key;
return 0;
}
@@ -593,6 +625,20 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.32 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.31 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.30 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.29 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.28 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+251 -1
View File
@@ -17,13 +17,157 @@
* 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.12 2003/01/27 00:14:37 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
# include <iostream>
NetExpr::TYPE NetExpr::expr_type() const
{
return ET_VECTOR;
}
/*
* 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;
}
NetExpr::TYPE NetEBAdd::expr_type() const
{
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
return ET_VECTOR;
}
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
unsigned w = l->expr_width();
if (r->expr_width() > w)
w = r->expr_width();
expr_width(w);
cast_signed(l->has_sign() && r->has_sign());
}
NetEBDiv::~NetEBDiv()
{
}
NetEBDiv* NetEBDiv::dup_expr() const
{
NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
NetExpr::TYPE NetEBDiv::expr_type() const
{
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
return ET_VECTOR;
}
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width(l->expr_width() + r->expr_width());
cast_signed(l->has_sign() && r->has_sign());
}
NetEBMult::~NetEBMult()
{
}
NetEBMult* NetEBMult::dup_expr() const
{
NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
NetExpr::TYPE NetEBMult::expr_type() const
{
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
return ET_VECTOR;
}
NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
: parms_(cnt), repeat_(r)
{
@@ -43,6 +187,11 @@ NetEConcat::~NetEConcat()
delete parms_[idx];
}
bool NetEConcat::has_width() const
{
return true;
}
void NetEConcat::set(unsigned idx, NetExpr*e)
{
assert(idx < parms_.count());
@@ -110,6 +259,32 @@ unsigned NetEConcat::repeat() const
return repeat_value_;
}
NetECReal::NetECReal(const verireal&val)
: value_(val)
{
}
NetECReal::~NetECReal()
{
}
const verireal& NetECReal::value() const
{
return value_;
}
NetECReal* NetECReal::dup_expr() const
{
NetECReal*tmp = new NetECReal(value_);
tmp->set_line(*this);
return tmp;
}
NetExpr::TYPE NetECReal::expr_type() const
{
return ET_REAL;
}
NetEParam::NetEParam()
: des_(0), scope_(0)
{
@@ -169,8 +344,83 @@ bool NetESelect::set_width(unsigned w)
return false;
}
NetESFunc::NetESFunc(const string&n, unsigned width, unsigned np)
: name_(0)
{
name_ = new char [n.length()+1];
strcpy(name_, n.c_str());
expr_width(width);
nparms_ = np;
parms_ = new NetExpr*[np];
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
parms_[idx] = 0;
}
NetESFunc::~NetESFunc()
{
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
if (parms_[idx]) delete parms_[idx];
delete[]parms_;
delete[]name_;
}
const char* NetESFunc::name() const
{
return name_;
}
unsigned NetESFunc::nparms() const
{
return nparms_;
}
void NetESFunc::parm(unsigned idx, NetExpr*v)
{
assert(idx < nparms_);
if (parms_[idx])
delete parms_[idx];
parms_[idx] = v;
}
const NetExpr* NetESFunc::parm(unsigned idx) const
{
assert(idx < nparms_);
return parms_[idx];
}
NetExpr* NetESFunc::parm(unsigned idx)
{
assert(idx < nparms_);
return parms_[idx];
}
NetExpr::TYPE NetESFunc::expr_type() const
{
if (strcmp(name_,"$realtime") == 0)
return ET_REAL;
return ET_VECTOR;
}
/*
* $Log: net_expr.cc,v $
* Revision 1.12 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.11 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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.
+9 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
#ident "$Id: net_link.cc,v 1.13 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -25,7 +25,7 @@
# include <iostream>
# include "netlist.h"
# include <strstream>
# include <sstream>
# include <string>
# include <typeinfo>
#ifdef HAVE_MALLOC_H
@@ -363,14 +363,14 @@ const char* Nexus::name() const
}
assert(sig);
ostrstream tmp;
ostringstream tmp;
tmp << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
tmp << ends;
name_ = new char[strlen(tmp.str()) + 1];
strcpy(name_, tmp.str());
const string tmps = tmp.str();
name_ = new char[strlen(tmps.c_str()) + 1];
strcpy(name_, tmps.c_str());
return name_;
}
@@ -499,6 +499,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/*
* $Log: net_link.cc,v $
* Revision 1.13 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.12 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
+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: net_nex_input.cc,v 1.6 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.8 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
@@ -82,6 +82,11 @@ NexusSet* NetEConst::nex_input()
return new NexusSet;
}
NexusSet* NetECReal::nex_input()
{
return new NexusSet;
}
NexusSet* NetEMemory::nex_input()
{
NexusSet*result = idx_->nex_input();
@@ -167,6 +172,11 @@ NexusSet* NetEUnary::nex_input()
return expr_->nex_input();
}
NexusSet* NetEVariable::nex_input()
{
return new NexusSet;
}
NexusSet* NetAssignBase::nex_input()
{
NexusSet*result = rval_->nex_input();
@@ -250,11 +260,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 +372,13 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* Revision 1.8 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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.
*
+34 -6
View File
@@ -17,13 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.20 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: net_scope.cc,v 1.23 2003/01/26 21:15:58 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
# include <strstream>
# include <sstream>
/*
* The NetScope class keeps a scope tree organized. Each node of the
@@ -40,6 +40,7 @@ NetScope::NetScope(NetScope*up, const char*n, NetScope::TYPE t)
memories_ = 0;
signals_ = 0;
events_ = 0;
vars_ = 0;
lcounter_ = 0;
if (up) {
@@ -255,10 +256,19 @@ 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;
}
NetVariable* NetScope::find_variable(const char*name)
{
for (NetVariable*cur = vars_; cur ; cur = cur->snext_)
if (strcmp(cur->basename(), name) == 0)
return cur;
return 0;
@@ -377,6 +387,14 @@ NetMemory* NetScope::find_memory(const string&key)
return 0;
}
void NetScope::add_variable(NetVariable*var)
{
assert(var->scope_ == 0);
var->scope_ = this;
var->snext_ = vars_;
vars_ = var;
}
/*
* This method locates a child scope by name. The name is the simple
* name of the child, no heirarchy is searched.
@@ -419,8 +437,8 @@ const NetScope* NetScope::parent() const
string NetScope::local_symbol()
{
strstream res;
res << "_s" << (lcounter_++) << ends;
ostringstream res;
res << "_s" << (lcounter_++);
return res.str();
}
@@ -432,6 +450,16 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* Revision 1.23 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.22 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.21 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.20 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
+18 -127
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.205 2003/01/27 00:14:37 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
@@ -1861,28 +1827,6 @@ NetEBComp* NetEBComp::dup_expr() const
return result;
}
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
unsigned w = l->expr_width();
if (r->expr_width() > w)
w = r->expr_width();
expr_width(w);
cast_signed(l->has_sign() && r->has_sign());
}
NetEBDiv::~NetEBDiv()
{
}
NetEBDiv* NetEBDiv::dup_expr() const
{
NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
: op_(op), left_(l), right_(r)
{
@@ -1921,24 +1865,6 @@ NetEBLogic* NetEBLogic::dup_expr() const
return result;
}
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
expr_width(l->expr_width() + r->expr_width());
cast_signed(l->has_sign() && r->has_sign());
}
NetEBMult::~NetEBMult()
{
}
NetEBMult* NetEBMult::dup_expr() const
{
NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
@@ -2063,57 +1989,6 @@ const NetScope* NetEScope::scope() const
return scope_;
}
NetESFunc::NetESFunc(const string&n, unsigned width, unsigned np)
: name_(0)
{
name_ = new char [n.length()+1];
strcpy(name_, n.c_str());
expr_width(width);
nparms_ = np;
parms_ = new NetExpr*[np];
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
parms_[idx] = 0;
}
NetESFunc::~NetESFunc()
{
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
if (parms_[idx]) delete parms_[idx];
delete[]parms_;
delete[]name_;
}
const char* NetESFunc::name() const
{
return name_;
}
unsigned NetESFunc::nparms() const
{
return nparms_;
}
void NetESFunc::parm(unsigned idx, NetExpr*v)
{
assert(idx < nparms_);
if (parms_[idx])
delete parms_[idx];
parms_[idx] = v;
}
const NetExpr* NetESFunc::parm(unsigned idx) const
{
assert(idx < nparms_);
return parms_[idx];
}
NetExpr* NetESFunc::parm(unsigned idx)
{
assert(idx < nparms_);
return parms_[idx];
}
NetESignal::NetESignal(NetNet*n)
: NetExpr(n->pin_count()), net_(n)
{
@@ -2320,6 +2195,22 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.205 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.204 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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.
+132 -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.273 2003/01/27 00:14:37 steve Exp $"
#endif
/*
@@ -32,6 +32,7 @@
# include <map>
# include <list>
# include "verinum.h"
# include "verireal.h"
# include "HName.h"
# include "LineInfo.h"
# include "svector.h"
@@ -51,6 +52,7 @@ class NetProc;
class NetProcTop;
class NetRelease;
class NetScope;
class NetVariable;
class NetEvProbe;
class NetExpr;
class NetESignal;
@@ -923,6 +925,16 @@ class NetExpr : public LineInfo {
virtual void expr_scan(struct expr_scan_t*) const =0;
virtual void dump(ostream&) const;
// Expressions have type. The most common type is ET_VECTOR,
// which is a vector (possibly 1 bit) of 4-value bits. The
// ET_VOID is not generally used.
//
// ET_VOID - No value at all.
// ET_VECTOR - Vector of Verilog 4-value bits
// ET_REAL - real/realtime expression
enum TYPE { ET_VOID=0, ET_VECTOR, ET_REAL };
virtual TYPE expr_type() const;
// How wide am I?
unsigned expr_width() const { return width_; }
@@ -1006,6 +1018,31 @@ class NetEConst : public NetExpr {
verinum value_;
};
/*
* This class represents a constant real value.
*/
class NetECReal : public NetExpr {
public:
explicit NetECReal(const verireal&val);
~NetECReal();
const verireal&value() const;
// The type of this expression is ET_REAL
TYPE expr_type() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
virtual NetECReal* dup_expr() const;
virtual NetNet*synthesize(Design*);
virtual NexusSet* nex_input();
private:
verireal value_;
};
/*
* This is a special, magical NetNet object. It represents a constant
* bit or part select of another NetNet, so is used to return that
@@ -1285,6 +1322,7 @@ class NetAssign_ {
public:
NetAssign_(NetNet*sig);
NetAssign_(NetMemory*mem);
NetAssign_(NetVariable*var);
~NetAssign_();
// If this expression exists, then only a single bit is to be
@@ -1308,6 +1346,7 @@ class NetAssign_ {
NetNet* sig() const;
NetMemory*mem() const;
NetVariable*var() const;
// This pointer is for keeping simple lists.
NetAssign_* more;
@@ -1317,6 +1356,7 @@ class NetAssign_ {
private:
NetNet *sig_;
NetMemory*mem_;
NetVariable*var_;
NetExpr*bmux_;
unsigned loff_;
@@ -2044,6 +2084,34 @@ class NetTaskDef {
NetTaskDef& operator= (const NetTaskDef&);
};
/*
* Variable object such as real and realtime are represented by
* instances of this class.
*/
class NetVariable : public LineInfo {
friend class NetScope;
public:
NetVariable(const char* name);
~NetVariable();
const char* basename() const;
NetScope* scope();
const NetScope* scope() const;
private:
char* name_;
NetScope*scope_;
NetVariable*snext_;
private:
NetVariable(const NetVariable&);
NetVariable& operator= (const NetVariable&);
};
/*
* This node represents a function call in an expression. The object
* contains a pointer to the function definition, which is used to
@@ -2252,6 +2320,8 @@ class NetEBAdd : public NetEBinary {
NetEBAdd(char op, NetExpr*l, NetExpr*r);
~NetEBAdd();
virtual TYPE expr_type() const;
virtual bool set_width(unsigned w);
virtual NetEBAdd* dup_expr() const;
virtual NetEConst* eval_tree();
@@ -2269,6 +2339,8 @@ class NetEBDiv : public NetEBinary {
NetEBDiv(char op, NetExpr*l, NetExpr*r);
~NetEBDiv();
virtual TYPE expr_type() const;
virtual bool set_width(unsigned w);
virtual NetEBDiv* dup_expr() const;
virtual NetEConst* eval_tree();
@@ -2370,6 +2442,8 @@ class NetEBMult : public NetEBinary {
NetEBMult(char op, NetExpr*l, NetExpr*r);
~NetEBMult();
virtual TYPE expr_type() const;
virtual bool set_width(unsigned w);
virtual NetEBMult* dup_expr() const;
virtual NetEConst* eval_tree();
@@ -2428,6 +2502,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();
@@ -2442,6 +2517,29 @@ class NetEConcat : public NetExpr {
bool repeat_calculated_;
};
/*
* This node represents a reference to a variable.
*/
class NetEVariable : public NetExpr {
public:
NetEVariable(NetVariable*);
~NetEVariable();
const NetVariable* variable() const;
TYPE expr_type() const;
void expr_scan(struct expr_scan_t*) const;
void dump(ostream&) const;
NetEVariable*dup_expr() const;
NexusSet* nex_input();
private:
NetVariable*var_;
};
/*
* This clas is a placeholder for a parameter expression. When
* parameters are first created, an instance of this object is used to
@@ -2493,6 +2591,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:
@@ -2541,6 +2640,7 @@ class NetESFunc : public NetExpr {
NetExpr* parm(unsigned idx);
const NetExpr* parm(unsigned idx) const;
virtual TYPE expr_type() const;
virtual NexusSet* nex_input();
virtual bool set_width(unsigned);
virtual void dump(ostream&) const;
@@ -2793,7 +2893,11 @@ class NetScope {
void add_event(NetEvent*);
void rem_event(NetEvent*);
NetEvent*find_event(const hname_t&name);
NetEvent*find_event(const char*name);
void add_variable(NetVariable*);
void rem_variable(NetVariable*);
NetVariable*find_variable(const char*name);
/* These methods manage signals. The add_ and rem_signal
@@ -2898,6 +3002,7 @@ class NetScope {
map<string,param_expr_t>localparams_;
NetEvent *events_;
NetVariable*vars_;
NetNet *signals_;
NetMemory*memories_;
@@ -2995,7 +3100,10 @@ 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);
// Variables
NetVariable* find_variable(NetScope*scope, const hname_t&path);
// NODES
void add_node(NetNode*);
@@ -3083,6 +3191,27 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.273 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.272 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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.
+9 -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: pad_to_width.cc,v 1.11 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: pad_to_width.cc,v 1.12 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -40,13 +40,17 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
const. This is a more efficient result. */
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
verinum eval = tmp->value();
bool signed_flag = eval.has_sign();
verinum::V pad = verinum::V0;
if (signed_flag)
pad = eval.get(eval.len()-1);
verinum oval (pad, wid, eval.has_len());
for (unsigned idx = 0 ; idx < eval.len() ; idx += 1)
oval.set(idx, eval.get(idx));
oval.has_sign(signed_flag);
tmp = new NetEConst(oval);
delete expr;
return tmp;
@@ -95,6 +99,10 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
/*
* $Log: pad_to_width.cc,v $
* Revision 1.12 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.11 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+30 -13
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.170 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -33,6 +33,24 @@ extern void lex_end_table();
static svector<PExpr*>* active_range = 0;
static bool active_signed = false;
/* Later version of bison (including 1.35) will not compile in stack
extension if the output is compiled with C++ and either the YYSTYPE
or YYLTYPE are provided by the source code. However, I can get the
old behavior back by defining these symbols. */
# define YYSTYPE_IS_TRIVIAL 1
# define YYLTYPE_IS_TRIVIAL 1
/* Recent version of bison expect that the user supply a
YYLLOC_DEFAULT macro that makes up a yylloc value from existing
values. I need to supply an explicit version to account for the
text field, that otherwise won't be copied. */
# define YYLLOC_DEFAULT(Current, Rhs, N) \
Current.first_line = Rhs[1].first_line; \
Current.first_column = Rhs[1].first_column; \
Current.last_line = Rhs[N].last_line; \
Current.last_column = Rhs[N].last_column; \
Current.text = Rhs[1].text;
/*
* These are some common strength pairs that are used as defaults when
* the user is not otherwise specific.
@@ -283,12 +301,10 @@ block_item_decl
{ pform_set_reg_time($2);
}
| K_real list_of_identifiers ';'
{ delete $2;
yyerror(@1, "sorry: real variables not supported.");
{ pform_make_reals($2, @1.text, @1.first_line);
}
| K_realtime list_of_identifiers ';'
{ delete $2;
yyerror(@1, "sorry: realtime variables not supported.");
{ pform_make_reals($2, @1.text, @1.first_line);
}
| K_parameter parameter_assign_decl ';'
| K_localparam localparam_assign_list ';'
@@ -551,11 +567,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 +1700,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 +2100,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 +2156,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 +2332,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.
*
+66 -17
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.102 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: pform.cc,v 1.107 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -26,13 +26,14 @@
# include "pform.h"
# include "parse_misc.h"
# include "parse_api.h"
# include "PData.h"
# include "PEvent.h"
# include "PUdp.h"
# include <list>
# include <map>
# include <assert.h>
# include <typeinfo>
# include <strstream>
# include <sstream>
map<string,Module*> pform_modules;
map<string,PUdp*> pform_primitives;
@@ -212,6 +213,16 @@ void pform_endmodule(const char*name)
{
assert(pform_cur_module);
assert(strcmp(name, pform_cur_module->mod_name()) == 0);
map<string,Module*>::const_iterator test = pform_modules.find(name);
if (test != pform_modules.end()) {
ostringstream msg;
msg << "Module " << name << " was already declared here: "
<< (*test).second->get_line() << endl;
VLerror(msg.str().c_str());
pform_cur_module = 0;
return;
}
pform_modules[name] = pform_cur_module;
pform_cur_module = 0;
}
@@ -421,7 +432,7 @@ void pform_make_udp(const char*name, list<string>*parms,
}
/* Verify the "initial" statement, if present, to be sure that
it only assignes to the output and the output is
it only assigns to the output and the output is
registered. Then save the initial value that I get. */
verinum::V init = verinum::Vx;
if (init_expr) {
@@ -547,6 +558,26 @@ void pform_make_events(list<char*>*names, const char*fn, unsigned ln)
delete names;
}
static void pform_make_datum(const char*name, const char*fn, unsigned ln)
{
PData*datum = new PData(hname_t(name));
datum->set_file(fn);
datum->set_lineno(ln);
pform_cur_module->datum[name] = datum;
}
void pform_make_reals(list<char*>*names, const char*fn, unsigned ln)
{
list<char*>::iterator cur;
for (cur = names->begin() ; cur != names->end() ; cur++) {
char*txt = *cur;
pform_make_datum(txt, fn, ln);
free(txt);
}
delete names;
}
/*
* pform_makegates is called when a list of gates (with the same type)
* are ready to be instantiated. The function runs through the list of
@@ -608,7 +639,7 @@ void pform_makegates(PGBuiltin::Type type,
/*
* A module is different from a gate in that there are different
* constraints, and sometimes different syntax. The X_modgate
* functions handle the instantaions of modules (and UDP objects) by
* functions handle the instantiations of modules (and UDP objects) by
* making PGModule objects.
*/
static void pform_make_modgate(const char*type,
@@ -767,13 +798,13 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
*
* reg foo = <expr>;
*
* This is equivilent to the combination of statements:
* This is equivalent to the combination of statements:
*
* reg foo;
* initital foo = <expr>;
* initial foo = <expr>;
*
* and that is how it is parsed. This syntax is not part of the
* IEEE1364-1994 standard, but is approved by OVI as enhancement
* IEEE1364-1995 standard, but is approved by OVI as enhancement
* BTF-B14.
*/
void pform_make_reginit(const struct vlltype&li,
@@ -820,11 +851,11 @@ void pform_module_define_port(const struct vlltype&li,
hname_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur) {
strstream msg;
ostringstream msg;
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< "." << ends;
VLerror(msg.str());
<< ".";
VLerror(msg.str().c_str());
return;
}
@@ -862,7 +893,7 @@ void pform_module_define_port(const struct vlltype&li,
* reg bar;
*
* The output (or other port direction indicator) may or may not have
* been seen already, so I do not do any cheching with it yet. But I
* been seen already, so I do not do any checking with it yet. But I
* do check to see if the name has already been declared, as this
* function is called for every declaration.
*/
@@ -874,18 +905,18 @@ void pform_makewire(const vlltype&li, const char*nm,
if (cur) {
if ((cur->get_wire_type() != NetNet::IMPLICIT)
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
strstream msg;
ostringstream msg;
msg << name << " previously defined at " <<
cur->get_line() << "." << ends;
VLerror(msg.str());
cur->get_line() << ".";
VLerror(msg.str().c_str());
} else {
bool rc = cur->set_wire_type(type);
if (rc == false) {
strstream msg;
ostringstream msg;
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< "." << ends;
VLerror(msg.str());
<< ".";
VLerror(msg.str().c_str());
}
}
@@ -948,6 +979,8 @@ void pform_makewire(const vlltype&li,
PWire*cur = pform_cur_module->get_wire(name);
if (cur != 0) {
PEIdent*lval = new PEIdent(hname_t(first->name));
lval->set_file(li.text);
lval->set_lineno(li.first_line);
pform_make_pgassign(lval, first->expr, delay, str);
}
@@ -1360,6 +1393,22 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* Revision 1.107 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.106 2003/01/17 05:47:30 steve
* Missed a case of setting line on an PEident.
*
* Revision 1.105 2003/01/16 21:44:19 steve
* Detect duplicate module declarations.
*
* Revision 1.104 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.103 2003/01/10 03:08:13 steve
* Spelling fixes.
*
* Revision 1.102 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
+10 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.64 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: pform.h,v 1.65 2003/01/26 21:15:59 steve Exp $"
#endif
# include "netlist.h"
@@ -216,6 +216,11 @@ extern bool pform_expression_is_constant(const PExpr*);
extern void pform_make_events(list<char*>*names,
const char*file, unsigned lineno);
/*
* Make real datum objects.
*/
extern void pform_make_reals(list<char*>*names,
const char*file, unsigned lineno);
/*
* The makegate function creates a new gate (which need not have a
@@ -259,6 +264,10 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.65 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.64 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
+13 -231
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.77 2002/10/19 22:59:49 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.78 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -29,6 +29,7 @@
* module in question.
*/
# include "pform.h"
# include "PData.h"
# include "PEvent.h"
# include <iostream>
# include <iomanip>
@@ -753,6 +754,13 @@ void Module::dump(ostream&out) const
<< ev->get_line() << endl;
}
for (map<string,PData*>::const_iterator cur = datum.begin()
; cur != datum.end() ; cur ++ ) {
PData*tmp = (*cur).second;
out << " real " << tmp->name() << "; // "
<< tmp->get_line() << endl;
}
// Iterate through and display all the wires.
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
; wire != wires_.end()
@@ -848,6 +856,10 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.78 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.77 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
@@ -890,235 +902,5 @@ void PUdp::dump(ostream&out) const
* Revision 1.68 2001/12/03 04:47:15 steve
* Parser and pform use hierarchical names as hname_t
* objects instead of encoded strings.
*
* Revision 1.67 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.66 2001/01/13 22:20:08 steve
* Parse parameters within nested scopes.
*
* Revision 1.65 2000/12/11 00:31:43 steve
* Add support for signed reg variables,
* simulate in t-vvm signed comparisons.
*
* Revision 1.64 2000/12/10 22:01:36 steve
* Support decimal constants in behavioral delays.
*
* Revision 1.63 2000/11/11 01:52:09 steve
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
* change set to correct behavior of bufif0 and bufif1
* (Tim Leight)
*
* Also includes fix for PR#27
*
* Revision 1.62 2000/10/14 02:23:02 steve
* Check for missing concat subexpressions (PR#11)
*
* Revision 1.61 2000/07/26 05:08:07 steve
* Parse disable statements to pform.
*
* Revision 1.60 2000/05/23 16:03:13 steve
* Better parsing of expressions lists will empty expressoins.
*
* Revision 1.59 2000/05/16 04:05:16 steve
* Module ports are really special PEIdent
* expressions, because a name can be used
* many places in the port list.
*
* Revision 1.58 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
* Revision 1.57 2000/05/06 15:41:57 steve
* Carry assignment strength to pform.
*
* Revision 1.56 2000/05/04 03:37:59 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.55 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.54 2000/04/12 20:02:53 steve
* Finally remove the NetNEvent and NetPEvent classes,
* Get synthesis working with the NetEvWait class,
* and get started supporting multiple events in a
* wait in vvm.
*
* Revision 1.53 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,
*
* Handle named events within the mix of net events
* and edges. As a unified lot they get caught together.
* wait statements are broken into more complex statements
* that include a conditional.
*
* Do not generate NetPEvent or NetNEvent objects in
* elaboration. NetEvent, NetEvWait and NetEvProbe
* take over those functions in the netlist.
*
* Revision 1.52 2000/04/01 19:31:57 steve
* Named events as far as the pform.
*
* Revision 1.51 2000/03/12 17:09:41 steve
* Support localparam.
*
* Revision 1.50 2000/03/08 04:36:54 steve
* Redesign the implementation of scopes and parameters.
* I now generate the scopes and notice the parameters
* in a separate pass over the pform. Once the scopes
* are generated, I can process overrides and evalutate
* paremeters before elaboration begins.
*
* Revision 1.49 2000/02/23 02:56:55 steve
* Macintosh compilers do not support ident.
*
* Revision 1.48 2000/02/18 05:15:03 steve
* Catch module instantiation arrays.
*
* Revision 1.47 2000/01/09 20:37:57 steve
* Careful with wires connected to multiple ports.
*
* Revision 1.46 2000/01/09 05:50:49 steve
* Support named parameter override lists.
*
* Revision 1.45 1999/10/10 01:59:55 steve
* Structural case equals device.
*
* Revision 1.44 1999/09/30 02:43:02 steve
* Elaborate ~^ and ~| operators.
*
* Revision 1.43 1999/09/30 00:48:50 steve
* Cope with errors during ternary operator elaboration.
*
* Revision 1.42 1999/09/29 21:15:58 steve
* Handle some mor missing names.
*
* Revision 1.41 1999/09/29 20:23:53 steve
* Handle empty named ports in the dump.
*
* Revision 1.40 1999/09/29 18:36:04 steve
* Full case support
*
* Revision 1.39 1999/09/17 02:06:26 steve
* Handle unconnected module ports.
*
* Revision 1.38 1999/09/08 02:24:39 steve
* Empty conditionals (pmonta@imedia.com)
*
* Revision 1.37 1999/09/04 19:11:46 steve
* Add support for delayed non-blocking assignments.
*
* Revision 1.36 1999/08/25 22:22:41 steve
* elaborate some aspects of functions.
*
* Revision 1.35 1999/08/23 16:48:39 steve
* Parameter overrides support from Peter Monta
* AND and XOR support wide expressions.
*
* Revision 1.34 1999/08/03 04:49:13 steve
* Proper port type names.
*
* Revision 1.33 1999/08/03 04:14:49 steve
* Parse into pform arbitrarily complex module
* port declarations.
*
* Revision 1.32 1999/08/01 16:34:50 steve
* Parse and elaborate rise/fall/decay times
* for gates, and handle the rules for partial
* lists of times.
*
* Revision 1.31 1999/07/31 19:14:47 steve
* Add functions up to elaboration (Ed Carter)
*
* Revision 1.30 1999/07/30 00:43:17 steve
* Handle dumping tasks with no ports.
*
* Revision 1.29 1999/07/24 02:11:20 steve
* Elaborate task input ports.
*
* Revision 1.28 1999/07/17 19:51:00 steve
* netlist support for ternary operator.
*
* Revision 1.27 1999/07/12 00:59:36 steve
* procedural blocking assignment delays.
*
* Revision 1.26 1999/07/03 02:12:52 steve
* Elaborate user defined tasks.
*
* Revision 1.25 1999/06/24 04:24:18 steve
* Handle expression widths for EEE and NEE operators,
* add named blocks and scope handling,
* add registers declared in named blocks.
*
* Revision 1.24 1999/06/19 21:06:16 steve
* Elaborate and supprort to vvm the forever
* and repeat statements.
*
* Revision 1.23 1999/06/17 05:34:42 steve
* Clean up interface of the PWire class,
* Properly match wire ranges.
*
* Revision 1.22 1999/06/15 05:38:39 steve
* Support case expression lists.
*
* Revision 1.21 1999/06/15 03:44:53 steve
* Get rid of the STL vector template.
*
* Revision 1.20 1999/06/13 23:51:16 steve
* l-value part select for procedural assignments.
*
* Revision 1.19 1999/06/10 04:03:53 steve
* Add support for the Ternary operator,
* Add support for repeat concatenation,
* Correct some seg faults cause by elaboration
* errors,
* Parse the casex anc casez statements.
*
* Revision 1.18 1999/06/06 20:45:39 steve
* Add parse and elaboration of non-blocking assignments,
* Replace list<PCase::Item*> with an svector version,
* Add integer support.
*
* Revision 1.17 1999/05/29 02:36:17 steve
* module parameter bind by name.
*
* Revision 1.16 1999/05/10 00:16:58 steve
* Parse and elaborate the concatenate operator
* in structural contexts, Replace vector<PExpr*>
* and list<PExpr*> with svector<PExpr*>, evaluate
* constant expressions with parameters, handle
* memories as lvalues.
*
* Parse task declarations, integer types.
*
* Revision 1.15 1999/05/05 03:04:46 steve
* Fix handling of null delay statements.
*
* Revision 1.14 1999/05/01 02:57:53 steve
* Handle much more complex event expressions.
*
* Revision 1.13 1999/04/29 02:16:26 steve
* Parse OR of event expressions.
*
* Revision 1.12 1999/04/19 01:59:37 steve
* Add memories to the parse and elaboration phases.
*
* Revision 1.11 1999/02/21 17:01:57 steve
* Add support for module parameters.
*
* Revision 1.10 1999/02/15 02:06:15 steve
* Elaborate gate ranges.
*
* Revision 1.9 1999/02/03 04:20:11 steve
* Parse and elaborate the Verilog CASE statement.
*
* Revision 1.8 1999/02/01 00:26:49 steve
* Carry some line info to the netlist,
* Dump line numbers for processes.
* Elaborate prints errors about port vector
* width mismatch
* Emit better handles null statements.
*/
+32 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,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.26 2003/01/26 21:02:21 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,12 +251,13 @@ 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)
tmp.set(idx, pad);
tmp.has_sign(value_.has_sign());
value_ = tmp;
expr_width(w);
@@ -259,7 +273,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 +371,17 @@ bool NetEUReduce::set_width(unsigned w)
/*
* $Log: set_width.cc,v $
* Revision 1.26 2003/01/26 21:02:21 steve
* Remember to save signedness of number.
*
* 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.
+75 -274
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.88 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.90 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -218,6 +218,12 @@ extern "C" ivl_scope_t ivl_expr_def(ivl_expr_t net)
return 0;
}
extern "C" double ivl_expr_dvalue(ivl_expr_t net)
{
assert(net->type_ == IVL_EX_REALNUM);
return net->u_.real_.value;
}
extern "C" unsigned ivl_expr_lsi(ivl_expr_t net)
{
switch (net->type_) {
@@ -242,6 +248,9 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net)
case IVL_EX_SIGNAL:
return net->u_.signal_.sig->name_;
case IVL_EX_VARIABLE:
return net->u_.variable_.var->name;
default:
assert(0);
}
@@ -414,6 +423,12 @@ extern "C" unsigned long ivl_expr_uvalue(ivl_expr_t net)
return net->u_.ulong_.value;
}
extern "C" ivl_variable_type_t ivl_expr_value(ivl_expr_t net)
{
assert(net);
return net->value_;
}
extern "C" unsigned ivl_expr_width(ivl_expr_t net)
{
assert(net);
@@ -426,6 +441,12 @@ extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net)
return net->u_.memory_.mem_;
}
extern "C" ivl_variable_t ivl_expr_variable(ivl_expr_t net)
{
assert(net->type_ == IVL_EX_VARIABLE);
return net->u_.variable_.var;
}
extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key)
{
assert(net);
@@ -899,6 +920,14 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
return 0x0;
}
extern "C" ivl_variable_t ivl_lval_var(ivl_lval_t net)
{
assert(net);
if (net->type_ == IVL_LVAL_VAR)
return net->n.var;
return 0x0;
}
extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
{
assert(net);
@@ -1079,6 +1108,19 @@ extern "C" ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx)
return net->event_[idx];
}
extern "C" unsigned ivl_scope_vars(ivl_scope_t net)
{
assert(net);
return net->nvar_;
}
extern "C" ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx)
{
assert(net);
assert(idx < net->nvar_);
return net->var_[idx];
}
extern "C" unsigned ivl_scope_logs(ivl_scope_t net)
{
assert(net);
@@ -1157,6 +1199,12 @@ extern "C" ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx)
return net->sigs_[idx];
}
extern "C" int ivl_scope_time_units(ivl_scope_t net)
{
assert(net);
return net->time_units;
}
extern "C" ivl_scope_type_t ivl_scope_type(ivl_scope_t net)
{
assert(net);
@@ -1478,6 +1526,9 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
case IVL_LVAL_MEM:
sum += ivl_memory_width(ivl_lval_mem(cur));
break;
case IVL_LVAL_VAR:
sum += 0;
break;
default:
assert(0);
}
@@ -1583,8 +1634,31 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
return 0;
}
extern "C" const char* ivl_variable_name(ivl_variable_t net)
{
assert(net);
return net->name;
}
extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
{
assert(net);
return net->type;
}
/*
* $Log: t-dll-api.cc,v $
* Revision 1.90 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.89 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.88 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
@@ -1621,278 +1695,5 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
*
* Revision 1.79 2002/05/24 04:36:23 steve
* Verilog 2001 attriubtes on nets/wires.
*
* Revision 1.78 2002/05/23 03:08:51 steve
* Add language support for Verilog-2001 attribute
* syntax. Hook this support into existing $attribute
* handling, and add number and void value types.
*
* Add to the ivl_target API new functions for access
* of complex attributes attached to gates.
*
* Revision 1.77 2002/03/17 19:30:47 steve
* Add API to support user defined function.
*
* Revision 1.76 2002/03/09 02:10:22 steve
* Add the NetUserFunc netlist node.
*
* Revision 1.75 2002/01/28 00:52:41 steve
* Add support for bit select of parameters.
* This leads to a NetESelect node and the
* vvp code generator to support that.
*
* Revision 1.74 2002/01/03 04:19:01 steve
* Add structural modulus support down to vvp.
*
* Revision 1.73 2001/12/06 03:11:00 steve
* Add ivl_logic_delay function to ivl_target.
*
* Revision 1.72 2001/11/14 03:28:49 steve
* DLL target support for force and release.
*
* Revision 1.71 2001/11/01 04:25:31 steve
* ivl_target support for cassign.
*
* Revision 1.70 2001/10/31 05:24:52 steve
* ivl_target support for assign/deassign.
*
* Revision 1.69 2001/10/19 21:53:24 steve
* Support multiple root modules (Philip Blundell)
*
* Revision 1.68 2001/10/16 02:19:27 steve
* Support IVL_LPM_DIVIDE for structural divide.
*
* Revision 1.67 2001/09/16 22:19:42 steve
* Support attributes to logic gates.
*
* Revision 1.66 2001/09/01 01:57:31 steve
* Make constants available through the design root
*
* Revision 1.65 2001/08/31 22:58:40 steve
* Support DFF CE inputs.
*
* Revision 1.64 2001/08/28 04:07:18 steve
* Add some ivl_target convenience functions.
*
* Revision 1.63 2001/08/25 23:50:03 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.62 2001/08/10 00:40:45 steve
* tgt-vvp generates code that skips nets as inputs.
*
* Revision 1.61 2001/07/28 01:17:40 steve
* Support getting the signal from IVL_EX_SIGNAL expressions.
*
* Revision 1.60 2001/07/27 04:51:44 steve
* Handle part select expressions as variants of
* NetESignal/IVL_EX_SIGNAL objects, instead of
* creating new and useless temporary signals.
*
* Revision 1.59 2001/07/27 02:41:55 steve
* Fix binding of dangling function ports. do not elide them.
*
* Revision 1.58 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.57 2001/07/22 00:17:49 steve
* Support the NetESubSignal expressions in vvp.tgt.
*
* Revision 1.56 2001/07/19 04:55:06 steve
* Support calculated delays in vvp.tgt.
*
* Revision 1.55 2001/07/07 20:20:10 steve
* Pass parameters to system functions.
*
* Revision 1.54 2001/07/07 03:01:37 steve
* Detect and make available to t-dll the right shift.
*
* Revision 1.53 2001/07/04 22:59:25 steve
* handle left shifter in dll output.
*
* Revision 1.52 2001/06/30 23:03:16 steve
* support fast programming by only writing the bits
* that are listed in the input file.
*
* Revision 1.51 2001/06/16 23:45:05 steve
* Add support for structural multiply in t-dll.
* Add code generators and vvp support for both
* structural and behavioral multiply.
*
* Revision 1.50 2001/06/16 02:41:41 steve
* Generate code to support memory access in continuous
* assignment statements. (Stephan Boettcher)
*
* Revision 1.49 2001/06/15 04:14:19 steve
* Generate vvp code for GT and GE comparisons.
*
* Revision 1.48 2001/06/07 03:09:37 steve
* support subtraction in tgt-vvp.
*
* Revision 1.47 2001/06/07 02:12:43 steve
* Support structural addition.
*
* Revision 1.46 2001/05/20 01:06:16 steve
* stub ivl_expr_parms for sfunctions.
*
* Revision 1.45 2001/05/17 04:37:02 steve
* Behavioral ternary operators for vvp.
*
* Revision 1.44 2001/05/08 23:59:33 steve
* Add ivl and vvp.tgt support for memories in
* expressions and l-values. (Stephan Boettcher)
*
* Revision 1.43 2001/05/06 17:48:20 steve
* Support memory objects. (Stephan Boettcher)
*
* Revision 1.42 2001/04/29 23:17:38 steve
* Carry drive strengths in the ivl_nexus_ptr_t, and
* handle constant devices in targets.'
*
* Revision 1.41 2001/04/26 05:12:02 steve
* Implement simple MUXZ for ?: operators.
*
* Revision 1.40 2001/04/22 23:09:46 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.39 2001/04/21 00:55:46 steve
* Generate code for disable.
*
* Revision 1.38 2001/04/15 02:58:11 steve
* vvp support for <= with internal delay.
*
* Revision 1.37 2001/04/06 02:28:02 steve
* Generate vvp code for functions with ports.
*
* Revision 1.36 2001/04/05 03:20:57 steve
* Generate vvp code for the repeat statement.
*
* Revision 1.35 2001/04/05 01:12:28 steve
* Get signed compares working correctly in vvp.
*
* Revision 1.34 2001/04/04 04:50:35 steve
* Support forever loops in the tgt-vvp target.
*
* Revision 1.33 2001/04/03 04:50:37 steve
* Support non-blocking assignments.
*
* Revision 1.32 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.31 2001/04/02 00:28:35 steve
* Support the scope expression node.
*
* Revision 1.30 2001/04/01 06:52:27 steve
* support the NetWhile statement.
*
* Revision 1.29 2001/04/01 01:48:21 steve
* Redesign event information to support arbitrary edge combining.
*
* Revision 1.28 2001/03/31 17:36:38 steve
* Generate vvp code for case statements.
*
* Revision 1.27 2001/03/30 05:49:52 steve
* Generate code for fork/join statements.
*
* Revision 1.26 2001/03/29 03:47:38 steve
* Behavioral trigger statements.
*
* Revision 1.25 2001/03/29 02:52:39 steve
* Add unary ~ operator to tgt-vvp.
*
* Revision 1.24 2001/03/28 06:07:39 steve
* Add the ivl_event_t to ivl_target, and use that to generate
* .event statements in vvp way ahead of the thread that uses it.
*
* Revision 1.23 2001/03/27 06:27:40 steve
* Generate code for simple @ statements.
*
* Revision 1.22 2001/03/20 01:44:13 steve
* Put processes in the proper scope.
*
* Revision 1.21 2001/01/15 00:47:02 steve
* Pass scope type information to the target module.
*
* Revision 1.20 2001/01/15 00:05:39 steve
* Add client data pointer for scope and process scanners.
*
* Revision 1.19 2000/12/05 06:29:33 steve
* Make signal attributes available to ivl_target API.
*
* Revision 1.18 2000/11/12 17:47:29 steve
* flip-flop pins for ivl_target API.
*
* Revision 1.17 2000/11/11 00:03:36 steve
* Add support for the t-dll backend grabing flip-flops.
*
* Revision 1.16 2000/10/28 22:32:34 steve
* API for concatenation expressions.
*
* Revision 1.15 2000/10/25 05:41:24 steve
* Get target signal from nexus_ptr.
*
* Revision 1.14 2000/10/18 20:04:39 steve
* Add ivl_lval_t and support for assignment l-values.
*
* Revision 1.13 2000/10/16 22:44:54 steve
* Stubs so that cygwin port will link ivl.
*
* Revision 1.12 2000/10/15 04:46:23 steve
* Scopes and processes are accessible randomly from
* the design, and signals and logic are accessible
* from scopes. Remove the target calls that are no
* longer needed.
*
* Add the ivl_nexus_ptr_t and the means to get at
* them from nexus objects.
*
* Give names to methods that manipulate the ivl_design_t
* type more consistent names.
*
* Revision 1.11 2000/10/08 04:01:54 steve
* Back pointers in the nexus objects into the devices
* that point to it.
*
* Collect threads into a list in the design.
*
* Revision 1.10 2000/10/06 23:46:50 steve
* ivl_target updates, including more complete
* handling of ivl_nexus_t objects. Much reduced
* dependencies on pointers to netlist objects.
*
* Revision 1.9 2000/10/05 05:03:01 steve
* xor and constant devices.
*
* Revision 1.8 2000/09/30 02:18:15 steve
* ivl_expr_t support for binary operators,
* Create a proper ivl_scope_t object.
*
* Revision 1.7 2000/09/26 00:30:07 steve
* Add EX_NUMBER and ST_TRIGGER to dll-api.
*
* Revision 1.6 2000/09/24 15:46:00 steve
* API access to signal type and port type.
*
* Revision 1.5 2000/09/24 02:21:53 steve
* Add support for signal expressions.
*
* Revision 1.4 2000/09/23 05:15:07 steve
* Add enough tgt-verilog code to support hello world.
*
* Revision 1.3 2000/09/22 03:58:30 steve
* Access to the name of a system task call.
*
* Revision 1.2 2000/09/19 04:15:27 steve
* Introduce the means to get statement types.
*
* Revision 1.1 2000/09/18 01:24:32 steve
* Get the structure for ivl_statement_t worked out.
*
*/
+82 -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: t-dll-expr.cc,v 1.29 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.31 2003/01/27 00:14:37 steve Exp $"
#endif
# include "config.h"
@@ -32,6 +32,26 @@
#endif
# include <stdlib.h>
/*
* This is a little convenience function for converting a NetExpr
* expresion type to the expression type used by ivl_expr_t objects.
*/
static ivl_variable_type_t get_expr_type(const NetExpr*net)
{
switch (net->expr_type()) {
case NetExpr::ET_VOID:
return IVL_VT_VOID;
case NetExpr::ET_REAL:
return IVL_VT_REAL;
case NetExpr::ET_VECTOR:
return IVL_VT_VECTOR;
}
return IVL_VT_VOID;
}
/*
* These methods implement the expression scan that generates the
* ivl_expr_t representing the expression. Each method leaves the
@@ -50,6 +70,7 @@ void dll_target::sub_off_from_expr_(long off)
char*bits;
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmpc->type_ = IVL_EX_NUMBER;
tmpc->value_ = IVL_VT_VECTOR;
tmpc->width_ = expr_->width_;
tmpc->signed_ = expr_->signed_;
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
@@ -63,6 +84,7 @@ void dll_target::sub_off_from_expr_(long off)
the constant to subtract. */
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmps->type_ = IVL_EX_BINARY;
tmps->value_ = IVL_VT_VECTOR;
tmps->width_ = tmpc->width_;
tmps->signed_ = tmpc->signed_;
tmps->u_.binary_.op_ = '-';
@@ -80,6 +102,7 @@ void dll_target::mul_expr_by_const_(long val)
char*bits;
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmpc->type_ = IVL_EX_NUMBER;
tmpc->value_ = IVL_VT_VECTOR;
tmpc->width_ = expr_->width_;
tmpc->signed_ = expr_->signed_;
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
@@ -93,6 +116,7 @@ void dll_target::mul_expr_by_const_(long val)
the constant to subtract. */
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
tmps->type_ = IVL_EX_BINARY;
tmps->value_ = IVL_VT_VECTOR;
tmps->width_ = tmpc->width_;
tmps->signed_ = tmpc->signed_;
tmps->u_.binary_.op_ = '*';
@@ -111,6 +135,7 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val)
unsigned idx;
char*bits;
expr->type_ = IVL_EX_NUMBER;
expr->value_= IVL_VT_VECTOR;
expr->width_= val.len();
expr->signed_ = val.has_sign()? 1 : 0;
expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_);
@@ -150,6 +175,7 @@ void dll_target::expr_binary(const NetEBinary*net)
assert(expr_);
expr_->type_ = IVL_EX_BINARY;
expr_->value_= get_expr_type(net);
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
@@ -165,8 +191,9 @@ void dll_target::expr_concat(const NetEConcat*net)
ivl_expr_t cur = new struct ivl_expr_s;
assert(cur);
cur->type_ = IVL_EX_CONCAT;
cur->width_= net->expr_width();
cur->type_ = IVL_EX_CONCAT;
cur->value_ = IVL_VT_VECTOR;
cur->width_ = net->expr_width();
cur->u_.concat_.rept = net->repeat();
cur->u_.concat_.parms = net->nparms();
@@ -194,6 +221,7 @@ void dll_target::expr_memory(const NetEMemory*net)
assert(cur);
cur->type_ = IVL_EX_MEMORY;
cur->value_ = IVL_VT_VECTOR;
cur->width_= net->expr_width();
cur->signed_ = net->has_sign()? 1 : 0;
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
@@ -210,6 +238,7 @@ void dll_target::expr_const(const NetEConst*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_);
expr_->value_= IVL_VT_VECTOR;
if (net->value().is_string()) {
expr_->type_ = IVL_EX_STRING;
@@ -245,6 +274,17 @@ void dll_target::expr_const(const NetEConst*net)
}
}
void dll_target::expr_creal(const NetECReal*net)
{
assert(expr_ == 0);
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->width_ = net->expr_width();
expr_->signed_ = 1;
expr_->type_ = IVL_EX_REALNUM;
expr_->value_= IVL_VT_REAL;
expr_->u_.real_.value = net->value().as_double();
}
void dll_target::expr_scope(const NetEScope*net)
{
assert(expr_ == 0);
@@ -253,6 +293,7 @@ void dll_target::expr_scope(const NetEScope*net)
assert(expr_);
expr_->type_ = IVL_EX_SCOPE;
expr_->value_= IVL_VT_VOID;
expr_->u_.scope_.scope = lookup_scope_(net->scope());
}
@@ -271,6 +312,7 @@ void dll_target::expr_select(const NetESelect*net)
assert(expr_);
expr_->type_ = IVL_EX_SELECT;
expr_->value_= IVL_VT_VECTOR;
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
@@ -286,6 +328,18 @@ void dll_target::expr_sfunc(const NetESFunc*net)
assert(expr);
expr->type_ = IVL_EX_SFUNC;
switch (net->expr_type()) {
case NetExpr::ET_VECTOR:
expr->value_= IVL_VT_VECTOR;
break;
case NetExpr::ET_REAL:
expr->value_= IVL_VT_REAL;
break;
case NetExpr::ET_VOID:
assert(0);
expr->value_= IVL_VT_VECTOR;
break;
}
expr->width_= net->expr_width();
expr->u_.sfunc_.name_ = strdup(net->name());
@@ -312,6 +366,7 @@ void dll_target::expr_ternary(const NetETernary*net)
assert(expr);
expr->type_ = IVL_EX_TERNARY;
expr->value_= IVL_VT_VECTOR;
expr->width_ = net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
@@ -340,6 +395,7 @@ void dll_target::expr_signal(const NetESignal*net)
assert(expr_);
expr_->type_ = IVL_EX_SIGNAL;
expr_->value_= IVL_VT_VECTOR;
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->u_.signal_.sig = find_signal(des_, net->sig());
@@ -355,6 +411,7 @@ void dll_target::expr_subsignal(const NetEBitSel*net)
assert(expr);
expr->type_ = IVL_EX_BITSEL;
expr->value_= IVL_VT_VECTOR;
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
expr->u_.bitsel_.sig = find_signal(des_, net->sig());
@@ -450,6 +507,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net)
assert(expr);
expr->type_ = IVL_EX_UFUNC;
expr->value_= IVL_VT_VECTOR;
expr->width_= net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
@@ -482,14 +540,35 @@ void dll_target::expr_unary(const NetEUnary*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_UNARY;
expr_->value_= IVL_VT_VECTOR;
expr_->width_ = net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->u_.unary_.op_ = net->op();
expr_->u_.unary_.sub_ = sub;
}
void dll_target::expr_variable(const NetEVariable*net)
{
assert(expr_ == 0);
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_VARIABLE;
expr_->value_ = IVL_VT_REAL;
expr_->width_ = 0;
expr_->signed_= net->has_sign()? 1 : 0;
expr_->u_.variable_.var = find_variable(des_, net->variable());
}
/*
* $Log: t-dll-expr.cc,v $
* Revision 1.31 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.30 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.29 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+10 -1
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-proc.cc,v 1.54 2002/08/19 00:06:12 steve Exp $"
#ident "$Id: t-dll-proc.cc,v 1.55 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -163,6 +163,11 @@ void dll_target::proc_assign(const NetAssign*net)
expr_ = 0;
}
} else if (asn->var()) {
cur->type_ = IVL_LVAL_VAR;
cur->idx = 0;
cur->n.var = find_variable(des_, asn->var());
} else {
assert(asn->mem());
cur->type_ = IVL_LVAL_MEM;
@@ -822,6 +827,10 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* Revision 1.55 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.54 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
+91 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2002 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,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.103 2003/01/26 21:15:59 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;
@@ -234,6 +235,22 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
return 0;
}
ivl_variable_t dll_target::find_variable(ivl_design_s&des,
const NetVariable*net)
{
ivl_scope_t scope = find_scope(des, net->scope());
assert(scope);
const char*nname = net->basename();
for (unsigned idx = 0 ; idx < scope->nvar_ ; idx += 1) {
if (strcmp(scope->var_[idx]->name, nname) == 0)
return scope->var_[idx];
}
assert(0);
return 0;
}
/*
* This function locates an ivl_memory_t object that matches the
* NetMemory object. The search works by looking for the parent scope,
@@ -414,6 +431,14 @@ static void scope_add_mem(ivl_scope_t scope, ivl_memory_t net)
scope->mem_[scope->nmem_-1] = net;
}
static void scope_add_var(ivl_scope_t scope, ivl_variable_t net)
{
scope->nvar_ += 1;
scope->var_ = (ivl_variable_t*)
realloc(scope->var_, scope->nvar_*sizeof(ivl_variable_t));
scope->var_[scope->nvar_-1] = net;
}
void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
{
ivl_scope_t root_ = new struct ivl_scope_s;
@@ -432,8 +457,12 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
root_->lpm_ = 0;
root_->nmem_ = 0;
root_->mem_ = 0;
root_->nvar_ = 0;
root_->var_ = 0;
root_->type_ = IVL_SCT_MODULE;
root_->tname_ = root_->name_;
root_->time_units = s->time_unit();
des_.nroots_++;
if (des_.roots_)
des_.roots_ = (ivl_scope_t *)realloc(des_.roots_, des_.nroots_ * sizeof(ivl_scope_t));
@@ -448,6 +477,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;
}
@@ -629,6 +659,18 @@ void dll_target::event(const NetEvent*net)
}
void dll_target::variable(const NetVariable*net)
{
struct ivl_variable_s *obj = new struct ivl_variable_s;
ivl_scope_t scope = find_scope(des_, net->scope());
obj->type = IVL_VT_REAL;
obj->name = strings_.add(net->basename());
obj->scope = scope;
scope_add_var(scope, obj);
}
void dll_target::logic(const NetLogic*net)
{
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
@@ -1764,6 +1806,7 @@ void dll_target::scope(const NetScope*net)
scope->child_ = 0;
scope->sibling_ = 0;
scope->parent = find_scope(des_, net->parent());
assert(scope->parent);
scope->nsigs_ = 0;
scope->sigs_ = 0;
scope->nlog_ = 0;
@@ -1774,16 +1817,27 @@ void dll_target::scope(const NetScope*net)
scope->lpm_ = 0;
scope->nmem_ = 0;
scope->mem_ = 0;
scope->nvar_ = 0;
scope->var_ = 0;
scope->time_units = net->time_unit();
switch (net->type()) {
case NetScope::MODULE:
scope->type_ = IVL_SCT_MODULE;
scope->tname_ = net->module_name();
break;
case NetScope::TASK:
scope->type_ = IVL_SCT_TASK;
scope->tname_ = strings_.add(net->task_def()->name().c_str());
break;
case NetScope::TASK: {
const NetTaskDef*def = net->task_def();
if (def == 0) {
cerr << "?:?" << ": internal error: "
<< "task " << scope->name_
<< " has no definition." << endl;
}
assert(def);
scope->type_ = IVL_SCT_TASK;
scope->tname_ = strings_.add(def->name().c_str());
break;
}
case NetScope::FUNC:
scope->type_ = IVL_SCT_FUNCTION;
scope->tname_ = strings_.add(net->func_def()->name().c_str());
@@ -1979,6 +2033,29 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.103 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.102 2003/01/16 21:43:52 steve
* Assert some task definition sanity.
*
* Revision 1.101 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.100 2002/11/05 02:12:35 steve
* Fix the call to FormatMessage under Windows.
*
* 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.
+41 -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: t-dll.h,v 1.95 2002/10/23 01:47:17 steve Exp $"
#ident "$Id: t-dll.h,v 1.97 2003/01/26 21:15:59 steve Exp $"
#endif
# include "target.h"
@@ -68,6 +68,7 @@ struct dll_target : public target_t, public expr_scan_t {
bool bufz(const NetBUFZ*);
void event(const NetEvent*);
void variable(const NetVariable*);
void logic(const NetLogic*);
void net_case_cmp(const NetCaseCmp*);
void udp(const NetUDP*);
@@ -130,6 +131,7 @@ struct dll_target : public target_t, public expr_scan_t {
void expr_concat(const NetEConcat*);
void expr_memory(const NetEMemory*);
void expr_const(const NetEConst*);
void expr_creal(const NetECReal*);
void expr_scope(const NetEScope*);
void expr_select(const NetESelect*);
void expr_sfunc(const NetESFunc*);
@@ -138,6 +140,7 @@ struct dll_target : public target_t, public expr_scan_t {
void expr_ufunc(const NetEUFunc*);
void expr_unary(const NetEUnary*);
void expr_signal(const NetESignal*);
void expr_variable(const NetEVariable*);
ivl_scope_t lookup_scope_(const NetScope*scope);
@@ -150,6 +153,7 @@ struct dll_target : public target_t, public expr_scan_t {
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
static ivl_variable_t find_variable(ivl_design_s &des, const NetVariable*net);
void add_root(ivl_design_s &des_, const NetScope *s);
void sub_off_from_expr_(long);
@@ -177,6 +181,7 @@ struct ivl_event_s {
*/
struct ivl_expr_s {
ivl_expr_type_t type_;
ivl_variable_type_t value_;
unsigned width_ :24;
unsigned signed_ : 1;
@@ -243,11 +248,18 @@ struct ivl_expr_s {
unsigned long value;
} ulong_;
struct {
double value;
} real_;
struct {
char op_;
ivl_expr_t sub_;
} unary_;
struct {
ivl_variable_t var;
} variable_;
} u_;
};
@@ -334,7 +346,8 @@ enum ivl_lval_type_t {
IVL_LVAL_REG = 0,
IVL_LVAL_MUX = 1,
IVL_LVAL_MEM = 2,
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
IVL_LVAL_VAR = 4
};
struct ivl_lval_s {
@@ -345,6 +358,7 @@ struct ivl_lval_s {
union {
ivl_signal_t sig;
ivl_memory_t mem;
ivl_variable_t var;
} n;
};
@@ -495,11 +509,16 @@ struct ivl_scope_s {
unsigned nmem_;
ivl_memory_t* mem_;
unsigned nvar_;
ivl_variable_t* var_;
/* Scopes that are tasks/functions have a definition. */
ivl_statement_t def;
unsigned ports;
ivl_signal_t*port;
signed int time_units :8;
};
/*
@@ -620,8 +639,28 @@ struct ivl_statement_s {
} u_;
};
/*
* This holds the details about a variable object.
*/
struct ivl_variable_s {
ivl_variable_type_t type;
const char* name;
ivl_scope_t scope;
};
/*
* $Log: t-dll.h,v $
* Revision 1.97 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.96 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.95 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+7 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-xnf.cc,v 1.45 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: t-xnf.cc,v 1.46 2003/01/14 21:16:18 steve Exp $"
#endif
# include "config.h"
@@ -77,7 +77,7 @@
# include "netlist.h"
# include "target.h"
# include <fstream>
# include <strstream>
# include <sstream>
verinum::V link_get_ival(const Link&lnk)
{
@@ -765,8 +765,8 @@ void target_xnf::lpm_ram_dq(const NetRamDq*ram)
draw_pin(out_, "WE", ram->pin_WE());
draw_pin(out_, "WCLK", ram->pin_InClock());
for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
strstream tmp;
tmp << "A" << adr << ends;
ostringstream tmp;
tmp << "A" << adr;
draw_pin(out_, tmp.str(), ram->pin_Address(adr));
}
@@ -927,6 +927,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
/*
* $Log: t-xnf.cc,v $
* Revision 1.46 2003/01/14 21:16:18 steve
* Move strstream to ostringstream for compatibility.
*
* Revision 1.45 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+24 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2002 Stephen Williams <steve@icarus.com>
* Copyright (c) 1998-2003 Stephen Williams <steve@icarus.com>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.cc,v 1.63 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: target.cc,v 1.64 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -47,6 +47,12 @@ void target_t::memory(const NetMemory*)
"Unhandled memory." << endl;
}
void target_t::variable(const NetVariable*that)
{
cerr << that->get_line() << ": error: target (" << typeid(*this).name()
<< "): Unhandled variable <" << that->basename() << ">." << endl;
}
void target_t::func_def(const NetScope*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -317,6 +323,12 @@ void expr_scan_t::expr_const(const NetEConst*)
"unhandled expr_const." << endl;
}
void expr_scan_t::expr_creal(const NetECReal*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_creal." << endl;
}
void expr_scan_t::expr_concat(const NetEConcat*that)
{
cerr << that->get_line() << ": expr_scan_t (" <<
@@ -377,6 +389,12 @@ void expr_scan_t::expr_unary(const NetEUnary*)
"unhandled expr_unary." << endl;
}
void expr_scan_t::expr_variable(const NetEVariable*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_variable." << endl;
}
void expr_scan_t::expr_binary(const NetEBinary*ex)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
@@ -385,6 +403,10 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.64 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.63 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+11 -2
View File
@@ -1,7 +1,7 @@
#ifndef __target_H
#define __target_H
/*
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.h,v 1.60 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: target.h,v 1.61 2003/01/26 21:15:59 steve Exp $"
#endif
# include "netlist.h"
@@ -68,6 +68,9 @@ struct target_t {
/* Output a memory (called for each memory object) */
virtual void memory(const NetMemory*);
/* Output an event object. Called for each named event in the scope. */
virtual void variable(const NetVariable*);
/* Output a defined task. */
virtual void task_def(const NetScope*);
virtual void func_def(const NetScope*);
@@ -128,6 +131,7 @@ struct target_t {
struct expr_scan_t {
virtual ~expr_scan_t();
virtual void expr_const(const NetEConst*);
virtual void expr_creal(const NetECReal*);
virtual void expr_concat(const NetEConcat*);
virtual void expr_memory(const NetEMemory*);
virtual void expr_scope(const NetEScope*);
@@ -138,6 +142,7 @@ struct expr_scan_t {
virtual void expr_ternary(const NetETernary*);
virtual void expr_ufunc(const NetEUFunc*);
virtual void expr_unary(const NetEUnary*);
virtual void expr_variable(const NetEVariable*);
virtual void expr_binary(const NetEBinary*);
};
@@ -162,6 +167,10 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.61 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.60 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+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
+74 -11
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.70 2002/10/23 01:45:24 steve Exp $"
#ident "$Id: stub.c,v 1.72 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -40,6 +40,19 @@ static void show_expression(ivl_expr_t net, unsigned ind)
const ivl_expr_type_t code = ivl_expr_type(net);
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = "?";
switch (ivl_expr_value(net)) {
case IVL_VT_VOID:
vt = "void";
break;
case IVL_VT_REAL:
vt = "real";
break;
case IVL_VT_VECTOR:
vt = "vector";
break;
}
switch (code) {
@@ -50,15 +63,15 @@ static void show_expression(ivl_expr_t net, unsigned ind)
break;
case IVL_EX_BINARY:
fprintf(out, "%*s<\"%c\" width=%u, %s>\n", ind, "",
ivl_expr_opcode(net), width, sign);
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
ivl_expr_opcode(net), width, sign, vt);
show_expression(ivl_expr_oper1(net), ind+3);
show_expression(ivl_expr_oper2(net), ind+3);
break;
case IVL_EX_CONCAT:
fprintf(out, "%*s<concat repeat=%u, width=%u, %s>\n", ind, "",
ivl_expr_repeat(net), width, sign);
fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
ind, "", ivl_expr_repeat(net), width, sign, vt);
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
show_expression(ivl_expr_parm(net, idx), ind+3);
@@ -116,6 +129,15 @@ static void show_expression(ivl_expr_t net, unsigned ind)
show_expression(ivl_expr_oper1(net), ind+4);
break;
case IVL_EX_VARIABLE:
fprintf(out, "%*s<variable %s, type=%s>\n",
ind, "", ivl_expr_name(net), vt);
break;
case IVL_EX_REALNUM:
fprintf(out, "%*s<realnum=%f>\n", ind, "", ivl_expr_dvalue(net));
break;
default:
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
break;
@@ -244,6 +266,7 @@ static void show_lpm(ivl_lpm_t net)
static void show_assign_lval(ivl_lval_t lval, unsigned ind)
{
ivl_memory_t mem;
ivl_variable_t var;
if ( (mem = ivl_lval_mem(lval)) ) {
@@ -254,6 +277,10 @@ static void show_assign_lval(ivl_lval_t lval, unsigned ind)
show_expression(ivl_lval_idx(lval), ind+4);
fprintf(out, "%*s]\n", ind, "");
} else if ( (var = ivl_lval_var(lval)) ) {
fprintf(out, "%*svariable %s\n", ind, "", ivl_variable_name(var));
} else {
unsigned pp;
ivl_nexus_t nex = ivl_lval_pin(lval, 0);
@@ -450,6 +477,26 @@ static int show_process(ivl_process_t net, void*x)
return 0;
}
static void show_variable(ivl_variable_t net)
{
const char*type = "?";
const char*name = ivl_variable_name(net);
switch (ivl_variable_type(net)) {
case IVL_VT_VOID:
type = "void";
break;
case IVL_VT_REAL:
type = "real";
break;
case IVL_VT_VECTOR:
type = "vector";
break;
}
fprintf(out, " variable %s %s;\n", type, name);
}
static void show_event(ivl_event_t net)
{
unsigned idx;
@@ -666,26 +713,31 @@ static int show_scope(ivl_scope_t net, void*x)
switch (ivl_scope_type(net)) {
case IVL_SCT_MODULE:
fprintf(out, " module %s\n", ivl_scope_tname(net));
fprintf(out, " module %s", ivl_scope_tname(net));
break;
case IVL_SCT_FUNCTION:
fprintf(out, " function %s\n", ivl_scope_tname(net));
fprintf(out, " function %s", ivl_scope_tname(net));
break;
case IVL_SCT_BEGIN:
fprintf(out, " begin : %s\n", ivl_scope_tname(net));
fprintf(out, " begin : %s", ivl_scope_tname(net));
break;
case IVL_SCT_FORK:
fprintf(out, " fork : %s\n", ivl_scope_tname(net));
fprintf(out, " fork : %s", ivl_scope_tname(net));
break;
case IVL_SCT_TASK:
fprintf(out, " task %s\n", ivl_scope_tname(net));
fprintf(out, " task %s", ivl_scope_tname(net));
break;
default:
fprintf(out, " type(%u) %s\n", ivl_scope_type(net),
fprintf(out, " type(%u) %s", ivl_scope_type(net),
ivl_scope_tname(net));
break;
}
fprintf(out, " time units = 10e%d\n", ivl_scope_time_units(net));
for (idx = 0 ; idx < ivl_scope_vars(net) ; idx += 1)
show_variable(ivl_scope_var(net, idx));
for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1)
show_event(ivl_scope_event(net, idx));
@@ -728,6 +780,17 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.72 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.71 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.70 2002/10/23 01:45:24 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
+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
+3 -3
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.13 2003/01/26 21:15:59 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,7 +50,7 @@ all: vvp.tgt
$(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = vvp.o draw_mux.o eval_expr.o vector.o vvp_process.o vvp_scope.o
O = vvp.o draw_mux.o eval_expr.o eval_real.o vector.o vvp_process.o vvp_scope.o
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
@@ -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
+291 -99
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.90 2003/01/27 00:14:37 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)
{
@@ -187,7 +189,8 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
} else if (lv.wid < ewid) {
unsigned short base = allocate_vector(ewid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", base,
lv.base, lv.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
@@ -199,6 +202,43 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
return lv;
}
/*
* This handles the special case that the operands of the comparison
* are real valued expressions.
*/
static struct vector_info draw_binary_expr_eq_real(ivl_expr_t exp)
{
struct vector_info res;
int lword, rword;
res.base = allocate_vector(1);
res.wid = 1;
lword = draw_eval_real(ivl_expr_oper1(exp));
rword = draw_eval_real(ivl_expr_oper2(exp));
clr_word(lword);
clr_word(rword);
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword);
switch (ivl_expr_opcode(exp)) {
case 'e':
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
break;
case 'n': /* != */
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);
break;
default:
assert(0);
}
return res;
}
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
unsigned ewid,
int stuff_ok_flag)
@@ -220,6 +260,14 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
&& number_is_immediate(re, 16))
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
if (ivl_expr_value(le) == IVL_VT_REAL) {
assert(ivl_expr_value(re) == IVL_VT_REAL);
return draw_binary_expr_eq_real(exp);
}
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
wid = ivl_expr_width(le);
if (ivl_expr_width(re) > wid)
wid = ivl_expr_width(re);
@@ -232,8 +280,10 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
assert(lv.wid == rv.wid);
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base,
rv.base, lv.wid);
clr_vector(lv);
clr_vector(rv);
if (lv.base >= 8)
clr_vector(lv);
if (rv.base >= 8)
clr_vector(rv);
lv.base = 6;
lv.wid = 1;
break;
@@ -460,6 +510,40 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
return lv;
}
static struct vector_info draw_binary_expr_le_real(ivl_expr_t exp)
{
struct vector_info res;
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
int lword = draw_eval_real(le);
int rword = draw_eval_real(re);
res.base = allocate_vector(1);
res.wid = 1;
clr_word(lword);
clr_word(rword);
switch (ivl_expr_opcode(exp)) {
case '<':
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword);
fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base);
break;
case '>':
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", rword, lword);
fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base);
break;
default:
assert(0);
}
return res;
}
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
unsigned wid,
int stuff_ok_flag)
@@ -476,6 +560,14 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
if (ivl_expr_width(re) > owid)
owid = ivl_expr_width(re);
if (ivl_expr_value(le) == IVL_VT_REAL) {
assert(ivl_expr_value(re) == IVL_VT_REAL);
return draw_binary_expr_le_real(exp);
}
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
@@ -616,9 +708,62 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
const char*opcode = "?";
struct vector_info lv;
/* Evaluate the expression that is to be shifted. */
switch (ivl_expr_opcode(exp)) {
case 'l': /* << (left shift) */
lv = draw_eval_expr_wid(le, wid, 0);
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
opcode = "%shiftl";
break;
case 'r': /* >> (unsigned right shift) */
/* with the right shift, there may be high bits that are
shifted into the desired width of the expression, so
we let the expression size itself, if it is bigger
then what is requested of us. */
if (wid > ivl_expr_width(le)) {
lv = draw_eval_expr_wid(le, wid, 0);
} else {
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
}
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
opcode = "%shiftr";
break;
default:
assert(0);
}
/* Figure out the shift amount and load that into the index
register. The value may be a constant, or may need to be
evaluated at run time. */
@@ -659,21 +804,11 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
}
}
lv = draw_eval_expr_wid(le, wid, 0);
switch (ivl_expr_opcode(exp)) {
fprintf(vvp_out, " %s/i0 %u, %u;\n", opcode, lv.base, lv.wid);
case 'l': /* << (left shift) */
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
break;
case 'r': /* >> (unsigned right shift) */
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lv.base, lv.wid);
break;
default:
assert(0);
}
if (lv.base >= 8)
save_expression_lookaside(lv.base, exp, lv.wid);
return lv;
}
@@ -789,6 +924,12 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
if (lv.wid != wid) {
fprintf(stderr, "XXXX ivl_expr_opcode(exp) = %c,"
" lv.wid=%u, wid=%u\n", ivl_expr_opcode(exp),
lv.wid, wid);
}
assert(lv.wid == wid);
assert(rv.wid == wid);
@@ -990,22 +1131,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;
@@ -1115,6 +1260,19 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
return res;
}
static struct vector_info draw_realnum_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
double val = ivl_expr_dvalue(exp);
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " ; XXXX draw_realnum_expr(%f, %u)\n", val, wid);
return res;
}
/*
* A string in an expression is made up by copying constant bits into
* the allocated vector.
@@ -1171,36 +1329,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;
}
@@ -1314,7 +1490,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
writeable vector space and work from there instead. */
if (subv.base < 4) {
res.base = allocate_vector(subv.wid);
res.wid = wid;
res.wid = subv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base,
subv.base, res.wid);
subv = res;
@@ -1509,8 +1685,10 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, ", $time");
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $stime");
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $realtime");
else
fprintf(vvp_out, ", ?");
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
continue;
case IVL_EX_MEMORY:
@@ -1794,6 +1972,53 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
return res;
}
static struct vector_info draw_variable_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
ivl_variable_t var = ivl_expr_variable(exp);
fprintf(vvp_out, " ; XXXX Read variable %s\n",
ivl_variable_name(var));
res.base = 0;
res.wid = 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)
{
@@ -1829,6 +2054,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
res = draw_number_expr(exp, wid);
break;
case IVL_EX_REALNUM:
res = draw_realnum_expr(exp, wid);
break;
case IVL_EX_SELECT:
res = draw_select_expr(exp, wid);
break;
@@ -1856,6 +2085,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
case IVL_EX_UNARY:
res = draw_unary_expr(exp, wid);
break;
case IVL_EX_VARIABLE:
res = draw_variable_expr(exp, wid);
break;
}
return res;
@@ -1868,60 +2101,19 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.82 2002/10/20 02:55:37 steve
* Properly set or clear expression lookaside for binary expressions.
* Revision 1.90 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.81 2002/09/27 20:24:42 steve
* Allow expression lookaside map to spam statements.
* Revision 1.89 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.80 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
* Revision 1.88 2002/12/20 01:11:14 steve
* Evaluate shift index after shift operand because
* the chift operand may use the index register itself.
*
* Revision 1.79 2002/09/24 04:20:32 steve
* Allow results in register bits 47 in certain cases.
*
* Revision 1.78 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.77 2002/09/13 04:09:51 steve
* single bit optimization for != in expressions,
* and expand ++ and != results if needed.
*
* Revision 1.76 2002/09/13 03:12:50 steve
* Optimize ==1 when in context where x vs z doesnt matter.
*
* Revision 1.75 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.74 2002/09/01 01:42:34 steve
* Fix leaking vthread bits in ?: eval.
*
* Revision 1.73 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
* Revision 1.72 2002/08/28 17:15:35 steve
* Generate %load/nx for indexed load of nets.
*
* Revision 1.71 2002/08/27 05:39:57 steve
* Fix l-value indexing of memories and vectors so that
* an unknown (x) index causes so cell to be addresses.
*
* Fix tangling of label identifiers in the fork-join
* code generator.
*
* Revision 1.70 2002/08/22 03:38:40 steve
* Fix behavioral eval of x?a:b expressions.
*
* Revision 1.69 2002/08/12 01:35:03 steve
* conditional ident string using autoconfig.
*
* Revision 1.68 2002/08/05 04:18:45 steve
* Store only the base name of memories.
*
* Revision 1.67 2002/08/04 18:28:15 steve
* Do not use hierarchical names of memories to
* generate vvp labels. -tdll target does not
* used hierarchical name string to look up the
* memory objects in the design.
* Revision 1.87 2002/12/19 23:11:29 steve
* Keep bit select subexpression width if it is constant.
*/
+223
View File
@@ -0,0 +1,223 @@
/*
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_real.c,v 1.2 2003/01/27 00:14:37 steve Exp $"
#endif
/*
* This file includes functions for evaluating REAL expressions.
*/
# include "vvp_priv.h"
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <math.h>
# include <assert.h>
static unsigned long word_alloc_mask = 0x0f;
int allocate_word()
{
int res = 4;
while ((1 << res) & word_alloc_mask)
res += 1;
word_alloc_mask |= 1 << res;
return res;
}
void clr_word(int res)
{
assert(word_alloc_mask & (1 << res));
word_alloc_mask &= ~ (1 << res);
}
static int draw_binary_real(ivl_expr_t exp)
{
int l, r;
l = draw_eval_real(ivl_expr_oper1(exp));
r = draw_eval_real(ivl_expr_oper2(exp));
switch (ivl_expr_opcode(exp)) {
case '+':
fprintf(vvp_out, " %%add/wr %d, %d;\n", l, r);
clr_word(r);
break;
case '*':
fprintf(vvp_out, " %%mul/wr %d, %d;\n", l, r);
clr_word(r);
break;
default:
assert(0);
}
return l;
}
static int draw_number_real(ivl_expr_t exp)
{
int idx;
int res = allocate_word();
const char*bits = ivl_expr_bits(exp);
unsigned wid = ivl_expr_width(exp);
unsigned long mant = 0;
for (idx = 0 ; idx < wid ; idx += 1) {
if (bits[idx] == '1')
mant |= 1 << idx;
}
fprintf(vvp_out, " %%loadi/wr %d, %lu, 4096;\n", res, mant);
return res;
}
/*
* Evaluate a real variable expression by loading the real variable
* into a real thread word.
*/
static int draw_variable_real(ivl_expr_t exp)
{
int res = allocate_word();
ivl_variable_t var = ivl_expr_variable(exp);
fprintf(vvp_out, " %%load/wr %d, W_%s;\n", res, vvp_word_label(var));
return res;
}
static int draw_realnum_real(ivl_expr_t exp)
{
int res = allocate_word();
double value = ivl_expr_dvalue(exp);
double fract;
int vexp;
unsigned long mant;
int sign = 0;
if (value < 0) {
sign = 0x4000;;
value *= -1;
}
fract = frexp(value, &vexp);
fract *= 0x10000;
fract *= 0x10000;
mant = fract;
vexp -= 32;
vexp += 0x1000;
assert(vexp >= 0);
assert(vexp < 0x2000);
vexp += sign;
fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load=%f\n",
res, mant, vexp, ivl_expr_dvalue(exp));
return res;
}
static int draw_sfunc_real(ivl_expr_t exp)
{
int res;
assert(ivl_expr_parms(exp) == 0);
assert(ivl_expr_value(exp) == IVL_VT_REAL);
res = allocate_word();
fprintf(vvp_out, " %%vpi_func/r \"%s\", %d;\n",
ivl_expr_name(exp), res);
return res;
}
/*
* The real value of a signal is the integer value of a signal
* converted to real.
*/
static int draw_signal_real(ivl_expr_t exp)
{
int res = allocate_word();
struct vector_info sv = draw_eval_expr(exp, 0);
fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, sv.base, sv.wid);
clr_vector(sv);
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
return res;
}
int draw_eval_real(ivl_expr_t exp)
{
int res = 0;
switch (ivl_expr_type(exp)) {
case IVL_EX_BINARY:
res = draw_binary_real(exp);
break;
case IVL_EX_NUMBER:
res = draw_number_real(exp);
break;
case IVL_EX_REALNUM:
res = draw_realnum_real(exp);
break;
case IVL_EX_VARIABLE:
res = draw_variable_real(exp);
break;
case IVL_EX_SFUNC:
res = draw_sfunc_real(exp);
break;
case IVL_EX_SIGNAL:
res = draw_signal_real(exp);
break;
default:
fprintf(vvp_out, " ; XXXX Evaluate real expression (%d)\n",
ivl_expr_type(exp));
return 0;
}
return res;
}
/*
* $Log: eval_real.c,v $
* Revision 1.2 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.1 2003/01/26 21:16:00 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
+20 -33
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.23 2003/01/26 21:16:00 steve Exp $"
#endif
# include "ivl_target.h"
@@ -48,6 +48,8 @@ extern const char* vvp_signal_label(ivl_signal_t sig);
*/
extern const char* vvp_memory_label(ivl_memory_t mem);
extern const char* vvp_word_label(ivl_variable_t var);
/*
* This function draws a process (initial or always) into the output
* file. It normally returns 0, but returns !0 of there is some sort
@@ -158,6 +160,19 @@ extern int number_is_unknown(ivl_expr_t ex);
extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid);
extern unsigned long get_number_immediate(ivl_expr_t ex);
/*
* draw_eval_real evaluates real value expressions. The return code
* from the function is the index of the word register that contains
* the result.
*/
extern int draw_eval_real(ivl_expr_t ex);
/*
* These functions manage word register allocation.
*/
extern int allocate_word(void);
extern void clr_word(int idx);
/*
* These are used to count labels as I generate code.
*/
@@ -166,6 +181,10 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.23 2003/01/26 21:16:00 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.22 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
@@ -211,37 +230,5 @@ extern unsigned thread_count;
* 2. Id and name mangling
* 3. A memory leak in draw_net_in_scope()
* (Stephan Boettcher)
*
* Revision 1.10 2001/05/17 04:37:02 steve
* Behavioral ternary operators for vvp.
*
* Revision 1.9 2001/05/06 17:54:33 steve
* Behavioral code to read memories. (Stephan Boettcher)
*
* Revision 1.8 2001/04/06 02:28:03 steve
* Generate vvp code for functions with ports.
*
* Revision 1.7 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.6 2001/03/31 17:36:39 steve
* Generate vvp code for case statements.
*
* Revision 1.5 2001/03/27 06:27:41 steve
* Generate code for simple @ statements.
*
* Revision 1.4 2001/03/27 03:31:07 steve
* Support error code from target_t::end_design method.
*
* Revision 1.3 2001/03/22 05:06:21 steve
* Geneate code for conditional statements.
*
* Revision 1.2 2001/03/21 01:49:43 steve
* Scan the scopes of a design, and draw behavioral
* blocking assignments of constants to vectors.
*
* Revision 1.1 2001/03/19 01:20:46 steve
* Add the tgt-vvp code generator target.
*
*/
#endif
+300 -57
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.78 2003/01/27 00:14:37 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)
{
@@ -143,7 +164,7 @@ static void calculate_into_x1(ivl_expr_t expr)
clr_vector(vec);
}
static int show_stmt_assign(ivl_statement_t net)
static int show_stmt_assign_vector(ivl_statement_t net)
{
ivl_lval_t lval;
ivl_expr_t rval = ivl_stmt_rval(net);
@@ -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);
@@ -281,6 +325,56 @@ static int show_stmt_assign(ivl_statement_t net)
return 0;
}
static int show_stmt_assign_real(ivl_statement_t net)
{
int res;
ivl_lval_t lval;
ivl_variable_t var;
res = draw_eval_real(ivl_stmt_rval(net));
clr_word(res);
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
var = ivl_lval_var(lval);
assert(var != 0);
fprintf(vvp_out, " %%set/wr W_%s, %d;\n",
vvp_word_label(var), res);
return 0;
}
static int show_stmt_assign(ivl_statement_t net)
{
ivl_lval_t lval;
ivl_variable_t var;
lval = ivl_stmt_lval(net, 0);
if ( (var = ivl_lval_var(lval)) != 0 ) {
switch (ivl_variable_type(var)) {
case IVL_VT_VOID:
assert(0);
return 1;
case IVL_VT_VECTOR:
/* Can't happen. */
assert(0);
return 1;
case IVL_VT_REAL:
return show_stmt_assign_real(net);
}
} else {
return show_stmt_assign_vector(net);
}
return 0;
}
static int show_stmt_assign_nb(ivl_statement_t net)
{
ivl_lval_t lval;
@@ -345,6 +439,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 +554,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) {
@@ -732,9 +884,25 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
ivl_expr_t exp = ivl_stmt_delay_expr(net);
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
{ struct vector_info del = draw_eval_expr(exp, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", del.base, del.wid);
clr_vector(del);
switch (ivl_expr_value(exp)) {
case IVL_VT_VECTOR: {
struct vector_info del = draw_eval_expr(exp, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n",
del.base, del.wid);
clr_vector(del);
break;
}
case IVL_VT_REAL: {
int word = draw_eval_real(exp);
fprintf(vvp_out, " %%cvt/ir 0, %d;\n", word);
clr_word(word);
break;
}
default:
assert(0);
}
fprintf(vvp_out, " %%delayx 0;\n");
@@ -761,6 +929,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 +939,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;
}
@@ -1027,21 +1197,33 @@ static int show_system_task_call(ivl_statement_t net)
return 0;
}
/* Figure out how many expressions are going to be evaluated
for this task call. I won't need to evaluate expressions
for items that are VPI objects directly. */
for (idx = 0 ; idx < parm_count ; idx += 1) {
ivl_expr_t expr = ivl_stmt_parm(net, idx);
switch (ivl_expr_type(expr)) {
/* These expression types can be handled directly,
with VPI handles of their own. Therefore, skip
them in the process of evaluating expressions. */
case IVL_EX_NONE:
case IVL_EX_NUMBER:
case IVL_EX_STRING:
case IVL_EX_SCOPE:
case IVL_EX_SFUNC:
case IVL_EX_VARIABLE:
continue;
case IVL_EX_SIGNAL:
/* If the signal node is narrower then the signal
itself, then this is a part select so I'm going
to need to evaluate the expression. */
to need to evaluate the expression.
If I don't need to do any evaluating, then skip
it as I'll be passing the handle to the signal
itself. */
if (ivl_expr_width(expr) !=
ivl_signal_pins(ivl_expr_signal(expr))) {
break;
@@ -1049,17 +1231,32 @@ static int show_system_task_call(ivl_statement_t net)
continue;
}
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
continue;
}
/* Everything else will need to be evaluated and
passed as a constant to the vpi task. */
default:
break;
}
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
vec[vecs] = draw_eval_expr(expr, 0);
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
vec[vecs] = draw_eval_expr(expr, 0);
break;
case IVL_VT_REAL:
vec[vecs].base = draw_eval_real(expr);
vec[vecs].wid = 0;
break;
default:
assert(0);
}
vecs++;
}
@@ -1096,6 +1293,12 @@ static int show_system_task_call(ivl_statement_t net)
continue;
}
case IVL_EX_VARIABLE: {
ivl_variable_t var = ivl_expr_variable(expr);
fprintf(vvp_out, ", W_%s", vvp_word_label(var));
continue;
}
case IVL_EX_STRING:
fprintf(vvp_out, ", \"%s\"",
ivl_expr_string(expr));
@@ -1110,9 +1313,11 @@ static int show_system_task_call(ivl_statement_t net)
if (strcmp("$time", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $time");
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $time");
fprintf(vvp_out, ", $stime");
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
fprintf(vvp_out, ", $realtime");
else
fprintf(vvp_out, ", ?");
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
continue;
case IVL_EX_MEMORY:
@@ -1127,16 +1332,31 @@ static int show_system_task_call(ivl_statement_t net)
break;
}
assert(veci < vecs);
fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
break;
case IVL_VT_REAL:
fprintf(vvp_out, ", W<%u,r>", vec[veci].base);
break;
default:
assert(0);
}
veci++;
}
assert(veci == vecs);
if (vecs) {
for (idx = 0; idx < vecs; idx++)
clr_vector(vec[idx]);
for (idx = 0; idx < vecs; idx++) {
if (vec[idx].wid > 0)
clr_vector(vec[idx]);
}
free(vec);
}
@@ -1345,6 +1565,29 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.78 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.77 2003/01/26 21:16:00 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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.
*
+54 -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: vvp_scope.c,v 1.80 2002/10/23 04:39:35 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.83 2003/01/26 21:16:00 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -139,6 +139,13 @@ const char* vvp_signal_label(ivl_signal_t sig)
return buf;
}
const char* vvp_word_label(ivl_variable_t sig)
{
static char buf[32];
sprintf(buf, "$%p", sig);
return buf;
}
/*
* This makes a string suitable for use as a label for memories.
*/
@@ -1367,10 +1374,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 +1401,15 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
draw_input_from_net(ivl_lpm_data(net, idx));
}
for (idx = 0 ; idx < selects ; idx += 1) {
for (idx = 0 ; idx < selwid ; idx += 1) {
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_select(net, idx));
}
for (idx = selwid ; idx < width ; idx += 1) {
fprintf(vvp_out, ", C<0>");
}
fprintf(vvp_out, ";\n");
}
@@ -1532,12 +1554,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
vvp_mangle_id(ivl_scope_name(net)),
type,
vvp_mangle_name(ivl_scope_name(net)));
if (parent) {
fprintf(vvp_out, ", S_%s;\n",
vvp_mangle_id(ivl_scope_name(parent)));
}
else
} else {
fprintf(vvp_out, ";\n");
}
fprintf(vvp_out, " .timescale %d;\n", ivl_scope_time_units(net));
/* Scan the scope for logic devices. For each device, draw out
a functor that connects pin 0 to the output, and the
@@ -1549,6 +1575,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
}
/* Scan the scope for word variables. */
for (idx = 0 ; idx < ivl_scope_vars(net) ; idx += 1) {
ivl_variable_t var = ivl_scope_var(net, idx);
const char*type = "real";
fprintf(vvp_out, "W_%s .word %s, \"%s\";\n",
vvp_word_label(var), type,
ivl_variable_name(var));
}
/* Scan the signals (reg and net) and draw the appropriate
statements to make the signal function. */
@@ -1592,6 +1628,20 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.83 2003/01/26 21:16:00 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.82 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.81 2002/11/21 18:08:09 steve
* Better handling of select width of shifters.
*
* Revision 1.80 2002/10/23 04:39:35 steve
* draw lpm ff with aset_expr taken into account.
*
+3 -3
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
+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: verireal.cc,v 1.8 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: verireal.cc,v 1.9 2003/01/26 21:15:59 steve Exp $"
#endif
# include "config.h"
@@ -25,6 +25,7 @@
# include "verireal.h"
# include <ctype.h>
# include <iostream>
# include <math.h>
# include <assert.h>
verireal::verireal()
@@ -123,6 +124,11 @@ long verireal::as_long(int shift) const
return val;
}
double verireal::as_double() const
{
return mant_ * pow(10.0, exp10_) * (sign_? -1 : 1);
}
verireal operator* (const verireal&l, const verireal&r)
{
verireal res;
@@ -140,6 +146,10 @@ ostream& operator<< (ostream&out, const verireal&v)
/*
* $Log: verireal.cc,v $
* Revision 1.9 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.8 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+6 -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: verireal.h,v 1.6 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: verireal.h,v 1.7 2003/01/26 21:15:59 steve Exp $"
#endif
#ifdef HAVE_IOSFWD
@@ -53,6 +53,7 @@ class verireal {
is 25. */
long as_long(int shift =0) const;
double as_double() const;
private:
bool sign_;
@@ -65,6 +66,10 @@ extern verireal operator* (const verireal&, const verireal&);
/*
* $Log: verireal.h,v $
* Revision 1.7 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.6 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+134 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: veriuser.h,v 1.17 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: veriuser.h,v 1.18 2002/12/19 21:37:04 steve Exp $"
#endif
/*
@@ -56,6 +56,47 @@
EXTERN_C_START
#ifndef PLI_TYPES
#define PLI_TYPES
typedef signed int PLI_INT32;
typedef unsigned int PLI_UINT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT12;
typedef signed char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
#endif
/*
* defines for tf_message
*/
#define ERR_MESSAGE 1
#define ERR_WARNING 2
#define ERR_ERROR 3
#define ERR_INTERNAL 4
#define ERR_SYSTEM 5
/*
* These are some defines for backwards compatibility. They should not
* be used in new code.
*/
#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif
#ifndef __cplusplus
# ifndef true
# define true 1
# endif
# ifndef false
# define false 0
# endif
# ifndef bool
# define bool int
# endif
#endif
/*
* structure for veriusertfs array
*/
@@ -74,6 +115,20 @@ typedef struct t_tfcell
char reserved[20]; /* reserved */
} s_tfcell, *p_tfcell;
/*
* Normal PLI1.0 modules export a veriusertfs array that contains all
* the function definitions for use by the simulator. The user code is
* expected to supply that array.
*
* However, Icarus Verilog doesn't normally look for the veriusertfs
* array, it instead looks for the vlog_startup_routines array, as
* declared in vpi_user.h. So the veriuser library includes the
* veriusertfs_register function that can be used to do the PLI 1.0
* setup. Create a vlog_startup_routines table like this if you are
* just interested in making your PLI1 functions work:
*
* void (*vlog_startup_routines[])() = { &veriusertfs_register };
*/
extern s_tfcell veriusertfs[];
extern void veriusertfs_register();
@@ -88,6 +143,64 @@ extern void veriusertfs_register();
#define reason_finish 9
#define reason_endofcompile 16
/* These are values returned by tf_typep */
#define tf_nullparam 0
#define TF_NULLPARAM tf_nullparam
#define tf_string 1
#define TF_STRING tf_string
#define tf_readonly 10
#define TF_READONLY tf_readonly
#define tf_readwrite 11
#define TF_READWRITE tf_readwrite
#define tf_rwbitselect 12
#define TF_RWBITSELECT tf_rwbitselect
#define tf_rwpartselect 13
#define TF_RWPARTSELECT tf_rwpartselect
#define tf_rwmemselect 14
#define TF_RWMEMSELECT tf_rwmemselect
#define tf_readonlyreal 15
#define TF_READONLYREAL tf_readonlyreal
#define tf_readwritereal 16
#define TF_READWRITEREAD tf_readwritereal
typedef struct t_tfnodeinfo {
PLI_INT16 node_type;
PLI_INT16 padding;
union {
struct t_vecval *vecval_p;
struct t_strengthval *strengthval_p;
PLI_BYTE8 *memoryval_p;
double *read_value_p;
} node_value;
char* node_symbol;
PLI_INT32 node_ngroups;
PLI_INT32 node_vec_size;
PLI_INT32 node_sign;
PLI_INT32 node_ms_index;
PLI_INT32 node_ls_index;
PLI_INT32 node_mem_size;
PLI_INT32 node_lhs_element;
PLI_INT32 node_rhs_element;
PLI_INT32*node_handle;
} s_tfnodeinfo, *p_tfnodeinfo;
/* values used in the node_type of the tfnodeinfo structure. */
#define tf_null_node 100
#define TF_NULL_NODE tf_null_node
#define tf_reg_node 101
#define TF_REG_NODE tf_reg_node
#define tf_integer_node 102
#define TF_INTEGER_NODE tf_integer_node
#define tf_time_node 103
#define TF_TIME_NODE tf_time_node
#define tf_netvector_node 104
#define TF_NETVECTOR_NODE tf_netvector_node
#define tf_netscalar_node 105
#define TF_NETSCALAR_NODE tf_netscalar_node
#define tf_memory_node 106
#define TF_MEMORY_NODE tf_memory_node
#define tf_real_node 107
#define TF_REAL_NODE tf_real_node
/* Extern functions from the library. */
extern void io_printf (const char *, ...)
@@ -114,6 +227,12 @@ extern int tf_getlongtime(int*high_bits);
extern int tf_getp(int pnum);
extern PLI_BYTE8* tf_getworkarea(void);
extern PLI_INT32 tf_message(PLI_INT32 level, char*facility,
char*messno, char*fmt, ...)
__attribute__((format (printf,4,5)));
extern int tf_nump(void);
/* IEEE1364 NOTE: tf_putlongp is listed as returning in in the header
@@ -123,6 +242,15 @@ extern void tf_putlongp(int pnum, int lowvalue, int highvalue);
extern void tf_putp(int pnum, int value);
/* IEEE1364 NOTE: tf_setworkarea is listed as taking a PLI_BYTE8*, but
that is silly, it really takes any kind of pointer. Taking void* is
compatible with those who pass a PLI_BYTE8*. */
extern PLI_INT32 tf_setworkarea(void*workarea);
extern char* tf_spname(void);
extern PLI_INT32 tf_typep(PLI_INT32 narg);
extern void tf_warning(const char*, ...)
__attribute__((format (printf,1,2)));
@@ -130,6 +258,11 @@ EXTERN_C_END
/*
* $Log: veriuser.h,v $
* Revision 1.18 2002/12/19 21:37:04 steve
* Add tf_message, tf_get/setworkarea, and
* ty_typep functions, along with defines
* related to these functions.
*
* Revision 1.17 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+3 -3
View File
@@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.31 2002/04/07 04:37:53 steve Exp $"
#ident "$Id: Makefile.in,v 1.32 2003/01/10 03:06:32 steve Exp $"
#
#
SHELL = /bin/sh
@@ -60,12 +60,12 @@ sys_random.o sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \
sys_lxt.o lxt_write.o \
mt19937int.o
SYSTEM_VPI_LDFLAGS = -L.. -lvpi
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@WIN32@,yes)
SYSTEM_VPI_LDFLAGS += -liberty
endif
system.vpi: $O ../libvpi.a
system.vpi: $O ../vvp/libvpi.a
$(CC) @shared@ -o $@ $O $(SYSTEM_VPI_LDFLAGS)
sys_readmem_lex.c: sys_readmem_lex.lex
+208 -83
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.49 2003/01/26 18:18:36 steve Exp $"
#endif
# include "config.h"
@@ -113,96 +113,158 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
}
}
static void format_time(unsigned mcd, int fsize, const char*value)
/*
* This function writes the time value into the mcd target with the
* proper format. The mcd is the destination file.
*
* The fsize is the width of the field to use. Normally, this is -1 to
* reflect the format string "%t". It may also be 0 for the format
* string "%0t". This formatter also allows for the nonstandard use of
* positive values to enforce a with to override the width given in
* the $timeformat system task.
*
* The value argument is the time value as a decimal string. There are
* no leading zeros in this string, and the units of the value are
* given in the units argument.
*/
static void format_time(unsigned mcd, int fsize,
const char*value, int time_units)
{
char buf[256];
const char*cp;
char*bp;
unsigned len;
char*bp, *start_address;
int idx, idx_point, idx_start, idx_value;
int idx;
int fraction_chars, fraction_pad, value_chop, whole_fill;
/* This is the time precision for the simulation. */
int prec = vpi_get(vpiTimePrecision, 0);
/* This is the format precision expressed as the power of 10
of the desired precision. The following code uses this
format to be consistent with the units specifications. */
int format_precision = timeformat_info.units - timeformat_info.prec;
/* If the fsize is <0, then use the value from the
$timeformat. If the fsize is >=0, then it overrides the
$timeformat value. */
if (fsize < 0)
fsize = timeformat_info.width;
/* bp starts at the end of the buffer, and works forward as we
build up the output value. */
bp = buf + sizeof buf;
assert(fsize < (sizeof buf - 1));
/* cp points to digits of the value, starting with the least
significant. If the value is only '0', then short circuit
the value by setting cp = value. */
if (value[0] != '0')
cp = value + strlen(value);
/* This is the number of characters to the right of the
decimal point. This is defined completely by the
timeformat. It is legal for the precision to be larger then
the units, and in this case there will be no fraction_chars
at all. */
fraction_chars = timeformat_info.units - format_precision;
if (fraction_chars < 0)
fraction_chars = 0;
/* This is the number of zeros I must add to the value to get
the desired precision within the fraction. If this value is
greater then 0, the value does not have enough characters,
so I will be adding zeros. */
fraction_pad = time_units - format_precision;
if (fraction_pad < 0)
fraction_pad = 0;
if (fraction_pad > fraction_chars)
fraction_pad = fraction_chars;
/* This is the number of characters of excess precision in the
supplied value. This many characters are chopped from the
least significant end. */
value_chop = format_precision - time_units;
if (value_chop < 0)
value_chop = 0;
/* This is the number of zeros that I must add to the integer
part of the output string to pad the value out to the
desired units. This will only have a non-zero value if the
units of the value is greater then the desired units.
Detect the special case where the value is 0. In this case,
do not do any integer filling ever. The output should be
padded with blanks in that case. */
whole_fill = time_units - timeformat_info.units;
if (whole_fill < 0)
whole_fill = 0;
if (strcmp(value,"0") == 0)
whole_fill = 0;
/* This is the expected start address of the output. It
accounts for the fsize value that is chosen. The output
will be filled out to complete the buffer. */
if (fsize == 0)
start_address = buf;
else
start_address = buf + sizeof buf - fsize - 1;
/* Now start the character pointers, ready to start copying
the value into the format. */
cp = value + strlen(value);
if (value_chop > (cp - value))
cp = value;
else
cp -= value_chop;
/* Draw the suffix into the buffer. */
bp = buf + sizeof buf;
*--bp = 0;
/* Write the suffix. */
bp -= strlen(timeformat_info.suff);
strcpy(bp, timeformat_info.suff);
/* This is the precision index where the decimal point goes. */
idx_point = timeformat_info.units;
/* This is the precision index where we start drawing digits. */
idx_start = idx_point - (int)timeformat_info.prec;
/* This is the precision index where the integer time value
digits start. */
idx_value = prec;
idx = idx_start;
if (idx > idx_value)
idx = idx_value;
/* If we want no precision, then set idx_point to a high value
so that the '.' is never printed. */
if (timeformat_info.prec == 0)
idx_point = idx - 1;
/* Now build up the time string, from the least significant
digit up to the last. */
while ((cp > value) || (idx <= idx_point)) {
if (idx == idx_point) {
*--bp = '.';
}
if (idx >= idx_start) {
if (idx < idx_value) {
*--bp = '0';
} else if (cp > value) {
*--bp = cp[-1];
} else {
*--bp = '0';
}
}
if ((idx >= idx_value) && (cp > value))
cp -= 1;
idx += 1;
}
/* Patch up cases that need a leading 0. */
if ((*bp == '.') || (idx == idx_start))
/* Write the padding needed to fill out the fraction. */
for (idx = 0 ; idx < fraction_pad ; idx += 1)
*--bp = '0';
/* Pad the string on the left to the requested minimum
width. Pad with spaces. */
len = strlen(bp);
while (len < fsize) {
*--bp = ' ';
len += 1;
/* Subtract the pad from the needed chars. */
assert(fraction_pad <= fraction_chars);
fraction_chars -= fraction_pad;
fraction_pad = 0;
/* Write the fraction chars. */
for (idx = 0 ; idx < fraction_chars ; idx += 1) {
if (cp > value)
*--bp = *--cp;
else
*--bp = '0';
assert(cp >= value);
}
/* Write the decimal point, if needed. */
if (timeformat_info.prec > 0)
*--bp = '.';
/* Fill the gap between the value and the decimal point. */
for (idx = 0 ; idx < whole_fill ; idx += 1)
*--bp = '0';
/* Write the integer part of the value. */
while (cp > value) {
*--bp = *--cp;
}
/* Fill the leading characters to make up the desired
width. This may require a '0' if the last character
written was the decimal point. */
if (fsize > 0) {
while (bp > start_address) {
if (*bp == '.')
*--bp = '0';
else
*--bp = ' ';
}
} else {
if (*bp == '.')
*--bp = '0';
}
vpi_mcd_printf(mcd, "%s", bp);
}
@@ -305,6 +367,8 @@ static int format_str(vpiHandle scope, unsigned int mcd,
char*cp = fmt;
char format_char = ' ';
int idx;
/* Time units of the current scope. */
int time_units = vpi_get(vpiTimeUnit, scope);
assert(fmt);
@@ -361,6 +425,14 @@ static int format_str(vpiHandle scope, unsigned int mcd,
cp += 1;
break;
case 'f':
case 'F':
format_char = 'f';
do_arg = 1;
value.format = vpiRealVal;
cp += 1;
break;
case 'h':
case 'H':
case 'x':
@@ -458,7 +530,6 @@ static int format_str(vpiHandle scope, unsigned int mcd,
break;
case 'e':
case 'f':
case 'g':
// new Verilog 2001 format specifiers...
case 'l':
@@ -495,11 +566,17 @@ static int format_str(vpiHandle scope, unsigned int mcd,
switch(format_char){
case 'c':
vpi_mcd_printf(mcd, "%c", value.value.str[strlen(value.value.str)-1]);
break;
vpi_mcd_printf(mcd, "%c", value.value.str[strlen(value.value.str)-1]);
break;
case 'f':
vpi_mcd_printf(mcd, "%f",
value.value.real);
break;
case 't':
format_time(mcd, fsize, value.value.str);
format_time(mcd, fsize,
value.value.str, time_units);
break;
case 'd':
@@ -609,6 +686,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;
@@ -674,6 +774,12 @@ static void do_display(unsigned int mcd, struct strobe_cb_info*info)
vpi_mcd_printf(mcd, "%20u", value.value.time->low);
break;
case vpiRealVar:
value.format = vpiRealVal;
vpi_get_value(item, &value);
vpi_mcd_printf(mcd, "%f", value.value.real);
break;
default:
vpi_mcd_printf(mcd, "?");
break;
@@ -702,19 +808,24 @@ static int get_default_format(char *name)
static int sys_display_calltf(char *name)
{
struct strobe_cb_info info;
struct strobe_cb_info*info;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle scope = vpi_handle(vpiScope, sys);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
info = vpi_get_userdata(sys);
if (info == 0) {
vpiHandle scope = vpi_handle(vpiScope, sys);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
assert(scope);
info.default_format = get_default_format(name);
info.scope = scope;
array_from_iterator(&info, argv);
assert(scope);
info = malloc(sizeof (struct strobe_cb_info));
info->default_format = get_default_format(name);
info->scope = scope;
array_from_iterator(info, argv);
do_display(5, &info);
free(info.items);
vpi_put_userdata(sys, info);
}
do_display(5, info);
if (strncmp(name,"$display",8) == 0)
vpi_mcd_printf(5, "\n");
@@ -1206,6 +1317,8 @@ static int sys_timeformat_calltf(char *xx)
static int sys_end_of_compile(p_cb_data cb_data)
{
/* The default timeformat prints times in unit of simulation
precision. */
timeformat_info.suff = strdup("");
timeformat_info.units = vpi_get(vpiTimePrecision, 0);
timeformat_info.prec = 0;
@@ -1461,6 +1574,18 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.49 2003/01/26 18:18:36 steve
* Support display of real values and constants.
*
* Revision 1.48 2003/01/09 04:10:58 steve
* use userdata to save $display argument handles.
*
* Revision 1.47 2002/12/21 19:41:49 steve
* Rewrite time formatting to account for local scope.
*
* Revision 1.46 2002/11/09 06:01:11 steve
* display octal escapes properly.
*
* 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
+17 -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.13 2002/12/21 00:55:58 steve Exp $"
#endif
# include "config.h"
@@ -343,6 +343,7 @@ static int sys_dumpoff_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
lt_set_time(dump_file, now.low);
@@ -368,6 +369,7 @@ static int sys_dumpon_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
lt_set_time(dump_file, now.low);
@@ -388,6 +390,7 @@ static int sys_dumpall_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
lt_set_time(dump_file, now.low);
@@ -460,6 +463,9 @@ static int sys_dumpfile_calltf(char*name)
path = strdup("dumpfile.lxt");
}
if (dump_file)
close_dumpfile();
assert(dump_file == 0);
open_dumpfile(path);
@@ -814,6 +820,16 @@ void sys_lxt_register()
/*
* $Log: sys_lxt.c,v $
* Revision 1.13 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.12 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
* Revision 1.11 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
+107 -1
View File
@@ -17,14 +17,25 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_time.c,v 1.4 2002/08/12 01:35:05 steve Exp $"
#ident "$Id: sys_time.c,v 1.6 2003/01/27 00:14:37 steve Exp $"
#endif
# include "config.h"
# include "vpi_user.h"
# include <string.h>
# include <assert.h>
static vpiHandle module_of_function(vpiHandle obj)
{
while (vpi_get(vpiType, obj) != vpiModule) {
obj = vpi_handle(vpiScope, obj);
assert(obj);
}
return obj;
}
static int sys_time_sizetf(char*x)
{
return 64;
@@ -40,16 +51,82 @@ static int sys_time_calltf(char*name)
s_vpi_value val;
s_vpi_time now;
vpiHandle call_handle;
vpiHandle mod;
int units, prec;
long scale;
call_handle = vpi_handle(vpiSysTfCall, 0);
assert(call_handle);
mod = module_of_function(call_handle);
now.type = vpiSimTime;
vpi_get_time(0, &now);
/* All the variants but $simtime return the time in units of
the local scope. The $simtime function returns the
simulation time. */
if (strcmp(name, "$simtime") == 0)
units = vpi_get(vpiTimePrecision, 0);
else
units = vpi_get(vpiTimeUnit, mod);
prec = vpi_get(vpiTimePrecision, 0);
scale = 1;
while (units > prec) {
scale *= 10;
units -= 1;
}
val.format = vpiIntVal;
val.value.integer = now.low;
assert(now.high == 0);
val.value.integer /= scale;
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
return 0;
}
static int sys_realtime_calltf(char*name)
{
s_vpi_value val;
s_vpi_time now;
vpiHandle call_handle;
vpiHandle mod;
int units, prec;
double scale;
call_handle = vpi_handle(vpiSysTfCall, 0);
assert(call_handle);
mod = module_of_function(call_handle);
now.type = vpiSimTime;
vpi_get_time(0, &now);
/* All the variants but $simtime return the time in units of
the local scope. The $simtime function returns the
simulation time. */
if (strcmp(name, "$simtime") == 0)
units = vpi_get(vpiTimePrecision, 0);
else
units = vpi_get(vpiTimeUnit, mod);
prec = vpi_get(vpiTimePrecision, 0);
scale = 1;
while (units > prec) {
scale *= 10;
units -= 1;
}
val.format = vpiRealVal;
val.value.real = now.low;
assert(now.high == 0);
val.value.real /= scale;
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
return 0;
@@ -64,6 +141,15 @@ void sys_time_register()
tf_data.calltf = sys_time_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_time_sizetf;
tf_data.user_data = "$time";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
tf_data.tfname = "$realtime";
tf_data.calltf = sys_realtime_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
tf_data.user_data = "$realtime";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
@@ -71,11 +157,31 @@ void sys_time_register()
tf_data.calltf = sys_time_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_stime_sizetf;
tf_data.user_data = "$stime";
vpi_register_systf(&tf_data);
tf_data.type = vpiSysFunc;
tf_data.tfname = "$simtime";
tf_data.calltf = sys_time_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = sys_time_sizetf;
tf_data.user_data = "$simtime";
vpi_register_systf(&tf_data);
}
/*
* $Log: sys_time.c,v $
* Revision 1.6 2003/01/27 00:14:37 steve
* Support in various contexts the $realtime
* system task.
*
* Revision 1.5 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.4 2002/08/12 01:35:05 steve
* conditional ident string using autoconfig.
*
+23 -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.40 2002/12/21 00:55:58 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 ++;
@@ -315,6 +315,7 @@ static int sys_dumpoff_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
@@ -342,6 +343,7 @@ static int sys_dumpon_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
@@ -364,6 +366,7 @@ static int sys_dumpall_calltf(char*name)
if (dump_header_pending())
return 0;
now.type = vpiSimTime;
vpi_get_time(0, &now);
if (now.low > vcd_cur_time)
fprintf(dump_file, "#%u\n", now.low);
@@ -449,6 +452,11 @@ static int sys_dumpfile_calltf(char*name)
path = strdup("dumpfile.vcd");
}
if (dump_file) {
fclose(dump_file);
dump_file = 0;
}
assert(dump_file == 0);
open_dumpfile(path);
@@ -844,6 +852,19 @@ void sys_vcd_register()
/*
* $Log: sys_vcd.c,v $
* Revision 1.40 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*
* Revision 1.39 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
* Revision 1.38 2002/11/14 22:43:58 steve
* Save vpiFullName results.
*
* Revision 1.37 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
+16 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_user.h,v 1.15 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: vpi_user.h,v 1.17 2003/01/26 21:15:59 steve Exp $"
#endif
@@ -161,6 +161,7 @@ typedef struct t_vpi_value {
#define vpiNamedEvent 34
#define vpiNamedFork 35
#define vpiNet 36
#define vpiRealVar 47
#define vpiReg 48
#define vpiSysFuncCall 56
#define vpiSysTaskCall 57
@@ -323,6 +324,13 @@ extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
extern int vpi_free_object(vpiHandle ref);
extern int vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p);
/*
* These functions support attaching user data to an instance of a
* system task or function. These functions only apply to
* vpiSysTaskCall or vpiSysFuncCall handles.
*/
extern int vpi_put_userdata(vpiHandle obj, void*data);
extern void*vpi_get_userdata(vpiHandle obj);
/*
* Support for handling errors.
@@ -359,6 +367,13 @@ EXTERN_C_END
/*
* $Log: vpi_user.h,v $
* Revision 1.17 2003/01/26 21:15:59 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.16 2003/01/09 04:10:17 steve
* Add vpi_put_userdata
*
* Revision 1.15 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
-241
View File
@@ -1,241 +0,0 @@
/*
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.c,v 1.6 2002/08/12 01:35:01 steve Exp $"
#endif
#include <stdio.h>
#include <stdarg.h>
#include "vpi_user.h"
#include "vpithunk.h"
/*
* This code is linked into the VPI module, not the simulator. The
* module uses the symbols defined in here to call implementations
* supplied by the simulator, which loaded this module with dlopen or
* the equivilent.
*
* The vpi_thunk_p pointer points to a table of function pointers that
* point to all the functions that a simulator is expected to provide.
* The vlog_register_sim is a function that the simulator is expected
* to call with a value for the vpi_thunk_p pointer. This is how the
* run time linkage to all the functions in the make program are made.
*
* In Icarus Verilog, the VPI module is also supposed to export a
* vlog_startup_routines table. This is something that the programmer
* does, so the libvpi library, and the vlog_register_sim function,
* are invisible to the user.
*
* The simulator is careful to call the vpi_register_sim function from
* a loaded module before executing the startup routines.
*/
static p_vpi_thunk vpi_thunk_p = 0;
#define VPITV_CALL(fn,args) { \
if (vpi_thunk_p == 0) { \
no_sim(#fn); return; \
} \
if (vpi_thunk_p->fn == 0) { \
no_func(#fn); return; \
} \
vpi_thunk_p->fn args; \
}
#define VPIT_CALL(fn,def,args) { \
if (vpi_thunk_p == 0) { \
no_sim(#fn); return def; \
} \
if (vpi_thunk_p->fn == 0) { \
no_func(#fn); return def; \
} \
return vpi_thunk_p->fn args; \
}
static void no_sim(const char *fn)
{
fprintf(stderr, "No Simulator registered, cannot handle vpi "
"call to %s\n", fn);
}
static void no_func(const char *fn)
{
fprintf(stderr, "Simulator doesn't have a %s function\n",fn);
}
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp)
{
vpi_thunk_p = 0;
if (tp->magic != VPI_THUNK_MAGIC) {
fprintf(stderr, "Thunk Magic Number mismatch. Got %08X, expected %08x\n",
tp->magic, VPI_THUNK_MAGIC);
return 0;
}
vpi_thunk_p = tp;
return 1;
}
void vpi_register_systf(const struct t_vpi_systf_data *ss)
{
VPITV_CALL(vpi_register_systf,(ss));
}
void vpi_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
VPITV_CALL(vpi_vprintf,(fmt,ap));
va_end(ap);
}
unsigned int vpi_mcd_close(unsigned int mcd)
{
VPIT_CALL(vpi_mcd_close,-1,(mcd));
}
char *vpi_mcd_name(unsigned int mcd)
{
VPIT_CALL(vpi_mcd_name,0,(mcd));
}
unsigned int vpi_mcd_open(char *name)
{
VPIT_CALL(vpi_mcd_open,-1,(name));
}
unsigned int vpi_mcd_open_x(char *name, char *mode)
{
VPIT_CALL(vpi_mcd_open_x,-1, (name, mode));
}
int vpi_mcd_printf(unsigned int mcd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
VPIT_CALL(vpi_mcd_vprintf,0,(mcd,fmt,ap));
va_end(ap); /* bad - never hit */
}
int vpi_mcd_fputc(unsigned int mcd, unsigned char x)
{
VPIT_CALL(vpi_mcd_fputc, 0, (mcd, x));
}
int vpi_mcd_fgetc(unsigned int mcd)
{
VPIT_CALL(vpi_mcd_fgetc, -1, (mcd));
}
extern vpiHandle vpi_register_cb(p_cb_data data)
{
VPIT_CALL(vpi_register_cb,0,(data));
}
extern int vpi_remove_cb(vpiHandle ref)
{
VPIT_CALL(vpi_remove_cb,0,(ref));
}
extern void vpi_sim_control(int operation, ...)
{
va_list ap;
va_start(ap, operation);
VPITV_CALL(vpi_sim_vcontrol,(operation,ap));
va_end(ap); /* bad - never hit */
}
extern void vpi_control(int operation, ...)
{
va_list ap;
va_start(ap, operation);
VPITV_CALL(vpi_sim_vcontrol,(operation,ap));
va_end(ap); /* bad - never hit */
}
extern vpiHandle vpi_handle(int type, vpiHandle ref)
{
VPIT_CALL(vpi_handle, 0, (type, ref));
}
extern vpiHandle vpi_iterate(int type, vpiHandle ref)
{
VPIT_CALL(vpi_iterate, 0, (type, ref));
}
extern vpiHandle vpi_scan(vpiHandle iter)
{
VPIT_CALL(vpi_scan, 0, (iter));
}
extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index)
{
VPIT_CALL(vpi_handle_by_index,0,(ref, index));
}
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t)
{
VPITV_CALL(vpi_get_time, (obj,t));
}
extern int vpi_get(int property, vpiHandle ref)
{
VPIT_CALL(vpi_get, 0, (property, ref));
}
extern char* vpi_get_str(int property, vpiHandle ref)
{
VPIT_CALL(vpi_get_str, 0, (property,ref));
}
extern void vpi_get_value(vpiHandle expr, p_vpi_value value)
{
VPITV_CALL(vpi_get_value, (expr, value));
}
extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
p_vpi_time when, int flags)
{
VPIT_CALL(vpi_put_value, 0, (obj, value, when, flags));
}
extern int vpi_free_object(vpiHandle ref)
{
VPIT_CALL(vpi_free_object, -1, (ref));
}
extern int vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
{
VPIT_CALL(vpi_get_vlog_info, 0, (vlog_info_p));
}
extern int vpi_chk_error(p_vpi_error_info info)
{
VPIT_CALL(vpi_chk_error, 0, (info));
}
/*
* $Log: vpithunk.c,v $
* Revision 1.6 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.5 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/
-84
View File
@@ -1,84 +0,0 @@
#ifndef _VPI_THUNK_H_
#define _VPI_THUNK_H_ 1
/*
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
#endif
/* These functions are actually defined in lieu of the vpi functions
by the simulator. These prototypes should'nt go into vpi_user.h,
because we don't want the users to be seeing this stuff. They
are non-standard. We have to put them here, so that
including vpi_user.h doesn't require including stdarg.h */
EXTERN_C_START
# include <stdarg.h>
extern void vpi_vprintf(const char*fmt, va_list ap);
extern int vpi_mcd_vprintf(unsigned int mcd, const char*fmt, va_list ap);
extern void vpi_sim_vcontrol(int operation, va_list ap);
EXTERN_C_END
#define VPI_THUNK_MAGIC (0x87836BA4)
typedef struct {
int magic;
void (*vpi_register_systf)(const struct t_vpi_systf_data*ss);
void (*vpi_vprintf)(const char*fmt, va_list ap);
unsigned int (*vpi_mcd_close)(unsigned int mcd);
char *(*vpi_mcd_name)(unsigned int mcd);
unsigned int (*vpi_mcd_open)(char *name);
unsigned int (*vpi_mcd_open_x)(char *name, char *mode);
int (*vpi_mcd_vprintf)(unsigned int mcd, const char*fmt, va_list ap);
int (*vpi_mcd_fputc)(unsigned int mcd, unsigned char x);
int (*vpi_mcd_fgetc)(unsigned int mcd);
vpiHandle (*vpi_register_cb)(p_cb_data data);
int (*vpi_remove_cb)(vpiHandle ref);
void (*vpi_sim_vcontrol)(int operation, va_list ap);
vpiHandle (*vpi_handle)(int type, vpiHandle ref);
vpiHandle (*vpi_iterate)(int type, vpiHandle ref);
vpiHandle (*vpi_scan)(vpiHandle iter);
vpiHandle (*vpi_handle_by_index)(vpiHandle ref, int index);
void (*vpi_get_time)(vpiHandle obj, s_vpi_time*t);
int (*vpi_get)(int property, vpiHandle ref);
char* (*vpi_get_str)(int property, vpiHandle ref);
void (*vpi_get_value)(vpiHandle expr, p_vpi_value value);
vpiHandle (*vpi_put_value)(vpiHandle obj, p_vpi_value value,
p_vpi_time when, int flags);
int (*vpi_free_object)(vpiHandle ref);
int (*vpi_get_vlog_info)(p_vpi_vlog_info vlog_info_p);
int (*vpi_chk_error)(p_vpi_error_info info);
} vpi_thunk, *p_vpi_thunk;
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
#endif
/*
* $Log: vpithunk.h,v $
* Revision 1.4 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
* Revision 1.3 2002/08/11 23:47:04 steve
* Add missing Log and Ident strings.
*
*/

Some files were not shown because too many files have changed in this diff Show More