mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-25 07:16:52 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04ada23119 | ||
|
|
46253ed873 | ||
|
|
1a9ab8ec84 | ||
|
|
47db309d30 | ||
|
|
7de4108bad | ||
|
|
9a5a00f836 | ||
|
|
07a427bf28 | ||
|
|
dfc9a9474a | ||
|
|
54206ef92b | ||
|
|
ddd43f1378 | ||
|
|
38ccb12eb0 | ||
|
|
ca3bf14fb6 | ||
|
|
982474899b | ||
|
|
ad6ff5562d | ||
|
|
d4cd1dbd27 | ||
|
|
3c1426e631 | ||
|
|
c3a1a9514f | ||
|
|
f56d763411 | ||
|
|
4ec91047dd | ||
|
|
0579ae08cd | ||
|
|
9074999666 | ||
|
|
0458ab5a53 | ||
|
|
4a3459c87c | ||
|
|
301cbe31ad | ||
|
|
165dd82bb2 | ||
|
|
9c3b3246c8 | ||
|
|
6416f8b90e | ||
|
|
e6eae5fd15 | ||
|
|
aa3a6dba4e | ||
|
|
dedae73761 | ||
|
|
d7f3d00f5c | ||
|
|
c2070777b2 | ||
|
|
42b34c2ce6 | ||
|
|
6fbfdd8f3f | ||
|
|
bee3acfd12 | ||
|
|
2e279b61dd | ||
|
|
8ab909a765 | ||
|
|
cca07fa42d | ||
|
|
5b81798205 | ||
|
|
a8a82df47d | ||
|
|
e62e1d89b6 | ||
|
|
c032186133 | ||
|
|
b89e138404 | ||
|
|
9f80ed32b6 | ||
|
|
c16a4a3950 | ||
|
|
90fa90a508 | ||
|
|
aaa734690f | ||
|
|
88da7804c4 | ||
|
|
8604f922a5 | ||
|
|
807a758f7c | ||
|
|
ef55086543 | ||
|
|
2001903c89 | ||
|
|
751e4e4c79 | ||
|
|
9d91b5db4c | ||
|
|
9a3c9507ed | ||
|
|
d71d52bfe9 | ||
|
|
8e30bc9f9e | ||
|
|
412518d1ca | ||
|
|
03afbf157b | ||
|
|
00b2d467e4 | ||
|
|
856829d299 | ||
|
|
2fafe6866f | ||
|
|
b9188ad0ca | ||
|
|
0ccb9139c9 | ||
|
|
18e402ddc8 | ||
|
|
b82d3165da | ||
|
|
91580d1fcc | ||
|
|
35d7384903 | ||
|
|
4539632f34 | ||
|
|
0651f246b2 | ||
|
|
6d0dee9341 | ||
|
|
c692f1708c | ||
|
|
d91733d32c | ||
|
|
cd7378ff3f | ||
|
|
c98ce4a029 | ||
|
|
d035a7e92c | ||
|
|
6db6359363 | ||
|
|
5c07a29e46 | ||
|
|
42d9094e9b | ||
|
|
1742231eba | ||
|
|
3178f886b7 | ||
|
|
cbc4a0ab52 | ||
|
|
cfd8cbf850 | ||
|
|
013b18b3dc | ||
|
|
db9f20b21a | ||
|
|
f611260089 | ||
|
|
e34e3a4875 | ||
|
|
aa8869a3c7 | ||
|
|
588931fcf2 | ||
|
|
07e49e215e | ||
|
|
1b84893ccb | ||
|
|
6445bb6915 | ||
|
|
db899bd1b5 | ||
|
|
c6dcc38fe0 | ||
|
|
b0a7909162 | ||
|
|
d7ae85a13a | ||
|
|
46ee38b466 | ||
|
|
bc6a958a50 | ||
|
|
0e751ad975 | ||
|
|
de94d09706 | ||
|
|
2f88a631df | ||
|
|
4e5dd49a37 | ||
|
|
8463dcc878 | ||
|
|
18bc2f65b3 | ||
|
|
b4e8ea5a0c | ||
|
|
06a8087cb5 | ||
|
|
a9dfef0f55 | ||
|
|
e4540c3d0d | ||
|
|
0cc8396244 | ||
|
|
946693ad4d | ||
|
|
f014d4c533 | ||
|
|
6a1e3f7e27 | ||
|
|
7ad66b0725 | ||
|
|
0341c0c727 | ||
|
|
20c8550139 | ||
|
|
39aa90ce59 | ||
|
|
6c67a64fc3 | ||
|
|
86032c0aa5 | ||
|
|
f243f694b4 | ||
|
|
276ae3e228 | ||
|
|
fe6756eb07 | ||
|
|
539e494bc0 | ||
|
|
1298656c22 |
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.h,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
@@ -61,6 +61,10 @@ class hname_t {
|
||||
const char*peek_name(unsigned idx) const;
|
||||
const char*peek_tail_name() const;
|
||||
|
||||
// Return the number of components in the hierarchical
|
||||
// name. If this is a simple name, this will return 1.
|
||||
unsigned component_count() const;
|
||||
|
||||
friend ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
private:
|
||||
@@ -79,6 +83,10 @@ extern bool operator == (const hname_t&, const hname_t&);
|
||||
|
||||
/*
|
||||
* $Log: HName.h,v $
|
||||
* Revision 1.4 2002/11/02 03:27:51 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+25
-5
@@ -17,13 +17,18 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.cc,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include <cstdio>
|
||||
# include <sstream>
|
||||
|
||||
LineInfo::LineInfo()
|
||||
: file_(0), lineno_(0)
|
||||
{
|
||||
}
|
||||
|
||||
LineInfo::~LineInfo()
|
||||
{
|
||||
@@ -31,9 +36,11 @@ LineInfo::~LineInfo()
|
||||
|
||||
string LineInfo::get_line() const
|
||||
{
|
||||
char buf[8];
|
||||
sprintf(buf, "%u", lineno_);
|
||||
return string(file_? file_ : "") + ":" + buf;
|
||||
ostringstream buf;
|
||||
buf << (file_? file_ : "") << ":" << lineno_;
|
||||
|
||||
string res = buf.str();
|
||||
return res;
|
||||
}
|
||||
|
||||
void LineInfo::set_line(const LineInfo&that)
|
||||
@@ -42,8 +49,21 @@ void LineInfo::set_line(const LineInfo&that)
|
||||
lineno_ = that.lineno_;
|
||||
}
|
||||
|
||||
void LineInfo::set_file(const char*f)
|
||||
{
|
||||
file_ = f;
|
||||
}
|
||||
|
||||
void LineInfo::set_lineno(unsigned n)
|
||||
{
|
||||
lineno_ = n;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.cc,v $
|
||||
* Revision 1.4 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+7
-4
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.h,v 1.6 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -35,15 +35,15 @@
|
||||
|
||||
class LineInfo {
|
||||
public:
|
||||
LineInfo() : file_(0), lineno_(0) { }
|
||||
LineInfo();
|
||||
~LineInfo();
|
||||
|
||||
string get_line() const;
|
||||
|
||||
void set_line(const LineInfo&that);
|
||||
|
||||
void set_file(const char*f) { file_ = f; }
|
||||
void set_lineno(unsigned n) { lineno_ = n; }
|
||||
void set_file(const char*f);
|
||||
void set_lineno(unsigned n);
|
||||
|
||||
private:
|
||||
const char* file_;
|
||||
@@ -52,6 +52,9 @@ class LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.7 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+21
-27
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.134 2002/09/16 00:30:33 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.143 2003/01/26 21:15:58 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -25,7 +25,7 @@ SHELL = /bin/sh
|
||||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -67,7 +67,7 @@ ifeq ('@HAVE_IPAL@','yes')
|
||||
TARGETS += tgt-pal
|
||||
endif
|
||||
|
||||
all: ivl@EXEEXT@ libvpi.a
|
||||
all: ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS) ; do (cd $$dir ; $(MAKE) all); done
|
||||
cd vpi ; $(MAKE) all
|
||||
cd ivlpp ; $(MAKE) all
|
||||
@@ -83,6 +83,10 @@ all: dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
SUBDIRS += driver-vpi
|
||||
endif
|
||||
|
||||
else
|
||||
all: iverilog-vpi
|
||||
endif
|
||||
@@ -92,7 +96,7 @@ endif
|
||||
check: all
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) check); done
|
||||
driver/iverilog -Ccheck.conf -ocheck.vvp -tvvp-check -B./ivlpp $(srcdir)/examples/hello.vl
|
||||
vvp/vvp -M./vpi ./check.vvp | grep 'Hello, World'
|
||||
vvp/vvp -M- -M./vpi ./check.vvp | grep 'Hello, World'
|
||||
|
||||
clean:
|
||||
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc lexor_keyword.cc ivl@EXEEXT@ libivl.a libvpi.a iverilog-vpi
|
||||
@@ -124,11 +128,11 @@ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_udp.o pad_to_width.o \
|
||||
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o sync.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o \
|
||||
PTask.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
@@ -137,19 +141,6 @@ Makefile: Makefile.in config.h.in config.status
|
||||
./config.status
|
||||
|
||||
|
||||
libvpi.a: vpithunk.o
|
||||
rm -f $@
|
||||
ar cvq $@ vpithunk.o
|
||||
ranlib $@
|
||||
|
||||
# The vpithunk.c file (that makes up the libvpi.a library) needs to
|
||||
# be make with PIC flags, because shared objects load it.
|
||||
vpithunk.o: vpithunk.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
# Under Windows (mingw) I need to make the ivl.exe in two steps.
|
||||
# The first step makes an ivl.exe that dlltool can use to make an
|
||||
@@ -216,12 +207,12 @@ INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
|
||||
else
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(libdir)/libvpi.a $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
cd vpi ; $(MAKE) install
|
||||
cd ivlpp ; $(MAKE) install
|
||||
cd driver ; $(MAKE) install
|
||||
@@ -229,16 +220,16 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
|
||||
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
|
||||
$(libdir)/libvpi.a : ./libvpi.a
|
||||
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/iverilog.conf: $(srcdir)/iverilog.conf
|
||||
# Install iverilog.conf whenever ivl.exe is installed. This
|
||||
# forces iverilog.conf to be treated similarly, in spite of
|
||||
# dates in the source bundle.
|
||||
$(libdir)/ivl/iverilog.conf: $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.conf $(libdir)/ivl/iverilog.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
@@ -270,6 +261,10 @@ $(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
|
||||
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt.vl
|
||||
|
||||
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
|
||||
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt-virtex.v
|
||||
|
||||
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
|
||||
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
|
||||
mv tmp.txt $(prefix)/QUICK_START.txt
|
||||
@@ -283,7 +278,6 @@ uninstall:
|
||||
rm -f $(libdir)/ivl/iverilog.conf
|
||||
rm -f $(libdir)/ivl/ivl
|
||||
-rmdir $(libdir)/ivl
|
||||
rm -f $(libdir)/libvpi.a
|
||||
rm -f $(bindir)/verilog
|
||||
rm -f $(bindir)/iverilog-vpi
|
||||
rm -f $(bindir)/gverilog@EXEEXT@
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.h,v 1.27 2002/08/19 02:39:16 steve Exp $"
|
||||
#ident "$Id: Module.h,v 1.28 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -29,6 +29,7 @@
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include <string>
|
||||
class PData;
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
@@ -97,6 +98,9 @@ class Module : public LineInfo {
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<string,PEvent*>events;
|
||||
|
||||
/* Keep a table of datum variables declared in the module. */
|
||||
map<string,PData*>datum;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
@@ -151,6 +155,10 @@ class Module : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.28 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.27 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PData.cc,v 1.1 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PData.h"
|
||||
|
||||
PData::PData(const hname_t&h)
|
||||
: hname_(h)
|
||||
{
|
||||
}
|
||||
|
||||
PData::~PData()
|
||||
{
|
||||
}
|
||||
|
||||
const hname_t&PData::name() const
|
||||
{
|
||||
return hname_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PData.cc,v $
|
||||
* Revision 1.1 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef __PData_H
|
||||
#define __PData_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "HName.h"
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
|
||||
/*
|
||||
* The PData object represents declaration of atomic datum such as
|
||||
* real and realtime variables. These are variables that cannot be bit
|
||||
* or part selected, but can be used in expressions.
|
||||
*/
|
||||
|
||||
class PData : public LineInfo {
|
||||
|
||||
public:
|
||||
PData(const hname_t&hname);
|
||||
~PData();
|
||||
|
||||
// Return a hierarchical name.
|
||||
const hname_t&name() const;
|
||||
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
private:
|
||||
hname_t hname_;
|
||||
|
||||
private:
|
||||
PData(const PData&);
|
||||
PData& operator= (const PData&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PData.h,v $
|
||||
* Revision 1.1 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.h,v 1.14 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: PWire.h,v 1.15 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -53,7 +53,6 @@ class PWire : public LineInfo {
|
||||
PWire(char*name, NetNet::Type t, NetNet::PortType pt);
|
||||
|
||||
// Return a hierarchical name.
|
||||
//const string name() const;
|
||||
const hname_t&path() const;
|
||||
|
||||
NetNet::Type get_wire_type() const;
|
||||
@@ -101,6 +100,10 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.15 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.14 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+24
@@ -344,6 +344,19 @@ language that are defined.
|
||||
The $sizeof function is deprecated in favor of $bits, which is
|
||||
the same thing, but included in the SystemVerilog definition.
|
||||
|
||||
$simtime
|
||||
The $simtime system function returns as a 64bit value the
|
||||
simulation time, unscaled by the time units of local
|
||||
scope. This is different from the $time and $stime functions
|
||||
which return the scaled times. This function is added for
|
||||
regression testing of the compiler and run time, but can be
|
||||
used by applications who really want the simulation time.
|
||||
|
||||
Note that the simulation time can be confusing if there are
|
||||
lots of different `timescales within a design. It is not in
|
||||
general possible to predict what the simulation precision will
|
||||
turn out to be.
|
||||
|
||||
Builtin system functions
|
||||
|
||||
Certain of the system functions have well defined meanings, so
|
||||
@@ -396,6 +409,17 @@ language that are defined.
|
||||
Icarus Verilog will override the $timeformat minimum width and
|
||||
use the explicit minimum width.
|
||||
|
||||
vpiScope iterator on vpiScope objects.
|
||||
|
||||
In the VPI, the normal way to iterate over vpiScope objects
|
||||
contained within a vpiScope object, is the vpiInternalScope
|
||||
iterator. Icarus Verilog adds support for the vpiScope
|
||||
iterator of a vpiScope object, that iterates over *everything*
|
||||
the is contained in the current scope. This is useful in cases
|
||||
where one wants to iterate over all the objects in a scope
|
||||
without iterating over all the contained types explicitly.
|
||||
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
|
||||
+9
-1
@@ -23,7 +23,7 @@
|
||||
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.cc,v 1.2 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: StringHeap.cc,v 1.3 2003/01/16 21:44:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
@@ -38,6 +38,7 @@ StringHeap::StringHeap()
|
||||
{
|
||||
cell_base_ = 0;
|
||||
cell_ptr_ = HEAPCELL;
|
||||
cell_count_ = 0;
|
||||
}
|
||||
|
||||
StringHeap::~StringHeap()
|
||||
@@ -55,6 +56,8 @@ const char* StringHeap::add(const char*text)
|
||||
if (rem < (len+1)) {
|
||||
cell_base_ = (char*)malloc(HEAPCELL);
|
||||
cell_ptr_ = 0;
|
||||
cell_count_ += 1;
|
||||
assert(cell_base_ != 0);
|
||||
}
|
||||
|
||||
char*res = cell_base_ + cell_ptr_;
|
||||
@@ -62,11 +65,16 @@ const char* StringHeap::add(const char*text)
|
||||
cell_ptr_ += len;
|
||||
cell_base_[cell_ptr_++] = 0;
|
||||
|
||||
assert(cell_ptr_ <= HEAPCELL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.cc,v $
|
||||
* Revision 1.3 2003/01/16 21:44:46 steve
|
||||
* Keep some debugging status.
|
||||
*
|
||||
* Revision 1.2 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+5
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.h,v 1.2 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: StringHeap.h,v 1.3 2003/01/16 21:44:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
class StringHeap {
|
||||
@@ -35,6 +35,7 @@ class StringHeap {
|
||||
|
||||
char*cell_base_;
|
||||
unsigned cell_ptr_;
|
||||
unsigned cell_count_;
|
||||
|
||||
private: // not implemented
|
||||
StringHeap(const StringHeap&);
|
||||
@@ -43,6 +44,9 @@ class StringHeap {
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.3 2003/01/16 21:44:46 steve
|
||||
* Keep some debugging status.
|
||||
*
|
||||
* Revision 1.2 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+5
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: config.h.in,v 1.5 2002/08/11 23:39:33 steve Exp $"
|
||||
#ident "$Id: config.h.in,v 1.6 2003/01/10 19:01:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -37,6 +37,7 @@
|
||||
# undef HAVE_TIMES
|
||||
# undef HAVE_IOSFWD
|
||||
# undef HAVE_GETOPT_H
|
||||
# undef HAVE_LIBIBERTY_H
|
||||
# undef HAVE_MALLOC_H
|
||||
# undef HAVE_DLFCN_H
|
||||
# undef HAVE_DL_H
|
||||
@@ -46,6 +47,9 @@
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.6 2003/01/10 19:01:04 steve
|
||||
* Only use libiberty.h if available.
|
||||
*
|
||||
* Revision 1.5 2002/08/11 23:39:33 steve
|
||||
* Remove VVM option.
|
||||
*
|
||||
|
||||
+5
-3
@@ -32,7 +32,7 @@ fi
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_CHECK_HEADERS(getopt.h malloc.h iosfwd sys/wait.h)
|
||||
AC_CHECK_HEADERS(getopt.h malloc.h libiberty.h iosfwd sys/wait.h)
|
||||
|
||||
AC_MSG_CHECKING(for sys/times)
|
||||
AC_TRY_LINK(
|
||||
@@ -190,6 +190,8 @@ if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
|
||||
AC_SUBST(MINGW32)
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
@@ -206,7 +208,7 @@ CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -o $WIN32 = "yes"; then
|
||||
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
@@ -255,4 +257,4 @@ AC_MSG_RESULT($ident_support)
|
||||
|
||||
AC_CONFIG_SUBDIRS(vvp tgt-vvp tgt-fpga libveriuser)
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
+22
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.136 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -447,6 +447,8 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
} else if (var_) {
|
||||
o << "<real " << var_->basename() << ">";
|
||||
} else {
|
||||
o << "";
|
||||
}
|
||||
@@ -733,6 +735,11 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
}
|
||||
|
||||
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) {
|
||||
o << " real " << cur->basename() << " // "
|
||||
<< cur->get_line() << endl;
|
||||
}
|
||||
|
||||
/* Dump the events in this scope. */
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
|
||||
o << " event " << cur->name() << "; nprobe="
|
||||
@@ -896,6 +903,11 @@ void NetEConst::dump(ostream&o) const
|
||||
o << value_;
|
||||
}
|
||||
|
||||
void NetECReal::dump(ostream&o) const
|
||||
{
|
||||
o << value_;
|
||||
}
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
{
|
||||
o << "<scope=" << scope_->name() << ">";
|
||||
@@ -975,6 +987,11 @@ void NetEUnary::dump(ostream&o) const
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEVariable::dump(ostream&o) const
|
||||
{
|
||||
o << var_->basename();
|
||||
}
|
||||
|
||||
void Design::dump(ostream&o) const
|
||||
{
|
||||
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
|
||||
@@ -1004,6 +1021,10 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.136 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.135 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
iverilog-vpi.exe
|
||||
@@ -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@
|
||||
@@ -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,®KeyType,NULL,®KeySize);
|
||||
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,®KeyType,regKeyBuffer,®KeySize);
|
||||
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);
|
||||
}
|
||||
Executable
+38
@@ -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
@@ -3,9 +3,7 @@
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version. In order to redistribute the software in
|
||||
# binary form, you will need a Picture Elements Binary Software
|
||||
# License.
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -18,12 +16,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.15 2002/08/10 22:36:59 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.16 2002/12/08 03:06:30 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
+42
-2
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: main.c,v 1.47 2002/08/12 01:27:48 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.50 2003/01/10 19:01:04 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -44,8 +44,10 @@ const char HELP[] =
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#ifdef HAVE_LIBIBERTY_H
|
||||
#include <libiberty.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
@@ -119,6 +121,35 @@ char tmp[MAXSIZE];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
#ifdef __MINGW32__
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
static FILE*fopen_safe(const char*path)
|
||||
{
|
||||
FILE*file = 0;
|
||||
int fd;
|
||||
|
||||
fd = _open(path, _O_WRONLY|_O_CREAT|_O_EXCL, 0700);
|
||||
if (fd != -1)
|
||||
file = _fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
}
|
||||
#else
|
||||
# include <fcntl.h>
|
||||
static FILE*fopen_safe(const char*path)
|
||||
{
|
||||
FILE*file = 0;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0700);
|
||||
if (fd != -1)
|
||||
file = fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char*my_tempfile(const char*str, FILE**fout)
|
||||
{
|
||||
FILE*file;
|
||||
@@ -148,7 +179,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
|
||||
while ((retry > 0) && (file == NULL)) {
|
||||
unsigned code = rand();
|
||||
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
|
||||
file = fopen(pathbuf, "w");
|
||||
file = fopen_safe(pathbuf);
|
||||
retry -= 1;
|
||||
}
|
||||
|
||||
@@ -657,6 +688,15 @@ int main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.50 2003/01/10 19:01:04 steve
|
||||
* Only use libiberty.h if available.
|
||||
*
|
||||
* Revision 1.49 2002/12/04 03:26:59 steve
|
||||
* Mingw32 compatible temp file management.
|
||||
*
|
||||
* Revision 1.48 2002/12/04 02:29:36 steve
|
||||
* Use O_EXCL when opening temp files.
|
||||
*
|
||||
* Revision 1.47 2002/08/12 01:27:48 steve
|
||||
* Escape the backslash in the windows file name.
|
||||
*
|
||||
|
||||
+30
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.8 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: dup_expr.cc,v 1.10 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -65,6 +65,21 @@ NetETernary* NetETernary::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUFunc* NetEUFunc::dup_expr() const
|
||||
{
|
||||
NetEUFunc*tmp;
|
||||
svector<NetExpr*> tmp_parms (parms_.count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = new NetEUFunc(func_, result_->dup_expr(), tmp_parms);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUnary* NetEUnary::dup_expr() const
|
||||
{
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||
@@ -72,8 +87,21 @@ NetEUnary* NetEUnary::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEVariable* NetEVariable::dup_expr() const
|
||||
{
|
||||
NetEVariable*tmp = new NetEVariable(var_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.10 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.9 2002/11/09 00:25:27 steve
|
||||
* Add dup_expr for user defined function calls.
|
||||
*
|
||||
* Revision 1.8 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
@@ -97,12 +125,5 @@ NetEUnary* NetEUnary::dup_expr() const
|
||||
* Revision 1.3 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+32
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2003 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.68 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -215,6 +215,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
|
||||
if (strcmp(path_.peek_name(0), "$time") == 0)
|
||||
wid = 64;
|
||||
if (strcmp(path_.peek_name(0), "$simtime") == 0)
|
||||
wid = 64;
|
||||
if (strcmp(path_.peek_name(0), "$stime") == 0)
|
||||
wid = 32;
|
||||
|
||||
@@ -404,8 +406,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new NetEConst(verinum(val));
|
||||
NetECReal*tmp = new NetECReal(*value_);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -719,6 +722,15 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
return node;
|
||||
}
|
||||
|
||||
// If the identifier names a variable of some sort, then this
|
||||
// is a variable reference.
|
||||
if (NetVariable*var = des->find_variable(scope, path_)) {
|
||||
|
||||
NetEVariable*node = new NetEVariable(var);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Finally, if this is a scope name, then return that. Look
|
||||
// first to see if this is a name of a local scope. Failing
|
||||
// that, search globally for a heirarchical name.
|
||||
@@ -810,10 +822,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
|
||||
case '-':
|
||||
if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
|
||||
/* When taking the - of a number, turn it into a
|
||||
signed expression and extend it one bit to
|
||||
accommodate a possible sign bit. */
|
||||
verinum val = ipc->value();
|
||||
verinum zero (verinum::V0, val.len(), val.has_len());
|
||||
verinum zero (verinum::V0, val.len()+1, val.has_len());
|
||||
val = zero - val;
|
||||
val.has_sign(ipc->has_sign());
|
||||
val.has_sign(true);
|
||||
tmp = new NetEConst(val);
|
||||
delete ip;
|
||||
} else {
|
||||
@@ -885,6 +900,17 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.68 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.67 2002/12/21 00:55:57 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.66 2002/09/21 21:28:18 steve
|
||||
* Allow constant bit selects out of range.
|
||||
*
|
||||
|
||||
+74
-10
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.20 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.25 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -103,6 +103,14 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_*res = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
if (parms_[idx] == 0) {
|
||||
cerr << get_line() << ": error: Empty expressions "
|
||||
<< "not allowed in concatenations." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
|
||||
|
||||
/* If the l-value doesn't elaborate, the error was
|
||||
@@ -130,17 +138,24 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
/*
|
||||
* Handle the ident as an l-value. This includes bit and part selects
|
||||
* of that ident.
|
||||
*
|
||||
* XXXX FIXME: The search order looks for signals all the way up the
|
||||
* scope tree, then looks for memories then variables. It should be
|
||||
* looking for signals, memories and variables in parallel.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. (Wires are not allows in this context. */
|
||||
NetNet*reg = des->find_signal(scope, path_);
|
||||
|
||||
if (reg == 0) {
|
||||
NetMemory*mem = des->find_memory(scope, path_);
|
||||
if (mem != 0)
|
||||
if (NetMemory*mem = des->find_memory(scope, path_)) {
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
|
||||
if (NetVariable*var = des->find_variable(scope, path_)) {
|
||||
NetAssign_*cur = new NetAssign_(var);
|
||||
return cur;
|
||||
}
|
||||
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope->name() <<
|
||||
@@ -149,8 +164,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(reg);
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. (Wires are not allows in this context. */
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
@@ -170,16 +188,20 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
verinum*vl = lsb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *lsb_;
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
verinum*vm = msb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
if (vm == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *msb_;
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -277,12 +299,38 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
if (msb_ == 0) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": error: Cannot use part select on "
|
||||
<< "memory \"" << mem->name() << ".\"" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ && !lsb_);
|
||||
|
||||
NetExpr*ix = msb_->elaborate_expr(des, scope);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
/* Evaluate the memory index expression down as must as
|
||||
possible. Ideally, we can get it down to a constant. */
|
||||
if (! dynamic_cast<NetEConst*>(ix)) {
|
||||
NetExpr*tmp = ix->eval_tree();
|
||||
if (tmp) {
|
||||
tmp->set_line(*ix);
|
||||
delete ix;
|
||||
ix = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
@@ -299,6 +347,22 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.25 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.24 2003/01/19 00:35:39 steve
|
||||
* Detect null arguments to concatenation operator.
|
||||
*
|
||||
* Revision 1.23 2002/11/21 23:27:51 steve
|
||||
* Precalculate indices to l-value arrays.
|
||||
*
|
||||
* Revision 1.22 2002/11/21 18:15:40 steve
|
||||
* Fix const test of msb in assignment l-values.
|
||||
*
|
||||
* Revision 1.21 2002/11/02 01:10:49 steve
|
||||
* Detect memories without work index in l-value.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+105
-16
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.101 2002/09/18 04:29:55 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.105 2003/01/19 00:35:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -1437,14 +1437,79 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value.
|
||||
*/
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": sorry: I do not know how to"
|
||||
" elaborate repeat concatenation nets." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Elaborate the operands of the concatenation. */
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
|
||||
if (parms_[idx] == 0) {
|
||||
cerr << get_line() << ": error: Empty expressions "
|
||||
<< "not allowed in concatenations." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
|
||||
implicit_net_ok);
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
delete all those that did and abort myself. */
|
||||
if (errors) {
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list. */
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
|
||||
NetNet::IMPLICIT, pins);
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
}
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identifiers in continuous assignment l-values are limited to wires
|
||||
* and that ilk. Detect registers and memories here and report errors.
|
||||
*/
|
||||
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
{
|
||||
string path = scope->name();
|
||||
|
||||
NetNet*sig = des->find_signal(scope, path_);
|
||||
if (sig == 0) {
|
||||
/* Don't allow memories here. Is it a memory? */
|
||||
@@ -1455,29 +1520,41 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
cerr << get_line() << ": error: Net " << path_
|
||||
<< " is not defined in this context." << endl;
|
||||
cerr << get_line() << ": : Do you mean this? wire "
|
||||
<< path_ << " = <expr>;" << endl;
|
||||
return 0;
|
||||
if (implicit_net_ok && !error_implicit) {
|
||||
|
||||
sig = new NetNet(scope, scope->name()+"."+path_.peek_name(0),
|
||||
NetNet::IMPLICIT, 1);
|
||||
|
||||
if (warn_implicit) {
|
||||
cerr << get_line() << ": warning: implicit "
|
||||
"definition of wire " << scope->name()
|
||||
<< "." << path_.peek_name(0) << "." << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Net " << path_
|
||||
<< " is not defined in this context." << endl;
|
||||
cerr << get_line() << ": : Do you mean this? wire "
|
||||
<< path_ << " = <expr>;" << endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
|
||||
/* Don't allow registers as assign l-values. */
|
||||
if (sig->type() == NetNet::REG) {
|
||||
cerr << get_line() << ": error: registers (" << sig->name()
|
||||
<< ") cannot be l-values in continuous"
|
||||
cerr << get_line() << ": error: reg " << sig->name()
|
||||
<< "; cannot be an L-value in continuous"
|
||||
<< " assignments." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig->port_type() == NetNet::PINPUT) {
|
||||
cerr << get_line() << ": warning: assign l-value ``"
|
||||
<< sig->name() << "'' is also an input to "
|
||||
<< sig->scope()->name() << "." << endl;
|
||||
cerr << sig->get_line() << ": warning: input ``"
|
||||
<< sig->name() << "'' is coerced to inout." << endl;
|
||||
cerr << get_line() << ": warning: L-value ``"
|
||||
<< sig->name() << "'' is also an input port." << endl;
|
||||
cerr << sig->get_line() << ": warning: input "
|
||||
<< sig->name() << "; is coerced to inout." << endl;
|
||||
sig->port_type(NetNet::PINOUT);
|
||||
}
|
||||
|
||||
@@ -2207,6 +2284,18 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.105 2003/01/19 00:35:39 steve
|
||||
* Detect null arguments to concatenation operator.
|
||||
*
|
||||
* Revision 1.104 2003/01/17 05:48:35 steve
|
||||
* Remove useless variable.
|
||||
*
|
||||
* Revision 1.103 2002/12/06 03:08:19 steve
|
||||
* Reword some error messages for clarity.
|
||||
*
|
||||
* Revision 1.102 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
* Revision 1.101 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
|
||||
+24
-12
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.16 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.18 2002/12/05 02:14:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -108,11 +108,6 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
<< *ex << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (ex->expr_width() == 0) {
|
||||
cerr << ex->get_line() << ": internal error: "
|
||||
<< "Operand of concatenation has no width: "
|
||||
<< *ex << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
tmp->set(idx, ex);
|
||||
@@ -150,15 +145,26 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_ || idx_) {
|
||||
cerr << get_line() << ": error: Cannot bit/part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, hname_t(name));
|
||||
assert(res);
|
||||
delete name;
|
||||
|
||||
assert(idx_ == 0);
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (msb_) {
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -222,6 +228,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.18 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.17 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.16 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+21
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: elab_scope.cc,v 1.18 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -32,6 +32,7 @@
|
||||
*/
|
||||
|
||||
# include "Module.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
@@ -40,6 +41,7 @@
|
||||
# include "Statement.h"
|
||||
# include "netlist.h"
|
||||
# include <typeinfo>
|
||||
# include <assert.h>
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
@@ -217,6 +219,12 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
for (map<string,PData*>::const_iterator cur = datum.begin()
|
||||
; cur != datum.end() ; cur ++ ) {
|
||||
|
||||
(*cur).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
return des->errors == 0;
|
||||
}
|
||||
|
||||
@@ -341,6 +349,14 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
}
|
||||
}
|
||||
|
||||
void PData::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(hname_.component_count() == 1);
|
||||
NetVariable*tmp = new NetVariable(hname_.peek_tail_name());
|
||||
tmp->set_line(*this);
|
||||
scope->add_variable(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* The isn't really able to create new scopes, but it does create the
|
||||
* event name in the current scope, so can be done during the
|
||||
@@ -496,6 +512,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.18 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.17 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
||||
+104
-100
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.263 2002/08/28 18:54:36 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.269 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
# include <typeinfo>
|
||||
# include <strstream>
|
||||
# include <sstream>
|
||||
# include <list>
|
||||
# include "pform.h"
|
||||
# include "PEvent.h"
|
||||
@@ -314,14 +314,14 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
a unique name, and set the delay times. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < count ; idx += 1) {
|
||||
strstream tmp;
|
||||
ostringstream tmp;
|
||||
unsigned index;
|
||||
if (low < high)
|
||||
index = low + idx;
|
||||
else
|
||||
index = low - idx;
|
||||
|
||||
tmp << name << "<" << index << ">" << ends;
|
||||
tmp << name << "<" << index << ">";
|
||||
const string inm = tmp.str();
|
||||
|
||||
switch (type()) {
|
||||
@@ -612,33 +612,38 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// port. sig is the thing outside the module that
|
||||
// connects to the port.
|
||||
|
||||
NetNet*sig = (*pins)[idx]->elaborate_net(des, scope,
|
||||
prts_pin_count,
|
||||
0, 0, 0);
|
||||
if (sig == 0) {
|
||||
cerr << "internal error: Expression too complicated "
|
||||
"for elaboration." << endl;
|
||||
continue;
|
||||
NetNet*sig;
|
||||
if ((prts.count() >= 1)
|
||||
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
||||
|
||||
sig = (*pins)[idx]->elaborate_lnet(des, scope, true);
|
||||
if (sig == 0) {
|
||||
cerr << (*pins)[idx]->get_line() << ": error: "
|
||||
<< "Output port expression must support "
|
||||
<< "continuous assignment." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
sig = (*pins)[idx]->elaborate_net(des, scope,
|
||||
prts_pin_count,
|
||||
0, 0, 0);
|
||||
if (sig == 0) {
|
||||
cerr << "internal error: Expression too complicated "
|
||||
"for elaboration." << endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
|
||||
// Check that a reg is not passed as an output or inout
|
||||
// port of the module. sig is the elaborated signal in
|
||||
// the outside that is to be passed, and prts is a
|
||||
// concatenation of signals on the input that receive a
|
||||
// reg value.
|
||||
if ((sig->type() == NetNet::REG)
|
||||
&& (prts.count() >= 1)
|
||||
#ifndef NDEBUG
|
||||
if ((prts.count() >= 1)
|
||||
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
||||
cerr << get_line() << ": error: reg/variable "
|
||||
<< sig->name() << " cannot connect to "
|
||||
<< "output port " << (idx+1) << " of "
|
||||
<< my_scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
assert(sig->type() != NetNet::REG);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Check that the parts have matching pin counts. If
|
||||
// not, they are different widths. Note that idx is 0
|
||||
@@ -838,61 +843,6 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value.
|
||||
*/
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": sorry: I do not know how to"
|
||||
" elaborate repeat concatenation nets." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Elaborate the operands of the concatenation. */
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
delete all those that did and abort myself. */
|
||||
if (errors) {
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list. */
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
|
||||
NetNet::IMPLICIT, pins);
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
}
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetProc* Statement::elaborate(Design*des, NetScope*) const
|
||||
{
|
||||
@@ -976,23 +926,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
delay = elaborate_delay_expr(delay_, des, scope);
|
||||
|
||||
|
||||
/* Elaborate the r-value expression. */
|
||||
/* Elaborate the r-value expression, then try to evaluate it. */
|
||||
|
||||
assert(rval());
|
||||
|
||||
NetExpr*rv;
|
||||
|
||||
if (verinum*val = rval()->eval_const(des, scope)) {
|
||||
rv = new NetEConst(*val);
|
||||
delete val;
|
||||
|
||||
} else if (rv = rval()->elaborate_expr(des, scope)) {
|
||||
|
||||
/* OK, go on. */
|
||||
|
||||
} else {
|
||||
/* Unable to elaborate expression. Retreat. */
|
||||
NetExpr*rv = rval()->elaborate_expr(des, scope);
|
||||
if (rv == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(rv);
|
||||
|
||||
@@ -1025,7 +964,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
|
||||
if (! rv->set_width(wid)) {
|
||||
if (wid != rv->expr_width()) {
|
||||
cerr << get_line() << ": error: Unable to match "
|
||||
"expression width of " << rv->expr_width() <<
|
||||
" to l-value width of " << wid << "." << endl;
|
||||
@@ -1078,10 +1017,15 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return bl;
|
||||
}
|
||||
|
||||
{ unsigned wid = count_lval_width(lv);
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
assert(rv->expr_width() >= wid);
|
||||
/* Based on the specific type of the l-value, do cleanup
|
||||
processing on the r-value. */
|
||||
if (NetVariable*tmp = lv->var()) {
|
||||
|
||||
} else {
|
||||
unsigned wid = count_lval_width(lv);
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
assert(rv->expr_width() >= wid);
|
||||
}
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, rv);
|
||||
@@ -1126,6 +1070,12 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
assert(rv);
|
||||
|
||||
/* Try to evaluate the expression, at least as far as possible. */
|
||||
if (NetExpr*tmp = rv->eval_tree()) {
|
||||
delete rv;
|
||||
rv = tmp;
|
||||
}
|
||||
|
||||
{ unsigned wid = count_lval_width(lv);
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
@@ -1401,6 +1351,17 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
|
||||
|
||||
/* Attempt to pre-evaluate the parameters. It may be
|
||||
possible to at least partially reduce the
|
||||
expression. */
|
||||
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
|
||||
NetExpr*tmp = eparms[idx]->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete eparms[idx];
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
|
||||
@@ -1639,6 +1600,30 @@ NetProc* PDelayStatement::elaborate(Design*des, NetScope*scope) const
|
||||
/* Ah, the delay is not constant. OK, elaborate the
|
||||
expression and let the run-time handle it. */
|
||||
NetExpr*dex = delay_->elaborate_expr(des, scope);
|
||||
|
||||
/* If the local scope units are different from the
|
||||
simulation precision, then extend the expression to
|
||||
convert the delay to simulation time. */
|
||||
if (scope->time_unit() != des->get_precision()) {
|
||||
long scale = 1;
|
||||
int unit = scope->time_unit();
|
||||
int prec = des->get_precision();
|
||||
while (unit > prec) {
|
||||
scale *= 10;
|
||||
unit -= 1;
|
||||
}
|
||||
|
||||
verinum scale_v (scale);
|
||||
NetEConst*scale_e = new NetEConst(scale_v);
|
||||
NetEBMult*scale_m = new NetEBMult('*', scale_e, dex);
|
||||
if (NetExpr*tmp = scale_m->eval_tree()) {
|
||||
dex = tmp;
|
||||
delete scale_m;
|
||||
} else {
|
||||
dex = scale_m;
|
||||
}
|
||||
}
|
||||
|
||||
if (statement_)
|
||||
return new NetPDelay(dex, statement_->elaborate(des, scope));
|
||||
else
|
||||
@@ -2522,6 +2507,25 @@ Design* elaborate(list<const char*>roots)
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.269 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.268 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.267 2002/12/21 19:42:17 steve
|
||||
* Account for local units in calculated delays.
|
||||
*
|
||||
* Revision 1.266 2002/12/05 04:15:14 steve
|
||||
* precalculate r-values of nb assignments and task arguments.
|
||||
*
|
||||
* Revision 1.265 2002/11/26 03:35:13 steve
|
||||
* Do not set width if width is already OK.
|
||||
*
|
||||
* Revision 1.264 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
* Revision 1.263 2002/08/28 18:54:36 steve
|
||||
* Evaluate nonblocking assign r-values.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.69 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.71 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -312,6 +312,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
|
||||
tgt->event(cur);
|
||||
|
||||
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_)
|
||||
tgt->variable(cur);
|
||||
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_scope(tgt);
|
||||
|
||||
@@ -411,6 +414,11 @@ void NetEConst::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_const(this);
|
||||
}
|
||||
|
||||
void NetECReal::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_creal(this);
|
||||
}
|
||||
|
||||
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_memory(this);
|
||||
@@ -462,6 +470,11 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_variable(this);
|
||||
}
|
||||
|
||||
bool emit(const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
@@ -470,11 +483,22 @@ bool emit(const Design*des, const char*type)
|
||||
return des->emit(tgt->meth);
|
||||
|
||||
}
|
||||
|
||||
cerr << "error: Code generator type " << type
|
||||
<< " not found." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.71 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.70 2002/11/03 20:36:10 steve
|
||||
* Error message for mising code generator type.
|
||||
*
|
||||
* Revision 1.69 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+60
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.42 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.44 2002/12/05 02:14:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -752,7 +752,13 @@ NetEConst* NetEConcat::eval_tree()
|
||||
<< "operand has indefinite width: "
|
||||
<< *parms_[idx] << endl;
|
||||
local_errors += 1;
|
||||
} else if (expr->expr_width() == 0) {
|
||||
cerr << expr->get_line() << ": internal error: "
|
||||
<< "Operand of concatenation has no width: "
|
||||
<< *expr << endl;
|
||||
local_errors += 1;
|
||||
}
|
||||
|
||||
gap += expr->expr_width();
|
||||
}
|
||||
|
||||
@@ -888,6 +894,53 @@ NetExpr* NetEParam::eval_tree()
|
||||
return res->dup_expr();
|
||||
}
|
||||
|
||||
NetEConst* NetESelect::eval_tree()
|
||||
{
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
|
||||
if (expr == 0) {
|
||||
NetExpr*tmp = expr_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete expr_;
|
||||
expr_ = tmp;
|
||||
}
|
||||
|
||||
expr = dynamic_cast<NetEConst*>(expr_);
|
||||
}
|
||||
|
||||
NetEConst*base = dynamic_cast<NetEConst*>(base_);
|
||||
if (base == 0) {
|
||||
NetExpr*tmp = base_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete base_;
|
||||
base_ = tmp;
|
||||
}
|
||||
|
||||
base = dynamic_cast<NetEConst*>(base_);
|
||||
}
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
verinum eval = expr->value();
|
||||
verinum oval (verinum::V0, expr_width(), true);
|
||||
long bval = base->value().as_long();
|
||||
|
||||
for (long idx = 0 ; idx < expr_width() ; idx += 1) {
|
||||
if ((bval >= eval.len()) || (bval < 0))
|
||||
oval.set(idx, verinum::Vx);
|
||||
else
|
||||
oval.set(idx, eval.get(bval));
|
||||
|
||||
bval += 1;
|
||||
}
|
||||
|
||||
NetEConst*res = new NetEConst(oval);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A ternary expression evaluation is controlled by the condition
|
||||
* expression. If the condition evaluates to true or false, then
|
||||
@@ -1134,6 +1187,12 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.44 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.43 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.42 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: sqrt-virtex.v,v 1.2 2002/11/13 01:49:43 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module is a synthesizeable square-root function. It is also a
|
||||
* detailed example of how to target Xilinx Virtex parts using
|
||||
* Icarus Verilog. In fact, for no particular reason other then to
|
||||
* be excessively specific, I will step through the process of
|
||||
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
|
||||
* generate a generic library part for larger Virtex designs.
|
||||
*
|
||||
* In addition to Icarus Verilog, you will need implementation
|
||||
* software from Xilinx. As of this writing, this example was tested
|
||||
* with Foundation 4.2i, but it should work the same with ISE and
|
||||
* Webpack software.
|
||||
*
|
||||
* This example source contains all the Verilog needed to do
|
||||
* everything described below. We use conditional compilation to
|
||||
* select the bits of Verilog that are needed to perform each specific
|
||||
* task.
|
||||
*
|
||||
* SIMULATE THE DESIGN
|
||||
*
|
||||
* This source file includes a simulation test bench. To compile the
|
||||
* program to include this test bench, use the command line:
|
||||
*
|
||||
* iverilog -DSIMULATE=1 -oa.out sqrt-virtex.v
|
||||
*
|
||||
* This generates the file "a.out" that can then be executed with the
|
||||
* command:
|
||||
*
|
||||
* vvp a.out
|
||||
*
|
||||
* This causes the simulation to run a long set of example sqrt
|
||||
* calculations. Each result is checked by the test bench to assure
|
||||
* that the result is valid. When it is done, the program prints
|
||||
* "PASSED" and finishes the simulation.
|
||||
*
|
||||
* When you take a close look at the "main" module below, you will see
|
||||
* that it uses Verilog constructs that are not synthesizeable. This
|
||||
* is fine, as we will never try to synthesize it.
|
||||
*
|
||||
* LIBRARY PARTS
|
||||
*
|
||||
* One can use the sqrt32 module to generate an EDIF file suitable for
|
||||
* use as a library part. This part can be imported to the Xilinx
|
||||
* schematic editor, then placed like any other pre-existing
|
||||
* macro. One can also pass the generated EDIF as a precompiled macro
|
||||
* that other designers may use as they see fit.
|
||||
*
|
||||
* To make an EDIF file from the sqrt32 module, execute the command:
|
||||
*
|
||||
* iverilog -osqrt32.edf -tfpga -parch=virtex sqrt-virtex.v
|
||||
*
|
||||
* The -parch=virtex tells the code generator to generate code for the
|
||||
* virtex architecture family (we don't yet care what specific part)
|
||||
* and the -osqrt32.edf places the output into the file
|
||||
* sqrt32.edf.
|
||||
*
|
||||
* Without any preprocessor directives, the only module is the sqrt32
|
||||
* module, so sqrt32 is compiled as the root. The ports of the module
|
||||
* are automatically made into ports of the sqrt32.edf netlist, and
|
||||
* the contents of the sqrt32 module are connected approprately.
|
||||
*
|
||||
* COMPLETE CHIP DESIGNS
|
||||
*
|
||||
* To make a complete chip design, there are other bits that need to
|
||||
* be accounted for. Signals must be assigned to pins, and some
|
||||
* special devices may need to be created. We also want to write into
|
||||
* the EDIF file complete part information so that the implementation
|
||||
* tools know how to route the complete design. The command to compile
|
||||
* for our target part is:
|
||||
*
|
||||
* iverilog -ochip.edf -tfpga \
|
||||
* -parch=virtex -ppart=XC2S15-VQ100 \
|
||||
* -DMAKE_CHIP=1 sqrt-virtex.v
|
||||
*
|
||||
* This command uses the "chip" module as the root. This module in
|
||||
* turn has ports that are destined to be the pins of the completed
|
||||
* part. The -ppart= option gives complete part information, that is
|
||||
* in turn written into the EDIF file. This saves us the drudgery of
|
||||
* repeating that part number for later commands.
|
||||
*
|
||||
* The next steps involve Xilinx software, and to talk to Xilinx
|
||||
* software, the netlist must be in the form of an "ngd" file, a
|
||||
* binary netlist format. The command:
|
||||
*
|
||||
* ngdbuild chip.edf chip.ngd
|
||||
*
|
||||
* does the trick. The input to ngdbuild is the chip.edf file created
|
||||
* by Icarus Verilog, and the output is the chip.ngd file that the
|
||||
* implementation tools may read. From this point, it is best to refer
|
||||
* to Xilinx documentation for the software you are using, but the
|
||||
* quick summary is:
|
||||
*
|
||||
* map -o map.ncd chip.ngd
|
||||
* par -w map.ncd chip.ncd
|
||||
*
|
||||
* The result of this sequence of commands is the chip.ncd file that
|
||||
* is ready to be viewed by FPGA Edit, or converted to a bit stream,
|
||||
* or whatever.
|
||||
*
|
||||
* POST MAP SIMULATION
|
||||
*
|
||||
* Warm fuzzies are good, and retesting your design after the part
|
||||
* is mapped by the Xilinx backend tools is a cheap source of fuzzies.
|
||||
* The command to make a Verilog file out of the mapped design is:
|
||||
*
|
||||
* ngd2ver chip.ngd chip_root.v
|
||||
*
|
||||
* This command creates from the chip.ngd the file "chip_root.v" that
|
||||
* contains Verilog code that simulates the mapped design. This output
|
||||
* Verilog has the single root module "chip_root", which came from the
|
||||
* name of the root module when we were making hte EDIF file in the
|
||||
* first place. The module has ports named just line the ports of the
|
||||
* chip_root module below.
|
||||
*
|
||||
* The generated Verilog uses the library in the directory
|
||||
* $(XILINX)/verilog/src/simprims. This directory comes with the ISE
|
||||
* WebPACK installation that you are using. Icarus Verilog is able to
|
||||
* simulate using that library.
|
||||
*
|
||||
* To compile a post-map simulation of the chip_root.v, use the
|
||||
* command:
|
||||
*
|
||||
* iverilog -DSIMULATE -DPOST_MAP -ob.out \
|
||||
* -y $(XILINX)/verilog/src/simprims \
|
||||
* sqrt-virtex.v chip_root.v \
|
||||
* $(XILINX)/verilog/src/glbl.v
|
||||
*
|
||||
* This command line generates b.out from the source files
|
||||
* sqrt-virtex.v and chip_root.v (the latter from ngd2ver)
|
||||
* and the "-y <path>" flag specifies the library directory that will
|
||||
* be needed. The glbl.v source file is also included to provide the
|
||||
* GSR and related signals.
|
||||
*
|
||||
* The POST_MAP compiler directive causes the GSR manipulations
|
||||
* included in the test bench to be compiled in, to simulate the chip
|
||||
* startup. Other then that, the test bench runs the post-map design
|
||||
* the same way the pre-synthesis design works.
|
||||
*
|
||||
* Run this design with the command:
|
||||
*
|
||||
* vvp b.out
|
||||
*
|
||||
* And there you go.
|
||||
*/
|
||||
|
||||
`ifndef POST_MAP
|
||||
/*
|
||||
* This module approximates the square root of an unsigned 32bit
|
||||
* number. The algorithm works by doing a bit-wise binary search.
|
||||
* Starting from the most significant bit, the accumulated value
|
||||
* tries to put a 1 in the bit position. If that makes the square
|
||||
* too big for the input, the bit is left zero, otherwise it is set
|
||||
* in the result. This continues for each bit, decreasing in
|
||||
* significance, until all the bits are calculated or all the
|
||||
* remaining bits are zero.
|
||||
*
|
||||
* Since the result is an integer, this function really calculates
|
||||
* value of the expression:
|
||||
*
|
||||
* x = floor(sqrt(y))
|
||||
*
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] acc;
|
||||
|
||||
|
||||
// acc holds the accumulated result, and acc2 is the accumulated
|
||||
// square of the accumulated result.
|
||||
reg [15:0] acc;
|
||||
reg [31:0] acc2;
|
||||
|
||||
// Keep track of which bit I'm working on.
|
||||
reg [4:0] bitl;
|
||||
wire [15:0] bit = 1 << bitl;
|
||||
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||
|
||||
// The output is ready when the bitl counter underflows.
|
||||
wire rdy = bitl[4];
|
||||
|
||||
// guess holds the potential next values for acc, and guess2 holds
|
||||
// the square of that guess. The guess2 calculation is a little bit
|
||||
// subtle. The idea is that:
|
||||
//
|
||||
// guess2 = (acc + bit) * (acc + bit)
|
||||
// = (acc * acc) + 2*acc*bit + bit*bit
|
||||
// = acc2 + 2*acc*bit + bit2
|
||||
// = acc2 + 2 * (acc<<bitl) + bit
|
||||
//
|
||||
// This works out using shifts because bit and bit2 are known to
|
||||
// have only a single bit in them.
|
||||
wire [15:0] guess = acc | bit;
|
||||
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||
|
||||
(* ivl_synthesis_on *)
|
||||
always @(posedge clk or posedge reset)
|
||||
if (reset) begin
|
||||
acc = 0;
|
||||
acc2 = 0;
|
||||
bitl = 15;
|
||||
end else begin
|
||||
if (guess2 <= x) begin
|
||||
acc <= guess;
|
||||
acc2 <= guess2;
|
||||
end
|
||||
bitl <= bitl - 5'd1;
|
||||
end
|
||||
|
||||
endmodule // sqrt32
|
||||
|
||||
`endif // `ifndef POST_MAP
|
||||
|
||||
`ifdef SIMULATE
|
||||
/*
|
||||
* This module is a test bench for the sqrt32 module. It runs some
|
||||
* test input values through the sqrt32 module, and checks that the
|
||||
* output is valid. If an invalid output is generated, print and
|
||||
* error message and stop immediately. If all the tested values pass,
|
||||
* then print PASSED after the test is complete.
|
||||
*/
|
||||
module main;
|
||||
|
||||
reg [31:0] x;
|
||||
reg clk, reset;
|
||||
|
||||
wire [15:0] y;
|
||||
wire rdy;
|
||||
|
||||
`ifdef POST_MAP
|
||||
chip_root dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
|
||||
`else
|
||||
sqrt32 dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
|
||||
`endif
|
||||
|
||||
(* ivl_synthesis_off *)
|
||||
always #5 clk = !clk;
|
||||
|
||||
task reset_dut;
|
||||
begin
|
||||
reset = 1;
|
||||
#1 reset = 0;
|
||||
@(negedge clk) ;
|
||||
end
|
||||
endtask // reset_dut
|
||||
|
||||
task crank_dut;
|
||||
begin
|
||||
while (rdy == 0) begin
|
||||
@(posedge clk) /* wait */;
|
||||
end
|
||||
end
|
||||
endtask // crank_dut
|
||||
|
||||
`ifdef POST_MAP
|
||||
reg GSR;
|
||||
assign glbl.GSR = GSR;
|
||||
`endif
|
||||
|
||||
integer idx;
|
||||
|
||||
(* ivl_synthesis_off *)
|
||||
initial begin
|
||||
reset = 0;
|
||||
clk = 0;
|
||||
|
||||
/* If doing a post-map simulation, when we need to wiggle
|
||||
The GSR bit to simulate chip power-up. */
|
||||
`ifdef POST_MAP
|
||||
GSR = 1;
|
||||
#100 GSR = 0;
|
||||
`endif
|
||||
#100 x = 1;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
x = 3;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
x = 4;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
for (idx = 0 ; idx < 200 ; idx = idx + 1) begin
|
||||
x = $random;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
if (x < (y * y)) begin
|
||||
$display("ERROR: y is too big");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (x > ((y + 1)*(y + 1))) begin
|
||||
$display("ERROR: y is too small");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
`endif
|
||||
|
||||
`ifdef MAKE_CHIP
|
||||
/*
|
||||
* This module represents the chip packaging that we intend to
|
||||
* generate. We bind pins here, and route the clock to the global
|
||||
* clock buffer.
|
||||
*/
|
||||
module chip_root(clk, rdy, reset, x, y);
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] y;
|
||||
|
||||
wire clk_int;
|
||||
|
||||
(* cellref="BUFG:O,I" *)
|
||||
buf gbuf (clk_int, clk);
|
||||
|
||||
sqrt32 dut(.clk(clk_int), .reset(reset), .rdy(rdy), .x(x), .y(y));
|
||||
|
||||
/* Assign the clk to GCLK0, which is on pin P39. */
|
||||
$attribute(clk, "PAD", "39");
|
||||
|
||||
// We don't care where the remaining pins go, so set the pin number
|
||||
// to 0. This tells the implementation tools that we want a PAD,
|
||||
// but we don't care which. Also note the use of a comma (,)
|
||||
// separated list to assign pins to the bits of a vector.
|
||||
$attribute(rdy, "PAD", "0");
|
||||
$attribute(reset, "PAD", "0");
|
||||
$attribute(x, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
|
||||
$attribute(y, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
|
||||
|
||||
endmodule // chip_root
|
||||
|
||||
`endif
|
||||
+43
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.36 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.38 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -192,6 +192,33 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
/* sig > 0 is true if any bit in sig is set. This
|
||||
is very much like sig != 0. (0 > sig) shouldn't
|
||||
happen. */
|
||||
if (rcon) {
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
/* 0 < sig is handled like sig > 0. */
|
||||
if (! rcon) {
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -425,6 +452,14 @@ NetNet* NetEConst::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetECReal::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": error: Real constants are "
|
||||
<< "not synthesizeable." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The bitwise unary logic operator (there is only one) is turned
|
||||
* into discrete gates just as easily as the binary ones above.
|
||||
@@ -608,6 +643,13 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.38 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.37 2002/11/17 23:37:55 steve
|
||||
* Magnitude compare to 0.
|
||||
*
|
||||
* Revision 1.36 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+26
-2
@@ -1,4 +1,4 @@
|
||||
.TH iverilog-vpi 1 "$Date: 2002/07/05 17:17:20 $" Version "$Date: 2002/07/05 17:17:20 $"
|
||||
.TH iverilog-vpi 1 "$Date: 2002/11/23 00:51:53 $" Version "$Date: 2002/11/23 00:51:53 $"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
@@ -32,13 +32,37 @@ VPI modules to further reference external libraries.
|
||||
Normally, the output VPI module will be named after the first source
|
||||
file passed to the command. This flag sets the name (without the .vpi
|
||||
suffix) of the output vpi module.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog-vpi\fP includes two special flags needed to
|
||||
support the more intractable development environment. These flags help
|
||||
the program locate parts that it needs.
|
||||
|
||||
.TP 8
|
||||
.B -mingw=\fIpath\fP
|
||||
Tell the program the root of the Mingw compiler tool suite. The
|
||||
\fBvvp\fP runtime is compiled with this compiler, and this is the
|
||||
compiler that \fIiverilog-vpi\fP expects to use to compile your source
|
||||
code. This is notmally not needed, and if you do use it, it is only
|
||||
needed once. The compiler will save the \fIpath\fP in the registry for
|
||||
use later.
|
||||
|
||||
.TP 8
|
||||
.B -ivl=\fIpath\fP
|
||||
Set for the use during compilation the root if the Icarus Verilog
|
||||
install. This is the place where you installed Icarus Verilog when you
|
||||
ran the installer. This flag is also only needed once, and the path is
|
||||
stored in the registry for future use.
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
.BR "<http://www.icarus.com/eda/verilog/>",
|
||||
.BR "<http://www.mingw.org>",
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
|
||||
+1
-1
@@ -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]
|
||||
|
||||
@@ -120,6 +120,7 @@ ivl_scope_port
|
||||
ivl_scope_ports
|
||||
ivl_scope_sigs
|
||||
ivl_scope_sig
|
||||
ivl_scope_time_units
|
||||
ivl_scope_type
|
||||
ivl_scope_tname
|
||||
|
||||
|
||||
+67
-4
@@ -1,7 +1,7 @@
|
||||
#ifndef __ivl_target_H
|
||||
#define __ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.110 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -137,6 +137,7 @@ typedef struct ivl_scope_s *ivl_scope_t;
|
||||
typedef struct ivl_signal_s *ivl_signal_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t;
|
||||
typedef struct ivl_statement_s*ivl_statement_t;
|
||||
typedef struct ivl_variable_s *ivl_variable_t;
|
||||
|
||||
/*
|
||||
* These are types that are defined as enumerations. These have
|
||||
@@ -171,7 +172,9 @@ typedef enum ivl_expr_type_e {
|
||||
IVL_EX_TERNARY,
|
||||
IVL_EX_UFUNC,
|
||||
IVL_EX_ULONG,
|
||||
IVL_EX_UNARY
|
||||
IVL_EX_UNARY,
|
||||
IVL_EX_VARIABLE,
|
||||
IVL_EX_REALNUM
|
||||
} ivl_expr_type_t;
|
||||
|
||||
/* This is the type code for an ivl_net_logic_t object. */
|
||||
@@ -292,6 +295,14 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_WHILE
|
||||
} ivl_statement_type_t;
|
||||
|
||||
/* This is the type of a variable, and also used as the type for an
|
||||
expression. */
|
||||
typedef enum ivl_variable_type_e {
|
||||
IVL_VT_VOID = 0, /* Not used */
|
||||
IVL_VT_REAL,
|
||||
IVL_VT_VECTOR
|
||||
} ivl_variable_type_t;
|
||||
|
||||
/* This is the type of the function to apply to a process. */
|
||||
typedef int (*ivl_process_f)(ivl_process_t net, void*cd);
|
||||
|
||||
@@ -416,6 +427,10 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
||||
* type, which can affect how some of the other expression methods
|
||||
* operate on the node
|
||||
*
|
||||
* ivl_expr_value
|
||||
* Get the data type of the expression node. This uses the variable
|
||||
* type enum to express the type of the expression node.
|
||||
*
|
||||
* ivl_expr_width
|
||||
* This method returns the bit width of the expression at this
|
||||
* node. It can be applied to any expression node, and returns the
|
||||
@@ -430,14 +445,17 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
||||
*/
|
||||
|
||||
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
|
||||
extern ivl_variable_type_t ivl_expr_value(ivl_expr_t net);
|
||||
|
||||
/* IVL_EX_NUMBER */
|
||||
extern const char* ivl_expr_bits(ivl_expr_t net);
|
||||
/* IVL_EX_UFUNC */
|
||||
extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
|
||||
/* IVL_EX_REALNUM */
|
||||
extern double ivl_expr_dvalue(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL */
|
||||
extern unsigned ivl_expr_lsi(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC */
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_VARIABLE */
|
||||
extern const char* ivl_expr_name(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
extern char ivl_expr_opcode(ivl_expr_t net);
|
||||
@@ -463,6 +481,8 @@ extern int ivl_expr_signed(ivl_expr_t net);
|
||||
extern const char* ivl_expr_string(ivl_expr_t net);
|
||||
/* IVL_EX_ULONG */
|
||||
extern unsigned long ivl_expr_uvalue(ivl_expr_t net);
|
||||
/* IVL_EX_VARIABLE */
|
||||
extern ivl_variable_t ivl_expr_variable(ivl_expr_t net);
|
||||
/* any expression */
|
||||
extern unsigned ivl_expr_width(ivl_expr_t net);
|
||||
|
||||
@@ -671,6 +691,12 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
* If the l-value is a variable, this method returns the signal
|
||||
* object that is the target of the assign.
|
||||
*
|
||||
* ivl_lval_var
|
||||
* If the l-value is a non-signal variable (i.e. a real) this
|
||||
* method returns the ivl_variable_t object that represents it.
|
||||
* If the lval is this sort of variable, then the part_off, idx and
|
||||
* pin methods do not apply.
|
||||
*
|
||||
* ivl_lval_part_off
|
||||
* The part select of the signal is based here. This is the
|
||||
* canonical index of bit-0 of the part select.
|
||||
@@ -690,6 +716,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
|
||||
extern ivl_variable_t ivl_lval_var(ivl_lval_t net);
|
||||
extern unsigned ivl_lval_part_off(ivl_lval_t net);
|
||||
extern unsigned ivl_lval_pins(ivl_lval_t net);
|
||||
extern ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx);
|
||||
@@ -825,6 +852,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* ivl_scope_events
|
||||
* Scopes have 0 or more event objects in them.
|
||||
*
|
||||
* ivl_scope_var
|
||||
* ivl_scope_vars
|
||||
* Scopes have 0 or more variable objects in them.
|
||||
*
|
||||
* ivl_scope_log
|
||||
* ivl_scope_logs
|
||||
* Scopes have 0 or more logic devices in them. A logic device is
|
||||
@@ -861,6 +892,11 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* anything that can become and ivl_signal_t, include synthetic
|
||||
* signals generated by the compiler.
|
||||
*
|
||||
* ivl_scope_time_units
|
||||
* Scopes have their own intrinsic time units, typically from the
|
||||
* timescale compiler directive. This method returns the units as a
|
||||
* signed power of 10 value.
|
||||
*
|
||||
* ivl_scope_type
|
||||
* ivl_scope_tname
|
||||
* Scopes have a type and a type name. For example, if a scope is
|
||||
@@ -882,6 +918,8 @@ extern unsigned ivl_scope_lpms(ivl_scope_t net);
|
||||
extern ivl_lpm_t ivl_scope_lpm(ivl_scope_t, unsigned idx);
|
||||
extern unsigned ivl_scope_mems(ivl_scope_t net);
|
||||
extern ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_vars(ivl_scope_t net);
|
||||
extern ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx);
|
||||
extern const char* ivl_scope_name(ivl_scope_t net);
|
||||
extern const char* ivl_scope_basename(ivl_scope_t net);
|
||||
extern ivl_scope_t ivl_scope_parent(ivl_scope_t net);
|
||||
@@ -891,6 +929,7 @@ extern unsigned ivl_scope_sigs(ivl_scope_t net);
|
||||
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
|
||||
extern ivl_scope_type_t ivl_scope_type(ivl_scope_t net);
|
||||
extern const char* ivl_scope_tname(ivl_scope_t net);
|
||||
extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
|
||||
|
||||
/* SIGNALS
|
||||
@@ -1065,6 +1104,19 @@ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
|
||||
IVL_ST_WAIT, IVL_ST_WHILE */
|
||||
extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
|
||||
|
||||
/*
|
||||
* These functions manipulate variable objects.
|
||||
*
|
||||
* ivl_variable_name
|
||||
* Return the base name of the variable.
|
||||
*
|
||||
* ivl_variable_type
|
||||
* Return the type of the variable. The ivl_variable_type_t is an
|
||||
* enumeration that is defined earlier.
|
||||
*/
|
||||
extern const char* ivl_variable_name(ivl_variable_t net);
|
||||
extern ivl_variable_type_t ivl_variable_type(ivl_variable_t net);
|
||||
|
||||
|
||||
#if defined(__MINGW32__) || defined (__CYGWIN32__)
|
||||
# define DLLEXPORT __declspec(dllexport)
|
||||
@@ -1091,6 +1143,17 @@ _END_DECL
|
||||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.110 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.109 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.108 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
+2
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.35 2002/09/25 02:23:08 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.36 2002/11/08 00:04:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -239,6 +239,7 @@ W [ \t\b\f]+
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else { }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>"//".* { }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>. { }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>\n { istack->lineno += 1; fputc('\n', yyout); }
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.73 2002/06/06 18:57:18 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.75 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -375,7 +375,7 @@ W [ \t\b\f\r]+
|
||||
if (isgraph(yytext[0]))
|
||||
cerr << yytext[0];
|
||||
else
|
||||
cerr << (unsigned)yytext[0];
|
||||
cerr << "hex " << hex << (0xffU & ((unsigned) (yytext[0])));
|
||||
|
||||
cerr << ")" << endl; }
|
||||
|
||||
@@ -974,7 +974,8 @@ static verinum*make_sized_dec(const char*txt)
|
||||
|
||||
static verinum*make_unsized_dec(const char*txt)
|
||||
{
|
||||
return make_dec_with_size(INTEGER_WIDTH, false, txt+1);
|
||||
verinum*tmp = make_dec_with_size(INTEGER_WIDTH, false, txt+1);
|
||||
tmp->has_sign(true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.14 2002/06/11 15:19:12 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.15 2002/12/19 21:37:04 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -50,7 +50,7 @@ a_initialize.o a_next_topmod.o a_object_of_type.o a_product_version.o \
|
||||
a_set_value.o a_version.o
|
||||
O = asynch.o finish.o getcstringp.o getinstance.o getlongp.o \
|
||||
getp.o getsimtime.o io_print.o mc_scan_plusargs.o nump.o putlongp.o \
|
||||
putp.o veriusertfs.o $A
|
||||
putp.o typep.o workarea.o veriusertfs.o $A
|
||||
|
||||
all: libveriuser.a
|
||||
|
||||
|
||||
+22
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: io_print.c,v 1.3 2002/08/12 01:35:02 steve Exp $"
|
||||
#ident "$Id: io_print.c,v 1.4 2002/12/19 21:37:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vpi_user.h>
|
||||
@@ -56,8 +56,29 @@ void tf_error(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
PLI_INT32 tf_message(PLI_INT32 level, char*facility,
|
||||
char*messno, char*fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
vpi_printf("%s[%s] ", facility, messno);
|
||||
|
||||
va_start(ap, fmt);
|
||||
vpi_vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
vpi_printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: io_print.c,v $
|
||||
* Revision 1.4 2002/12/19 21:37:04 steve
|
||||
* Add tf_message, tf_get/setworkarea, and
|
||||
* ty_typep functions, along with defines
|
||||
* related to these functions.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: typep.c,v 1.1 2002/12/19 21:37:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <veriuser.h>
|
||||
#include <vpi_user.h>
|
||||
|
||||
PLI_INT32 tf_typep(PLI_INT32 narg)
|
||||
{
|
||||
vpiHandle sys_h, argv, arg_h = 0;
|
||||
s_vpi_value value;
|
||||
int rtn;
|
||||
|
||||
assert(narg > 0);
|
||||
|
||||
/* get task/func handle */
|
||||
sys_h = vpi_handle(vpiSysTfCall, 0);
|
||||
argv = vpi_iterate(vpiArgument, sys_h);
|
||||
|
||||
/* find nth arg */
|
||||
while (narg > 0) {
|
||||
/* Watch that the argument is not out of range. */
|
||||
if (!(arg_h = vpi_scan(argv)))
|
||||
return TF_NULLPARAM;
|
||||
narg -= 1;
|
||||
}
|
||||
|
||||
switch (vpi_get(vpiType, arg_h)) {
|
||||
case vpiConstant:
|
||||
switch (vpi_get(vpiConstType, arg_h)) {
|
||||
case vpiStringConst:
|
||||
rtn = TF_STRING;
|
||||
break;
|
||||
default:
|
||||
rtn = TF_READONLY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case vpiIntegerVar:
|
||||
case vpiReg:
|
||||
case vpiMemoryWord:
|
||||
rtn = TF_READWRITE;
|
||||
break;
|
||||
|
||||
default:
|
||||
rtn = TF_READONLY;
|
||||
break;
|
||||
}
|
||||
|
||||
vpi_free_object(argv);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: typep.c,v $
|
||||
* Revision 1.1 2002/12/19 21:37:04 steve
|
||||
* Add tf_message, tf_get/setworkarea, and
|
||||
* ty_typep functions, along with defines
|
||||
* related to these functions.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: workarea.c,v 1.1 2002/12/19 21:37:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <veriuser.h>
|
||||
# include <vpi_user.h>
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Keep a list of sys handle to work area bindings.
|
||||
*/
|
||||
struct workarea_cell {
|
||||
vpiHandle sys;
|
||||
void* area;
|
||||
struct workarea_cell*next;
|
||||
};
|
||||
|
||||
static struct workarea_cell*area_list = 0;
|
||||
|
||||
PLI_INT32 tf_setworkarea(void*workarea)
|
||||
{
|
||||
vpiHandle sys;
|
||||
struct workarea_cell*cur;
|
||||
|
||||
sys = vpi_handle(vpiSysTfCall, 0);
|
||||
cur = area_list;
|
||||
|
||||
while (cur) {
|
||||
if (cur->sys == sys) {
|
||||
cur->area = workarea;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
cur = calloc(1, sizeof (struct workarea_cell));
|
||||
cur->next = area_list;
|
||||
cur->sys = sys;
|
||||
cur->area = workarea;
|
||||
area_list = cur;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PLI_BYTE8* tf_getworkarea(void)
|
||||
{
|
||||
struct workarea_cell*cur;
|
||||
vpiHandle sys;
|
||||
|
||||
sys = vpi_handle(vpiSysTfCall, 0);
|
||||
cur = area_list;
|
||||
|
||||
while (cur) {
|
||||
if (cur->sys == sys) {
|
||||
return cur->area;
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: workarea.c,v $
|
||||
* Revision 1.1 2002/12/19 21:37:04 steve
|
||||
* Add tf_message, tf_get/setworkarea, and
|
||||
* ty_typep functions, along with defines
|
||||
* related to these functions.
|
||||
*
|
||||
*/
|
||||
|
||||
+20
-2
@@ -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
|
||||
|
||||
@@ -76,13 +76,18 @@ without white space.
|
||||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run this command:
|
||||
|
||||
$ ./configure --prefix=/cygdrive/d/iverilog
|
||||
$ ./configure --prefix=d:/iverilog
|
||||
|
||||
Substitute your chosen directory for the prefix. This will cause the
|
||||
makefiles to build and the source code to configure. The configure
|
||||
program will detect that this is a mingw environment and set things up
|
||||
to build properly.
|
||||
|
||||
(For a prefix, use the drive letter notation, the mingw compiled parts
|
||||
require it, and the Cygwin tools should be able to handle it. You may
|
||||
need to check or upgrade your Cygwin installation if this causes
|
||||
problems for you.)
|
||||
|
||||
|
||||
* Compile Icarus Verilog
|
||||
|
||||
@@ -108,7 +113,7 @@ window.
|
||||
|
||||
When you are ready, install like this:
|
||||
|
||||
$ /usr/bin/make STRIP=/usr/bin/strip.exe install
|
||||
$ /usr/bin/make install
|
||||
|
||||
This is part of what the configure program did for you. The Makefiles
|
||||
now know to put the files under the D:\iverilog (or whatever directory
|
||||
|
||||
+20
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_assign.cc,v 1.15 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.16 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -39,7 +39,7 @@ unsigned count_lval_width(const NetAssign_*idx)
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), mem_(0), bmux_(0)
|
||||
: sig_(s), mem_(0), var_(0), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = sig_->pin_count();
|
||||
@@ -48,13 +48,21 @@ NetAssign_::NetAssign_(NetNet*s)
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
: sig_(0), mem_(s), bmux_(0)
|
||||
: sig_(0), mem_(s), var_(0), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetVariable*s)
|
||||
: sig_(0), mem_(0), var_(s), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = 0;
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
{
|
||||
if (sig_) {
|
||||
@@ -111,6 +119,11 @@ NetMemory* NetAssign_::mem() const
|
||||
return mem_;
|
||||
}
|
||||
|
||||
NetVariable* NetAssign_::var() const
|
||||
{
|
||||
return var_;
|
||||
}
|
||||
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
{
|
||||
@@ -241,6 +254,10 @@ NetAssignNB::~NetAssignNB()
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.16 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.15 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+53
-7
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_design.cc,v 1.28 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.32 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
# include "netlist.h"
|
||||
# include "util.h"
|
||||
# include <strstream>
|
||||
# include <sstream>
|
||||
|
||||
Design:: Design()
|
||||
: errors(0), nodes_(0), procs_(0), lcounter_(0)
|
||||
@@ -48,10 +48,11 @@ Design::~Design()
|
||||
|
||||
string Design::local_symbol(const string&path)
|
||||
{
|
||||
strstream res;
|
||||
res << "_L" << (lcounter_++) << ends;
|
||||
ostringstream res;
|
||||
res << path << "." << "_L" << lcounter_;
|
||||
lcounter_ += 1;
|
||||
|
||||
return path + "." + res.str();
|
||||
return res.str();
|
||||
}
|
||||
|
||||
void Design::set_precision(int val)
|
||||
@@ -501,12 +502,18 @@ NetScope* Design::find_task(const hname_t&key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEvent* Design::find_event(NetScope*scope, hname_t path)
|
||||
NetEvent* Design::find_event(NetScope*scope, const hname_t&p)
|
||||
{
|
||||
hname_t path = p;
|
||||
assert(scope);
|
||||
|
||||
char*key = path.remove_tail_name();
|
||||
if (path.peek_name(0))
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
while (scope) {
|
||||
if (NetEvent*ev = scope->find_event(path)) {
|
||||
if (NetEvent*ev = scope->find_event(key)) {
|
||||
delete key;
|
||||
return ev;
|
||||
}
|
||||
|
||||
@@ -515,6 +522,31 @@ NetEvent* Design::find_event(NetScope*scope, hname_t path)
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetVariable* Design::find_variable(NetScope*scope, const hname_t&p)
|
||||
{
|
||||
hname_t path = p;
|
||||
assert(scope);
|
||||
|
||||
char*key = path.remove_tail_name();
|
||||
if (path.peek_name(0))
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
while (scope) {
|
||||
if (NetVariable*ev = scope->find_variable(key)) {
|
||||
delete key;
|
||||
return ev;
|
||||
}
|
||||
|
||||
if (scope->type() == NetScope::MODULE)
|
||||
break;
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -593,6 +625,20 @@ void Design::delete_process(NetProcTop*top)
|
||||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.32 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.31 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.30 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.29 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.28 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
||||
+251
-1
@@ -17,13 +17,157 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_expr.cc,v 1.8 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: net_expr.cc,v 1.12 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "netlist.h"
|
||||
# include <iostream>
|
||||
|
||||
NetExpr::TYPE NetExpr::expr_type() const
|
||||
{
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an add/sub node from the two operands. Make a best guess of
|
||||
* the
|
||||
*/
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
NetEConst* tmp;
|
||||
|
||||
/* Catch the special case that one of the operands is an
|
||||
unsized constant number. If so, then we should set the
|
||||
width of that number to the size of the other operand, plus
|
||||
one. This expands the expression to account for the largest
|
||||
possible result.
|
||||
|
||||
The set_width applied to a constant value will only
|
||||
truncate the constant so far as it can still hold its
|
||||
logical value, so this is safe to do. */
|
||||
if ( (tmp = dynamic_cast<NetEConst*>(r))
|
||||
&& (! tmp->has_width())
|
||||
&& (tmp->expr_width() > l->expr_width()) ) {
|
||||
|
||||
unsigned target_width = l->expr_width() + 1;
|
||||
r->set_width(target_width);
|
||||
|
||||
/* Note: This constant value will not gain a defined
|
||||
with from this. Make sure. */
|
||||
assert(! r->has_width() );
|
||||
|
||||
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
|
||||
&& (! tmp->has_width())
|
||||
&& (tmp->expr_width() > r->expr_width()) ) {
|
||||
|
||||
unsigned target_width = r->expr_width() + 1;
|
||||
l->set_width(target_width);
|
||||
|
||||
/* Note: This constant value will not gain a defined
|
||||
with from this. Make sure. */
|
||||
assert(! l->has_width() );
|
||||
|
||||
}
|
||||
|
||||
/* Now that we have the operand sizes the way we like, or as
|
||||
good as we are going to get them, set the size of myself. */
|
||||
if (r->expr_width() > l->expr_width()) {
|
||||
|
||||
expr_width(r->expr_width());
|
||||
|
||||
} else {
|
||||
expr_width(l->expr_width());
|
||||
}
|
||||
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBAdd::~NetEBAdd()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBAdd* NetEBAdd::dup_expr() const
|
||||
{
|
||||
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEBAdd::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
unsigned w = l->expr_width();
|
||||
if (r->expr_width() > w)
|
||||
w = r->expr_width();
|
||||
|
||||
expr_width(w);
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBDiv::~NetEBDiv()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBDiv* NetEBDiv::dup_expr() const
|
||||
{
|
||||
NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEBDiv::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
expr_width(l->expr_width() + r->expr_width());
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBMult::~NetEBMult()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBMult* NetEBMult::dup_expr() const
|
||||
{
|
||||
NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEBMult::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
|
||||
: parms_(cnt), repeat_(r)
|
||||
{
|
||||
@@ -43,6 +187,11 @@ NetEConcat::~NetEConcat()
|
||||
delete parms_[idx];
|
||||
}
|
||||
|
||||
bool NetEConcat::has_width() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetEConcat::set(unsigned idx, NetExpr*e)
|
||||
{
|
||||
assert(idx < parms_.count());
|
||||
@@ -110,6 +259,32 @@ unsigned NetEConcat::repeat() const
|
||||
return repeat_value_;
|
||||
}
|
||||
|
||||
NetECReal::NetECReal(const verireal&val)
|
||||
: value_(val)
|
||||
{
|
||||
}
|
||||
|
||||
NetECReal::~NetECReal()
|
||||
{
|
||||
}
|
||||
|
||||
const verireal& NetECReal::value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
NetECReal* NetECReal::dup_expr() const
|
||||
{
|
||||
NetECReal*tmp = new NetECReal(value_);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetECReal::expr_type() const
|
||||
{
|
||||
return ET_REAL;
|
||||
}
|
||||
|
||||
NetEParam::NetEParam()
|
||||
: des_(0), scope_(0)
|
||||
{
|
||||
@@ -169,8 +344,83 @@ bool NetESelect::set_width(unsigned w)
|
||||
return false;
|
||||
}
|
||||
|
||||
NetESFunc::NetESFunc(const string&n, unsigned width, unsigned np)
|
||||
: name_(0)
|
||||
{
|
||||
name_ = new char [n.length()+1];
|
||||
strcpy(name_, n.c_str());
|
||||
expr_width(width);
|
||||
nparms_ = np;
|
||||
parms_ = new NetExpr*[np];
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
parms_[idx] = 0;
|
||||
}
|
||||
|
||||
NetESFunc::~NetESFunc()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
if (parms_[idx]) delete parms_[idx];
|
||||
|
||||
delete[]parms_;
|
||||
delete[]name_;
|
||||
}
|
||||
|
||||
const char* NetESFunc::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
unsigned NetESFunc::nparms() const
|
||||
{
|
||||
return nparms_;
|
||||
}
|
||||
|
||||
void NetESFunc::parm(unsigned idx, NetExpr*v)
|
||||
{
|
||||
assert(idx < nparms_);
|
||||
if (parms_[idx])
|
||||
delete parms_[idx];
|
||||
parms_[idx] = v;
|
||||
}
|
||||
|
||||
const NetExpr* NetESFunc::parm(unsigned idx) const
|
||||
{
|
||||
assert(idx < nparms_);
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetExpr* NetESFunc::parm(unsigned idx)
|
||||
{
|
||||
assert(idx < nparms_);
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetESFunc::expr_type() const
|
||||
{
|
||||
if (strcmp(name_,"$realtime") == 0)
|
||||
return ET_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_expr.cc,v $
|
||||
* Revision 1.12 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.11 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.10 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.9 2002/11/06 02:25:13 steve
|
||||
* No need to keep excess width from an
|
||||
* unsigned constant value, if it can
|
||||
* be trimmed safely.
|
||||
*
|
||||
* Revision 1.8 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
||||
+9
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.13 2003/01/14 21:16:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,7 +25,7 @@
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include <strstream>
|
||||
# include <sstream>
|
||||
# include <string>
|
||||
# include <typeinfo>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
@@ -363,14 +363,14 @@ const char* Nexus::name() const
|
||||
|
||||
}
|
||||
assert(sig);
|
||||
ostrstream tmp;
|
||||
ostringstream tmp;
|
||||
tmp << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
tmp << ends;
|
||||
|
||||
name_ = new char[strlen(tmp.str()) + 1];
|
||||
strcpy(name_, tmp.str());
|
||||
const string tmps = tmp.str();
|
||||
name_ = new char[strlen(tmps.c_str()) + 1];
|
||||
strcpy(name_, tmps.c_str());
|
||||
return name_;
|
||||
}
|
||||
|
||||
@@ -499,6 +499,9 @@ bool NexusSet::intersect(const NexusSet&that) const
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.13 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.12 2002/10/21 01:42:08 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
|
||||
+27
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_input.cc,v 1.6 2002/08/18 22:07:16 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.8 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -82,6 +82,11 @@ NexusSet* NetEConst::nex_input()
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetECReal::nex_input()
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEMemory::nex_input()
|
||||
{
|
||||
NexusSet*result = idx_->nex_input();
|
||||
@@ -167,6 +172,11 @@ NexusSet* NetEUnary::nex_input()
|
||||
return expr_->nex_input();
|
||||
}
|
||||
|
||||
NexusSet* NetEVariable::nex_input()
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetAssignBase::nex_input()
|
||||
{
|
||||
NexusSet*result = rval_->nex_input();
|
||||
@@ -250,11 +260,15 @@ NexusSet* NetCase::nex_input()
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
assert(items_[idx].guard);
|
||||
tmp = items_[idx].guard->nex_input();
|
||||
assert(tmp);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
/* Usually, this is the guard expression. The default
|
||||
case is special and is identified by a null
|
||||
guard. The default guard obviously has no input. */
|
||||
if (items_[idx].guard) {
|
||||
tmp = items_[idx].guard->nex_input();
|
||||
assert(tmp);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -358,6 +372,13 @@ NexusSet* NetWhile::nex_input()
|
||||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.8 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.7 2002/11/16 05:45:41 steve
|
||||
* Handle default: case in net_inputs for NetCase.
|
||||
*
|
||||
* Revision 1.6 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
|
||||
+34
-6
@@ -17,13 +17,13 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_scope.cc,v 1.20 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: net_scope.cc,v 1.23 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include <strstream>
|
||||
# include <sstream>
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
@@ -40,6 +40,7 @@ NetScope::NetScope(NetScope*up, const char*n, NetScope::TYPE t)
|
||||
memories_ = 0;
|
||||
signals_ = 0;
|
||||
events_ = 0;
|
||||
vars_ = 0;
|
||||
lcounter_ = 0;
|
||||
|
||||
if (up) {
|
||||
@@ -255,10 +256,19 @@ void NetScope::rem_event(NetEvent*ev)
|
||||
}
|
||||
|
||||
|
||||
NetEvent* NetScope::find_event(const hname_t&name)
|
||||
NetEvent* NetScope::find_event(const char*name)
|
||||
{
|
||||
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->name(), name.peek_tail_name()) == 0)
|
||||
if (strcmp(cur->name(), name) == 0)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetVariable* NetScope::find_variable(const char*name)
|
||||
{
|
||||
for (NetVariable*cur = vars_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->basename(), name) == 0)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
@@ -377,6 +387,14 @@ NetMemory* NetScope::find_memory(const string&key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_variable(NetVariable*var)
|
||||
{
|
||||
assert(var->scope_ == 0);
|
||||
var->scope_ = this;
|
||||
var->snext_ = vars_;
|
||||
vars_ = var;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a child scope by name. The name is the simple
|
||||
* name of the child, no heirarchy is searched.
|
||||
@@ -419,8 +437,8 @@ const NetScope* NetScope::parent() const
|
||||
|
||||
string NetScope::local_symbol()
|
||||
{
|
||||
strstream res;
|
||||
res << "_s" << (lcounter_++) << ends;
|
||||
ostringstream res;
|
||||
res << "_s" << (lcounter_++);
|
||||
return res.str();
|
||||
}
|
||||
|
||||
@@ -432,6 +450,16 @@ string NetScope::local_hsymbol()
|
||||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.23 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.22 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.21 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.20 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
|
||||
+18
-127
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.cc,v 1.201 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.205 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -1707,12 +1707,6 @@ const NetScope* NetEUFunc::func() const
|
||||
return func_;
|
||||
}
|
||||
|
||||
NetEUFunc* NetEUFunc::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetUTask::NetUTask(NetScope*def)
|
||||
: task_(def)
|
||||
{
|
||||
@@ -1756,34 +1750,6 @@ bool NetExpr::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a bitwise operator node from the opcode and the left and
|
||||
* right expressions. Don't worry about the width of the expression
|
||||
* yet, we'll get that from the l-value, whatever that turns out to
|
||||
* be.
|
||||
*/
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
if (r->expr_width() > l->expr_width())
|
||||
expr_width(r->expr_width());
|
||||
else
|
||||
expr_width(l->expr_width());
|
||||
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBAdd::~NetEBAdd()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBAdd* NetEBAdd::dup_expr() const
|
||||
{
|
||||
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a bitwise operator node from the opcode and the left and
|
||||
* right expressions. Don't worry about the width of the expression
|
||||
@@ -1861,28 +1827,6 @@ NetEBComp* NetEBComp::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
unsigned w = l->expr_width();
|
||||
if (r->expr_width() > w)
|
||||
w = r->expr_width();
|
||||
|
||||
expr_width(w);
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBDiv::~NetEBDiv()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBDiv* NetEBDiv::dup_expr() const
|
||||
{
|
||||
NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBinary::NetEBinary(char op, NetExpr*l, NetExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
@@ -1921,24 +1865,6 @@ NetEBLogic* NetEBLogic::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
expr_width(l->expr_width() + r->expr_width());
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBMult::~NetEBMult()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBMult* NetEBMult::dup_expr() const
|
||||
{
|
||||
NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
@@ -2063,57 +1989,6 @@ const NetScope* NetEScope::scope() const
|
||||
return scope_;
|
||||
}
|
||||
|
||||
NetESFunc::NetESFunc(const string&n, unsigned width, unsigned np)
|
||||
: name_(0)
|
||||
{
|
||||
name_ = new char [n.length()+1];
|
||||
strcpy(name_, n.c_str());
|
||||
expr_width(width);
|
||||
nparms_ = np;
|
||||
parms_ = new NetExpr*[np];
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
parms_[idx] = 0;
|
||||
}
|
||||
|
||||
NetESFunc::~NetESFunc()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
if (parms_[idx]) delete parms_[idx];
|
||||
|
||||
delete[]parms_;
|
||||
delete[]name_;
|
||||
}
|
||||
|
||||
const char* NetESFunc::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
unsigned NetESFunc::nparms() const
|
||||
{
|
||||
return nparms_;
|
||||
}
|
||||
|
||||
void NetESFunc::parm(unsigned idx, NetExpr*v)
|
||||
{
|
||||
assert(idx < nparms_);
|
||||
if (parms_[idx])
|
||||
delete parms_[idx];
|
||||
parms_[idx] = v;
|
||||
}
|
||||
|
||||
const NetExpr* NetESFunc::parm(unsigned idx) const
|
||||
{
|
||||
assert(idx < nparms_);
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetExpr* NetESFunc::parm(unsigned idx)
|
||||
{
|
||||
assert(idx < nparms_);
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetESignal::NetESignal(NetNet*n)
|
||||
: NetExpr(n->pin_count()), net_(n)
|
||||
{
|
||||
@@ -2320,6 +2195,22 @@ const NetProc*NetTaskDef::proc() const
|
||||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.205 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.204 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.203 2002/11/09 00:25:27 steve
|
||||
* Add dup_expr for user defined function calls.
|
||||
*
|
||||
* Revision 1.202 2002/11/06 02:25:13 steve
|
||||
* No need to keep excess width from an
|
||||
* unsigned constant value, if it can
|
||||
* be trimmed safely.
|
||||
*
|
||||
* Revision 1.201 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.267 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.273 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -32,6 +32,7 @@
|
||||
# include <map>
|
||||
# include <list>
|
||||
# include "verinum.h"
|
||||
# include "verireal.h"
|
||||
# include "HName.h"
|
||||
# include "LineInfo.h"
|
||||
# include "svector.h"
|
||||
@@ -51,6 +52,7 @@ class NetProc;
|
||||
class NetProcTop;
|
||||
class NetRelease;
|
||||
class NetScope;
|
||||
class NetVariable;
|
||||
class NetEvProbe;
|
||||
class NetExpr;
|
||||
class NetESignal;
|
||||
@@ -923,6 +925,16 @@ class NetExpr : public LineInfo {
|
||||
virtual void expr_scan(struct expr_scan_t*) const =0;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Expressions have type. The most common type is ET_VECTOR,
|
||||
// which is a vector (possibly 1 bit) of 4-value bits. The
|
||||
// ET_VOID is not generally used.
|
||||
//
|
||||
// ET_VOID - No value at all.
|
||||
// ET_VECTOR - Vector of Verilog 4-value bits
|
||||
// ET_REAL - real/realtime expression
|
||||
enum TYPE { ET_VOID=0, ET_VECTOR, ET_REAL };
|
||||
virtual TYPE expr_type() const;
|
||||
|
||||
// How wide am I?
|
||||
unsigned expr_width() const { return width_; }
|
||||
|
||||
@@ -1006,6 +1018,31 @@ class NetEConst : public NetExpr {
|
||||
verinum value_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a constant real value.
|
||||
*/
|
||||
class NetECReal : public NetExpr {
|
||||
|
||||
public:
|
||||
explicit NetECReal(const verireal&val);
|
||||
~NetECReal();
|
||||
|
||||
const verireal&value() const;
|
||||
|
||||
// The type of this expression is ET_REAL
|
||||
TYPE expr_type() const;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetECReal* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NexusSet* nex_input();
|
||||
|
||||
private:
|
||||
verireal value_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a special, magical NetNet object. It represents a constant
|
||||
* bit or part select of another NetNet, so is used to return that
|
||||
@@ -1285,6 +1322,7 @@ class NetAssign_ {
|
||||
public:
|
||||
NetAssign_(NetNet*sig);
|
||||
NetAssign_(NetMemory*mem);
|
||||
NetAssign_(NetVariable*var);
|
||||
~NetAssign_();
|
||||
|
||||
// If this expression exists, then only a single bit is to be
|
||||
@@ -1308,6 +1346,7 @@ class NetAssign_ {
|
||||
|
||||
NetNet* sig() const;
|
||||
NetMemory*mem() const;
|
||||
NetVariable*var() const;
|
||||
|
||||
// This pointer is for keeping simple lists.
|
||||
NetAssign_* more;
|
||||
@@ -1317,6 +1356,7 @@ class NetAssign_ {
|
||||
private:
|
||||
NetNet *sig_;
|
||||
NetMemory*mem_;
|
||||
NetVariable*var_;
|
||||
NetExpr*bmux_;
|
||||
|
||||
unsigned loff_;
|
||||
@@ -2044,6 +2084,34 @@ class NetTaskDef {
|
||||
NetTaskDef& operator= (const NetTaskDef&);
|
||||
};
|
||||
|
||||
/*
|
||||
* Variable object such as real and realtime are represented by
|
||||
* instances of this class.
|
||||
*/
|
||||
class NetVariable : public LineInfo {
|
||||
|
||||
friend class NetScope;
|
||||
|
||||
public:
|
||||
NetVariable(const char* name);
|
||||
~NetVariable();
|
||||
|
||||
const char* basename() const;
|
||||
|
||||
NetScope* scope();
|
||||
const NetScope* scope() const;
|
||||
|
||||
private:
|
||||
char* name_;
|
||||
|
||||
NetScope*scope_;
|
||||
NetVariable*snext_;
|
||||
|
||||
private:
|
||||
NetVariable(const NetVariable&);
|
||||
NetVariable& operator= (const NetVariable&);
|
||||
};
|
||||
|
||||
/*
|
||||
* This node represents a function call in an expression. The object
|
||||
* contains a pointer to the function definition, which is used to
|
||||
@@ -2252,6 +2320,8 @@ class NetEBAdd : public NetEBinary {
|
||||
NetEBAdd(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBAdd();
|
||||
|
||||
virtual TYPE expr_type() const;
|
||||
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEBAdd* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
@@ -2269,6 +2339,8 @@ class NetEBDiv : public NetEBinary {
|
||||
NetEBDiv(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBDiv();
|
||||
|
||||
virtual TYPE expr_type() const;
|
||||
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEBDiv* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
@@ -2370,6 +2442,8 @@ class NetEBMult : public NetEBinary {
|
||||
NetEBMult(char op, NetExpr*l, NetExpr*r);
|
||||
~NetEBMult();
|
||||
|
||||
virtual TYPE expr_type() const;
|
||||
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEBMult* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
@@ -2428,6 +2502,7 @@ class NetEConcat : public NetExpr {
|
||||
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual bool has_width() const;
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
@@ -2442,6 +2517,29 @@ class NetEConcat : public NetExpr {
|
||||
bool repeat_calculated_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This node represents a reference to a variable.
|
||||
*/
|
||||
class NetEVariable : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEVariable(NetVariable*);
|
||||
~NetEVariable();
|
||||
|
||||
const NetVariable* variable() const;
|
||||
|
||||
TYPE expr_type() const;
|
||||
|
||||
void expr_scan(struct expr_scan_t*) const;
|
||||
void dump(ostream&) const;
|
||||
|
||||
NetEVariable*dup_expr() const;
|
||||
NexusSet* nex_input();
|
||||
|
||||
private:
|
||||
NetVariable*var_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This clas is a placeholder for a parameter expression. When
|
||||
* parameters are first created, an instance of this object is used to
|
||||
@@ -2493,6 +2591,7 @@ class NetESelect : public NetExpr {
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetESelect* dup_expr() const;
|
||||
|
||||
private:
|
||||
@@ -2541,6 +2640,7 @@ class NetESFunc : public NetExpr {
|
||||
NetExpr* parm(unsigned idx);
|
||||
const NetExpr* parm(unsigned idx) const;
|
||||
|
||||
virtual TYPE expr_type() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual bool set_width(unsigned);
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -2793,7 +2893,11 @@ class NetScope {
|
||||
|
||||
void add_event(NetEvent*);
|
||||
void rem_event(NetEvent*);
|
||||
NetEvent*find_event(const hname_t&name);
|
||||
NetEvent*find_event(const char*name);
|
||||
|
||||
void add_variable(NetVariable*);
|
||||
void rem_variable(NetVariable*);
|
||||
NetVariable*find_variable(const char*name);
|
||||
|
||||
|
||||
/* These methods manage signals. The add_ and rem_signal
|
||||
@@ -2898,6 +3002,7 @@ class NetScope {
|
||||
map<string,param_expr_t>localparams_;
|
||||
|
||||
NetEvent *events_;
|
||||
NetVariable*vars_;
|
||||
NetNet *signals_;
|
||||
NetMemory*memories_;
|
||||
|
||||
@@ -2995,7 +3100,10 @@ class Design {
|
||||
NetScope* find_task(const hname_t&key);
|
||||
|
||||
// Events
|
||||
NetEvent* find_event(NetScope*scope, const hname_t path);
|
||||
NetEvent* find_event(NetScope*scope, const hname_t&path);
|
||||
|
||||
// Variables
|
||||
NetVariable* find_variable(NetScope*scope, const hname_t&path);
|
||||
|
||||
// NODES
|
||||
void add_node(NetNode*);
|
||||
@@ -3083,6 +3191,27 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.273 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.272 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.271 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.270 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.269 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.268 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.267 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
+9
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pad_to_width.cc,v 1.11 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: pad_to_width.cc,v 1.12 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -40,13 +40,17 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
|
||||
const. This is a more efficient result. */
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verinum eval = tmp->value();
|
||||
bool signed_flag = eval.has_sign();
|
||||
|
||||
verinum::V pad = verinum::V0;
|
||||
if (signed_flag)
|
||||
pad = eval.get(eval.len()-1);
|
||||
verinum oval (pad, wid, eval.has_len());
|
||||
|
||||
for (unsigned idx = 0 ; idx < eval.len() ; idx += 1)
|
||||
oval.set(idx, eval.get(idx));
|
||||
|
||||
oval.has_sign(signed_flag);
|
||||
tmp = new NetEConst(oval);
|
||||
delete expr;
|
||||
return tmp;
|
||||
@@ -95,6 +99,10 @@ NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
|
||||
|
||||
/*
|
||||
* $Log: pad_to_width.cc,v $
|
||||
* Revision 1.12 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.11 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.162 2002/10/13 05:01:44 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.170 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -33,6 +33,24 @@ extern void lex_end_table();
|
||||
static svector<PExpr*>* active_range = 0;
|
||||
static bool active_signed = false;
|
||||
|
||||
/* Later version of bison (including 1.35) will not compile in stack
|
||||
extension if the output is compiled with C++ and either the YYSTYPE
|
||||
or YYLTYPE are provided by the source code. However, I can get the
|
||||
old behavior back by defining these symbols. */
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYLTYPE_IS_TRIVIAL 1
|
||||
|
||||
/* Recent version of bison expect that the user supply a
|
||||
YYLLOC_DEFAULT macro that makes up a yylloc value from existing
|
||||
values. I need to supply an explicit version to account for the
|
||||
text field, that otherwise won't be copied. */
|
||||
# define YYLLOC_DEFAULT(Current, Rhs, N) \
|
||||
Current.first_line = Rhs[1].first_line; \
|
||||
Current.first_column = Rhs[1].first_column; \
|
||||
Current.last_line = Rhs[N].last_line; \
|
||||
Current.last_column = Rhs[N].last_column; \
|
||||
Current.text = Rhs[1].text;
|
||||
|
||||
/*
|
||||
* These are some common strength pairs that are used as defaults when
|
||||
* the user is not otherwise specific.
|
||||
@@ -283,12 +301,10 @@ block_item_decl
|
||||
{ pform_set_reg_time($2);
|
||||
}
|
||||
| K_real list_of_identifiers ';'
|
||||
{ delete $2;
|
||||
yyerror(@1, "sorry: real variables not supported.");
|
||||
{ pform_make_reals($2, @1.text, @1.first_line);
|
||||
}
|
||||
| K_realtime list_of_identifiers ';'
|
||||
{ delete $2;
|
||||
yyerror(@1, "sorry: realtime variables not supported.");
|
||||
{ pform_make_reals($2, @1.text, @1.first_line);
|
||||
}
|
||||
| K_parameter parameter_assign_decl ';'
|
||||
| K_localparam localparam_assign_list ';'
|
||||
@@ -551,11 +567,11 @@ dr_strength1
|
||||
;
|
||||
|
||||
event_control
|
||||
: '@' IDENTIFIER
|
||||
{ PEIdent*tmpi = new PEIdent(hname_t($2));
|
||||
: '@' identifier
|
||||
{ PEIdent*tmpi = new PEIdent(*$2);
|
||||
tmpi->set_file(@2.text);
|
||||
tmpi->set_lineno(@2.first_line);
|
||||
delete[]$2;
|
||||
delete $2;
|
||||
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
|
||||
PEventStatement*tmps = new PEventStatement(tmpe);
|
||||
tmps->set_file(@1.text);
|
||||
@@ -1684,7 +1700,7 @@ localparam_assign_list
|
||||
|
||||
|
||||
/* The parameters of a module instance can be overridden by writing
|
||||
a list of expressions in a syntax much line a delay list. (The
|
||||
a list of expressions in a syntax much like a delay list. (The
|
||||
difference being the list can have any length.) The pform that
|
||||
attaches the expression list to the module checks that the
|
||||
expressions are constant.
|
||||
@@ -2084,6 +2100,7 @@ specify_item_list
|
||||
|
||||
specify_edge_path_decl
|
||||
: specify_edge_path '=' '(' specify_delay_value_list ')'
|
||||
| specify_edge_path '=' delay_value_simple
|
||||
;
|
||||
|
||||
specify_edge_path
|
||||
@@ -2139,9 +2156,9 @@ specparam
|
||||
delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' '(' expression ')'
|
||||
| PATHPULSE_IDENTIFIER '=' expression
|
||||
{ delete $1;
|
||||
delete $4;
|
||||
delete $3;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' '(' expression ',' expression ')'
|
||||
{ delete $1;
|
||||
@@ -2315,8 +2332,8 @@ statement
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_TRIGGER IDENTIFIER ';'
|
||||
{ PTrigger*tmp = new PTrigger(hname_t($2));
|
||||
| K_TRIGGER identifier ';'
|
||||
{ PTrigger*tmp = new PTrigger(*$2);
|
||||
tmp->set_file(@2.text);
|
||||
tmp->set_lineno(@2.first_line);
|
||||
delete $2;
|
||||
|
||||
+9
-1
@@ -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.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.cc,v 1.102 2002/09/01 03:01:48 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.107 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,13 +26,14 @@
|
||||
# include "pform.h"
|
||||
# include "parse_misc.h"
|
||||
# include "parse_api.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include "PUdp.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <assert.h>
|
||||
# include <typeinfo>
|
||||
# include <strstream>
|
||||
# include <sstream>
|
||||
|
||||
map<string,Module*> pform_modules;
|
||||
map<string,PUdp*> pform_primitives;
|
||||
@@ -212,6 +213,16 @@ void pform_endmodule(const char*name)
|
||||
{
|
||||
assert(pform_cur_module);
|
||||
assert(strcmp(name, pform_cur_module->mod_name()) == 0);
|
||||
|
||||
map<string,Module*>::const_iterator test = pform_modules.find(name);
|
||||
if (test != pform_modules.end()) {
|
||||
ostringstream msg;
|
||||
msg << "Module " << name << " was already declared here: "
|
||||
<< (*test).second->get_line() << endl;
|
||||
VLerror(msg.str().c_str());
|
||||
pform_cur_module = 0;
|
||||
return;
|
||||
}
|
||||
pform_modules[name] = pform_cur_module;
|
||||
pform_cur_module = 0;
|
||||
}
|
||||
@@ -421,7 +432,7 @@ void pform_make_udp(const char*name, list<string>*parms,
|
||||
}
|
||||
|
||||
/* Verify the "initial" statement, if present, to be sure that
|
||||
it only assignes to the output and the output is
|
||||
it only assigns to the output and the output is
|
||||
registered. Then save the initial value that I get. */
|
||||
verinum::V init = verinum::Vx;
|
||||
if (init_expr) {
|
||||
@@ -547,6 +558,26 @@ void pform_make_events(list<char*>*names, const char*fn, unsigned ln)
|
||||
delete names;
|
||||
}
|
||||
|
||||
static void pform_make_datum(const char*name, const char*fn, unsigned ln)
|
||||
{
|
||||
PData*datum = new PData(hname_t(name));
|
||||
datum->set_file(fn);
|
||||
datum->set_lineno(ln);
|
||||
pform_cur_module->datum[name] = datum;
|
||||
}
|
||||
|
||||
void pform_make_reals(list<char*>*names, const char*fn, unsigned ln)
|
||||
{
|
||||
list<char*>::iterator cur;
|
||||
for (cur = names->begin() ; cur != names->end() ; cur++) {
|
||||
char*txt = *cur;
|
||||
pform_make_datum(txt, fn, ln);
|
||||
free(txt);
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
/*
|
||||
* pform_makegates is called when a list of gates (with the same type)
|
||||
* are ready to be instantiated. The function runs through the list of
|
||||
@@ -608,7 +639,7 @@ void pform_makegates(PGBuiltin::Type type,
|
||||
/*
|
||||
* A module is different from a gate in that there are different
|
||||
* constraints, and sometimes different syntax. The X_modgate
|
||||
* functions handle the instantaions of modules (and UDP objects) by
|
||||
* functions handle the instantiations of modules (and UDP objects) by
|
||||
* making PGModule objects.
|
||||
*/
|
||||
static void pform_make_modgate(const char*type,
|
||||
@@ -767,13 +798,13 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
*
|
||||
* reg foo = <expr>;
|
||||
*
|
||||
* This is equivilent to the combination of statements:
|
||||
* This is equivalent to the combination of statements:
|
||||
*
|
||||
* reg foo;
|
||||
* initital foo = <expr>;
|
||||
* initial foo = <expr>;
|
||||
*
|
||||
* and that is how it is parsed. This syntax is not part of the
|
||||
* IEEE1364-1994 standard, but is approved by OVI as enhancement
|
||||
* IEEE1364-1995 standard, but is approved by OVI as enhancement
|
||||
* BTF-B14.
|
||||
*/
|
||||
void pform_make_reginit(const struct vlltype&li,
|
||||
@@ -820,11 +851,11 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
hname_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur) {
|
||||
strstream msg;
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< "." << ends;
|
||||
VLerror(msg.str());
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -862,7 +893,7 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
* reg bar;
|
||||
*
|
||||
* The output (or other port direction indicator) may or may not have
|
||||
* been seen already, so I do not do any cheching with it yet. But I
|
||||
* been seen already, so I do not do any checking with it yet. But I
|
||||
* do check to see if the name has already been declared, as this
|
||||
* function is called for every declaration.
|
||||
*/
|
||||
@@ -874,18 +905,18 @@ void pform_makewire(const vlltype&li, const char*nm,
|
||||
if (cur) {
|
||||
if ((cur->get_wire_type() != NetNet::IMPLICIT)
|
||||
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
|
||||
strstream msg;
|
||||
ostringstream msg;
|
||||
msg << name << " previously defined at " <<
|
||||
cur->get_line() << "." << ends;
|
||||
VLerror(msg.str());
|
||||
cur->get_line() << ".";
|
||||
VLerror(msg.str().c_str());
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
strstream msg;
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< "." << ends;
|
||||
VLerror(msg.str());
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -948,6 +979,8 @@ void pform_makewire(const vlltype&li,
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur != 0) {
|
||||
PEIdent*lval = new PEIdent(hname_t(first->name));
|
||||
lval->set_file(li.text);
|
||||
lval->set_lineno(li.first_line);
|
||||
pform_make_pgassign(lval, first->expr, delay, str);
|
||||
}
|
||||
|
||||
@@ -1360,6 +1393,22 @@ int pform_parse(const char*path, FILE*file)
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.107 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.106 2003/01/17 05:47:30 steve
|
||||
* Missed a case of setting line on an PEident.
|
||||
*
|
||||
* Revision 1.105 2003/01/16 21:44:19 steve
|
||||
* Detect duplicate module declarations.
|
||||
*
|
||||
* Revision 1.104 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.103 2003/01/10 03:08:13 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.102 2002/09/01 03:01:48 steve
|
||||
* Properly cast signedness of parameters with ranges.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.h,v 1.64 2002/09/01 03:01:48 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.65 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -216,6 +216,11 @@ extern bool pform_expression_is_constant(const PExpr*);
|
||||
|
||||
extern void pform_make_events(list<char*>*names,
|
||||
const char*file, unsigned lineno);
|
||||
/*
|
||||
* Make real datum objects.
|
||||
*/
|
||||
extern void pform_make_reals(list<char*>*names,
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
/*
|
||||
* The makegate function creates a new gate (which need not have a
|
||||
@@ -259,6 +264,10 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.65 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.64 2002/09/01 03:01:48 steve
|
||||
* Properly cast signedness of parameters with ranges.
|
||||
*
|
||||
|
||||
+13
-231
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform_dump.cc,v 1.77 2002/10/19 22:59:49 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.78 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,6 +29,7 @@
|
||||
* module in question.
|
||||
*/
|
||||
# include "pform.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include <iostream>
|
||||
# include <iomanip>
|
||||
@@ -753,6 +754,13 @@ void Module::dump(ostream&out) const
|
||||
<< ev->get_line() << endl;
|
||||
}
|
||||
|
||||
for (map<string,PData*>::const_iterator cur = datum.begin()
|
||||
; cur != datum.end() ; cur ++ ) {
|
||||
PData*tmp = (*cur).second;
|
||||
out << " real " << tmp->name() << "; // "
|
||||
<< tmp->get_line() << endl;
|
||||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
@@ -848,6 +856,10 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.78 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.77 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
@@ -890,235 +902,5 @@ void PUdp::dump(ostream&out) const
|
||||
* Revision 1.68 2001/12/03 04:47:15 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.67 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.66 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.65 2000/12/11 00:31:43 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
*
|
||||
* Revision 1.64 2000/12/10 22:01:36 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.63 2000/11/11 01:52:09 steve
|
||||
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
|
||||
* change set to correct behavior of bufif0 and bufif1
|
||||
* (Tim Leight)
|
||||
*
|
||||
* Also includes fix for PR#27
|
||||
*
|
||||
* Revision 1.62 2000/10/14 02:23:02 steve
|
||||
* Check for missing concat subexpressions (PR#11)
|
||||
*
|
||||
* Revision 1.61 2000/07/26 05:08:07 steve
|
||||
* Parse disable statements to pform.
|
||||
*
|
||||
* Revision 1.60 2000/05/23 16:03:13 steve
|
||||
* Better parsing of expressions lists will empty expressoins.
|
||||
*
|
||||
* Revision 1.59 2000/05/16 04:05:16 steve
|
||||
* Module ports are really special PEIdent
|
||||
* expressions, because a name can be used
|
||||
* many places in the port list.
|
||||
*
|
||||
* Revision 1.58 2000/05/11 23:37:27 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.57 2000/05/06 15:41:57 steve
|
||||
* Carry assignment strength to pform.
|
||||
*
|
||||
* Revision 1.56 2000/05/04 03:37:59 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.55 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.54 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*
|
||||
* Revision 1.53 2000/04/12 04:23:58 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*
|
||||
* Revision 1.52 2000/04/01 19:31:57 steve
|
||||
* Named events as far as the pform.
|
||||
*
|
||||
* Revision 1.51 2000/03/12 17:09:41 steve
|
||||
* Support localparam.
|
||||
*
|
||||
* Revision 1.50 2000/03/08 04:36:54 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* Revision 1.49 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.48 2000/02/18 05:15:03 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.47 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.46 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.45 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.44 1999/09/30 02:43:02 steve
|
||||
* Elaborate ~^ and ~| operators.
|
||||
*
|
||||
* Revision 1.43 1999/09/30 00:48:50 steve
|
||||
* Cope with errors during ternary operator elaboration.
|
||||
*
|
||||
* Revision 1.42 1999/09/29 21:15:58 steve
|
||||
* Handle some mor missing names.
|
||||
*
|
||||
* Revision 1.41 1999/09/29 20:23:53 steve
|
||||
* Handle empty named ports in the dump.
|
||||
*
|
||||
* Revision 1.40 1999/09/29 18:36:04 steve
|
||||
* Full case support
|
||||
*
|
||||
* Revision 1.39 1999/09/17 02:06:26 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
* Revision 1.38 1999/09/08 02:24:39 steve
|
||||
* Empty conditionals (pmonta@imedia.com)
|
||||
*
|
||||
* Revision 1.37 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.36 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.35 1999/08/23 16:48:39 steve
|
||||
* Parameter overrides support from Peter Monta
|
||||
* AND and XOR support wide expressions.
|
||||
*
|
||||
* Revision 1.34 1999/08/03 04:49:13 steve
|
||||
* Proper port type names.
|
||||
*
|
||||
* Revision 1.33 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
*
|
||||
* Revision 1.32 1999/08/01 16:34:50 steve
|
||||
* Parse and elaborate rise/fall/decay times
|
||||
* for gates, and handle the rules for partial
|
||||
* lists of times.
|
||||
*
|
||||
* Revision 1.31 1999/07/31 19:14:47 steve
|
||||
* Add functions up to elaboration (Ed Carter)
|
||||
*
|
||||
* Revision 1.30 1999/07/30 00:43:17 steve
|
||||
* Handle dumping tasks with no ports.
|
||||
*
|
||||
* Revision 1.29 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.28 1999/07/17 19:51:00 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
* Revision 1.27 1999/07/12 00:59:36 steve
|
||||
* procedural blocking assignment delays.
|
||||
*
|
||||
* Revision 1.26 1999/07/03 02:12:52 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
* Revision 1.25 1999/06/24 04:24:18 steve
|
||||
* Handle expression widths for EEE and NEE operators,
|
||||
* add named blocks and scope handling,
|
||||
* add registers declared in named blocks.
|
||||
*
|
||||
* Revision 1.24 1999/06/19 21:06:16 steve
|
||||
* Elaborate and supprort to vvm the forever
|
||||
* and repeat statements.
|
||||
*
|
||||
* Revision 1.23 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
*
|
||||
* Revision 1.22 1999/06/15 05:38:39 steve
|
||||
* Support case expression lists.
|
||||
*
|
||||
* Revision 1.21 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
* Revision 1.20 1999/06/13 23:51:16 steve
|
||||
* l-value part select for procedural assignments.
|
||||
*
|
||||
* Revision 1.19 1999/06/10 04:03:53 steve
|
||||
* Add support for the Ternary operator,
|
||||
* Add support for repeat concatenation,
|
||||
* Correct some seg faults cause by elaboration
|
||||
* errors,
|
||||
* Parse the casex anc casez statements.
|
||||
*
|
||||
* Revision 1.18 1999/06/06 20:45:39 steve
|
||||
* Add parse and elaboration of non-blocking assignments,
|
||||
* Replace list<PCase::Item*> with an svector version,
|
||||
* Add integer support.
|
||||
*
|
||||
* Revision 1.17 1999/05/29 02:36:17 steve
|
||||
* module parameter bind by name.
|
||||
*
|
||||
* Revision 1.16 1999/05/10 00:16:58 steve
|
||||
* Parse and elaborate the concatenate operator
|
||||
* in structural contexts, Replace vector<PExpr*>
|
||||
* and list<PExpr*> with svector<PExpr*>, evaluate
|
||||
* constant expressions with parameters, handle
|
||||
* memories as lvalues.
|
||||
*
|
||||
* Parse task declarations, integer types.
|
||||
*
|
||||
* Revision 1.15 1999/05/05 03:04:46 steve
|
||||
* Fix handling of null delay statements.
|
||||
*
|
||||
* Revision 1.14 1999/05/01 02:57:53 steve
|
||||
* Handle much more complex event expressions.
|
||||
*
|
||||
* Revision 1.13 1999/04/29 02:16:26 steve
|
||||
* Parse OR of event expressions.
|
||||
*
|
||||
* Revision 1.12 1999/04/19 01:59:37 steve
|
||||
* Add memories to the parse and elaboration phases.
|
||||
*
|
||||
* Revision 1.11 1999/02/21 17:01:57 steve
|
||||
* Add support for module parameters.
|
||||
*
|
||||
* Revision 1.10 1999/02/15 02:06:15 steve
|
||||
* Elaborate gate ranges.
|
||||
*
|
||||
* Revision 1.9 1999/02/03 04:20:11 steve
|
||||
* Parse and elaborate the Verilog CASE statement.
|
||||
*
|
||||
* Revision 1.8 1999/02/01 00:26:49 steve
|
||||
* Carry some line info to the netlist,
|
||||
* Dump line numbers for processes.
|
||||
* Elaborate prints errors about port vector
|
||||
* width mismatch
|
||||
* Emit better handles null statements.
|
||||
*/
|
||||
|
||||
|
||||
+32
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: set_width.cc,v 1.23 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.26 2003/01/26 21:02:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -193,9 +193,22 @@ bool NetEBShift::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
left_->set_width(w);
|
||||
if (left_->expr_width() < w)
|
||||
left_ = pad_to_width(left_, w);
|
||||
switch (op()) {
|
||||
|
||||
case 'l':
|
||||
left_->set_width(w);
|
||||
if (left_->expr_width() < w)
|
||||
left_ = pad_to_width(left_, w);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (left_->expr_width() < w)
|
||||
left_ = pad_to_width(left_, w);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
expr_width(left_->expr_width());
|
||||
flag = expr_width() == w;
|
||||
@@ -238,12 +251,13 @@ bool NetEConst::set_width(unsigned w)
|
||||
if (value_.has_sign())
|
||||
pad = value_.get(value_.len()-1);
|
||||
|
||||
verinum tmp (verinum::V0, w);
|
||||
verinum tmp (verinum::V0, w, has_width());
|
||||
for (unsigned idx = 0 ; idx < value_.len() ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
for (unsigned idx = value_.len() ; idx < w ; idx += 1)
|
||||
tmp.set(idx, pad);
|
||||
|
||||
tmp.has_sign(value_.has_sign());
|
||||
value_ = tmp;
|
||||
|
||||
expr_width(w);
|
||||
@@ -259,7 +273,7 @@ bool NetEConst::set_width(unsigned w)
|
||||
if (value_[idx] != verinum::V0)
|
||||
use_w = idx+1;
|
||||
|
||||
verinum tmp (verinum::V0, use_w);
|
||||
verinum tmp (verinum::V0, use_w, has_width());
|
||||
for (unsigned idx = 0 ; idx < use_w ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
|
||||
@@ -357,6 +371,17 @@ bool NetEUReduce::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.26 2003/01/26 21:02:21 steve
|
||||
* Remember to save signedness of number.
|
||||
*
|
||||
* Revision 1.25 2002/11/13 03:03:08 steve
|
||||
* Do not truncate high bits of right shift.
|
||||
*
|
||||
* Revision 1.24 2002/11/06 02:25:13 steve
|
||||
* No need to keep excess width from an
|
||||
* unsigned constant value, if it can
|
||||
* be trimmed safely.
|
||||
*
|
||||
* Revision 1.23 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+1
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: synth2.cc,v 1.17 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.20 2002/11/09 23:29:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -315,8 +315,13 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
|
||||
bool flag = true;
|
||||
|
||||
/* Keep an accounting of which statement accounts for which
|
||||
bit slice of the FF bank. This is used for error checking. */
|
||||
NetProc**pin_accounting = new NetProc* [ff->pin_count()];
|
||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1)
|
||||
pin_accounting[idx] = 0;
|
||||
|
||||
NetProc*cur = last_;
|
||||
unsigned offset = 0;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
|
||||
@@ -329,7 +334,9 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
connect(tmp_set[idx], tmp_map->pin(idx));
|
||||
|
||||
/* Create also a temporary net_out to collect the
|
||||
output. */
|
||||
output. The tmp1 and tmp2 map and out sets together
|
||||
are used to collect the outputs from the substatement
|
||||
for the inputs of the FF bank. */
|
||||
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
|
||||
@@ -351,6 +358,17 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
|
||||
if (ptr < tmp_aset.len())
|
||||
aset_value2.set(idx, tmp_aset[ptr]);
|
||||
|
||||
if (pin_accounting[ptr] != 0) {
|
||||
cerr << cur->get_line() << ": error: "
|
||||
<< "Synchronous output conflicts with "
|
||||
<< pin_accounting[ptr]->get_line()
|
||||
<< "." << endl;
|
||||
flag = false;
|
||||
|
||||
} else {
|
||||
pin_accounting[ptr] = cur;
|
||||
}
|
||||
}
|
||||
if (ff->pin_Aclr().is_linked())
|
||||
connect(ff->pin_Aclr(), ff2->pin_Aclr());
|
||||
@@ -388,21 +406,25 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
continue;
|
||||
|
||||
/* Use the nex_map to link up the output from the
|
||||
substatement to the output of the block as a whole. */
|
||||
substatement to the output of the block as a
|
||||
whole. It is occasionally possible to have outputs
|
||||
beyond the input set, for example when the l-value of
|
||||
an assignment is smaller then the r-value. */
|
||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
||||
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
|
||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
||||
if (ptr < nex_out->pin_count())
|
||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
||||
}
|
||||
|
||||
delete tmp_map;
|
||||
delete tmp_out;
|
||||
offset += ff2->width();
|
||||
|
||||
} while (cur != last_);
|
||||
|
||||
delete[]pin_accounting;
|
||||
|
||||
/* Done. The large NetFF is no longer needed, as it has been
|
||||
taken up by the smaller NetFF devices. */
|
||||
assert(offset == ff->width());
|
||||
delete ff;
|
||||
|
||||
return flag;
|
||||
@@ -418,6 +440,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
|
||||
/* Synthesize the enable expression. */
|
||||
NetNet*ce = expr_->synthesize(des);
|
||||
assert(ce->pin_count() == 1);
|
||||
@@ -430,6 +453,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
|
||||
if (connected(ce->pin(0), ev->pin(0))) {
|
||||
|
||||
bool flag = true;
|
||||
assert(ev->edge() == NetEvProbe::POSEDGE);
|
||||
|
||||
/* Synthesize the true clause to figure out what
|
||||
@@ -437,7 +461,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
NetNet*asig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE, nex_map->pin_count());
|
||||
asig->local_flag(true);
|
||||
if_->synth_async(des, scope, nex_map, asig);
|
||||
flag = if_->synth_async(des, scope, nex_map, asig) && flag;
|
||||
|
||||
assert(asig->pin_count() == ff->width());
|
||||
|
||||
@@ -465,7 +489,8 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
|
||||
assert(events_in.count() == 1);
|
||||
return else_->synth_sync(des, scope, ff, nex_map,
|
||||
nex_out, svector<NetEvProbe*>(0));
|
||||
nex_out, svector<NetEvProbe*>(0))
|
||||
&& flag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -487,15 +512,48 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
assert(if_);
|
||||
assert(!else_);
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = if_->synth_async(des, scope, nex_map, nex_out);
|
||||
/* What's left, is a synchronous CE statement like this:
|
||||
|
||||
if (expr_) <true statement>;
|
||||
|
||||
The expr_ expression has alreacy been synthesized to the ce
|
||||
net, so we connect it here to the FF. What's left is to
|
||||
synthesize the substatement as a combinational
|
||||
statement.
|
||||
|
||||
Watch out for the special case that there is already a CE
|
||||
connected to this FF. This can be caused by code like this:
|
||||
|
||||
if (a) if (b) <statement>;
|
||||
|
||||
In this case, we are working on the inner IF, so we AND the
|
||||
a and b expressions to make a new CE. */
|
||||
|
||||
if (ff->pin_Enable().is_linked()) {
|
||||
NetLogic*ce_and = new NetLogic(scope,
|
||||
scope->local_hsymbol(), 3,
|
||||
NetLogic::AND);
|
||||
des->add_node(ce_and);
|
||||
connect(ff->pin_Enable(), ce_and->pin(1));
|
||||
connect(ce->pin(0), ce_and->pin(2));
|
||||
|
||||
ff->pin_Enable().unlink();
|
||||
connect(ff->pin_Enable(), ce_and->pin(0));
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
connect(ff->pin_Enable(), tmp->pin(0));
|
||||
|
||||
} else {
|
||||
|
||||
connect(ff->pin_Enable(), ce->pin(0));
|
||||
}
|
||||
|
||||
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
|
||||
if (flag == false)
|
||||
return flag;
|
||||
|
||||
assert(expr_);
|
||||
|
||||
connect(ff->pin_Enable(), ce->pin(0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -561,15 +619,6 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
||||
ff->attribute("Clock:LPM_Polarity", verinum("INVERT"));
|
||||
|
||||
#if 0
|
||||
if (ev->nprobe() > 1) {
|
||||
cerr << get_line() << ": sorry: I don't know how "
|
||||
<< "to synthesize asynchronous DFF controls."
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope, ff,
|
||||
nex_map, nex_out, events);
|
||||
@@ -689,6 +738,15 @@ void synth2(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.20 2002/11/09 23:29:29 steve
|
||||
* Handle nested-if chip enables.
|
||||
*
|
||||
* Revision 1.19 2002/11/09 20:22:57 steve
|
||||
* Detect synthesis conflicts blocks statements share outputs.
|
||||
*
|
||||
* Revision 1.18 2002/11/06 03:22:28 steve
|
||||
* More forgiving about assignment rval width mismatch.
|
||||
*
|
||||
* Revision 1.17 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
+75
-274
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.88 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.90 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -218,6 +218,12 @@ extern "C" ivl_scope_t ivl_expr_def(ivl_expr_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" double ivl_expr_dvalue(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_REALNUM);
|
||||
return net->u_.real_.value;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_expr_lsi(ivl_expr_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
@@ -242,6 +248,9 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net)
|
||||
case IVL_EX_SIGNAL:
|
||||
return net->u_.signal_.sig->name_;
|
||||
|
||||
case IVL_EX_VARIABLE:
|
||||
return net->u_.variable_.var->name;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -414,6 +423,12 @@ extern "C" unsigned long ivl_expr_uvalue(ivl_expr_t net)
|
||||
return net->u_.ulong_.value;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_expr_value(ivl_expr_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->value_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_expr_width(ivl_expr_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -426,6 +441,12 @@ extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net)
|
||||
return net->u_.memory_.mem_;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_t ivl_expr_variable(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_VARIABLE);
|
||||
return net->u_.variable_.var;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key)
|
||||
{
|
||||
assert(net);
|
||||
@@ -899,6 +920,14 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_t ivl_lval_var(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->type_ == IVL_LVAL_VAR)
|
||||
return net->n.var;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1079,6 +1108,19 @@ extern "C" ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx)
|
||||
return net->event_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_vars(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->nvar_;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->nvar_);
|
||||
return net->var_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_logs(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1157,6 +1199,12 @@ extern "C" ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx)
|
||||
return net->sigs_[idx];
|
||||
}
|
||||
|
||||
extern "C" int ivl_scope_time_units(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->time_units;
|
||||
}
|
||||
|
||||
extern "C" ivl_scope_type_t ivl_scope_type(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1478,6 +1526,9 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
||||
case IVL_LVAL_MEM:
|
||||
sum += ivl_memory_width(ivl_lval_mem(cur));
|
||||
break;
|
||||
case IVL_LVAL_VAR:
|
||||
sum += 0;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -1583,8 +1634,31 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_variable_name(ivl_variable_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.90 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.89 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.88 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
@@ -1621,278 +1695,5 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
*
|
||||
* Revision 1.79 2002/05/24 04:36:23 steve
|
||||
* Verilog 2001 attriubtes on nets/wires.
|
||||
*
|
||||
* Revision 1.78 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.77 2002/03/17 19:30:47 steve
|
||||
* Add API to support user defined function.
|
||||
*
|
||||
* Revision 1.76 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.75 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.74 2002/01/03 04:19:01 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
* Revision 1.73 2001/12/06 03:11:00 steve
|
||||
* Add ivl_logic_delay function to ivl_target.
|
||||
*
|
||||
* Revision 1.72 2001/11/14 03:28:49 steve
|
||||
* DLL target support for force and release.
|
||||
*
|
||||
* Revision 1.71 2001/11/01 04:25:31 steve
|
||||
* ivl_target support for cassign.
|
||||
*
|
||||
* Revision 1.70 2001/10/31 05:24:52 steve
|
||||
* ivl_target support for assign/deassign.
|
||||
*
|
||||
* Revision 1.69 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.68 2001/10/16 02:19:27 steve
|
||||
* Support IVL_LPM_DIVIDE for structural divide.
|
||||
*
|
||||
* Revision 1.67 2001/09/16 22:19:42 steve
|
||||
* Support attributes to logic gates.
|
||||
*
|
||||
* Revision 1.66 2001/09/01 01:57:31 steve
|
||||
* Make constants available through the design root
|
||||
*
|
||||
* Revision 1.65 2001/08/31 22:58:40 steve
|
||||
* Support DFF CE inputs.
|
||||
*
|
||||
* Revision 1.64 2001/08/28 04:07:18 steve
|
||||
* Add some ivl_target convenience functions.
|
||||
*
|
||||
* Revision 1.63 2001/08/25 23:50:03 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.62 2001/08/10 00:40:45 steve
|
||||
* tgt-vvp generates code that skips nets as inputs.
|
||||
*
|
||||
* Revision 1.61 2001/07/28 01:17:40 steve
|
||||
* Support getting the signal from IVL_EX_SIGNAL expressions.
|
||||
*
|
||||
* Revision 1.60 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.59 2001/07/27 02:41:55 steve
|
||||
* Fix binding of dangling function ports. do not elide them.
|
||||
*
|
||||
* Revision 1.58 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.57 2001/07/22 00:17:49 steve
|
||||
* Support the NetESubSignal expressions in vvp.tgt.
|
||||
*
|
||||
* Revision 1.56 2001/07/19 04:55:06 steve
|
||||
* Support calculated delays in vvp.tgt.
|
||||
*
|
||||
* Revision 1.55 2001/07/07 20:20:10 steve
|
||||
* Pass parameters to system functions.
|
||||
*
|
||||
* Revision 1.54 2001/07/07 03:01:37 steve
|
||||
* Detect and make available to t-dll the right shift.
|
||||
*
|
||||
* Revision 1.53 2001/07/04 22:59:25 steve
|
||||
* handle left shifter in dll output.
|
||||
*
|
||||
* Revision 1.52 2001/06/30 23:03:16 steve
|
||||
* support fast programming by only writing the bits
|
||||
* that are listed in the input file.
|
||||
*
|
||||
* Revision 1.51 2001/06/16 23:45:05 steve
|
||||
* Add support for structural multiply in t-dll.
|
||||
* Add code generators and vvp support for both
|
||||
* structural and behavioral multiply.
|
||||
*
|
||||
* Revision 1.50 2001/06/16 02:41:41 steve
|
||||
* Generate code to support memory access in continuous
|
||||
* assignment statements. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.49 2001/06/15 04:14:19 steve
|
||||
* Generate vvp code for GT and GE comparisons.
|
||||
*
|
||||
* Revision 1.48 2001/06/07 03:09:37 steve
|
||||
* support subtraction in tgt-vvp.
|
||||
*
|
||||
* Revision 1.47 2001/06/07 02:12:43 steve
|
||||
* Support structural addition.
|
||||
*
|
||||
* Revision 1.46 2001/05/20 01:06:16 steve
|
||||
* stub ivl_expr_parms for sfunctions.
|
||||
*
|
||||
* Revision 1.45 2001/05/17 04:37:02 steve
|
||||
* Behavioral ternary operators for vvp.
|
||||
*
|
||||
* Revision 1.44 2001/05/08 23:59:33 steve
|
||||
* Add ivl and vvp.tgt support for memories in
|
||||
* expressions and l-values. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.43 2001/05/06 17:48:20 steve
|
||||
* Support memory objects. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.42 2001/04/29 23:17:38 steve
|
||||
* Carry drive strengths in the ivl_nexus_ptr_t, and
|
||||
* handle constant devices in targets.'
|
||||
*
|
||||
* Revision 1.41 2001/04/26 05:12:02 steve
|
||||
* Implement simple MUXZ for ?: operators.
|
||||
*
|
||||
* Revision 1.40 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.39 2001/04/21 00:55:46 steve
|
||||
* Generate code for disable.
|
||||
*
|
||||
* Revision 1.38 2001/04/15 02:58:11 steve
|
||||
* vvp support for <= with internal delay.
|
||||
*
|
||||
* Revision 1.37 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.36 2001/04/05 03:20:57 steve
|
||||
* Generate vvp code for the repeat statement.
|
||||
*
|
||||
* Revision 1.35 2001/04/05 01:12:28 steve
|
||||
* Get signed compares working correctly in vvp.
|
||||
*
|
||||
* Revision 1.34 2001/04/04 04:50:35 steve
|
||||
* Support forever loops in the tgt-vvp target.
|
||||
*
|
||||
* Revision 1.33 2001/04/03 04:50:37 steve
|
||||
* Support non-blocking assignments.
|
||||
*
|
||||
* Revision 1.32 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.31 2001/04/02 00:28:35 steve
|
||||
* Support the scope expression node.
|
||||
*
|
||||
* Revision 1.30 2001/04/01 06:52:27 steve
|
||||
* support the NetWhile statement.
|
||||
*
|
||||
* Revision 1.29 2001/04/01 01:48:21 steve
|
||||
* Redesign event information to support arbitrary edge combining.
|
||||
*
|
||||
* Revision 1.28 2001/03/31 17:36:38 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.27 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.26 2001/03/29 03:47:38 steve
|
||||
* Behavioral trigger statements.
|
||||
*
|
||||
* Revision 1.25 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.24 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.23 2001/03/27 06:27:40 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.22 2001/03/20 01:44:13 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.21 2001/01/15 00:47:02 steve
|
||||
* Pass scope type information to the target module.
|
||||
*
|
||||
* Revision 1.20 2001/01/15 00:05:39 steve
|
||||
* Add client data pointer for scope and process scanners.
|
||||
*
|
||||
* Revision 1.19 2000/12/05 06:29:33 steve
|
||||
* Make signal attributes available to ivl_target API.
|
||||
*
|
||||
* Revision 1.18 2000/11/12 17:47:29 steve
|
||||
* flip-flop pins for ivl_target API.
|
||||
*
|
||||
* Revision 1.17 2000/11/11 00:03:36 steve
|
||||
* Add support for the t-dll backend grabing flip-flops.
|
||||
*
|
||||
* Revision 1.16 2000/10/28 22:32:34 steve
|
||||
* API for concatenation expressions.
|
||||
*
|
||||
* Revision 1.15 2000/10/25 05:41:24 steve
|
||||
* Get target signal from nexus_ptr.
|
||||
*
|
||||
* Revision 1.14 2000/10/18 20:04:39 steve
|
||||
* Add ivl_lval_t and support for assignment l-values.
|
||||
*
|
||||
* Revision 1.13 2000/10/16 22:44:54 steve
|
||||
* Stubs so that cygwin port will link ivl.
|
||||
*
|
||||
* Revision 1.12 2000/10/15 04:46:23 steve
|
||||
* Scopes and processes are accessible randomly from
|
||||
* the design, and signals and logic are accessible
|
||||
* from scopes. Remove the target calls that are no
|
||||
* longer needed.
|
||||
*
|
||||
* Add the ivl_nexus_ptr_t and the means to get at
|
||||
* them from nexus objects.
|
||||
*
|
||||
* Give names to methods that manipulate the ivl_design_t
|
||||
* type more consistent names.
|
||||
*
|
||||
* Revision 1.11 2000/10/08 04:01:54 steve
|
||||
* Back pointers in the nexus objects into the devices
|
||||
* that point to it.
|
||||
*
|
||||
* Collect threads into a list in the design.
|
||||
*
|
||||
* Revision 1.10 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.9 2000/10/05 05:03:01 steve
|
||||
* xor and constant devices.
|
||||
*
|
||||
* Revision 1.8 2000/09/30 02:18:15 steve
|
||||
* ivl_expr_t support for binary operators,
|
||||
* Create a proper ivl_scope_t object.
|
||||
*
|
||||
* Revision 1.7 2000/09/26 00:30:07 steve
|
||||
* Add EX_NUMBER and ST_TRIGGER to dll-api.
|
||||
*
|
||||
* Revision 1.6 2000/09/24 15:46:00 steve
|
||||
* API access to signal type and port type.
|
||||
*
|
||||
* Revision 1.5 2000/09/24 02:21:53 steve
|
||||
* Add support for signal expressions.
|
||||
*
|
||||
* Revision 1.4 2000/09/23 05:15:07 steve
|
||||
* Add enough tgt-verilog code to support hello world.
|
||||
*
|
||||
* Revision 1.3 2000/09/22 03:58:30 steve
|
||||
* Access to the name of a system task call.
|
||||
*
|
||||
* Revision 1.2 2000/09/19 04:15:27 steve
|
||||
* Introduce the means to get statement types.
|
||||
*
|
||||
* Revision 1.1 2000/09/18 01:24:32 steve
|
||||
* Get the structure for ivl_statement_t worked out.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+82
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-expr.cc,v 1.29 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.31 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -32,6 +32,26 @@
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
|
||||
/*
|
||||
* This is a little convenience function for converting a NetExpr
|
||||
* expresion type to the expression type used by ivl_expr_t objects.
|
||||
*/
|
||||
static ivl_variable_type_t get_expr_type(const NetExpr*net)
|
||||
{
|
||||
switch (net->expr_type()) {
|
||||
case NetExpr::ET_VOID:
|
||||
return IVL_VT_VOID;
|
||||
|
||||
case NetExpr::ET_REAL:
|
||||
return IVL_VT_REAL;
|
||||
|
||||
case NetExpr::ET_VECTOR:
|
||||
return IVL_VT_VECTOR;
|
||||
}
|
||||
|
||||
return IVL_VT_VOID;
|
||||
}
|
||||
|
||||
/*
|
||||
* These methods implement the expression scan that generates the
|
||||
* ivl_expr_t representing the expression. Each method leaves the
|
||||
@@ -50,6 +70,7 @@ void dll_target::sub_off_from_expr_(long off)
|
||||
char*bits;
|
||||
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmpc->type_ = IVL_EX_NUMBER;
|
||||
tmpc->value_ = IVL_VT_VECTOR;
|
||||
tmpc->width_ = expr_->width_;
|
||||
tmpc->signed_ = expr_->signed_;
|
||||
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
|
||||
@@ -63,6 +84,7 @@ void dll_target::sub_off_from_expr_(long off)
|
||||
the constant to subtract. */
|
||||
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmps->type_ = IVL_EX_BINARY;
|
||||
tmps->value_ = IVL_VT_VECTOR;
|
||||
tmps->width_ = tmpc->width_;
|
||||
tmps->signed_ = tmpc->signed_;
|
||||
tmps->u_.binary_.op_ = '-';
|
||||
@@ -80,6 +102,7 @@ void dll_target::mul_expr_by_const_(long val)
|
||||
char*bits;
|
||||
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmpc->type_ = IVL_EX_NUMBER;
|
||||
tmpc->value_ = IVL_VT_VECTOR;
|
||||
tmpc->width_ = expr_->width_;
|
||||
tmpc->signed_ = expr_->signed_;
|
||||
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
|
||||
@@ -93,6 +116,7 @@ void dll_target::mul_expr_by_const_(long val)
|
||||
the constant to subtract. */
|
||||
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmps->type_ = IVL_EX_BINARY;
|
||||
tmps->value_ = IVL_VT_VECTOR;
|
||||
tmps->width_ = tmpc->width_;
|
||||
tmps->signed_ = tmpc->signed_;
|
||||
tmps->u_.binary_.op_ = '*';
|
||||
@@ -111,6 +135,7 @@ ivl_expr_t dll_target::expr_from_value_(const verinum&val)
|
||||
unsigned idx;
|
||||
char*bits;
|
||||
expr->type_ = IVL_EX_NUMBER;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->width_= val.len();
|
||||
expr->signed_ = val.has_sign()? 1 : 0;
|
||||
expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_);
|
||||
@@ -150,6 +175,7 @@ void dll_target::expr_binary(const NetEBinary*net)
|
||||
assert(expr_);
|
||||
|
||||
expr_->type_ = IVL_EX_BINARY;
|
||||
expr_->value_= get_expr_type(net);
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
@@ -165,8 +191,9 @@ void dll_target::expr_concat(const NetEConcat*net)
|
||||
ivl_expr_t cur = new struct ivl_expr_s;
|
||||
assert(cur);
|
||||
|
||||
cur->type_ = IVL_EX_CONCAT;
|
||||
cur->width_= net->expr_width();
|
||||
cur->type_ = IVL_EX_CONCAT;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_ = net->expr_width();
|
||||
|
||||
cur->u_.concat_.rept = net->repeat();
|
||||
cur->u_.concat_.parms = net->nparms();
|
||||
@@ -194,6 +221,7 @@ void dll_target::expr_memory(const NetEMemory*net)
|
||||
assert(cur);
|
||||
|
||||
cur->type_ = IVL_EX_MEMORY;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
|
||||
@@ -210,6 +238,7 @@ void dll_target::expr_const(const NetEConst*net)
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr_);
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
|
||||
if (net->value().is_string()) {
|
||||
expr_->type_ = IVL_EX_STRING;
|
||||
@@ -245,6 +274,17 @@ void dll_target::expr_const(const NetEConst*net)
|
||||
}
|
||||
}
|
||||
|
||||
void dll_target::expr_creal(const NetECReal*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
expr_->width_ = net->expr_width();
|
||||
expr_->signed_ = 1;
|
||||
expr_->type_ = IVL_EX_REALNUM;
|
||||
expr_->value_= IVL_VT_REAL;
|
||||
expr_->u_.real_.value = net->value().as_double();
|
||||
}
|
||||
|
||||
void dll_target::expr_scope(const NetEScope*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
@@ -253,6 +293,7 @@ void dll_target::expr_scope(const NetEScope*net)
|
||||
assert(expr_);
|
||||
|
||||
expr_->type_ = IVL_EX_SCOPE;
|
||||
expr_->value_= IVL_VT_VOID;
|
||||
expr_->u_.scope_.scope = lookup_scope_(net->scope());
|
||||
}
|
||||
|
||||
@@ -271,6 +312,7 @@ void dll_target::expr_select(const NetESelect*net)
|
||||
assert(expr_);
|
||||
|
||||
expr_->type_ = IVL_EX_SELECT;
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
@@ -286,6 +328,18 @@ void dll_target::expr_sfunc(const NetESFunc*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_SFUNC;
|
||||
switch (net->expr_type()) {
|
||||
case NetExpr::ET_VECTOR:
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
break;
|
||||
case NetExpr::ET_REAL:
|
||||
expr->value_= IVL_VT_REAL;
|
||||
break;
|
||||
case NetExpr::ET_VOID:
|
||||
assert(0);
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
break;
|
||||
}
|
||||
expr->width_= net->expr_width();
|
||||
expr->u_.sfunc_.name_ = strdup(net->name());
|
||||
|
||||
@@ -312,6 +366,7 @@ void dll_target::expr_ternary(const NetETernary*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_TERNARY;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->width_ = net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
@@ -340,6 +395,7 @@ void dll_target::expr_signal(const NetESignal*net)
|
||||
assert(expr_);
|
||||
|
||||
expr_->type_ = IVL_EX_SIGNAL;
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
expr_->u_.signal_.sig = find_signal(des_, net->sig());
|
||||
@@ -355,6 +411,7 @@ void dll_target::expr_subsignal(const NetEBitSel*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_BITSEL;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->width_= net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
expr->u_.bitsel_.sig = find_signal(des_, net->sig());
|
||||
@@ -450,6 +507,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_UFUNC;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->width_= net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
@@ -482,14 +540,35 @@ void dll_target::expr_unary(const NetEUnary*net)
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
expr_->type_ = IVL_EX_UNARY;
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
expr_->width_ = net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
expr_->u_.unary_.op_ = net->op();
|
||||
expr_->u_.unary_.sub_ = sub;
|
||||
}
|
||||
|
||||
void dll_target::expr_variable(const NetEVariable*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
expr_->type_ = IVL_EX_VARIABLE;
|
||||
expr_->value_ = IVL_VT_REAL;
|
||||
expr_->width_ = 0;
|
||||
expr_->signed_= net->has_sign()? 1 : 0;
|
||||
expr_->u_.variable_.var = find_variable(des_, net->variable());
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.31 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.30 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.29 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
+10
-1
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-proc.cc,v 1.54 2002/08/19 00:06:12 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.55 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -163,6 +163,11 @@ void dll_target::proc_assign(const NetAssign*net)
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
} else if (asn->var()) {
|
||||
cur->type_ = IVL_LVAL_VAR;
|
||||
cur->idx = 0;
|
||||
cur->n.var = find_variable(des_, asn->var());
|
||||
|
||||
} else {
|
||||
assert(asn->mem());
|
||||
cur->type_ = IVL_LVAL_MEM;
|
||||
@@ -822,6 +827,10 @@ void dll_target::proc_while(const NetWhile*net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.55 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.54 2002/08/19 00:06:12 steve
|
||||
* Allow release to handle removal of target net.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.97 2002/10/23 01:47:18 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.103 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -36,32 +36,33 @@
|
||||
|
||||
inline ivl_dll_t ivl_dlopen(const char *name)
|
||||
{
|
||||
return (ivl_dll_t) LoadLibrary(name);
|
||||
ivl_dll_t res = (ivl_dll_t) LoadLibrary(name);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
inline void * ivl_dlsym(ivl_dll_t dll, const char *nm)
|
||||
{
|
||||
FARPROC sym;
|
||||
return GetProcAddress((HMODULE)dll, nm);
|
||||
FARPROC sym;
|
||||
return (void*)GetProcAddress((HMODULE)dll, nm);
|
||||
}
|
||||
|
||||
inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{
|
||||
FreeLibrary((HMODULE)dll);
|
||||
FreeLibrary((HMODULE)dll);
|
||||
}
|
||||
|
||||
const char *dlerror(void)
|
||||
{
|
||||
static char msg[255];
|
||||
|
||||
static char msg[256];
|
||||
unsigned long err = GetLastError();
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &msg,
|
||||
0,
|
||||
sizeof(msg) - 1,
|
||||
NULL
|
||||
);
|
||||
return msg;
|
||||
@@ -234,6 +235,22 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_variable_t dll_target::find_variable(ivl_design_s&des,
|
||||
const NetVariable*net)
|
||||
{
|
||||
ivl_scope_t scope = find_scope(des, net->scope());
|
||||
assert(scope);
|
||||
|
||||
const char*nname = net->basename();
|
||||
for (unsigned idx = 0 ; idx < scope->nvar_ ; idx += 1) {
|
||||
if (strcmp(scope->var_[idx]->name, nname) == 0)
|
||||
return scope->var_[idx];
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function locates an ivl_memory_t object that matches the
|
||||
* NetMemory object. The search works by looking for the parent scope,
|
||||
@@ -414,6 +431,14 @@ static void scope_add_mem(ivl_scope_t scope, ivl_memory_t net)
|
||||
scope->mem_[scope->nmem_-1] = net;
|
||||
}
|
||||
|
||||
static void scope_add_var(ivl_scope_t scope, ivl_variable_t net)
|
||||
{
|
||||
scope->nvar_ += 1;
|
||||
scope->var_ = (ivl_variable_t*)
|
||||
realloc(scope->var_, scope->nvar_*sizeof(ivl_variable_t));
|
||||
scope->var_[scope->nvar_-1] = net;
|
||||
}
|
||||
|
||||
void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
|
||||
{
|
||||
ivl_scope_t root_ = new struct ivl_scope_s;
|
||||
@@ -432,8 +457,12 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
|
||||
root_->lpm_ = 0;
|
||||
root_->nmem_ = 0;
|
||||
root_->mem_ = 0;
|
||||
root_->nvar_ = 0;
|
||||
root_->var_ = 0;
|
||||
root_->type_ = IVL_SCT_MODULE;
|
||||
root_->tname_ = root_->name_;
|
||||
root_->time_units = s->time_unit();
|
||||
|
||||
des_.nroots_++;
|
||||
if (des_.roots_)
|
||||
des_.roots_ = (ivl_scope_t *)realloc(des_.roots_, des_.nroots_ * sizeof(ivl_scope_t));
|
||||
@@ -448,6 +477,7 @@ bool dll_target::start_design(const Design*des)
|
||||
dll_path_ = des->get_flag("DLL");
|
||||
dll_ = ivl_dlopen(dll_path_.c_str());
|
||||
if (dll_ == 0) {
|
||||
cerr << "error: " << dll_path_ << " failed to load." << endl;
|
||||
cerr << dll_path_ << ": " << dlerror() << endl;
|
||||
return false;
|
||||
}
|
||||
@@ -629,6 +659,18 @@ void dll_target::event(const NetEvent*net)
|
||||
|
||||
}
|
||||
|
||||
void dll_target::variable(const NetVariable*net)
|
||||
{
|
||||
struct ivl_variable_s *obj = new struct ivl_variable_s;
|
||||
|
||||
ivl_scope_t scope = find_scope(des_, net->scope());
|
||||
obj->type = IVL_VT_REAL;
|
||||
obj->name = strings_.add(net->basename());
|
||||
obj->scope = scope;
|
||||
|
||||
scope_add_var(scope, obj);
|
||||
}
|
||||
|
||||
void dll_target::logic(const NetLogic*net)
|
||||
{
|
||||
struct ivl_net_logic_s *obj = new struct ivl_net_logic_s;
|
||||
@@ -1764,6 +1806,7 @@ void dll_target::scope(const NetScope*net)
|
||||
scope->child_ = 0;
|
||||
scope->sibling_ = 0;
|
||||
scope->parent = find_scope(des_, net->parent());
|
||||
assert(scope->parent);
|
||||
scope->nsigs_ = 0;
|
||||
scope->sigs_ = 0;
|
||||
scope->nlog_ = 0;
|
||||
@@ -1774,16 +1817,27 @@ void dll_target::scope(const NetScope*net)
|
||||
scope->lpm_ = 0;
|
||||
scope->nmem_ = 0;
|
||||
scope->mem_ = 0;
|
||||
scope->nvar_ = 0;
|
||||
scope->var_ = 0;
|
||||
scope->time_units = net->time_unit();
|
||||
|
||||
switch (net->type()) {
|
||||
case NetScope::MODULE:
|
||||
scope->type_ = IVL_SCT_MODULE;
|
||||
scope->tname_ = net->module_name();
|
||||
break;
|
||||
case NetScope::TASK:
|
||||
scope->type_ = IVL_SCT_TASK;
|
||||
scope->tname_ = strings_.add(net->task_def()->name().c_str());
|
||||
break;
|
||||
case NetScope::TASK: {
|
||||
const NetTaskDef*def = net->task_def();
|
||||
if (def == 0) {
|
||||
cerr << "?:?" << ": internal error: "
|
||||
<< "task " << scope->name_
|
||||
<< " has no definition." << endl;
|
||||
}
|
||||
assert(def);
|
||||
scope->type_ = IVL_SCT_TASK;
|
||||
scope->tname_ = strings_.add(def->name().c_str());
|
||||
break;
|
||||
}
|
||||
case NetScope::FUNC:
|
||||
scope->type_ = IVL_SCT_FUNCTION;
|
||||
scope->tname_ = strings_.add(net->func_def()->name().c_str());
|
||||
@@ -1979,6 +2033,29 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.103 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.102 2003/01/16 21:43:52 steve
|
||||
* Assert some task definition sanity.
|
||||
*
|
||||
* Revision 1.101 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.100 2002/11/05 02:12:35 steve
|
||||
* Fix the call to FormatMessage under Windows.
|
||||
*
|
||||
* Revision 1.99 2002/11/03 22:44:19 steve
|
||||
* Cast for gcc convenience.
|
||||
*
|
||||
* Revision 1.98 2002/11/03 20:47:23 steve
|
||||
* Slightly more verbose load fail message.
|
||||
*
|
||||
* Revision 1.97 2002/10/23 01:47:18 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.95 2002/10/23 01:47:17 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.97 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -68,6 +68,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
bool bufz(const NetBUFZ*);
|
||||
void event(const NetEvent*);
|
||||
void variable(const NetVariable*);
|
||||
void logic(const NetLogic*);
|
||||
void net_case_cmp(const NetCaseCmp*);
|
||||
void udp(const NetUDP*);
|
||||
@@ -130,6 +131,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void expr_concat(const NetEConcat*);
|
||||
void expr_memory(const NetEMemory*);
|
||||
void expr_const(const NetEConst*);
|
||||
void expr_creal(const NetECReal*);
|
||||
void expr_scope(const NetEScope*);
|
||||
void expr_select(const NetESelect*);
|
||||
void expr_sfunc(const NetESFunc*);
|
||||
@@ -138,6 +140,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void expr_ufunc(const NetEUFunc*);
|
||||
void expr_unary(const NetEUnary*);
|
||||
void expr_signal(const NetESignal*);
|
||||
void expr_variable(const NetEVariable*);
|
||||
|
||||
ivl_scope_t lookup_scope_(const NetScope*scope);
|
||||
|
||||
@@ -150,6 +153,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
|
||||
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
|
||||
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
|
||||
static ivl_variable_t find_variable(ivl_design_s &des, const NetVariable*net);
|
||||
void add_root(ivl_design_s &des_, const NetScope *s);
|
||||
|
||||
void sub_off_from_expr_(long);
|
||||
@@ -177,6 +181,7 @@ struct ivl_event_s {
|
||||
*/
|
||||
struct ivl_expr_s {
|
||||
ivl_expr_type_t type_;
|
||||
ivl_variable_type_t value_;
|
||||
|
||||
unsigned width_ :24;
|
||||
unsigned signed_ : 1;
|
||||
@@ -243,11 +248,18 @@ struct ivl_expr_s {
|
||||
unsigned long value;
|
||||
} ulong_;
|
||||
|
||||
struct {
|
||||
double value;
|
||||
} real_;
|
||||
|
||||
struct {
|
||||
char op_;
|
||||
ivl_expr_t sub_;
|
||||
} unary_;
|
||||
|
||||
struct {
|
||||
ivl_variable_t var;
|
||||
} variable_;
|
||||
} u_;
|
||||
};
|
||||
|
||||
@@ -334,7 +346,8 @@ enum ivl_lval_type_t {
|
||||
IVL_LVAL_REG = 0,
|
||||
IVL_LVAL_MUX = 1,
|
||||
IVL_LVAL_MEM = 2,
|
||||
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
|
||||
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
|
||||
IVL_LVAL_VAR = 4
|
||||
};
|
||||
|
||||
struct ivl_lval_s {
|
||||
@@ -345,6 +358,7 @@ struct ivl_lval_s {
|
||||
union {
|
||||
ivl_signal_t sig;
|
||||
ivl_memory_t mem;
|
||||
ivl_variable_t var;
|
||||
} n;
|
||||
};
|
||||
|
||||
@@ -495,11 +509,16 @@ struct ivl_scope_s {
|
||||
unsigned nmem_;
|
||||
ivl_memory_t* mem_;
|
||||
|
||||
unsigned nvar_;
|
||||
ivl_variable_t* var_;
|
||||
|
||||
/* Scopes that are tasks/functions have a definition. */
|
||||
ivl_statement_t def;
|
||||
|
||||
unsigned ports;
|
||||
ivl_signal_t*port;
|
||||
|
||||
signed int time_units :8;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -620,8 +639,28 @@ struct ivl_statement_s {
|
||||
} u_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This holds the details about a variable object.
|
||||
*/
|
||||
struct ivl_variable_s {
|
||||
ivl_variable_type_t type;
|
||||
const char* name;
|
||||
ivl_scope_t scope;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.97 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.96 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.95 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-xnf.cc,v 1.45 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: t-xnf.cc,v 1.46 2003/01/14 21:16:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -77,7 +77,7 @@
|
||||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
# include <fstream>
|
||||
# include <strstream>
|
||||
# include <sstream>
|
||||
|
||||
verinum::V link_get_ival(const Link&lnk)
|
||||
{
|
||||
@@ -765,8 +765,8 @@ void target_xnf::lpm_ram_dq(const NetRamDq*ram)
|
||||
draw_pin(out_, "WE", ram->pin_WE());
|
||||
draw_pin(out_, "WCLK", ram->pin_InClock());
|
||||
for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
|
||||
strstream tmp;
|
||||
tmp << "A" << adr << ends;
|
||||
ostringstream tmp;
|
||||
tmp << "A" << adr;
|
||||
draw_pin(out_, tmp.str(), ram->pin_Address(adr));
|
||||
}
|
||||
|
||||
@@ -927,6 +927,9 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-xnf.cc,v $
|
||||
* Revision 1.46 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.45 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2002 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 1998-2003 Stephen Williams <steve@icarus.com>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.63 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.64 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -47,6 +47,12 @@ void target_t::memory(const NetMemory*)
|
||||
"Unhandled memory." << endl;
|
||||
}
|
||||
|
||||
void target_t::variable(const NetVariable*that)
|
||||
{
|
||||
cerr << that->get_line() << ": error: target (" << typeid(*this).name()
|
||||
<< "): Unhandled variable <" << that->basename() << ">." << endl;
|
||||
}
|
||||
|
||||
void target_t::func_def(const NetScope*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -317,6 +323,12 @@ void expr_scan_t::expr_const(const NetEConst*)
|
||||
"unhandled expr_const." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_creal(const NetECReal*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_creal." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_concat(const NetEConcat*that)
|
||||
{
|
||||
cerr << that->get_line() << ": expr_scan_t (" <<
|
||||
@@ -377,6 +389,12 @@ void expr_scan_t::expr_unary(const NetEUnary*)
|
||||
"unhandled expr_unary." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_variable(const NetEVariable*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_variable." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
@@ -385,6 +403,10 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.64 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.63 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __target_H
|
||||
#define __target_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.60 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.61 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -68,6 +68,9 @@ struct target_t {
|
||||
/* Output a memory (called for each memory object) */
|
||||
virtual void memory(const NetMemory*);
|
||||
|
||||
/* Output an event object. Called for each named event in the scope. */
|
||||
virtual void variable(const NetVariable*);
|
||||
|
||||
/* Output a defined task. */
|
||||
virtual void task_def(const NetScope*);
|
||||
virtual void func_def(const NetScope*);
|
||||
@@ -128,6 +131,7 @@ struct target_t {
|
||||
struct expr_scan_t {
|
||||
virtual ~expr_scan_t();
|
||||
virtual void expr_const(const NetEConst*);
|
||||
virtual void expr_creal(const NetECReal*);
|
||||
virtual void expr_concat(const NetEConcat*);
|
||||
virtual void expr_memory(const NetEMemory*);
|
||||
virtual void expr_scope(const NetEScope*);
|
||||
@@ -138,6 +142,7 @@ struct expr_scan_t {
|
||||
virtual void expr_ternary(const NetETernary*);
|
||||
virtual void expr_ufunc(const NetEUFunc*);
|
||||
virtual void expr_unary(const NetEUnary*);
|
||||
virtual void expr_variable(const NetEVariable*);
|
||||
virtual void expr_binary(const NetEBinary*);
|
||||
};
|
||||
|
||||
@@ -162,6 +167,10 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.61 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.60 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-generic-edif.c,v 1.10 2002/10/28 02:05:56 steve Exp $"
|
||||
#ident "$Id: d-generic-edif.c,v 1.12 2002/11/01 02:36:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
@@ -174,7 +174,18 @@ static const char*external_library_text =
|
||||
" (port Q (direction OUTPUT))\n"
|
||||
" (port D (direction INPUT))\n"
|
||||
" (port C (direction INPUT))\n"
|
||||
" (port CE (direction INPUT)))))\n"
|
||||
" (port CE (direction INPUT))\n"
|
||||
" (port CLR (direction INPUT)))))\n"
|
||||
" (cell FDCPE (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface\n"
|
||||
" (port Q (direction OUTPUT))\n"
|
||||
" (port D (direction INPUT))\n"
|
||||
" (port C (direction INPUT))\n"
|
||||
" (port CE (direction INPUT))\n"
|
||||
" (port PRE (direction INPUT))\n"
|
||||
" (port CLR (direction INPUT)))))\n"
|
||||
" (cell GND (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
@@ -226,11 +237,11 @@ static void edif_show_consts(ivl_design_t des)
|
||||
switch (val[pin]) {
|
||||
case '0':
|
||||
name = "GND";
|
||||
port = "G";
|
||||
port = "GROUND";
|
||||
break;
|
||||
case '1':
|
||||
name = "VCC";
|
||||
port = "P";
|
||||
port = "VCC";
|
||||
break;
|
||||
default:
|
||||
name = "???";
|
||||
@@ -260,7 +271,8 @@ void edif_show_footer(ivl_design_t des)
|
||||
edif_show_consts(des);
|
||||
|
||||
for (cur = net_list ; cur ; cur = cur->next) {
|
||||
fprintf(xnf, "(net N%u (joined %s))\n", nref, cur->joined);
|
||||
fprintf(xnf, "(net (rename N%u \"%s\") (joined %s))\n",
|
||||
nref, ivl_nexus_name(cur->nex), cur->joined);
|
||||
nref += 1;
|
||||
}
|
||||
|
||||
@@ -355,6 +367,19 @@ void edif_show_generic_dff(ivl_lpm_t net)
|
||||
ivl_nexus_t nex;
|
||||
char jbuf[1024];
|
||||
unsigned idx;
|
||||
ivl_nexus_t aclr = ivl_lpm_async_clr(net);
|
||||
ivl_nexus_t aset = ivl_lpm_async_set(net);
|
||||
ivl_expr_t avalue = 0;
|
||||
const char*abits = 0;
|
||||
const char*fdcell = "FDCE";
|
||||
|
||||
if (aset != 0) {
|
||||
fdcell = "FDCPE";
|
||||
avalue = ivl_lpm_aset_value(net);
|
||||
assert(avalue);
|
||||
abits = ivl_expr_bits(avalue);
|
||||
assert(abits);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
|
||||
@@ -363,7 +388,8 @@ void edif_show_generic_dff(ivl_lpm_t net)
|
||||
fprintf(xnf, "(instance (rename U%u \"%s[%u]\")",
|
||||
edif_uref, ivl_lpm_name(net), idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef FDCE (libraryRef VIRTEX))))\n");
|
||||
" (cellRef %s (libraryRef VIRTEX))))\n",
|
||||
fdcell);
|
||||
|
||||
nex = ivl_lpm_q(net, idx);
|
||||
sprintf(jbuf, "(portRef Q (instanceRef U%u))", edif_uref);
|
||||
@@ -381,6 +407,25 @@ void edif_show_generic_dff(ivl_lpm_t net)
|
||||
sprintf(jbuf, "(portRef CE (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(nex, jbuf);
|
||||
}
|
||||
|
||||
if (aclr) {
|
||||
sprintf(jbuf, "(portRef CLR (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(aclr, jbuf);
|
||||
}
|
||||
|
||||
|
||||
if (aset) {
|
||||
if (abits[idx] == '1') {
|
||||
sprintf(jbuf, "(portRef PRE (instanceRef U%u))",
|
||||
edif_uref);
|
||||
edif_set_nexus_joint(aset, jbuf);
|
||||
} else {
|
||||
assert(aclr == 0);
|
||||
sprintf(jbuf, "(portRef CLR (instanceRef U%u))",
|
||||
edif_uref);
|
||||
edif_set_nexus_joint(aset, jbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,6 +449,14 @@ const struct device_s d_generic_edif = {
|
||||
|
||||
/*
|
||||
* $Log: d-generic-edif.c,v $
|
||||
* Revision 1.12 2002/11/01 02:36:22 steve
|
||||
* Give nets better names, if available.
|
||||
*
|
||||
* Revision 1.11 2002/10/30 03:58:45 steve
|
||||
* Fix up left shift to pass compile,
|
||||
* fix up ADD/SUB to generate missing pieces,
|
||||
* Add the asynch set/reset to DFF devices.
|
||||
*
|
||||
* Revision 1.10 2002/10/28 02:05:56 steve
|
||||
* Add Virtex code generators for left shift,
|
||||
* subtraction, and GE comparators.
|
||||
|
||||
+416
-93
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-virtex.c,v 1.16 2002/10/28 02:05:56 steve Exp $"
|
||||
#ident "$Id: d-virtex.c,v 1.21 2002/11/24 02:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
@@ -38,6 +38,8 @@
|
||||
* place-and-route step, as it is not normally needed within an
|
||||
* FPGA net.
|
||||
*
|
||||
* BUFT O, I, T
|
||||
*
|
||||
* INV O, I
|
||||
* Inverting buffer.
|
||||
*
|
||||
@@ -68,6 +70,19 @@ static const char*virtex_library_text =
|
||||
" (interface\n"
|
||||
" (port O (direction OUTPUT))\n"
|
||||
" (port I (direction INPUT)))))\n"
|
||||
" (cell BUFG (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface\n"
|
||||
" (port O (direction OUTPUT))\n"
|
||||
" (port I (direction INPUT)))))\n"
|
||||
" (cell BUFT (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface\n"
|
||||
" (port O (direction OUTPUT))\n"
|
||||
" (port I (direction OUTPUT))\n"
|
||||
" (port T (direction INPUT)))))\n"
|
||||
" (cell FDCE (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
@@ -75,13 +90,18 @@ static const char*virtex_library_text =
|
||||
" (port Q (direction OUTPUT))\n"
|
||||
" (port D (direction INPUT))\n"
|
||||
" (port C (direction INPUT))\n"
|
||||
" (port CE (direction INPUT)))))\n"
|
||||
" (cell GBUF (cellType GENERIC)\n"
|
||||
" (port CE (direction INPUT))\n"
|
||||
" (port CLR (direction INPUT)))))\n"
|
||||
" (cell FDCPE (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface\n"
|
||||
" (port O (direction OUTPUT))\n"
|
||||
" (port I (direction INPUT)))))\n"
|
||||
" (port Q (direction OUTPUT))\n"
|
||||
" (port D (direction INPUT))\n"
|
||||
" (port C (direction INPUT))\n"
|
||||
" (port CE (direction INPUT))\n"
|
||||
" (port PRE (direction INPUT))\n"
|
||||
" (port CLR (direction INPUT)))))\n"
|
||||
" (cell GND (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
@@ -215,9 +235,23 @@ static void edif_show_virtex_pad(ivl_signal_t sig, const char*str)
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
|
||||
char port_name[256];
|
||||
edif_uref += 1;
|
||||
|
||||
/* Calculate the name of the net that connects the
|
||||
pad to the I/OBUF. This leads to more humane
|
||||
names in the mapped netlist. */
|
||||
if (ivl_signal_pins(sig) == 1)
|
||||
sprintf(port_name, "(rename U%uN \"%s\")",
|
||||
edif_uref, ivl_signal_basename(sig));
|
||||
else
|
||||
sprintf(port_name, "(rename U%uN \"%s[%u]\")",
|
||||
edif_uref, ivl_signal_basename(sig), idx);
|
||||
|
||||
|
||||
/* Draw the PAD and the I/O BUF, and connect the buffer
|
||||
to the logic that we are generating. */
|
||||
|
||||
switch (ivl_signal_port(sig)) {
|
||||
case IVL_SIP_INPUT:
|
||||
fprintf(xnf, "(instance U%uPAD"
|
||||
@@ -232,10 +266,11 @@ static void edif_show_virtex_pad(ivl_signal_t sig, const char*str)
|
||||
" (viewRef net "
|
||||
" (cellRef IBUF (libraryRef VIRTEX))))\n",
|
||||
edif_uref);
|
||||
fprintf(xnf, "(net U%uN (joined"
|
||||
|
||||
fprintf(xnf, "(net %s (joined"
|
||||
" (portRef IPAD (instanceRef U%uPAD))"
|
||||
" (portRef I (instanceRef U%u))))\n",
|
||||
edif_uref, edif_uref, edif_uref);
|
||||
port_name, edif_uref, edif_uref);
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_signal_pin(sig, idx), jbuf);
|
||||
@@ -254,10 +289,11 @@ static void edif_show_virtex_pad(ivl_signal_t sig, const char*str)
|
||||
" (viewRef net "
|
||||
" (cellRef OBUF (libraryRef VIRTEX))))\n",
|
||||
edif_uref);
|
||||
fprintf(xnf, "(net U%uN (joined"
|
||||
|
||||
fprintf(xnf, "(net %s (joined"
|
||||
" (portRef OPAD (instanceRef U%uPAD))"
|
||||
" (portRef O (instanceRef U%u))))\n",
|
||||
edif_uref, edif_uref, edif_uref);
|
||||
port_name, edif_uref, edif_uref);
|
||||
|
||||
sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_signal_pin(sig, idx), jbuf);
|
||||
@@ -367,7 +403,7 @@ void edif_show_cellref_logic(ivl_net_logic_t net, const char*cellref)
|
||||
strncpy(tmpname, cellref, cp-cellref);
|
||||
tmpname[cp-cellref] = 0;
|
||||
|
||||
fprintf(xnf, "(instance (rename U%u (string \"%s\"))"
|
||||
fprintf(xnf, "(instance (rename U%u \"%s\")"
|
||||
" (viewRef net (cellRef %s (libraryRef VIRTEX))))\n",
|
||||
edif_uref, ivl_logic_name(net), tmpname);
|
||||
|
||||
@@ -395,6 +431,227 @@ void edif_show_cellref_logic(ivl_net_logic_t net, const char*cellref)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function draw wide AND-like devices. The input must have at
|
||||
* least 5 bits.
|
||||
*/
|
||||
static void wide_AND_logic(ivl_net_logic_t net, unsigned edif_uref)
|
||||
{
|
||||
char jbuf[1024];
|
||||
|
||||
/* This is the number of input bits left to connect. */
|
||||
unsigned ibits = ivl_logic_pins(net) - 1;
|
||||
/* Index to the next input bit. */
|
||||
unsigned idx = 1;
|
||||
unsigned slice = 0;
|
||||
|
||||
const char*lut4_init;
|
||||
const char*lut3_init;
|
||||
const char*lut2_init;
|
||||
const char*lut1_dev;
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
case IVL_LO_AND:
|
||||
lut4_init = "\"8000\"";
|
||||
lut3_init = "\"80\"";
|
||||
lut2_init = "\"8\"";
|
||||
lut1_dev = "BUF";
|
||||
break;
|
||||
case IVL_LO_NOR:
|
||||
lut4_init = "\"0001\"";
|
||||
lut3_init = "\"01\"";
|
||||
lut2_init = "\"1\"";
|
||||
lut1_dev = "INV";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
assert(ibits > 4);
|
||||
|
||||
while (ibits >= 4) {
|
||||
|
||||
/* The least significant bits are ANDed together 4 at a
|
||||
time with LUT4 devices. The output of the LUT4 device
|
||||
connects to a MUXCY device that passes its output
|
||||
up to the next stage.
|
||||
|
||||
The DI input of the MUXCY (S==0) is connected to
|
||||
ground, so that the ouput of the chain is pinned to 0
|
||||
if this slice does not AND to 1.
|
||||
|
||||
If the LUT emits 1, S==1 and this slice passes the
|
||||
compare from below. So the CI of the MUXCY gets the O
|
||||
of the MUXCY one slice back. */
|
||||
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT4 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string %s)))\n",
|
||||
edif_uref, slice, lut4_init);
|
||||
|
||||
fprintf(xnf, "(instance U%uM%u"
|
||||
" (viewRef net"
|
||||
" (cellRef MUXCY (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(instance U%uG%u"
|
||||
" (viewRef net"
|
||||
" (cellRef GND (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uLM%u (joined"
|
||||
" (portRef O (instanceRef U%uL%u))"
|
||||
" (portRef S (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uGM%u (joined"
|
||||
" (portRef GROUND (instanceRef U%uG%u))"
|
||||
" (portRef DI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
if (slice == 0) {
|
||||
fprintf(xnf, "(instance U%uV%u"
|
||||
" (viewRef net"
|
||||
" (cellRef VCC (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uMM%u (joined"
|
||||
" (portRef VCC (instanceRef U%uG%u))"
|
||||
" (portRef CI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
} else {
|
||||
fprintf(xnf, "(net U%uMM%u (joined"
|
||||
" (portRef O (instanceRef U%uM%u))"
|
||||
" (portReg CI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice-1,
|
||||
edif_uref, slice);
|
||||
}
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I2 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+2), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I3 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+3), jbuf);
|
||||
|
||||
ibits -= 4;
|
||||
idx += 4;
|
||||
slice += 1;
|
||||
}
|
||||
|
||||
if (ibits == 0) {
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%uM%u))",
|
||||
edif_uref, slice-1);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ibits) {
|
||||
|
||||
case 1:
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef %s (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice, lut1_dev);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string %s)))\n",
|
||||
edif_uref, slice, lut2_init);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(xnf, "(instance U%uL%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT3 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string %s)))\n",
|
||||
edif_uref, slice, lut3_init);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+1), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I2 (instanceRef U%uL%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, idx+2), jbuf);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
fprintf(xnf, "(instance U%uM%u"
|
||||
" (viewRef net"
|
||||
" (cellRef MUXCY (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(instance U%uG%u"
|
||||
" (viewRef net"
|
||||
" (cellRef GND (libraryRef VIRTEX))))\n",
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uLM%u (joined"
|
||||
" (portRef O (instanceRef U%uL%u))"
|
||||
" (portRef S (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uGM%u (joined"
|
||||
" (portRef GROUND (instanceRef U%uG%u))"
|
||||
" (portRef DI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice,
|
||||
edif_uref, slice);
|
||||
|
||||
fprintf(xnf, "(net U%uMM%u (joined"
|
||||
" (portRef O (instanceRef U%uM%u))"
|
||||
" (portReg CI (instanceRef U%uM%u))))\n",
|
||||
edif_uref, slice,
|
||||
edif_uref, slice-1,
|
||||
edif_uref, slice);
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%uM%u))",
|
||||
edif_uref, slice);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
|
||||
}
|
||||
|
||||
static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
{
|
||||
char jbuf[1024];
|
||||
@@ -411,7 +668,6 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_AND:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
@@ -436,6 +692,9 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
ivl_logic_pin(net, 3),
|
||||
ivl_logic_pin(net, 4), "8000");
|
||||
break;
|
||||
default:
|
||||
wide_AND_logic(net, edif_uref);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -454,8 +713,24 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF1:
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
fprintf(xnf, "(instance (rename U%u \"%s\")",
|
||||
edif_uref, ivl_logic_name(net));
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef TBUF (libraryRef VIRTEX))))\n");
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef T (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_logic_pin(net, 2), jbuf);
|
||||
break;
|
||||
|
||||
case IVL_LO_NOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
@@ -480,6 +755,9 @@ static void edif_show_virtex_logic(ivl_net_logic_t net)
|
||||
ivl_logic_pin(net, 3),
|
||||
ivl_logic_pin(net, 4), "0001");
|
||||
break;
|
||||
default:
|
||||
wide_AND_logic(net, edif_uref);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1161,12 +1439,18 @@ static void edif_show_virtex_add(ivl_lpm_t net)
|
||||
unsigned nref = 0;
|
||||
unsigned ha_init = 6;
|
||||
|
||||
edif_uref += 1;
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
ha_init = 6;
|
||||
fprintf(xnf, "(comment \"U%u implements %u bit ADD.\")\n",
|
||||
edif_uref, ivl_lpm_width(net));
|
||||
break;
|
||||
case IVL_LPM_SUB:
|
||||
ha_init = 9;
|
||||
fprintf(xnf, "(comment \"U%u implements %u bit SUB.\")\n",
|
||||
edif_uref, ivl_lpm_width(net));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -1175,7 +1459,6 @@ static void edif_show_virtex_add(ivl_lpm_t net)
|
||||
/* Handle the special case that the adder is only one bit
|
||||
wide. Generate an XOR gate to perform the half-add. */
|
||||
if (ivl_lpm_width(net) == 1) {
|
||||
edif_uref += 1;
|
||||
|
||||
edif_show_lut2(ivl_lpm_name(net), edif_uref,
|
||||
ivl_lpm_q(net, 0),
|
||||
@@ -1186,30 +1469,74 @@ static void edif_show_virtex_add(ivl_lpm_t net)
|
||||
}
|
||||
|
||||
assert(ivl_lpm_width(net) > 1);
|
||||
edif_uref += 1;
|
||||
|
||||
/* First, draw the bottom bit slice of the adder. This
|
||||
includes the LUT2 device to perform the addition, and a
|
||||
MUXCY_L device to send the carry up to the next bit. */
|
||||
fprintf(xnf, "(instance (rename U%u_L0 \"%s\"[0])"
|
||||
" (property INIT (string \"%u\"))", edif_uref,
|
||||
ivl_lpm_name(net), ha_init);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
|
||||
includes the LUT2 device to perform the addition, a
|
||||
MUXCY_L device to send the carry up to the next bit,
|
||||
and an XORCY to make the output bit[0]. The latter is not
|
||||
always needed, but it is free, because the XORCY is this
|
||||
slice cannot otherwise be used anyhow. */
|
||||
fprintf(xnf, "(instance U%u_L0"
|
||||
" (viewRef net (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string \"%u\")))\n",
|
||||
edif_uref, ha_init);
|
||||
|
||||
fprintf(xnf, "(instance (rename U%u_X0 \"%s[0]\")"
|
||||
" (viewRef net"
|
||||
" (cellRef XORCY (libraryRef VIRTEX))))\n",
|
||||
edif_uref, ivl_lpm_name(net));
|
||||
|
||||
fprintf(xnf, "(instance U%u_M0", edif_uref);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))", edif_uref);
|
||||
/* If the device is an ADD, then the CI is set to 0. If the
|
||||
device is really a SUB, then tie the CI to 1. This adds in
|
||||
the (+1) of the two's complement. */
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
fprintf(xnf, "(instance U%u_FILL"
|
||||
" (viewRef net"
|
||||
" (cellRef GND (libraryRef VIRTEX))))\n",
|
||||
edif_uref);
|
||||
fprintf(xnf, "(net U%u_FILLN (joined"
|
||||
" (portRef GROUND (instanceRef U%u_FILL))"
|
||||
" (portRef CI (instanceRef U%u_M0))"
|
||||
" (portRef CI (instanceRef U%u_X0))))\n",
|
||||
edif_uref, edif_uref, edif_uref, edif_uref);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SUB:
|
||||
fprintf(xnf, "(instance U%u_FILL"
|
||||
" (viewRef net"
|
||||
" (cellRef VCC (libraryRef VIRTEX))))\n",
|
||||
edif_uref);
|
||||
fprintf(xnf, "(net U%u_FILLN (joined"
|
||||
" (portRef VCC (instanceRef U%u_FILL))"
|
||||
" (portRef CI (instanceRef U%u_M0))"
|
||||
" (portRef CI (instanceRef U%u_X0))))\n",
|
||||
edif_uref, edif_uref, edif_uref, edif_uref);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))"
|
||||
" (portRef DI (instanceRef U%u_M0))",
|
||||
edif_uref, edif_uref);
|
||||
edif_set_nexus_joint(ivl_lpm_data(net, 0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L0))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_lpm_datab(net, 0), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%u_L0))"
|
||||
" (portRef S (instanceRef U%u_M0))",
|
||||
edif_uref, edif_uref);
|
||||
fprintf(xnf, "(net U%uN%u (joined"
|
||||
" (portRef O (instanceRef U%u_L0))"
|
||||
" (portRef S (instanceRef U%u_M0))"
|
||||
" (portRef LI (instanceRef U%u_X0))))\n",
|
||||
edif_uref, nref++, edif_uref, edif_uref, edif_uref);
|
||||
|
||||
sprintf(jbuf, "(portRef O (instanceRef U%u_X0))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_lpm_q(net, 0), jbuf);
|
||||
|
||||
/* Now draw all the inside bit slices. These include the LUT2
|
||||
@@ -1219,19 +1546,20 @@ static void edif_show_virtex_add(ivl_lpm_t net)
|
||||
device, the other devices have local names. */
|
||||
for (idx = 1 ; idx < (ivl_lpm_width(net)-1) ; idx += 1) {
|
||||
|
||||
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"%u\"))",
|
||||
fprintf(xnf, "(instance U%u_L%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string \"%u\")))\n",
|
||||
edif_uref, idx, ha_init);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(instance U%u_M%u", edif_uref, idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(instance (rename U%u_X%u \"%s[%u]\")",
|
||||
fprintf(xnf, "(instance (rename U%u_X%u \"%s[%u]\")"
|
||||
" (viewRef net"
|
||||
" (cellRef XORCY (libraryRef VIRTEX))))\n",
|
||||
edif_uref, idx, ivl_lpm_name(net), idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef XORCY (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(net U%uN%u (joined"
|
||||
" (portRef O (instanceRef U%u_L%u))"
|
||||
@@ -1247,8 +1575,9 @@ static void edif_show_virtex_add(ivl_lpm_t net)
|
||||
edif_uref, nref++, edif_uref, idx, edif_uref, idx,
|
||||
edif_uref, idx-1);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))",
|
||||
edif_uref, idx);
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))"
|
||||
" (portRef DI (instanceRef U%u_M%u))",
|
||||
edif_uref, idx, edif_uref, idx);
|
||||
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L%u))",
|
||||
@@ -1261,10 +1590,11 @@ static void edif_show_virtex_add(ivl_lpm_t net)
|
||||
}
|
||||
|
||||
|
||||
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"%u\"))",
|
||||
fprintf(xnf, "(instance U%u_L%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string \"%u\")))\n",
|
||||
edif_uref, idx, ha_init);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(instance (rename U%u_X%u \"%s[%u]\")",
|
||||
edif_uref, idx, ivl_lpm_name(net), idx);
|
||||
@@ -1319,16 +1649,20 @@ static void virtex_show_cmp_ge(ivl_lpm_t net)
|
||||
/* First, draw the bottom bit slice of the comparator. This
|
||||
includes the LUT2 device to perform the addition, and a
|
||||
MUXCY_L device to send the carry up to the next bit. */
|
||||
fprintf(xnf, "(instance (rename U%u_L0 \"%s\"[0])"
|
||||
" (property INIT (string \"9\"))", edif_uref,
|
||||
fprintf(xnf, "(instance (rename U%u_L0 \"%s[0]\")"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string \"9\")))\n", edif_uref,
|
||||
ivl_lpm_name(net));
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(instance U%u_M0", edif_uref);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef MUXCY_L (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(net U%uN%u (joined"
|
||||
" (portRef O (instanceRef U%u_L0))"
|
||||
" (portRef S (instanceRef U%u_M0))))\n",
|
||||
edif_uref, nref++, edif_uref, edif_uref);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L0))", edif_uref);
|
||||
edif_set_nexus_joint(ivl_lpm_data(net, 0), jbuf);
|
||||
|
||||
@@ -1366,16 +1700,15 @@ static void virtex_show_cmp_ge(ivl_lpm_t net)
|
||||
}
|
||||
|
||||
/* Now draw all the inside bit slices. These include the LUT2
|
||||
device for the basic add, the MUXCY_L device to propagate
|
||||
the carry, and an XORCY device to generate the real
|
||||
output. The XORCY device carries the name of the LPM
|
||||
device, the other devices have local names. */
|
||||
for (idx = 1 ; idx < (ivl_lpm_width(net)-1) ; idx += 1) {
|
||||
device for the NOR2 and the MUXCY_L device to propagate
|
||||
the result. */
|
||||
for (idx = 1 ; idx < (ivl_lpm_width(net)) ; idx += 1) {
|
||||
|
||||
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"9\"))",
|
||||
fprintf(xnf, "(instance U%u_L%u"
|
||||
" (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX)))"
|
||||
" (property INIT (string \"9\")))\n",
|
||||
edif_uref, idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(instance U%u_M%u", edif_uref, idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
@@ -1406,35 +1739,8 @@ static void virtex_show_cmp_ge(ivl_lpm_t net)
|
||||
}
|
||||
|
||||
|
||||
fprintf(xnf, "(instance U%u_L%u) (property INIT (string \"9\"))",
|
||||
edif_uref, idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef LUT2 (libraryRef VIRTEX))))\n");
|
||||
|
||||
fprintf(xnf, "(net U%uN%u (joined"
|
||||
" (portRef O (instanceRef U%u_L%u))"
|
||||
" (portRef LI (instanceRef U%u_X%u))))\n",
|
||||
edif_uref, nref++, edif_uref, idx, edif_uref, idx);
|
||||
|
||||
fprintf(xnf, "(net U%uN%u (joined"
|
||||
" (portRef CI (instanceRef U%u_X%u))"
|
||||
" (portRef LO (instanceRef U%u_M%u))))\n",
|
||||
edif_uref, nref++, edif_uref, idx, edif_uref, idx-1);
|
||||
|
||||
sprintf(jbuf, "(portRef I0 (instanceRef U%u_L%u))",
|
||||
edif_uref, idx);
|
||||
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef I1 (instanceRef U%u_L%u))",
|
||||
edif_uref, idx);
|
||||
edif_set_nexus_joint(ivl_lpm_datab(net, idx), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef DI (instanceRef U%u_M%u))",
|
||||
edif_uref, idx);
|
||||
edif_set_nexus_joint(ivl_lpm_data(net, idx), jbuf);
|
||||
|
||||
sprintf(jbuf, "(portRef LO (instanceRef U%u_M%u))",
|
||||
edif_uref, idx);
|
||||
edif_uref, idx-1);
|
||||
edif_set_nexus_joint(ivl_lpm_q(net, 0), jbuf);
|
||||
}
|
||||
|
||||
@@ -1546,14 +1852,25 @@ static void virtex_show_shiftl(ivl_lpm_t net)
|
||||
through, and the B side which is shifted based on the
|
||||
selector identity. */
|
||||
for (sdx = 0 ; sdx < (nsel-1) ; sdx += 1) {
|
||||
unsigned shift = 1 << sdx;
|
||||
unsigned shift = 2 << sdx;
|
||||
|
||||
for (qdx = 0 ; qdx < shift ; qdx += 1) {
|
||||
for (qdx = 0 ; qdx < (width-shift) ; qdx += 1) {
|
||||
fprintf(xnf, "(net U%uC%uR%uN (joined"
|
||||
" (portRef O (instanceRef U%uC%uR%u))"
|
||||
" (portRef I0 (instanceRef U%uC%uR%u))"
|
||||
" (portRef I1 (instanceRef U%uC%uR%u))))\n",
|
||||
edif_uref, sdx, qdx,
|
||||
edif_uref, sdx, qdx,
|
||||
edif_uref, sdx+1, qdx,
|
||||
edif_uref, sdx+1, qdx + shift);
|
||||
}
|
||||
|
||||
for (qdx = (width-shift) ; qdx < width ; qdx += 1) {
|
||||
fprintf(xnf, "(net U%uC%uR%uN (joined"
|
||||
" (portRef O (instanceRef U%uC%uR%u))"
|
||||
" (portRef I0 (instanceRef U%uC%uR%u))))\n",
|
||||
edif_uref, sdx, qdx,
|
||||
edif_uref, sdx+1, qdx,
|
||||
edif_uref, sdx, qdx,
|
||||
edif_uref, sdx+1, qdx);
|
||||
|
||||
fprintf(xnf, "(instance U%uC%uR%uG"
|
||||
@@ -1565,20 +1882,9 @@ static void virtex_show_shiftl(ivl_lpm_t net)
|
||||
" (portRef I1 (instanceRef U%uC%uR%u))"
|
||||
" (portRef GROUND (instanceRef U%uC%uR%uG))))\n",
|
||||
edif_uref, sdx+1, qdx,
|
||||
edif_uref, sdx+1, qdx,
|
||||
edif_uref, sdx+1, (qdx+shift)%width,
|
||||
edif_uref, sdx+1, qdx);
|
||||
}
|
||||
|
||||
for (qdx = shift ; qdx < width ; qdx += 1) {
|
||||
fprintf(xnf, "(net U%uC%uR%uN (joined"
|
||||
" (portRef O (instanceRef U%uC%uR%u))"
|
||||
" (portRef I0 (instanceRef U%uC%uR%u))"
|
||||
" (portRef I1 (instancdRef U%uC%uR%u))))\n",
|
||||
edif_uref, sdx, qdx,
|
||||
edif_uref, sdx, qdx,
|
||||
edif_uref, sdx+1, qdx,
|
||||
edif_uref, sdx+1, qdx - shift);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1602,6 +1908,23 @@ const struct device_s d_virtex_edif = {
|
||||
|
||||
/*
|
||||
* $Log: d-virtex.c,v $
|
||||
* Revision 1.21 2002/11/24 02:26:14 steve
|
||||
* Fix instanceRef spelling.
|
||||
*
|
||||
* Revision 1.20 2002/11/22 05:46:06 steve
|
||||
* Handle wide AND/NOR devices with Virtex carry logic.
|
||||
*
|
||||
* Revision 1.19 2002/11/22 01:45:40 steve
|
||||
* Implement bufif1 as BUFT
|
||||
*
|
||||
* Revision 1.18 2002/11/01 02:36:34 steve
|
||||
* Fix bottom bit of ADD/SUB device.
|
||||
*
|
||||
* Revision 1.17 2002/10/30 03:58:45 steve
|
||||
* Fix up left shift to pass compile,
|
||||
* fix up ADD/SUB to generate missing pieces,
|
||||
* Add the asynch set/reset to DFF devices.
|
||||
*
|
||||
* Revision 1.16 2002/10/28 02:05:56 steve
|
||||
* Add Virtex code generators for left shift,
|
||||
* subtraction, and GE comparators.
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.9 2001/11/17 17:57:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.10 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -72,7 +72,7 @@ install: all installdirs $(libdir)/ivl/stub.tgt \
|
||||
$(includedir)/vpi_user.h
|
||||
|
||||
$(libdir)/ivl/stub.tgt: ./stub.tgt
|
||||
$(INSTALL_DATA) ./stub.tgt $(libdir)/ivl/stub.tgt
|
||||
$(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
+74
-11
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: stub.c,v 1.70 2002/10/23 01:45:24 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.72 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -40,6 +40,19 @@ static void show_expression(ivl_expr_t net, unsigned ind)
|
||||
const ivl_expr_type_t code = ivl_expr_type(net);
|
||||
unsigned width = ivl_expr_width(net);
|
||||
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
|
||||
const char*vt = "?";
|
||||
|
||||
switch (ivl_expr_value(net)) {
|
||||
case IVL_VT_VOID:
|
||||
vt = "void";
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
vt = "real";
|
||||
break;
|
||||
case IVL_VT_VECTOR:
|
||||
vt = "vector";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
|
||||
@@ -50,15 +63,15 @@ static void show_expression(ivl_expr_t net, unsigned ind)
|
||||
break;
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
fprintf(out, "%*s<\"%c\" width=%u, %s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign);
|
||||
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign, vt);
|
||||
show_expression(ivl_expr_oper1(net), ind+3);
|
||||
show_expression(ivl_expr_oper2(net), ind+3);
|
||||
break;
|
||||
|
||||
case IVL_EX_CONCAT:
|
||||
fprintf(out, "%*s<concat repeat=%u, width=%u, %s>\n", ind, "",
|
||||
ivl_expr_repeat(net), width, sign);
|
||||
fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
|
||||
ind, "", ivl_expr_repeat(net), width, sign, vt);
|
||||
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
|
||||
show_expression(ivl_expr_parm(net, idx), ind+3);
|
||||
|
||||
@@ -116,6 +129,15 @@ static void show_expression(ivl_expr_t net, unsigned ind)
|
||||
show_expression(ivl_expr_oper1(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_EX_VARIABLE:
|
||||
fprintf(out, "%*s<variable %s, type=%s>\n",
|
||||
ind, "", ivl_expr_name(net), vt);
|
||||
break;
|
||||
|
||||
case IVL_EX_REALNUM:
|
||||
fprintf(out, "%*s<realnum=%f>\n", ind, "", ivl_expr_dvalue(net));
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
|
||||
break;
|
||||
@@ -244,6 +266,7 @@ static void show_lpm(ivl_lpm_t net)
|
||||
static void show_assign_lval(ivl_lval_t lval, unsigned ind)
|
||||
{
|
||||
ivl_memory_t mem;
|
||||
ivl_variable_t var;
|
||||
|
||||
if ( (mem = ivl_lval_mem(lval)) ) {
|
||||
|
||||
@@ -254,6 +277,10 @@ static void show_assign_lval(ivl_lval_t lval, unsigned ind)
|
||||
show_expression(ivl_lval_idx(lval), ind+4);
|
||||
fprintf(out, "%*s]\n", ind, "");
|
||||
|
||||
} else if ( (var = ivl_lval_var(lval)) ) {
|
||||
|
||||
fprintf(out, "%*svariable %s\n", ind, "", ivl_variable_name(var));
|
||||
|
||||
} else {
|
||||
unsigned pp;
|
||||
ivl_nexus_t nex = ivl_lval_pin(lval, 0);
|
||||
@@ -450,6 +477,26 @@ static int show_process(ivl_process_t net, void*x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_variable(ivl_variable_t net)
|
||||
{
|
||||
const char*type = "?";
|
||||
const char*name = ivl_variable_name(net);
|
||||
|
||||
switch (ivl_variable_type(net)) {
|
||||
case IVL_VT_VOID:
|
||||
type = "void";
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
type = "real";
|
||||
break;
|
||||
case IVL_VT_VECTOR:
|
||||
type = "vector";
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(out, " variable %s %s;\n", type, name);
|
||||
}
|
||||
|
||||
static void show_event(ivl_event_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
@@ -666,26 +713,31 @@ static int show_scope(ivl_scope_t net, void*x)
|
||||
|
||||
switch (ivl_scope_type(net)) {
|
||||
case IVL_SCT_MODULE:
|
||||
fprintf(out, " module %s\n", ivl_scope_tname(net));
|
||||
fprintf(out, " module %s", ivl_scope_tname(net));
|
||||
break;
|
||||
case IVL_SCT_FUNCTION:
|
||||
fprintf(out, " function %s\n", ivl_scope_tname(net));
|
||||
fprintf(out, " function %s", ivl_scope_tname(net));
|
||||
break;
|
||||
case IVL_SCT_BEGIN:
|
||||
fprintf(out, " begin : %s\n", ivl_scope_tname(net));
|
||||
fprintf(out, " begin : %s", ivl_scope_tname(net));
|
||||
break;
|
||||
case IVL_SCT_FORK:
|
||||
fprintf(out, " fork : %s\n", ivl_scope_tname(net));
|
||||
fprintf(out, " fork : %s", ivl_scope_tname(net));
|
||||
break;
|
||||
case IVL_SCT_TASK:
|
||||
fprintf(out, " task %s\n", ivl_scope_tname(net));
|
||||
fprintf(out, " task %s", ivl_scope_tname(net));
|
||||
break;
|
||||
default:
|
||||
fprintf(out, " type(%u) %s\n", ivl_scope_type(net),
|
||||
fprintf(out, " type(%u) %s", ivl_scope_type(net),
|
||||
ivl_scope_tname(net));
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(out, " time units = 10e%d\n", ivl_scope_time_units(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_vars(net) ; idx += 1)
|
||||
show_variable(ivl_scope_var(net, idx));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1)
|
||||
show_event(ivl_scope_event(net, idx));
|
||||
|
||||
@@ -728,6 +780,17 @@ int target_design(ivl_design_t des)
|
||||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.72 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.71 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.70 2002/10/23 01:45:24 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
|
||||
@@ -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
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.11 2002/09/27 16:33:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.13 2003/01/26 21:15:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -50,7 +50,7 @@ all: vvp.tgt
|
||||
$(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvp.o draw_mux.o eval_expr.o vector.o vvp_process.o vvp_scope.o
|
||||
O = vvp.o draw_mux.o eval_expr.o eval_real.o vector.o vvp_process.o vvp_scope.o
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
@@ -78,7 +78,7 @@ check: all
|
||||
install: all installdirs $(libdir)/ivl/vvp.tgt
|
||||
|
||||
$(libdir)/ivl/vvp.tgt: ./vvp.tgt
|
||||
$(INSTALL_DATA) ./vvp.tgt $(libdir)/ivl/vvp.tgt
|
||||
$(INSTALL_PROGRAM) ./vvp.tgt $(libdir)/ivl/vvp.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
+291
-99
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_expr.c,v 1.82 2002/10/20 02:55:37 steve Exp $"
|
||||
#ident "$Id: eval_expr.c,v 1.90 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -28,6 +28,8 @@
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||
int ok_flags);
|
||||
|
||||
int number_is_unknown(ivl_expr_t ex)
|
||||
{
|
||||
@@ -187,7 +189,8 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
||||
|
||||
} else if (lv.wid < ewid) {
|
||||
unsigned short base = allocate_vector(ewid);
|
||||
clr_vector(lv);
|
||||
if (lv.base >= 8)
|
||||
clr_vector(lv);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", base,
|
||||
lv.base, lv.wid);
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
@@ -199,6 +202,43 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
||||
return lv;
|
||||
}
|
||||
|
||||
/*
|
||||
* This handles the special case that the operands of the comparison
|
||||
* are real valued expressions.
|
||||
*/
|
||||
static struct vector_info draw_binary_expr_eq_real(ivl_expr_t exp)
|
||||
{
|
||||
struct vector_info res;
|
||||
int lword, rword;
|
||||
|
||||
res.base = allocate_vector(1);
|
||||
res.wid = 1;
|
||||
|
||||
lword = draw_eval_real(ivl_expr_oper1(exp));
|
||||
rword = draw_eval_real(ivl_expr_oper2(exp));
|
||||
|
||||
clr_word(lword);
|
||||
clr_word(rword);
|
||||
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword);
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
|
||||
case 'e':
|
||||
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
case 'n': /* != */
|
||||
fprintf(vvp_out, " %%mov %u, 4, 1;\n", res.base);
|
||||
fprintf(vvp_out, " %%inv %u, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
|
||||
unsigned ewid,
|
||||
int stuff_ok_flag)
|
||||
@@ -220,6 +260,14 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
|
||||
&& number_is_immediate(re, 16))
|
||||
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
|
||||
|
||||
if (ivl_expr_value(le) == IVL_VT_REAL) {
|
||||
assert(ivl_expr_value(re) == IVL_VT_REAL);
|
||||
return draw_binary_expr_eq_real(exp);
|
||||
}
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
|
||||
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
|
||||
|
||||
wid = ivl_expr_width(le);
|
||||
if (ivl_expr_width(re) > wid)
|
||||
wid = ivl_expr_width(re);
|
||||
@@ -232,8 +280,10 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
|
||||
assert(lv.wid == rv.wid);
|
||||
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base,
|
||||
rv.base, lv.wid);
|
||||
clr_vector(lv);
|
||||
clr_vector(rv);
|
||||
if (lv.base >= 8)
|
||||
clr_vector(lv);
|
||||
if (rv.base >= 8)
|
||||
clr_vector(rv);
|
||||
lv.base = 6;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
@@ -460,6 +510,40 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le_real(ivl_expr_t exp)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
|
||||
int lword = draw_eval_real(le);
|
||||
int rword = draw_eval_real(re);
|
||||
|
||||
res.base = allocate_vector(1);
|
||||
res.wid = 1;
|
||||
|
||||
clr_word(lword);
|
||||
clr_word(rword);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case '<':
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", lword, rword);
|
||||
fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
fprintf(vvp_out, " %%cmp/wr %d, %d;\n", rword, lword);
|
||||
fprintf(vvp_out, " %%mov %u, 5, 1;\n", res.base);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
|
||||
unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
@@ -476,6 +560,14 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
|
||||
if (ivl_expr_width(re) > owid)
|
||||
owid = ivl_expr_width(re);
|
||||
|
||||
if (ivl_expr_value(le) == IVL_VT_REAL) {
|
||||
assert(ivl_expr_value(re) == IVL_VT_REAL);
|
||||
return draw_binary_expr_le_real(exp);
|
||||
}
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
|
||||
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
|
||||
|
||||
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
|
||||
|
||||
@@ -616,9 +708,62 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
const char*opcode = "?";
|
||||
|
||||
struct vector_info lv;
|
||||
|
||||
/* Evaluate the expression that is to be shifted. */
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
|
||||
case 'l': /* << (left shift) */
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
opcode = "%shiftl";
|
||||
break;
|
||||
|
||||
case 'r': /* >> (unsigned right shift) */
|
||||
|
||||
/* with the right shift, there may be high bits that are
|
||||
shifted into the desired width of the expression, so
|
||||
we let the expression size itself, if it is bigger
|
||||
then what is requested of us. */
|
||||
if (wid > ivl_expr_width(le)) {
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
} else {
|
||||
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
|
||||
}
|
||||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
opcode = "%shiftr";
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Figure out the shift amount and load that into the index
|
||||
register. The value may be a constant, or may need to be
|
||||
evaluated at run time. */
|
||||
@@ -659,21 +804,11 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
||||
}
|
||||
}
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
fprintf(vvp_out, " %s/i0 %u, %u;\n", opcode, lv.base, lv.wid);
|
||||
|
||||
case 'l': /* << (left shift) */
|
||||
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
|
||||
break;
|
||||
|
||||
case 'r': /* >> (unsigned right shift) */
|
||||
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lv.base, lv.wid);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
if (lv.base >= 8)
|
||||
save_expression_lookaside(lv.base, exp, lv.wid);
|
||||
|
||||
return lv;
|
||||
}
|
||||
@@ -789,6 +924,12 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
|
||||
|
||||
if (lv.wid != wid) {
|
||||
fprintf(stderr, "XXXX ivl_expr_opcode(exp) = %c,"
|
||||
" lv.wid=%u, wid=%u\n", ivl_expr_opcode(exp),
|
||||
lv.wid, wid);
|
||||
}
|
||||
|
||||
assert(lv.wid == wid);
|
||||
assert(rv.wid == wid);
|
||||
|
||||
@@ -990,22 +1131,26 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
|
||||
avec.base = allocate_vector_exp(arg, awid);
|
||||
avec.wid = awid;
|
||||
|
||||
/* If it's not in the lookaside map, then
|
||||
evaluate the expression here. */
|
||||
if (avec.base == 0) {
|
||||
/* Evaluate this sub expression. */
|
||||
avec = draw_eval_expr_wid(arg, awid, 0);
|
||||
}
|
||||
|
||||
trans = awid;
|
||||
if ((off + awid) > wid)
|
||||
trans = wid - off;
|
||||
|
||||
assert(awid == avec.wid);
|
||||
if (avec.base != 0) {
|
||||
assert(awid == avec.wid);
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
res.base+off,
|
||||
avec.base, trans);
|
||||
clr_vector(avec);
|
||||
|
||||
} else {
|
||||
struct vector_info dest;
|
||||
|
||||
dest.base = res.base+off;
|
||||
dest.wid = trans;
|
||||
draw_eval_expr_dest(arg, dest, 0);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base+off,
|
||||
avec.base, trans);
|
||||
clr_vector(avec);
|
||||
|
||||
idx -= 1;
|
||||
off += trans;
|
||||
@@ -1115,6 +1260,19 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_realnum_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
double val = ivl_expr_dvalue(exp);
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
fprintf(vvp_out, " ; XXXX draw_realnum_expr(%f, %u)\n", val, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* A string in an expression is made up by copying constant bits into
|
||||
* the allocated vector.
|
||||
@@ -1171,36 +1329,54 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
||||
* offsetting the read from the lsi (least significant index) of the
|
||||
* signal.
|
||||
*/
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned lsi = ivl_expr_lsi(exp);
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
|
||||
if (swid > res.wid)
|
||||
swid = res.wid;
|
||||
|
||||
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
||||
/* If this is a REG (a variable) then I can do a vector
|
||||
read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
|
||||
res.base, vvp_signal_label(sig), lsi, swid);
|
||||
|
||||
} else {
|
||||
/* Vector reads of nets do not in general work because
|
||||
they are not really functors but references to
|
||||
scattered functors. So generate an array of loads. */
|
||||
for (idx = 0 ; idx < swid ; idx += 1) {
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, vvp_signal_label(sig), idx+lsi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < res.wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, res.wid-swid);
|
||||
}
|
||||
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
if (swid > wid)
|
||||
swid = wid;
|
||||
|
||||
/* Already in the vector lookaside? */
|
||||
res.base = allocate_vector_exp(exp, wid);
|
||||
res.wid = wid;
|
||||
if (res.base != 0)
|
||||
return res;
|
||||
|
||||
if (res.base == 0) {
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
}
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
for (idx = 0 ; idx < swid ; idx += 1)
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, vvp_signal_label(sig), idx+lsi);
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, wid-swid);
|
||||
draw_signal_dest(exp, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1314,7 +1490,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
writeable vector space and work from there instead. */
|
||||
if (subv.base < 4) {
|
||||
res.base = allocate_vector(subv.wid);
|
||||
res.wid = wid;
|
||||
res.wid = subv.wid;
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base,
|
||||
subv.base, res.wid);
|
||||
subv = res;
|
||||
@@ -1509,8 +1685,10 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
fprintf(vvp_out, ", $time");
|
||||
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
|
||||
fprintf(vvp_out, ", $stime");
|
||||
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
|
||||
fprintf(vvp_out, ", $realtime");
|
||||
else
|
||||
fprintf(vvp_out, ", ?");
|
||||
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
|
||||
continue;
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
@@ -1794,6 +1972,53 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_variable_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
ivl_variable_t var = ivl_expr_variable(exp);
|
||||
fprintf(vvp_out, " ; XXXX Read variable %s\n",
|
||||
ivl_variable_name(var));
|
||||
|
||||
res.base = 0;
|
||||
res.wid = wid;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sometimes we know ahead of time where we want the expression value
|
||||
* to go. In that case, call this function. It will check to see if
|
||||
* the expression can be preplaced, and if so it will evaluate it in
|
||||
* place.
|
||||
*/
|
||||
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
struct vector_info tmp;
|
||||
|
||||
switch (ivl_expr_type(exp)) {
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
draw_signal_dest(exp, dest);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fallback, is to draw the expression by width, and mov it to
|
||||
the required dest. */
|
||||
tmp = draw_eval_expr_wid(exp, dest.wid, stuff_ok_flag);
|
||||
assert(tmp.wid == dest.wid);
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
dest.base, tmp.base, dest.wid);
|
||||
|
||||
if (tmp.base >= 8)
|
||||
save_expression_lookaside(tmp.base, exp, tmp.wid);
|
||||
|
||||
clr_vector(tmp);
|
||||
}
|
||||
|
||||
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
@@ -1829,6 +2054,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
res = draw_number_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_REALNUM:
|
||||
res = draw_realnum_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_SELECT:
|
||||
res = draw_select_expr(exp, wid);
|
||||
break;
|
||||
@@ -1856,6 +2085,10 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
case IVL_EX_UNARY:
|
||||
res = draw_unary_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_VARIABLE:
|
||||
res = draw_variable_expr(exp, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -1868,60 +2101,19 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
||||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.82 2002/10/20 02:55:37 steve
|
||||
* Properly set or clear expression lookaside for binary expressions.
|
||||
* Revision 1.90 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.81 2002/09/27 20:24:42 steve
|
||||
* Allow expression lookaside map to spam statements.
|
||||
* Revision 1.89 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.80 2002/09/27 16:33:34 steve
|
||||
* Add thread expression lookaside map.
|
||||
* Revision 1.88 2002/12/20 01:11:14 steve
|
||||
* Evaluate shift index after shift operand because
|
||||
* the chift operand may use the index register itself.
|
||||
*
|
||||
* Revision 1.79 2002/09/24 04:20:32 steve
|
||||
* Allow results in register bits 47 in certain cases.
|
||||
*
|
||||
* Revision 1.78 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.77 2002/09/13 04:09:51 steve
|
||||
* single bit optimization for != in expressions,
|
||||
* and expand ++ and != results if needed.
|
||||
*
|
||||
* Revision 1.76 2002/09/13 03:12:50 steve
|
||||
* Optimize ==1 when in context where x vs z doesnt matter.
|
||||
*
|
||||
* Revision 1.75 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.74 2002/09/01 01:42:34 steve
|
||||
* Fix leaking vthread bits in ?: eval.
|
||||
*
|
||||
* Revision 1.73 2002/08/28 18:38:07 steve
|
||||
* Add the %subi instruction, and use it where possible.
|
||||
*
|
||||
* Revision 1.72 2002/08/28 17:15:35 steve
|
||||
* Generate %load/nx for indexed load of nets.
|
||||
*
|
||||
* Revision 1.71 2002/08/27 05:39:57 steve
|
||||
* Fix l-value indexing of memories and vectors so that
|
||||
* an unknown (x) index causes so cell to be addresses.
|
||||
*
|
||||
* Fix tangling of label identifiers in the fork-join
|
||||
* code generator.
|
||||
*
|
||||
* Revision 1.70 2002/08/22 03:38:40 steve
|
||||
* Fix behavioral eval of x?a:b expressions.
|
||||
*
|
||||
* Revision 1.69 2002/08/12 01:35:03 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.68 2002/08/05 04:18:45 steve
|
||||
* Store only the base name of memories.
|
||||
*
|
||||
* Revision 1.67 2002/08/04 18:28:15 steve
|
||||
* Do not use hierarchical names of memories to
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
* Revision 1.87 2002/12/19 23:11:29 steve
|
||||
* Keep bit select subexpression width if it is constant.
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_real.c,v 1.2 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file includes functions for evaluating REAL expressions.
|
||||
*/
|
||||
# include "vvp_priv.h"
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <math.h>
|
||||
# include <assert.h>
|
||||
|
||||
static unsigned long word_alloc_mask = 0x0f;
|
||||
|
||||
int allocate_word()
|
||||
{
|
||||
int res = 4;
|
||||
|
||||
while ((1 << res) & word_alloc_mask)
|
||||
res += 1;
|
||||
|
||||
word_alloc_mask |= 1 << res;
|
||||
return res;
|
||||
}
|
||||
|
||||
void clr_word(int res)
|
||||
{
|
||||
assert(word_alloc_mask & (1 << res));
|
||||
word_alloc_mask &= ~ (1 << res);
|
||||
}
|
||||
|
||||
|
||||
static int draw_binary_real(ivl_expr_t exp)
|
||||
{
|
||||
int l, r;
|
||||
|
||||
l = draw_eval_real(ivl_expr_oper1(exp));
|
||||
r = draw_eval_real(ivl_expr_oper2(exp));
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
|
||||
case '+':
|
||||
fprintf(vvp_out, " %%add/wr %d, %d;\n", l, r);
|
||||
clr_word(r);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
fprintf(vvp_out, " %%mul/wr %d, %d;\n", l, r);
|
||||
clr_word(r);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static int draw_number_real(ivl_expr_t exp)
|
||||
{
|
||||
int idx;
|
||||
int res = allocate_word();
|
||||
const char*bits = ivl_expr_bits(exp);
|
||||
unsigned wid = ivl_expr_width(exp);
|
||||
unsigned long mant = 0;
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1) {
|
||||
if (bits[idx] == '1')
|
||||
mant |= 1 << idx;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%loadi/wr %d, %lu, 4096;\n", res, mant);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate a real variable expression by loading the real variable
|
||||
* into a real thread word.
|
||||
*/
|
||||
static int draw_variable_real(ivl_expr_t exp)
|
||||
{
|
||||
int res = allocate_word();
|
||||
ivl_variable_t var = ivl_expr_variable(exp);
|
||||
|
||||
fprintf(vvp_out, " %%load/wr %d, W_%s;\n", res, vvp_word_label(var));
|
||||
return res;
|
||||
}
|
||||
|
||||
static int draw_realnum_real(ivl_expr_t exp)
|
||||
{
|
||||
int res = allocate_word();
|
||||
double value = ivl_expr_dvalue(exp);
|
||||
|
||||
double fract;
|
||||
int vexp;
|
||||
unsigned long mant;
|
||||
int sign = 0;
|
||||
|
||||
if (value < 0) {
|
||||
sign = 0x4000;;
|
||||
value *= -1;
|
||||
}
|
||||
|
||||
fract = frexp(value, &vexp);
|
||||
fract *= 0x10000;
|
||||
fract *= 0x10000;
|
||||
mant = fract;
|
||||
vexp -= 32;
|
||||
|
||||
vexp += 0x1000;
|
||||
assert(vexp >= 0);
|
||||
assert(vexp < 0x2000);
|
||||
vexp += sign;
|
||||
|
||||
fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load=%f\n",
|
||||
res, mant, vexp, ivl_expr_dvalue(exp));
|
||||
return res;
|
||||
}
|
||||
|
||||
static int draw_sfunc_real(ivl_expr_t exp)
|
||||
{
|
||||
int res;
|
||||
assert(ivl_expr_parms(exp) == 0);
|
||||
assert(ivl_expr_value(exp) == IVL_VT_REAL);
|
||||
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%vpi_func/r \"%s\", %d;\n",
|
||||
ivl_expr_name(exp), res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* The real value of a signal is the integer value of a signal
|
||||
* converted to real.
|
||||
*/
|
||||
static int draw_signal_real(ivl_expr_t exp)
|
||||
{
|
||||
int res = allocate_word();
|
||||
struct vector_info sv = draw_eval_expr(exp, 0);
|
||||
|
||||
fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, sv.base, sv.wid);
|
||||
clr_vector(sv);
|
||||
|
||||
fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int draw_eval_real(ivl_expr_t exp)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
switch (ivl_expr_type(exp)) {
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
res = draw_binary_real(exp);
|
||||
break;
|
||||
|
||||
case IVL_EX_NUMBER:
|
||||
res = draw_number_real(exp);
|
||||
break;
|
||||
|
||||
case IVL_EX_REALNUM:
|
||||
res = draw_realnum_real(exp);
|
||||
break;
|
||||
|
||||
case IVL_EX_VARIABLE:
|
||||
res = draw_variable_real(exp);
|
||||
break;
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
res = draw_sfunc_real(exp);
|
||||
break;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
res = draw_signal_real(exp);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(vvp_out, " ; XXXX Evaluate real expression (%d)\n",
|
||||
ivl_expr_type(exp));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: eval_real.c,v $
|
||||
* Revision 1.2 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.1 2003/01/26 21:16:00 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
|
||||
+20
-33
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $"
|
||||
#ident "$Id: vvp_priv.h,v 1.23 2003/01/26 21:16:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "ivl_target.h"
|
||||
@@ -48,6 +48,8 @@ extern const char* vvp_signal_label(ivl_signal_t sig);
|
||||
*/
|
||||
extern const char* vvp_memory_label(ivl_memory_t mem);
|
||||
|
||||
extern const char* vvp_word_label(ivl_variable_t var);
|
||||
|
||||
/*
|
||||
* This function draws a process (initial or always) into the output
|
||||
* file. It normally returns 0, but returns !0 of there is some sort
|
||||
@@ -158,6 +160,19 @@ extern int number_is_unknown(ivl_expr_t ex);
|
||||
extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid);
|
||||
extern unsigned long get_number_immediate(ivl_expr_t ex);
|
||||
|
||||
/*
|
||||
* draw_eval_real evaluates real value expressions. The return code
|
||||
* from the function is the index of the word register that contains
|
||||
* the result.
|
||||
*/
|
||||
extern int draw_eval_real(ivl_expr_t ex);
|
||||
|
||||
/*
|
||||
* These functions manage word register allocation.
|
||||
*/
|
||||
extern int allocate_word(void);
|
||||
extern void clr_word(int idx);
|
||||
|
||||
/*
|
||||
* These are used to count labels as I generate code.
|
||||
*/
|
||||
@@ -166,6 +181,10 @@ extern unsigned thread_count;
|
||||
|
||||
/*
|
||||
* $Log: vvp_priv.h,v $
|
||||
* Revision 1.23 2003/01/26 21:16:00 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.22 2002/09/27 16:33:34 steve
|
||||
* Add thread expression lookaside map.
|
||||
*
|
||||
@@ -211,37 +230,5 @@ extern unsigned thread_count;
|
||||
* 2. Id and name mangling
|
||||
* 3. A memory leak in draw_net_in_scope()
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.10 2001/05/17 04:37:02 steve
|
||||
* Behavioral ternary operators for vvp.
|
||||
*
|
||||
* Revision 1.9 2001/05/06 17:54:33 steve
|
||||
* Behavioral code to read memories. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.8 2001/04/06 02:28:03 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.7 2001/04/02 02:28:13 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.6 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.5 2001/03/27 06:27:41 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.4 2001/03/27 03:31:07 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.3 2001/03/22 05:06:21 steve
|
||||
* Geneate code for conditional statements.
|
||||
*
|
||||
* Revision 1.2 2001/03/21 01:49:43 steve
|
||||
* Scan the scopes of a design, and draw behavioral
|
||||
* blocking assignments of constants to vectors.
|
||||
*
|
||||
* Revision 1.1 2001/03/19 01:20:46 steve
|
||||
* Add the tgt-vvp code generator target.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+300
-57
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_process.c,v 1.71 2002/09/27 20:24:42 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.78 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -71,17 +71,25 @@ unsigned bitchar_to_idx(char bit)
|
||||
* nexus.
|
||||
*/
|
||||
|
||||
static void set_to_lvariable(ivl_lval_t lval, unsigned idx, unsigned bit)
|
||||
static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
|
||||
unsigned bit, unsigned wid)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
|
||||
if (ivl_lval_mux(lval))
|
||||
fprintf(vvp_out, " %%set/x V_%s, %u, 0;\n",
|
||||
vvp_signal_label(sig), bit);
|
||||
else
|
||||
if (ivl_lval_mux(lval)) {
|
||||
assert(wid == 1);
|
||||
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), bit, ivl_signal_pins(sig)-1);
|
||||
} else if (wid == 1) {
|
||||
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit);
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit, wid);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void set_to_memory(ivl_memory_t mem, unsigned idx, unsigned bit)
|
||||
@@ -116,6 +124,19 @@ static void assign_to_lvariable(ivl_lval_t lval, unsigned idx,
|
||||
idx+part_off, delay, bit);
|
||||
}
|
||||
|
||||
static void assign_to_lvector(ivl_lval_t lval, unsigned idx,
|
||||
unsigned bit, unsigned delay, unsigned width)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n",
|
||||
vvp_signal_label(sig), part_off+idx, delay, bit);
|
||||
|
||||
}
|
||||
|
||||
static void assign_to_memory(ivl_memory_t mem, unsigned idx,
|
||||
unsigned bit, unsigned delay)
|
||||
{
|
||||
@@ -143,7 +164,7 @@ static void calculate_into_x1(ivl_expr_t expr)
|
||||
clr_vector(vec);
|
||||
}
|
||||
|
||||
static int show_stmt_assign(ivl_statement_t net)
|
||||
static int show_stmt_assign_vector(ivl_statement_t net)
|
||||
{
|
||||
ivl_lval_t lval;
|
||||
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||
@@ -170,6 +191,8 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
value and write it into index0. */
|
||||
if (ivl_lval_mux(lval)) {
|
||||
calculate_into_x0(ivl_lval_mux(lval));
|
||||
/* Generate code to skip around the set
|
||||
if the index has X values. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
@@ -177,6 +200,8 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
mem = ivl_lval_mem(lval);
|
||||
if (mem) {
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
/* Generate code to skip around the set
|
||||
if the index has X values. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
@@ -198,16 +223,26 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
|
||||
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
set_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]));
|
||||
idx = 0;
|
||||
while (idx < bit_limit) {
|
||||
unsigned cnt = 1;
|
||||
while (((idx + cnt) < bit_limit)
|
||||
&& (bits[cur_rbit] == bits[cur_rbit+cnt]))
|
||||
cnt += 1;
|
||||
|
||||
cur_rbit += 1;
|
||||
set_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
cnt);
|
||||
|
||||
cur_rbit += cnt;
|
||||
idx += cnt;
|
||||
}
|
||||
|
||||
for (idx = bit_limit
|
||||
; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
set_to_lvariable(lval, idx, 0);
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_set_flag) {
|
||||
@@ -249,23 +284,32 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if (mem) {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
set_to_memory(mem, idx, bidx);
|
||||
cur_rbit += 1;
|
||||
}
|
||||
|
||||
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
|
||||
set_to_memory(mem, idx, 0);
|
||||
|
||||
} else {
|
||||
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
if (mem)
|
||||
set_to_memory(mem, idx, bidx);
|
||||
else
|
||||
set_to_lvariable(lval, idx, bidx);
|
||||
set_to_lvariable(lval, 0, bidx, bit_limit);
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
cur_rbit += 1;
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
if (mem)
|
||||
set_to_memory(mem, idx, 0);
|
||||
else
|
||||
set_to_lvariable(lval, idx, 0);
|
||||
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
@@ -281,6 +325,56 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_assign_real(ivl_statement_t net)
|
||||
{
|
||||
int res;
|
||||
ivl_lval_t lval;
|
||||
ivl_variable_t var;
|
||||
|
||||
res = draw_eval_real(ivl_stmt_rval(net));
|
||||
clr_word(res);
|
||||
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
var = ivl_lval_var(lval);
|
||||
assert(var != 0);
|
||||
|
||||
fprintf(vvp_out, " %%set/wr W_%s, %d;\n",
|
||||
vvp_word_label(var), res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_assign(ivl_statement_t net)
|
||||
{
|
||||
ivl_lval_t lval;
|
||||
ivl_variable_t var;
|
||||
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
|
||||
if ( (var = ivl_lval_var(lval)) != 0 ) {
|
||||
switch (ivl_variable_type(var)) {
|
||||
case IVL_VT_VOID:
|
||||
assert(0);
|
||||
return 1;
|
||||
|
||||
case IVL_VT_VECTOR:
|
||||
/* Can't happen. */
|
||||
assert(0);
|
||||
return 1;
|
||||
|
||||
case IVL_VT_REAL:
|
||||
return show_stmt_assign_real(net);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
return show_stmt_assign_vector(net);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_assign_nb(ivl_statement_t net)
|
||||
{
|
||||
ivl_lval_t lval;
|
||||
@@ -345,6 +439,54 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
||||
; idx += 1) {
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
}
|
||||
|
||||
} else if ((del == 0) && (bit_limit > 2)) {
|
||||
|
||||
/* We have a vector, but no runtime
|
||||
calculated delays, to try to use vector
|
||||
assign instructions. */
|
||||
idx = 0;
|
||||
while (idx < bit_limit) {
|
||||
unsigned wid = 0;
|
||||
|
||||
do {
|
||||
wid += 1;
|
||||
if ((idx + wid) == bit_limit)
|
||||
break;
|
||||
|
||||
} while (bits[cur_rbit] == bits[cur_rbit+wid]);
|
||||
|
||||
switch (wid) {
|
||||
case 1:
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
break;
|
||||
case 2:
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
assign_to_lvariable(lval, idx+1,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
break;
|
||||
default:
|
||||
assign_to_lvector(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
idx += wid;
|
||||
cur_rbit += wid;
|
||||
}
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned wid = ivl_lval_pins(lval) - bit_limit;
|
||||
assign_to_lvector(lval, bit_limit,
|
||||
0, delay, wid);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if (del != 0)
|
||||
@@ -412,29 +554,39 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if ((bit_limit > 2) && (mem == 0) && (del == 0)) {
|
||||
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, bidx, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
delay, 0);
|
||||
assign_to_lvector(lval, 0, bidx, delay, bit_limit);
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
cur_rbit += 1;
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, bidx, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
delay, 0);
|
||||
|
||||
cur_rbit += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, 0, 1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, 0, delay, 0);
|
||||
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, 0, 1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, 0, delay, 0);
|
||||
|
||||
|
||||
if (skip_set_flag) {
|
||||
@@ -732,9 +884,25 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
|
||||
ivl_expr_t exp = ivl_stmt_delay_expr(net);
|
||||
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
||||
|
||||
{ struct vector_info del = draw_eval_expr(exp, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", del.base, del.wid);
|
||||
clr_vector(del);
|
||||
switch (ivl_expr_value(exp)) {
|
||||
|
||||
case IVL_VT_VECTOR: {
|
||||
struct vector_info del = draw_eval_expr(exp, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n",
|
||||
del.base, del.wid);
|
||||
clr_vector(del);
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_REAL: {
|
||||
int word = draw_eval_real(exp);
|
||||
fprintf(vvp_out, " %%cvt/ir 0, %d;\n", word);
|
||||
clr_word(word);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%delayx 0;\n");
|
||||
@@ -761,6 +929,7 @@ static int show_stmt_force(ivl_statement_t net)
|
||||
ivl_lval_t lval;
|
||||
ivl_signal_t lsig;
|
||||
unsigned idx;
|
||||
static unsigned force_functor_label = 0;
|
||||
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
@@ -770,16 +939,17 @@ static int show_stmt_force(ivl_statement_t net)
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
||||
force_functor_label += 1;
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
|
||||
fprintf(vvp_out, "f_%s.%u .force V_%s[%u], %s;\n",
|
||||
vvp_signal_label(lsig), idx,
|
||||
fprintf(vvp_out, "f_%u.%u .force V_%s[%u], %s;\n",
|
||||
force_functor_label, idx,
|
||||
vvp_signal_label(lsig), idx,
|
||||
draw_net_input(ivl_stmt_nexus(net, idx)));
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
|
||||
fprintf(vvp_out, " %%force f_%s.%u, 1;\n",
|
||||
vvp_signal_label(lsig), idx);
|
||||
fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
|
||||
force_functor_label, idx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1027,21 +1197,33 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Figure out how many expressions are going to be evaluated
|
||||
for this task call. I won't need to evaluate expressions
|
||||
for items that are VPI objects directly. */
|
||||
for (idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
ivl_expr_t expr = ivl_stmt_parm(net, idx);
|
||||
|
||||
switch (ivl_expr_type(expr)) {
|
||||
|
||||
/* These expression types can be handled directly,
|
||||
with VPI handles of their own. Therefore, skip
|
||||
them in the process of evaluating expressions. */
|
||||
case IVL_EX_NONE:
|
||||
case IVL_EX_NUMBER:
|
||||
case IVL_EX_STRING:
|
||||
case IVL_EX_SCOPE:
|
||||
case IVL_EX_SFUNC:
|
||||
case IVL_EX_VARIABLE:
|
||||
continue;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
/* If the signal node is narrower then the signal
|
||||
itself, then this is a part select so I'm going
|
||||
to need to evaluate the expression. */
|
||||
to need to evaluate the expression.
|
||||
|
||||
If I don't need to do any evaluating, then skip
|
||||
it as I'll be passing the handle to the signal
|
||||
itself. */
|
||||
if (ivl_expr_width(expr) !=
|
||||
ivl_signal_pins(ivl_expr_signal(expr))) {
|
||||
break;
|
||||
@@ -1049,17 +1231,32 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
if (!ivl_expr_oper1(expr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Everything else will need to be evaluated and
|
||||
passed as a constant to the vpi task. */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vec = (struct vector_info *)
|
||||
realloc(vec, (vecs+1)*sizeof(struct vector_info));
|
||||
vec[vecs] = draw_eval_expr(expr, 0);
|
||||
|
||||
switch (ivl_expr_value(expr)) {
|
||||
case IVL_VT_VECTOR:
|
||||
vec[vecs] = draw_eval_expr(expr, 0);
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
vec[vecs].base = draw_eval_real(expr);
|
||||
vec[vecs].wid = 0;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
vecs++;
|
||||
}
|
||||
|
||||
@@ -1096,6 +1293,12 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
continue;
|
||||
}
|
||||
|
||||
case IVL_EX_VARIABLE: {
|
||||
ivl_variable_t var = ivl_expr_variable(expr);
|
||||
fprintf(vvp_out, ", W_%s", vvp_word_label(var));
|
||||
continue;
|
||||
}
|
||||
|
||||
case IVL_EX_STRING:
|
||||
fprintf(vvp_out, ", \"%s\"",
|
||||
ivl_expr_string(expr));
|
||||
@@ -1110,9 +1313,11 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
if (strcmp("$time", ivl_expr_name(expr)) == 0)
|
||||
fprintf(vvp_out, ", $time");
|
||||
else if (strcmp("$stime", ivl_expr_name(expr)) == 0)
|
||||
fprintf(vvp_out, ", $time");
|
||||
fprintf(vvp_out, ", $stime");
|
||||
else if (strcmp("$realtime", ivl_expr_name(expr)) == 0)
|
||||
fprintf(vvp_out, ", $realtime");
|
||||
else
|
||||
fprintf(vvp_out, ", ?");
|
||||
fprintf(vvp_out, ", ?%s?", ivl_expr_name(expr));
|
||||
continue;
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
@@ -1127,16 +1332,31 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
break;
|
||||
}
|
||||
assert(veci < vecs);
|
||||
fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
|
||||
vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
|
||||
|
||||
switch (ivl_expr_value(expr)) {
|
||||
|
||||
case IVL_VT_VECTOR:
|
||||
fprintf(vvp_out, ", T<%u,%u,%s>", vec[veci].base,
|
||||
vec[veci].wid, ivl_expr_signed(expr)? "s" : "u");
|
||||
break;
|
||||
|
||||
case IVL_VT_REAL:
|
||||
fprintf(vvp_out, ", W<%u,r>", vec[veci].base);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
veci++;
|
||||
}
|
||||
|
||||
assert(veci == vecs);
|
||||
|
||||
if (vecs) {
|
||||
for (idx = 0; idx < vecs; idx++)
|
||||
clr_vector(vec[idx]);
|
||||
for (idx = 0; idx < vecs; idx++) {
|
||||
if (vec[idx].wid > 0)
|
||||
clr_vector(vec[idx]);
|
||||
}
|
||||
free(vec);
|
||||
}
|
||||
|
||||
@@ -1345,6 +1565,29 @@ int draw_func_definition(ivl_scope_t scope)
|
||||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.78 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.77 2003/01/26 21:16:00 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.76 2002/11/21 22:43:13 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.75 2002/11/17 18:31:09 steve
|
||||
* Generate unique labels for force functors.
|
||||
*
|
||||
* Revision 1.74 2002/11/08 05:00:31 steve
|
||||
* Use the vectorized %assign where appropriate.
|
||||
*
|
||||
* Revision 1.73 2002/11/07 05:19:55 steve
|
||||
* Use Vector %set to set constants in variables.
|
||||
*
|
||||
* Revision 1.72 2002/11/07 03:12:18 steve
|
||||
* Vectorize load from REG variables.
|
||||
*
|
||||
* Revision 1.71 2002/09/27 20:24:42 steve
|
||||
* Allow expression lookaside map to spam statements.
|
||||
*
|
||||
|
||||
+54
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_scope.c,v 1.80 2002/10/23 04:39:35 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.83 2003/01/26 21:16:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -139,6 +139,13 @@ const char* vvp_signal_label(ivl_signal_t sig)
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char* vvp_word_label(ivl_variable_t sig)
|
||||
{
|
||||
static char buf[32];
|
||||
sprintf(buf, "$%p", sig);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* This makes a string suitable for use as a label for memories.
|
||||
*/
|
||||
@@ -1367,10 +1374,21 @@ static void draw_lpm_ff(ivl_lpm_t net)
|
||||
static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx, width, selects;
|
||||
unsigned selwid;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
selects = ivl_lpm_selects(net);
|
||||
|
||||
/* The .shift device can only take as many select inputs as
|
||||
the width of the device.
|
||||
|
||||
XXXX I should make some sort of overflow gate for this? If
|
||||
any high bits are set, then the shift is certain to be
|
||||
*way* beyond the width of the left shifted value. XXXX */
|
||||
selwid = selects;
|
||||
if (selwid > width)
|
||||
selwid = width;
|
||||
|
||||
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
|
||||
fprintf(vvp_out, "L_%s .shift/r %u",
|
||||
vvp_mangle_id(ivl_lpm_name(net)), width);
|
||||
@@ -1383,11 +1401,15 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
draw_input_from_net(ivl_lpm_data(net, idx));
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < selects ; idx += 1) {
|
||||
for (idx = 0 ; idx < selwid ; idx += 1) {
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(ivl_lpm_select(net, idx));
|
||||
}
|
||||
|
||||
for (idx = selwid ; idx < width ; idx += 1) {
|
||||
fprintf(vvp_out, ", C<0>");
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
@@ -1532,12 +1554,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
vvp_mangle_id(ivl_scope_name(net)),
|
||||
type,
|
||||
vvp_mangle_name(ivl_scope_name(net)));
|
||||
|
||||
if (parent) {
|
||||
fprintf(vvp_out, ", S_%s;\n",
|
||||
vvp_mangle_id(ivl_scope_name(parent)));
|
||||
}
|
||||
else
|
||||
} else {
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " .timescale %d;\n", ivl_scope_time_units(net));
|
||||
|
||||
/* Scan the scope for logic devices. For each device, draw out
|
||||
a functor that connects pin 0 to the output, and the
|
||||
@@ -1549,6 +1575,16 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
}
|
||||
|
||||
|
||||
/* Scan the scope for word variables. */
|
||||
for (idx = 0 ; idx < ivl_scope_vars(net) ; idx += 1) {
|
||||
ivl_variable_t var = ivl_scope_var(net, idx);
|
||||
const char*type = "real";
|
||||
|
||||
fprintf(vvp_out, "W_%s .word %s, \"%s\";\n",
|
||||
vvp_word_label(var), type,
|
||||
ivl_variable_name(var));
|
||||
}
|
||||
|
||||
/* Scan the signals (reg and net) and draw the appropriate
|
||||
statements to make the signal function. */
|
||||
|
||||
@@ -1592,6 +1628,20 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.83 2003/01/26 21:16:00 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.82 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.81 2002/11/21 18:08:09 steve
|
||||
* Better handling of select width of shifters.
|
||||
*
|
||||
* Revision 1.80 2002/10/23 04:39:35 steve
|
||||
* draw lpm ff with aset_expr taken into account.
|
||||
*
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog
|
||||
Version: 0.6.20021027
|
||||
Version: 0.7
|
||||
Release: 0
|
||||
Copyright: GPL
|
||||
Group: Applications/Engineering
|
||||
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20021027.tar.gz
|
||||
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-0.7.tar.gz
|
||||
URL: http://www.icarus.com/eda/verilog/index.html
|
||||
Packager: Stephen Williams <[email protected]>
|
||||
|
||||
@@ -20,7 +20,7 @@ engineering formats, including simulation. It strives to be true
|
||||
to the IEEE-1364 standard.
|
||||
|
||||
%prep
|
||||
%setup -n verilog-20021027
|
||||
%setup -n verilog-0.7
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
|
||||
+11
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verireal.cc,v 1.8 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: verireal.cc,v 1.9 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,6 +25,7 @@
|
||||
# include "verireal.h"
|
||||
# include <ctype.h>
|
||||
# include <iostream>
|
||||
# include <math.h>
|
||||
# include <assert.h>
|
||||
|
||||
verireal::verireal()
|
||||
@@ -123,6 +124,11 @@ long verireal::as_long(int shift) const
|
||||
return val;
|
||||
}
|
||||
|
||||
double verireal::as_double() const
|
||||
{
|
||||
return mant_ * pow(10.0, exp10_) * (sign_? -1 : 1);
|
||||
}
|
||||
|
||||
verireal operator* (const verireal&l, const verireal&r)
|
||||
{
|
||||
verireal res;
|
||||
@@ -140,6 +146,10 @@ ostream& operator<< (ostream&out, const verireal&v)
|
||||
|
||||
/*
|
||||
* $Log: verireal.cc,v $
|
||||
* Revision 1.9 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.8 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+6
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: verireal.h,v 1.6 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: verireal.h,v 1.7 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
@@ -53,6 +53,7 @@ class verireal {
|
||||
is 25. */
|
||||
long as_long(int shift =0) const;
|
||||
|
||||
double as_double() const;
|
||||
|
||||
private:
|
||||
bool sign_;
|
||||
@@ -65,6 +66,10 @@ extern verireal operator* (const verireal&, const verireal&);
|
||||
|
||||
/*
|
||||
* $Log: verireal.h,v $
|
||||
* Revision 1.7 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+134
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: veriuser.h,v 1.17 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: veriuser.h,v 1.18 2002/12/19 21:37:04 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -56,6 +56,47 @@
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
#ifndef PLI_TYPES
|
||||
#define PLI_TYPES
|
||||
typedef signed int PLI_INT32;
|
||||
typedef unsigned int PLI_UINT32;
|
||||
typedef signed short PLI_INT16;
|
||||
typedef unsigned short PLI_UINT12;
|
||||
typedef signed char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* defines for tf_message
|
||||
*/
|
||||
#define ERR_MESSAGE 1
|
||||
#define ERR_WARNING 2
|
||||
#define ERR_ERROR 3
|
||||
#define ERR_INTERNAL 4
|
||||
#define ERR_SYSTEM 5
|
||||
|
||||
/*
|
||||
* These are some defines for backwards compatibility. They should not
|
||||
* be used in new code.
|
||||
*/
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
# define FALSE 0
|
||||
#endif
|
||||
#ifndef __cplusplus
|
||||
# ifndef true
|
||||
# define true 1
|
||||
# endif
|
||||
# ifndef false
|
||||
# define false 0
|
||||
# endif
|
||||
# ifndef bool
|
||||
# define bool int
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* structure for veriusertfs array
|
||||
*/
|
||||
@@ -74,6 +115,20 @@ typedef struct t_tfcell
|
||||
char reserved[20]; /* reserved */
|
||||
} s_tfcell, *p_tfcell;
|
||||
|
||||
/*
|
||||
* Normal PLI1.0 modules export a veriusertfs array that contains all
|
||||
* the function definitions for use by the simulator. The user code is
|
||||
* expected to supply that array.
|
||||
*
|
||||
* However, Icarus Verilog doesn't normally look for the veriusertfs
|
||||
* array, it instead looks for the vlog_startup_routines array, as
|
||||
* declared in vpi_user.h. So the veriuser library includes the
|
||||
* veriusertfs_register function that can be used to do the PLI 1.0
|
||||
* setup. Create a vlog_startup_routines table like this if you are
|
||||
* just interested in making your PLI1 functions work:
|
||||
*
|
||||
* void (*vlog_startup_routines[])() = { &veriusertfs_register };
|
||||
*/
|
||||
extern s_tfcell veriusertfs[];
|
||||
extern void veriusertfs_register();
|
||||
|
||||
@@ -88,6 +143,64 @@ extern void veriusertfs_register();
|
||||
#define reason_finish 9
|
||||
#define reason_endofcompile 16
|
||||
|
||||
/* These are values returned by tf_typep */
|
||||
#define tf_nullparam 0
|
||||
#define TF_NULLPARAM tf_nullparam
|
||||
#define tf_string 1
|
||||
#define TF_STRING tf_string
|
||||
#define tf_readonly 10
|
||||
#define TF_READONLY tf_readonly
|
||||
#define tf_readwrite 11
|
||||
#define TF_READWRITE tf_readwrite
|
||||
#define tf_rwbitselect 12
|
||||
#define TF_RWBITSELECT tf_rwbitselect
|
||||
#define tf_rwpartselect 13
|
||||
#define TF_RWPARTSELECT tf_rwpartselect
|
||||
#define tf_rwmemselect 14
|
||||
#define TF_RWMEMSELECT tf_rwmemselect
|
||||
#define tf_readonlyreal 15
|
||||
#define TF_READONLYREAL tf_readonlyreal
|
||||
#define tf_readwritereal 16
|
||||
#define TF_READWRITEREAD tf_readwritereal
|
||||
|
||||
typedef struct t_tfnodeinfo {
|
||||
PLI_INT16 node_type;
|
||||
PLI_INT16 padding;
|
||||
union {
|
||||
struct t_vecval *vecval_p;
|
||||
struct t_strengthval *strengthval_p;
|
||||
PLI_BYTE8 *memoryval_p;
|
||||
double *read_value_p;
|
||||
} node_value;
|
||||
char* node_symbol;
|
||||
PLI_INT32 node_ngroups;
|
||||
PLI_INT32 node_vec_size;
|
||||
PLI_INT32 node_sign;
|
||||
PLI_INT32 node_ms_index;
|
||||
PLI_INT32 node_ls_index;
|
||||
PLI_INT32 node_mem_size;
|
||||
PLI_INT32 node_lhs_element;
|
||||
PLI_INT32 node_rhs_element;
|
||||
PLI_INT32*node_handle;
|
||||
} s_tfnodeinfo, *p_tfnodeinfo;
|
||||
|
||||
/* values used in the node_type of the tfnodeinfo structure. */
|
||||
#define tf_null_node 100
|
||||
#define TF_NULL_NODE tf_null_node
|
||||
#define tf_reg_node 101
|
||||
#define TF_REG_NODE tf_reg_node
|
||||
#define tf_integer_node 102
|
||||
#define TF_INTEGER_NODE tf_integer_node
|
||||
#define tf_time_node 103
|
||||
#define TF_TIME_NODE tf_time_node
|
||||
#define tf_netvector_node 104
|
||||
#define TF_NETVECTOR_NODE tf_netvector_node
|
||||
#define tf_netscalar_node 105
|
||||
#define TF_NETSCALAR_NODE tf_netscalar_node
|
||||
#define tf_memory_node 106
|
||||
#define TF_MEMORY_NODE tf_memory_node
|
||||
#define tf_real_node 107
|
||||
#define TF_REAL_NODE tf_real_node
|
||||
|
||||
/* Extern functions from the library. */
|
||||
extern void io_printf (const char *, ...)
|
||||
@@ -114,6 +227,12 @@ extern int tf_getlongtime(int*high_bits);
|
||||
|
||||
extern int tf_getp(int pnum);
|
||||
|
||||
extern PLI_BYTE8* tf_getworkarea(void);
|
||||
|
||||
extern PLI_INT32 tf_message(PLI_INT32 level, char*facility,
|
||||
char*messno, char*fmt, ...)
|
||||
__attribute__((format (printf,4,5)));
|
||||
|
||||
extern int tf_nump(void);
|
||||
|
||||
/* IEEE1364 NOTE: tf_putlongp is listed as returning in in the header
|
||||
@@ -123,6 +242,15 @@ extern void tf_putlongp(int pnum, int lowvalue, int highvalue);
|
||||
|
||||
extern void tf_putp(int pnum, int value);
|
||||
|
||||
/* IEEE1364 NOTE: tf_setworkarea is listed as taking a PLI_BYTE8*, but
|
||||
that is silly, it really takes any kind of pointer. Taking void* is
|
||||
compatible with those who pass a PLI_BYTE8*. */
|
||||
extern PLI_INT32 tf_setworkarea(void*workarea);
|
||||
|
||||
extern char* tf_spname(void);
|
||||
|
||||
extern PLI_INT32 tf_typep(PLI_INT32 narg);
|
||||
|
||||
extern void tf_warning(const char*, ...)
|
||||
__attribute__((format (printf,1,2)));
|
||||
|
||||
@@ -130,6 +258,11 @@ EXTERN_C_END
|
||||
|
||||
/*
|
||||
* $Log: veriuser.h,v $
|
||||
* Revision 1.18 2002/12/19 21:37:04 steve
|
||||
* Add tf_message, tf_get/setworkarea, and
|
||||
* ty_typep functions, along with defines
|
||||
* related to these functions.
|
||||
*
|
||||
* Revision 1.17 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.31 2002/04/07 04:37:53 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.32 2003/01/10 03:06:32 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -60,12 +60,12 @@ sys_random.o sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \
|
||||
sys_lxt.o lxt_write.o \
|
||||
mt19937int.o
|
||||
|
||||
SYSTEM_VPI_LDFLAGS = -L.. -lvpi
|
||||
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
|
||||
ifeq (@WIN32@,yes)
|
||||
SYSTEM_VPI_LDFLAGS += -liberty
|
||||
endif
|
||||
|
||||
system.vpi: $O ../libvpi.a
|
||||
system.vpi: $O ../vvp/libvpi.a
|
||||
$(CC) @shared@ -o $@ $O $(SYSTEM_VPI_LDFLAGS)
|
||||
|
||||
sys_readmem_lex.c: sys_readmem_lex.lex
|
||||
|
||||
+208
-83
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_display.c,v 1.45 2002/09/06 04:56:28 steve Exp $"
|
||||
#ident "$Id: sys_display.c,v 1.49 2003/01/26 18:18:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -113,96 +113,158 @@ static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||
}
|
||||
}
|
||||
|
||||
static void format_time(unsigned mcd, int fsize, const char*value)
|
||||
/*
|
||||
* This function writes the time value into the mcd target with the
|
||||
* proper format. The mcd is the destination file.
|
||||
*
|
||||
* The fsize is the width of the field to use. Normally, this is -1 to
|
||||
* reflect the format string "%t". It may also be 0 for the format
|
||||
* string "%0t". This formatter also allows for the nonstandard use of
|
||||
* positive values to enforce a with to override the width given in
|
||||
* the $timeformat system task.
|
||||
*
|
||||
* The value argument is the time value as a decimal string. There are
|
||||
* no leading zeros in this string, and the units of the value are
|
||||
* given in the units argument.
|
||||
*/
|
||||
static void format_time(unsigned mcd, int fsize,
|
||||
const char*value, int time_units)
|
||||
{
|
||||
char buf[256];
|
||||
const char*cp;
|
||||
char*bp;
|
||||
unsigned len;
|
||||
char*bp, *start_address;
|
||||
|
||||
int idx, idx_point, idx_start, idx_value;
|
||||
int idx;
|
||||
int fraction_chars, fraction_pad, value_chop, whole_fill;
|
||||
|
||||
/* This is the time precision for the simulation. */
|
||||
int prec = vpi_get(vpiTimePrecision, 0);
|
||||
/* This is the format precision expressed as the power of 10
|
||||
of the desired precision. The following code uses this
|
||||
format to be consistent with the units specifications. */
|
||||
int format_precision = timeformat_info.units - timeformat_info.prec;
|
||||
|
||||
/* If the fsize is <0, then use the value from the
|
||||
$timeformat. If the fsize is >=0, then it overrides the
|
||||
$timeformat value. */
|
||||
if (fsize < 0)
|
||||
fsize = timeformat_info.width;
|
||||
|
||||
/* bp starts at the end of the buffer, and works forward as we
|
||||
build up the output value. */
|
||||
bp = buf + sizeof buf;
|
||||
assert(fsize < (sizeof buf - 1));
|
||||
|
||||
/* cp points to digits of the value, starting with the least
|
||||
significant. If the value is only '0', then short circuit
|
||||
the value by setting cp = value. */
|
||||
if (value[0] != '0')
|
||||
cp = value + strlen(value);
|
||||
|
||||
/* This is the number of characters to the right of the
|
||||
decimal point. This is defined completely by the
|
||||
timeformat. It is legal for the precision to be larger then
|
||||
the units, and in this case there will be no fraction_chars
|
||||
at all. */
|
||||
fraction_chars = timeformat_info.units - format_precision;
|
||||
if (fraction_chars < 0)
|
||||
fraction_chars = 0;
|
||||
|
||||
/* This is the number of zeros I must add to the value to get
|
||||
the desired precision within the fraction. If this value is
|
||||
greater then 0, the value does not have enough characters,
|
||||
so I will be adding zeros. */
|
||||
|
||||
fraction_pad = time_units - format_precision;
|
||||
if (fraction_pad < 0)
|
||||
fraction_pad = 0;
|
||||
if (fraction_pad > fraction_chars)
|
||||
fraction_pad = fraction_chars;
|
||||
|
||||
|
||||
/* This is the number of characters of excess precision in the
|
||||
supplied value. This many characters are chopped from the
|
||||
least significant end. */
|
||||
value_chop = format_precision - time_units;
|
||||
if (value_chop < 0)
|
||||
value_chop = 0;
|
||||
|
||||
/* This is the number of zeros that I must add to the integer
|
||||
part of the output string to pad the value out to the
|
||||
desired units. This will only have a non-zero value if the
|
||||
units of the value is greater then the desired units.
|
||||
|
||||
Detect the special case where the value is 0. In this case,
|
||||
do not do any integer filling ever. The output should be
|
||||
padded with blanks in that case. */
|
||||
whole_fill = time_units - timeformat_info.units;
|
||||
if (whole_fill < 0)
|
||||
whole_fill = 0;
|
||||
if (strcmp(value,"0") == 0)
|
||||
whole_fill = 0;
|
||||
|
||||
/* This is the expected start address of the output. It
|
||||
accounts for the fsize value that is chosen. The output
|
||||
will be filled out to complete the buffer. */
|
||||
if (fsize == 0)
|
||||
start_address = buf;
|
||||
else
|
||||
start_address = buf + sizeof buf - fsize - 1;
|
||||
|
||||
/* Now start the character pointers, ready to start copying
|
||||
the value into the format. */
|
||||
cp = value + strlen(value);
|
||||
if (value_chop > (cp - value))
|
||||
cp = value;
|
||||
else
|
||||
cp -= value_chop;
|
||||
|
||||
|
||||
/* Draw the suffix into the buffer. */
|
||||
bp = buf + sizeof buf;
|
||||
*--bp = 0;
|
||||
|
||||
|
||||
/* Write the suffix. */
|
||||
bp -= strlen(timeformat_info.suff);
|
||||
strcpy(bp, timeformat_info.suff);
|
||||
|
||||
/* This is the precision index where the decimal point goes. */
|
||||
idx_point = timeformat_info.units;
|
||||
|
||||
/* This is the precision index where we start drawing digits. */
|
||||
idx_start = idx_point - (int)timeformat_info.prec;
|
||||
|
||||
/* This is the precision index where the integer time value
|
||||
digits start. */
|
||||
idx_value = prec;
|
||||
|
||||
idx = idx_start;
|
||||
if (idx > idx_value)
|
||||
idx = idx_value;
|
||||
|
||||
/* If we want no precision, then set idx_point to a high value
|
||||
so that the '.' is never printed. */
|
||||
if (timeformat_info.prec == 0)
|
||||
idx_point = idx - 1;
|
||||
|
||||
/* Now build up the time string, from the least significant
|
||||
digit up to the last. */
|
||||
while ((cp > value) || (idx <= idx_point)) {
|
||||
|
||||
if (idx == idx_point) {
|
||||
*--bp = '.';
|
||||
}
|
||||
|
||||
if (idx >= idx_start) {
|
||||
|
||||
if (idx < idx_value) {
|
||||
*--bp = '0';
|
||||
} else if (cp > value) {
|
||||
*--bp = cp[-1];
|
||||
} else {
|
||||
*--bp = '0';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((idx >= idx_value) && (cp > value))
|
||||
cp -= 1;
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
/* Patch up cases that need a leading 0. */
|
||||
if ((*bp == '.') || (idx == idx_start))
|
||||
/* Write the padding needed to fill out the fraction. */
|
||||
for (idx = 0 ; idx < fraction_pad ; idx += 1)
|
||||
*--bp = '0';
|
||||
|
||||
/* Pad the string on the left to the requested minimum
|
||||
width. Pad with spaces. */
|
||||
len = strlen(bp);
|
||||
while (len < fsize) {
|
||||
*--bp = ' ';
|
||||
len += 1;
|
||||
/* Subtract the pad from the needed chars. */
|
||||
assert(fraction_pad <= fraction_chars);
|
||||
fraction_chars -= fraction_pad;
|
||||
fraction_pad = 0;
|
||||
|
||||
/* Write the fraction chars. */
|
||||
for (idx = 0 ; idx < fraction_chars ; idx += 1) {
|
||||
if (cp > value)
|
||||
*--bp = *--cp;
|
||||
else
|
||||
*--bp = '0';
|
||||
|
||||
assert(cp >= value);
|
||||
}
|
||||
|
||||
/* Write the decimal point, if needed. */
|
||||
if (timeformat_info.prec > 0)
|
||||
*--bp = '.';
|
||||
|
||||
/* Fill the gap between the value and the decimal point. */
|
||||
for (idx = 0 ; idx < whole_fill ; idx += 1)
|
||||
*--bp = '0';
|
||||
|
||||
/* Write the integer part of the value. */
|
||||
while (cp > value) {
|
||||
*--bp = *--cp;
|
||||
}
|
||||
|
||||
/* Fill the leading characters to make up the desired
|
||||
width. This may require a '0' if the last character
|
||||
written was the decimal point. */
|
||||
if (fsize > 0) {
|
||||
while (bp > start_address) {
|
||||
if (*bp == '.')
|
||||
*--bp = '0';
|
||||
else
|
||||
*--bp = ' ';
|
||||
}
|
||||
} else {
|
||||
if (*bp == '.')
|
||||
*--bp = '0';
|
||||
}
|
||||
|
||||
|
||||
vpi_mcd_printf(mcd, "%s", bp);
|
||||
}
|
||||
|
||||
@@ -305,6 +367,8 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||
char*cp = fmt;
|
||||
char format_char = ' ';
|
||||
int idx;
|
||||
/* Time units of the current scope. */
|
||||
int time_units = vpi_get(vpiTimeUnit, scope);
|
||||
|
||||
assert(fmt);
|
||||
|
||||
@@ -361,6 +425,14 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||
cp += 1;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
format_char = 'f';
|
||||
do_arg = 1;
|
||||
value.format = vpiRealVal;
|
||||
cp += 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
case 'H':
|
||||
case 'x':
|
||||
@@ -458,7 +530,6 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
// new Verilog 2001 format specifiers...
|
||||
case 'l':
|
||||
@@ -495,11 +566,17 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||
|
||||
switch(format_char){
|
||||
case 'c':
|
||||
vpi_mcd_printf(mcd, "%c", value.value.str[strlen(value.value.str)-1]);
|
||||
break;
|
||||
vpi_mcd_printf(mcd, "%c", value.value.str[strlen(value.value.str)-1]);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
vpi_mcd_printf(mcd, "%f",
|
||||
value.value.real);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
format_time(mcd, fsize, value.value.str);
|
||||
format_time(mcd, fsize,
|
||||
value.value.str, time_units);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
@@ -609,6 +686,29 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||
cp += 1;
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
if (isdigit(cp[0])
|
||||
&& isdigit(cp[1])
|
||||
&& isdigit(cp[2])) {
|
||||
/* handle octal escapes (e.g. "\015" is CR)*/
|
||||
vpi_mcd_printf(mcd, "%c",
|
||||
(cp[2] - '0') +
|
||||
8 * ((cp[1] - '0') +
|
||||
8 * (cp[0] - '0')));
|
||||
cp += 3;
|
||||
} else {
|
||||
vpi_mcd_printf(mcd, "%c", *cp);
|
||||
cp += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_mcd_printf(mcd, "%c", *cp);
|
||||
cp += 1;
|
||||
@@ -674,6 +774,12 @@ static void do_display(unsigned int mcd, struct strobe_cb_info*info)
|
||||
vpi_mcd_printf(mcd, "%20u", value.value.time->low);
|
||||
break;
|
||||
|
||||
case vpiRealVar:
|
||||
value.format = vpiRealVal;
|
||||
vpi_get_value(item, &value);
|
||||
vpi_mcd_printf(mcd, "%f", value.value.real);
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_mcd_printf(mcd, "?");
|
||||
break;
|
||||
@@ -702,19 +808,24 @@ static int get_default_format(char *name)
|
||||
|
||||
static int sys_display_calltf(char *name)
|
||||
{
|
||||
struct strobe_cb_info info;
|
||||
struct strobe_cb_info*info;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle scope = vpi_handle(vpiScope, sys);
|
||||
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
info = vpi_get_userdata(sys);
|
||||
if (info == 0) {
|
||||
vpiHandle scope = vpi_handle(vpiScope, sys);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
|
||||
assert(scope);
|
||||
info.default_format = get_default_format(name);
|
||||
info.scope = scope;
|
||||
array_from_iterator(&info, argv);
|
||||
assert(scope);
|
||||
info = malloc(sizeof (struct strobe_cb_info));
|
||||
info->default_format = get_default_format(name);
|
||||
info->scope = scope;
|
||||
array_from_iterator(info, argv);
|
||||
|
||||
do_display(5, &info);
|
||||
free(info.items);
|
||||
vpi_put_userdata(sys, info);
|
||||
}
|
||||
|
||||
do_display(5, info);
|
||||
|
||||
if (strncmp(name,"$display",8) == 0)
|
||||
vpi_mcd_printf(5, "\n");
|
||||
@@ -1206,6 +1317,8 @@ static int sys_timeformat_calltf(char *xx)
|
||||
|
||||
static int sys_end_of_compile(p_cb_data cb_data)
|
||||
{
|
||||
/* The default timeformat prints times in unit of simulation
|
||||
precision. */
|
||||
timeformat_info.suff = strdup("");
|
||||
timeformat_info.units = vpi_get(vpiTimePrecision, 0);
|
||||
timeformat_info.prec = 0;
|
||||
@@ -1461,6 +1574,18 @@ void sys_display_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_display.c,v $
|
||||
* Revision 1.49 2003/01/26 18:18:36 steve
|
||||
* Support display of real values and constants.
|
||||
*
|
||||
* Revision 1.48 2003/01/09 04:10:58 steve
|
||||
* use userdata to save $display argument handles.
|
||||
*
|
||||
* Revision 1.47 2002/12/21 19:41:49 steve
|
||||
* Rewrite time formatting to account for local scope.
|
||||
*
|
||||
* Revision 1.46 2002/11/09 06:01:11 steve
|
||||
* display octal escapes properly.
|
||||
*
|
||||
* Revision 1.45 2002/09/06 04:56:28 steve
|
||||
* Add support for %v is the display system task.
|
||||
* Change the encoding of H and L outputs from
|
||||
|
||||
+17
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_lxt.c,v 1.11 2002/08/15 02:12:20 steve Exp $"
|
||||
#ident "$Id: sys_lxt.c,v 1.13 2002/12/21 00:55:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -343,6 +343,7 @@ static int sys_dumpoff_calltf(char*name)
|
||||
if (dump_header_pending())
|
||||
return 0;
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
if (now.low > vcd_cur_time)
|
||||
lt_set_time(dump_file, now.low);
|
||||
@@ -368,6 +369,7 @@ static int sys_dumpon_calltf(char*name)
|
||||
if (dump_header_pending())
|
||||
return 0;
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
if (now.low > vcd_cur_time)
|
||||
lt_set_time(dump_file, now.low);
|
||||
@@ -388,6 +390,7 @@ static int sys_dumpall_calltf(char*name)
|
||||
if (dump_header_pending())
|
||||
return 0;
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
if (now.low > vcd_cur_time)
|
||||
lt_set_time(dump_file, now.low);
|
||||
@@ -460,6 +463,9 @@ static int sys_dumpfile_calltf(char*name)
|
||||
path = strdup("dumpfile.lxt");
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
close_dumpfile();
|
||||
|
||||
assert(dump_file == 0);
|
||||
open_dumpfile(path);
|
||||
|
||||
@@ -814,6 +820,16 @@ void sys_lxt_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_lxt.c,v $
|
||||
* Revision 1.13 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.12 2002/11/17 22:28:42 steve
|
||||
* Close old file if $dumpfile is called again.
|
||||
*
|
||||
* Revision 1.11 2002/08/15 02:12:20 steve
|
||||
* add dumpvars_compiletf to check first argument.
|
||||
*
|
||||
|
||||
+107
-1
@@ -17,14 +17,25 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_time.c,v 1.4 2002/08/12 01:35:05 steve Exp $"
|
||||
#ident "$Id: sys_time.c,v 1.6 2003/01/27 00:14:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static vpiHandle module_of_function(vpiHandle obj)
|
||||
{
|
||||
while (vpi_get(vpiType, obj) != vpiModule) {
|
||||
obj = vpi_handle(vpiScope, obj);
|
||||
assert(obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static int sys_time_sizetf(char*x)
|
||||
{
|
||||
return 64;
|
||||
@@ -40,16 +51,82 @@ static int sys_time_calltf(char*name)
|
||||
s_vpi_value val;
|
||||
s_vpi_time now;
|
||||
vpiHandle call_handle;
|
||||
vpiHandle mod;
|
||||
int units, prec;
|
||||
long scale;
|
||||
|
||||
call_handle = vpi_handle(vpiSysTfCall, 0);
|
||||
assert(call_handle);
|
||||
|
||||
mod = module_of_function(call_handle);
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
|
||||
/* All the variants but $simtime return the time in units of
|
||||
the local scope. The $simtime function returns the
|
||||
simulation time. */
|
||||
if (strcmp(name, "$simtime") == 0)
|
||||
units = vpi_get(vpiTimePrecision, 0);
|
||||
else
|
||||
units = vpi_get(vpiTimeUnit, mod);
|
||||
|
||||
prec = vpi_get(vpiTimePrecision, 0);
|
||||
scale = 1;
|
||||
while (units > prec) {
|
||||
scale *= 10;
|
||||
units -= 1;
|
||||
}
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = now.low;
|
||||
assert(now.high == 0);
|
||||
|
||||
val.value.integer /= scale;
|
||||
|
||||
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_realtime_calltf(char*name)
|
||||
{
|
||||
s_vpi_value val;
|
||||
s_vpi_time now;
|
||||
vpiHandle call_handle;
|
||||
vpiHandle mod;
|
||||
int units, prec;
|
||||
double scale;
|
||||
|
||||
call_handle = vpi_handle(vpiSysTfCall, 0);
|
||||
assert(call_handle);
|
||||
|
||||
mod = module_of_function(call_handle);
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
|
||||
/* All the variants but $simtime return the time in units of
|
||||
the local scope. The $simtime function returns the
|
||||
simulation time. */
|
||||
if (strcmp(name, "$simtime") == 0)
|
||||
units = vpi_get(vpiTimePrecision, 0);
|
||||
else
|
||||
units = vpi_get(vpiTimeUnit, mod);
|
||||
|
||||
prec = vpi_get(vpiTimePrecision, 0);
|
||||
scale = 1;
|
||||
while (units > prec) {
|
||||
scale *= 10;
|
||||
units -= 1;
|
||||
}
|
||||
|
||||
val.format = vpiRealVal;
|
||||
val.value.real = now.low;
|
||||
assert(now.high == 0);
|
||||
|
||||
val.value.real /= scale;
|
||||
|
||||
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
@@ -64,6 +141,15 @@ void sys_time_register()
|
||||
tf_data.calltf = sys_time_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = sys_time_sizetf;
|
||||
tf_data.user_data = "$time";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$realtime";
|
||||
tf_data.calltf = sys_realtime_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$realtime";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
@@ -71,11 +157,31 @@ void sys_time_register()
|
||||
tf_data.calltf = sys_time_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = sys_stime_sizetf;
|
||||
tf_data.user_data = "$stime";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$simtime";
|
||||
tf_data.calltf = sys_time_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = sys_time_sizetf;
|
||||
tf_data.user_data = "$simtime";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_time.c,v $
|
||||
* Revision 1.6 2003/01/27 00:14:37 steve
|
||||
* Support in various contexts the $realtime
|
||||
* system task.
|
||||
*
|
||||
* Revision 1.5 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:35:05 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+23
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_vcd.c,v 1.37 2002/08/15 02:12:20 steve Exp $"
|
||||
#ident "$Id: sys_vcd.c,v 1.40 2002/12/21 00:55:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -146,7 +146,7 @@ inline static void vcd_names_add(const char *name)
|
||||
struct vcd_names_s *nl = (struct vcd_names_s *)
|
||||
malloc(sizeof(struct vcd_names_s));
|
||||
assert(nl);
|
||||
nl->name = name;
|
||||
nl->name = strdup(name);
|
||||
nl->next = vcd_names_list;
|
||||
vcd_names_list = nl;
|
||||
listed_names ++;
|
||||
@@ -315,6 +315,7 @@ static int sys_dumpoff_calltf(char*name)
|
||||
if (dump_header_pending())
|
||||
return 0;
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
if (now.low > vcd_cur_time)
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
@@ -342,6 +343,7 @@ static int sys_dumpon_calltf(char*name)
|
||||
if (dump_header_pending())
|
||||
return 0;
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
if (now.low > vcd_cur_time)
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
@@ -364,6 +366,7 @@ static int sys_dumpall_calltf(char*name)
|
||||
if (dump_header_pending())
|
||||
return 0;
|
||||
|
||||
now.type = vpiSimTime;
|
||||
vpi_get_time(0, &now);
|
||||
if (now.low > vcd_cur_time)
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
@@ -449,6 +452,11 @@ static int sys_dumpfile_calltf(char*name)
|
||||
path = strdup("dumpfile.vcd");
|
||||
}
|
||||
|
||||
if (dump_file) {
|
||||
fclose(dump_file);
|
||||
dump_file = 0;
|
||||
}
|
||||
|
||||
assert(dump_file == 0);
|
||||
open_dumpfile(path);
|
||||
|
||||
@@ -844,6 +852,19 @@ void sys_vcd_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_vcd.c,v $
|
||||
* Revision 1.40 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*
|
||||
* Revision 1.39 2002/11/17 22:28:42 steve
|
||||
* Close old file if $dumpfile is called again.
|
||||
*
|
||||
* Revision 1.38 2002/11/14 22:43:58 steve
|
||||
* Save vpiFullName results.
|
||||
*
|
||||
* Revision 1.37 2002/08/15 02:12:20 steve
|
||||
* add dumpvars_compiletf to check first argument.
|
||||
*
|
||||
|
||||
+16
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_user.h,v 1.15 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: vpi_user.h,v 1.17 2003/01/26 21:15:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ typedef struct t_vpi_value {
|
||||
#define vpiNamedEvent 34
|
||||
#define vpiNamedFork 35
|
||||
#define vpiNet 36
|
||||
#define vpiRealVar 47
|
||||
#define vpiReg 48
|
||||
#define vpiSysFuncCall 56
|
||||
#define vpiSysTaskCall 57
|
||||
@@ -323,6 +324,13 @@ extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
|
||||
extern int vpi_free_object(vpiHandle ref);
|
||||
extern int vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p);
|
||||
|
||||
/*
|
||||
* These functions support attaching user data to an instance of a
|
||||
* system task or function. These functions only apply to
|
||||
* vpiSysTaskCall or vpiSysFuncCall handles.
|
||||
*/
|
||||
extern int vpi_put_userdata(vpiHandle obj, void*data);
|
||||
extern void*vpi_get_userdata(vpiHandle obj);
|
||||
|
||||
/*
|
||||
* Support for handling errors.
|
||||
@@ -359,6 +367,13 @@ EXTERN_C_END
|
||||
|
||||
/*
|
||||
* $Log: vpi_user.h,v $
|
||||
* Revision 1.17 2003/01/26 21:15:59 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.16 2003/01/09 04:10:17 steve
|
||||
* Add vpi_put_userdata
|
||||
*
|
||||
* Revision 1.15 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
-241
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpithunk.c,v 1.6 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "vpi_user.h"
|
||||
#include "vpithunk.h"
|
||||
|
||||
/*
|
||||
* This code is linked into the VPI module, not the simulator. The
|
||||
* module uses the symbols defined in here to call implementations
|
||||
* supplied by the simulator, which loaded this module with dlopen or
|
||||
* the equivilent.
|
||||
*
|
||||
* The vpi_thunk_p pointer points to a table of function pointers that
|
||||
* point to all the functions that a simulator is expected to provide.
|
||||
* The vlog_register_sim is a function that the simulator is expected
|
||||
* to call with a value for the vpi_thunk_p pointer. This is how the
|
||||
* run time linkage to all the functions in the make program are made.
|
||||
*
|
||||
* In Icarus Verilog, the VPI module is also supposed to export a
|
||||
* vlog_startup_routines table. This is something that the programmer
|
||||
* does, so the libvpi library, and the vlog_register_sim function,
|
||||
* are invisible to the user.
|
||||
*
|
||||
* The simulator is careful to call the vpi_register_sim function from
|
||||
* a loaded module before executing the startup routines.
|
||||
*/
|
||||
static p_vpi_thunk vpi_thunk_p = 0;
|
||||
|
||||
#define VPITV_CALL(fn,args) { \
|
||||
if (vpi_thunk_p == 0) { \
|
||||
no_sim(#fn); return; \
|
||||
} \
|
||||
if (vpi_thunk_p->fn == 0) { \
|
||||
no_func(#fn); return; \
|
||||
} \
|
||||
vpi_thunk_p->fn args; \
|
||||
}
|
||||
|
||||
#define VPIT_CALL(fn,def,args) { \
|
||||
if (vpi_thunk_p == 0) { \
|
||||
no_sim(#fn); return def; \
|
||||
} \
|
||||
if (vpi_thunk_p->fn == 0) { \
|
||||
no_func(#fn); return def; \
|
||||
} \
|
||||
return vpi_thunk_p->fn args; \
|
||||
}
|
||||
|
||||
static void no_sim(const char *fn)
|
||||
{
|
||||
fprintf(stderr, "No Simulator registered, cannot handle vpi "
|
||||
"call to %s\n", fn);
|
||||
}
|
||||
|
||||
static void no_func(const char *fn)
|
||||
{
|
||||
fprintf(stderr, "Simulator doesn't have a %s function\n",fn);
|
||||
}
|
||||
|
||||
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp)
|
||||
{
|
||||
vpi_thunk_p = 0;
|
||||
if (tp->magic != VPI_THUNK_MAGIC) {
|
||||
fprintf(stderr, "Thunk Magic Number mismatch. Got %08X, expected %08x\n",
|
||||
tp->magic, VPI_THUNK_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
vpi_thunk_p = tp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void vpi_register_systf(const struct t_vpi_systf_data *ss)
|
||||
{
|
||||
VPITV_CALL(vpi_register_systf,(ss));
|
||||
}
|
||||
|
||||
void vpi_printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
VPITV_CALL(vpi_vprintf,(fmt,ap));
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
unsigned int vpi_mcd_close(unsigned int mcd)
|
||||
{
|
||||
VPIT_CALL(vpi_mcd_close,-1,(mcd));
|
||||
}
|
||||
|
||||
|
||||
char *vpi_mcd_name(unsigned int mcd)
|
||||
{
|
||||
VPIT_CALL(vpi_mcd_name,0,(mcd));
|
||||
}
|
||||
|
||||
unsigned int vpi_mcd_open(char *name)
|
||||
{
|
||||
VPIT_CALL(vpi_mcd_open,-1,(name));
|
||||
}
|
||||
|
||||
unsigned int vpi_mcd_open_x(char *name, char *mode)
|
||||
{
|
||||
VPIT_CALL(vpi_mcd_open_x,-1, (name, mode));
|
||||
}
|
||||
|
||||
int vpi_mcd_printf(unsigned int mcd, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
VPIT_CALL(vpi_mcd_vprintf,0,(mcd,fmt,ap));
|
||||
va_end(ap); /* bad - never hit */
|
||||
}
|
||||
|
||||
int vpi_mcd_fputc(unsigned int mcd, unsigned char x)
|
||||
{
|
||||
VPIT_CALL(vpi_mcd_fputc, 0, (mcd, x));
|
||||
}
|
||||
|
||||
int vpi_mcd_fgetc(unsigned int mcd)
|
||||
{
|
||||
VPIT_CALL(vpi_mcd_fgetc, -1, (mcd));
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_register_cb(p_cb_data data)
|
||||
{
|
||||
VPIT_CALL(vpi_register_cb,0,(data));
|
||||
}
|
||||
|
||||
extern int vpi_remove_cb(vpiHandle ref)
|
||||
{
|
||||
VPIT_CALL(vpi_remove_cb,0,(ref));
|
||||
}
|
||||
|
||||
extern void vpi_sim_control(int operation, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, operation);
|
||||
VPITV_CALL(vpi_sim_vcontrol,(operation,ap));
|
||||
va_end(ap); /* bad - never hit */
|
||||
}
|
||||
|
||||
extern void vpi_control(int operation, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, operation);
|
||||
VPITV_CALL(vpi_sim_vcontrol,(operation,ap));
|
||||
va_end(ap); /* bad - never hit */
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_handle(int type, vpiHandle ref)
|
||||
{
|
||||
VPIT_CALL(vpi_handle, 0, (type, ref));
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_iterate(int type, vpiHandle ref)
|
||||
{
|
||||
VPIT_CALL(vpi_iterate, 0, (type, ref));
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_scan(vpiHandle iter)
|
||||
{
|
||||
VPIT_CALL(vpi_scan, 0, (iter));
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index)
|
||||
{
|
||||
VPIT_CALL(vpi_handle_by_index,0,(ref, index));
|
||||
}
|
||||
|
||||
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t)
|
||||
{
|
||||
VPITV_CALL(vpi_get_time, (obj,t));
|
||||
}
|
||||
|
||||
extern int vpi_get(int property, vpiHandle ref)
|
||||
{
|
||||
VPIT_CALL(vpi_get, 0, (property, ref));
|
||||
|
||||
}
|
||||
|
||||
extern char* vpi_get_str(int property, vpiHandle ref)
|
||||
{
|
||||
VPIT_CALL(vpi_get_str, 0, (property,ref));
|
||||
}
|
||||
|
||||
extern void vpi_get_value(vpiHandle expr, p_vpi_value value)
|
||||
{
|
||||
VPITV_CALL(vpi_get_value, (expr, value));
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
|
||||
p_vpi_time when, int flags)
|
||||
{
|
||||
VPIT_CALL(vpi_put_value, 0, (obj, value, when, flags));
|
||||
}
|
||||
|
||||
extern int vpi_free_object(vpiHandle ref)
|
||||
{
|
||||
VPIT_CALL(vpi_free_object, -1, (ref));
|
||||
}
|
||||
|
||||
extern int vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p)
|
||||
{
|
||||
VPIT_CALL(vpi_get_vlog_info, 0, (vlog_info_p));
|
||||
}
|
||||
|
||||
extern int vpi_chk_error(p_vpi_error_info info)
|
||||
{
|
||||
VPIT_CALL(vpi_chk_error, 0, (info));
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpithunk.c,v $
|
||||
* Revision 1.6 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
*/
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
#ifndef _VPI_THUNK_H_
|
||||
#define _VPI_THUNK_H_ 1
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpithunk.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* These functions are actually defined in lieu of the vpi functions
|
||||
by the simulator. These prototypes should'nt go into vpi_user.h,
|
||||
because we don't want the users to be seeing this stuff. They
|
||||
are non-standard. We have to put them here, so that
|
||||
including vpi_user.h doesn't require including stdarg.h */
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
# include <stdarg.h>
|
||||
extern void vpi_vprintf(const char*fmt, va_list ap);
|
||||
extern int vpi_mcd_vprintf(unsigned int mcd, const char*fmt, va_list ap);
|
||||
extern void vpi_sim_vcontrol(int operation, va_list ap);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#define VPI_THUNK_MAGIC (0x87836BA4)
|
||||
|
||||
typedef struct {
|
||||
int magic;
|
||||
void (*vpi_register_systf)(const struct t_vpi_systf_data*ss);
|
||||
void (*vpi_vprintf)(const char*fmt, va_list ap);
|
||||
unsigned int (*vpi_mcd_close)(unsigned int mcd);
|
||||
char *(*vpi_mcd_name)(unsigned int mcd);
|
||||
unsigned int (*vpi_mcd_open)(char *name);
|
||||
unsigned int (*vpi_mcd_open_x)(char *name, char *mode);
|
||||
int (*vpi_mcd_vprintf)(unsigned int mcd, const char*fmt, va_list ap);
|
||||
int (*vpi_mcd_fputc)(unsigned int mcd, unsigned char x);
|
||||
int (*vpi_mcd_fgetc)(unsigned int mcd);
|
||||
vpiHandle (*vpi_register_cb)(p_cb_data data);
|
||||
int (*vpi_remove_cb)(vpiHandle ref);
|
||||
void (*vpi_sim_vcontrol)(int operation, va_list ap);
|
||||
vpiHandle (*vpi_handle)(int type, vpiHandle ref);
|
||||
vpiHandle (*vpi_iterate)(int type, vpiHandle ref);
|
||||
vpiHandle (*vpi_scan)(vpiHandle iter);
|
||||
vpiHandle (*vpi_handle_by_index)(vpiHandle ref, int index);
|
||||
void (*vpi_get_time)(vpiHandle obj, s_vpi_time*t);
|
||||
int (*vpi_get)(int property, vpiHandle ref);
|
||||
char* (*vpi_get_str)(int property, vpiHandle ref);
|
||||
void (*vpi_get_value)(vpiHandle expr, p_vpi_value value);
|
||||
vpiHandle (*vpi_put_value)(vpiHandle obj, p_vpi_value value,
|
||||
p_vpi_time when, int flags);
|
||||
int (*vpi_free_object)(vpiHandle ref);
|
||||
int (*vpi_get_vlog_info)(p_vpi_vlog_info vlog_info_p);
|
||||
int (*vpi_chk_error)(p_vpi_error_info info);
|
||||
} vpi_thunk, *p_vpi_thunk;
|
||||
|
||||
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: vpithunk.h,v $
|
||||
* Revision 1.4 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user