Compare commits

...
143 Commits
Author SHA1 Message Date
steve 2e279b61dd Update to 0.7 release. 2002-12-14 18:20:14 +00:00
steve 8ab909a765 Add vpi_handle_by_name to the VPI interface,
and bump the vpithunk magic number.
2002-12-11 23:55:22 +00:00
steve cca07fa42d Account for bison 1.35 and stack manipulations. 2002-12-10 05:49:51 +00:00
steve 5b81798205 install iverilog-vpi as a script. 2002-12-10 05:45:44 +00:00
steve a8a82df47d Prepare for 20021207 snapshot 2002-12-08 03:06:30 +00:00
steve e62e1d89b6 Named event triggers can take hierarchical names. 2002-12-07 02:49:24 +00:00
steve c032186133 Reword some error messages for clarity. 2002-12-06 03:08:19 +00:00
steve b89e138404 precalculate r-values of nb assignments and task arguments. 2002-12-05 04:15:14 +00:00
steve 9f80ed32b6 Support bit select in constant expressions. 2002-12-05 02:14:33 +00:00
steve c16a4a3950 distclean target. 2002-12-04 03:33:38 +00:00
steve 90fa90a508 Mingw32 compatible temp file management. 2002-12-04 03:26:59 +00:00
steve aaa734690f Use O_EXCL when opening temp files. 2002-12-04 02:29:36 +00:00
steve 88da7804c4 Improve the bad character error message. 2002-12-04 02:07:00 +00:00
steve 8604f922a5 specify delay can take an unbracketed simple value. 2002-11-26 03:56:10 +00:00
steve 807a758f7c Do not set width if width is already OK. 2002-11-26 03:35:13 +00:00
steve ef55086543 Support put of vpiStringVal to signals. 2002-11-25 23:33:45 +00:00
steve 2001903c89 Cygwin doesnot need driver-vpi sibdirectory. 2002-11-24 02:27:28 +00:00
steve 751e4e4c79 Fix instanceRef spelling. 2002-11-24 02:26:14 +00:00
steve 9d91b5db4c Document the Windows specific flags. 2002-11-23 00:51:53 +00:00
steve 9a3c9507ed Handle wide AND/NOR devices with Virtex carry logic. 2002-11-22 05:46:06 +00:00
steve d71d52bfe9 Implement bufif1 as BUFT 2002-11-22 01:45:40 +00:00
steve 8e30bc9f9e Careful of left operands to shift that are constant. 2002-11-22 00:01:50 +00:00
steve 412518d1ca Precalculate indices to l-value arrays. 2002-11-21 23:27:51 +00:00
steve 03afbf157b %set/x0 instruction to support bounds checking. 2002-11-21 22:43:13 +00:00
steve 00b2d467e4 Allow right values of right shift to shift in. 2002-11-21 22:42:48 +00:00
steve 856829d299 Fix const test of msb in assignment l-values. 2002-11-21 18:15:40 +00:00
steve 2fafe6866f Better handling of select width of shifters. 2002-11-21 18:08:09 +00:00
steve b9188ad0ca PATHPULSE specparam assignment syntax. 2002-11-21 17:40:11 +00:00
steve 0ccb9139c9 Magnitude compare to 0. 2002-11-17 23:37:55 +00:00
steve 18e402ddc8 Close old file if $dumpfile is called again. 2002-11-17 22:28:42 +00:00
steve b82d3165da Update version strings in spec flie. 2002-11-17 18:38:03 +00:00
steve 91580d1fcc Generate unique labels for force functors. 2002-11-17 18:31:09 +00:00
steve 35d7384903 Handle default: case in net_inputs for NetCase. 2002-11-16 05:45:41 +00:00
steve 4539632f34 Add vpiScope iterate on vpiScope objects. 2002-11-15 22:14:12 +00:00
steve 0651f246b2 Save vpiFullName results. 2002-11-14 22:43:58 +00:00
steve 6d0dee9341 Add version resources to the Windows binary. 2002-11-13 17:25:10 +00:00
steve c692f1708c Allow -mingw and -ivl flags to stand alone. 2002-11-13 17:03:49 +00:00
steve d91733d32c Spell the iverilog-vpi target correctly. 2002-11-13 16:57:25 +00:00
steve cd7378ff3f Do not truncate high bits of right shift. 2002-11-13 03:03:08 +00:00
steve c98ce4a029 Add Windows version of iverilog-vpi. 2002-11-13 01:50:11 +00:00
steve d035a7e92c spelling error. 2002-11-13 01:49:43 +00:00
steve 6db6359363 Update Solaris packaging to to realities. 2002-11-11 15:49:03 +00:00
steve 5c07a29e46 Install sqrt-virtex.v under Windows. 2002-11-11 01:12:41 +00:00
steve 42d9094e9b Snapshot 20021109 2002-11-09 23:41:15 +00:00
steve 1742231eba Handle nested-if chip enables. 2002-11-09 23:29:29 +00:00
steve 3178f886b7 XNF target uses only legacy functors. 2002-11-09 23:29:02 +00:00
steve cbc4a0ab52 Detect synthesis conflicts blocks statements share outputs. 2002-11-09 20:22:57 +00:00
steve cfd8cbf850 Port expressions for output ports are lnets, not nets. 2002-11-09 19:20:48 +00:00
steve 013b18b3dc leading underscore test for Windows more robust. 2002-11-09 06:03:57 +00:00
steve db9f20b21a Macos install notes. 2002-11-09 06:03:38 +00:00
steve f611260089 display octal escapes properly. 2002-11-09 06:01:11 +00:00
steve e34e3a4875 spelling in a comment. 2002-11-09 02:22:07 +00:00
steve aa8869a3c7 Postpone parameter width check to evaluation. 2002-11-09 01:40:19 +00:00
steve 588931fcf2 Add dup_expr for user defined function calls. 2002-11-09 00:25:27 +00:00
steve 07e49e215e Use the vectorized %assign where appropriate. 2002-11-08 05:00:31 +00:00
steve 1b84893ccb Add the %assign/v0 instruction. 2002-11-08 04:59:57 +00:00
steve 6445bb6915 Handle comments in suppressed code. 2002-11-08 00:04:16 +00:00
steve db899bd1b5 Use Vector %set to set constants in variables. 2002-11-07 05:19:55 +00:00
steve c6dcc38fe0 Vectorize load from REG variables. 2002-11-07 03:12:17 +00:00
steve b0a7909162 functor_set takes bit and strength, not 2 strengths. 2002-11-07 03:11:43 +00:00
steve d7ae85a13a Add vector set and load instructions. 2002-11-07 02:32:39 +00:00
steve 46ee38b466 Concatenation can evaluate sub-expressions in place. 2002-11-06 05:41:37 +00:00
steve bc6a958a50 More reliable iverilog.conf install dependency. 2002-11-06 03:42:40 +00:00
steve 0e751ad975 More forgiving about assignment rval width mismatch. 2002-11-06 03:22:28 +00:00
steve de94d09706 No need to keep excess width from an
unsigned constant value, if it can
 be trimmed safely.
2002-11-06 02:25:13 +00:00
steve 2f88a631df Run output with the vvp command. 2002-11-05 03:49:21 +00:00
steve 4e5dd49a37 Fix mask calculate when MOV_b is right on the word boundary. 2002-11-05 03:46:44 +00:00
steve 8463dcc878 ignore parse.output 2002-11-05 02:19:37 +00:00
steve 18bc2f65b3 Misspelled name. 2002-11-05 02:18:53 +00:00
steve b4e8ea5a0c Install shared objects as programs, not data. 2002-11-05 02:14:41 +00:00
steve 06a8087cb5 Do not need _leading underscore on Windows. 2002-11-05 02:14:16 +00:00
steve a9dfef0f55 Fix the call to FormatMessage under Windows. 2002-11-05 02:12:35 +00:00
steve e4540c3d0d Better error message for load failure on Windows. 2002-11-05 02:11:56 +00:00
steve 0cc8396244 Cast for gcc convenience. 2002-11-03 22:44:19 +00:00
steve 946693ad4d New output files from new bison. 2002-11-03 20:50:33 +00:00
steve f014d4c533 Update instructions, now that Cygwin handles X:/path strings. 2002-11-03 20:49:57 +00:00
steve 6a1e3f7e27 Slightly more verbose load fail message. 2002-11-03 20:47:23 +00:00
steve 7ad66b0725 Support old/new bison yylloc. 2002-11-03 20:36:53 +00:00
steve 0341c0c727 Error message for mising code generator type. 2002-11-03 20:36:10 +00:00
steve 20c8550139 Compiler error wrt ptrdiff_t. 2002-11-03 20:33:43 +00:00
steve 39aa90ce59 Snapshot 20021102 2002-11-03 02:12:00 +00:00
steve 6c67a64fc3 Get VectorVals from constant values. 2002-11-03 02:07:24 +00:00
steve 86032c0aa5 Allow named events to be referenced by
hierarchical names.
2002-11-02 03:27:51 +00:00
steve f243f694b4 Detect memories without work index in l-value. 2002-11-02 01:10:49 +00:00
steve 276ae3e228 Add the sqrt-virtex example. 2002-11-01 03:29:43 +00:00
steve fe6756eb07 Fix bottom bit of ADD/SUB device. 2002-11-01 02:36:34 +00:00
steve 539e494bc0 Give nets better names, if available. 2002-11-01 02:36:22 +00:00
steve 1298656c22 Fix up left shift to pass compile,
fix up ADD/SUB to generate missing pieces,
 Add the asynch set/reset to DFF devices.
2002-10-30 03:58:45 +00:00
steve c66d319d9c UPdate to 20021027 snapshot. 2002-10-28 02:26:41 +00:00
steve ae27165ffe Add Virtex code generators for left shift,
subtraction, and GE comparators.
2002-10-28 02:05:56 +00:00
steve 32f1ca6f8b draw lpm ff with aset_expr taken into account. 2002-10-23 04:39:35 +00:00
steve 9ce2806710 Fix synth2 handling of aset/aclr signals where
flip-flops are split by begin-end blocks.
2002-10-23 01:45:24 +00:00
steve 3d4593d4d5 Synthesizer support for synchronous begin-end blocks. 2002-10-21 01:42:08 +00:00
steve df5ae54ec7 Handle conditional error cases better. 2002-10-20 19:19:37 +00:00
steve fbee1b424d Properly set or clear expression lookaside for binary expressions. 2002-10-20 02:55:37 +00:00
steve 555017b525 Snapshot 20021019 2002-10-19 23:38:49 +00:00
steve 1e170ee005 bourne shell compatibility. 2002-10-19 23:18:52 +00:00
steve 43501809b1 Redo the parameter vector support to allow
parameter names in range expressions.
2002-10-19 22:59:49 +00:00
steve c0c67a101a Fix spelling of the scalared keyword. 2002-10-13 05:01:44 +00:00
steve 1eb714e097 More verbose eval_const assert message. 2002-10-13 05:01:07 +00:00
steve 54a8e12856 Fix symbol underscore needs for Mac OS X. 2002-10-03 18:03:35 +00:00
steve 6203f05ef9 Add pal target enable help message. 2002-10-03 17:57:54 +00:00
steve 703ad04067 Allow expression lookaside map to spam statements. 2002-09-27 20:24:42 +00:00
steve 778e96330d Add thread expression lookaside map. 2002-09-27 16:33:34 +00:00
steve e3eb89fb12 Remove excess debug messages. 2002-09-26 03:42:10 +00:00
steve 166621bcb3 Generate vvp code for asynch set/reset of NetFF. 2002-09-26 03:18:04 +00:00
steve 879a5a4cbe Synthesize async set/reset is certain cases. 2002-09-26 01:13:14 +00:00
steve 9faabfe995 Fix missing endifs within supressed ifdefs. 2002-09-25 02:23:08 +00:00
steve 6f23fa61ac Allow results in register bits 47 in certain cases. 2002-09-24 04:20:32 +00:00
steve 30b6cf7821 Include user specified libraries on the link line. 2002-09-24 01:50:53 +00:00
steve 6258011210 More detailed check of process edge events. 2002-09-24 00:58:35 +00:00
steve 7557a46382 Remove some now useless asserts. 2002-09-21 23:47:30 +00:00
steve a0a91f358c Snapshot 20020921 2002-09-21 21:29:09 +00:00
steve 0128286966 Allow constant bit selects out of range. 2002-09-21 21:28:18 +00:00
steve acd5e86e04 Fix disable in arbitrary fork/join situations. 2002-09-21 04:55:00 +00:00
steve ab94b0a636 disable threads with children. 2002-09-20 03:59:34 +00:00
steve de6d696667 Add support for cbAfterDelay. 2002-09-20 02:42:11 +00:00
steve 63946c4cfb More careful cd command. 2002-09-20 02:41:36 +00:00
steve 475b603d15 Relax position constrations of ifdef and friends. 2002-09-19 20:33:27 +00:00
steve 096956cda9 Fix multiple source on the command line. 2002-09-18 23:25:18 +00:00
steve 3d3116d48b Add support for binary NOR operator. 2002-09-18 04:29:55 +00:00
steve 616360d751 Spelling errors. 2002-09-18 04:08:45 +00:00
steve 7a5c30d297 printf size warning. 2002-09-18 03:34:07 +00:00
steve 9c5ab36a8b Fix switch case warnings. 2002-09-18 03:33:10 +00:00
steve 466656b167 Allow forward references of memories. 2002-09-18 02:55:18 +00:00
steve 5d6567cb02 Generate vvp code for structural flip-flops. 2002-09-17 05:37:45 +00:00
steve c44c123ef5 Connect output of block to net_out, instead of statement outputs. 2002-09-17 04:40:28 +00:00
steve 4ecbf56e2b Account for part select in l-value. 2002-09-17 04:39:20 +00:00
steve ed9a2c4b3f Proper initialization of the memories table. 2002-09-17 00:42:22 +00:00
steve 90751b9250 Reject multiple probes on synchronous logic. 2002-09-16 21:55:06 +00:00
steve 7d8011669d snapshot 20020915 2002-09-16 03:48:56 +00:00
steve eb81062d85 Add to synth2 support for synthesis of
synchronous logic. This includes DFF enables
 modeled by if/then/else.
2002-09-16 00:30:33 +00:00
steve 8fbacc966e compile error. 2002-09-16 00:28:51 +00:00
steve 75801a12e3 Display FF enables. 2002-09-16 00:28:25 +00:00
steve 9f1ce170e6 Generate code for 8:1 muxes msing F5 and F6 muxes. 2002-09-15 21:52:19 +00:00
steve 327c8826f4 Generate Virtex code for 4:1 mux slices. 2002-09-14 05:19:19 +00:00
steve fb0383d2bd single bit optimization for != in expressions,
and expand ++ and != results if needed.
2002-09-13 04:09:51 +00:00
steve 28725d0d74 Optimize ==1 when in context where x vs z doesnt matter. 2002-09-13 03:12:50 +00:00
steve dac99b9374 Add support for binary nand operator. 2002-09-12 15:49:43 +00:00
steve 1573477caf Account for buffer overrun in memory word names. 2002-09-12 15:13:07 +00:00
steve 70a7513781 Support $ in preprocessor identifiers. 2002-09-11 19:42:37 +00:00
steve 0277035496 Fix wrecked rbuf in vpi_get_str of signals and memories. 2002-09-11 16:06:57 +00:00
steve 33f462fdf6 Actually set strength pointer when getting strength val. 2002-09-10 02:27:11 +00:00
98 changed files with 5808 additions and 1140 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.
*
+17 -6
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.133 2002/08/12 00:27:10 steve Exp $"
#ident "$Id: Makefile.in,v 1.140 2002/12/10 05:45:44 steve Exp $"
#
#
SHELL = /bin/sh
@@ -25,7 +25,7 @@ SHELL = /bin/sh
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well.
VERSION = 0.6
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -83,6 +83,10 @@ all: dosify.exe
dosify.exe: dosify.c
$(CC) -o dosify.exe dosify.c
ifeq (@MINGW32@,yes)
SUBDIRS += driver-vpi
endif
else
all: iverilog-vpi
endif
@@ -126,7 +130,7 @@ 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 \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.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 \
PExpr.o PGate.o \
@@ -216,7 +220,7 @@ INSTALL_DOCDIR = $(mandir)/man1
endif
ifeq (@WIN32@,yes)
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
else
WIN32_INSTALL = $(bindir)/iverilog-vpi
endif
@@ -229,7 +233,7 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
$(bindir)/iverilog-vpi: ./iverilog-vpi
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
$(libdir)/libvpi.a : ./libvpi.a
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
@@ -238,7 +242,10 @@ $(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
$(libdir)/ivl/iverilog.conf: $(srcdir)/iverilog.conf
# Install iverilog.conf whenever ivl.exe is installed. This
# forces iverilog.conf to be treated similarly, in spite of
# dates in the source bundle.
$(libdir)/ivl/iverilog.conf: $(libdir)/ivl/ivl@EXEEXT@
$(INSTALL_DATA) $(srcdir)/iverilog.conf $(libdir)/ivl/iverilog.conf
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
@@ -270,6 +277,10 @@ $(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
mv tmp.vl $(prefix)/sqrt.vl
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
mv tmp.vl $(prefix)/sqrt-virtex.v
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
mv tmp.txt $(prefix)/QUICK_START.txt
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.cc,v 1.31 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: PExpr.cc,v 1.32 2002/11/09 19:20:48 steve Exp $"
#endif
# include "config.h"
@@ -46,7 +46,7 @@ bool PExpr::is_constant(Module*) const
return false;
}
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
{
cerr << get_line() << ": error: expression not valid in assign l-value: "
<< *this << endl;
@@ -256,6 +256,9 @@ bool PEUnary::is_constant(Module*m) const
/*
* $Log: PExpr.cc,v $
* Revision 1.32 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.31 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
+10 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.62 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: PExpr.h,v 1.63 2002/11/09 19:20:48 steve Exp $"
#endif
# include <string>
@@ -80,7 +80,8 @@ class PExpr : public LineInfo {
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method.
@@ -126,7 +127,8 @@ class PEConcat : public PExpr {
// continuous assignments.
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
unsigned long rise,
@@ -216,7 +218,8 @@ class PEIdent : public PExpr {
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
// Identifiers are also allowed as procedural assignment l-values.
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
@@ -501,6 +504,9 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
* Revision 1.63 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.62 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+11
View File
@@ -396,6 +396,17 @@ language that are defined.
Icarus Verilog will override the $timeformat minimum width and
use the explicit minimum width.
vpiScope iterator on vpiScope objects.
In the VPI, the normal way to iterate over vpiScope objects
contained within a vpiScope object, is the vpiInternalScope
iterator. Icarus Verilog adds support for the vpiScope
iterator of a vpiScope object, that iterates over *everything*
the is contained in the current scope. This is useful in cases
where one wants to iterate over all the objects in a scope
without iterating over all the contained types explicitly.
6.0 CREDITS
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
+1 -1
View File
@@ -12,7 +12,7 @@ autoconf
for dir in vpip vvp tgt-vvp tgt-fpga libveriuser
do
echo "Autoconf in $dir..."
( cd $dir ; autoconf )
( cd ./$dir ; autoconf )
done
echo "Precompiling lexor_keyword.gperf"
+62 -62
View File
@@ -46,7 +46,8 @@ do_times=no
AC_MSG_RESULT($do_times)
AC_CHECK_HEADER(ipal.h, HAVE_IPAL=yes, HAVE_IPAL=)
AC_ARG_WITH(ipal,enable PAL target,
AC_ARG_WITH(ipal,
[ --with-ipal enable PAL target],
if test "$with_ipal" = no; then
echo Disabling ipal support
HAVE_IPAL=
@@ -74,66 +75,6 @@ AC_LANG_C
AC_CANONICAL_HOST
# $host
#######################
## test for underscores. The vpi module loader needs to know this
## in order to know the name of the start symbol for the .vpi module.
#######################
AC_CYGWIN
AC_EXEEXT
AC_MINGW32
WIN32=no
AC_MSG_CHECKING("Checking for windows")
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
then
WIN32=yes
fi
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
AC_SUBST(EXEEXT)
AC_MSG_CHECKING("for leading and/or trailing underscores")
cat << EOF > underscore.c
void underscore(void){}
EOF
$CC -shared -c underscore.c > /dev/null 2>&1
CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
output=`nm underscore.o|grep underscore_ 2>&1`
if test ! -z "$output"; then
CC_TRAILING_UNDERSCORE=yes
AC_DEFINE(NEED_TU)
fi
if test "$CC_LEADING_UNDERSCORE" = yes; then
AC_DEFINE(WLU)
fi
if test "$CC_TRAILING_UNDERSCORE" = yes; then
AC_DEFINE(WTU)
fi
rm underscore.c underscore.o
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
#######################
## end of test for underscores
#######################
# The -fPIC flag is used to tell the compiler to make position
# independent code. It is needed when making shared objects.
@@ -233,6 +174,65 @@ esac
AC_SUBST(shared)
AC_MSG_RESULT($shared)
#######################
## test for underscores. The vpi module loader needs to know this
## in order to know the name of the start symbol for the .vpi module.
#######################
AC_CYGWIN
AC_EXEEXT
AC_MINGW32
WIN32=no
AC_MSG_CHECKING("Checking for windows")
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
then
WIN32=yes
fi
AC_SUBST(MINGW32)
AC_SUBST(WIN32)
AC_MSG_RESULT($WIN32)
AC_SUBST(EXEEXT)
AC_MSG_CHECKING("for leading and/or trailing underscores")
cat << EOF > underscore.c
void underscore(void){}
EOF
$CC $shared -c underscore.c > /dev/null 2>&1
CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
output=`nm underscore.o|grep underscore_ 2>&1`
if test ! -z "$output"; then
CC_TRAILING_UNDERSCORE=yes
AC_DEFINE(NEED_TU)
fi
if test "$CC_LEADING_UNDERSCORE" = yes; then
AC_DEFINE(WLU)
fi
if test "$CC_TRAILING_UNDERSCORE" = yes; then
AC_DEFINE(WTU)
fi
rm underscore.c underscore.o
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
#######################
## end of test for underscores
#######################
AC_MSG_CHECKING("for ident support in C compiler")
ident_support='-DHAVE_CVS_IDENT=1'
@@ -257,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)
+28 -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: design_dump.cc,v 1.133 2002/08/19 00:06:11 steve Exp $"
#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -271,7 +271,8 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
void NetFF::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_FF: " << name()
<< " scope=" << (scope()? scope()->name() : "") << endl;
<< " scope=" << (scope()? scope()->name() : "")
<< " aset_value=" << aset_value_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -699,17 +700,26 @@ void NetScope::dump(ostream&o) const
/* Dump the parameters for this scope. */
{
map<string,NetExpr*>::const_iterator pp;
map<string,param_expr_t>::const_iterator pp;
for (pp = parameters_.begin()
; pp != parameters_.end() ; pp ++) {
o << " parameter " << (*pp).first << " = " <<
*(*pp).second << ";" << endl;
o << " parameter ";
if ((*pp).second.signed_flag)
o << "signed ";
if ((*pp).second.msb)
o << "[" << *(*pp).second.msb
<< ":" << *(*pp).second.lsb << "] ";
o << (*pp).first << " = " <<
*(*pp).second.expr << ";" << endl;
}
for (pp = localparams_.begin()
; pp != localparams_.end() ; pp ++) {
o << " localparam " << (*pp).first << " = " <<
*(*pp).second << ";" << endl;
*(*pp).second.expr << ";" << endl;
}
}
@@ -925,7 +935,10 @@ void NetEMemory::dump(ostream&o) const
void NetEParam::dump(ostream&o) const
{
o << "<" << scope_->name() << "." << name_ << ">";
if (scope_ != 0)
o << "<" << scope_->name() << "." << name_ << ">";
else
o << "<" << name_ << ">";
}
void NetETernary::dump(ostream&o) const
@@ -991,6 +1004,14 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* 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.
*
* Revision 1.134 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.133 2002/08/19 00:06:11 steve
* Allow release to handle removal of target net.
*
+2
View File
@@ -0,0 +1,2 @@
Makefile
iverilog-vpi.exe
+82
View File
@@ -0,0 +1,82 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc.,
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.5 2002/12/08 03:06:30 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
mandir = @mandir@
dllib=@DLLIB@
CC = @CC@
CXX = @CXX@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"'
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)/..
LDFLAGS = @LDFLAGS@
all: iverilog-vpi@EXEEXT@
clean:
rm -f *.o
rm -f iverilog-vpi@EXEEXT@
distclean: clean
rm -f Makefile
O = main.o res.o
iverilog-vpi@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
main.o: main.c
$(CC) $(CFLAGS) -c $(srcdir)/main.c
# Windows specific...
res.o: res.rc
windres -i res.rc -o res.o
#
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(bindir)
uninstall:
rm -f $(bindir)/iverilog-vpi@EXEEXT@
+565
View File
@@ -0,0 +1,565 @@
/*
* Copyright (c) 2002 Gus Baldauf ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/*
* iverilog-vpi.c
*
* this program provides the functionality of iverilog-vpi.sh under Win32
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
/* Macros used for compiling and linking */
#define IVERILOG_VPI_CC "gcc" /* no .exe extension */
#define IVERILOG_VPI_CXX "gcc" /* no .exe extension */
#define IVERILOG_VPI_CFLAGS "-O" /* -I appended later */
#define IVERILOG_VPI_LD "gcc" /* no .exe extension */
#define IVERILOG_VPI_LDFLAGS "-shared -Wl,--enable-auto-image-base"
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi" /* -L prepended later */
/* pointers to global strings */
static struct global_strings {
char *pCCSRC; /* list of C source files */
char *pCXSRC; /* list of C++ source files */
char *pOBJ; /* list of object files */
char *pLIB; /* list of library files */
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
char *pMINGW; /* path to MinGW directory */
char *pIVL; /* path to IVL directory */
char *pCFLAGS; /* CFLAGS option */
char *pLDLIBS; /* LDLIBS option */
char *pNewPath; /* new PATH environment variable setting */
} gstr;
static void deInitDynString(char *str)
{
free(str);
}
/* when finished, free allocated memory and return error code */
static void myExit(int exitVal)
{
deInitDynString(gstr.pCCSRC);
deInitDynString(gstr.pCXSRC);
deInitDynString(gstr.pOBJ);
deInitDynString(gstr.pLIB);
deInitDynString(gstr.pOUT);
deInitDynString(gstr.pMINGW);
deInitDynString(gstr.pIVL);
deInitDynString(gstr.pCFLAGS);
deInitDynString(gstr.pLDLIBS);
deInitDynString(gstr.pNewPath);
exit(exitVal);
}
/* display usage summary and exit */
static void usage()
{
fprintf(stderr,"usage: iverilog-vpi [--name=name] [-llibrary] [-mingw=dir] [-ivl=dir] sourcefile...\n");
fprintf(stderr," or iverilog-vpi -mingw=dir\n");
fprintf(stderr," or iverilog-vpi -ivl=dir\n");
myExit(1);
}
static void initDynString(char **str)
{
*str = (char *) malloc(1);
if (!*str) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
*str[0] = 0;
}
/* initialize dynamic memory buffers */
static void init()
{
initDynString(&gstr.pCCSRC);
initDynString(&gstr.pCXSRC);
initDynString(&gstr.pOBJ);
initDynString(&gstr.pLIB);
initDynString(&gstr.pOUT);
initDynString(&gstr.pMINGW);
initDynString(&gstr.pIVL);
initDynString(&gstr.pCFLAGS);
initDynString(&gstr.pLDLIBS);
initDynString(&gstr.pNewPath);
}
/* return true if "str" is terminated with with "end", case insensitive */
static int endsIn (char *end, char *str)
{
char *ext;
if (strlen(end) >= strlen(str))
return 0;
ext = str + (strlen(str) - strlen(end));
return stricmp(end,ext) ? 0 : 1;
}
/* return true if "str" begins with "prefix", case insensitive */
static int startsWith (char *prefix, char *str)
{
if (strlen(prefix) >= strlen(str))
return 0;
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
}
/* append "app" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "app" */
static void appendn (char **ptr, char *app, int count)
{
*ptr = (char *) realloc(*ptr,strlen(*ptr)+(count?count:strlen(app))+1);
if (*ptr == NULL) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
if (count)
strncat(*ptr,app,count);
else
strcat(*ptr,app);
}
/* append "app" to "ptr", allocating memory as needed */
static void append (char **ptr, char *app)
{
appendn(ptr,app,0);
}
/* if the string does not end with a backslash, add one */
static void appendBackSlash(char **str)
{
if ((*str)[strlen(*str)-1] != '\\')
append(str,"\\");
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
/* if count is zero, then copy all characters of "str" */
static void assignn (char **ptr, char *str, int count)
{
*ptr = (char *) realloc(*ptr,(count?count:strlen(str))+1);
if (*ptr == NULL) {
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
if (count) {
strncpy(*ptr,str,count);
(*ptr)[count] = 0;
}
else
strcpy(*ptr,str);
}
/* copy count characters of "str" to "ptr", allocating memory as needed */
static void assign (char **ptr, char *str)
{
assignn(ptr,str,0);
}
/* get a copy of a Icarus Verilog registry string key */
static int GetRegistryKey(char *key, char **value)
{
long lrv;
HKEY hkKey;
char *regKeyBuffer;
DWORD regKeyType, regKeySize;
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
if (lrv != ERROR_SUCCESS)
return 0;
lrv = RegQueryValueEx(hkKey,key,NULL,&regKeyType,NULL,&regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
return 0;
}
regKeyBuffer = (char *) malloc(regKeySize+1);
if (!regKeyBuffer) {
lrv = RegCloseKey(hkKey);
fprintf(stderr,"error: out of memory\n");
myExit(4);
}
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
lrv = RegQueryValueEx(hkKey,key,NULL,&regKeyType,regKeyBuffer,&regKeySize);
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
lrv = RegCloseKey(hkKey);
free(regKeyBuffer);
return 0;
}
RegCloseKey(hkKey);
assign(value,regKeyBuffer);
free(regKeyBuffer);
return 1;
}
/* store a copy of a Icarus Verilog registry string key */
static void SetRegistryKey(char *key, char *value)
{
HKEY hkKey;
DWORD res;
if (RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
"Software\\Icarus Verilog",
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,NULL,
&hkKey,
&res) != ERROR_SUCCESS)
return;
RegSetValueEx(hkKey,key,0,REG_SZ,value,strlen(value)+1);
RegCloseKey(hkKey);
printf("info: storing %s in Windows' registry entry\n",value);
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
}
/* parse the command line, assign results to global variable strings */
static int parse(int argc, char *argv[])
{
int idx, srcFileCnt=0;
char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc";
char dot_o_ext[] = ".o";
char name_option[] = "--name=";
char lib_option[] = "-l";
char mingw_option[] = "-mingw=";
char ivl_option[] = "-ivl=";
if (argc == 1)
return 0;
for (idx=1; idx<argc; ++idx) {
if (endsIn(dot_c_ext,argv[idx])) { /* check for C source files */
++srcFileCnt;
append(&gstr.pCCSRC,argv[idx]);
append(&gstr.pCCSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_c_ext));
}
else if (endsIn(dot_cc_ext,argv[idx])) { /* check for C++ source files */
++srcFileCnt;
append(&gstr.pCXSRC,argv[idx]);
append(&gstr.pCXSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
}
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
++srcFileCnt;
append(&gstr.pOBJ,argv[idx]);
append(&gstr.pOBJ," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_o_ext));
}
else if (startsWith(name_option,argv[idx])) { /* check for --name option */
assignn(&gstr.pOUT,argv[idx]+sizeof(name_option)-1,strlen(argv[idx])-(sizeof(name_option)-1));
}
else if (startsWith(lib_option,argv[idx])) { /* check for -l option */
append(&gstr.pLIB,argv[idx]);
append(&gstr.pLIB," ");
}
else if (startsWith(mingw_option,argv[idx])) /* check for -mingw option */
assignn(&gstr.pMINGW,argv[idx]+sizeof(mingw_option)-1,strlen(argv[idx])-(sizeof(mingw_option)-1));
else if (startsWith(ivl_option,argv[idx])) /* check for -ivl option */
assignn(&gstr.pIVL,argv[idx]+sizeof(ivl_option)-1,strlen(argv[idx])-(sizeof(ivl_option)-1));
else
return 0; /* different from iverilog-vpi.sh, we don't ignore accept arguments */
}
if (0 == srcFileCnt)
assign(&gstr.pOUT,""); /* in case they used --name with no source files */
if (!*gstr.pOUT) { /* normally it's an error if there are no *.c,*.cc,*.o files */
if (!*gstr.pMINGW && !*gstr.pIVL) /* unless they are just setting the IVL or MinGW registry entries */
usage();
}
else {
append(&gstr.pOUT,".vpi"); /* the result file should have a .vpi extension */
append(&gstr.pOUT," ");
}
return 1;
}
/* do minimal check that the MinGW root directory looks valid */
static void checkMingwDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path;
initDynString(&path);
assign(&path,gstr.pMINGW);
appendBackSlash(&path);
append(&path,"bin\\" IVERILOG_VPI_CC ".exe");
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\\\mingw\n");
myExit(5);
}
}
/* do minimal check that the Icarus Verilog root directory looks valid */
static void checkIvlDir(char *root)
{
int irv;
struct _stat stat_buf;
char *path;
initDynString(&path);
assign(&path,gstr.pIVL);
appendBackSlash(&path);
append(&path,"bin\\vvp.exe");
irv = _stat(path,&stat_buf);
deInitDynString(path);
if (irv) {
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi.exe to\n");
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
fprintf(stderr," For a Cygwin shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\\\iverilog\n");
myExit(6);
}
}
/* see if we can find mingw root */
#define IVL_REGKEY_MINGW "MingwDir"
static void setup_mingw_environment()
{
char *pOldPATH = getenv("PATH"); /* get current path */
if (*gstr.pMINGW) {
checkMingwDir(gstr.pMINGW);
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
}
else
if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
fprintf(stderr," a Windows command shell the option would be something like\n");
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
myExit(5);
}
assign(&gstr.pNewPath,"PATH="); /* create new path */
append(&gstr.pNewPath,gstr.pMINGW);
appendBackSlash(&gstr.pNewPath);
append(&gstr.pNewPath,"bin;");
append(&gstr.pNewPath,pOldPATH);
_putenv(gstr.pNewPath); /* place new path in environment variable */
}
/* see if we can find iverilog root */
#define IVL_REGKEY_IVL "InstallDir"
static void setup_ivl_environment()
{
if (*gstr.pIVL) {
checkIvlDir(gstr.pIVL);
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
}
else
if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\n");
fprintf(stderr," For a Windows command shell the option would be something like\n");
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
myExit(6);
}
/* build up the CFLAGS option string */
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS);
append(&gstr.pCFLAGS," -I");
append(&gstr.pCFLAGS,gstr.pIVL);
appendBackSlash(&gstr.pCFLAGS);
append(&gstr.pCFLAGS,"include");
/* build up the LDFLAGS option string */
assign(&gstr.pLDLIBS,"-L");
append(&gstr.pLDLIBS,gstr.pIVL);
appendBackSlash(&gstr.pLDLIBS);
append(&gstr.pLDLIBS,"lib ");
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
}
/* compile source modules */
static void compile(char *pSource, char **pObject, char *ext, int *compile_errors, char *compiler)
{
char *ptr1 = pSource;
char *ptr2 = strchr(pSource,' ');
char *buf=0,*src=0,*obj=0;
while (ptr2) {
int len = ptr2 - ptr1;
assignn(&src,ptr1,len);
assignn(&obj,ptr1,len-strlen(ext)); /* strip off the extension */
append (&obj,".o");
assign (&buf,compiler);
append (&buf," -c -o ");
append (&buf,obj);
append (&buf," ");
append (&buf,gstr.pCFLAGS);
append (&buf," ");
append (&buf,src);
append (pObject,obj);
append (pObject," ");
printf("%s\n",buf);
if (system(buf))
++*compile_errors;
ptr1 = ptr2 + 1; /* advance to next token */
ptr2 = strchr(ptr1,' ');
}
free(buf);
free(src);
free(obj);
}
/* using the global strings, compile and link */
static void compile_and_link()
{
char *buf=0;
int iRet, compile_errors = 0;
/* print out the mingw and ivl directories to help the user debug problems */
printf("info: %s will be used as the MinGW root directory.\n",gstr.pMINGW);
checkMingwDir(gstr.pMINGW);
printf("info: %s will be used as the Icarus Verilog root directory.\n",gstr.pIVL);
checkIvlDir(gstr.pIVL);
/* compile */
compile(gstr.pCCSRC,&gstr.pOBJ,".c" ,&compile_errors,IVERILOG_VPI_CC ); /* compile the C source files */
compile(gstr.pCXSRC,&gstr.pOBJ,".cc",&compile_errors,IVERILOG_VPI_CXX); /* compile the C++ source files */
if (compile_errors) {
fprintf(stderr,"iverilog-vpi: Some %d files failed to compile.\n",compile_errors);
myExit(2);
}
/* link */
assign(&buf,IVERILOG_VPI_LD);
append(&buf," -o ");
append(&buf,gstr.pOUT); /* has a trailing space */
append(&buf,IVERILOG_VPI_LDFLAGS);
append(&buf," ");
append(&buf,gstr.pOBJ) /* has a trailing space */;
append(&buf,gstr.pLIB); /* has a trailing space */
append(&buf,gstr.pLDLIBS);
printf("%s\n",buf);
iRet = system(buf);
free(buf);
if (iRet)
myExit(3);
}
/* program execution starts here */
int main(int argc, char *argv[])
{
init();
if (!parse(argc,argv))
usage();
setup_mingw_environment();
setup_ivl_environment();
if (*gstr.pOUT) /* are there any *.c,*.cc,*.o files specified */
compile_and_link();
myExit(0);
}
+38
View File
@@ -0,0 +1,38 @@
// LANGUAGE ENGLISH
LANGUAGE 9, 4
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
1 VERSIONINFO
FILEVERSION 2002,11,13,0
PRODUCTVERSION 0,7,0,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x2L
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Icarus Verilog\0"
VALUE "FileDescription", "Icarus Veriog VPI Tool\0"
VALUE "FileVersion", "2002, 11, 13, 0\0"
VALUE "InternalName", "iverilog-vpi\0"
VALUE "LegalCopyright", "Copyright 2002 Gus Baldauf\0"
VALUE "OriginalFilename", "iverilog-vpi.exe\0"
VALUE "ProductName", "Icarus Verilog\0"
VALUE "ProductVersion", "0, 7, 0, 0\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
+3 -5
View File
@@ -3,9 +3,7 @@
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -18,12 +16,12 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.15 2002/08/10 22:36:59 steve Exp $"
#ident "$Id: Makefile.in,v 1.16 2002/12/08 03:06:30 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.6
VERSION = 0.7
prefix = @prefix@
exec_prefix = @exec_prefix@
+37 -2
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ident "$Id: main.c,v 1.47 2002/08/12 01:27:48 steve Exp $"
#ident "$Id: main.c,v 1.49 2002/12/04 03:26:59 steve Exp $"
# include "config.h"
@@ -119,6 +119,35 @@ char tmp[MAXSIZE];
static char ivl_root[MAXSIZE];
#ifdef __MINGW32__
# include <io.h>
# include <fcntl.h>
static FILE*fopen_safe(const char*path)
{
FILE*file = 0;
int fd;
fd = _open(path, _O_WRONLY|_O_CREAT|_O_EXCL, 0700);
if (fd != -1)
file = _fdopen(fd, "w");
return file;
}
#else
# include <fcntl.h>
static FILE*fopen_safe(const char*path)
{
FILE*file = 0;
int fd;
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0700);
if (fd != -1)
file = fdopen(fd, "w");
return file;
}
#endif
static const char*my_tempfile(const char*str, FILE**fout)
{
FILE*file;
@@ -148,7 +177,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
while ((retry > 0) && (file == NULL)) {
unsigned code = rand();
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
file = fopen(pathbuf, "w");
file = fopen_safe(pathbuf);
retry -= 1;
}
@@ -657,6 +686,12 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.49 2002/12/04 03:26:59 steve
* Mingw32 compatible temp file management.
*
* Revision 1.48 2002/12/04 02:29:36 steve
* Use O_EXCL when opening temp files.
*
* Revision 1.47 2002/08/12 01:27:48 steve
* Escape the backslash in the windows file name.
*
+20 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999 Stephen Williams ([email protected])
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.8 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: dup_expr.cc,v 1.9 2002/11/09 00:25:27 steve Exp $"
#endif
# include "config.h"
@@ -65,6 +65,21 @@ NetETernary* NetETernary::dup_expr() const
return tmp;
}
NetEUFunc* NetEUFunc::dup_expr() const
{
NetEUFunc*tmp;
svector<NetExpr*> tmp_parms (parms_.count());
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
assert(parms_[idx]);
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(func_, result_->dup_expr(), tmp_parms);
return tmp;
}
NetEUnary* NetEUnary::dup_expr() const
{
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
@@ -74,6 +89,9 @@ NetEUnary* NetEUnary::dup_expr() const
/*
* $Log: dup_expr.cc,v $
* Revision 1.9 2002/11/09 00:25:27 steve
* Add dup_expr for user defined function calls.
*
* Revision 1.8 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
@@ -97,12 +115,5 @@ NetEUnary* NetEUnary::dup_expr() const
* Revision 1.3 2000/05/04 03:37:58 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.2 2000/02/23 02:56:54 steve
* Macintosh compilers do not support ident.
*
* Revision 1.1 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
*/
+26 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.63 2002/08/19 02:39:16 steve Exp $"
#ident "$Id: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
#endif
# include "config.h"
@@ -120,7 +120,8 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case '^':
case '&':
case '|':
case 'O':
case 'O': // NOR (~|)
case 'A': // NAND (~&)
case 'X':
tmp = new NetEBBits(op_, lp, rp);
tmp->set_line(*this);
@@ -632,11 +633,21 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
unsigned idx = net->sb_to_idx(msv);
if (idx >= net->pin_count()) {
cerr << get_line() << ": internal error: "
<< "bit " << msv << " out of range of net "
/* The bit select is out of range of the
vector. This is legal, but returns a
constant 1'bx value. */
verinum x (verinum::Vx);
NetEConst*tmp = new NetEConst(x);
tmp->set_line(*this);
cerr << get_line() << ": warning: Bit select ["
<< msv << "] out of range of vector "
<< net->name() << "[" << net->msb()
<< ":" << net->lsb() << "]." << endl;
return 0;
cerr << get_line() << ": : Replacing "
<< "expression with a constant 1'bx." << endl;
delete msn;
return tmp;
}
NetESignal*tmp = new NetESignal(net, idx, idx);
@@ -697,7 +708,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
assert(idx_ == 0);
NetExpr*i = msb_->elaborate_expr(des, scope);
if (msb_ && i == 0) {
cerr << get_line() << ": error: Unable to exaborate "
cerr << get_line() << ": error: Unable to elaborate "
"index expression `" << *msb_ << "'" << endl;
des->errors += 1;
return 0;
@@ -874,6 +885,15 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
/*
* $Log: elab_expr.cc,v $
* Revision 1.66 2002/09/21 21:28:18 steve
* Allow constant bit selects out of range.
*
* Revision 1.65 2002/09/18 04:08:45 steve
* Spelling errors.
*
* Revision 1.64 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.63 2002/08/19 02:39:16 steve
* Support parameters with defined ranges.
*
+45 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_lval.cc,v 1.20 2002/08/12 01:34:58 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.23 2002/11/21 23:27:51 steve Exp $"
#endif
# include "config.h"
@@ -170,16 +170,20 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
verinum*vl = lsb_->eval_const(des, scope);
if (vl == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant: "
<< *lsb_;
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return 0;
}
verinum*vm = msb_->eval_const(des, scope);
if (vl == 0) {
if (vm == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant: "
<< *msb_;
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return 0;
}
@@ -277,12 +281,38 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
{
if (msb_ == 0) {
cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index."
<< endl;
des->errors += 1;
return 0;
}
if (msb_ && lsb_) {
cerr << get_line() << ": error: Cannot use part select on "
<< "memory \"" << mem->name() << ".\"" << endl;
des->errors += 1;
return 0;
}
assert(msb_ && !lsb_);
NetExpr*ix = msb_->elaborate_expr(des, scope);
if (ix == 0)
return 0;
/* Evaluate the memory index expression down as must as
possible. Ideally, we can get it down to a constant. */
if (! dynamic_cast<NetEConst*>(ix)) {
NetExpr*tmp = ix->eval_tree();
if (tmp) {
tmp->set_line(*ix);
delete ix;
ix = tmp;
}
}
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
lv->set_part(0, mem->width());
@@ -299,6 +329,15 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.23 2002/11/21 23:27:51 steve
* Precalculate indices to l-value arrays.
*
* Revision 1.22 2002/11/21 18:15:40 steve
* Fix const test of msb in assignment l-values.
*
* Revision 1.21 2002/11/02 01:10:49 steve
* Detect memories without work index in l-value.
*
* Revision 1.20 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+127 -14
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.99 2002/09/08 01:37:13 steve Exp $"
#ident "$Id: elab_net.cc,v 1.103 2002/12/06 03:08:19 steve Exp $"
#endif
# include "config.h"
@@ -67,6 +67,8 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
case '|': // Bitwise OR
case '&':
case '^':
case 'A': // Bitwise NAND (~&)
case 'O': // Bitwise NOR (~|)
case 'X': // Exclusing NOR
return elaborate_net_bit_(des, scope, width, rise, fall, decay);
case 'E': // === (case equals)
@@ -340,6 +342,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
}
break;
case 'A': // NAND (~&)
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
3, NetLogic::NAND);
connect(gate->pin(1), lsig->pin(idx));
connect(gate->pin(2), rsig->pin(idx));
connect(gate->pin(0), osig->pin(idx));
gate->rise_time(rise);
gate->fall_time(fall);
gate->decay_time(decay);
des->add_node(gate);
}
break;
case '|': // Bitwise OR
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
@@ -354,6 +370,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
}
break;
case 'O': // Bitwise NOR
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
3, NetLogic::NOR);
connect(gate->pin(1), lsig->pin(idx));
connect(gate->pin(2), rsig->pin(idx));
connect(gate->pin(0), osig->pin(idx));
gate->rise_time(rise);
gate->fall_time(fall);
gate->decay_time(decay);
des->add_node(gate);
}
break;
default:
assert(0);
}
@@ -1407,11 +1437,70 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
return osig;
}
/*
* The concatenation is also OK an an l-value. This method elaborates
* it as a structural l-value.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
{
assert(scope);
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned errors = 0;
if (repeat_) {
cerr << get_line() << ": sorry: I do not know how to"
" elaborate repeat concatenation nets." << endl;
return 0;
}
/* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
implicit_net_ok);
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
}
/* If any of the sub expressions failed to elaborate, then
delete all those that did and abort myself. */
if (errors) {
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (nets[idx]) delete nets[idx];
}
des->errors += 1;
return 0;
}
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list. */
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
NetNet::IMPLICIT, pins);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
}
osig->local_flag(true);
return osig;
}
/*
* Identifiers in continuous assignment l-values are limited to wires
* and that ilk. Detect registers and memories here and report errors.
*/
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
{
string path = scope->name();
@@ -1425,29 +1514,41 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
return 0;
}
cerr << get_line() << ": error: Net " << path_
<< " is not defined in this context." << endl;
cerr << get_line() << ": : Do you mean this? wire "
<< path_ << " = <expr>;" << endl;
return 0;
if (implicit_net_ok && !error_implicit) {
sig = new NetNet(scope, scope->name()+"."+path_.peek_name(0),
NetNet::IMPLICIT, 1);
if (warn_implicit) {
cerr << get_line() << ": warning: implicit "
"definition of wire " << scope->name()
<< "." << path_.peek_name(0) << "." << endl;
}
} else {
cerr << get_line() << ": error: Net " << path_
<< " is not defined in this context." << endl;
cerr << get_line() << ": : Do you mean this? wire "
<< path_ << " = <expr>;" << endl;
return 0;
}
}
assert(sig);
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_line() << ": error: registers (" << sig->name()
<< ") cannot be l-values in continuous"
cerr << get_line() << ": error: reg " << sig->name()
<< "; cannot be an L-value in continuous"
<< " assignments." << endl;
return 0;
}
if (sig->port_type() == NetNet::PINPUT) {
cerr << get_line() << ": warning: assign l-value ``"
<< sig->name() << "'' is also an input to "
<< sig->scope()->name() << "." << endl;
cerr << sig->get_line() << ": warning: input ``"
<< sig->name() << "'' is coerced to inout." << endl;
cerr << get_line() << ": warning: L-value ``"
<< sig->name() << "'' is also an input port." << endl;
cerr << sig->get_line() << ": warning: input "
<< sig->name() << "; is coerced to inout." << endl;
sig->port_type(NetNet::PINOUT);
}
@@ -2177,6 +2278,18 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.103 2002/12/06 03:08:19 steve
* Reword some error messages for clarity.
*
* Revision 1.102 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.101 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.100 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.99 2002/09/08 01:37:13 steve
* Fix padding of operand of unary minus.
*
+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.
*
+23 -35
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.16 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -68,7 +68,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp);
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
for (mparm_it_t cur = localparams.begin()
@@ -78,7 +78,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp);
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
@@ -94,6 +94,9 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = false;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
@@ -101,37 +104,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
parameter value is coerced to have the correct
and defined width. */
if ((*cur).second.msb) {
verinum*msb = (*cur).second.msb ->eval_const(des, scope);
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
assert(msb);
verinum*lsb = (*cur).second.lsb ->eval_const(des, scope);
assert(lsb);
long msl = msb->as_long();
long lsl = lsb->as_long();
delete msb;
delete lsb;
unsigned width;
if (msl >= lsl)
width = msl - lsl + 1;
else
width = lsl - msl + 1;
if (NetEConst*tmp = dynamic_cast<NetEConst*>(val)) {
verinum tval (tmp->value(), width);
tval.has_sign((*cur).second.signed_flag);
val = new NetEConst(tval);
delete tmp;
}
/* If the parameter has a range, then the
signedness is taken from the parameter
declaration, and the signedness of the
expression is ignored. */
val->cast_signed( (*cur).second.signed_flag );
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
signed_flag = (*cur).second.signed_flag;
}
val = scope->set_parameter((*cur).first, val);
val->cast_signed(signed_flag);
val = scope->set_parameter((*cur).first, val,
msb, lsb, signed_flag);
assert(val);
delete val;
}
@@ -143,7 +124,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
assert(ex);
NetExpr*val = ex->elaborate_pexpr(des, scope);
val = scope->set_parameter((*cur).first, val);
val = scope->set_parameter((*cur).first, val, 0, 0, false);
assert(val);
delete val;
}
@@ -351,9 +332,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
PExpr*tmp = (*cur).second;
NetExpr*val = tmp->elaborate_pexpr(des, sc);
val = my_scope->set_parameter((*cur).first, val);
assert(val);
delete val;
bool flag = my_scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< (*cur).first << " not found in "
<< sc->name() << "." << endl;
}
}
}
@@ -512,6 +496,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.17 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.16 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
+54 -78
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.263 2002/08/28 18:54:36 steve Exp $"
#ident "$Id: elaborate.cc,v 1.266 2002/12/05 04:15:14 steve Exp $"
#endif
# include "config.h"
@@ -612,33 +612,38 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// port. sig is the thing outside the module that
// connects to the port.
NetNet*sig = (*pins)[idx]->elaborate_net(des, scope,
prts_pin_count,
0, 0, 0);
if (sig == 0) {
cerr << "internal error: Expression too complicated "
"for elaboration." << endl;
continue;
NetNet*sig;
if ((prts.count() >= 1)
&& (prts[0]->port_type() != NetNet::PINPUT)) {
sig = (*pins)[idx]->elaborate_lnet(des, scope, true);
if (sig == 0) {
cerr << (*pins)[idx]->get_line() << ": error: "
<< "Output port expression must support "
<< "continuous assignment." << endl;
des->errors += 1;
continue;
}
} else {
sig = (*pins)[idx]->elaborate_net(des, scope,
prts_pin_count,
0, 0, 0);
if (sig == 0) {
cerr << "internal error: Expression too complicated "
"for elaboration." << endl;
continue;
}
}
assert(sig);
// Check that a reg is not passed as an output or inout
// port of the module. sig is the elaborated signal in
// the outside that is to be passed, and prts is a
// concatenation of signals on the input that receive a
// reg value.
if ((sig->type() == NetNet::REG)
&& (prts.count() >= 1)
#ifndef NDEBUG
if ((prts.count() >= 1)
&& (prts[0]->port_type() != NetNet::PINPUT)) {
cerr << get_line() << ": error: reg/variable "
<< sig->name() << " cannot connect to "
<< "output port " << (idx+1) << " of "
<< my_scope->name() << "." << endl;
des->errors += 1;
continue;
assert(sig->type() != NetNet::REG);
}
#endif
// Check that the parts have matching pin counts. If
// not, they are different widths. Note that idx is 0
@@ -838,61 +843,6 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
des->errors += 1;
}
/*
* The concatenation is also OK an an l-value. This method elaborates
* it as a structural l-value.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
{
assert(scope);
svector<NetNet*>nets (parms_.count());
unsigned pins = 0;
unsigned errors = 0;
if (repeat_) {
cerr << get_line() << ": sorry: I do not know how to"
" elaborate repeat concatenation nets." << endl;
return 0;
}
/* Elaborate the operands of the concatenation. */
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
if (nets[idx] == 0)
errors += 1;
else
pins += nets[idx]->pin_count();
}
/* If any of the sub expressions failed to elaborate, then
delete all those that did and abort myself. */
if (errors) {
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
if (nets[idx]) delete nets[idx];
}
des->errors += 1;
return 0;
}
/* Make the temporary signal that connects to all the
operands, and connect it up. Scan the operands of the
concat operator from least significant to most significant,
which is opposite from how they are given in the list. */
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
NetNet::IMPLICIT, pins);
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
}
}
osig->local_flag(true);
return osig;
}
NetProc* Statement::elaborate(Design*des, NetScope*) const
{
@@ -1025,7 +975,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
rv->set_width(wid);
rv = pad_to_width(rv, wid);
if (! rv->set_width(wid)) {
if (wid != rv->expr_width()) {
cerr << get_line() << ": error: Unable to match "
"expression width of " << rv->expr_width() <<
" to l-value width of " << wid << "." << endl;
@@ -1126,6 +1076,12 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
assert(rv);
/* Try to evaluate the expression, at least as far as possible. */
if (NetExpr*tmp = rv->eval_tree()) {
delete rv;
rv = tmp;
}
{ unsigned wid = count_lval_width(lv);
rv->set_width(wid);
rv = pad_to_width(rv, wid);
@@ -1401,6 +1357,17 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parm(idx);
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
/* Attempt to pre-evaluate the parameters. It may be
possible to at least partially reduce the
expression. */
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
NetExpr*tmp = eparms[idx]->eval_tree();
if (tmp != 0) {
delete eparms[idx];
eparms[idx] = tmp;
}
}
}
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
@@ -2522,6 +2489,15 @@ Design* elaborate(list<const char*>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.266 2002/12/05 04:15:14 steve
* precalculate r-values of nb assignments and task arguments.
*
* Revision 1.265 2002/11/26 03:35:13 steve
* Do not set width if width is already OK.
*
* Revision 1.264 2002/11/09 19:20:48 steve
* Port expressions for output ports are lnets, not nets.
*
* Revision 1.263 2002/08/28 18:54:36 steve
* Evaluate nonblocking assign r-values.
*
+8 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: emit.cc,v 1.69 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: emit.cc,v 1.70 2002/11/03 20:36:10 steve Exp $"
#endif
# include "config.h"
@@ -470,11 +470,18 @@ bool emit(const Design*des, const char*type)
return des->emit(tgt->meth);
}
cerr << "error: Code generator type " << type
<< " not found." << endl;
return false;
}
/*
* $Log: emit.cc,v $
* Revision 1.70 2002/11/03 20:36:10 steve
* Error message for mising code generator type.
*
* Revision 1.69 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+15 -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.cc,v 1.30 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: eval.cc,v 1.32 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -143,6 +143,13 @@ verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
return 0;
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
if (eval == 0) {
cerr << get_line() << ": internal error: Unable to evaluate "
<< "constant expression (parameter=" << path_
<< "): " << *expr << endl;
return 0;
}
assert(eval);
if (msb_ || lsb_)
@@ -219,6 +226,13 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
/*
* $Log: eval.cc,v $
* Revision 1.32 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.31 2002/10/13 05:01:07 steve
* More verbose eval_const assert message.
*
* Revision 1.30 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+65 -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: eval_tree.cc,v 1.41 2002/08/12 01:34:59 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();
}
@@ -884,10 +890,57 @@ NetExpr* NetEParam::eval_tree()
// The result can be saved as the value of the parameter for
// future reference, and return a copy to the caller.
scope_->set_parameter(name_.peek_name(0), res);
scope_->replace_parameter(name_.peek_name(0), res);
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,16 @@ 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.
*
* Revision 1.41 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+1 -1
View File
@@ -31,7 +31,7 @@
* file "hello" which is compiled, linked and ready to run. Run this
* program like so:
*
* ./hello
* vvp hello
*
* and the program will print the message to its output. Easy! For
* more on how to make the iverilog command work, see the iverilog
+377
View File
@@ -0,0 +1,377 @@
/*
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: sqrt-virtex.v,v 1.2 2002/11/13 01:49:43 steve Exp $"
*/
/*
* This module is a synthesizeable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other then to
* be excessively specific, I will step through the process of
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
* generate a generic library part for larger Virtex designs.
*
* In addition to Icarus Verilog, you will need implementation
* software from Xilinx. As of this writing, this example was tested
* with Foundation 4.2i, but it should work the same with ISE and
* Webpack software.
*
* This example source contains all the Verilog needed to do
* everything described below. We use conditional compilation to
* select the bits of Verilog that are needed to perform each specific
* task.
*
* SIMULATE THE DESIGN
*
* This source file includes a simulation test bench. To compile the
* program to include this test bench, use the command line:
*
* iverilog -DSIMULATE=1 -oa.out sqrt-virtex.v
*
* This generates the file "a.out" that can then be executed with the
* command:
*
* vvp a.out
*
* This causes the simulation to run a long set of example sqrt
* calculations. Each result is checked by the test bench to assure
* that the result is valid. When it is done, the program prints
* "PASSED" and finishes the simulation.
*
* When you take a close look at the "main" module below, you will see
* that it uses Verilog constructs that are not synthesizeable. This
* is fine, as we will never try to synthesize it.
*
* LIBRARY PARTS
*
* One can use the sqrt32 module to generate an EDIF file suitable for
* use as a library part. This part can be imported to the Xilinx
* schematic editor, then placed like any other pre-existing
* macro. One can also pass the generated EDIF as a precompiled macro
* that other designers may use as they see fit.
*
* To make an EDIF file from the sqrt32 module, execute the command:
*
* iverilog -osqrt32.edf -tfpga -parch=virtex sqrt-virtex.v
*
* The -parch=virtex tells the code generator to generate code for the
* virtex architecture family (we don't yet care what specific part)
* and the -osqrt32.edf places the output into the file
* sqrt32.edf.
*
* Without any preprocessor directives, the only module is the sqrt32
* module, so sqrt32 is compiled as the root. The ports of the module
* are automatically made into ports of the sqrt32.edf netlist, and
* the contents of the sqrt32 module are connected approprately.
*
* COMPLETE CHIP DESIGNS
*
* To make a complete chip design, there are other bits that need to
* be accounted for. Signals must be assigned to pins, and some
* special devices may need to be created. We also want to write into
* the EDIF file complete part information so that the implementation
* tools know how to route the complete design. The command to compile
* for our target part is:
*
* iverilog -ochip.edf -tfpga \
* -parch=virtex -ppart=XC2S15-VQ100 \
* -DMAKE_CHIP=1 sqrt-virtex.v
*
* This command uses the "chip" module as the root. This module in
* turn has ports that are destined to be the pins of the completed
* part. The -ppart= option gives complete part information, that is
* in turn written into the EDIF file. This saves us the drudgery of
* repeating that part number for later commands.
*
* The next steps involve Xilinx software, and to talk to Xilinx
* software, the netlist must be in the form of an "ngd" file, a
* binary netlist format. The command:
*
* ngdbuild chip.edf chip.ngd
*
* does the trick. The input to ngdbuild is the chip.edf file created
* by Icarus Verilog, and the output is the chip.ngd file that the
* implementation tools may read. From this point, it is best to refer
* to Xilinx documentation for the software you are using, but the
* quick summary is:
*
* map -o map.ncd chip.ngd
* par -w map.ncd chip.ncd
*
* The result of this sequence of commands is the chip.ncd file that
* is ready to be viewed by FPGA Edit, or converted to a bit stream,
* or whatever.
*
* POST MAP SIMULATION
*
* Warm fuzzies are good, and retesting your design after the part
* is mapped by the Xilinx backend tools is a cheap source of fuzzies.
* The command to make a Verilog file out of the mapped design is:
*
* ngd2ver chip.ngd chip_root.v
*
* This command creates from the chip.ngd the file "chip_root.v" that
* contains Verilog code that simulates the mapped design. This output
* Verilog has the single root module "chip_root", which came from the
* name of the root module when we were making hte EDIF file in the
* first place. The module has ports named just line the ports of the
* chip_root module below.
*
* The generated Verilog uses the library in the directory
* $(XILINX)/verilog/src/simprims. This directory comes with the ISE
* WebPACK installation that you are using. Icarus Verilog is able to
* simulate using that library.
*
* To compile a post-map simulation of the chip_root.v, use the
* command:
*
* iverilog -DSIMULATE -DPOST_MAP -ob.out \
* -y $(XILINX)/verilog/src/simprims \
* sqrt-virtex.v chip_root.v \
* $(XILINX)/verilog/src/glbl.v
*
* This command line generates b.out from the source files
* sqrt-virtex.v and chip_root.v (the latter from ngd2ver)
* and the "-y <path>" flag specifies the library directory that will
* be needed. The glbl.v source file is also included to provide the
* GSR and related signals.
*
* The POST_MAP compiler directive causes the GSR manipulations
* included in the test bench to be compiled in, to simulate the chip
* startup. Other then that, the test bench runs the post-map design
* the same way the pre-synthesis design works.
*
* Run this design with the command:
*
* vvp b.out
*
* And there you go.
*/
`ifndef POST_MAP
/*
* This module approximates the square root of an unsigned 32bit
* number. The algorithm works by doing a bit-wise binary search.
* Starting from the most significant bit, the accumulated value
* tries to put a 1 in the bit position. If that makes the square
* too big for the input, the bit is left zero, otherwise it is set
* in the result. This continues for each bit, decreasing in
* significance, until all the bits are calculated or all the
* remaining bits are zero.
*
* Since the result is an integer, this function really calculates
* value of the expression:
*
* x = floor(sqrt(y))
*
* where sqrt(y) is the exact square root of y and floor(N) is the
* largest integer <= N.
*
* For 32bit numbers, this will never run more then 16 iterations,
* which amounts to 16 clocks.
*/
module sqrt32(clk, rdy, reset, x, .y(acc));
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] acc;
// acc holds the accumulated result, and acc2 is the accumulated
// square of the accumulated result.
reg [15:0] acc;
reg [31:0] acc2;
// Keep track of which bit I'm working on.
reg [4:0] bitl;
wire [15:0] bit = 1 << bitl;
wire [31:0] bit2 = 1 << (bitl << 1);
// The output is ready when the bitl counter underflows.
wire rdy = bitl[4];
// guess holds the potential next values for acc, and guess2 holds
// the square of that guess. The guess2 calculation is a little bit
// subtle. The idea is that:
//
// guess2 = (acc + bit) * (acc + bit)
// = (acc * acc) + 2*acc*bit + bit*bit
// = acc2 + 2*acc*bit + bit2
// = acc2 + 2 * (acc<<bitl) + bit
//
// This works out using shifts because bit and bit2 are known to
// have only a single bit in them.
wire [15:0] guess = acc | bit;
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
(* ivl_synthesis_on *)
always @(posedge clk or posedge reset)
if (reset) begin
acc = 0;
acc2 = 0;
bitl = 15;
end else begin
if (guess2 <= x) begin
acc <= guess;
acc2 <= guess2;
end
bitl <= bitl - 5'd1;
end
endmodule // sqrt32
`endif // `ifndef POST_MAP
`ifdef SIMULATE
/*
* This module is a test bench for the sqrt32 module. It runs some
* test input values through the sqrt32 module, and checks that the
* output is valid. If an invalid output is generated, print and
* error message and stop immediately. If all the tested values pass,
* then print PASSED after the test is complete.
*/
module main;
reg [31:0] x;
reg clk, reset;
wire [15:0] y;
wire rdy;
`ifdef POST_MAP
chip_root dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
`else
sqrt32 dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
`endif
(* ivl_synthesis_off *)
always #5 clk = !clk;
task reset_dut;
begin
reset = 1;
#1 reset = 0;
@(negedge clk) ;
end
endtask // reset_dut
task crank_dut;
begin
while (rdy == 0) begin
@(posedge clk) /* wait */;
end
end
endtask // crank_dut
`ifdef POST_MAP
reg GSR;
assign glbl.GSR = GSR;
`endif
integer idx;
(* ivl_synthesis_off *)
initial begin
reset = 0;
clk = 0;
/* If doing a post-map simulation, when we need to wiggle
The GSR bit to simulate chip power-up. */
`ifdef POST_MAP
GSR = 1;
#100 GSR = 0;
`endif
#100 x = 1;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
x = 3;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
x = 4;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
for (idx = 0 ; idx < 200 ; idx = idx + 1) begin
x = $random;
reset_dut;
crank_dut;
$display("x=%d, y=%d", x, y);
if (x < (y * y)) begin
$display("ERROR: y is too big");
$finish;
end
if (x > ((y + 1)*(y + 1))) begin
$display("ERROR: y is too small");
$finish;
end
end
$display("PASSED");
$finish;
end
endmodule // main
`endif
`ifdef MAKE_CHIP
/*
* This module represents the chip packaging that we intend to
* generate. We bind pins here, and route the clock to the global
* clock buffer.
*/
module chip_root(clk, rdy, reset, x, y);
input clk;
output rdy;
input reset;
input [31:0] x;
output [15:0] y;
wire clk_int;
(* cellref="BUFG:O,I" *)
buf gbuf (clk_int, clk);
sqrt32 dut(.clk(clk_int), .reset(reset), .rdy(rdy), .x(x), .y(y));
/* Assign the clk to GCLK0, which is on pin P39. */
$attribute(clk, "PAD", "39");
// We don't care where the remaining pins go, so set the pin number
// to 0. This tells the implementation tools that we want a PAD,
// but we don't care which. Also note the use of a comma (,)
// separated list to assign pins to the bits of a vector.
$attribute(rdy, "PAD", "0");
$attribute(reset, "PAD", "0");
$attribute(x, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
$attribute(y, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
endmodule // chip_root
`endif
+31 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.36 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.37 2002/11/17 23:37:55 steve Exp $"
#endif
# include "config.h"
@@ -192,6 +192,33 @@ NetNet* NetEBComp::synthesize(Design*des)
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::OR);
break;
case '>':
/* sig > 0 is true if any bit in sig is set. This
is very much like sig != 0. (0 > sig) shouldn't
happen. */
if (rcon) {
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::OR);
} else {
assert(0);
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::NOR);
}
break;
case '<':
/* 0 < sig is handled like sig > 0. */
if (! rcon) {
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::OR);
} else {
assert(0);
gate = new NetLogic(scope, des->local_symbol(path),
lsig->pin_count()+1, NetLogic::NOR);
}
break;
default:
assert(0);
}
@@ -608,6 +635,9 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.37 2002/11/17 23:37:55 steve
* Magnitude compare to 0.
*
* Revision 1.36 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+26 -2
View File
@@ -1,4 +1,4 @@
.TH iverilog-vpi 1 "$Date: 2002/07/05 17:17:20 $" Version "$Date: 2002/07/05 17:17:20 $"
.TH iverilog-vpi 1 "$Date: 2002/11/23 00:51:53 $" Version "$Date: 2002/11/23 00:51:53 $"
.SH NAME
iverilog-vpi - Compile front end for VPI modules
@@ -32,13 +32,37 @@ VPI modules to further reference external libraries.
Normally, the output VPI module will be named after the first source
file passed to the command. This flag sets the name (without the .vpi
suffix) of the output vpi module.
.SH "PC-ONLY OPTIONS"
The PC port of \fIiverilog-vpi\fP includes two special flags needed to
support the more intractable development environment. These flags help
the program locate parts that it needs.
.TP 8
.B -mingw=\fIpath\fP
Tell the program the root of the Mingw compiler tool suite. The
\fBvvp\fP runtime is compiled with this compiler, and this is the
compiler that \fIiverilog-vpi\fP expects to use to compile your source
code. This is notmally not needed, and if you do use it, it is only
needed once. The compiler will save the \fIpath\fP in the registry for
use later.
.TP 8
.B -ivl=\fIpath\fP
Set for the use during compilation the root if the Icarus Verilog
install. This is the place where you installed Icarus Verilog when you
ran the installer. This flag is also only needed once, and the path is
stored in the registry for future use.
.SH "AUTHOR"
.nf
Steve Williams ([email protected])
.SH SEE ALSO
iverilog(1), vvp(1),
.BR "<http://www.icarus.com/eda/verilog/>"
.BR "<http://www.icarus.com/eda/verilog/>",
.BR "<http://www.mingw.org>",
.SH COPYRIGHT
.nf
+6 -8
View File
@@ -17,7 +17,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.6 2002/07/05 17:17:20 steve Exp $"
#ident "$Id: iverilog-vpi.sh,v 1.9 2002/10/19 23:18:52 steve Exp $"
# These are the variables used for compiling files
CC=gcc
@@ -44,13 +44,13 @@ do
case $parm
in
*.c) CCSRC="$SRC $parm"
*.c) CCSRC="$CCSRC $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .c`
fi
;;
*.cc) CXSRC="$SRC $parm"
*.cc) CXSRC="$CXSRC $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .cc`
fi
@@ -84,8 +84,7 @@ OUT=$OUT".vpi"
compile_errors=0
# Compile all the source files into object files
for src
in $CCSRC
for src in $CCSRC
do
base=`basename $src .c`
obj=$base".o"
@@ -95,8 +94,7 @@ do
OBJ="$OBJ $obj"
done
for src
in $CXSRC
for src in $CXSRC
do
base=`basename $src .cc`
obj=$base".o"
@@ -113,4 +111,4 @@ then
fi
echo "Making $OUT from $OBJ..."
exec $LD -o $OUT $LDFLAGS $OBJ $LDLIBS
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
+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]
+3
View File
@@ -54,6 +54,9 @@ ivl_logic_pin
ivl_logic_pins
ivl_logic_udp
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data
+24 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.105 2002/08/24 05:03:40 steve Exp $"
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
#endif
#ifdef __cplusplus
@@ -418,7 +418,15 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
*
* ivl_expr_width
* This method returns the bit width of the expression at this
* node. It can be applied to any expression node.
* node. It can be applied to any expression node, and returns the
* *output* width of the expression node.
*
* ivl_expr_opcode
* IVL_EX_BINARY and IVL_EX_UNARY expression nodes include an
* upcode from this table:
* & -- AND
* A -- NAND (~&)
* X -- XNOR (~^)
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
@@ -604,6 +612,10 @@ extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net);
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
extern unsigned ivl_lpm_width(ivl_lpm_t net);
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
@@ -1079,6 +1091,16 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* 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.
*
* Revision 1.107 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.106 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.105 2002/08/24 05:03:40 steve
* Missing declaration of ivl_memory_scope.
*
+13 -12
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.32 2002/04/04 05:26:13 steve Exp $"
#ident "$Id: lexor.lex,v 1.36 2002/11/08 00:04:16 steve Exp $"
#endif
# include "config.h"
@@ -170,7 +170,7 @@ W [ \t\b\f]+
directive and the name, go into PPDEFINE mode and prepare to
collect the defined value. */
`define{W}[a-zA-Z_][a-zA-Z0-9_]*{W}? { yy_push_state(PPDEFINE); def_start(); }
`define{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}? { yy_push_state(PPDEFINE); def_start(); }
<PPDEFINE>.* {
do_define();
@@ -194,7 +194,7 @@ W [ \t\b\f]+
yy_pop_state();
}
`undef{W}[a-zA-Z_][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
`undef{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}?.* { def_undefine(); }
/* Detect conditional compilation directives, and parse them. If I
@@ -206,7 +206,7 @@ W [ \t\b\f]+
condition that stacks on top of the IFDEF_FALSE so that output is
not accidentally turned on within nested ifdefs. */
^{W}?`ifdef{W}[a-zA-Z_][a-zA-Z0-9_]* {
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char*name = strchr(yytext, '`');
assert(name);
name += 6;
@@ -219,7 +219,7 @@ W [ \t\b\f]+
}
}
^{W}?`ifndef{W}[a-zA-Z_][a-zA-Z0-9_]* {
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char*name = strchr(yytext, '`');
assert(name);
name += 7;
@@ -232,22 +232,23 @@ W [ \t\b\f]+
}
}
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifdef{W}.* { yy_push_state(IFDEF_SUPR); }
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifndef{W}.* { yy_push_state(IFDEF_SUPR); }
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} { yy_push_state(IFDEF_SUPR); }
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { yy_push_state(IFDEF_SUPR); }
<IFDEF_TRUE>{W}?`else { BEGIN(IFDEF_FALSE); }
<IFDEF_FALSE>{W}?`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>{W}?`else { }
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
<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); }
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>^{W}?`endif {
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif {
yy_pop_state();
}
/* This pattern notices macros and arranges for them to be replaced. */
`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
/* Any text that is not a directive just gets passed through to the
output. Very easy. */
+2 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: lexor.lex,v 1.73 2002/06/06 18:57:18 steve Exp $"
#ident "$Id: lexor.lex,v 1.74 2002/12/04 02:07:00 steve Exp $"
#endif
# include "config.h"
@@ -375,7 +375,7 @@ W [ \t\b\f\r]+
if (isgraph(yytext[0]))
cerr << yytext[0];
else
cerr << (unsigned)yytext[0];
cerr << "hex " << hex << (0xffU & ((unsigned) (yytext[0])));
cerr << ")" << endl; }
+1 -1
View File
@@ -82,7 +82,7 @@ rpmos, K_rpmos
rtran, K_rtran
rtranif0, K_rtranif0
rtranif1, K_rtranif1
scalered, K_scalered
scalared, K_scalared
signed, K_signed
small, K_small
specify, K_specify
+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
+141 -111
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-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: net_design.cc,v 1.27 2002/08/16 05:18:27 steve Exp $"
#ident "$Id: net_design.cc,v 1.30 2002/12/07 02:49:24 steve Exp $"
#endif
# include "config.h"
@@ -242,13 +242,11 @@ void NetScope::run_defparams(Design*des)
continue;
}
NetExpr*tmp = targ_scope->set_parameter(name, val);
if (tmp == 0) {
bool flag = targ_scope->replace_parameter(name, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< name << " not found in " << targ_scope->name()
<< "." << endl;
} else {
delete tmp;
<< name << " not found in "
<< targ_scope->name() << "." << endl;
}
delete[]name;
@@ -276,34 +274,129 @@ void NetScope::evaluate_parameters(Design*des)
// scanning code. Now the parameter expression can be fully
// evaluated, or it cannot be evaluated at all.
typedef map<string,NetExpr*>::iterator mparm_it_t;
typedef map<string,param_expr_t>::iterator mparm_it_t;
for (mparm_it_t cur = parameters_.begin()
; cur != parameters_.end() ; cur ++) {
// Get the NetExpr for the parameter.
NetExpr*expr = (*cur).second;
assert(expr);
long msb = 0;
long lsb = 0;
bool range_flag = false;
NetExpr*expr;
// If it's already a NetEConst, then this parameter is done.
if (dynamic_cast<const NetEConst*>(expr))
continue;
/* Evaluate the msb expression, if it is present. */
expr = (*cur).second.msb;
// Try to evaluate the expression.
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second->get_line() << ": internal error: "
"unable to evaluate parm expression: " <<
*expr << endl;
des->errors += 1;
continue;
if (expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
if (! tmp) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate msb expression "
<< "for parameter " << (*cur).first << ": "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.msb = nexpr;
tmp = dynamic_cast<NetEConst*>(nexpr);
}
assert(tmp);
msb = tmp->value().as_long();
range_flag = true;
}
// The evaluate worked, replace the old expression with
// this constant value.
assert(nexpr);
delete expr;
(*cur).second = nexpr;
/* Evaluate the lsb expression, if it is present. */
expr = (*cur).second.lsb;
if (expr) {
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
if (! tmp) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate lsb expression "
<< "for parameter " << (*cur).first << ": "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.lsb = nexpr;
tmp = dynamic_cast<NetEConst*>(nexpr);
}
assert(tmp);
lsb = tmp->value().as_long();
assert(range_flag);
}
/* Evaluate the parameter expression, if necessary. */
expr = (*cur).second.expr;
assert(expr);
if (! dynamic_cast<const NetEConst*>(expr)) {
// Try to evaluate the expression.
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
"unable to evaluate parameter value: " <<
*expr << endl;
des->errors += 1;
continue;
}
// The evaluate worked, replace the old expression with
// this constant value.
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
// Set the signedness flag.
(*cur).second.expr->cast_signed( (*cur).second.signed_flag );
}
/* If the parameter has range information, then make
sure the value is set right. */
if (range_flag) {
long wid = (msb >= lsb)? msb - lsb : lsb - msb;
wid += 1;
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
assert(val);
verinum value = val->value();
if (! (value.has_len()
&& (value.len() == wid)
&& (value.has_sign() == (*cur).second.signed_flag))) {
verinum tmp (value, wid);
tmp.has_sign ( (*cur).second.signed_flag );
delete val;
val = new NetEConst(tmp);
(*cur).second.expr = val;
}
}
}
}
@@ -408,12 +501,18 @@ NetScope* Design::find_task(const hname_t&key)
return 0;
}
NetEvent* Design::find_event(NetScope*scope, hname_t path)
NetEvent* Design::find_event(NetScope*scope, const hname_t&p)
{
hname_t path = p;
assert(scope);
char*key = path.remove_tail_name();
if (path.peek_name(0))
scope = find_scope(scope, path);
while (scope) {
if (NetEvent*ev = scope->find_event(path)) {
if (NetEvent*ev = scope->find_event(key)) {
delete key;
return ev;
}
@@ -422,6 +521,7 @@ NetEvent* Design::find_event(NetScope*scope, hname_t path)
scope = scope->parent();
}
delete key;
return 0;
}
@@ -500,6 +600,17 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.30 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.29 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.28 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.27 2002/08/16 05:18:27 steve
* Fix intermix of node functors and node delete.
*
@@ -518,86 +629,5 @@ void Design::delete_process(NetProcTop*top)
*
* Revision 1.22 2001/10/20 05:21:51 steve
* Scope/module names are char* instead of string.
*
* Revision 1.21 2001/10/19 21:53:24 steve
* Support multiple root modules (Philip Blundell)
*
* Revision 1.20 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.19 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.18 2001/01/14 23:04:56 steve
* Generalize the evaluation of floating point delays, and
* get it working with delay assignment statements.
*
* Allow parameters to be referenced by hierarchical name.
*
* Revision 1.17 2000/12/16 01:45:48 steve
* Detect recursive instantiations (PR#2)
*
* Revision 1.16 2000/09/24 17:41:13 steve
* fix null pointer when elaborating undefined task.
*
* Revision 1.15 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.14 2000/08/12 17:59:48 steve
* Limit signal scope search at module boundaries.
*
* Revision 1.13 2000/07/30 18:25:43 steve
* Rearrange task and function elaboration so that the
* NetTaskDef and NetFuncDef functions are created during
* signal enaboration, and carry these objects in the
* NetScope class instead of the extra, useless map in
* the Design class.
*
* Revision 1.12 2000/07/23 02:41:32 steve
* Excessive assert.
*
* Revision 1.11 2000/07/22 22:09:03 steve
* Parse and elaborate timescale to scopes.
*
* Revision 1.10 2000/07/16 04:56:08 steve
* Handle some edge cases during node scans.
*
* Revision 1.9 2000/07/14 06:12:57 steve
* Move inital value handling from NetNet to Nexus
* objects. This allows better propogation of inital
* values.
*
* Clean up constant propagation a bit to account
* for regs that are not really values.
*
* Revision 1.8 2000/05/02 16:27:38 steve
* Move signal elaboration to a seperate pass.
*
* Revision 1.7 2000/05/02 03:13:31 steve
* Move memories to the NetScope object.
*
* Revision 1.6 2000/05/02 00:58:12 steve
* Move signal tables to the NetScope class.
*
* Revision 1.5 2000/04/28 16:50:53 steve
* Catch memory word parameters to tasks.
*
* Revision 1.4 2000/04/10 05:26:06 steve
* All events now use the NetEvent class.
*
* Revision 1.3 2000/03/11 03:25:52 steve
* Locate scopes in statements.
*
* Revision 1.2 2000/03/10 06:20:48 steve
* Handle defparam to partial hierarchical names.
*
* Revision 1.1 2000/03/08 04:36:53 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.
*
*/
+85 -2
View File
@@ -17,13 +17,79 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_expr.cc,v 1.7 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: net_expr.cc,v 1.10 2002/11/09 01:40:19 steve Exp $"
#endif
# include "config.h"
# include "netlist.h"
# include <iostream>
/*
* Create an add/sub node from the two operands. Make a best guess of
* the
*/
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
NetEConst* tmp;
/* Catch the special case that one of the operands is an
unsized constant number. If so, then we should set the
width of that number to the size of the other operand, plus
one. This expands the expression to account for the largest
possible result.
The set_width applied to a constant value will only
truncate the constant so far as it can still hold its
logical value, so this is safe to do. */
if ( (tmp = dynamic_cast<NetEConst*>(r))
&& (! tmp->has_width())
&& (tmp->expr_width() > l->expr_width()) ) {
unsigned target_width = l->expr_width() + 1;
r->set_width(target_width);
/* Note: This constant value will not gain a defined
with from this. Make sure. */
assert(! r->has_width() );
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
&& (! tmp->has_width())
&& (tmp->expr_width() > r->expr_width()) ) {
unsigned target_width = r->expr_width() + 1;
l->set_width(target_width);
/* Note: This constant value will not gain a defined
with from this. Make sure. */
assert(! l->has_width() );
}
/* Now that we have the operand sizes the way we like, or as
good as we are going to get them, set the size of myself. */
if (r->expr_width() > l->expr_width()) {
expr_width(r->expr_width());
} else {
expr_width(l->expr_width());
}
cast_signed(l->has_sign() && r->has_sign());
}
NetEBAdd::~NetEBAdd()
{
}
NetEBAdd* NetEBAdd::dup_expr() const
{
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
right_->dup_expr());
return result;
}
NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
: parms_(cnt), repeat_(r)
{
@@ -43,6 +109,11 @@ NetEConcat::~NetEConcat()
delete parms_[idx];
}
bool NetEConcat::has_width() const
{
return true;
}
void NetEConcat::set(unsigned idx, NetExpr*e)
{
assert(idx < parms_.count());
@@ -111,7 +182,7 @@ unsigned NetEConcat::repeat() const
}
NetEParam::NetEParam()
: des_(0)
: des_(0), scope_(0)
{
}
@@ -171,6 +242,18 @@ bool NetESelect::set_width(unsigned w)
/*
* $Log: net_expr.cc,v $
* Revision 1.10 2002/11/09 01:40:19 steve
* Postpone parameter width check to evaluation.
*
* Revision 1.9 2002/11/06 02:25:13 steve
* No need to keep excess width from an
* unsigned constant value, if it can
* be trimmed safely.
*
* Revision 1.8 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.7 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
+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: net_link.cc,v 1.11 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
#endif
# include "config.h"
@@ -484,8 +484,24 @@ bool NexusSet::contains(const NexusSet&that) const
return true;
}
bool NexusSet::intersect(const NexusSet&that) const
{
for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) {
unsigned where = bsearch_(that[idx]);
if (where == nitems_)
continue;
if (items_[where] == that[idx])
return true;
}
return false;
}
/*
* $Log: net_link.cc,v $
* Revision 1.12 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.11 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
+13 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_input.cc,v 1.6 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.7 2002/11/16 05:45:41 steve Exp $"
#endif
# include "config.h"
@@ -250,11 +250,15 @@ NexusSet* NetCase::nex_input()
result->add(*tmp);
delete tmp;
assert(items_[idx].guard);
tmp = items_[idx].guard->nex_input();
assert(tmp);
result->add(*tmp);
delete tmp;
/* Usually, this is the guard expression. The default
case is special and is identified by a null
guard. The default guard obviously has no input. */
if (items_[idx].guard) {
tmp = items_[idx].guard->nex_input();
assert(tmp);
result->add(*tmp);
delete tmp;
}
}
return result;
@@ -358,6 +362,9 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* Revision 1.7 2002/11/16 05:45:41 steve
* Handle default: case in net_inputs for NetCase.
*
* Revision 1.6 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
+8 -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_nex_output.cc,v 1.5 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.6 2002/09/17 04:39:20 steve Exp $"
#endif
# include "config.h"
@@ -42,8 +42,10 @@ void NetAssignBase::nex_output(NexusSet&out)
assert(lsig);
assert(lval_->more == 0);
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
out.add(lsig->pin(idx).nexus());
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
unsigned off = lval_->get_loff() + idx;
out.add(lsig->pin(off).nexus());
}
}
@@ -85,6 +87,9 @@ void NetEvWait::nex_output(NexusSet&out)
/*
* $Log: net_nex_output.cc,v $
* Revision 1.6 2002/09/17 04:39:20 steve
* Account for part select in l-value.
*
* Revision 1.5 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+50 -13
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.19 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_scope.cc,v 1.21 2002/12/07 02:49:24 steve Exp $"
#endif
# include "config.h"
@@ -78,33 +78,63 @@ NetScope::~NetScope()
free(module_name_);
}
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr)
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr,
NetExpr*msb, NetExpr*lsb, bool signed_flag)
{
NetExpr*&ref = parameters_[key];
NetExpr* res = ref;
ref = expr;
param_expr_t&ref = parameters_[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.msb = msb;
ref.lsb = lsb;
ref.signed_flag = signed_flag;
return res;
}
/*
* Return false if this creates a new parameter.
*/
bool NetScope::replace_parameter(const string&key, NetExpr*expr)
{
bool flag = true;
param_expr_t&ref = parameters_[key];
NetExpr* res = ref.expr;
if (res) {
delete res;
} else {
flag = false;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
}
ref.expr = expr;
return flag;
}
NetExpr* NetScope::set_localparam(const string&key, NetExpr*expr)
{
NetExpr*&ref = localparams_[key];
NetExpr* res = ref;
ref = expr;
param_expr_t&ref = localparams_[key];
NetExpr* res = ref.expr;
ref.expr = expr;
ref.msb = 0;
ref.lsb = 0;
ref.signed_flag = false;
return res;
}
const NetExpr* NetScope::get_parameter(const string&key) const
{
map<string,NetExpr*>::const_iterator idx;
map<string,param_expr_t>::const_iterator idx;
idx = parameters_.find(key);
if (idx != parameters_.end())
return (*idx).second;
return (*idx).second.expr;
idx = localparams_.find(key);
if (idx != localparams_.end())
return (*idx).second;
return (*idx).second.expr;
return 0;
}
@@ -225,10 +255,10 @@ void NetScope::rem_event(NetEvent*ev)
}
NetEvent* NetScope::find_event(const hname_t&name)
NetEvent* NetScope::find_event(const char*name)
{
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
if (strcmp(cur->name(), name.peek_tail_name()) == 0)
if (strcmp(cur->name(), name) == 0)
return cur;
return 0;
@@ -402,6 +432,13 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* Revision 1.21 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.20 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.19 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+37 -36
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.199 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: netlist.cc,v 1.203 2002/11/09 00:25:27 steve Exp $"
#endif
# include "config.h"
@@ -592,11 +592,21 @@ Link& NetFF::pin_Aset()
return pin(3);
}
const Link& NetFF::pin_Aset() const
{
return pin(3);
}
Link& NetFF::pin_Aclr()
{
return pin(4);
}
const Link& NetFF::pin_Aclr() const
{
return pin(4);
}
Link& NetFF::pin_Sload()
{
return pin(5);
@@ -640,6 +650,16 @@ const Link& NetFF::pin_Q(unsigned w) const
return pin(pn);
}
void NetFF::aset_value(const verinum&val)
{
aset_value_ = val;
}
const verinum& NetFF::aset_value() const
{
return aset_value_;
}
/*
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
@@ -1687,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)
{
@@ -1736,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
@@ -2300,6 +2286,21 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.203 2002/11/09 00:25:27 steve
* Add dup_expr for user defined function calls.
*
* Revision 1.202 2002/11/06 02:25:13 steve
* No need to keep excess width from an
* unsigned constant value, if it can
* be trimmed safely.
*
* Revision 1.201 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.200 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.199 2002/09/01 03:01:48 steve
* Properly cast signedness of parameters with ranges.
*
+105 -8
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.260 2002/08/19 00:06:12 steve Exp $"
#ident "$Id: netlist.h,v 1.271 2002/12/07 02:49:24 steve Exp $"
#endif
/*
@@ -51,6 +51,7 @@ class NetProc;
class NetProcTop;
class NetRelease;
class NetScope;
class NetEvProbe;
class NetExpr;
class NetESignal;
class NetFuncDef;
@@ -296,6 +297,9 @@ class NexusSet {
// Return true if this set contains every nexus in that set.
bool contains(const NexusSet&that) const;
// Return true if this set contains any nexus in that set.
bool intersect(const NexusSet&that) const;
private:
Nexus**items_;
unsigned nitems_;
@@ -662,12 +666,20 @@ class NetFF : public NetNode {
const Link& pin_Clock() const;
const Link& pin_Enable() const;
const Link& pin_Aset() const;
const Link& pin_Aclr() const;
const Link& pin_Data(unsigned) const;
const Link& pin_Q(unsigned) const;
void aset_value(const verinum&val);
const verinum& aset_value() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
virtual void functor_node(Design*des, functor_t*fun);
private:
verinum aset_value_;
};
@@ -1214,10 +1226,18 @@ class NetProc : public LineInfo {
// process. Most process types are not.
virtual bool is_asynchronous();
// Return true if this represents the root of a synchronous
// process. Most process types are not.
virtual bool is_synchronous();
// synthesize as asynchronous logic, and return true.
virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
private:
@@ -1400,6 +1420,10 @@ class NetBlock : public NetProc {
bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
// This version of emit_recurse scans all the statements of
// the begin-end block sequentially. It is typically of use
// for sequential blocks.
@@ -1530,6 +1554,10 @@ class NetCondit : public NetProc {
bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
virtual bool emit_proc(struct target_t*) const;
virtual int match_proc(struct proc_match_t*);
virtual void dump(ostream&, unsigned ind) const;
@@ -1735,11 +1763,19 @@ class NetEvWait : public NetProc {
// process. This method checks.
virtual bool is_asynchronous();
// It is possible that this is the root of a synchronous
// process? This method checks.
virtual bool is_synchronous();
virtual void nex_output(NexusSet&out);
virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events);
virtual void dump(ostream&, unsigned ind) const;
private:
@@ -2116,13 +2152,20 @@ class NetProcTop : public LineInfo, public Attrib {
NetScope*scope();
const NetScope*scope() const;
/* Return true of this process represents combinational logic. */
/* Return true if this process represents combinational logic. */
bool is_asynchronous();
/* Create asynchronous logic from this thread and return true,
or return false if that cannot be done. */
bool synth_async(Design*des);
/* Return true if this process represents synchronous logic. */
bool is_synchronous();
/* Create synchronous logic from this thread and return true,
or return false if that cannot be done. */
bool synth_sync(Design*des);
void dump(ostream&, unsigned ind) const;
bool emit(struct target_t*tgt) const;
@@ -2157,8 +2200,9 @@ class NetProcTop : public LineInfo, public Attrib {
* n -- Logical inequality (!=)
* N -- Case inequality (!==)
* a -- Logical AND (&&)
* A -- Bitwise NAND (~&)
* o -- Logical OR (||)
* O -- Bit-wise NOR
* O -- Bit-wise NOR (~|)
* l -- Left shift (<<)
* r -- Right shift (>>)
* X -- Bitwise exclusive NOR (~^)
@@ -2384,6 +2428,7 @@ class NetEConcat : public NetExpr {
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
virtual NexusSet* nex_input();
virtual bool has_width() const;
virtual bool set_width(unsigned w);
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree();
@@ -2449,6 +2494,7 @@ class NetESelect : public NetExpr {
virtual bool set_width(unsigned w);
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree();
virtual NetESelect* dup_expr() const;
private:
@@ -2733,16 +2779,23 @@ class NetScope {
the scope. The return value from set_parameter is the
previous expression, if there was one. */
NetExpr* set_parameter(const string&name, NetExpr*val);
NetExpr* set_parameter(const string&name, NetExpr*val,
NetExpr*msb, NetExpr*lsb, bool signed_flag);
NetExpr* set_localparam(const string&name, NetExpr*val);
const NetExpr*get_parameter(const string&name) const;
/* These are used by defparam elaboration to replace the
expression with a new expression, without affecting the
range or signed_flag. Return false if the name does not
exist. */
bool replace_parameter(const string&name, NetExpr*val);
/* These methods set or access events that live in this
scope. */
void add_event(NetEvent*);
void rem_event(NetEvent*);
NetEvent*find_event(const hname_t&name);
NetEvent*find_event(const char*name);
/* These methods manage signals. The add_ and rem_signal
@@ -2837,8 +2890,14 @@ class NetScope {
signed char time_unit_, time_prec_;
map<string,NetExpr*>parameters_;
map<string,NetExpr*>localparams_;
struct param_expr_t {
NetExpr*expr;
NetExpr*msb;
NetExpr*lsb;
bool signed_flag;
};
map<string,param_expr_t>parameters_;
map<string,param_expr_t>localparams_;
NetEvent *events_;
NetNet *signals_;
@@ -2938,7 +2997,7 @@ class Design {
NetScope* find_task(const hname_t&key);
// Events
NetEvent* find_event(NetScope*scope, const hname_t path);
NetEvent* find_event(NetScope*scope, const hname_t&path);
// NODES
void add_node(NetNode*);
@@ -3026,6 +3085,44 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* Revision 1.271 2002/12/07 02:49:24 steve
* Named event triggers can take hierarchical names.
*
* Revision 1.270 2002/12/05 02:14:33 steve
* Support bit select in constant expressions.
*
* Revision 1.269 2002/11/09 01:40:19 steve
* Postpone parameter width check to evaluation.
*
* Revision 1.268 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
*
* Revision 1.267 2002/10/23 01:47:17 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.266 2002/10/21 01:42:08 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.265 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.264 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.263 2002/09/26 01:13:14 steve
* Synthesize async set/reset is certain cases.
*
* Revision 1.262 2002/09/16 00:30:33 steve
* Add to synth2 support for synthesis of
* synchronous logic. This includes DFF enables
* modeled by if/then/else.
*
* Revision 1.261 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.260 2002/08/19 00:06:12 steve
* Allow release to handle removal of target net.
*
+25 -11
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.159 2002/09/01 03:01:48 steve Exp $"
#ident "$Id: parse.y,v 1.168 2002/12/10 05:49:51 steve Exp $"
#endif
# include "config.h"
@@ -33,6 +33,13 @@ extern void lex_end_table();
static svector<PExpr*>* active_range = 0;
static bool active_signed = false;
/* Later version of bison (including 1.35) will not compile in stack
extension if the output is compiled with C++ and either the YYSTYPE
or YYLTYPE are provided by the source code. However, I can get the
old behavior back by defining these symbols. */
# define YYSTYPE_IS_TRIVIAL 1
# define YYLTYPE_IS_TRIVIAL 1
/*
* These are some common strength pairs that are used as defaults when
* the user is not otherwise specific.
@@ -115,7 +122,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%token K_notif1 K_or K_output K_parameter K_pmos K_posedge K_primitive
%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime
%token K_reg K_release K_repeat
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalered
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalared
%token K_signed K_small K_specify
%token K_specparam K_strong0 K_strong1 K_supply0 K_supply1 K_table K_task
%token K_time K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand
@@ -551,11 +558,11 @@ dr_strength1
;
event_control
: '@' IDENTIFIER
{ PEIdent*tmpi = new PEIdent(hname_t($2));
: '@' identifier
{ PEIdent*tmpi = new PEIdent(*$2);
tmpi->set_file(@2.text);
tmpi->set_lineno(@2.first_line);
delete[]$2;
delete $2;
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
PEventStatement*tmps = new PEventStatement(tmpe);
tmps->set_file(@1.text);
@@ -736,6 +743,12 @@ expression
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NAND expression
{ PEBinary*tmp = new PEBinary('A', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NOR expression
{ PEBinary*tmp = new PEBinary('O', $1, $3);
tmp->set_file(@2.text);
@@ -889,7 +902,7 @@ expr_primary
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
$$ = tmp;
delete $1
delete $1;
}
| identifier '[' expression ']'
{ PEIdent*tmp = new PEIdent(*$1);
@@ -1678,7 +1691,7 @@ localparam_assign_list
/* The parameters of a module instance can be overridden by writing
a list of expressions in a syntax much line a delay list. (The
a list of expressions in a syntax much like a delay list. (The
difference being the list can have any length.) The pform that
attaches the expression list to the module checks that the
expressions are constant.
@@ -2078,6 +2091,7 @@ specify_item_list
specify_edge_path_decl
: specify_edge_path '=' '(' specify_delay_value_list ')'
| specify_edge_path '=' delay_value_simple
;
specify_edge_path
@@ -2133,9 +2147,9 @@ specparam
delete $5;
delete $7;
}
| PATHPULSE_IDENTIFIER '=' '(' expression ')'
| PATHPULSE_IDENTIFIER '=' expression
{ delete $1;
delete $4;
delete $3;
}
| PATHPULSE_IDENTIFIER '=' '(' expression ',' expression ')'
{ delete $1;
@@ -2309,8 +2323,8 @@ statement
delete $2;
$$ = tmp;
}
| K_TRIGGER IDENTIFIER ';'
{ PTrigger*tmp = new PTrigger(hname_t($2));
| K_TRIGGER identifier ';'
{ PTrigger*tmp = new PTrigger(*$2);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
delete $2;
+9 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: parse_misc.h,v 1.5 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: parse_misc.h,v 1.6 2002/11/03 20:36:53 steve Exp $"
#endif
# include <list>
@@ -38,6 +38,11 @@ struct vlltype {
const char*text;
};
# define YYLTYPE vlltype
/* This for compatibility with new and older bison versions. */
#ifndef yylloc
# define yylloc VLlloc
#endif
extern YYLTYPE yylloc;
/*
@@ -53,6 +58,9 @@ extern unsigned error_count, warn_count;
/*
* $Log: parse_misc.h,v $
* Revision 1.6 2002/11/03 20:36:53 steve
* Support old/new bison yylloc.
*
* Revision 1.5 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+7 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.76 2002/08/19 02:39:17 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.77 2002/10/19 22:59:49 steve Exp $"
#endif
# include "config.h"
@@ -712,6 +712,8 @@ void Module::dump(ostream&out) const
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << " parameter ";
if ((*cur).second.signed_flag)
out << "signed ";
if ((*cur).second.msb)
out << "[" << *(*cur).second.msb << ":"
<< *(*cur).second.lsb << "] ";
@@ -846,6 +848,10 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.77 2002/10/19 22:59:49 steve
* Redo the parameter vector support to allow
* parameter names in range expressions.
*
* Revision 1.76 2002/08/19 02:39:17 steve
* Support parameters with defined ranges.
*
+27 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: set_width.cc,v 1.23 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: set_width.cc,v 1.25 2002/11/13 03:03:08 steve Exp $"
#endif
# include "config.h"
@@ -193,9 +193,22 @@ bool NetEBShift::set_width(unsigned w)
{
bool flag = true;
left_->set_width(w);
if (left_->expr_width() < w)
left_ = pad_to_width(left_, w);
switch (op()) {
case 'l':
left_->set_width(w);
if (left_->expr_width() < w)
left_ = pad_to_width(left_, w);
break;
case 'r':
if (left_->expr_width() < w)
left_ = pad_to_width(left_, w);
break;
default:
assert(0);
}
expr_width(left_->expr_width());
flag = expr_width() == w;
@@ -238,7 +251,7 @@ bool NetEConst::set_width(unsigned w)
if (value_.has_sign())
pad = value_.get(value_.len()-1);
verinum tmp (verinum::V0, w);
verinum tmp (verinum::V0, w, has_width());
for (unsigned idx = 0 ; idx < value_.len() ; idx += 1)
tmp.set(idx, value_[idx]);
for (unsigned idx = value_.len() ; idx < w ; idx += 1)
@@ -259,7 +272,7 @@ bool NetEConst::set_width(unsigned w)
if (value_[idx] != verinum::V0)
use_w = idx+1;
verinum tmp (verinum::V0, use_w);
verinum tmp (verinum::V0, use_w, has_width());
for (unsigned idx = 0 ; idx < use_w ; idx += 1)
tmp.set(idx, value_[idx]);
@@ -357,6 +370,14 @@ bool NetEUReduce::set_width(unsigned w)
/*
* $Log: set_width.cc,v $
* Revision 1.25 2002/11/13 03:03:08 steve
* Do not truncate high bits of right shift.
*
* Revision 1.24 2002/11/06 02:25:13 steve
* No need to keep excess width from an
* unsigned constant value, if it can
* be trimmed safely.
*
* Revision 1.23 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+1 -1
View File
@@ -1,7 +1,7 @@
PKG="IVLver"
NAME="verilog"
ARCH="sparc"
VERSION="0.6"
VERSION="0.7"
CATEGORY="application"
VENDOR="Icarus.com"
EMAIL="[email protected]"
+5 -10
View File
@@ -1,18 +1,13 @@
i pkginfo=./pkginfo
d none bin 0755 bin bin
f none bin/iverilog 0755 bin bin
f none bin/iverilog-vpi 0755 bin bin
f none bin/vvp 0755 bin bin
d none include 0755 bin bin
f none include/acc_user.h 0644 bin bin
f none include/ivl_target.h 0644 bin bin
f none include/vpi_priv.h 0644 bin bin
f none include/veriuser.h 0644 bin bin
f none include/vpi_user.h 0644 bin bin
f none include/vvm.h 0644 bin bin
f none include/vvm_calltf.h 0644 bin bin
f none include/vvm_func.h 0644 bin bin
f none include/vvm_gates.h 0644 bin bin
f none include/vvm_nexus.h 0644 bin bin
f none include/vvm_signal.h 0644 bin bin
f none include/vvm_thread.h 0644 bin bin
d none lib 0755 bin bin
d none lib/ivl 0755 bin bin
f none lib/ivl/fpga.tgt 0644 bin bin
@@ -22,10 +17,10 @@ f none lib/ivl/ivlpp 0755 bin bin
f none lib/ivl/null.tgt 0644 bin bin
f none lib/ivl/system.vpi 0644 bin bin
f none lib/ivl/vvp.tgt 0644 bin bin
f none lib/libveriuser.a 0644 bin bin
f none lib/libvpi.a 0644 bin bin
f none lib/libvpip.a 0644 bin bin
f none lib/libvvm.a 0644 bin bin
d none man 0755 bin bin
d none man/man1 0755 bin bin
f none man/man1/iverilog.1 0644 bin bin
f none man/man1/iverilog-vpi.1 0644 bin bin
f none man/man1/vvp.1 0644 bin bin
+81
View File
@@ -0,0 +1,81 @@
/*
* 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: sync.cc,v 1.3 2002/09/24 00:58:35 steve Exp $"
#endif
# include "config.h"
# include "functor.h"
# include "netlist.h"
# include <assert.h>
/*
* Most process statements are not roots of synchronous logic.
*/
bool NetProc::is_synchronous()
{
return false;
}
bool NetEvWait::is_synchronous()
{
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
NetEvent*ev = events_[idx];
if (ev->nprobe() == 0)
return false;
for (unsigned pdx = 0 ; pdx < ev->nprobe() ; pdx += 1) {
NetEvProbe*pr = ev->probe(pdx);
/* No level sensitive clocks. */
if (pr->edge() == NetEvProbe::ANYEDGE)
return false;
}
}
/* So we know that there is a clock source. Check that the
input to the storage is asynchronous. */
return true; //statement_->is_asynchronous();
}
bool NetProcTop::is_synchronous()
{
if (type_ == NetProcTop::KINITIAL)
return false;
return statement_->is_synchronous();
}
/*
* $Log: sync.cc,v $
* Revision 1.3 2002/09/24 00:58:35 steve
* More detailed check of process edge events.
*
* Revision 1.2 2002/09/16 21:55:06 steve
* Reject multiple probes on synchronous logic.
*
* Revision 1.1 2002/09/16 00:30:33 steve
* Add to synth2 support for synthesis of
* synchronous logic. This includes DFF enables
* modeled by if/then/else.
*
*/
+469 -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: synth2.cc,v 1.8 2002/08/18 22:07:16 steve Exp $"
#ident "$Id: synth2.cc,v 1.20 2002/11/09 23:29:29 steve Exp $"
#endif
# include "config.h"
@@ -27,6 +27,26 @@
# include "compiler.h"
# include <assert.h>
bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
{
return false;
}
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events)
{
if (events.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
des->errors += 1;
}
/* Synthesize the input to the DFF. */
return synth_async(des, scope, nex_map, nex_out);
}
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
{
unsigned idx = 0;
@@ -57,11 +77,12 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
assert(lsig);
assert(lval_->more == 0);
assert(lsig->pin_count() == nex_map->pin_count());
assert(lval_->lwidth() == nex_map->pin_count());
assert(nex_map->pin_count() <= rsig->pin_count());
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus());
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
unsigned off = lval_->get_loff()+idx;
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
connect(nex_out->pin(ptr), rsig->pin(idx));
}
@@ -85,27 +106,33 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
do {
cur = cur->next_;
/* Create a temporary nex_out for the substatement. */
/* Create a temporary nex_map for the substatement. */
NexusSet tmp_set;
cur->nex_output(tmp_set);
NetNet*tmp_out = new NetNet(scope, "tmp", NetNet::WIRE,
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_out->pin(idx));
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_map->pin(idx));
bool ok_flag = cur->synth_async(des, scope, tmp_out, tmp_out);
/* Create also a temporary net_out to collect the
output. */
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
tmp_set.count());
bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out);
flag = flag && ok_flag;
if (ok_flag == false)
continue;
/* Use tne nex_map to link up the output from the
/* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */
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));
}
delete tmp_map;
delete tmp_out;
} while (cur != last_);
@@ -201,6 +228,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
NetNet*ssig = expr_->synthesize(des);
assert(ssig);
if (if_ == 0)
return false;
if (else_ == 0) {
cerr << get_line() << ": error: Asynchronous if statement"
<< " is missing the else clause." << endl;
return false;
}
assert(if_ != 0);
assert(else_ != 0);
@@ -241,12 +276,6 @@ bool NetEvWait::synth_async(Design*des, NetScope*scope,
return statement_->synth_async(des, scope, nex_map, nex_out);
}
bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out)
{
return false;
}
bool NetProcTop::synth_async(Design*des)
{
NexusSet nex_set;
@@ -263,6 +292,379 @@ bool NetProcTop::synth_async(Design*des)
return flag;
}
/*
* This method is called when a block is encountered near the surface
* of a synchronous always statement. For example, this code will be
* invoked for input like this:
*
* always @(posedge clk...) begin
* <statement1>
* <statement2>
* ...
* end
*
* This needs to be split into a DFF bank for each statement, because
* the statements may each infer different reset and enable signals.
*/
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events_in)
{
if (last_ == 0)
return true;
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_;
do {
cur = cur->next_;
/* Create a temporary nex_map for the substatement. */
NexusSet tmp_set;
cur->nex_output(tmp_set);
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
connect(tmp_set[idx], tmp_map->pin(idx));
/* Create also a temporary net_out to collect the
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());
verinum tmp_aset = ff->aset_value();
/* Create a new DFF to handle this part of the begin-end
block. Connect this NetFF to the associated pins of
the existing wide NetFF device. While I'm at it, also
copy the aset_value bits for the new ff device. */
NetFF*ff2 = new NetFF(scope, scope->local_hsymbol().c_str(),
tmp_out->pin_count());
des->add_node(ff2);
verinum aset_value2 (verinum::V1, ff2->width());
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(ff->pin_Data(ptr), ff2->pin_Data(idx));
connect(ff->pin_Q(ptr), ff2->pin_Q(idx));
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());
if (ff->pin_Aset().is_linked())
connect(ff->pin_Aset(), ff2->pin_Aset());
if (ff->pin_Clock().is_linked())
connect(ff->pin_Clock(), ff2->pin_Clock());
if (ff->pin_Enable().is_linked())
connect(ff->pin_Enable(),ff2->pin_Enable());
/* Remember to store the aset value into the new FF. If
this leads to an Aset value of 0 (and Aclr is not
otherwise used) then move the Aset input to Aclr. */
if (tmp_aset.len() == ff->width()) {
if ((aset_value2.as_ulong() == 0)
&& ff2->pin_Aset().is_linked()
&& !ff2->pin_Aclr().is_linked()) {
connect(ff2->pin_Aclr(), ff2->pin_Aset());
ff2->pin_Aset().unlink();
} else {
ff2->aset_value(aset_value2);
}
}
/* Now go on with the synchronous synthesis for this
subset of the statement. */
bool ok_flag = cur->synth_sync(des, scope, ff2, tmp_map,
tmp_out, events_in);
flag = flag && ok_flag;
if (ok_flag == false)
continue;
/* Use the nex_map to link up the output from the
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]);
if (ptr < nex_out->pin_count())
connect(nex_out->pin(ptr), tmp_out->pin(idx));
}
delete tmp_map;
delete tmp_out;
} 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. */
delete ff;
return flag;
}
/*
* This method handles the case where I find a conditional near the
* surface of a synchronous thread. This conditional can be a CE or an
* asynchronous set/reset, depending on whether the pin of the
* expression is connected to an event, or not.
*/
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);
/* Try first to turn the ce into an asynchronous set/reset
input. If the ce is linked to a probe, then that probe is a
set/reset input. */
for (unsigned idx = 0 ; idx < events_in.count() ; idx += 1) {
NetEvProbe*ev = events_in[idx];
if (connected(ce->pin(0), ev->pin(0))) {
bool flag = true;
assert(ev->edge() == NetEvProbe::POSEDGE);
/* Synthesize the true clause to figure out what
kind of set/reset we have. */
NetNet*asig = new NetNet(scope, scope->local_hsymbol(),
NetNet::WIRE, nex_map->pin_count());
asig->local_flag(true);
flag = if_->synth_async(des, scope, nex_map, asig) && flag;
assert(asig->pin_count() == ff->width());
/* Collect the set/reset value into a verinum. If
this turns out to be entirely 0 values, then
use the Aclr input. Otherwise, use the Aset
input and save the set value. */
verinum tmp (verinum::V0, ff->width());
for (unsigned bit = 0 ; bit < ff->width() ; bit += 1) {
assert(asig->pin(bit).nexus()->drivers_constant());
tmp.set(bit, asig->pin(bit).nexus()->driven_value());
}
assert(tmp.is_defined());
if (tmp.as_ulong() == 0) {
connect(ff->pin_Aclr(), ce->pin(0));
} else {
connect(ff->pin_Aset(), ce->pin(0));
ff->aset_value(tmp);
}
delete asig;
assert(events_in.count() == 1);
return else_->synth_sync(des, scope, ff, nex_map,
nex_out, svector<NetEvProbe*>(0))
&& flag;
}
}
/* Failed to find an asynchronous set/reset, so any events
input are probably in error. */
if (events_in.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
des->errors += 1;
}
/* If this is an if/then/else, then it is likely a
combinational if, and I should synthesize it that way. */
if (if_ && else_) {
return synth_async(des, scope, nex_map, nex_out);
}
assert(if_);
assert(!else_);
/* 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;
return true;
}
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events_in)
{
if (events_in.count() > 0) {
cerr << get_line() << ": error: Events are unaccounted"
<< " for in process synthesis." << endl;
des->errors += 1;
}
assert(events_in.count() == 0);
/* This can't be other then one unless there are named events,
which I cannot synthesize. */
assert(nevents_ == 1);
NetEvent*ev = events_[0];
assert(ev->nprobe() >= 1);
svector<NetEvProbe*>events (ev->nprobe() - 1);
/* Get the input set from the substatement. This will be used
to figure out which of the probes in the clock. */
NexusSet*statement_input = statement_ -> nex_input();
/* Search for a clock input. The clock input is the edge event
that is not also an input to the substatement. */
NetEvProbe*pclk = 0;
unsigned event_idx = 0;
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
NetEvProbe*tmp = ev->probe(idx);
assert(tmp->pin_count() == 1);
NexusSet tmp_nex;
tmp_nex .add( tmp->pin(0).nexus() );
if (! statement_input ->contains(tmp_nex)) {
if (pclk != 0) {
cerr << get_line() << ": error: Too many "
<< "clocks for synchronous logic." << endl;
cerr << get_line() << ": : Perhaps an"
<< " asynchronous set/reset is misused?" << endl;
des->errors += 1;
}
pclk = tmp;
} else {
events[event_idx++] = tmp;
}
}
if (pclk == 0) {
cerr << get_line() << ": error: None of the edges"
<< " are valid clock inputs." << endl;
cerr << get_line() << ": : Perhaps the clock"
<< " is read by a statement or expression?" << endl;
return false;
}
connect(ff->pin_Clock(), pclk->pin(0));
if (pclk->edge() == NetEvProbe::NEGEDGE)
ff->attribute("Clock:LPM_Polarity", verinum("INVERT"));
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope, ff,
nex_map, nex_out, events);
return flag;
}
bool NetProcTop::synth_sync(Design*des)
{
NexusSet nex_set;
statement_->nex_output(nex_set);
NetFF*ff = new NetFF(scope(), scope()->local_hsymbol().c_str(),
nex_set.count());
des->add_node(ff);
ff->attribute("LPM_FFType", verinum("DFF"));
/* The D inputs to the DFF device will receive the output from
the statments of the process. */
NetNet*nex_d = new NetNet(scope(), scope()->local_hsymbol().c_str(),
NetNet::WIRE, nex_set.count());
nex_d->local_flag(true);
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_d->pin(idx), ff->pin_Data(idx));
}
/* The Q outputs of the DFF will connect to the actual outputs
of the process. Thus, the DFF will be between the outputs
of the process and the outputs of the substatement. */
NetNet*nex_q = new NetNet(scope(), "tmpq", NetNet::WIRE,
nex_set.count());
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
connect(nex_set[idx], nex_q->pin(idx));
connect(nex_q->pin(idx), ff->pin_Q(idx));
}
/* Synthesize the input to the DFF. */
bool flag = statement_->synth_sync(des, scope(), ff,
nex_q, nex_d,
svector<NetEvProbe*>());
delete nex_q;
return flag;
}
class synth2_f : public functor_t {
public:
@@ -281,6 +683,18 @@ void synth2_f::process(class Design*des, class NetProcTop*top)
if (top->attribute("ivl_synthesis_off").as_ulong() != 0)
return;
if (top->is_synchronous()) do {
bool flag = top->synth_sync(des);
if (! flag) {
cerr << top->get_line() << ": error: "
<< "Unable to synthesize synchronous process." << endl;
des->errors += 1;
return;
}
des->delete_process(top);
return;
} while (0);
if (! top->is_asynchronous()) {
bool synth_error_flag = false;
if (top->attribute("ivl_combinational").as_ulong() != 0) {
@@ -324,6 +738,45 @@ 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.
*
* Revision 1.16 2002/10/21 01:42:09 steve
* Synthesizer support for synchronous begin-end blocks.
*
* Revision 1.15 2002/10/20 19:19:37 steve
* Handle conditional error cases better.
*
* Revision 1.14 2002/09/26 03:42:10 steve
* Remove excess debug messages.
*
* Revision 1.13 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.12 2002/09/26 01:13:14 steve
* Synthesize async set/reset is certain cases.
*
* Revision 1.11 2002/09/24 00:58:35 steve
* More detailed check of process edge events.
*
* Revision 1.10 2002/09/17 04:40:28 steve
* Connect output of block to net_out, instead of statement outputs.
*
* Revision 1.9 2002/09/16 00:30:33 steve
* Add to synth2 support for synthesis of
* synchronous logic. This includes DFF enables
* modeled by if/then/else.
*
* Revision 1.8 2002/08/18 22:07:16 steve
* Detect temporaries in sequential block synthesis.
*
+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: t-dll-api.cc,v 1.86 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.88 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -540,6 +540,29 @@ extern "C" const char* ivl_lpm_basename(ivl_lpm_t net)
return basename(net->scope, net->name);
}
extern "C" ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net)
{
assert(net);
switch(net->type) {
case IVL_LPM_FF:
return net->u_.ff.aclr;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net)
{
assert(net);
switch(net->type) {
case IVL_LPM_FF:
return net->u_.ff.aset;
default:
assert(0);
return 0;
}
}
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
{
@@ -554,6 +577,18 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
}
}
extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.aset_value;
default:
assert(0);
return 0;
}
}
extern "C" ivl_scope_t ivl_lpm_define(ivl_lpm_t net)
{
assert(net);
@@ -1550,6 +1585,13 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* 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.
*
* Revision 1.87 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.86 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+37 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-expr.cc,v 1.28 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.29 2002/10/23 01:47:17 steve Exp $"
#endif
# include "config.h"
@@ -103,6 +103,38 @@ void dll_target::mul_expr_by_const_(long val)
expr_ = tmps;
}
ivl_expr_t dll_target::expr_from_value_(const verinum&val)
{
ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr);
unsigned idx;
char*bits;
expr->type_ = IVL_EX_NUMBER;
expr->width_= val.len();
expr->signed_ = val.has_sign()? 1 : 0;
expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_);
for (idx = 0 ; idx < expr->width_ ; idx += 1)
switch (val.get(idx)) {
case verinum::V0:
bits[idx] = '0';
break;
case verinum::V1:
bits[idx] = '1';
break;
case verinum::Vx:
bits[idx] = 'x';
break;
case verinum::Vz:
bits[idx] = 'z';
break;
default:
assert(0);
}
return expr;
}
void dll_target::expr_binary(const NetEBinary*net)
{
assert(expr_ == 0);
@@ -458,6 +490,10 @@ void dll_target::expr_unary(const NetEUnary*net)
/*
* $Log: t-dll-expr.cc,v $
* 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.
*
* Revision 1.28 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+52 -9
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.95 2002/08/12 01:35:00 steve Exp $"
#ident "$Id: t-dll.cc,v 1.100 2002/11/05 02:12:35 steve Exp $"
#endif
# include "config.h"
@@ -36,32 +36,33 @@
inline ivl_dll_t ivl_dlopen(const char *name)
{
return (ivl_dll_t) LoadLibrary(name);
ivl_dll_t res = (ivl_dll_t) LoadLibrary(name);
return res;
}
inline void * ivl_dlsym(ivl_dll_t dll, const char *nm)
{
FARPROC sym;
return GetProcAddress((HMODULE)dll, nm);
FARPROC sym;
return (void*)GetProcAddress((HMODULE)dll, nm);
}
inline void ivl_dlclose(ivl_dll_t dll)
{
FreeLibrary((HMODULE)dll);
FreeLibrary((HMODULE)dll);
}
const char *dlerror(void)
{
static char msg[255];
static char msg[256];
unsigned long err = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
0,
sizeof(msg) - 1,
NULL
);
return msg;
@@ -448,6 +449,7 @@ bool dll_target::start_design(const Design*des)
dll_path_ = des->get_flag("DLL");
dll_ = ivl_dlopen(dll_path_.c_str());
if (dll_ == 0) {
cerr << "error: " << dll_path_ << " failed to load." << endl;
cerr << dll_path_ << ": " << dlerror() << endl;
return false;
}
@@ -1361,6 +1363,31 @@ void dll_target::lpm_ff(const NetFF*net)
obj->u_.ff.we = 0;
}
if (net->pin_Aclr().is_linked()) {
nex = net->pin_Aclr().nexus();
assert(nex->t_cookie());
obj->u_.ff.aclr = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.aclr);
nexus_lpm_add(obj->u_.ff.aclr, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
} else {
obj->u_.ff.aclr = 0;
}
if (net->pin_Aset().is_linked()) {
nex = net->pin_Aset().nexus();
assert(nex->t_cookie());
obj->u_.ff.aset = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.aset);
nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
verinum tmp = net->aset_value();
obj->u_.ff.aset_value = expr_from_value_(tmp);
} else {
obj->u_.ff.aset = 0;
obj->u_.ff.aset_value = 0;
}
if (obj->u_.ff.width == 1) {
nex = net->pin_Q(0).nexus();
assert(nex->t_cookie());
@@ -1954,6 +1981,22 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.100 2002/11/05 02:12:35 steve
* Fix the call to FormatMessage under Windows.
*
* Revision 1.99 2002/11/03 22:44:19 steve
* Cast for gcc convenience.
*
* Revision 1.98 2002/11/03 20:47:23 steve
* Slightly more verbose load fail message.
*
* Revision 1.97 2002/10/23 01:47:18 steve
* Fix synth2 handling of aset/aclr signals where
* flip-flops are split by begin-end blocks.
*
* Revision 1.96 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.95 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
+13 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.93 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: t-dll.h,v 1.95 2002/10/23 01:47:17 steve Exp $"
#endif
# include "target.h"
@@ -154,6 +154,8 @@ struct dll_target : public target_t, public expr_scan_t {
void sub_off_from_expr_(long);
void mul_expr_by_const_(long);
static ivl_expr_t expr_from_value_(const verinum&that);
};
/*
@@ -267,6 +269,8 @@ struct ivl_lpm_s {
unsigned short swid; // ram only
ivl_nexus_t clk;
ivl_nexus_t we;
ivl_nexus_t aclr;
ivl_nexus_t aset;
union {
ivl_nexus_t*pins;
ivl_nexus_t pin;
@@ -280,6 +284,7 @@ struct ivl_lpm_s {
ivl_nexus_t pin;
} s;
ivl_memory_t mem; // ram only
ivl_expr_t aset_value;
} ff;
struct ivl_lpm_mux_s {
@@ -617,6 +622,13 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* 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.
*
* Revision 1.94 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.93 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
+68 -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: d-generic-edif.c,v 1.9 2002/08/12 01:35:02 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);
}
}
}
}
@@ -394,12 +439,28 @@ const struct device_s d_generic_edif = {
0,
0,
0,
0
0,
0, /* show_add */
0, /* show_sub */
0, /* show_shiftl */
0 /* show_shiftr */
};
/*
* $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.
*
* Revision 1.9 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+10 -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: d-generic.c,v 1.11 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: d-generic.c,v 1.12 2002/10/28 02:05:56 steve Exp $"
#endif
# include "device.h"
@@ -503,13 +503,21 @@ const struct device_s d_generic = {
generic_show_dff,
generic_show_cmp_eq,
generic_show_cmp_eq,
0, /* ge not implemented */
generic_show_mux,
generic_show_add
generic_show_add,
0, /* subtract not implemented */
0,
0
};
/*
* $Log: d-generic.c,v $
* Revision 1.12 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.11 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+914 -75
View File
File diff suppressed because it is too large Load Diff
+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: device.h,v 1.9 2002/08/12 01:35:02 steve Exp $"
#ident "$Id: device.h,v 1.10 2002/10/28 02:05:56 steve Exp $"
#endif
# include <ivl_target.h>
@@ -50,10 +50,15 @@ struct device_s {
/* These methods show various comparators */
void (*show_cmp_eq)(ivl_lpm_t net);
void (*show_cmp_ne)(ivl_lpm_t net);
void (*show_cmp_ge)(ivl_lpm_t net);
/* This method draws MUX devices */
void (*show_mux)(ivl_lpm_t net);
/* This method draws ADD devices */
void (*show_add)(ivl_lpm_t net);
void (*show_sub)(ivl_lpm_t net);
/* These methods draw SHIFT devices */
void (*show_shiftl)(ivl_lpm_t net);
void (*show_shiftr)(ivl_lpm_t net);
};
/*
@@ -68,6 +73,10 @@ extern device_t device_from_arch(const char*arch);
/*
* $Log: device.h,v $
* Revision 1.10 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.9 2002/08/12 01:35:02 steve
* conditional ident string using autoconfig.
*
+41 -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: gates.c,v 1.9 2002/08/12 01:35:03 steve Exp $"
#ident "$Id: gates.c,v 1.10 2002/10/28 02:05:56 steve Exp $"
#endif
# include <ivl_target.h>
@@ -42,6 +42,15 @@ static void show_gate_lpm(ivl_lpm_t net)
device->show_add(net);
break;
case IVL_LPM_SUB:
if (device->show_sub == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SUB not supported"
" by this target.\n");
return;
}
device->show_sub(net);
break;
case IVL_LPM_CMP_EQ:
if (device->show_cmp_eq == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_EQ not supported"
@@ -60,6 +69,15 @@ static void show_gate_lpm(ivl_lpm_t net)
device->show_cmp_ne(net);
break;
case IVL_LPM_CMP_GE:
if (device->show_cmp_ge == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GE not supported"
" by this target.\n");
return;
}
device->show_cmp_ge(net);
break;
case IVL_LPM_FF:
if (device->show_dff == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_FF not supported"
@@ -78,6 +96,24 @@ static void show_gate_lpm(ivl_lpm_t net)
device->show_mux(net);
break;
case IVL_LPM_SHIFTL:
if (device->show_shiftl == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTL not supported"
" by this target.\n");
return;
}
device->show_shiftl(net);
break;
case IVL_LPM_SHIFTR:
if (device->show_shiftr == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTR not supported"
" by this target.\n");
return;
}
device->show_shiftr(net);
break;
default:
fprintf(stderr, "fpga.tgt: unknown LPM type %u\n",
ivl_lpm_type(net));
@@ -100,6 +136,10 @@ int show_scope_gates(ivl_scope_t net, void*x)
/*
* $Log: gates.c,v $
* Revision 1.10 2002/10/28 02:05:56 steve
* Add Virtex code generators for left shift,
* subtraction, and GE comparators.
*
* Revision 1.9 2002/08/12 01:35:03 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.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
+38 -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: stub.c,v 1.66 2002/08/12 01:35:03 steve Exp $"
#ident "$Id: stub.c,v 1.70 2002/10/23 01:45:24 steve Exp $"
#endif
# include "config.h"
@@ -182,8 +182,25 @@ static void show_lpm(ivl_lpm_t net)
fprintf(out, " LPM_FF %s: <width=%u>\n",
ivl_lpm_name(net), width);
fprintf(out, " clk: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)));
if (ivl_lpm_enable(net))
fprintf(out, " clk: %s CE: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)),
ivl_nexus_name(ivl_lpm_enable(net)));
else
fprintf(out, " clk: %s\n",
ivl_nexus_name(ivl_lpm_clk(net)));
if (ivl_lpm_async_clr(net))
fprintf(out, " Aclr: %s\n",
ivl_nexus_name(ivl_lpm_async_clr(net)));
if (ivl_lpm_async_set(net)) {
fprintf(out, " Aset: %s\n",
ivl_nexus_name(ivl_lpm_async_set(net)));
if (ivl_lpm_aset_value(net))
show_expression(ivl_lpm_aset_value(net), 10);
}
for (idx = 0 ; idx < width ; idx += 1)
fprintf(out, " Data %u: %s\n", idx,
@@ -476,6 +493,8 @@ static void show_signal(ivl_signal_t net)
case IVL_SIT_SUPPLY1:
type = "supply1";
break;
default:
break;
}
switch (ivl_signal_port(net)) {
@@ -491,6 +510,9 @@ static void show_signal(ivl_signal_t net)
case IVL_SIP_INOUT:
port = "inout ";
break;
case IVL_SIP_NONE:
break;
}
fprintf(out, " %s %s %s[%u] %s\n", type, sign, port,
@@ -706,6 +728,19 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* 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.
*
* Revision 1.69 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.68 2002/09/18 03:33:10 steve
* Fix switch case warnings.
*
* Revision 1.67 2002/09/16 00:28:25 steve
* Display FF enables.
*
* Revision 1.66 2002/08/12 01:35:03 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.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.10 2002/08/12 00:27:10 steve Exp $"
#ident "$Id: Makefile.in,v 1.12 2002/11/05 02:14:41 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 vvp_process.o vvp_scope.o
O = vvp.o draw_mux.o eval_expr.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
+346 -229
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_expr.c,v 1.74 2002/09/01 01:42:34 steve Exp $"
#ident "$Id: eval_expr.c,v 1.86 2002/11/22 00:01:50 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -28,71 +28,8 @@
# include <stdlib.h>
# include <assert.h>
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid);
static unsigned char allocation_map[0x10000/8];
static inline int peek_bit(unsigned addr)
{
unsigned bit = addr % 8;
addr /= 8;
return 1 & (allocation_map[addr] >> bit);
}
static inline void set_bit(unsigned addr)
{
unsigned bit = addr % 8;
addr /= 8;
allocation_map[addr] |= (1 << bit);
}
static inline void clr_bit(unsigned addr)
{
unsigned bit = addr % 8;
addr /= 8;
allocation_map[addr] &= ~(1 << bit);
}
/*
* This clears a vector that was previously allocated by
* allocate_vector. That is, it unmarks all the bits of the map that
* represent this vector.
*
* If the vector is based in one of 4 constant bit values, then there
* are no bits to clear. If the vector is based in the 4-8 result
* area, then someone is broken.
*/
void clr_vector(struct vector_info vec)
{
unsigned idx;
if (vec.base < 4)
return;
assert(vec.base >= 8);
for (idx = 0 ; idx < vec.wid ; idx += 1)
clr_bit(vec.base + idx);
}
unsigned short allocate_vector(unsigned short wid)
{
unsigned short base = 8;
unsigned short idx = 0;
while (idx < wid) {
assert((base + idx) < 0x10000);
if (peek_bit(base+idx)) {
base = base + idx + 1;
idx = 0;
} else {
idx += 1;
}
}
for (idx = 0 ; idx < wid ; idx += 1)
set_bit(base+idx);
return base;
}
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)
{
@@ -162,30 +99,44 @@ unsigned long get_number_immediate(ivl_expr_t ex)
return imm;
}
/*
* The STUFF_OK_XZ bit is true if the output is going to be further
* processed so that x and z values are equivilent. This may allow for
* new optimizations.
*/
static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
ivl_expr_t le,
ivl_expr_t re)
ivl_expr_t re,
int stuff_ok_flag)
{
unsigned wid;
struct vector_info lv;
unsigned long imm = get_number_immediate(re);
wid = ivl_expr_width(le);
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
switch (ivl_expr_opcode(exp)) {
case 'E': /* === */
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 6;
lv.wid = 1;
break;
case 'e': /* == */
/* If this is a single bit being compared to 1, and the
output doesn't care about x vs z, then just return
the value itself. */
if ((stuff_ok_flag&STUFF_OK_XZ) && (lv.wid == 1) && (imm == 1))
break;
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 4;
lv.wid = 1;
break;
@@ -193,16 +144,24 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
case 'N': /* !== */
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 6;
lv.wid = 1;
fprintf(vvp_out, " %%inv 6, 1;\n");
break;
case 'n': /* != */
/* If this is a single bit being compared to 0, and the
output doesn't care about x vs z, then just return
the value itself. */
if ((stuff_ok_flag&STUFF_OK_XZ) && (lv.wid == 1) && (imm == 0))
break;
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
lv.base, imm, wid);
clr_vector(lv);
if (lv.base >= 8)
clr_vector(lv);
lv.base = 4;
lv.wid = 1;
fprintf(vvp_out, " %%inv 4, 1;\n");
@@ -212,21 +171,39 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
assert(0);
}
/* In the special case that 47 bits are ok, and this really is
a single bit value, then we are done. */
if ((lv.wid == 1) && (ewid == 1) && (stuff_ok_flag&STUFF_OK_47))
return lv;
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
{ unsigned short base = allocate_vector(ewid);
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
lv.base = base;
lv.wid = ewid;
if (ewid > 1)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1);
if (lv.base < 8) {
unsigned short base = allocate_vector(ewid);
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
lv.base = base;
lv.wid = ewid;
if (ewid > 1)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1);
} else if (lv.wid < ewid) {
unsigned short base = allocate_vector(ewid);
clr_vector(lv);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", base,
lv.base, lv.wid);
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
base+lv.wid, ewid-lv.wid);
lv.base = base;
lv.wid = ewid;
}
return lv;
}
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
unsigned ewid,
int stuff_ok_flag)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
@@ -238,19 +215,19 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
if ((ivl_expr_type(re) == IVL_EX_ULONG)
&& (0 == (ivl_expr_uvalue(re) & ~0xffff)))
return draw_eq_immediate(exp, ewid, le, re);
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
if ((ivl_expr_type(re) == IVL_EX_NUMBER)
&& (! number_is_unknown(re))
&& number_is_immediate(re, 16))
return draw_eq_immediate(exp, ewid, le, re);
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
wid = ivl_expr_width(le);
if (ivl_expr_width(re) > wid)
wid = ivl_expr_width(re);
lv = draw_eval_expr_wid(le, wid);
rv = draw_eval_expr_wid(re, wid);
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&STUFF_OK_XZ);
switch (ivl_expr_opcode(exp)) {
case 'E': /* === */
@@ -316,6 +293,10 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
assert(0);
}
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
return lv;
}
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
@@ -339,7 +320,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid)
struct vector_info rv;
lv = draw_eval_expr(le);
lv = draw_eval_expr(le, STUFF_OK_XZ);
if ((lv.base >= 4) && (lv.wid > 1)) {
struct vector_info tmp;
@@ -351,7 +332,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid)
lv = tmp;
}
rv = draw_eval_expr(re);
rv = draw_eval_expr(re, STUFF_OK_XZ);
if ((rv.base >= 4) && (rv.wid > 1)) {
struct vector_info tmp;
clr_vector(rv);
@@ -411,7 +392,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
struct vector_info lv;
struct vector_info rv;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
/* if the left operand has width, then evaluate the single-bit
logical equivilent. */
@@ -425,7 +406,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
lv = tmp;
}
rv = draw_eval_expr_wid(re, wid);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
/* if the right operand has width, then evaluate the single-bit
logical equivilent. */
@@ -481,7 +462,9 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
return lv;
}
static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
unsigned wid,
int stuff_ok_flag)
{
ivl_expr_t le = ivl_expr_oper1(exp);
ivl_expr_t re = ivl_expr_oper2(exp);
@@ -495,8 +478,8 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
if (ivl_expr_width(re) > owid)
owid = ivl_expr_width(re);
lv = draw_eval_expr_wid(le, owid);
rv = draw_eval_expr_wid(re, owid);
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
switch (ivl_expr_opcode(exp)) {
case 'G':
@@ -532,6 +515,12 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
clr_vector(lv);
clr_vector(rv);
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
lv.base = 5;
lv.wid = wid;
return lv;
}
/* Move the result out out the 4-7 bit that the compare
uses. This is because that bit may be clobbered by other
expressions. */
@@ -555,8 +544,8 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
struct vector_info lv;
struct vector_info rv;
lv = draw_eval_expr_wid(le, wid);
rv = draw_eval_expr_wid(re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
/* The result goes into the left operand, and that is returned
as the result. The instructions do not allow the lv value
@@ -595,6 +584,16 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
lv.base, rv.base, wid);
break;
case 'A': /* NAND (~&) */
fprintf(vvp_out, " %%nand %u, %u, %u;\n",
lv.base, rv.base, wid);
break;
case 'O': /* NOR (~|) */
fprintf(vvp_out, " %%nor %u, %u, %u;\n",
lv.base, rv.base, wid);
break;
case 'X': /* exclusive nor (~^) */
fprintf(vvp_out, " %%xnor %u, %u, %u;\n",
lv.base, rv.base, wid);
@@ -654,7 +653,7 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
default: {
struct vector_info rv;
rv = draw_eval_expr(re);
rv = draw_eval_expr(re, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n",
rv.base, rv.wid);
clr_vector(rv);
@@ -662,15 +661,51 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
}
}
lv = draw_eval_expr_wid(le, wid);
switch (ivl_expr_opcode(exp)) {
case 'l': /* << (left shift) */
lv = draw_eval_expr_wid(le, wid, 0);
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
break;
case 'r': /* >> (unsigned right shift) */
/* with the right shift, there may be high bits that are
shifted into the desired width of the expression, so
we let the expression size itself, if it is bigger
then what is requested of us. */
if (wid > ivl_expr_width(le)) {
lv = draw_eval_expr_wid(le, wid, 0);
} else {
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
}
/* shifting 0 gets 0. */
if (lv.base == 0)
break;
if (lv.base < 4) {
struct vector_info tmp;
tmp.base = allocate_vector(lv.wid);
tmp.wid = lv.wid;
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
tmp.base, lv.base, lv.wid);
lv = tmp;
}
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lv.base, lv.wid);
break;
@@ -688,7 +723,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
struct vector_info lv;
unsigned long imm;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
imm = get_number_immediate(re);
@@ -725,7 +760,7 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
struct vector_info lv;
unsigned long imm;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
imm = get_number_immediate(re);
@@ -743,7 +778,7 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
struct vector_info lv;
unsigned long imm;
lv = draw_eval_expr_wid(le, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
imm = get_number_immediate(re);
@@ -789,8 +824,8 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
&& number_is_immediate(re, 16))
return draw_mul_immediate(le, re, wid);
lv = draw_eval_expr_wid(le, wid);
rv = draw_eval_expr_wid(re, wid);
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
assert(lv.wid == wid);
assert(rv.wid == wid);
@@ -840,9 +875,12 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
return lv;
}
static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
static struct vector_info draw_binary_expr(ivl_expr_t exp,
unsigned wid,
int stuff_ok_flag)
{
struct vector_info rv;
int stuff_ok_used_flag = 0;
switch (ivl_expr_opcode(exp)) {
case 'a': /* && (logical and) */
@@ -853,14 +891,16 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
case 'e': /* == */
case 'N': /* !== */
case 'n': /* != */
rv = draw_binary_expr_eq(exp, wid);
rv = draw_binary_expr_eq(exp, wid, stuff_ok_flag);
stuff_ok_used_flag = 1;
break;
case '<':
case '>':
case 'L': /* <= */
case 'G': /* >= */
rv = draw_binary_expr_le(exp, wid);
rv = draw_binary_expr_le(exp, wid, stuff_ok_flag);
stuff_ok_used_flag = 1;
break;
case '+':
@@ -883,7 +923,9 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
case '&':
case '|':
case '^':
case 'X':
case 'A': /* NAND (~&) */
case 'O': /* NOR (~|) */
case 'X': /* XNOR (~^) */
rv = draw_binary_expr_logic(exp, wid);
break;
@@ -893,6 +935,21 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
assert(0);
}
/* Mark in the lookaside that this value is done. If any OK
flags besides the STUFF_OK_47 flag are set, then the result
may not be a pure one, so clear the lookaside for the range
instead of setting in to the new expression result.
The stuff_ok_used_flag tells me if the stuff_ok_flag was
even used by anything. If not, then I can ignore it in the
following logic. */
if (rv.base >= 8) {
if (stuff_ok_used_flag && (stuff_ok_flag & ~STUFF_OK_47))
save_expression_lookaside(rv.base, 0, wid);
else
save_expression_lookaside(rv.base, exp, wid);
}
return rv;
}
@@ -904,7 +961,7 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
/* Evaluate the bit select expression and save the result into
index register 0. */
res = draw_eval_expr(sel);
res = draw_eval_expr(sel, 0);
fprintf(vvp_out, " %%ix/get 0, %u,%u;\n", res.base, res.wid);
clr_vector(res);
@@ -924,6 +981,8 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
break;
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -961,18 +1020,34 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
ivl_expr_t arg = ivl_expr_parm(exp, idx-1);
unsigned awid = ivl_expr_width(arg);
/* Evaluate this sub expression. */
struct vector_info avec = draw_eval_expr_wid(arg, awid);
unsigned trans;
struct vector_info avec;
unsigned trans = awid;
/* Try to locate the subexpression in the
lookaside map. */
avec.base = allocate_vector_exp(arg, awid);
avec.wid = awid;
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;
@@ -987,6 +1062,10 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
res.base+off, wid-off);
}
/* Save the accumulated result in the lookaside map. */
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1072,6 +1151,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
if (idx < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1119,6 +1201,9 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
if (idx < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1128,28 +1213,54 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
* offsetting the read from the lsi (least significant index) of the
* signal.
*/
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
{
unsigned idx;
unsigned lsi = ivl_expr_lsi(exp);
unsigned swid = ivl_expr_width(exp);
ivl_signal_t sig = ivl_expr_signal(exp);
if (swid > res.wid)
swid = res.wid;
if (ivl_signal_type(sig) == IVL_SIT_REG) {
/* If this is a REG (a variable) then I can do a vector
read. */
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
res.base, vvp_signal_label(sig), lsi, swid);
} else {
/* Vector reads of nets do not in general work because
they are not really functors but references to
scattered functors. So generate an array of loads. */
for (idx = 0 ; idx < swid ; idx += 1) {
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
res.base+idx, vvp_signal_label(sig), idx+lsi);
}
}
/* Pad the signal value with zeros. */
if (swid < res.wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, res.wid-swid);
}
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
if (swid > wid)
swid = wid;
/* Already in the vector lookaside? */
res.base = allocate_vector_exp(exp, wid);
res.wid = wid;
if (res.base != 0)
return res;
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;
}
@@ -1191,7 +1302,7 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
break;
}
default: {
struct vector_info addr = draw_eval_expr(ae);
struct vector_info addr = draw_eval_expr(ae, 0);
fprintf(vvp_out, " %%ix/get 3, %u, %u;\n",
addr.base, addr.wid);
clr_vector(addr);
@@ -1231,6 +1342,9 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1241,7 +1355,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
ivl_expr_t shift = ivl_expr_oper2(exp);
/* Evaluate the sub-expression. */
subv = draw_eval_expr(sube);
subv = draw_eval_expr(sube, 0);
/* Any bit select of a constant zero is another constant zero,
so short circuit and return the value we know. */
@@ -1252,7 +1366,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
/* Evaluate the bit select base expression and store the
result into index register 0. */
shiv = draw_eval_expr(shift);
shiv = draw_eval_expr(shift, STUFF_OK_XZ);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
clr_vector(shiv);
@@ -1280,6 +1394,9 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
res = subv;
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1296,7 +1413,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
lab_false = local_count++;
lab_out = local_count++;
tmp = draw_eval_expr(cond);
tmp = draw_eval_expr(cond, STUFF_OK_XZ);
clr_vector(tmp);
if ((tmp.base >= 4) && (tmp.wid > 1)) {
@@ -1316,11 +1433,11 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
/* Ambiguous case. Evaluate both true and false expressions,
and use %blend to merge them. */
tmp = draw_eval_expr_wid(true_ex, wid);
tmp = draw_eval_expr_wid(true_ex, wid, 0);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
clr_vector(tmp);
tmp = draw_eval_expr_wid(false_ex, wid);
tmp = draw_eval_expr_wid(false_ex, wid, 0);
fprintf(vvp_out, " %%blend %u, %u, %u;\n", res.base, tmp.base, wid);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
if (tmp.base >= 8)
@@ -1328,8 +1445,9 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
/* This is the true case. Just evaluate the true expression. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_true);
clear_expression_lookaside();
tmp = draw_eval_expr_wid(true_ex, wid);
tmp = draw_eval_expr_wid(true_ex, wid, 0);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
if (tmp.base >= 8)
@@ -1338,14 +1456,19 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
/* This is the false case. Just evaluate the false expression. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_false);
clear_expression_lookaside();
tmp = draw_eval_expr_wid(false_ex, wid);
tmp = draw_eval_expr_wid(false_ex, wid, 0);
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
if (tmp.base >= 8)
clr_vector(tmp);
/* This is the out label. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
clear_expression_lookaside();
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
@@ -1396,7 +1519,7 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
vec[vecs] = draw_eval_expr(expr);
vec[vecs] = draw_eval_expr(expr, 0);
vecs++;
}
@@ -1476,6 +1599,9 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
free(vec);
}
/* New basic block starts after VPI calls. */
clear_expression_lookaside();
fprintf(vvp_out, ";\n");
@@ -1510,7 +1636,7 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
unsigned pin, bit;
res = draw_eval_expr_wid(ivl_expr_parm(exp, idx),
ivl_signal_pins(port));
ivl_signal_pins(port), 0);
bit = res.base;
assert(res.wid <= ivl_signal_pins(port));
for (pin = 0 ; pin < res.wid ; pin += 1) {
@@ -1530,6 +1656,9 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
fprintf(vvp_out, ", S_%s;\n", vvp_mangle_id(ivl_scope_name(def)));
fprintf(vvp_out, " %%join;\n");
/* Fresh basic block starts after the join. */
clear_expression_lookaside();
/* The return value is in a signal that has the name of the
expression. Load that into the thread and return the
vector result. */
@@ -1577,7 +1706,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
switch (ivl_expr_opcode(exp)) {
case '~':
res = draw_eval_expr_wid(sub, wid);
res = draw_eval_expr_wid(sub, wid, STUFF_OK_XZ);
switch (res.base) {
case 0:
res.base = 1;
@@ -1600,7 +1729,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
complement of the number. That is the 1's complement
(bitwise invert) with a 1 added in. Note that the
%sub subtracts -1 (1111...) to get %add of +1. */
res = draw_eval_expr_wid(sub, wid);
res = draw_eval_expr_wid(sub, wid, STUFF_OK_XZ);
switch (res.base) {
case 0:
res.base = 0;
@@ -1620,7 +1749,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
break;
case '!':
res = draw_eval_expr(sub);
res = draw_eval_expr(sub, STUFF_OK_XZ);
if (res.wid > 1) {
/* a ! on a vector is implemented with a reduction
nor. Generate the result into the first bit of
@@ -1672,7 +1801,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
case '&':
case '|':
case '^':
res = draw_eval_expr(sub);
res = draw_eval_expr(sub, 0);
if (res.wid > 1) {
struct vector_info tmp;
/* If the previous result is in the constant area
@@ -1719,10 +1848,49 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
assert(0);
}
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
/*
* 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)
{
struct vector_info res;
@@ -1741,7 +1909,7 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
break;
case IVL_EX_BINARY:
res = draw_binary_expr(exp, wid);
res = draw_binary_expr(exp, wid, stuff_ok_flag);
break;
case IVL_EX_BITSEL:
@@ -1788,13 +1956,50 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
return res;
}
struct vector_info draw_eval_expr(ivl_expr_t exp)
struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
{
return draw_eval_expr_wid(exp, ivl_expr_width(exp));
return draw_eval_expr_wid(exp, ivl_expr_width(exp), stuff_ok_flag);
}
/*
* $Log: eval_expr.c,v $
* Revision 1.86 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
* Revision 1.85 2002/11/21 22:42:48 steve
* Allow right values of right shift to shift in.
*
* Revision 1.84 2002/11/07 03:12:17 steve
* Vectorize load from REG variables.
*
* Revision 1.83 2002/11/06 05:41:37 steve
* Concatenation can evaluate sub-expressions in place.
*
* Revision 1.82 2002/10/20 02:55:37 steve
* Properly set or clear expression lookaside for binary expressions.
*
* Revision 1.81 2002/09/27 20:24:42 steve
* Allow expression lookaside map to spam statements.
*
* Revision 1.80 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
* 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.
*
@@ -1825,93 +2030,5 @@ struct vector_info draw_eval_expr(ivl_expr_t exp)
* generate vvp labels. -tdll target does not
* used hierarchical name string to look up the
* memory objects in the design.
*
* Revision 1.66 2002/08/03 22:30:48 steve
* Eliminate use of ivl_signal_name for signal labels.
*
* Revision 1.65 2002/07/12 18:10:45 steve
* Use all bits of ?: condit expression.
*
* Revision 1.64 2002/07/01 00:52:47 steve
* Carry can propagate to the otp in addi.
*
* Revision 1.63 2002/06/02 18:57:17 steve
* Generate %cmpi/u where appropriate.
*
* Revision 1.62 2002/05/31 20:04:57 steve
* Generate %muli instructions when possible.
*
* Revision 1.61 2002/05/30 01:57:23 steve
* Use addi with wide immediate values.
*
* Revision 1.60 2002/05/29 16:29:34 steve
* Add %addi, which is faster to simulate.
*
* Revision 1.59 2002/05/07 03:49:58 steve
* Handle x case of unary ! properly.
*
* Revision 1.58 2002/04/22 02:41:30 steve
* Reduce the while loop expression if needed.
*
* Revision 1.57 2002/04/14 18:41:34 steve
* Support signed integer division.
*
* Revision 1.56 2002/02/03 05:53:00 steve
* Fix parameter bit select check for magic constants.
*
* Revision 1.55 2002/01/28 00:52:42 steve
* Add support for bit select of parameters.
* This leads to a NetESelect node and the
* vvp code generator to support that.
*
* Revision 1.54 2002/01/11 05:23:05 steve
* Handle certain special cases of stime.
*
* Revision 1.53 2001/11/19 04:25:46 steve
* Handle padding out of logical values.
*
* Revision 1.52 2001/10/24 05:06:54 steve
* The ! expression returns 0 to x and z values.
*
* Revision 1.51 2001/10/18 16:41:49 steve
* Evaluate string expressions (Philip Blundell)
*
* Revision 1.50 2001/10/16 01:27:17 steve
* Generate %div instructions for binary /.
*
* Revision 1.49 2001/10/14 03:24:35 steve
* Handle constant bits in arithmetic expressions.
*
* Revision 1.48 2001/10/10 04:47:43 steve
* Support vectors as operands to logical and.
*
* Revision 1.47 2001/09/29 04:37:44 steve
* Generate code for unary minus (PR#272)
*
* Revision 1.46 2001/09/29 01:53:22 steve
* Fix the size of unsized constant operants to compare (PR#274)
*
* Revision 1.45 2001/09/20 03:46:38 steve
* Handle short l-values to concatenation.
*
* Revision 1.44 2001/09/15 18:27:04 steve
* Make configure detect malloc.h
*
* Revision 1.43 2001/08/31 01:37:56 steve
* Handle update in place of repeat constants.
*
* Revision 1.42 2001/08/23 02:54:15 steve
* Handle wide assignment to narrow return value.
*
* Revision 1.41 2001/08/03 17:06:10 steve
* More detailed messages about unsupported things.
*
* Revision 1.40 2001/07/27 04:51:45 steve
* Handle part select expressions as variants of
* NetESignal/IVL_EX_SIGNAL objects, instead of
* creating new and useless temporary signals.
*
* Revision 1.39 2001/07/27 02:41:56 steve
* Fix binding of dangling function ports. do not elide them.
*/
+211
View File
@@ -0,0 +1,211 @@
/*
* 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: vector.c,v 1.1 2002/09/27 16:33:34 steve Exp $"
#endif
# include "vvp_priv.h"
# include <assert.h>
static struct allocation_score_s {
ivl_expr_t exp;
unsigned bit :16;
unsigned alloc : 1;
} allocation_map[0x10000] = { {0} };
/* This is the largest bit to have lookaside values. */
static unsigned lookaside_top = 0;
static inline int peek_bit(unsigned addr)
{
return allocation_map[addr].alloc;
}
static inline void set_bit(unsigned addr)
{
allocation_map[addr].alloc = 1;
}
static inline void clr_bit(unsigned addr)
{
allocation_map[addr].alloc = 0;
}
/*
* This clears a vector that was previously allocated by
* allocate_vector. That is, it unmarks all the bits of the map that
* represent this vector.
*
* If the vector is based in one of 4 constant bit values, then there
* are no bits to clear. If the vector is based in the 4-8 result
* area, then someone is broken.
*/
void clr_vector(struct vector_info vec)
{
unsigned idx;
if (vec.base < 4)
return;
assert(vec.base >= 8);
for (idx = 0 ; idx < vec.wid ; idx += 1)
clr_bit(vec.base + idx);
}
/*
* This unconditionally allocates a stretch of bits from the register
* set. It never returns a bit addressed <8 (0-3 are constant, 4-7 are
* condition codes).
*/
unsigned short allocate_vector(unsigned short wid)
{
unsigned short base = 8;
unsigned short idx = 0;
while (idx < wid) {
assert((base + idx) < 0x10000);
if (peek_bit(base+idx)) {
base = base + idx + 1;
idx = 0;
} else {
idx += 1;
}
}
for (idx = 0 ; idx < wid ; idx += 1) {
allocation_map[base+idx].alloc = 1;
allocation_map[base+idx].exp = 0;
}
return base;
}
/*
* This clears the expression cache of the allocation map. It is
* called to prevent reuse of existing expressions, normally at the
* start of a basic block.
*/
void clear_expression_lookaside(void)
{
unsigned idx;
for (idx = 0 ; idx < lookaside_top ; idx += 1) {
allocation_map[idx].exp = 0;
}
lookaside_top = 0;
}
void save_expression_lookaside(unsigned short addr, ivl_expr_t exp,
unsigned short wid)
{
unsigned idx;
assert(addr >= 8);
assert((addr+wid) <= 0x10000);
for (idx = 0 ; idx < wid ; idx += 1) {
allocation_map[addr+idx].exp = exp;
allocation_map[addr+idx].bit = idx;
}
if ((addr+wid) > lookaside_top)
lookaside_top = addr+wid;
}
static int compare_exp(ivl_expr_t l, ivl_expr_t r)
{
if (! (l && r))
return 0;
if (l == r)
return 1;
if (ivl_expr_type(l) != ivl_expr_type(r))
return 0;
switch (ivl_expr_type(l)) {
case IVL_EX_SIGNAL:
if (ivl_expr_signal(l) != ivl_expr_signal(r))
return 0;
if (ivl_expr_lsi(l) != ivl_expr_lsi(r))
return 0;
if (ivl_expr_width(l) != ivl_expr_width(r))
return 0;
return 1;
default:
break;
}
return 0;
}
static unsigned short find_expression_lookaside(ivl_expr_t exp,
unsigned short wid)
{
unsigned top;
unsigned idx, match;
if (lookaside_top <= wid)
return 0;
top = lookaside_top - wid + 1;
assert(exp);
match = 0;
for (idx = 8 ; idx < top ; idx += 1) {
if (! compare_exp(allocation_map[idx].exp, exp)) {
match = 0;
continue;
}
if (allocation_map[idx].bit != match) {
match = 0;
continue;
}
match += 1;
if (match == wid)
return idx-match+1;
}
return 0;
}
unsigned short allocate_vector_exp(ivl_expr_t exp, unsigned short wid)
{
unsigned idx;
unsigned short la = find_expression_lookaside(exp, wid);
for (idx = 0 ; idx < wid ; idx += 1)
if (allocation_map[la+idx].alloc)
return 0;
for (idx = 0 ; idx < wid ; idx += 1)
allocation_map[la+idx].alloc = 1;
return la;
}
/*
* $Log: vector.c,v $
* Revision 1.1 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
*/
+63 -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: vvp_priv.h,v 1.19 2002/08/27 05:39:57 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $"
#endif
# include "ivl_target.h"
@@ -83,14 +83,28 @@ extern void draw_input_from_net(ivl_nexus_t nex);
* allocation. When the caller is done with the bits, it must release
* the vector with clr_vector so that the code generator can reuse
* those bits.
*
* The stuff_ok_flag is normally empty. Bits in the bitmask are set
* true in cases where certain special situations are allows. This
* might allow deeper expressions to make assumptions about the
* caller.
*
* STUFF_OK_XZ -- This bit is set if the code processing the result
* doesn't distinguish between x and z values.
*
* STUFF_OK_47 -- This bit is set if the node is allowed to leave a
* result in any of the 4-7 vthread bits.
*/
struct vector_info {
unsigned short base;
unsigned short wid;
};
extern struct vector_info draw_eval_expr(ivl_expr_t exp);
extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w);
extern struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag);
extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w,
int stuff_ok_flag);
#define STUFF_OK_XZ 0x0001
#define STUFF_OK_47 0x0002
/*
* This function draws code to evaluate the index expression exp for
@@ -100,9 +114,46 @@ extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w);
*/
extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
/*
* These functions manage vector allocation in the thread register
* space. They presume that we work on one thread at a time, to
* completion.
*
* allocate_vector
* Return the base of an allocated vector in the thread. The bits
* are marked allocated in the process.
*
* clr_bector
* Clear a vector previously allocated.
*
* The thread vector allocator also keeps a lookaside of expression
* results that are stored in register bit. This lookaside can be used
* by the code generator to notice that certain expression bits are
* already calculated, and can be reused.
*
* clear_expression_lookaside
* Clear the lookaside tables for the current thread.
*
* save_expression_lookaside
* Mark the given expression as available in the given register
* bits. This remains until the lookaside is cleared.
*
* allocate_vector_exp
* This function attempts to locate the expression in the
* lookaside. If it finds it, return a reallocated base for the
* expression. Otherwise, return 0.
*/
extern unsigned short allocate_vector(unsigned short wid);
extern void clr_vector(struct vector_info vec);
extern void clear_expression_lookaside(void);
extern void save_expression_lookaside(unsigned short addr,
ivl_expr_t exp,
unsigned short wid);
extern unsigned short allocate_vector_exp(ivl_expr_t exp,
unsigned short wid);
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);
@@ -115,6 +166,15 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.22 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
* Revision 1.21 2002/09/24 04:20:32 steve
* Allow results in register bits 47 in certain cases.
*
* Revision 1.20 2002/09/13 03:12:50 steve
* Optimize ==1 when in context where x vs z doesnt matter.
*
* Revision 1.19 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.
+238 -158
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.67 2002/09/01 00:19:35 steve Exp $"
#ident "$Id: vvp_process.c,v 1.76 2002/11/21 22:43:13 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -71,17 +71,25 @@ unsigned bitchar_to_idx(char bit)
* nexus.
*/
static void set_to_lvariable(ivl_lval_t lval, unsigned idx, unsigned bit)
static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
unsigned bit, unsigned wid)
{
ivl_signal_t sig = ivl_lval_sig(lval);
unsigned part_off = ivl_lval_part_off(lval);
if (ivl_lval_mux(lval))
fprintf(vvp_out, " %%set/x V_%s, %u, 0;\n",
vvp_signal_label(sig), bit);
else
if (ivl_lval_mux(lval)) {
assert(wid == 1);
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
vvp_signal_label(sig), bit, ivl_signal_pins(sig)-1);
} else if (wid == 1) {
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
vvp_signal_label(sig), idx+part_off, bit);
} else {
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n",
vvp_signal_label(sig), idx+part_off, bit, wid);
}
}
static void set_to_memory(ivl_memory_t mem, unsigned idx, unsigned bit)
@@ -116,6 +124,19 @@ static void assign_to_lvariable(ivl_lval_t lval, unsigned idx,
idx+part_off, delay, bit);
}
static void assign_to_lvector(ivl_lval_t lval, unsigned idx,
unsigned bit, unsigned delay, unsigned width)
{
ivl_signal_t sig = ivl_lval_sig(lval);
unsigned part_off = ivl_lval_part_off(lval);
assert(ivl_lval_mux(lval) == 0);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n",
vvp_signal_label(sig), part_off+idx, delay, bit);
}
static void assign_to_memory(ivl_memory_t mem, unsigned idx,
unsigned bit, unsigned delay)
{
@@ -131,14 +152,14 @@ static void assign_to_memory(ivl_memory_t mem, unsigned idx,
*/
static void calculate_into_x0(ivl_expr_t expr)
{
struct vector_info vec = draw_eval_expr(expr);
struct vector_info vec = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", vec.base, vec.wid);
clr_vector(vec);
}
static void calculate_into_x1(ivl_expr_t expr)
{
struct vector_info vec = draw_eval_expr(expr);
struct vector_info vec = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get 1, %u, %u;\n", vec.base, vec.wid);
clr_vector(vec);
}
@@ -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,26 +223,38 @@ 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)
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
return 0;
}
{ struct vector_info res = draw_eval_expr(rval);
{ struct vector_info res = draw_eval_expr(rval, 0);
unsigned wid = res.wid;
unsigned lidx;
unsigned cur_rbit = 0;
@@ -247,27 +284,37 @@ 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)
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
if (res.base > 3)
@@ -342,6 +389,54 @@ static int show_stmt_assign_nb(ivl_statement_t net)
; idx += 1) {
assign_to_memory(mem, idx, 0, delay);
}
} else if ((del == 0) && (bit_limit > 2)) {
/* We have a vector, but no runtime
calculated delays, to try to use vector
assign instructions. */
idx = 0;
while (idx < bit_limit) {
unsigned wid = 0;
do {
wid += 1;
if ((idx + wid) == bit_limit)
break;
} while (bits[cur_rbit] == bits[cur_rbit+wid]);
switch (wid) {
case 1:
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
break;
case 2:
assign_to_lvariable(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
assign_to_lvariable(lval, idx+1,
bitchar_to_idx(bits[cur_rbit]),
delay, 0);
break;
default:
assign_to_lvector(lval, idx,
bitchar_to_idx(bits[cur_rbit]),
delay, wid);
break;
}
idx += wid;
cur_rbit += wid;
}
if (bit_limit < ivl_lval_pins(lval)) {
unsigned wid = ivl_lval_pins(lval) - bit_limit;
assign_to_lvector(lval, bit_limit,
0, delay, wid);
}
} else {
for (idx = 0 ; idx < bit_limit ; idx += 1) {
if (del != 0)
@@ -367,14 +462,16 @@ static int show_stmt_assign_nb(ivl_statement_t net)
}
}
if (skip_set_flag)
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
return 0;
}
{ struct vector_info res = draw_eval_expr(rval);
{ struct vector_info res = draw_eval_expr(rval, 0);
unsigned wid = res.wid;
unsigned lidx;
unsigned cur_rbit = 0;
@@ -407,34 +504,45 @@ 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)
if (skip_set_flag) {
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
}
if (res.base > 3)
@@ -480,6 +588,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
fprintf(vvp_out, " %%end;\n");
fprintf(vvp_out, "t_%u %%join;\n", out_id);
clear_expression_lookaside();
return rc;
}
@@ -488,7 +597,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
{
ivl_expr_t exp = ivl_stmt_cond_expr(net);
struct vector_info cond = draw_eval_expr(exp);
struct vector_info cond = draw_eval_expr(exp, 0);
unsigned count = ivl_stmt_case_count(net);
unsigned local_base = local_count;
@@ -531,7 +640,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
/* Oh well, do this case the hard way. */
cvec = draw_eval_expr_wid(cex, cond.wid);
cvec = draw_eval_expr_wid(cex, cond.wid, 0);
assert(cvec.wid == cond.wid);
switch (ivl_statement_type(net)) {
@@ -585,6 +694,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
continue;
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx);
clear_expression_lookaside();
show_statement(cst, sscope);
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count,
@@ -592,8 +702,10 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
}
/* The out of the case. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+count);
clear_expression_lookaside();
return 0;
}
@@ -651,7 +763,7 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
int rc = 0;
unsigned lab_false, lab_out;
ivl_expr_t exp = ivl_stmt_cond_expr(net);
struct vector_info cond = draw_eval_expr(exp);
struct vector_info cond = draw_eval_expr(exp, STUFF_OK_XZ|STUFF_OK_47);
assert(cond.wid == 1);
@@ -662,21 +774,26 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
thread_count, lab_false, cond.base);
/* Done with the condition expression. */
clr_vector(cond);
if (cond.base >= 8)
clr_vector(cond);
if (ivl_stmt_cond_true(net))
rc += show_statement(ivl_stmt_cond_true(net), sscope);
if (ivl_stmt_cond_false(net)) {
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_false);
clear_expression_lookaside();
rc += show_statement(ivl_stmt_cond_false(net), sscope);
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_out);
clear_expression_lookaside();
} else {
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_false);
clear_expression_lookaside();
}
return rc;
@@ -697,6 +814,9 @@ static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope)
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
fprintf(vvp_out, " %%delay %lu;\n", delay);
/* Lots of things can happen during a delay. */
clear_expression_lookaside();
rc += show_statement(stmt, sscope);
return rc;
@@ -714,12 +834,14 @@ 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);
{ 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);
}
fprintf(vvp_out, " %%delayx 0;\n");
/* Lots of things can happen during a delay. */
clear_expression_lookaside();
rc += show_statement(stmt, sscope);
return rc;
@@ -741,6 +863,7 @@ static int show_stmt_force(ivl_statement_t net)
ivl_lval_t lval;
ivl_signal_t lsig;
unsigned idx;
static unsigned force_functor_label = 0;
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
@@ -750,16 +873,17 @@ static int show_stmt_force(ivl_statement_t net)
assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0);
force_functor_label += 1;
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
fprintf(vvp_out, "f_%s.%u .force V_%s[%u], %s;\n",
vvp_signal_label(lsig), idx,
fprintf(vvp_out, "f_%u.%u .force V_%s[%u], %s;\n",
force_functor_label, idx,
vvp_signal_label(lsig), idx,
draw_net_input(ivl_stmt_nexus(net, idx)));
}
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
fprintf(vvp_out, " %%force f_%s.%u, 1;\n",
vvp_signal_label(lsig), idx);
fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
force_functor_label, idx);
}
return 0;
}
@@ -808,12 +932,14 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
for (idx = 0 ; idx < cnt-1 ; idx += 1) {
fprintf(vvp_out, "t_%u ;\n", id_base+idx);
clear_expression_lookaside();
rc += show_statement(ivl_stmt_block_stmt(net, idx), sscope);
fprintf(vvp_out, " %%end;\n");
}
/* This is the label for the out. Use this to branch around
the implementations of all the child threads. */
clear_expression_lookaside();
fprintf(vvp_out, "t_%u ;\n", out);
return rc;
@@ -868,11 +994,12 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
int rc = 0;
unsigned lab_top = local_count++, lab_out = local_count++;
ivl_expr_t exp = ivl_stmt_cond_expr(net);
struct vector_info cnt = draw_eval_expr(exp);
struct vector_info cnt = draw_eval_expr(exp, 0);
/* Test that 0 < expr */
fprintf(vvp_out, "T_%u.%u %%cmp/u 0, %u, %u;\n", thread_count,
lab_top, cnt.base, cnt.wid);
clear_expression_lookaside();
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, lab_out);
/* This adds -1 (all ones in 2's complement) to the count. */
fprintf(vvp_out, " %%add %u, 1, %u;\n", cnt.base, cnt.wid);
@@ -881,6 +1008,7 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top);
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out);
clear_expression_lookaside();
clr_vector(cnt);
@@ -905,6 +1033,7 @@ static int show_stmt_utask(ivl_statement_t net)
fprintf(vvp_out, ", S_%s;\n",
vvp_mangle_id(ivl_scope_name(task)));
fprintf(vvp_out, " %%join;\n");
clear_expression_lookaside();
return 0;
}
@@ -914,6 +1043,10 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
fprintf(vvp_out, " %%wait E_%s;\n",
vvp_mangle_id(ivl_event_name(ev)));
/* Always clear the expression lookaside after a
%wait. Anything can happen while the thread is waiting. */
clear_expression_lookaside();
return show_statement(ivl_stmt_sub_stmt(net), sscope);
}
@@ -955,18 +1088,23 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
unsigned top_label = local_count++;
unsigned out_label = local_count++;
/* Start the loop. The top of the loop starts a basic block
because it can be entered from above or from the bottom of
the loop. */
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, top_label);
clear_expression_lookaside();
/* Draw the evaluation of the condition expression, and test
the result. If the expression evaluates to false, then
branch to the out label. */
cvec = draw_eval_expr(ivl_stmt_cond_expr(net));
cvec = draw_eval_expr(ivl_stmt_cond_expr(net), STUFF_OK_XZ|STUFF_OK_47);
if (cvec.wid > 1)
cvec = reduction_or(cvec);
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, %u;\n",
thread_count, out_label, cvec.base);
clr_vector(cvec);
if (cvec.base >= 8)
clr_vector(cvec);
/* Draw the body of the loop. */
rc += show_statement(ivl_stmt_sub_stmt(net), sscope);
@@ -975,6 +1113,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
test is repeased, and also draw the out label. */
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, top_label);
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, out_label);
clear_expression_lookaside();
return rc;
}
@@ -988,6 +1127,7 @@ static int show_system_task_call(ivl_statement_t net)
if (parm_count == 0) {
fprintf(vvp_out, " %%vpi_call \"%s\";\n", ivl_stmt_name(net));
clear_expression_lookaside();
return 0;
}
@@ -1023,7 +1163,7 @@ static int show_system_task_call(ivl_statement_t net)
vec = (struct vector_info *)
realloc(vec, (vecs+1)*sizeof(struct vector_info));
vec[vecs] = draw_eval_expr(expr);
vec[vecs] = draw_eval_expr(expr, 0);
vecs++;
}
@@ -1106,6 +1246,10 @@ static int show_system_task_call(ivl_statement_t net)
fprintf(vvp_out, ";\n");
/* VPI calls can manipulate anything, so clear the expression
lookahead table after the call. */
clear_expression_lookaside();
return 0;
}
@@ -1240,6 +1384,7 @@ int draw_process(ivl_process_t net, void*x)
/* Generate the entry label. Just give the thread a number so
that we ar certain the label is unique. */
fprintf(vvp_out, "T_%d ;\n", thread_count);
clear_expression_lookaside();
/* Draw the contents of the thread. */
rc += show_statement(stmt, scope);
@@ -1274,6 +1419,7 @@ int draw_task_definition(ivl_scope_t scope)
ivl_statement_t def = ivl_scope_def(scope);
fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope)));
clear_expression_lookaside();
assert(def);
rc += show_statement(def, scope);
@@ -1290,6 +1436,7 @@ int draw_func_definition(ivl_scope_t scope)
ivl_statement_t def = ivl_scope_def(scope);
fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope)));
clear_expression_lookaside();
assert(def);
rc += show_statement(def, scope);
@@ -1302,6 +1449,33 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.76 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.75 2002/11/17 18:31:09 steve
* Generate unique labels for force functors.
*
* Revision 1.74 2002/11/08 05:00:31 steve
* Use the vectorized %assign where appropriate.
*
* Revision 1.73 2002/11/07 05:19:55 steve
* Use Vector %set to set constants in variables.
*
* Revision 1.72 2002/11/07 03:12:18 steve
* Vectorize load from REG variables.
*
* Revision 1.71 2002/09/27 20:24:42 steve
* Allow expression lookaside map to spam statements.
*
* Revision 1.70 2002/09/27 16:33:34 steve
* Add thread expression lookaside map.
*
* Revision 1.69 2002/09/24 04:20:32 steve
* Allow results in register bits 47 in certain cases.
*
* Revision 1.68 2002/09/13 03:12:50 steve
* Optimize ==1 when in context where x vs z doesnt matter.
*
* Revision 1.67 2002/09/01 00:19:35 steve
* Watch for x indices in l-value of non-blocking assignments.
*
@@ -1384,99 +1558,5 @@ int draw_func_definition(ivl_scope_t scope)
*
* Revision 1.44 2001/09/01 00:58:16 steve
* dead comments.
*
* Revision 1.43 2001/08/26 23:00:13 steve
* Generate code for l-value bit selects.
*
* Revision 1.42 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.41 2001/08/16 03:45:17 steve
* statement ends after while loop labels.
*
* Revision 1.40 2001/07/28 01:18:07 steve
* Evaluate part selects when passed to system tasks.
*
* Revision 1.39 2001/07/19 04:55:06 steve
* Support calculated delays in vvp.tgt.
*
* Revision 1.38 2001/06/29 02:41:05 steve
* Handle null parameters to system tasks.
*
* Revision 1.37 2001/06/23 00:30:42 steve
* Handle short inputs to tasks. (Stephan Boettcher)
*
* Revision 1.36 2001/06/18 03:10:34 steve
* 1. Logic with more than 4 inputs
* 2. Id and name mangling
* 3. A memory leak in draw_net_in_scope()
* (Stephan Boettcher)
*
* Revision 1.35 2001/05/24 04:31:00 steve
* Attach noops to case labels.
*
* Revision 1.34 2001/05/17 04:37:02 steve
* Behavioral ternary operators for vvp.
*
* Revision 1.33 2001/05/10 00:26:53 steve
* VVP support for memories in expressions,
* including general support for thread bit
* vectors as system task parameters.
* (Stephan Boettcher)
*
* Revision 1.32 2001/05/08 23:59:33 steve
* Add ivl and vvp.tgt support for memories in
* expressions and l-values. (Stephan Boettcher)
*
* Revision 1.31 2001/05/03 04:55:28 steve
* Generate null statements for conditional labels.
*
* Revision 1.30 2001/04/21 03:26:23 steve
* Right shift by constant.
*
* Revision 1.29 2001/04/21 00:55:46 steve
* Generate code for disable.
*
* Revision 1.28 2001/04/18 05:12:03 steve
* Use the new %fork syntax.
*
* Revision 1.27 2001/04/15 02:58:11 steve
* vvp support for <= with internal delay.
*
* Revision 1.26 2001/04/06 02:28:03 steve
* Generate vvp code for functions with ports.
*
* Revision 1.25 2001/04/05 03:20:58 steve
* Generate vvp code for the repeat statement.
*
* Revision 1.24 2001/04/04 04:50:35 steve
* Support forever loops in the tgt-vvp target.
*
* Revision 1.23 2001/04/04 04:28:41 steve
* Fix broken look scanning down bits of number.
*
* Revision 1.22 2001/04/04 04:14:09 steve
* emit vpi parameters values as vectors.
*
* Revision 1.21 2001/04/03 04:50:37 steve
* Support non-blocking assignments.
*
* Revision 1.20 2001/04/02 04:09:20 steve
* thread bit allocation leak in assign.
*
* Revision 1.19 2001/04/02 02:28:13 steve
* Generate code for task calls.
*
* Revision 1.18 2001/04/02 00:27:53 steve
* Scopes and numbers as vpi_call parameters.
*
* Revision 1.17 2001/04/01 06:49:04 steve
* Generate code for while statements.
*/
+133 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.77 2002/08/12 01:35:04 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.81 2002/11/21 18:08:09 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -330,6 +330,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
lpm = ivl_nexus_ptr_lpm(nptr);
if (lpm) switch (ivl_lpm_type(lpm)) {
case IVL_LPM_FF:
case IVL_LPM_MUX:
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
if (ivl_lpm_q(lpm, idx) == nex) {
@@ -1264,13 +1265,123 @@ static void draw_lpm_eq(ivl_lpm_t net)
}
}
/*
* primitive FD (q, clk, ce, d);
* output q;
* reg q;
* input clk, ce, d;
* table
* // clk ce d r s q q+
* r 1 0 0 0 : ? : 0;
* r 1 1 0 0 : ? : 1;
* f 1 ? 0 0 : ? : -;
* ? 1 ? 0 0 : ? : -;
* * 0 ? 0 0 : ? : -;
* ? ? ? 1 ? : ? : 0;
* ? ? ? 0 1 : ? : 1;
* endtable
* endprimitive
*/
static void draw_lpm_ff(ivl_lpm_t net)
{
ivl_expr_t aset_expr = 0;
const char*aset_bits = 0;
unsigned width, idx;
width = ivl_lpm_width(net);
/* Q C CE D RS --> Q+ */
fprintf(vvp_out, "L_%s/def .udp/sequ \"DFF\", 5, 2,"
" \"?" "r" "1" "0" "00" "0\","
" \"?" "r" "1" "1" "00" "1\","
" \"?" "r" "1" "x" "00" "x\","
" \"0" "r" "x" "0" "00" "0\","
" \"1" "r" "x" "1" "00" "1\","
" \"?" "*" "0" "?" "00" "-\","
" \"?" "_" "?" "?" "00" "-\","
" \"?" "?" "?" "?" "01" "1\","
" \"?" "?" "?" "?" "1?" "0\","
" \"?" "?" "1" "?" "00" "-\","
" \"?" "?" "?" "?" "00" "-\""
";\n", vvp_mangle_id(ivl_lpm_name(net)));
aset_expr = ivl_lpm_aset_value(net);
if (aset_expr) {
assert(ivl_expr_width(aset_expr) == width);
aset_bits = ivl_expr_bits(aset_expr);
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t tmp;
fprintf(vvp_out, "L_%s/%u .udp ",
vvp_mangle_id(ivl_lpm_name(net)), idx);
fprintf(vvp_out, "L_%s/def, ", vvp_mangle_id(ivl_lpm_name(net)));
tmp = ivl_lpm_clk(net);
draw_input_from_net(tmp);
tmp = ivl_lpm_enable(net);
fprintf(vvp_out, ", ");
if (tmp)
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<1>");
tmp = ivl_lpm_data(net, idx);
assert(tmp);
fprintf(vvp_out, ", ");
draw_input_from_net(tmp);
/* Connect reset input. This may be the Aclr input, or
an Aset to zero. */
fprintf(vvp_out, ", ");
tmp = ivl_lpm_async_clr(net);
if (tmp) {
draw_input_from_net(tmp);
} else {
tmp = ivl_lpm_async_set(net);
if (aset_bits && (aset_bits[idx] == '0'))
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<0>");
}
/* Connect set input */
fprintf(vvp_out, ", ");
tmp = ivl_lpm_async_set(net);
if (aset_bits && (aset_bits[idx] != '1'))
tmp = 0;
if (tmp)
draw_input_from_net(tmp);
else
fprintf(vvp_out, "C<0>");
fprintf(vvp_out, ";\n");
}
}
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);
@@ -1283,11 +1394,15 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
draw_input_from_net(ivl_lpm_data(net, idx));
}
for (idx = 0 ; idx < selects ; idx += 1) {
for (idx = 0 ; idx < selwid ; idx += 1) {
fprintf(vvp_out, ", ");
draw_input_from_net(ivl_lpm_select(net, idx));
}
for (idx = selwid ; idx < width ; idx += 1) {
fprintf(vvp_out, ", C<0>");
}
fprintf(vvp_out, ";\n");
}
@@ -1373,6 +1488,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_eq(net);
return;
case IVL_LPM_FF:
draw_lpm_ff(net);
return;
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
draw_lpm_cmp(net);
@@ -1488,6 +1607,18 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.81 2002/11/21 18:08:09 steve
* Better handling of select width of shifters.
*
* Revision 1.80 2002/10/23 04:39:35 steve
* draw lpm ff with aset_expr taken into account.
*
* Revision 1.79 2002/09/26 03:18:04 steve
* Generate vvp code for asynch set/reset of NetFF.
*
* Revision 1.78 2002/09/17 05:37:45 steve
* Generate vvp code for structural flip-flops.
*
* Revision 1.77 2002/08/12 01:35:04 steve
* conditional ident string using autoconfig.
*
+3 -3
View File
@@ -1,10 +1,10 @@
Summary: Icarus Verilog
Name: verilog
Version: 0.6.20020907
Version: 0.7
Release: 0
Copyright: GPL
Group: Applications/Engineering
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20020907.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-20020907
%setup -n verilog-0.7
%build
./configure --prefix=/usr
+27 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_display.c,v 1.45 2002/09/06 04:56:28 steve Exp $"
#ident "$Id: sys_display.c,v 1.46 2002/11/09 06:01:11 steve Exp $"
#endif
# include "config.h"
@@ -609,6 +609,29 @@ static int format_str(vpiHandle scope, unsigned int mcd,
cp += 1;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
if (isdigit(cp[0])
&& isdigit(cp[1])
&& isdigit(cp[2])) {
/* handle octal escapes (e.g. "\015" is CR)*/
vpi_mcd_printf(mcd, "%c",
(cp[2] - '0') +
8 * ((cp[1] - '0') +
8 * (cp[0] - '0')));
cp += 3;
} else {
vpi_mcd_printf(mcd, "%c", *cp);
cp += 1;
}
break;
default:
vpi_mcd_printf(mcd, "%c", *cp);
cp += 1;
@@ -1461,6 +1484,9 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.46 2002/11/09 06:01:11 steve
* display octal escapes properly.
*
* Revision 1.45 2002/09/06 04:56:28 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
+7 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_lxt.c,v 1.11 2002/08/15 02:12:20 steve Exp $"
#ident "$Id: sys_lxt.c,v 1.12 2002/11/17 22:28:42 steve Exp $"
#endif
# include "config.h"
@@ -460,6 +460,9 @@ static int sys_dumpfile_calltf(char*name)
path = strdup("dumpfile.lxt");
}
if (dump_file)
close_dumpfile();
assert(dump_file == 0);
open_dumpfile(path);
@@ -814,6 +817,9 @@ void sys_lxt_register()
/*
* $Log: sys_lxt.c,v $
* Revision 1.12 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
* Revision 1.11 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
+13 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_vcd.c,v 1.37 2002/08/15 02:12:20 steve Exp $"
#ident "$Id: sys_vcd.c,v 1.39 2002/11/17 22:28:42 steve Exp $"
#endif
# include "config.h"
@@ -146,7 +146,7 @@ inline static void vcd_names_add(const char *name)
struct vcd_names_s *nl = (struct vcd_names_s *)
malloc(sizeof(struct vcd_names_s));
assert(nl);
nl->name = name;
nl->name = strdup(name);
nl->next = vcd_names_list;
vcd_names_list = nl;
listed_names ++;
@@ -449,6 +449,11 @@ static int sys_dumpfile_calltf(char*name)
path = strdup("dumpfile.vcd");
}
if (dump_file) {
fclose(dump_file);
dump_file = 0;
}
assert(dump_file == 0);
open_dumpfile(path);
@@ -844,6 +849,12 @@ void sys_vcd_register()
/*
* $Log: sys_vcd.c,v $
* Revision 1.39 2002/11/17 22:28:42 steve
* Close old file if $dumpfile is called again.
*
* Revision 1.38 2002/11/14 22:43:58 steve
* Save vpiFullName results.
*
* Revision 1.37 2002/08/15 02:12:20 steve
* add dumpvars_compiletf to check first argument.
*
+10 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.c,v 1.6 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: vpithunk.c,v 1.7 2002/12/11 23:55:22 steve Exp $"
#endif
#include <stdio.h>
@@ -188,6 +188,11 @@ extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index)
VPIT_CALL(vpi_handle_by_index,0,(ref, index));
}
extern vpiHandle vpi_handle_by_name(char *name, vpiHandle scope)
{
VPIT_CALL(vpi_handle_by_name,0,(name, scope));
}
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t)
{
VPITV_CALL(vpi_get_time, (obj,t));
@@ -232,6 +237,10 @@ extern int vpi_chk_error(p_vpi_error_info info)
/*
* $Log: vpithunk.c,v $
* Revision 1.7 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.6 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+9 -2
View File
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpithunk.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: vpithunk.h,v 1.5 2002/12/11 23:55:22 steve Exp $"
#endif
/* These functions are actually defined in lieu of the vpi functions
@@ -38,7 +38,9 @@ extern void vpi_sim_vcontrol(int operation, va_list ap);
EXTERN_C_END
#define VPI_THUNK_MAGIC (0x87836BA4)
/* before v0.7: 0x87836BA4 */
/* v0.7 thunk magic is 0x87836BA5 */
#define VPI_THUNK_MAGIC (0x87836BA5)
typedef struct {
int magic;
@@ -67,6 +69,7 @@ typedef struct {
int (*vpi_free_object)(vpiHandle ref);
int (*vpi_get_vlog_info)(p_vpi_vlog_info vlog_info_p);
int (*vpi_chk_error)(p_vpi_error_info info);
vpiHandle (*vpi_handle_by_name)(char *name, vpiHandle scope);
} vpi_thunk, *p_vpi_thunk;
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
@@ -75,6 +78,10 @@ DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
/*
* $Log: vpithunk.h,v $
* Revision 1.5 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.4 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+1
View File
@@ -10,6 +10,7 @@ Makefile
lexor.cc
parse.cc
parse.cc.output
parse.output
parse.h
tables.cc
vvp
+22 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: codes.h,v 1.49 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: codes.h,v 1.54 2002/11/21 22:43:13 steve Exp $"
#endif
@@ -42,6 +42,7 @@ extern bool of_ANDR(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
extern bool of_ASSIGN_X0(vthread_t thr, vvp_code_t code);
extern bool of_BLEND(vthread_t thr, vvp_code_t code);
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
@@ -74,20 +75,24 @@ extern bool of_JOIN(vthread_t thr, vvp_code_t code);
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_MEM(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
extern bool of_LOAD_X(vthread_t thr, vvp_code_t code);
extern bool of_MOD(vthread_t thr, vvp_code_t code);
extern bool of_MOV(vthread_t thr, vvp_code_t code);
extern bool of_MUL(vthread_t thr, vvp_code_t code);
extern bool of_MULI(vthread_t thr, vvp_code_t code);
extern bool of_NAND(vthread_t thr, vvp_code_t code);
extern bool of_NANDR(vthread_t thr, vvp_code_t code);
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
extern bool of_NOR(vthread_t thr, vvp_code_t code);
extern bool of_NORR(vthread_t thr, vvp_code_t code);
extern bool of_OR(vthread_t thr, vvp_code_t code);
extern bool of_ORR(vthread_t thr, vvp_code_t code);
extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
extern bool of_SET(vthread_t thr, vvp_code_t code);
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
extern bool of_SET_X(vthread_t thr, vvp_code_t code);
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
extern bool of_SET_X0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
extern bool of_SUB(vthread_t thr, vvp_code_t code);
@@ -155,6 +160,21 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
/*
* $Log: codes.h,v $
* Revision 1.54 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.53 2002/11/08 04:59:57 steve
* Add the %assign/v0 instruction.
*
* Revision 1.52 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.51 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.50 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.49 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
+61 -9
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compile.cc,v 1.140 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: compile.cc,v 1.146 2002/11/21 22:43:13 steve Exp $"
#endif
# include "arith.h"
@@ -87,8 +87,9 @@ const static struct opcode_table_s opcode_table[] = {
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
{ "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
@@ -119,20 +120,24 @@ const static struct opcode_table_s opcode_table[] = {
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
{ "%load/m", of_LOAD_MEM,2, {OA_BIT1, OA_MEM_PTR, OA_NONE} },
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%load/x", of_LOAD_X, 3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
{ "%mod", of_MOD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
{ "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
{ "%release",of_RELEASE,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
{ "%set/x", of_SET_X, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
@@ -462,6 +467,40 @@ void code_label_lookup(struct vvp_code_s *code, char *label)
resolv_submit(res);
}
/*
* Lookup memories.
*/
struct memory_resolv_list_s: public resolv_list_s {
struct vvp_code_s *code;
char *label;
virtual bool resolve(bool mes);
};
bool memory_resolv_list_s::resolve(bool mes)
{
code->mem = memory_find(label);
if (code->mem != 0) {
free(label);
return true;
}
if (mes)
fprintf(stderr, "Memory unresolved: %s\n", label);
return false;
}
static void compile_mem_lookup(struct vvp_code_s *code, char *label)
{
struct memory_resolv_list_s *res
= new struct memory_resolv_list_s;
res->code = code;
res->label = label;
resolv_submit(res);
}
/*
* When parsing is otherwise complete, this function is called to do
* the final stuff. Clean up deferred linking here.
@@ -1252,12 +1291,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
break;
}
code->mem = memory_find(opa->argv[idx].symb.text);
if (code->mem == 0) {
yyerror("memory undefined");
}
free(opa->argv[idx].symb.text);
compile_mem_lookup(code, opa->argv[idx].symb.text);
break;
case OA_VPI_PTR:
@@ -1449,6 +1483,24 @@ void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
/*
* $Log: compile.cc,v $
* Revision 1.146 2002/11/21 22:43:13 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.145 2002/11/08 04:59:58 steve
* Add the %assign/v0 instruction.
*
* Revision 1.144 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.143 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.142 2002/09/18 02:55:18 steve
* Allow forward references of memories.
*
* Revision 1.141 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.140 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
+1 -1
View File
@@ -146,7 +146,7 @@ CC_LEADING_UNDERSCORE=no
CC_TRAILING_UNDERSCORE=no
output=`nm underscore.o|grep _underscore 2>&1`
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
CC_LEADING_UNDERSCORE=yes
AC_DEFINE(NEED_LU)
fi
+18 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_dlfcn.h,v 1.5 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: ivl_dlfcn.h,v 1.6 2002/11/05 02:11:56 steve Exp $"
#endif
#if defined(__MINGW32__)
@@ -45,7 +45,20 @@ inline void ivl_dlclose(ivl_dll_t dll)
{ (void)FreeLibrary((HINSTANCE)dll);}
inline const char *dlerror(void)
{ static char s[30]; sprintf(s,"DLError:%ld", GetLastError()); return s;}
{
static char msg[256];
unsigned long err = GetLastError();
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &msg,
sizeof(msg) - 1,
NULL
);
return msg;
}
#elif defined(HAVE_DLFCN_H)
inline ivl_dll_t ivl_dlopen(const char*name)
@@ -77,6 +90,9 @@ inline const char*dlerror(void)
/*
* $Log: ivl_dlfcn.h,v $
* Revision 1.6 2002/11/05 02:11:56 steve
* Better error message for load failure on Windows.
*
* Revision 1.5 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+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: main.cc,v 1.30 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: main.cc,v 1.31 2002/09/18 03:34:07 steve Exp $"
#endif
# include "config.h"
@@ -245,7 +245,7 @@ int main(int argc, char*argv[])
fprintf(stderr, " %8lu resolv\n", count_functors_resolv);
fprintf(stderr, " %8lu variable\n", count_functors_var);
fprintf(stderr, " ... %8lu opcodes (%lu bytes)\n",
count_opcodes, size_opcodes);
count_opcodes, (unsigned long)size_opcodes);
fprintf(stderr, " ... %8lu nets\n", count_vpi_nets);
fprintf(stderr, " ... %8lu memories\n", count_vpi_memories);
fprintf(stderr, " ... %8lu scopes\n", count_vpi_scopes);
@@ -280,6 +280,9 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.31 2002/09/18 03:34:07 steve
* printf size warning.
*
* Revision 1.30 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+10 -4
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: memory.cc,v 1.18 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: memory.cc,v 1.19 2002/09/17 00:42:22 steve Exp $"
#endif
#include "memory.h"
@@ -130,12 +130,15 @@ char *memory_name(vvp_memory_t mem)
// Compilation
static symbol_table_t memory_table;
static symbol_table_t memory_table = 0;
vvp_memory_t memory_find(char *label)
{
symbol_value_t v = sym_get_value(memory_table, label);
return (vvp_memory_t)v.ptr;
if (memory_table == 0)
return 0;
symbol_value_t v = sym_get_value(memory_table, label);
return (vvp_memory_t)v.ptr;
}
vvp_memory_t memory_create(char *label)
@@ -507,6 +510,9 @@ void schedule_memory(vvp_memory_t mem, unsigned idx,
/*
* $Log: memory.cc,v $
* Revision 1.19 2002/09/17 00:42:22 steve
* Proper initialization of the memories table.
*
* Revision 1.18 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+45 -7
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2001 Stephen Williams ([email protected])
*
* $Id: opcodes.txt,v 1.40 2002/08/28 18:38:07 steve Exp $
* $Id: opcodes.txt,v 1.45 2002/11/21 22:43:13 steve Exp $
*/
@@ -49,6 +49,7 @@ means the following:
* %assign <var-label>, <delay>, <bit>
* %assign/d <var-label>, <delay>, <bit>
* %assign/v0 <var-label>, <delay>, <bit>
This does a non-blocking assignment to a variable. The <label>
identifies the affected variable, and the <delay> gives the delay when
@@ -60,6 +61,8 @@ The %assign/d instruction is exactly the same as the %assign
instruction, except that the <delay> specifies one of the index
registers, that contain a calculated delay.
The %assign/v0 instruction is a vector version of %assign, with the
vector width in index register 0.
* %assign/m <memory-label>, <delay>, <bit>
@@ -297,6 +300,7 @@ ended, then the %join does not block or yield the thread.
* %load <bit>, <functor-label>
* %load/v <bit>, <functor-label>, <wid>
This instruction loads a value from the given functor output into the
specified thread register bit. The functor-label can refer to a .net,
@@ -304,6 +308,8 @@ a .var or a .functor, and may be indexed with array syntax to get at a
functor within a vector of functors. This instruction loads only a
single bit.
THe %load/v instruction is a vector version, that loads an entire
vector, starting at the given <bit> and functor.
* %load/m <bit>, <memory-label>
@@ -359,6 +365,30 @@ This instruction is the same as %mul, but the second operand is an
immediate value that is padded to the width of the result.
* %nand <dst>, <src>, <wid>
Perform the bitwise NAND of the two vectors, and store the result in
the left vector. Each bit is calculated independent of other bits. NAND
means the following:
0 and ? --> 1
? and 0 --> 1
1 and 1 --> 0
otherwise x
* %nor <dst>, <src>, <wid>
Perform the bitwise nor of the vectors. Each bit in the <dst> is
combined with the corresponding bit in the source, according to the
truth table:
1 nor ? --> 0
? nor 1 --> 0
0 nor 0 --> 1
otherwise x
* %nor/r <dst>, <src>, <wid>
The %nor/r instruction is a reduction nor. That is, the <src> is a
@@ -407,6 +437,7 @@ semantics. Like:
* %set <var-label>, <bit>
* %set/v <var-label>, <bit>, <wid>
This sets a bit of a variable, and is used to implement blocking
assignments. The <label> identifies the variable to receive the new
@@ -414,6 +445,11 @@ value. Once the set completes, the value is immediately available to
be read out of the variable. The <bit> is the address of the thread
register that contains the bit value to assign.
The %set/v instrunction is the same as the %set, but it adds a width
for a vector. The bits are written out in order, starting at the
addressed variable bit and working up. If the <bit> is one of the
constant bits, then the value is repeated for the width. Otherwise,
the vector is taken from increasing thread bit addresses.
* %set/m <memory-label>, <bit>
@@ -423,15 +459,17 @@ address zero is the LSB of the first memory word. This instruction
sets only a single bit.
* %set/x <var-label>, <bit>, <idx>
* %set/x0 <var-label>, <bit>, <top>
This sets the bit of a variable functor, the address calculated by
using the index register <idx> (0, 1, 2 or 3) to index the functor
address of <var-label>.
using the index register 0 to index the functor address of
<var-label>.
If the index value in index register <idx> is <0 (for example if
%ix/get converted an unknown value into the register) then the set is
not performed.
If the index value in index register is <0 (for example if %ix/get
converted an unknown value into the register) then the set is not
performed. Also, if the index value is > the immediate top value, then
the set is not performed. The 0 and <top> values suffice to provide
complete bounds checking.
* %shiftl/i0 <bit>, <wid>
+39 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_callback.cc,v 1.24 2002/09/07 04:54:51 steve Exp $"
#ident "$Id: vpi_callback.cc,v 1.25 2002/09/20 02:42:11 steve Exp $"
#endif
/*
@@ -298,6 +298,37 @@ static struct __vpiCallback* make_sync(p_cb_data data, bool readonly_flag)
return obj;
}
static struct __vpiCallback* make_afterdelay(p_cb_data data)
{
struct __vpiCallback*obj = new_vpi_callback();
obj->cb_data = *data;
assert(data->time);
obj->cb_time = *(data->time);
obj->cb_data.time = &obj->cb_time;
obj->next = 0;
struct sync_cb*cb = new sync_cb;
cb->sync_flag = false;
cb->run = &make_sync_run;
cb->handle = obj;
obj->cb_sync = cb;
switch (obj->cb_time.type) {
case vpiSimTime: {
vvp_time64_t tv = vpip_timestruct_to_time(&obj->cb_time);
schedule_generic(cb, 0, tv);
break;
}
default:
assert(0);
break;
}
return obj;
}
/*
* The following functions are the used for pre and post simulation
* callbacks.
@@ -396,6 +427,10 @@ vpiHandle vpi_register_cb(p_cb_data data)
obj = make_sync(data, false);
break;
case cbAfterDelay:
obj = make_afterdelay(data);
break;
case cbEndOfCompile:
case cbStartOfSimulation:
case cbEndOfSimulation:
@@ -495,6 +530,9 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
/*
* $Log: vpi_callback.cc,v $
* Revision 1.25 2002/09/20 02:42:11 steve
* Add support for cbAfterDelay.
*
* Revision 1.24 2002/09/07 04:54:51 steve
* Implement vpi_remove_cb for cbValueChange.
*
+50 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_const.cc,v 1.19 2002/08/12 01:35:08 steve Exp $"
#ident "$Id: vpi_const.cc,v 1.21 2002/11/03 20:33:43 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -335,6 +335,49 @@ static void binary_value(vpiHandle ref, p_vpi_value vp)
break;
}
case vpiVectorVal: {
unsigned int obit = 0;
unsigned hwid = (rfp->nbits - 1)/32 + 1;
char*rbuf = need_result_buf(hwid*sizeof(s_vpi_vecval), RBUF_VAL);
s_vpi_vecval *op = (p_vpi_vecval)rbuf;
vp->value.vector = op;
op->aval = op->bval = 0;
for (unsigned idx = 0 ; idx < rfp->nbits ; idx += 1) {
unsigned nibble = idx/4;
unsigned shift = 2 * (idx%4);
unsigned bit_val = (rfp->bits[nibble] >> shift) & 3;
switch (bit_val) {
case 0:
op->aval &= ~(1 << obit);
op->bval &= ~(1 << obit);
break;
case 1:
op->aval |= (1 << obit);
op->bval &= ~(1 << obit);
break;
case 2:
op->aval |= (1 << obit);
op->bval |= (1 << obit);
break;
case 3:
op->aval &= ~(1 << obit);
op->bval |= (1 << obit);
break;
}
obit++;
if (!(obit % 32)) {
op += 1;
if ((op - vp->value.vector) < (long)hwid)
op->aval = op->bval = 0;
obit = 0;
}
}
break;
}
case vpiStringVal:
binary_vpiStringVal(rfp, vp);
break;
@@ -514,6 +557,12 @@ vpiHandle vpip_make_dec_const(int value)
/*
* $Log: vpi_const.cc,v $
* Revision 1.21 2002/11/03 20:33:43 steve
* Compiler error wrt ptrdiff_t.
*
* Revision 1.20 2002/11/03 02:07:24 steve
* Get VectorVals from constant values.
*
* Revision 1.19 2002/08/12 01:35:08 steve
* conditional ident string using autoconfig.
*
+17 -5
View File
@@ -27,7 +27,7 @@
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_memory.cc,v 1.18 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_memory.cc,v 1.20 2002/09/12 15:13:07 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -109,20 +109,23 @@ static char* memory_get_str(int code, vpiHandle ref)
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
char *bn = vpi_get_str(vpiFullName, &rfp->scope->base);
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->scope->base));
char *nm = memory_name(rfp->mem);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 2, RBUF_STR);
switch (code) {
case vpiFullName:
sprintf(rbuf, "%s.%s", bn, nm);
free(bn);
return rbuf;
case vpiName:
strcpy(rbuf, nm);
free(bn);
return rbuf;
}
free(bn);
return 0;
}
@@ -344,23 +347,26 @@ static char* memory_word_get_str(int code, vpiHandle ref)
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
char *bn = vpi_get_str(vpiFullName, &rfp->mem->scope->base);
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->mem->scope->base));
char *nm = memory_name(rfp->mem->mem);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 10 + 4, RBUF_STR);
switch (code) {
case vpiFullName:
sprintf(rbuf, "%s.%s[%d]", bn, nm, rfp->index.value);
free(bn);
return rbuf;
break;
case vpiName: {
sprintf(rbuf, "%s[%d]", nm, rfp->index.value);
free(bn);
return rbuf;
break;
}
}
free(bn);
return 0;
}
@@ -580,6 +586,12 @@ vpiHandle vpip_make_memory(vvp_memory_t mem)
/*
* $Log: vpi_memory.cc,v $
* Revision 1.20 2002/09/12 15:13:07 steve
* Account for buffer overrun in memory word names.
*
* Revision 1.19 2002/09/11 16:06:57 steve
* Fix wrecked rbuf in vpi_get_str of signals and memories.
*
* Revision 1.18 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+11 -1
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_priv.cc,v 1.24 2002/08/24 05:02:58 steve Exp $"
#ident "$Id: vpi_priv.cc,v 1.25 2002/12/11 23:55:22 steve Exp $"
#endif
# include "vpi_priv.h"
@@ -133,6 +133,12 @@ int vpi_get(int property, vpiHandle ref)
char* vpi_get_str(int property, vpiHandle ref)
{
if (ref == 0) {
fprintf(stderr, "vpi error: vpi_get_str(%d, ...) called "
"with null vpiHandle.\n", property);
return 0;
}
assert(ref);
if (ref->vpi_type->vpi_get_str_ == 0)
return 0;
@@ -363,6 +369,10 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
/*
* $Log: vpi_priv.cc,v $
* Revision 1.25 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.24 2002/08/24 05:02:58 steve
* Fix = vs == error.
*
+22 -20
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_scope.cc,v 1.20 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vpi_scope.cc,v 1.21 2002/11/15 22:14:12 steve Exp $"
#endif
# include "compile.h"
@@ -100,20 +100,29 @@ static vpiHandle scope_get_handle(int code, vpiHandle obj)
/* compares vpiType's considering object classes */
static int compare_types(int code, int type)
{
if ( code == type
|| (code == vpiInternalScope &&
/* NOTE: The Verilog VPI does not for any object support
vpiScope as an iterator parameter, so it is used here as a
means to scan everything in the *current* scope. */
if (code == vpiScope)
return 1;
if (code == type)
return 1;
if ( code == vpiInternalScope &&
(type == vpiModule ||
type == vpiFunction ||
type == vpiTask ||
type == vpiNamedBegin ||
type == vpiNamedFork))
|| (code == vpiVariables &&
type == vpiNamedFork) )
return 1;
if ( code == vpiVariables &&
(type == vpiIntegerVar ||
type == vpiTimeVar))
)
return 1;
else
return 0;
return 1;
return 0;
}
static vpiHandle module_iter_subset(int code, struct __vpiScope*ref)
@@ -153,17 +162,7 @@ static vpiHandle module_iter(int code, vpiHandle obj)
|| (obj->vpi_type->type_code == vpiNamedBegin)
|| (obj->vpi_type->type_code == vpiNamedFork));
switch (code) {
case vpiInternalScope:
case vpiMemory:
case vpiModule:
case vpiNamedEvent:
case vpiNet:
case vpiReg:
return module_iter_subset(code, ref);
}
return 0;
return module_iter_subset(code, ref);
}
/*
@@ -407,6 +406,9 @@ void vpip_attach_to_current_scope(vpiHandle obj)
/*
* $Log: vpi_scope.cc,v $
* Revision 1.21 2002/11/15 22:14:12 steve
* Add vpiScope iterate on vpiScope objects.
*
* Revision 1.20 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*
+62 -7
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vpi_signal.cc,v 1.47 2002/09/06 04:56:29 steve Exp $"
#ident "$Id: vpi_signal.cc,v 1.50 2002/11/25 23:33:45 steve Exp $"
#endif
/*
@@ -62,10 +62,11 @@ char *need_result_buf(unsigned cnt, vpi_rbuf_t type)
if (result_buf_size[type] == 0) {
result_buf[type] = (char*)malloc(cnt);
result_buf_size[type] = cnt;
} else if (result_buf_size[type] < cnt) {
result_buf[type] = (char*)realloc(result_buf[type], cnt);
result_buf_size[type] = cnt;
}
result_buf_size[type] = cnt;
return result_buf[type];
}
@@ -109,22 +110,25 @@ static char* signal_get_str(int code, vpiHandle ref)
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
char *bn = vpi_get_str(vpiFullName, &rfp->scope->base);
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->scope->base));
char *nm = (char*)rfp->name;
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 2, RBUF_STR);
switch (code) {
case vpiFullName:
sprintf(rbuf, "%s.%s", bn, nm);
free(bn);
return rbuf;
case vpiName:
strcpy(rbuf, nm);
free(bn);
return rbuf;
}
free(bn);
return 0;
}
@@ -382,6 +386,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
s_vpi_strengthval*op = (s_vpi_strengthval*)
need_result_buf(wid * sizeof(s_vpi_strengthval),
RBUF_VAL);
vp->value.strength = op;
/* Convert the internal strength values of each
functor in the vector to a PLI2.0 version. */
@@ -414,6 +419,8 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
op[idx].s0 = vpiHiZ;
op[idx].s1 = vpiHiZ;
break;
default:
assert(0);
}
}
@@ -421,9 +428,10 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
}
default:
fprintf(stderr, "vvp internal error: signal_get_value: "
"value type %u not implemented.\n", vp->format);
fprintf(stderr, "vvp internal error: get_value: "
"value type %u not implemented."
" Signal is %s in scope %s\n",
vp->format, rfp->name, rfp->scope->name);
assert(0);
}
}
@@ -443,6 +451,36 @@ static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
fu->put_ostr(val, str, true);
}
static void signal_put_stringval(struct __vpiSignal*rfp, unsigned wid,
const char*str)
{
unsigned idx;
const char*cp;
cp = str + strlen(str);
idx = 0;
while ((idx < wid) && (cp > str)) {
unsigned byte = *--cp;
int bit;
for (bit = 0 ; bit < 8 ; bit += 1) {
if (byte & 1)
functor_poke(rfp, idx, 1, St1);
else
functor_poke(rfp, idx, 0, St0);
byte >>= 1;
idx += 1;
}
}
while (idx < wid) {
functor_poke(rfp, 0, 0, St0);
idx += 1;
}
}
static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
p_vpi_time when, int flags)
{
@@ -634,7 +672,15 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
break;
}
case vpiStringVal:
signal_put_stringval(rfp, wid, vp->value.str);
break;
default:
fprintf(stderr, "vvp internal error: put_value: "
"value type %u not implemented."
" Signal is %s in scope %s\n",
vp->format, rfp->name, rfp->scope->name);
assert(0);
}
@@ -715,6 +761,15 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
/*
* $Log: vpi_signal.cc,v $
* Revision 1.50 2002/11/25 23:33:45 steve
* Support put of vpiStringVal to signals.
*
* Revision 1.49 2002/09/11 16:06:57 steve
* Fix wrecked rbuf in vpi_get_str of signals and memories.
*
* Revision 1.48 2002/09/10 02:27:11 steve
* Actually set strength pointer when getting strength val.
*
* Revision 1.47 2002/09/06 04:56:29 steve
* Add support for %v is the display system task.
* Change the encoding of H and L outputs from
+256 -46
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vthread.cc,v 1.84 2002/08/28 18:38:07 steve Exp $"
#ident "$Id: vthread.cc,v 1.95 2002/11/22 00:01:50 steve Exp $"
#endif
# include "vthread.h"
@@ -72,7 +72,7 @@
*
* A --> C(zombie) --> X --> B
*
* If A then executes 2 %joins, it will read C and X (when it ends)
* If A then executes 2 %joins, it will reap C and X (when it ends)
* leaving B in purgatory. What's worse, A will block on the schedules
* of X and C instead of C and B, possibly creating incorrect timing.
*
@@ -103,6 +103,7 @@ struct vthread_s {
unsigned i_have_ended :1;
unsigned waiting_for_event :1;
unsigned is_scheduled :1;
unsigned fork_count :8;
/* This points to the sole child of the thread. */
struct vthread_s*child;
/* This points to my parent, if I have one. */
@@ -213,7 +214,7 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
thr->nbits = 4 * (CPU_WORD_BITS/2);
thr->child = 0;
thr->parent = 0;
thr->wait_next = 0;
thr->wait_next = 0;
/* If the target scope never held a thread, then create a
header cell for it. This is a stub to make circular lists
@@ -241,6 +242,7 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
thr->i_have_ended = 0;
thr->waiting_for_event = 0;
thr->is_scheduled = 0;
thr->fork_count = 0;
thr_put_bit(thr, 0, 0);
thr_put_bit(thr, 1, 1);
@@ -256,15 +258,17 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
*/
static void vthread_reap(vthread_t thr)
{
assert(thr->wait_next == 0);
free(thr->bits);
thr->bits = 0;
if (thr->child)
if (thr->child) {
assert(thr->child->parent == thr);
thr->child->parent = thr->parent;
if (thr->parent)
}
if (thr->parent) {
assert(thr->parent->child == thr);
thr->parent->child = thr->child;
}
thr->child = 0;
thr->parent = 0;
@@ -277,8 +281,11 @@ static void vthread_reap(vthread_t thr)
/* If this thread is not scheduled, then is it safe to delete
it now. Otherwise, let the schedule event (which will
execute the thread at of_ZOMBIE) delete the object. */
if (thr->is_scheduled == 0)
if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) {
assert(thr->fork_count == 0);
assert(thr->wait_next == 0);
delete thr;
}
}
void vthread_mark_scheduled(vthread_t thr)
@@ -480,6 +487,32 @@ bool of_ASSIGN_D(vthread_t thr, vvp_code_t cp)
return true;
}
/*
* This is %assign/v0 <label>, <delay>, <bit>
* Index register 0 contains a vector width.
*/
bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
{
unsigned wid = thr->index[0];
assert(wid > 0);
assert(wid < 0x10000);
unsigned delay = cp->bit_idx[0];
unsigned bit = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
unsigned char bit_val = thr_get_bit(thr, bit);
schedule_assign(iptr, bit_val, delay);
if (bit >= 4)
bit += 1;
}
return true;
}
bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
@@ -752,14 +785,63 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
return false;
}
static bool do_disable(vthread_t thr, vthread_t match)
{
bool flag = false;
/* Pull the target thread out of its scope. */
thr->scope_next->scope_prev = thr->scope_prev;
thr->scope_prev->scope_next = thr->scope_next;
/* Turn the thread off by setting is program counter to
zero and setting an OFF bit. */
thr->pc = 0;
thr->i_have_ended = 1;
/* Turn off all the children of the thread. Simulate a %join
for as many times as needed to clear the results of all the
%forks that this thread has done. */
while (thr->fork_count > 0) {
vthread_t tmp = thr->child;
assert(tmp);
assert(tmp->parent == thr);
tmp->schedule_parent_on_end = 0;
if (do_disable(tmp, match))
flag = true;
thr->fork_count -= 1;
vthread_reap(tmp);
}
if (thr->schedule_parent_on_end) {
/* If a parent is waiting in a %join, wake it up. */
assert(thr->parent);
assert(thr->parent->fork_count > 0);
thr->parent->fork_count -= 1;
schedule_vthread(thr->parent, 0, true);
vthread_reap(thr);
} else if (thr->parent) {
/* If the parent is yet to %join me, let its %join
do the reaping. */
//assert(tmp->is_scheduled == 0);
} else {
/* No parent at all. Goodby. */
vthread_reap(thr);
}
return flag || (thr == match);
}
/*
* Implement the %disable instruction by scanning the target scope for
* all the target threads. Kill the target threads and wake up a
* parent that is attempting a %join.
*
* XXXX BUG BUG!
* The scheduler probably still has a pointer to me, and this reaping
* will destroy this object. The result: dangling pointer.
*/
bool of_DISABLE(vthread_t thr, vvp_code_t cp)
{
@@ -774,38 +856,14 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
while (head->scope_next != head) {
vthread_t tmp = head->scope_next;
/* Pull the target thread out of the scope. */
tmp->scope_next->scope_prev = tmp->scope_prev;
tmp->scope_prev->scope_next = tmp->scope_next;
/* XXXX I don't support disabling threads with children. */
assert(tmp->child == 0);
/* XXXX Don't know how to disable waiting threads. */
assert(tmp->waiting_for_event == 0);
/* If I am disabling myself, that remember that fact so
that I can finish this statement differently. */
if (tmp == thr)
disabled_myself_flag = true;
tmp->pc = 0;
tmp->i_have_ended = 1;
if (tmp->schedule_parent_on_end) {
/* If a parent is waiting in a %join, wake it up. */
assert(tmp->parent);
schedule_vthread(tmp->parent, 0, true);
vthread_reap(tmp);
} else if (tmp->parent) {
/* If the parent is yet to %join me, let its %join
do the reaping. */
//assert(tmp->is_scheduled == 0);
} else {
/* No parent at all. Goodby. */
vthread_reap(tmp);
}
if (do_disable(tmp, thr))
disabled_myself_flag = true;
}
return ! disabled_myself_flag;
@@ -1146,7 +1204,7 @@ bool of_DIV_S(vthread_t thr, vvp_code_t cp)
bool of_END(vthread_t thr, vvp_code_t)
{
assert(! thr->waiting_for_event);
assert( thr->fork_count == 0 );
thr->i_have_ended = 1;
thr->pc = 0;
@@ -1155,6 +1213,9 @@ bool of_END(vthread_t thr, vvp_code_t)
%join for the parent. */
if (thr->schedule_parent_on_end) {
assert(thr->parent);
assert(thr->parent->fork_count > 0);
thr->parent->fork_count -= 1;
schedule_vthread(thr->parent, 0, true);
vthread_reap(thr);
return false;
@@ -1196,6 +1257,9 @@ bool of_FORK(vthread_t thr, vvp_code_t cp)
assert(child->child->parent == thr);
child->child->parent = child;
}
thr->fork_count += 1;
schedule_vthread(child, 0, true);
return true;
}
@@ -1327,8 +1391,12 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
assert(thr->child);
assert(thr->child->parent == thr);
assert(thr->fork_count > 0);
/* If the child has already ended, reap it now. */
if (thr->child->i_have_ended) {
thr->fork_count -= 1;
vthread_reap(thr->child);
return true;
}
@@ -1372,6 +1440,21 @@ bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0];
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
thr_put_bit(thr, bit, functor_get(iptr));
}
return true;
}
bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
@@ -1590,9 +1673,15 @@ bool of_MOV(vthread_t thr, vvp_code_t cp)
unsigned addr2 = (test_addr) / (CPU_WORD_BITS/2);
if (addr1 == addr2) {
unsigned sh1 = cp->bit_idx[0] % (CPU_WORD_BITS/2);
unsigned sh2 = (test_addr+1) % (CPU_WORD_BITS/2);
unsigned sh2 = (test_addr % (CPU_WORD_BITS/2)) + 1;
unsigned long mask;
if ( (sh2-sh1) == CPU_WORD_BITS/2)
mask = 0UL;
else
mask = ULONG_MAX << ((sh2 - sh1) * 2UL);
unsigned long mask = ULONG_MAX << ((sh2 - sh1) * 2UL);
mask = (~mask) << sh1*2UL;
cp->number = ~mask;
@@ -1815,6 +1904,37 @@ bool of_MULI(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_NAND(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb == 0) || (rb == 0)) {
thr_put_bit(thr, idx1, 1);
} else if ((lb == 1) && (rb == 1)) {
thr_put_bit(thr, idx1, 0);
} else {
thr_put_bit(thr, idx1, 2);
}
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
return true;
}
bool of_NOOP(vthread_t thr, vvp_code_t cp)
{
return true;
@@ -1992,6 +2112,36 @@ bool of_OR(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_NOR(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[0] >= 4);
unsigned idx1 = cp->bit_idx[0];
unsigned idx2 = cp->bit_idx[1];
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
unsigned lb = thr_get_bit(thr, idx1);
unsigned rb = thr_get_bit(thr, idx2);
if ((lb == 1) || (rb == 1)) {
thr_put_bit(thr, idx1, 0);
} else if ((lb == 0) && (rb == 0)) {
thr_put_bit(thr, idx1, 1);
} else {
thr_put_bit(thr, idx1, 2);
}
idx1 += 1;
if (idx2 >= 4)
idx2 += 1;
}
return true;
}
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
bool of_SET(vthread_t thr, vvp_code_t cp)
@@ -2010,6 +2160,29 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
return true;
}
bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
{
assert(cp->bit_idx[1] > 0);
unsigned bit = cp->bit_idx[0];
if (bit >= 4) {
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
unsigned char bit_val = thr_get_bit(thr, bit);
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
functor_set(iptr, bit_val, strong_values[bit_val], true);
}
} else {
unsigned char bit_val = strong_values[bit];
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1) {
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
functor_set(iptr, bit, bit_val, true);
}
}
return true;
}
/*
* Implement the %set/x instruction:
*
@@ -2018,17 +2191,19 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
* The single bit goes into the indexed functor. Abort the instruction
* if the index is <0.
*/
bool of_SET_X(vthread_t thr, vvp_code_t cp)
bool of_SET_X0(vthread_t thr, vvp_code_t cp)
{
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
long idx = thr->index[cp->bit_idx[1]&3];
long idx = thr->index[0];
/* If idx < 0, then the index value is probably generated from
an undefined value. At any rate, this is defined to have no
effect so quit now. */
if (idx < 0) {
if (idx < 0)
return true;
if (idx > cp->bit_idx[1])
return true;
}
/* Form the functor pointer from the base pointer and the
index from the index register. */
@@ -2046,6 +2221,8 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
unsigned wid = cp->number;
unsigned long shift = thr->index[0];
assert(base >= 4);
if (shift >= wid) {
for (unsigned idx = 0 ; idx < wid ; idx += 1)
thr_put_bit(thr, base+idx, 0);
@@ -2319,6 +2496,39 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
/*
* $Log: vthread.cc,v $
* Revision 1.95 2002/11/22 00:01:50 steve
* Careful of left operands to shift that are constant.
*
* Revision 1.94 2002/11/21 22:43:14 steve
* %set/x0 instruction to support bounds checking.
*
* Revision 1.93 2002/11/08 04:59:58 steve
* Add the %assign/v0 instruction.
*
* Revision 1.92 2002/11/07 03:11:43 steve
* functor_set takes bit and strength, not 2 strengths.
*
* Revision 1.91 2002/11/07 02:32:39 steve
* Add vector set and load instructions.
*
* Revision 1.90 2002/11/05 03:46:44 steve
* Fix mask calculate when MOV_b is right on the word boundary.
*
* Revision 1.89 2002/09/21 23:47:30 steve
* Remove some now useless asserts.
*
* Revision 1.88 2002/09/21 04:55:00 steve
* Fix disable in arbitrary fork/join situations.
*
* Revision 1.87 2002/09/20 03:59:34 steve
* disable threads with children.
*
* Revision 1.86 2002/09/18 04:29:55 steve
* Add support for binary NOR operator.
*
* Revision 1.85 2002/09/12 15:49:43 steve
* Add support for binary nand operator.
*
* Revision 1.84 2002/08/28 18:38:07 steve
* Add the %subi instruction, and use it where possible.
*
+6 -1
View File
@@ -1,5 +1,5 @@
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_vpi.cc,v 1.5 2002/08/12 01:35:09 steve Exp $"
#ident "$Id: vvp_vpi.cc,v 1.6 2002/12/11 23:55:22 steve Exp $"
#endif
#include <stdarg.h>
@@ -27,6 +27,7 @@ void vvp_vpi_init()
vvpt.vpi_iterate = vpi_iterate;
vvpt.vpi_scan = vpi_scan;
vvpt.vpi_handle_by_index = vpi_handle_by_index;
vvpt.vpi_handle_by_name = vpi_handle_by_name;
vvpt.vpi_get_time = vpi_get_time;
vvpt.vpi_get = vpi_get;
vvpt.vpi_get_str = vpi_get_str;
@@ -39,6 +40,10 @@ void vvp_vpi_init()
/*
* $Log: vvp_vpi.cc,v $
* Revision 1.6 2002/12/11 23:55:22 steve
* Add vpi_handle_by_name to the VPI interface,
* and bump the vpithunk magic number.
*
* Revision 1.5 2002/08/12 01:35:09 steve
* conditional ident string using autoconfig.
*