Compare commits
152 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
1b551aaf94 | |
|
|
a3dda80fb2 | |
|
|
9e9d5ccfdd | |
|
|
07daee9438 | |
|
|
82808d8b5d | |
|
|
c045f51a7f | |
|
|
d72eadb885 | |
|
|
e99f0a8f51 | |
|
|
ed2cb380cd | |
|
|
dc8e941260 | |
|
|
d486b81f23 | |
|
|
59c2f16a5f | |
|
|
1470a061fd | |
|
|
c1333a21ef | |
|
|
04ef0b7d80 | |
|
|
2fc9413d1f | |
|
|
c94bdbcdb0 | |
|
|
1820cd0244 | |
|
|
aa3cbbdf99 | |
|
|
0a9b6f34ae | |
|
|
5c2c5453ac | |
|
|
0c6bb476ea | |
|
|
568924dcb5 | |
|
|
33b3f7bdda | |
|
|
3a04e0a051 | |
|
|
66ae377801 | |
|
|
898db57405 | |
|
|
0fe45b5046 | |
|
|
20cfe99457 | |
|
|
4ec8b38a5c | |
|
|
79add47002 | |
|
|
c429f4c9a7 | |
|
|
7f6a0b652a | |
|
|
9f3f9154eb | |
|
|
498fd06412 | |
|
|
6d3b780791 | |
|
|
a0ec981c50 | |
|
|
930cd598a0 | |
|
|
77adab0f33 | |
|
|
0e3768f829 | |
|
|
22884f2e64 | |
|
|
62da6aca28 | |
|
|
525ebddb0c | |
|
|
521750c007 | |
|
|
85d2833a62 | |
|
|
e2cc258283 | |
|
|
f09cf85c76 | |
|
|
c32de1dba0 | |
|
|
628b866c36 | |
|
|
08dbe801c1 | |
|
|
101810df21 | |
|
|
3877b636df | |
|
|
9d028a63f2 | |
|
|
35e5cea9df | |
|
|
ec510071f1 | |
|
|
7413c533f6 | |
|
|
dde69cebb6 | |
|
|
f942657ad5 | |
|
|
fad1620828 | |
|
|
a9931e7a58 | |
|
|
6cd4adb135 | |
|
|
9643b86ab3 | |
|
|
452eaeaea8 | |
|
|
3a6e2df958 | |
|
|
e73b7e2656 | |
|
|
469ec11190 | |
|
|
e0bbfa512c | |
|
|
94c9af2a5d | |
|
|
9f2e7df0ff | |
|
|
f02b2c9d7a | |
|
|
058dac4290 | |
|
|
ce4e21a962 | |
|
|
065d6bc1e3 | |
|
|
312d09dc1d | |
|
|
faf7f30283 | |
|
|
5d41e98c1f | |
|
|
5e8330a4ff | |
|
|
ef8964c65a | |
|
|
aa42ec381c | |
|
|
c9d4aab9cb | |
|
|
b8bc531f05 | |
|
|
79cb8c883a | |
|
|
27e633410c | |
|
|
7527c466ed | |
|
|
3ea1214160 | |
|
|
782542922d | |
|
|
1f8102c4dc | |
|
|
c4b34e8720 | |
|
|
e494be7cbf | |
|
|
eb0a78e9ce | |
|
|
e80138ec8c | |
|
|
943316c6f6 | |
|
|
52b8ed9077 | |
|
|
fc227aa3e1 | |
|
|
41993815e9 | |
|
|
c5063f5d2f | |
|
|
f28aa11936 | |
|
|
3131fa68b7 | |
|
|
def3809b3f | |
|
|
3429c24a6a | |
|
|
f47627d752 | |
|
|
9468f3d06f | |
|
|
b997de63a5 | |
|
|
f50f06ab4e | |
|
|
d5d03812cd | |
|
|
b6d5a0675e | |
|
|
e63e830d62 | |
|
|
74ca34bd82 | |
|
|
c9d480028e | |
|
|
cc89ba66af | |
|
|
05e6d51004 | |
|
|
ae583204e3 | |
|
|
018476f7cd | |
|
|
bfabeab6b9 | |
|
|
4a3f1a3641 | |
|
|
d97560caa7 | |
|
|
393102d43a | |
|
|
8e97a0e4d4 | |
|
|
4ea789a2d7 | |
|
|
354f7ad920 | |
|
|
f4a6206790 | |
|
|
fd29ba3398 | |
|
|
44fbf60885 | |
|
|
a0d69113c3 | |
|
|
86942ac592 | |
|
|
075f9cbc4b | |
|
|
9dab368880 | |
|
|
5f6027fb66 | |
|
|
53156793fe | |
|
|
4644c220e8 | |
|
|
c30cd9afea | |
|
|
a8f45a18f0 | |
|
|
6828e3e2ea | |
|
|
75eb372adf | |
|
|
3b753fe52b | |
|
|
8c73fa7840 | |
|
|
d310e656c7 | |
|
|
0510367b70 | |
|
|
3e11207a56 | |
|
|
665f31271f | |
|
|
9a2b56675c | |
|
|
c9f38f5ffa | |
|
|
5ea4152162 | |
|
|
327c897d7e | |
|
|
29ebe486b7 | |
|
|
4af0acb3be | |
|
|
8435774c26 | |
|
|
6172748c65 | |
|
|
ca0ae9040a | |
|
|
d9cdbde3f6 | |
|
|
307a97116f | |
|
|
83d2c6dfd1 |
11
LineInfo.cc
11
LineInfo.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
|
||||
#ident "$Id: LineInfo.cc,v 1.4.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -34,12 +34,12 @@ LineInfo::~LineInfo()
|
|||
{
|
||||
}
|
||||
|
||||
string LineInfo::get_line() const
|
||||
std::string LineInfo::get_line() const
|
||||
{
|
||||
ostringstream buf;
|
||||
std::ostringstream buf;
|
||||
buf << (file_? file_ : "") << ":" << lineno_;
|
||||
|
||||
string res = buf.str();
|
||||
std::string res = buf.str();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
|
|||
|
||||
/*
|
||||
* $Log: LineInfo.cc,v $
|
||||
* Revision 1.4.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.4 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
|
|
|||
12
LineInfo.h
12
LineInfo.h
|
|
@ -19,11 +19,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $"
|
||||
#ident "$Id: LineInfo.h,v 1.7.2.2 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* This class holds line information for an internal object.
|
||||
*
|
||||
|
|
@ -38,7 +40,7 @@ class LineInfo {
|
|||
LineInfo();
|
||||
~LineInfo();
|
||||
|
||||
string get_line() const;
|
||||
std::string get_line() const;
|
||||
|
||||
void set_line(const LineInfo&that);
|
||||
|
||||
|
|
@ -52,6 +54,12 @@ class LineInfo {
|
|||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.7.2.2 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.7.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.7 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
|
|
|||
27
Makefile.in
27
Makefile.in
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.169.2.6 2007/03/23 23:26:51 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.8
|
||||
VERSION = 0.8.4
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -54,6 +54,8 @@ INSTALL_DATA = @INSTALL_DATA@
|
|||
STRIP = @STRIP@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
|
||||
CXXFLAGS = -Wall @CXXFLAGS@
|
||||
|
|
@ -103,6 +105,7 @@ distclean: clean
|
|||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
rm -rf autom4te.cache
|
||||
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
|
||||
|
|
@ -169,10 +172,8 @@ lexor.o: lexor.cc parse.h
|
|||
|
||||
parse.o: parse.cc
|
||||
|
||||
parse.cc: $(srcdir)/parse.y
|
||||
parse.cc parse.h: $(srcdir)/parse.y
|
||||
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
|
||||
|
||||
parse.h: parse.cc
|
||||
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
|
||||
|
||||
syn-rules.cc: $(srcdir)/syn-rules.y
|
||||
|
|
@ -187,15 +188,25 @@ lexor_keyword.cc: lexor_keyword.gperf
|
|||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
|
||||
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
$(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
|
||||
iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
|
||||
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
|
||||
|
||||
# Build and install the iverilog-vpi.pdf only if there is a man
|
||||
# program *and* a ps2pdf program.
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: dep iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
|
|
|
|||
20
PDelays.cc
20
PDelays.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.cc,v 1.11 2003/06/21 01:21:42 steve Exp $"
|
||||
#ident "$Id: PDelays.cc,v 1.11.2.1 2006/10/04 00:37:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -72,6 +72,20 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
|
|||
dex = tmp;
|
||||
}
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
if (sizeof(unsigned) <= 4 && shift > 9) {
|
||||
cerr << expr->get_line() << ": error: Precision overflow"
|
||||
<< " in scope " << scope->name() << "." << endl;
|
||||
cerr << expr->get_line() << ": :"
|
||||
<< " Units are 10e" << scope->time_unit()
|
||||
<< " minus precision 10e" << des->get_precision()
|
||||
<< " is 10e" << shift << "." << endl;
|
||||
cerr << expr->get_line() << ": : Perhaps a timescale "
|
||||
<< "is missing or incorrect?" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the delay expression is a real constant or vector
|
||||
constant, then evaluate it, scale it to the local time
|
||||
units, and return an adjusted value. */
|
||||
|
|
@ -79,7 +93,6 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
|
|||
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
||||
verireal fn = tmp->value();
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
long delay = fn.as_long(shift);
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
|
|
@ -146,6 +159,9 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.11.2.1 2006/10/04 00:37:03 steve
|
||||
* Detect delay precision overflow.
|
||||
*
|
||||
* Revision 1.11 2003/06/21 01:21:42 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
|
|
|
|||
7
PExpr.cc
7
PExpr.cc
|
|
@ -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.35 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: PExpr.cc,v 1.35.2.1 2006/02/07 22:46:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -90,6 +90,8 @@ bool PEConcat::is_constant(Module *mod) const
|
|||
{
|
||||
bool constant = repeat_? repeat_->is_constant(mod) : true;
|
||||
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
|
||||
if (parms_[i] == 0)
|
||||
continue;
|
||||
constant = constant && parms_[i]->is_constant(mod);
|
||||
}
|
||||
return constant;
|
||||
|
|
@ -262,6 +264,9 @@ bool PEUnary::is_constant(Module*m) const
|
|||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.35.2.1 2006/02/07 22:46:23 steve
|
||||
* More robust test for concat constant-ness.
|
||||
*
|
||||
* Revision 1.35 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
12
PExpr.h
12
PExpr.h
|
|
@ -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.66 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.66.2.2 2006/07/28 16:26:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -115,6 +115,8 @@ class PEConcat : public PExpr {
|
|||
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Concatenated Regs can be on the left of procedural
|
||||
|
|
@ -324,7 +326,7 @@ class PEString : public PExpr {
|
|||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* PEString::eval_const(const Design*, const NetScope*) const;
|
||||
verinum* eval_const(const Design*, const NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
|
|
@ -492,6 +494,12 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.66.2.2 2006/07/28 16:26:17 steve
|
||||
* Remove excess PEString:: prefix for stubborn compilers.
|
||||
*
|
||||
* Revision 1.66.2.1 2005/12/07 03:28:44 steve
|
||||
* Support constant concatenation of constants.
|
||||
*
|
||||
* Revision 1.66 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
9
PTask.h
9
PTask.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.h,v 1.13 2004/05/31 23:34:36 steve Exp $"
|
||||
#ident "$Id: PTask.h,v 1.13.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
|
|
@ -70,7 +70,7 @@ class PTask : public LineInfo {
|
|||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
|
|
@ -106,7 +106,7 @@ class PFunction : public LineInfo {
|
|||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
|
@ -117,6 +117,9 @@ class PFunction : public LineInfo {
|
|||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.13.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.13 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
13
PUdp.h
13
PUdp.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $"
|
||||
#ident "$Id: PUdp.h,v 1.12.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
|
|
@ -55,20 +55,20 @@ class PUdp {
|
|||
public:
|
||||
explicit PUdp(perm_string n, unsigned nports);
|
||||
|
||||
svector<string>ports;
|
||||
svector<std::string>ports;
|
||||
unsigned find_port(const char*name);
|
||||
|
||||
bool sequential;
|
||||
|
||||
svector<string>tinput;
|
||||
svector<std::string>tinput;
|
||||
svector<char> tcurrent;
|
||||
svector<char> toutput;
|
||||
|
||||
verinum::V initial;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
std::map<std::string,PExpr*> attributes;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
|
||||
perm_string name_;
|
||||
private:
|
||||
|
|
@ -80,6 +80,9 @@ class PUdp {
|
|||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.12.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.12 2004/03/08 00:47:44 steve
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ configure script that modify its behavior:
|
|||
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
|
||||
most out of your install, first make sure you have both 64bit and
|
||||
32bit development libraries installed. Then configure with this
|
||||
somewhat more compilcated command:
|
||||
somewhat more complex command:
|
||||
|
||||
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
|
||||
|
||||
|
|
|
|||
10
Statement.h
10
Statement.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $"
|
||||
#ident "$Id: Statement.h,v 1.40.2.1 2006/07/10 00:21:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -71,12 +71,15 @@ class PProcess : public LineInfo {
|
|||
* fact, the Statement class is abstract and represents all the
|
||||
* possible kinds of statements that exist in Verilog.
|
||||
*/
|
||||
class Statement : public LineInfo {
|
||||
class Statement : public LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
Statement() { }
|
||||
virtual ~Statement() =0;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
void dump_attributes(ostream&out, unsigned ind) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
|
@ -456,6 +459,9 @@ class PWhile : public Statement {
|
|||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.40.2.1 2006/07/10 00:21:49 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.40 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $"
|
||||
#ident "$Id: StringHeap.cc,v 1.6.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
|
|
@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*text)
|
|||
return perm_string(add(text));
|
||||
}
|
||||
|
||||
perm_string StringHeapLex::make(const string&text)
|
||||
perm_string StringHeapLex::make(const std::string&text)
|
||||
{
|
||||
return perm_string(add(text.c_str()));
|
||||
}
|
||||
|
|
@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
|
|||
|
||||
/*
|
||||
* $Log: StringHeap.cc,v $
|
||||
* Revision 1.6.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.6 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
12
StringHeap.h
12
StringHeap.h
|
|
@ -19,12 +19,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.h,v 1.5 2004/02/18 17:11:54 steve Exp $"
|
||||
#ident "$Id: StringHeap.h,v 1.5.2.2 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class perm_string {
|
||||
|
||||
public:
|
||||
|
|
@ -101,7 +103,7 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
const char*add(const char*);
|
||||
perm_string make(const char*);
|
||||
perm_string make(const string&);
|
||||
perm_string make(const std::string&);
|
||||
|
||||
unsigned add_count() const;
|
||||
unsigned add_hit_count() const;
|
||||
|
|
@ -120,6 +122,12 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.5.2.2 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.5.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.5 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
AC_DEFUN([AX_CPP_IDENT],
|
||||
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
|
||||
[AC_TRY_COMPILE([
|
||||
#ident "$Id: aclocal.m4,v 1.6 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: aclocal.m4,v 1.6.2.1 2005/08/27 22:19:37 steve Exp $"
|
||||
],[while (0) {}],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
|
||||
|
|
@ -91,13 +91,9 @@ AC_MSG_RESULT($WIN32)
|
|||
AC_DEFUN([AX_LD_EXTRALIBS],
|
||||
[AC_MSG_CHECKING([for extra libs needed])
|
||||
EXTRALIBS=
|
||||
case "${host}" in
|
||||
*-*-cygwin* )
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
AC_SUBST(EXTRALIBS)
|
||||
AC_MSG_RESULT($EXTRALIBS)
|
||||
])# AX_LD_EXTRALIBS
|
||||
|
|
@ -109,7 +105,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
|
|||
[AC_MSG_CHECKING([for shared library link flag])
|
||||
shared=-shared
|
||||
case "${host}" in
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
shared="-shared -Wl,--enable-auto-image-base"
|
||||
;;
|
||||
|
||||
|
|
@ -138,7 +134,7 @@ AC_DEFUN([AX_C_PICFLAG],
|
|||
PICFLAG=-fPIC
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
PICFLAG=
|
||||
;;
|
||||
|
||||
|
|
@ -173,7 +169,7 @@ case "${host}" in
|
|||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
|
|
|
|||
9
async.cc
9
async.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
|
||||
#ident "$Id: async.cc,v 1.7.2.1 2006/05/21 21:58:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -66,6 +66,10 @@ bool NetEvWait::is_asynchronous()
|
|||
|
||||
NexusSet*inputs = statement_->nex_input();
|
||||
|
||||
/* All the inputs of the statement must be accounted for in
|
||||
the sensitivity list. Otherwise, there are inputs that can
|
||||
change without the event being triggered, and that implies
|
||||
a latch, not a combinational circuit. */
|
||||
if (! sense->contains(*inputs)) {
|
||||
delete sense;
|
||||
delete inputs;
|
||||
|
|
@ -95,6 +99,9 @@ bool NetProcTop::is_asynchronous()
|
|||
|
||||
/*
|
||||
* $Log: async.cc,v $
|
||||
* Revision 1.7.2.1 2006/05/21 21:58:46 steve
|
||||
* NetESignal input is only selected bits.
|
||||
*
|
||||
* Revision 1.7 2004/01/18 23:26:54 steve
|
||||
* The is_combinational function really need not recurse.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -70,6 +70,14 @@ warning.)
|
|||
|
||||
* Other Attributes
|
||||
|
||||
(* ivl_full_case *)
|
||||
|
||||
This attribute only has meaning when attached to case statements,
|
||||
and only when doing synthesis. The statement means to ignore the
|
||||
possibility that some cases are not defined. Presume that the
|
||||
device really is fully specified and do not emit any warnings
|
||||
about missing guards.
|
||||
|
||||
[ none defined yet ]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
echo "Autoconf in root..."
|
||||
autoconf
|
||||
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-edif tgt-fpga libveriuser cadpli
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf --include=.. )
|
||||
( cd ./$dir ; autoconf -f --include=.. )
|
||||
done
|
||||
|
||||
echo "Precompiling lexor_keyword.gperf"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.11 2004/10/04 01:09:07 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.11.2.1 2005/02/23 18:40:23 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -86,6 +86,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ AC_SUBST(DLLIB)
|
|||
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# Linker option used when compiling the target
|
||||
|
|
|
|||
16
compiler.h
16
compiler.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compiler.h,v 1.26 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: compiler.h,v 1.26.2.3 2006/06/12 00:16:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
|
|
@ -78,12 +78,17 @@ extern bool warn_timescale;
|
|||
/* Warn about legal but questionable module port bindings. */
|
||||
extern bool warn_portbinding;
|
||||
|
||||
/* Warn about unused or unassigned variables. */
|
||||
extern bool warn_unused;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
extern bool debug_scopes;
|
||||
extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth;
|
||||
extern bool debug_cprop;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
|
|
@ -136,6 +141,15 @@ extern int load_sys_func_table(const char*path);
|
|||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.26.2.3 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.26.2.2 2006/04/23 04:25:45 steve
|
||||
* Add cprop debugging.
|
||||
*
|
||||
* Revision 1.26.2.1 2006/04/01 01:37:24 steve
|
||||
* Add synth debug flag
|
||||
*
|
||||
* Revision 1.26 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ AC_PROG_CC
|
|||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_PROGS(XGPERF,gperf,none)
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
|
||||
if test "$XGPERF" = "none"
|
||||
then
|
||||
echo ""
|
||||
|
|
@ -93,7 +96,7 @@ AC_C_BIGENDIAN
|
|||
|
||||
AX_LD_EXTRALIBS
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
# CFLAGS inherited by cadpli/Makefile?
|
||||
AX_C_PICFLAG
|
||||
|
||||
|
|
@ -141,6 +144,6 @@ AC_SUBST(vpidir1)
|
|||
AC_SUBST(vpidir2)
|
||||
AC_MSG_RESULT(${vpidir1} ${vpidir2})
|
||||
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-fpga libveriuser cadpli)
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-edif tgt-fpga libveriuser cadpli)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
|
|
|||
408
cprop.cc
408
cprop.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2006 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: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.47.2.7 2007/02/26 19:51:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "functor.h"
|
||||
# include "compiler.h"
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
|
|
@ -47,6 +48,9 @@ struct cprop_functor : public functor_t {
|
|||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||
virtual void lpm_mux_large(Design*des, NetMux*obj);
|
||||
virtual void lpm_ram_dq(Design*des, NetRamDq*obj);
|
||||
bool lpm_ram_dq_const_address_(Design*des, NetRamDq*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
|
|
@ -847,79 +851,373 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
*/
|
||||
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
{
|
||||
if (obj->size() > 2) {
|
||||
lpm_mux_large(des, obj);
|
||||
return;
|
||||
}
|
||||
if (obj->size() != 2)
|
||||
return;
|
||||
if (obj->sel_width() != 1)
|
||||
return;
|
||||
|
||||
/* If the first input is all constant Vz, then replace the
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
connected to the select input. */
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
|
||||
bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
|
||||
|
||||
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
/* If both data inputs are constant, we'll be able to do
|
||||
a substitution. */
|
||||
if (cflag_a && cflag_b)
|
||||
continue;
|
||||
|
||||
verinum::V va = cflag_a
|
||||
? obj->pin_Data(idx, 0).nexus()->driven_value()
|
||||
: verinum::Vx;
|
||||
verinum::V vb = cflag_b
|
||||
? obj->pin_Data(idx, 1).nexus()->driven_value()
|
||||
: verinum::Vx;
|
||||
|
||||
/* If only one Data input is constant, but a constant
|
||||
HiZ, then we will be able to to a bufif
|
||||
substitution. */
|
||||
if (cflag_a && va==verinum::Vz)
|
||||
continue;
|
||||
|
||||
if (cflag_b && vb==verinum::Vz)
|
||||
continue;
|
||||
|
||||
/* Otherwise, we cannot accurately do a substitution. If
|
||||
one input is non-constant, then that input may have a
|
||||
HiZ value, and there is no Verilog logic other then a
|
||||
MUX that can pass a HiZ value. */
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
if (! flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a temporary net to hold the result value that we
|
||||
build up. When we are done, we will connect this to the
|
||||
Result pins of the mux, then delete the mux *and* this
|
||||
net. That will cause all the proper connectivity to
|
||||
happen. */
|
||||
NetNet result_tmp(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
|
||||
/* We know that every slice has at least one constant. Run
|
||||
through the slices again, creating boolean devices to
|
||||
replace the MUX slice. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
|
||||
/* If the Sel==0 input is constant Z, make a bufif1. */
|
||||
if (obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 0).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1);
|
||||
|
||||
connect(obj->pin_Result(idx), tmp->pin(0));
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
/* If the Sel==1 input is constant Z, make a bufif0. */
|
||||
if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
/* If instead the second input is all constant Vz, replace the
|
||||
NetMux with an array of BUFIF0 devices. */
|
||||
flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! obj->pin_Data(idx, 1).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0);
|
||||
|
||||
connect(obj->pin_Result(idx), tmp->pin(0));
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
/* At this point, the only cases that are left are where
|
||||
the data inputs are both constant, and neither are
|
||||
HiZ. From this we know how to generate the output
|
||||
from only the S input. */
|
||||
if (! (obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->drivers_constant())) {
|
||||
cerr << obj->get_line() << ": internal error: "
|
||||
<< "Drivers not constant where expected?"
|
||||
<< " obj->width()=" << obj->width()
|
||||
<< " idx=" << idx
|
||||
<< endl;
|
||||
obj->dump_node(cerr, 4);
|
||||
}
|
||||
assert(obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->drivers_constant());
|
||||
|
||||
|
||||
verinum::V a = obj->pin_Data(idx, 0).nexus()->driven_value();
|
||||
verinum::V b = obj->pin_Data(idx, 1).nexus()->driven_value();
|
||||
|
||||
if (a == b) {
|
||||
connect(result_tmp.pin(idx), obj->pin_Data(idx,0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == verinum::V0 && b == verinum::V1) {
|
||||
connect(result_tmp.pin(idx), obj->pin_Sel(0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == verinum::V1 && b == verinum::V0) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Sel(0), tmp->pin(1));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A==0: Q = B & S */
|
||||
if (a == verinum::V0) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* B==1: Q = A | S */
|
||||
if (b == verinum::V1) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
/* A==1: Q = B | ~S */
|
||||
if (a == verinum::V1) {
|
||||
NetLogic*inv = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
NetNet*invs = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, 1);
|
||||
invs->local_flag(true);
|
||||
connect(inv->pin(0), invs->pin(0));
|
||||
connect(inv->pin(1), obj->pin_Sel(0));
|
||||
des->add_node(inv);
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(inv->pin(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
/* B==0: Q = A & ~S */
|
||||
if (b == verinum::V0) {
|
||||
NetLogic*inv = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
NetNet*invs = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, 1);
|
||||
invs->local_flag(true);
|
||||
connect(inv->pin(0), invs->pin(0));
|
||||
connect(inv->pin(1), obj->pin_Sel(0));
|
||||
des->add_node(inv);
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(inv->pin(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
connect(result_tmp.pin(idx), obj->pin_Result(idx));
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_mux_large(Design*des, NetMux*obj)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
unsigned width = obj->width();
|
||||
unsigned size = obj->size();
|
||||
|
||||
/* This test looks for bit slices that are constant
|
||||
throughout. If we find any, we can reduce the width of the
|
||||
MUX to eliminate the fixed value. */
|
||||
|
||||
/* After the following for loop, this array of bools will
|
||||
contain "true" for each bit slice that is constant and
|
||||
identical, and "false" otherwise. The reduce_width will
|
||||
count the number of true entries in the flags array. */
|
||||
bool*flags = new bool[width];
|
||||
unsigned reduce_width = 0;
|
||||
|
||||
for (unsigned bit = 0 ; bit < width ; bit += 1) {
|
||||
|
||||
flags[bit] = true;
|
||||
|
||||
/* If not even the first selection is constant, then the
|
||||
slice cannot be reduced. */
|
||||
if (! obj->pin_Data(bit, 0).nexus()->drivers_constant()) {
|
||||
flags[bit] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If any of the remaining selections in non-consant, or
|
||||
constant with a different value, then this slice
|
||||
cannot be reduced. */
|
||||
verinum::V val = obj->pin_Data(bit, 0).nexus()->driven_value();
|
||||
|
||||
for (unsigned idx = 1; flags[bit] && idx < size ; idx += 1) {
|
||||
|
||||
if (!obj->pin_Data(bit,idx).nexus()->drivers_constant()) {
|
||||
flags[bit] = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val != obj->pin_Data(bit,idx).nexus()->driven_value()) {
|
||||
flags[bit] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! flags[bit]) {
|
||||
/* This bit slice is too complex. Go on. */
|
||||
continue;
|
||||
}
|
||||
|
||||
reduce_width += 1;
|
||||
}
|
||||
|
||||
/* If no slices can be reduced, then we are finished. */
|
||||
if (reduce_width == 0) {
|
||||
delete[]flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the very special case that all the slices can be
|
||||
reduced. We don't need a MUX at all! */
|
||||
if (reduce_width == width) {
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
delete[]flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a reduced mux with the same name and size, but fewer
|
||||
slices. Connect all the slices that we are keeping. */
|
||||
NetMux*tmp = new NetMux(scope, obj->name(),
|
||||
width-reduce_width, size, obj->sel_width());
|
||||
tmp->set_line(*obj);
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->sel_width() ; idx += 1)
|
||||
connect(obj->pin_Sel(idx), tmp->pin_Sel(idx));
|
||||
|
||||
unsigned dst_bit = 0;
|
||||
|
||||
for (unsigned bit = 0 ; bit < width ; bit += 1) {
|
||||
if (flags[bit]) {
|
||||
connect(obj->pin_Result(bit), obj->pin_Data(bit,0));
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(obj->pin_Result(bit), tmp->pin_Result(dst_bit));
|
||||
|
||||
for (unsigned idx = 0 ; idx < size ; idx += 1)
|
||||
connect(obj->pin_Data(bit,idx), tmp->pin_Data(dst_bit,idx));
|
||||
|
||||
dst_bit += 1;
|
||||
}
|
||||
|
||||
/* Add the new node. Delete the old node. Signal that we
|
||||
change the design and may use a rescan. */
|
||||
des->add_node(tmp);
|
||||
delete obj;
|
||||
delete[]flags;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ram_dq(Design*des, NetRamDq*obj)
|
||||
{
|
||||
if (lpm_ram_dq_const_address_(des,obj))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to evaluate a constant address input. If we find it, then
|
||||
* replace the NetRamDq with a direct link to the addressed word.
|
||||
*/
|
||||
bool cprop_functor::lpm_ram_dq_const_address_(Design*des, NetRamDq*obj)
|
||||
{
|
||||
NetMemory*mem = obj->mem();
|
||||
NetNet* reg = mem->reg_from_explode();
|
||||
|
||||
/* I only know how to do this on exploded memories. */
|
||||
if (reg == 0)
|
||||
return false;
|
||||
|
||||
verinum sel (0UL, obj->awidth());
|
||||
for (unsigned idx = 0 ; idx < obj->awidth() ; idx += 1) {
|
||||
if (! obj->pin_Address(idx).nexus()->drivers_constant())
|
||||
return false;
|
||||
|
||||
sel.set(idx, obj->pin_Address(idx).nexus()->driven_value());
|
||||
}
|
||||
|
||||
unsigned long address = sel.as_ulong();
|
||||
|
||||
/* If the address is outside the ram, then leave this to the
|
||||
code generator to figure out. */
|
||||
if (address >= obj->size())
|
||||
return false;
|
||||
|
||||
|
||||
unsigned base = address * obj->width();
|
||||
assert(base+obj->width() <= reg->pin_count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
connect(reg->pin(base+idx), obj->pin_Q(idx));
|
||||
|
||||
if (debug_cprop) {
|
||||
cerr << obj->get_line() << ": debug: Replace read port with"
|
||||
<< " fixed link to word " << address << "." << endl;
|
||||
}
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This functor looks to see if the constant is connected to nothing
|
||||
* but signals. If that is the case, delete the dangling constant and
|
||||
|
|
@ -1038,6 +1336,24 @@ void cprop(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.47.2.7 2007/02/26 19:51:38 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.47.2.6 2006/11/12 01:20:45 steve
|
||||
* Prevent constant mux outputs from confusing itself.
|
||||
*
|
||||
* Revision 1.47.2.5 2006/04/23 04:26:13 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.47.2.4 2005/09/11 02:50:51 steve
|
||||
* Fix overly agressive constant propagation through MUX causing lost Z bits.
|
||||
*
|
||||
* Revision 1.47.2.3 2005/08/28 22:00:39 steve
|
||||
* Reduce mux slices that are constant throughout range.
|
||||
*
|
||||
* Revision 1.47.2.2 2005/08/28 19:51:02 steve
|
||||
* More thorough constant propagation through MUX devices.
|
||||
*
|
||||
* Revision 1.47 2004/02/20 18:53:34 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.149 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.149.2.7 2006/08/23 04:09:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -171,7 +171,8 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
|||
|
||||
if (pin(idx).is_linked()) {
|
||||
const Nexus*nex = pin(idx).nexus();
|
||||
o << nex << " " << nex->name();
|
||||
const char*nex_name = nex->name();
|
||||
o << nex << " " << (nex_name? nex_name : "????");
|
||||
}
|
||||
o << endl;
|
||||
|
||||
|
|
@ -216,6 +217,23 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDecode::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
|
||||
<< " ff=" << ff_->name() << ", word width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDemux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
|
||||
<< " bus width=" << width() << ", address width=" << awidth()
|
||||
<< ", word count=" << size() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDivide::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl;
|
||||
|
|
@ -240,6 +258,7 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
|
||||
<< " scope=" << scope()->name() << endl;
|
||||
o << setw(ind+6) << "" << "source=" << get_line() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -272,7 +291,12 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
<< " aset_value=" << aset_value_
|
||||
<< " sset_value=" << sset_value_;
|
||||
|
||||
if (demux_) o << " demux=" << demux_->name();
|
||||
|
||||
o << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
@ -355,8 +379,16 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
|
|||
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
<< name() << endl;
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (";
|
||||
|
||||
if (mem_)
|
||||
if (NetNet*tmp = mem_->reg_from_explode())
|
||||
o << "exploded mem=" << tmp->name();
|
||||
else
|
||||
o << "mem=" << mem_->name();
|
||||
|
||||
o << "): " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -537,6 +569,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
|||
break;
|
||||
}
|
||||
|
||||
dump_proc_attr(o, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
o << setw(ind+2) << "";
|
||||
if (items_[idx].guard)
|
||||
|
|
@ -842,6 +876,15 @@ void NetProc::dump(ostream&o, unsigned ind) const
|
|||
o << setw(ind) << "" << "// " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void NetProc::dump_proc_attr(ostream&o, unsigned ind) const
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < attr_cnt() ; idx += 1) {
|
||||
o << setw(ind) << "" << "(* " << attr_key(idx) << " = "
|
||||
<< attr_value(idx) << " *)" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump an expression that no one wrote a dump method for. */
|
||||
void NetExpr::dump(ostream&o) const
|
||||
{
|
||||
|
|
@ -1089,6 +1132,27 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.149.2.7 2006/08/23 04:09:14 steve
|
||||
* missing sig diagnostics.
|
||||
*
|
||||
* Revision 1.149.2.6 2006/07/10 00:21:50 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.149.2.5 2006/04/16 19:26:37 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.149 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.7 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.8
|
||||
VERSION = 0.8.3
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
|
|||
|
|
@ -562,4 +562,5 @@ int main(int argc, char *argv[])
|
|||
compile_and_link();
|
||||
|
||||
myExit(0);
|
||||
return 0; // eliminate warnings.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.24 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.24.2.2 2006/05/08 04:33:35 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -40,6 +40,8 @@ CC = @CC@
|
|||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
|
|
@ -54,6 +56,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
rm -rf autom4te.cache
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
|
||||
|
|
@ -75,15 +78,23 @@ cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
|||
cfparse.o: cfparse.c globals.h cfparse_misc.h
|
||||
|
||||
iverilog.ps: $(srcdir)/iverilog.man
|
||||
man -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
$(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
|
||||
iverilog.pdf: iverilog.ps
|
||||
ps2pdf iverilog.ps iverilog.pdf
|
||||
$(PS2PDF) iverilog.ps iverilog.pdf
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: iverilog.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH iverilog 1 "$Date: 2004/10/04 01:10:56 $" Version "$Date: 2004/10/04 01:10:56 $"
|
||||
.TH iverilog 1 "$Date: 2006/06/12 00:16:53 $" Version "$Date: 2006/06/12 00:16:53 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
|
|
@ -212,6 +212,12 @@ inherit timescale from another file. Both probably mean that
|
|||
timescales are inconsistent, and simulation timing can be confusing
|
||||
and dependent on compilation order.
|
||||
|
||||
.TP 8
|
||||
.B unused
|
||||
This enables warnings for unused variables. This may detect variables
|
||||
that are not assigned, or variables and nets that are not used, or
|
||||
similar possible misuses of variables and nets.
|
||||
|
||||
.SH "SYSTEM FUNCTION TABLE FILES"
|
||||
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
||||
a system function table file. A System function table file is used to
|
||||
|
|
|
|||
101
driver/main.c
101
driver/main.c
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.65 2004/06/17 14:47:22 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.65.2.5 2006/07/07 21:31:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -88,6 +88,10 @@ extern const char*optarg;
|
|||
# define IVL_ROOT "."
|
||||
#endif
|
||||
|
||||
#ifndef IVL_ROOT_VARIABLE
|
||||
# define IVL_ROOT_VARIABLE "IVERILOG_ROOT"
|
||||
#endif
|
||||
|
||||
# include "globals.h"
|
||||
#include "cfparse_misc.h" /* cfparse() */
|
||||
|
||||
|
|
@ -291,7 +295,7 @@ static int t_default(char*cmd, unsigned ncmd)
|
|||
static void process_warning_switch(const char*name)
|
||||
{
|
||||
if (strcmp(name,"all") == 0) {
|
||||
strcat(warning_flags, "ipt");
|
||||
strcat(warning_flags, "iptu");
|
||||
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags+2, 'i'))
|
||||
|
|
@ -302,6 +306,9 @@ static void process_warning_switch(const char*name)
|
|||
} else if (strcmp(name,"timescale") == 0) {
|
||||
if (! strchr(warning_flags+2, 't'))
|
||||
strcat(warning_flags, "t");
|
||||
} else if (strcmp(name,"unused") == 0) {
|
||||
if (! strchr(warning_flags+2, 'u'))
|
||||
strcat(warning_flags, "u");
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'i');
|
||||
if (cp) while (*cp) {
|
||||
|
|
@ -320,6 +327,12 @@ static void process_warning_switch(const char*name)
|
|||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-unused") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'u');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -409,14 +422,13 @@ int process_generation(const char*name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
/*
|
||||
* This function fills in th ivl_root directory with the appropriate
|
||||
* path, based on operating system, build time configuration, and
|
||||
* environment.
|
||||
*/
|
||||
static char* get_root_dir()
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{ char * s;
|
||||
char basepath[1024];
|
||||
|
|
@ -443,16 +455,56 @@ int main(int argc, char **argv)
|
|||
s = strrchr(ivl_root, sep);
|
||||
if (s) *s = 0;
|
||||
strcat(ivl_root, "\\lib\\ivl");
|
||||
|
||||
base = ivl_root;
|
||||
}
|
||||
|
||||
#else
|
||||
/* In a UNIX environment, the IVL_ROOT from the Makefile is
|
||||
dependable. It points to the $prefix/lib/ivl directory,
|
||||
where the sub-parts are installed. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
base = ivl_root;
|
||||
|
||||
{ char*var = 0;
|
||||
|
||||
/* In other systems, use the configured root. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
|
||||
/* In any case, the IVL_ROOT variable can be used to override
|
||||
the install location at run time. If it is set, use that
|
||||
value instead. */
|
||||
if ( (var = getenv(IVL_ROOT_VARIABLE)) ) {
|
||||
strncpy(ivl_root, var, MAXSIZE);
|
||||
strcat(ivl_root, "/lib/ivl");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ivl_root;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
|
||||
base = get_root_dir();
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/* Under Windows, there is no point checking the root
|
||||
directory. */
|
||||
#else
|
||||
/* On other systems, check that the root directory seems
|
||||
reasonable. */
|
||||
{ size_t tmp_len = strlen(base) + 16;
|
||||
char* tmp = malloc(tmp_len);
|
||||
snprintf(tmp, tmp_len, "%s%civl", base, sep);
|
||||
|
||||
if (0 != access(tmp, F_OK)) {
|
||||
fprintf(stderr, "%s: INSTALLATION ERROR: Directory %s"
|
||||
" does not contain ivl files.\n", argv[0], base);
|
||||
fprintf(stderr, "%s: : Check installation"
|
||||
" or set " IVL_ROOT_VARIABLE " correctly.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a temporary file for communicating input parameters
|
||||
|
|
@ -735,6 +787,21 @@ int main(int argc, char **argv)
|
|||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.65.2.5 2006/07/07 21:31:50 steve
|
||||
* Root dir variable does not include lib/ivl components.
|
||||
*
|
||||
* Revision 1.65.2.4 2006/06/27 01:30:20 steve
|
||||
* Fix unused var warning for mingw32 build.
|
||||
*
|
||||
* Revision 1.65.2.3 2006/06/14 03:01:49 steve
|
||||
* Remove redundant call to get_root_dir.
|
||||
*
|
||||
* Revision 1.65.2.2 2006/06/12 00:16:53 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.65.2.1 2006/03/26 21:47:26 steve
|
||||
* More installation directory flexibility.
|
||||
*
|
||||
* Revision 1.65 2004/06/17 14:47:22 steve
|
||||
* Add a .sft file for the system functions.
|
||||
*
|
||||
|
|
|
|||
11
dup_expr.cc
11
dup_expr.cc
|
|
@ -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.18 2004/06/17 16:06:18 steve Exp $"
|
||||
#ident "$Id: dup_expr.cc,v 1.18.2.2 2006/11/02 02:13:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -29,6 +29,7 @@ NetEBComp* NetEBComp::dup_expr() const
|
|||
{
|
||||
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
result->set_line(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +91,7 @@ NetESignal* NetESignal::dup_expr() const
|
|||
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
|
||||
assert(tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +120,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
|||
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
|
||||
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +146,12 @@ NetEVariable* NetEVariable::dup_expr() const
|
|||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.18.2.2 2006/11/02 02:13:15 steve
|
||||
* Error message for condit expression not synthesized.
|
||||
*
|
||||
* Revision 1.18.2.1 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
|
|
|||
16
elab_expr.cc
16
elab_expr.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2006 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: elab_expr.cc,v 1.91 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.91.2.2 2006/11/02 02:13:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -387,13 +387,16 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
if (NetNet*res = dscope->find_signal(dscope->basename())) {
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
eres->set_line(*this);
|
||||
func->set_line(*this);
|
||||
return func;
|
||||
}
|
||||
|
||||
if (NetVariable*res = dscope->find_variable(dscope->basename())) {
|
||||
NetEVariable*eres = new NetEVariable(res);
|
||||
eres->set_line(*res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
eres->set_line(*res);
|
||||
func->set_line(*this);
|
||||
return func;
|
||||
}
|
||||
|
||||
|
|
@ -742,6 +745,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
|
|
@ -1005,6 +1009,12 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.91.2.2 2006/11/02 02:13:15 steve
|
||||
* Error message for condit expression not synthesized.
|
||||
*
|
||||
* Revision 1.91.2.1 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.91 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
27
elab_net.cc
27
elab_net.cc
|
|
@ -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.138 2004/10/04 03:09:38 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.138.2.3 2005/09/11 02:56:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1312,21 +1312,25 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
unsigned repeat = 1;
|
||||
|
||||
if (repeat_) {
|
||||
verinum*rep = repeat_->eval_const(des, scope);
|
||||
if (rep == 0) {
|
||||
NetExpr*etmp = elab_and_eval(des, scope, repeat_);
|
||||
assert(etmp);
|
||||
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
|
||||
|
||||
if (erep == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to "
|
||||
<< "evaluate constant repeat expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep->as_ulong();
|
||||
repeat = erep->value().as_ulong();
|
||||
delete etmp;
|
||||
|
||||
if (repeat == 0) {
|
||||
cerr << get_line() << ": error: Invalid repeat value."
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
"may not be 0."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete rep;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1435,6 +1439,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
|||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(), 1,
|
||||
sig_width, sel->pin_count());
|
||||
mux->set_line(*this);
|
||||
|
||||
/* Connect the signal bits to the mux. Account for the
|
||||
direction of the numbering (lsb to msb vs. msb to lsb) by
|
||||
|
|
@ -2268,6 +2273,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
(true) connected to tru_sig. */
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(), dwidth, 2, 1);
|
||||
mux->set_line(*this);
|
||||
connect(mux->pin_Sel(0), expr_sig->pin(0));
|
||||
|
||||
/* Connect the data inputs. */
|
||||
|
|
@ -2513,6 +2519,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.138.2.3 2005/09/11 02:56:37 steve
|
||||
* Attach line numbers to NetMux devices.
|
||||
*
|
||||
* Revision 1.138.2.2 2005/02/19 16:39:30 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.138.2.1 2005/01/29 00:18:23 steve
|
||||
* Fix evaluate of constants in netlist concatenation repeats.
|
||||
*
|
||||
* Revision 1.138 2004/10/04 03:09:38 steve
|
||||
* Fix excessive error message.
|
||||
*
|
||||
|
|
|
|||
81
elaborate.cc
81
elaborate.cc
|
|
@ -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.308 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.308.2.6 2006/11/27 01:47:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -67,6 +67,21 @@ void PGate::elaborate(Design*des, NetScope*scope) const
|
|||
typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void process_attributes(Design*des, NetScope*scope,
|
||||
Attrib*dest, const map<perm_string,PExpr*>&table)
|
||||
{
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(table, attrib_list_n,
|
||||
des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
dest->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the continuous assign. (This is *not* the procedural
|
||||
* assign.) Elaborate the lvalue and rvalue, and do the assignment.
|
||||
|
|
@ -1179,6 +1194,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
tmp->set_line(*this);
|
||||
|
||||
NetESignal*sig = new NetESignal(tmp);
|
||||
sig->set_line(*this);
|
||||
|
||||
/* Generate an assignment of the l-value to the temporary... */
|
||||
string n = scope->local_hsymbol();
|
||||
|
|
@ -1215,6 +1231,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* And build up the complex statement. */
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU, 0);
|
||||
bl->set_line(*this);
|
||||
bl->append(a1);
|
||||
bl->append(st);
|
||||
|
||||
|
|
@ -1318,6 +1335,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
NetBlock*cur = new NetBlock(type, nscope);
|
||||
cur->set_line(*this);
|
||||
bool fail_flag = false;
|
||||
|
||||
if (nscope == 0)
|
||||
|
|
@ -1388,6 +1406,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
NetCase*res = new NetCase(type_, expr, icount);
|
||||
res->set_line(*this);
|
||||
process_attributes(des, scope, res, attributes);
|
||||
|
||||
/* Iterate over all the case items (guard/statement pairs)
|
||||
elaborating them. If the guard has no expression, then this
|
||||
|
|
@ -1403,8 +1422,12 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
/* If there are no expressions, then this is the
|
||||
default case. */
|
||||
NetProc*st = 0;
|
||||
if (cur->stat)
|
||||
if (cur->stat) {
|
||||
st = cur->stat->elaborate(des, scope);
|
||||
} else {
|
||||
st = new NetBlock(NetBlock::SEQU, scope);
|
||||
st->set_line(*this);
|
||||
}
|
||||
|
||||
res->set_case(inum, 0, st);
|
||||
inum += 1;
|
||||
|
|
@ -1413,16 +1436,19 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* If there are one or more expressions, then
|
||||
iterate over the guard expressions, elaborating
|
||||
a separate case for each. (Yes, the statement
|
||||
will be elaborated again for each.) */
|
||||
a separate case for each. If the statement is
|
||||
nul, then put an appropriate stub in place. */
|
||||
NetExpr*gu = 0;
|
||||
NetProc*st = 0;
|
||||
assert(cur->expr[e]);
|
||||
gu = elab_and_eval(des, scope, cur->expr[e]);
|
||||
|
||||
if (cur->stat)
|
||||
if (cur->stat) {
|
||||
st = cur->stat->elaborate(des, scope);
|
||||
|
||||
} else {
|
||||
st = new NetBlock(NetBlock::SEQU, scope);
|
||||
st->set_line(*this);
|
||||
}
|
||||
res->set_case(inum, gu, st);
|
||||
inum += 1;
|
||||
}
|
||||
|
|
@ -1451,12 +1477,26 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
|||
if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) {
|
||||
verinum val = ce->value();
|
||||
delete expr;
|
||||
if (val[0] == verinum::V1)
|
||||
return if_->elaborate(des, scope);
|
||||
|
||||
verinum::V val_reduced = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
val_reduced = val_reduced | val[idx];
|
||||
|
||||
if (val_reduced == verinum::V1)
|
||||
if (if_) {
|
||||
return if_->elaborate(des, scope);
|
||||
} else {
|
||||
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
else if (else_)
|
||||
return else_->elaborate(des, scope);
|
||||
else
|
||||
return new NetBlock(NetBlock::SEQU, 0);
|
||||
else {
|
||||
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// If the condition expression is more then 1 bits, then
|
||||
|
|
@ -1625,6 +1665,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
NetBlock*block = new NetBlock(NetBlock::SEQU, 0);
|
||||
block->set_line(*this);
|
||||
|
||||
|
||||
/* Detect the case where the definition of the task is known
|
||||
|
|
@ -1702,6 +1743,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
continue;
|
||||
|
||||
NetESignal*sig = new NetESignal(port);
|
||||
sig->set_line(*this);
|
||||
|
||||
/* Generate the assignment statement. */
|
||||
NetAssign*ass = new NetAssign(lv, sig);
|
||||
|
|
@ -2481,6 +2523,7 @@ void PTask::elaborate(Design*des, NetScope*task) const
|
|||
NetProc*st;
|
||||
if (statement_ == 0) {
|
||||
st = new NetBlock(NetBlock::SEQU, 0);
|
||||
st->set_line(*this);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -2769,6 +2812,24 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.308.2.6 2006/11/27 01:47:14 steve
|
||||
* Fix crash handling constant true conditional.
|
||||
*
|
||||
* Revision 1.308.2.5 2006/11/27 01:32:24 steve
|
||||
* Fix evaluate of constant condition expressions.
|
||||
*
|
||||
* Revision 1.308.2.4 2006/07/10 00:21:50 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.308.2.3 2006/06/12 00:16:51 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.308.2.2 2005/12/10 03:30:50 steve
|
||||
* Fix crash on block with assignments that assign lval to self.
|
||||
*
|
||||
* Revision 1.308.2.1 2005/11/13 22:28:14 steve
|
||||
* Do not panic if case statement is nul.
|
||||
*
|
||||
* Revision 1.308 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
18
emit.cc
18
emit.cc
|
|
@ -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.77 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.77.2.2 2006/03/26 23:09:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -86,6 +86,16 @@ bool NetConst::emit_node(struct target_t*tgt) const
|
|||
return tgt->net_const(this);
|
||||
}
|
||||
|
||||
bool NetDecode::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_decode(this);
|
||||
}
|
||||
|
||||
bool NetDemux::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_demux(this);
|
||||
}
|
||||
|
||||
bool NetDivide::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_divide(this);
|
||||
|
|
@ -511,6 +521,12 @@ bool emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.77.2.2 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.77 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
37
eval.cc
37
eval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval.cc,v 1.36 2003/06/21 01:21:43 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.36.2.3 2006/09/20 20:27:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -112,7 +112,10 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
|||
case 'l': { // left shift (<<)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
unsigned use_wid = l->len();
|
||||
if (! l->has_len())
|
||||
use_wid += rv;
|
||||
res = new verinum(verinum::V0, use_wid);
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
|
|
@ -143,6 +146,27 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
|||
return res;
|
||||
}
|
||||
|
||||
verinum* PEConcat::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*accum = parms_[0]->eval_const(des, scope);
|
||||
if (accum == 0)
|
||||
return 0;
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
verinum*tmp = parms_[idx]->eval_const(des, scope);
|
||||
/* Oops, found an argument that is not constant. Give up. */
|
||||
if (tmp == 0) {
|
||||
delete accum;
|
||||
return 0;
|
||||
}
|
||||
assert(tmp);
|
||||
|
||||
*accum = concat(*accum, *tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
|
|
@ -240,6 +264,15 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
|||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.36.2.3 2006/09/20 20:27:02 steve
|
||||
* Fix left shift of small unsized constants.
|
||||
*
|
||||
* Revision 1.36.2.2 2005/12/18 21:06:01 steve
|
||||
* Properly fail when concat is not actually constant.
|
||||
*
|
||||
* Revision 1.36.2.1 2005/12/07 03:28:44 steve
|
||||
* Support constant concatenation of constants.
|
||||
*
|
||||
* Revision 1.36 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
|
|
|
|||
101
eval_tree.cc
101
eval_tree.cc
|
|
@ -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.62 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.62.2.5 2007/03/23 23:02:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -215,6 +215,11 @@ NetEConst* NetEBComp::eval_eqeq_()
|
|||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, false);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
|
|
@ -224,12 +229,24 @@ NetEConst* NetEBComp::eval_less_()
|
|||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (left_->expr_width() == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Having trouble evaluating left expression of < op."
|
||||
<< endl;
|
||||
cerr << get_line() << ": : "
|
||||
<< "Expression is: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
if (lv < rv) {
|
||||
verinum lv (verinum::V1, left_->expr_width() + 1);
|
||||
lv.set(left_->expr_width(), verinum::V0);
|
||||
lv.has_sign( left_->has_sign() );
|
||||
if ((lv < rv) == verinum::V1) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
|
@ -259,7 +276,7 @@ NetEConst* NetEBComp::eval_less_()
|
|||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_real_()
|
||||
NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
|
||||
{
|
||||
NetEConst*vtmp;
|
||||
NetECReal*rtmp;
|
||||
|
|
@ -308,7 +325,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
|||
assert(0);
|
||||
}
|
||||
|
||||
verinum result((lv <= rv)? verinum::V1 : verinum::V0, 1);
|
||||
/* This function supports < and <=. If the eq_flag is true,
|
||||
then include <=. Otherwise, include only <. */
|
||||
bool flag;
|
||||
if (gt_flag)
|
||||
flag = include_eq_flag? (lv >= rv) : (lv > rv);
|
||||
else
|
||||
flag = include_eq_flag? (lv <= rv) : (lv < rv);
|
||||
|
||||
|
||||
verinum result(flag? verinum::V1 : verinum::V0, 1);
|
||||
vtmp = new NetEConst(result);
|
||||
vtmp->set_line(*this);
|
||||
|
||||
|
|
@ -318,9 +344,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
|||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_();
|
||||
return eval_leeq_real_(false, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_();
|
||||
return eval_leeq_real_(false, true);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
|
@ -341,7 +367,9 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
verinum lv (verinum::V1, left_->expr_width() + 1);
|
||||
lv.set(left_->expr_width(), verinum::V0);
|
||||
lv.has_sign( left_->has_sign() );
|
||||
if (lv <= rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
|
|
@ -374,23 +402,10 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
return 0;
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmpr == 0)
|
||||
return 0;
|
||||
|
||||
double ll = tmpl->value().as_double();
|
||||
double rr = tmpr->value().as_double();
|
||||
|
||||
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
|
@ -450,23 +465,10 @@ NetEConst* NetEBComp::eval_gt_()
|
|||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
return 0;
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmpr == 0)
|
||||
return 0;
|
||||
|
||||
double ll = tmpl->value().as_double();
|
||||
double rr = tmpr->value().as_double();
|
||||
|
||||
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
|
@ -1551,6 +1553,21 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.62.2.5 2007/03/23 23:02:31 steve
|
||||
* Fix compile time eval of <= comparison.
|
||||
*
|
||||
* Revision 1.62.2.4 2007/03/23 20:59:25 steve
|
||||
* Fix compile time evaluation of < operator.
|
||||
*
|
||||
* Revision 1.62.2.3 2005/09/09 02:17:08 steve
|
||||
* Evaluate magnitude compare with real operands.
|
||||
*
|
||||
* Revision 1.62.2.2 2005/09/04 15:41:54 steve
|
||||
* More explicit internal error message.
|
||||
*
|
||||
* Revision 1.62.2.1 2005/09/04 15:39:19 steve
|
||||
* More explicit internal error message.
|
||||
*
|
||||
* Revision 1.62 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
* 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.4 2003/11/25 18:35:31 steve Exp $"
|
||||
* $Id: sqrt-virtex.v,v 1.4.2.2 2005/02/23 18:37:52 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
|
||||
* Icarus Verilog. In fact, for no particular reason other than 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.
|
||||
|
|
@ -129,8 +129,8 @@
|
|||
* 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
|
||||
* name of the root module when we were making the EDIF file in the
|
||||
* first place. The module has ports named just like the ports of the
|
||||
* chip_root module below.
|
||||
*
|
||||
* The generated Verilog uses the library in the directory
|
||||
|
|
|
|||
341
expr_synth.cc
341
expr_synth.cc
|
|
@ -17,24 +17,64 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.59.2.11 2007/02/26 19:51:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": internal error: cannot synthesize expression: "
|
||||
<< *this << endl;
|
||||
cerr << get_line() << ": : typeid="
|
||||
<< typeid(*this).name() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the NetEBitSel expression, create a NetMux node that selects a
|
||||
* bit from the input.
|
||||
*/
|
||||
NetNet* NetEBitSel::synthesize(Design*des)
|
||||
{
|
||||
NetNet*net = sig_->synthesize(des);
|
||||
assert(net);
|
||||
|
||||
NetNet*adr = idx_->synthesize(des);
|
||||
if (adr == 0)
|
||||
return 0;
|
||||
|
||||
NetScope*scope = adr->scope();
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
1, net->pin_count(), adr->pin_count());
|
||||
des->add_node(mux);
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Data(0, idx), net->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Sel(idx), adr->pin(idx));
|
||||
|
||||
connect(mux->pin_Result(0), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make an LPM_ADD_SUB device from addition operators.
|
||||
*/
|
||||
|
|
@ -408,7 +448,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
|||
|
||||
default: {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "NetEBDiv has unexpeced op() code: "
|
||||
<< "NetEBDiv has unexpected op() code: "
|
||||
<< op() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
|
|
@ -472,13 +512,18 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
perm_string oname = scope->local_symbol();
|
||||
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
olog->set_line(*this);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
des->add_node(olog);
|
||||
|
||||
/* XXXX Here, I need to reduce the parameters with
|
||||
reduction or. */
|
||||
/* Here, I need to reduce the parameters with
|
||||
reduction or. Only do this if we must. */
|
||||
if (lsig->pin_count() > 1)
|
||||
lsig = reduction_or(des, lsig);
|
||||
|
||||
if (rsig->pin_count() > 1)
|
||||
rsig = reduction_or(des, rsig);
|
||||
|
||||
/* By this point, the left and right parameters have been
|
||||
reduced to single bit values. Now we just connect them to
|
||||
|
|
@ -486,6 +531,11 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
assert(lsig->pin_count() == 1);
|
||||
connect(lsig->pin(0), olog->pin(1));
|
||||
|
||||
if (rsig->pin_count() != 1) {
|
||||
cerr << olog->get_line() << ": internal error: "
|
||||
<< "right argument not reduced. expr=" << *this << endl;
|
||||
}
|
||||
|
||||
assert(rsig->pin_count() == 1);
|
||||
connect(rsig->pin(0), olog->pin(2));
|
||||
}
|
||||
|
|
@ -566,7 +616,6 @@ NetNet* NetEBShift::synthesize(Design*des)
|
|||
NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
assert(op() == 'l');
|
||||
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
|
||||
osig->pin_count(),
|
||||
rsig->pin_count(),
|
||||
|
|
@ -640,6 +689,71 @@ NetNet* NetEConst::synthesize(Design*des)
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEMemory::synthesize(Design*des)
|
||||
{
|
||||
NetScope*scope = mem_->scope();
|
||||
|
||||
NetNet*explode = mem_->explode_to_reg();
|
||||
unsigned width = expr_width();
|
||||
|
||||
assert(idx_);
|
||||
NetNet*addr = idx_->synthesize(des);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT,
|
||||
width);
|
||||
osig->set_line(*this);
|
||||
|
||||
if (explode) {
|
||||
if (debug_synth)
|
||||
cerr << get_line() << ": debug: synthesize read of "
|
||||
<< explode->pin_count() << " bit exploded memory." << endl;
|
||||
|
||||
/* Only make a mux big enough to address the words that
|
||||
the address can generate. (If the address is
|
||||
0-extended, then only the low words are addressable.) */
|
||||
unsigned use_count = mem_->count();
|
||||
if (use_count > (1U << addr->pin_count())) {
|
||||
use_count = 1 << addr->pin_count();
|
||||
|
||||
if (debug_synth)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Index expression can only address "
|
||||
<< use_count << " of "
|
||||
<< mem_->count() << " words." << endl;
|
||||
}
|
||||
|
||||
/* This is a reference to an exploded memory. So locate
|
||||
the reg vector and use the addr expression as a
|
||||
select into a MUX. */
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
width, use_count, addr->pin_count());
|
||||
des->add_node(mux);
|
||||
mux->set_line(*this);
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(mux->pin_Result(idx), osig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < mux->sel_width() ; idx += 1)
|
||||
connect(mux->pin_Sel(idx), addr->pin(idx));
|
||||
|
||||
for (unsigned wrd = 0 ; wrd < use_count ; wrd += 1)
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1) {
|
||||
unsigned bit = wrd*width + idx;
|
||||
connect(mux->pin_Data(idx, wrd), explode->pin(bit));
|
||||
}
|
||||
|
||||
if (debug_synth)
|
||||
cerr << get_line() << ": debug: synthesis done." << endl;
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": internal error: Synthesize memory "
|
||||
<< "expression that is not exploded?" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetECReal::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": error: Real constants are "
|
||||
|
|
@ -684,6 +798,96 @@ NetNet* NetEUBits::synthesize(Design*des)
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des)
|
||||
{
|
||||
assert(func_);
|
||||
|
||||
NetFuncDef* def = func_->func_def();
|
||||
assert(def);
|
||||
|
||||
assert(parms_.count() == def->port_count());
|
||||
|
||||
svector<NetNet*> inports (parms_.count());
|
||||
|
||||
unsigned errors = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
inports[idx] = parms_[idx]->synthesize(des);
|
||||
if (inports[idx] == 0)
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "Cannot continue with function instance synthesis."
|
||||
<< endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet*out = def->synthesize(des, inports);
|
||||
|
||||
if (! out) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "User defined functions do not synthesize." << endl;
|
||||
def->dump(cerr, 4);
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
NetNet* NetFuncDef::synthesize(Design*des, const svector<NetNet*>&inports_)
|
||||
{
|
||||
|
||||
/* First run synthesis for the function definition as if this
|
||||
where a toplevel process. This will create the logic that
|
||||
the function represents, but connected to the port nets for
|
||||
the function definition. We will detach those common ports
|
||||
later. */
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
|
||||
const perm_string tmp1 = scope()->local_symbol();
|
||||
NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE,
|
||||
nex_set.count());
|
||||
for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1)
|
||||
connect(nex_set[idx], nex_out->pin(idx));
|
||||
|
||||
bool flag = statement_->synth_async_noaccum(des, scope(), false, 0,
|
||||
nex_out, nex_out);
|
||||
|
||||
if (!flag) {
|
||||
delete nex_out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Connect the inports_ vectors to the input ports and detach
|
||||
the static arg ports themselves. This moves the input from
|
||||
the synthesized device from the static ports to the actual
|
||||
ports from the instance context. */
|
||||
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
|
||||
NetNet*in = inports_[idx];
|
||||
NetNet*arg = ports_[idx];
|
||||
|
||||
assert(in->pin_count() == arg->pin_count());
|
||||
for (unsigned pin = 0 ; pin < arg->pin_count() ; pin += 1) {
|
||||
connect(in->pin(pin), arg->pin(pin));
|
||||
arg->pin(pin).unlink();
|
||||
}
|
||||
}
|
||||
|
||||
/* Detach the output signal from the synthesized result. We
|
||||
use instead the nex_out that was returned from the
|
||||
synthesis of the function. This is how we account for the
|
||||
fact that the function may be synthesized multiple times to
|
||||
go into multiple expression. Each synthesis needs a unique
|
||||
output. */
|
||||
for (unsigned idx = 0 ; idx < result_sig_->pin_count() ; idx += 1)
|
||||
result_sig_->pin(idx).unlink();
|
||||
|
||||
return nex_out;
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
|
@ -811,6 +1015,7 @@ NetNet* NetETernary::synthesize(Design *des)
|
|||
|
||||
perm_string oname = csig->scope()->local_symbol();
|
||||
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
|
||||
mux->set_line(*this);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(tsig->pin(idx), mux->pin_Data(idx, 1));
|
||||
connect(fsig->pin(idx), mux->pin_Data(idx, 0));
|
||||
|
|
@ -854,6 +1059,21 @@ NetNet* NetETernary::synthesize(Design *des)
|
|||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
if (warn_unused) {
|
||||
if (net_->peek_lref() == 0 && net_->type()==NetNet::REG) {
|
||||
cerr << get_line() << ": warning: "
|
||||
<< "reg " << net_->name()
|
||||
<< " is used by logic but never assigned." << endl;
|
||||
}
|
||||
|
||||
if (net_->peek_lref() == 0 && net_->type()==NetNet::INTEGER) {
|
||||
cerr << get_line() << ": warning: "
|
||||
<< "reg " << net_->name()
|
||||
<< " is used by logic but never assigned." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no part select, then the synthesis is trivial. */
|
||||
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
|
||||
return net_;
|
||||
|
||||
|
|
@ -866,6 +1086,7 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
perm_string name = scope->local_symbol();
|
||||
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net_->pin(idx+lsi_));
|
||||
|
|
@ -875,6 +1096,39 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.59.2.11 2007/02/26 19:51:38 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.59.2.10 2006/11/26 01:54:05 steve
|
||||
* Add synthesis of user defined functions.
|
||||
*
|
||||
* Revision 1.59.2.9 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.59.2.8 2006/06/15 01:57:26 steve
|
||||
* Handle simple memory addressing in expression synthesis.
|
||||
*
|
||||
* Revision 1.59.2.7 2006/06/14 03:02:54 steve
|
||||
* synthesis for NetEBitSel.
|
||||
*
|
||||
* Revision 1.59.2.6 2006/06/12 00:16:52 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.59.2.5 2006/05/15 03:55:22 steve
|
||||
* Fix synthesis of expressions with land of vectors.
|
||||
*
|
||||
* Revision 1.59.2.4 2006/04/10 03:43:39 steve
|
||||
* Exploded memories accessed by constant indices.
|
||||
*
|
||||
* Revision 1.59.2.3 2006/03/16 05:39:20 steve
|
||||
* Right shifts really are allowed.
|
||||
*
|
||||
* Revision 1.59.2.2 2005/09/11 02:56:37 steve
|
||||
* Attach line numbers to NetMux devices.
|
||||
*
|
||||
* Revision 1.59.2.1 2005/02/19 16:39:31 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.59 2004/06/30 02:16:26 steve
|
||||
* Implement signed divide and signed right shift in nets.
|
||||
*
|
||||
|
|
@ -883,82 +1137,5 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
*
|
||||
* Revision 1.57 2004/06/12 15:00:02 steve
|
||||
* Support / and % in synthesized contexts.
|
||||
*
|
||||
* Revision 1.56 2004/06/01 01:04:57 steve
|
||||
* Fix synthesis method for logical and/or
|
||||
*
|
||||
* Revision 1.55 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.54 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.53 2004/02/15 04:23:48 steve
|
||||
* Fix evaluation of compare to constant expression.
|
||||
*
|
||||
* Revision 1.52 2003/11/10 19:39:20 steve
|
||||
* Remove redundant scope tokens.
|
||||
*
|
||||
* Revision 1.51 2003/10/27 06:04:21 steve
|
||||
* More flexible width handling for synthesized add.
|
||||
*
|
||||
* Revision 1.50 2003/09/26 02:44:27 steve
|
||||
* Assure ternary arguments are wide enough.
|
||||
*
|
||||
* Revision 1.49 2003/09/03 23:31:36 steve
|
||||
* Support synthesis of constant downshifts.
|
||||
*
|
||||
* Revision 1.48 2003/08/28 04:11:18 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
* Revision 1.47 2003/08/09 03:23:40 steve
|
||||
* Add support for IVL_LPM_MULT device.
|
||||
*
|
||||
* Revision 1.46 2003/07/26 03:34:42 steve
|
||||
* Start handling pad of expressions in code generators.
|
||||
*
|
||||
* Revision 1.45 2003/06/24 01:38:02 steve
|
||||
* Various warnings fixed.
|
||||
*
|
||||
* Revision 1.44 2003/04/19 04:52:56 steve
|
||||
* Less picky about expression widths while synthesizing ternary.
|
||||
*
|
||||
* Revision 1.43 2003/04/08 05:07:15 steve
|
||||
* Detect constant shift distances in synthesis.
|
||||
*
|
||||
* Revision 1.42 2003/04/08 04:33:55 steve
|
||||
* Synthesize shift expressions.
|
||||
*
|
||||
* Revision 1.41 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.40 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.39 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Revision 1.35 2002/07/07 22:31:39 steve
|
||||
* Smart synthesis of binary AND expressions.
|
||||
*
|
||||
* Revision 1.34 2002/07/05 21:26:17 steve
|
||||
* Avoid emitting to vvp local net symbols.
|
||||
*
|
||||
* Revision 1.33 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*/
|
||||
|
||||
|
|
|
|||
13
functor.cc
13
functor.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.cc,v 1.32 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.32.2.1 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -79,6 +79,9 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
|
|||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ram_dq(class Design*, class NetRamDq*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
{
|
||||
|
|
@ -206,6 +209,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
|
|||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
void NetRamDq::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ram_dq(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
{
|
||||
}
|
||||
|
|
@ -267,6 +275,9 @@ int proc_match_t::event_wait(NetEvWait*)
|
|||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.32.2.1 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.32 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.20 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.20.2.1 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -77,6 +77,9 @@ struct functor_t {
|
|||
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
|
||||
/* This is called for eacm RamDq device. */
|
||||
virtual void lpm_ram_dq(class Design*des, class NetRamDq*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
|
|
@ -92,6 +95,9 @@ struct proc_match_t {
|
|||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.20.2.1 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
|
|
|||
3
ivl.def
3
ivl.def
|
|
@ -62,12 +62,15 @@ ivl_logic_udp
|
|||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_attr_cnt
|
||||
ivl_lpm_attr_val
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_data2
|
||||
ivl_lpm_data2_width
|
||||
ivl_lpm_decode
|
||||
ivl_lpm_define
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
|
|
|
|||
109
ivl_target.h
109
ivl_target.h
|
|
@ -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.126 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.126.2.5 2006/04/16 19:26:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -226,6 +226,8 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
IVL_LPM_CMP_NE = 11,
|
||||
IVL_LPM_DECODE = 15,
|
||||
IVL_LPM_DEMUX = 16,
|
||||
IVL_LPM_DIVIDE = 12,
|
||||
IVL_LPM_FF = 3,
|
||||
IVL_LPM_MOD = 13,
|
||||
|
|
@ -629,6 +631,11 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* the LPM type, but it generally has to do with the width of the
|
||||
* output data path.
|
||||
*
|
||||
* ivl_lpm_attr_cnt
|
||||
* ivl_lpm_attr_val
|
||||
* These functions access attributes attached to LPM devices. These
|
||||
* attributes may be explicit attributes collected from the Verilog
|
||||
* source, or implicit attributes generated by the compiler.
|
||||
*
|
||||
* These functions apply to a subset of the LPM devices, or may have
|
||||
* varying meaning depending on the device:
|
||||
|
|
@ -642,13 +649,18 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* Return the input data nexus for device types that have a second
|
||||
* input vector. For example, arithmetic devices are like this.
|
||||
*
|
||||
* ivl_lpm_decode
|
||||
* Return the DECODER associated with this LPM_FF device. The
|
||||
* decoder for a FF takes an input address and generates an enable
|
||||
* input for no more then 1 bit (can be none) of the FF device.
|
||||
*
|
||||
* ivl_lpm_q
|
||||
* Return the output data nexus for device types that have a single
|
||||
* output vector. This is most devices, it turns out.
|
||||
*
|
||||
* ivl_lpm_selects
|
||||
* This is the size of the select input for a LPM_MUX device, or the
|
||||
* address bus width of an LPM_RAM.
|
||||
* This is the size of the select input for a LPM_MUX or LPM_DECODE
|
||||
* device, or the address bus width of an LPM_RAM.
|
||||
*
|
||||
* ivl_lpm_signed
|
||||
* Arithmetic LPM devices may be signed or unsigned if there is a
|
||||
|
|
@ -658,6 +670,64 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* In addition to a width, some devices have a size. The size is
|
||||
* often the number of inputs per out, i.e., the number of inputs
|
||||
* per bit for a MUX.
|
||||
*
|
||||
* SEMANTIC NOTES:
|
||||
*
|
||||
* - IVL_LPM_FF
|
||||
* The IVL_LPM_FF and IVL_LPM_DECODE devices are closely related. If
|
||||
* the ivl_lpm_decode function returns a non-nil value, then the
|
||||
* decoder represents an extra ENABLE-like input, where exactly <N>
|
||||
* bits of the width of the FF is enabled. The ivl_lpm_width of the
|
||||
* decoder defines <N>.
|
||||
*
|
||||
* The decoder inputs are the address that selects the FF to be
|
||||
* enabled, and the ivl_lpm_selects for the decoder gives the width of
|
||||
* the address. The address of the LSB of the memory, then, is the
|
||||
* word width times the input address. For a simple l-value bit
|
||||
* select, the word width <N> will be 1, and the address goes directly
|
||||
* to the bit. Otherwise, <N>*address gets to the first bit of the word.
|
||||
*
|
||||
* The core compiler generates these attributes in certain cases:
|
||||
*
|
||||
* - ivl:clock_polarity
|
||||
* If present, the string value can be "INVERT". That indicates
|
||||
* that the clock is negedge sensitive instead of the default
|
||||
* posedge sensitive.
|
||||
*
|
||||
* - IVL_LPM_RAM
|
||||
* The IVL_LPM_RAM may also appear as a READ port for a FF array. In
|
||||
* this case, the IVL_LPM_RAM device has an ivl_lpm_width that is the
|
||||
* width of the word, and an ivl_lpm_size that is the number of words
|
||||
* in the array. In effect, the IVL_LPM_RAM reorganizes a vector into
|
||||
* an array of words. If this is happening, then the ivl_lpm_memory
|
||||
* will return 0.
|
||||
*
|
||||
* The ivl_lpm_q function gets the output nexa of the read port. The
|
||||
* "q" port has as many bits as the width. The ivl_lpm_data2 function
|
||||
* gets the nexa of the input, with the sdx the word address and the
|
||||
* idx the bit within the word.
|
||||
*
|
||||
* - IVL_LPM_DEMUX
|
||||
* This device is a form of bit replacement. The device has a data bus
|
||||
* width (ivl_lpm_width) and an address width. The Data outputs are
|
||||
* ivl_lpm_q and have the data bus width. The ivl_lpm_data functions are
|
||||
* inputs to the device. Normally, the device passes the data inputs
|
||||
* through to the Q output.
|
||||
*
|
||||
* The IVL_LPM_DEMUX also has a size (ivl_lpm_size) which is the
|
||||
* number of addressable units in the device. If the device is bit-
|
||||
* addressable, then the size is the same as the width. I.e. if
|
||||
* ivl_lpm_width == ivl_lpm_size, then the address selects a single
|
||||
* bit. If ivl_lpm_width/ivl_lpm_size == 8, then the address selects
|
||||
* words of 8 bits and there are ivl_lpm_size of them. The
|
||||
* ivl_lpm_width will always be an exact multiple of
|
||||
* ivl_lpm_size. This is slightly different from the meaning of width
|
||||
* in memory ports, but reflects that the DEMUX manipulates fixed
|
||||
* width ranges within a single vector.
|
||||
*
|
||||
* The ivl_lpm_select inputs address a bit of the device. The
|
||||
* addressed bit is substituted by the replacement bit. This
|
||||
* replacement bit comes from the ivl_lpm_datab(net,0) nexus.
|
||||
*/
|
||||
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
|
||||
|
|
@ -667,6 +737,9 @@ extern int ivl_lpm_signed(ivl_lpm_t net);
|
|||
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
|
||||
extern unsigned ivl_lpm_width(ivl_lpm_t net);
|
||||
|
||||
extern unsigned ivl_lpm_attr_cnt(ivl_lpm_t net);
|
||||
extern ivl_attribute_t ivl_lpm_attr_val(ivl_lpm_t net, unsigned idx);
|
||||
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net);
|
||||
|
|
@ -676,26 +749,29 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
|||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT */
|
||||
/* IVL_LPM_RAM IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_MUX IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX */
|
||||
/* IVL_LPM_DEMUX, IVL_LPM_MUX, IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
|
@ -1236,6 +1312,21 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.126.2.5 2006/04/16 19:26:37 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.126.2.4 2006/03/26 23:09:22 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.126.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.126.2.2 2006/02/25 05:03:28 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.126.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.126 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ valid options include:
|
|||
Predefine the symbol ``name'' to have the specified
|
||||
value. If the value is not specified, then ``1'' is
|
||||
used. This is mostly of use for controlling conditional
|
||||
compilaiton.
|
||||
compilation.
|
||||
|
||||
This option does *not* override existing `define
|
||||
directives in the source file.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.20 2004/09/10 00:15:45 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.20.2.1 2006/06/27 01:37:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -126,8 +126,8 @@ int main(int argc, char*argv[])
|
|||
int opt, idx;
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
char *dep_path = NULL;
|
||||
const char*out_path = 0;
|
||||
const char*dep_path = NULL;
|
||||
FILE*out;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
|
|
@ -290,6 +290,9 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.20.2.1 2006/06/27 01:37:14 steve
|
||||
* Fix const/non-const warnings.
|
||||
*
|
||||
* Revision 1.20 2004/09/10 00:15:45 steve
|
||||
* Remove bad casts.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
%option never-interactive
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
|
|
@ -19,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.86 2004/06/13 04:56:54 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.86.2.4 2007/02/09 05:29:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -160,7 +162,8 @@ W [ \t\b\f\r]+
|
|||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
|
||||
\" { BEGIN(CSTRING); }
|
||||
<CSTRING>\\\" { yymore(); }
|
||||
<CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
|
||||
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
|
||||
<CSTRING>\n { BEGIN(0);
|
||||
yylval.text = strdup(yytext);
|
||||
VLerror(yylloc, "Missing close quote of string.");
|
||||
|
|
@ -179,6 +182,8 @@ W [ \t\b\f\r]+
|
|||
<UDPTABLE>\(01\) { return 'r'; }
|
||||
<UDPTABLE>\(0[xX]\) { return 'Q'; }
|
||||
<UDPTABLE>\(b[xX]\) { return 'q'; }
|
||||
<UDPTABLE>\(b0\) { return 'f'; /* b0 is 10|00, but only 10 is meaningful */}
|
||||
<UDPTABLE>\(b1\) { return 'r'; /* b1 is 11|01, but only 01 is meaningful */}
|
||||
<UDPTABLE>\(0\?\) { return 'P'; }
|
||||
<UDPTABLE>\(10\) { return 'f'; }
|
||||
<UDPTABLE>\(1[xX]\) { return 'M'; }
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.34 2004/10/04 01:10:07 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.34.2.1 2005/02/23 18:40:24 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -93,6 +93,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
AC_INIT(Makefile.in)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
|
|
@ -21,7 +23,7 @@ AC_CHECK_SIZEOF(unsigned)
|
|||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
AC_SUBST(EXEEXT)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: load_module.cc,v 1.12 2003/06/05 04:31:09 steve Exp $"
|
||||
#ident "$Id: load_module.cc,v 1.12.2.1 2005/03/22 15:53:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -88,7 +88,7 @@ bool load_module(const char*type)
|
|||
cerr << "Executing: " << cmdline << endl;
|
||||
|
||||
pform_parse(path, file);
|
||||
fclose(file);
|
||||
pclose(file);
|
||||
free(cmdline);
|
||||
|
||||
} else {
|
||||
|
|
@ -193,6 +193,9 @@ int build_library_index(const char*path, bool key_case_sensitive)
|
|||
|
||||
/*
|
||||
* $Log: load_module.cc,v $
|
||||
* Revision 1.12.2.1 2005/03/22 15:53:12 steve
|
||||
* popen must be matched by pclose.
|
||||
*
|
||||
* Revision 1.12 2003/06/05 04:31:09 steve
|
||||
* INclude missing assert.h in load_module.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
Icarus Verilog for Mac OS X
|
||||
|
||||
NOTE: Icarus Verilog version 0.8 is known to compile "out of the
|
||||
box" on MacOSX 10.3. OSX 10.3 users need only the developer tools
|
||||
included with new systems or available for free download from
|
||||
Apple. Install Xcode and skip directly to step #3.
|
||||
|
||||
This file describes the procedure to build and install Icarus Verilog
|
||||
on Mac OS X. I assume that you have experience with Unix and
|
||||
Terminal.app and a basic knowledge of how to download, compile and
|
||||
|
|
|
|||
24
main.cc
24
main.cc
|
|
@ -19,7 +19,7 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.86 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.86.2.3 2006/06/12 00:16:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -103,6 +103,7 @@ FILE *depend_file = NULL;
|
|||
bool warn_implicit = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_unused = false;
|
||||
|
||||
bool error_implicit = false;
|
||||
|
||||
|
|
@ -112,6 +113,9 @@ bool error_implicit = false;
|
|||
bool debug_scopes = false;
|
||||
bool debug_eval_tree = false;
|
||||
bool debug_elaborate = false;
|
||||
bool debug_synth = false;
|
||||
bool debug_cprop = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
*/
|
||||
|
|
@ -314,6 +318,12 @@ static void read_iconfig_file(const char*ipath)
|
|||
} else if (strcmp(cp,"elaborate") == 0) {
|
||||
debug_elaborate = true;
|
||||
cerr << "debug: Enable elaborate debug" << endl;
|
||||
} else if (strcmp(cp,"synth") == 0) {
|
||||
debug_synth = true;
|
||||
cerr << "debug: Enable synthesis debug" << endl;
|
||||
} else if (strcmp(cp,"cprop") == 0) {
|
||||
debug_cprop = true;
|
||||
cerr << "debug: Enable cprop debug" << endl;
|
||||
} else {
|
||||
}
|
||||
|
||||
|
|
@ -376,6 +386,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
case 't':
|
||||
warn_timescale = true;
|
||||
break;
|
||||
case 'u':
|
||||
warn_unused = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -744,6 +757,15 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.86.2.3 2006/06/12 00:16:53 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.86.2.2 2006/04/23 04:25:45 steve
|
||||
* Add cprop debugging.
|
||||
*
|
||||
* Revision 1.86.2.1 2006/04/01 01:37:24 steve
|
||||
* Add synth debug flag
|
||||
*
|
||||
* Revision 1.86 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
217
mingw.txt
217
mingw.txt
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
MINGW PORT OF ICARUS VERILOG
|
||||
|
||||
Copyright 2003 Stephen Williams <steve@icarus.com>
|
||||
Copyright 2006 Stephen Williams <steve@icarus.com>
|
||||
|
||||
|
||||
Icarus Verilog source can be compiled with the mingw C/C++ compilers
|
||||
|
|
@ -12,13 +12,13 @@ or without Cygwin, so this is the preferred Windows distribution form.
|
|||
The configure scripts automatically detect that the compilers in use
|
||||
are the mingw compilers and will configure the Makefiles appropriately.
|
||||
|
||||
However, the mingw tools do not include all the other tools around the
|
||||
compiler, including the shell interpreter for the configure script,
|
||||
bison, flex, gperf, etc. Therefore, you still need Cygwin to compile
|
||||
Icarus Verilog, even if you don't need the Cygwin compilers. There are
|
||||
also a few precompiled library prerequisites that you need.
|
||||
The mingw patch doesn't contain tools beyond the compiler, but there
|
||||
is the "msys" package that the makers of Mingw publish that has enough
|
||||
extra tools to get most everything else working. There are a few extra
|
||||
packages needed beyond mingw and msys, and the following instructions
|
||||
explain how to get them and install them.
|
||||
|
||||
* Some Preliminary Comments
|
||||
* Some Preliminary Comments -- PLEASE READ ME --
|
||||
|
||||
The Windows port of Icarus Verilog is the most difficult of all the
|
||||
ports. The Windows system off the shelf is completely stripped, devoid
|
||||
|
|
@ -26,7 +26,15 @@ of any support for software development. Everything needed to compile
|
|||
Icarus Verilog must be collected from various sources and stitched
|
||||
together by hand. Normal human beings with a basic understanding of
|
||||
software development can do this, but some patience (and access to the
|
||||
Internet) is required. You may choose to print these instructions.
|
||||
Internet) is required. You may choose to print these instructions. FOR
|
||||
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
|
||||
|
||||
NOTE that if you have Cygwin installed, it is best to not use a cygwin
|
||||
window to do the build, as the Cygwin tools will intermix with the
|
||||
mingw tools such that it is hard to be sure you are using the right
|
||||
compiler. Thus, it is recommended that these steps be *not* done in a
|
||||
Cygwin window. Use an MSYS window instead, and be careful that your
|
||||
msys/mingw tools are not masked by paths that point to Cygwin binaries.
|
||||
|
||||
I have no plans to intentionally support MSVC++ compilation. Don't ask.
|
||||
|
||||
|
|
@ -36,13 +44,15 @@ This is a brief list of prerequisite packages, along with the URL
|
|||
where each can be found. In most cases, the specific version is not
|
||||
critical, but these are the versions I use.
|
||||
|
||||
Cygwin <http://cygwin.com>
|
||||
Mingw32-2.0.0 <http://www.mingw.org>
|
||||
msys-1.0 <http://www.mingw/org>
|
||||
msysDTK-1.0 <http://www.mingw.org>
|
||||
Mingw32-5.x <http://www.mingw.org>
|
||||
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
|
||||
bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.2-lib.zip <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.1.4-lib.zip <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
||||
bison-2.1 <http://gnuwin32.sourceforge.net>
|
||||
flex-2.5.4a <http://gnuwin32.sourceforge.net>
|
||||
|
||||
The above table lists the packages required. It is convenient to
|
||||
install them in the above order. Many of these packages are also
|
||||
|
|
@ -55,59 +65,38 @@ installation of Icarus Verilog is complete. These are only needed to
|
|||
build the compiler. The Mingw32 package can be used to compile VPI
|
||||
modules if you choose.
|
||||
|
||||
* Install Cygwin
|
||||
* Install MSYS and msysDTK
|
||||
|
||||
So, step 1 is "Download and Install Cygwin." See the web page
|
||||
http://www.cygwin.com for instructions and the files to do
|
||||
this. Cygwin *is* a kool package, and is worth having anyhow. There is
|
||||
a convenient setup program that you download first. You execute the
|
||||
setup program, and that prompts you to select the package you want.
|
||||
The msys package is available from the mingw download site. This is
|
||||
not the compiler but a collection of *nix tools ported to Windows and
|
||||
wrapped in a convenient installer. The msys package is all the various
|
||||
basic tools (shells, file utils, etc) and the msysDTK is extra
|
||||
developer tools other then the compiler.
|
||||
|
||||
You need in particular the Cygwin base, bison (see notes) flex, make
|
||||
and gperf. If you are compiling from CVS, you also need cvs, rcs and
|
||||
automake packages. You will also need tar and gunzip, but these are
|
||||
hard to not install. I recommend installing the "which" package as
|
||||
well. Beyond the basics, be sure to install these Cygwin packages:
|
||||
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
||||
self-installing packages. Install msys first, and then msysDTC. Most
|
||||
likely, you want to install them in c:/msys. (The msysDTK is installed
|
||||
in the same location, as it is an add-on.)
|
||||
|
||||
bison (*not* 1.875. See Notes.)
|
||||
flex
|
||||
ghostscript (makes the documentation)
|
||||
gperf
|
||||
gzip
|
||||
make
|
||||
strip
|
||||
tar (tar and gunzip for unpacking the source)
|
||||
unzip (For unpacking zip compressed packages.)
|
||||
which
|
||||
This install should be easy and reliable.
|
||||
|
||||
NOTES:
|
||||
bison-1.875 is broken, it generates invalid C/C++ code. You
|
||||
don't want that version for anything you do. If you have that
|
||||
version (use "bison -V" to check the version) then use the
|
||||
Cygwin setup program to get a different version. I've downgraded
|
||||
to 1.75 and couldn't be happier. In fact, a whole host of insane
|
||||
bison bugs can be avoided that way.
|
||||
|
||||
There is a mingw32 runtime package included in the Cygwin
|
||||
distribution. You do *not* need that, as you will be getting
|
||||
everything from the mingw32 distribution itself.
|
||||
|
||||
Other then the install of mingw32, most of the remaining steps are
|
||||
best done in a Cygwin window. When you installed Cygwin, a start menu
|
||||
entry was created to allow you to start up the Cygwin window. I'll use
|
||||
the string "$ " to represent a command prompt in this window, because
|
||||
that is the usual bash prompt.
|
||||
The installation will leave an "msys" icon on your desktop and in the
|
||||
mingw sub-menu of your Start menu. This icon brings up a shell window
|
||||
(a command line) that has paths all set up for executing msys and
|
||||
mingw commands. This is what you will want to use while executing
|
||||
commands below.
|
||||
|
||||
* Install Mingw32
|
||||
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found at the web page <http://www.mingw.org>. The Mingw-2.x.x version
|
||||
comes prepackaged in a convenient, Windows style, installer. I
|
||||
recommend you download this package instead of picking and choosing
|
||||
bits.
|
||||
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
|
||||
is a convenient remote installer. Download this program and run
|
||||
it. The installer will ask wich components you want to install. You
|
||||
need only the base C compiler and the C++ compiler. (You may install
|
||||
other languages if you wish.)
|
||||
|
||||
When I install Mingw32 (using the installer) I typically set a
|
||||
destination directory of d:\mingw-2.0.0 or the like. You will be using
|
||||
destination directory of d:\mingw or the like. You will be using
|
||||
that path later.
|
||||
|
||||
NOTES:
|
||||
|
|
@ -115,6 +104,10 @@ that path later.
|
|||
need Mingw32, even if you are using a precompiled binary. VPI
|
||||
modules only require Mingw32, and none of the other libraries.
|
||||
|
||||
Finally, as part of installing the mingw32 compilers, remember to add
|
||||
the mingw/bin directory to your path. You will need that to be able to
|
||||
find the compilers later.
|
||||
|
||||
* Install Mingw32 Packages
|
||||
|
||||
There is a collection of precompiled libraries and add-on packages
|
||||
|
|
@ -123,86 +116,94 @@ with simplified Windows installers, but they are pretty easy to
|
|||
install by hand. Icarus Verilog uses the readline-4.2 package from
|
||||
that collection.
|
||||
|
||||
Since I installed Mingw32 in d:\mingw-2.0.0, I also created a
|
||||
Mingw-packages directory called d:\mingw-packages. The install, then,
|
||||
Since I installed Mingw32 in c:\mingw, I also created a
|
||||
Mingw-packages directory called c:\mingw-packages. The install, then,
|
||||
is as easy as this:
|
||||
|
||||
<cygwin shell>
|
||||
$ cd d:/mingw-packages
|
||||
<msys shell>
|
||||
$ cd c:/mingw-packages
|
||||
$ unzip readline-4.2-20010727.zip
|
||||
[lots of inflating...]
|
||||
|
||||
There is no need to adjust your execution path for this package as we
|
||||
are only using a library out of here. However, do remember the
|
||||
directory name, as you will need it later.
|
||||
|
||||
Done. On to the next packages.
|
||||
|
||||
* Install GnuWin32 Packages
|
||||
|
||||
The GnuWin32 project is a collections of open source programs and
|
||||
libraries ported to Windows. These also work well with the Mingw
|
||||
compiler, and in fact Icarus Verilog uses a few libraries from this
|
||||
compiler, and in fact Icarus Verilog uses a few pieces from this
|
||||
collection.
|
||||
|
||||
You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||
|
||||
<http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.2-lib.zip
|
||||
bzip2-1.0.2-bin.zip
|
||||
zlib-1.1.4-lib.zip
|
||||
zlib-1.1.4-bin.zip
|
||||
bzip2-1.0.3.exe
|
||||
zlib-1.2.3.exe
|
||||
gperf-3.0.1.exe
|
||||
bison-2.1.exe
|
||||
flex-2.5.4a.exe
|
||||
|
||||
I suggest creating a common directory for holding all your gnuwin32
|
||||
packages. I use D:\gnuwin32.
|
||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||
has a "setup" link for each of these packages. Click the setup to
|
||||
download the installer for each of the desired programes, then execute
|
||||
the downloaded .exe files to invoke the installer. Install into the
|
||||
c:\gunwin32 directory.
|
||||
|
||||
After downloading these packages, put the .zip files in your gnuwin32
|
||||
directory and install them like so:
|
||||
NOTES:
|
||||
You need the binaries and the developer files, but you do not
|
||||
need the source to these packages. The installer gives you the
|
||||
choice.
|
||||
|
||||
<cygwin shell>
|
||||
$ cd d:/gnuwin32
|
||||
$ unzip bzip2-1.0.2-bin.zip
|
||||
[lots of inflating...]
|
||||
$ unzip bzip2-1.0.2-lib.zip
|
||||
[lots of inflating...]
|
||||
$ unzip zlib-1.1.4-bin.zip
|
||||
[lots of inflating...]
|
||||
$ unzip zlib-1.1.4-lib.zip
|
||||
[lots of inflating...]
|
||||
|
||||
Done.
|
||||
After you are done installing the gnuwin32 tools, you should add the
|
||||
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
|
||||
your Windows path. The msys shell will pick up your Windows path.
|
||||
|
||||
* Unpack Icarus Verilog source
|
||||
|
||||
Unpack the compressed tar file (.tar.gz) of the source with a command
|
||||
like this:
|
||||
|
||||
$ gunzip -d verilog-20030303.tar.gz | tar xvf -
|
||||
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
|
||||
|
||||
This will create a directory "verilog-20030303" that contains all the
|
||||
This will create a directory "verilog-xxxxxxxx" that contains all the
|
||||
source for Icarus Verilog. Descend into that directory, as that is
|
||||
where we will work from now on.
|
||||
|
||||
$ cd verilog-20030303
|
||||
$ cd verilog-xxxxxxxx
|
||||
|
||||
NOTE:
|
||||
NOTES:
|
||||
The exact name of the file will vary according to the
|
||||
snapshot. The 20030303 name is only an example.
|
||||
|
||||
* Select the mingw compilers
|
||||
Unpack the source into a directory that has no spaces. The
|
||||
makefiles included in the source get confused by white space in
|
||||
directory names.
|
||||
|
||||
In your cygwin window, if you type "which c++" you might get the
|
||||
response path "/usr/bin/c++" which is the cygwin compiler. This is not
|
||||
the one we want to use, however. Tell the shell where the mingw
|
||||
compilers are by setting the search path like so:
|
||||
* Preconfigure Icarus Verilog (Not normally needed)
|
||||
|
||||
$ PATH=/cygdrive/d/mingw-2.0.0/bin:$PATH
|
||||
Under certain cases, you may need to "preconfigure" the Icarus Verilog
|
||||
source tree. You should only need to do this if you are getting the
|
||||
Icarus Verilog source tree from CVS, or you are using an existing
|
||||
source tree that you've patched to cause configure.in files to change.
|
||||
|
||||
This assumes that you installed mingw in D:\mingw-2.0.0. The actual
|
||||
programs are in the bin directory under the root. After this command,
|
||||
check that you are now getting the right compilers with this "which"
|
||||
command:
|
||||
NOTE: If you are building from a fresh, bundled source tree that
|
||||
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
|
||||
the "Configure Icarus Verilog" step below.
|
||||
|
||||
$ which c++
|
||||
/cygdrive/d/mingw-2.0.0/bin/c++
|
||||
First, remove any autom4te.cache directories that may exist in your
|
||||
source tree. These can make a mess of autoconf runs. Then, generate
|
||||
configure scripts with this command:
|
||||
|
||||
Good!
|
||||
$ sh autoconf.sh
|
||||
|
||||
This script will run the "autoconf" command (part of the msysDTK) to
|
||||
generate all the necessary "configure" scripts. This will take a few
|
||||
minutes. This should go smoothly.
|
||||
|
||||
* Configure Icarus Verilog
|
||||
|
||||
|
|
@ -215,10 +216,10 @@ without white space.
|
|||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run these commands:
|
||||
|
||||
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include"
|
||||
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include"
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=d:/iverilog
|
||||
$ ./configure --prefix=c:/iverilog
|
||||
|
||||
NOTES:
|
||||
The CPPFLAGS and LDFLAGS variables tell configure where
|
||||
|
|
@ -267,10 +268,10 @@ directory you chose) and away you go.
|
|||
You may find that you need to put some of the prerequisite DLLs into
|
||||
the d:\iverilog\bin directory. These include:
|
||||
|
||||
d:\mingw-2.0.0\bin\mingw10.dll
|
||||
d:\mingw-packages\bin\libreadline.dll
|
||||
d:\gnuwin32\bin\bzip2.dll
|
||||
d:\gnuwin32\bin\zlib.dll
|
||||
c:\mingw\bin\mingw10.dll
|
||||
c:\mingw-packages\bin\libreadline.dll
|
||||
c:\gnuwin32\bin\bzip2.dll
|
||||
c:\gnuwin32\bin\zlib.dll
|
||||
|
||||
If you already have these in your Windows path (i.e. your system32
|
||||
directory) then you do not need to copy them into the iverilog
|
||||
|
|
@ -279,14 +280,14 @@ files.
|
|||
|
||||
* Running Icarus Verilog
|
||||
|
||||
Finally, put the D:\iverilog\bin directory in your Windows path, and
|
||||
Finally, put the C:\iverilog\bin directory in your Windows path, and
|
||||
you should be able to run the iverilog and vvp commands to your
|
||||
heart's content.
|
||||
|
||||
Currently, the iverilog.exe uses the path to itself to locate the
|
||||
libraries and modules associated with itself. In other words, if you
|
||||
execute the D:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the D:\iverilog directory and subdirectories below
|
||||
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the C:\iverilog directory and subdirectories below
|
||||
that. This means you can move the Icarus Verilog installation by
|
||||
simply moving the root directory and all its contents.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.18 2004/08/28 15:08:31 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.18.2.3 2006/05/02 02:00:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -45,6 +45,7 @@ NetAssign_::NetAssign_(NetNet*s)
|
|||
lwid_ = sig_->pin_count();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
|
|
@ -53,6 +54,7 @@ NetAssign_::NetAssign_(NetMemory*s)
|
|||
loff_ = 0;
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetVariable*s)
|
||||
|
|
@ -61,6 +63,7 @@ NetAssign_::NetAssign_(NetVariable*s)
|
|||
loff_ = 0;
|
||||
lwid_ = 0;
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
|
|
@ -71,6 +74,14 @@ NetAssign_::~NetAssign_()
|
|||
sig_->type(NetNet::WIRE);
|
||||
}
|
||||
|
||||
if (mem_) {
|
||||
NetNet*exp = mem_->reg_from_explode();
|
||||
if (exp && mem_lref_) {
|
||||
exp->decr_lref();
|
||||
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
|
||||
exp->type(NetNet::WIRE);
|
||||
}
|
||||
}
|
||||
assert( more == 0 );
|
||||
if (bmux_) delete bmux_;
|
||||
}
|
||||
|
|
@ -111,7 +122,10 @@ perm_string NetAssign_::name() const
|
|||
|
||||
NetNet* NetAssign_::sig() const
|
||||
{
|
||||
return sig_;
|
||||
if (mem_)
|
||||
return 0;
|
||||
else
|
||||
return sig_;
|
||||
}
|
||||
|
||||
NetMemory* NetAssign_::mem() const
|
||||
|
|
@ -124,6 +138,16 @@ NetVariable* NetAssign_::var() const
|
|||
return var_;
|
||||
}
|
||||
|
||||
void NetAssign_::incr_mem_lref()
|
||||
{
|
||||
if (! mem_lref_) {
|
||||
assert(mem_);
|
||||
NetNet*exp = mem_->reg_from_explode();
|
||||
assert(exp);
|
||||
exp->incr_lref();
|
||||
mem_lref_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
{
|
||||
|
|
@ -261,6 +285,15 @@ NetAssignNB::~NetAssignNB()
|
|||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.18.2.3 2006/05/02 02:00:15 steve
|
||||
* Fix uninitialized mem_lref_ member.
|
||||
*
|
||||
* Revision 1.18.2.2 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.18 2004/08/28 15:08:31 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.45 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.45.2.1 2006/10/04 00:34:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -279,7 +279,7 @@ void NetScope::run_defparams(Design*des)
|
|||
continue;
|
||||
}
|
||||
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val);
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val->dup_expr());
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< perm_name << " not found in "
|
||||
|
|
@ -618,6 +618,9 @@ void Design::delete_process(NetProcTop*top)
|
|||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.45.2.1 2006/10/04 00:34:45 steve
|
||||
* Fix a dangling reference to NetEParam objects in defparams.
|
||||
*
|
||||
* Revision 1.45 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
191
net_link.cc
191
net_link.cc
|
|
@ -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.14 2004/02/18 17:11:56 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.14.2.6 2006/08/23 04:09:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -40,30 +40,33 @@ void connect(Nexus*l, Link&r)
|
|||
if (l == r.nexus_)
|
||||
return;
|
||||
|
||||
|
||||
Nexus*tmp = r.nexus_;
|
||||
|
||||
while (Link*cur = tmp->list_) {
|
||||
tmp->list_ = cur->next_;
|
||||
cur->nexus_ = 0;
|
||||
cur->next_ = 0;
|
||||
cur->prev_ = 0;
|
||||
l->relink(cur);
|
||||
}
|
||||
|
||||
l->driven_ = Nexus::NO_GUESS;
|
||||
|
||||
assert(tmp->list_ == 0);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
void connect(Link&l, Link&r)
|
||||
{
|
||||
assert(&l != &r);
|
||||
connect(l.nexus_, r);
|
||||
if (r.is_linked() && !l.is_linked())
|
||||
connect(r.nexus_, l);
|
||||
else if (r.nexus_->list_len_ > l.nexus_->list_len_)
|
||||
connect(r.nexus_, l);
|
||||
else
|
||||
connect(l.nexus_, r);
|
||||
}
|
||||
|
||||
Link::Link()
|
||||
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
||||
inst_(0), next_(0), nexus_(0)
|
||||
inst_(0), next_(0), prev_(0), nexus_(0)
|
||||
{
|
||||
(new Nexus()) -> relink(this);
|
||||
}
|
||||
|
|
@ -215,6 +218,7 @@ Nexus::Nexus()
|
|||
{
|
||||
name_ = 0;
|
||||
list_ = 0;
|
||||
list_len_ = 0;
|
||||
driven_ = NO_GUESS;
|
||||
t_cookie_ = 0;
|
||||
}
|
||||
|
|
@ -241,6 +245,18 @@ verinum::V Nexus::get_init() const
|
|||
return verinum::Vz;
|
||||
}
|
||||
|
||||
int Nexus::is_driven() const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
|
|
@ -254,22 +270,32 @@ void Nexus::unlink(Link*that)
|
|||
driven_ = NO_GUESS;
|
||||
|
||||
assert(that);
|
||||
assert(that->nexus_ == this);
|
||||
if (list_ == that) {
|
||||
assert(that->prev_ == 0);
|
||||
// Move the second item the front of the list.
|
||||
list_ = that->next_;
|
||||
if (list_)
|
||||
list_->prev_ = 0;
|
||||
list_len_ -= 1;
|
||||
// Clear the pointers for the link.
|
||||
that->next_ = 0;
|
||||
that->prev_ = 0;
|
||||
that->nexus_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Link*cur = list_;
|
||||
while (cur->next_ != that) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
Link*cur = that->prev_;
|
||||
assert(cur->nexus_ == this);
|
||||
|
||||
cur->next_ = that->next_;
|
||||
if (cur->next_)
|
||||
cur->next_->prev_ = cur;
|
||||
that->nexus_ = 0;
|
||||
that->next_ = 0;
|
||||
that->prev_ = 0;
|
||||
list_len_ -= 1;
|
||||
}
|
||||
|
||||
void Nexus::relink(Link*that)
|
||||
|
|
@ -287,8 +313,13 @@ void Nexus::relink(Link*that)
|
|||
assert(that->nexus_ == 0);
|
||||
assert(that->next_ == 0);
|
||||
that->next_ = list_;
|
||||
that->prev_ = 0;
|
||||
if (that->next_)
|
||||
that->next_->prev_ = that;
|
||||
|
||||
that->nexus_ = this;
|
||||
list_ = that;
|
||||
list_len_ += 1;
|
||||
}
|
||||
|
||||
Link* Nexus::first_nlink()
|
||||
|
|
@ -360,8 +391,9 @@ const char* Nexus::name() const
|
|||
obj->name() << " pin " << pin << "(" <<
|
||||
lnk->get_name() << "<" << lnk->get_inst() << ">)"
|
||||
" type=" << typeid(*obj).name() << "?" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << sig->name();
|
||||
|
|
@ -378,6 +410,7 @@ const char* Nexus::name() const
|
|||
NexusSet::NexusSet()
|
||||
{
|
||||
items_ = 0;
|
||||
index_ = 0;
|
||||
nitems_ = 0;
|
||||
}
|
||||
|
||||
|
|
@ -386,8 +419,11 @@ NexusSet::~NexusSet()
|
|||
if (nitems_ > 0) {
|
||||
assert(items_ != 0);
|
||||
delete[] items_;
|
||||
assert(index_ != 0);
|
||||
delete[] index_;
|
||||
} else {
|
||||
assert(items_ == 0);
|
||||
assert(index_ == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -396,25 +432,44 @@ unsigned NexusSet::count() const
|
|||
return nitems_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the Nexus to the nexus set at the *end* of the array. This
|
||||
* preserves order, which is used in a few cases by the
|
||||
* synthesizer. But for efficiency, also create a sorted index.
|
||||
*/
|
||||
void NexusSet::add(Nexus*that)
|
||||
{
|
||||
/* Handle the special case that the set is empty. */
|
||||
if (nitems_ == 0) {
|
||||
assert(items_ == 0);
|
||||
assert(index_ == 0);
|
||||
items_ = (Nexus**)malloc(sizeof(Nexus*));
|
||||
items_[0] = that;
|
||||
index_ = (unsigned*)malloc(sizeof(unsigned));
|
||||
index_[0] = 0;
|
||||
nitems_ = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr < nitems_) && (items_[ptr] == that))
|
||||
if (ptr < nitems_ && items_[index_[ptr]] == that) {
|
||||
assert(items_[index_[ptr]] == that);
|
||||
return;
|
||||
}
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1)
|
||||
items_[idx] = items_[idx-1];
|
||||
items_ = (Nexus**) realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
index_ = (unsigned*)realloc(index_, (nitems_+1) * sizeof(unsigned));
|
||||
|
||||
items_[nitems_] = that;
|
||||
|
||||
unsigned dest = nitems_;
|
||||
for (unsigned idx = ptr ; idx < nitems_ ; idx += 1) {
|
||||
unsigned tmp = index_[idx];
|
||||
index_[idx] = dest;
|
||||
dest = tmp;
|
||||
}
|
||||
index_[nitems_] = dest;
|
||||
|
||||
items_[ptr] = that;
|
||||
nitems_ += 1;
|
||||
}
|
||||
|
||||
|
|
@ -430,20 +485,31 @@ void NexusSet::rem(Nexus*that)
|
|||
return;
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr >= nitems_) || (items_[ptr] != that))
|
||||
if (ptr >= nitems_ || items_[index_[ptr]] != that)
|
||||
return;
|
||||
|
||||
if (nitems_ == 1) {
|
||||
free(items_);
|
||||
free(index_);
|
||||
items_ = 0;
|
||||
index_ = 0;
|
||||
nitems_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
unsigned index_ptr = index_[ptr];
|
||||
for (unsigned idx = index_ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
items_[idx] = items_[idx+1];
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*));
|
||||
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
index_[idx] = index_[idx+1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < (nitems_-1) ; idx += 1)
|
||||
if (index_[idx] > index_ptr)
|
||||
index_[idx] -= 1;
|
||||
|
||||
items_ = (Nexus**) realloc(items_, (nitems_-1) * sizeof(Nexus*));
|
||||
index_ = (unsigned*)realloc(index_, (nitems_-1) * sizeof(unsigned));
|
||||
nitems_ -= 1;
|
||||
}
|
||||
|
||||
|
|
@ -459,16 +525,37 @@ Nexus* NexusSet::operator[] (unsigned idx) const
|
|||
return items_[idx];
|
||||
}
|
||||
|
||||
/*
|
||||
* This method uses binary search to locate the item in the list of
|
||||
* nexus pointers. If the item is in the set, then this method returns
|
||||
* the index where it exists in the *index* array. If the item is not
|
||||
* in the set, the index points to where in the array the item should go.
|
||||
*/
|
||||
unsigned NexusSet::bsearch_(Nexus*that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
if (items_[idx] < that)
|
||||
continue;
|
||||
|
||||
return idx;
|
||||
unsigned low = 0, hig = nitems_;
|
||||
|
||||
while (low < hig) {
|
||||
unsigned mid = (low + hig) / 2;
|
||||
if (mid == hig) mid -= 1;
|
||||
assert(mid >= low);
|
||||
assert(mid < hig);
|
||||
|
||||
if (items_[index_[mid]] == that) {
|
||||
return mid;
|
||||
|
||||
} else if (items_[index_[mid]] > that) {
|
||||
hig = mid;
|
||||
|
||||
} else {
|
||||
low = mid+1;
|
||||
}
|
||||
}
|
||||
|
||||
return nitems_;
|
||||
assert(low == hig);
|
||||
assert(low == nitems_ || items_[index_[low]] >= that);
|
||||
return low;
|
||||
}
|
||||
|
||||
bool NexusSet::contains(const NexusSet&that) const
|
||||
|
|
@ -477,7 +564,7 @@ bool NexusSet::contains(const NexusSet&that) const
|
|||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
return false;
|
||||
if (items_[where] != that[idx])
|
||||
if (items_[index_[where]] != that[idx])
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +577,7 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
continue;
|
||||
if (items_[where] == that[idx])
|
||||
if (items_[index_[where]] == that[idx])
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -499,6 +586,24 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.14.2.6 2006/08/23 04:09:14 steve
|
||||
* missing sig diagnostics.
|
||||
*
|
||||
* Revision 1.14.2.5 2006/08/15 03:41:24 steve
|
||||
* Improve performance of unlink of heavily connected nexa.
|
||||
*
|
||||
* Revision 1.14.2.4 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.14.2.3 2006/07/23 19:42:33 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.14.2.2 2006/01/27 02:05:46 steve
|
||||
* Speed up processing of connect when one side is empty.
|
||||
*
|
||||
* Revision 1.14.2.1 2005/09/25 23:30:31 steve
|
||||
* More predictable ordering of items in NexusSet.
|
||||
*
|
||||
* Revision 1.14 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
@ -523,35 +628,5 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
* Revision 1.7 2002/06/24 01:49:39 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.6 2002/04/21 04:59:08 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.5 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.4 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.3 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.2 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.1 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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.12 2004/09/04 04:24:15 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.12.2.1 2006/05/21 21:58:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -138,7 +138,8 @@ NexusSet* NetESFunc::nex_input()
|
|||
NexusSet* NetESignal::nex_input()
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
||||
assert(msi_ <= net_->pin_count());
|
||||
for (unsigned idx = lsi_ ; idx <= msi_ ; idx += 1)
|
||||
result->add(net_->pin(idx).nexus());
|
||||
|
||||
return result;
|
||||
|
|
@ -398,6 +399,9 @@ NexusSet* NetWhile::nex_input()
|
|||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.12.2.1 2006/05/21 21:58:47 steve
|
||||
* NetESignal input is only selected bits.
|
||||
*
|
||||
* Revision 1.12 2004/09/04 04:24:15 steve
|
||||
* PR1026: assignment statements can have sensitivities in the l-values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_output.cc,v 1.11 2004/09/16 03:17:33 steve Exp $"
|
||||
#ident "$Id: net_nex_output.cc,v 1.11.2.8 2006/08/08 02:17:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -47,10 +47,55 @@ void NetAssignBase::nex_output(NexusSet&out)
|
|||
{
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
if (NetNet*lsig = cur->sig()) {
|
||||
|
||||
if (cur->bmux()) {
|
||||
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) {
|
||||
out.add(lsig->pin(idx).nexus());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle l-value signals. We don't need to worry
|
||||
here about whether there is a bmux, because the
|
||||
synthesizer will detect that mux and create a
|
||||
decoder between the expression and the signal. */
|
||||
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
|
||||
unsigned off = cur->get_loff() + idx;
|
||||
out.add(lsig->pin(off).nexus());
|
||||
}
|
||||
|
||||
} else if (NetMemory*lmem = cur->mem()) {
|
||||
|
||||
/* Memories here are treated as a bunch of reg
|
||||
devices. Use the explode_to_reg method to get
|
||||
access to the FF version of the memory and use
|
||||
that in our l-value management. */
|
||||
NetNet*tmp = lmem->explode_to_reg();
|
||||
|
||||
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
|
||||
/* The address is constant, so simply
|
||||
connect to the right pins and we are
|
||||
done. */
|
||||
long adr_s = ae->value().as_long();
|
||||
unsigned adr = lmem->index_to_address(adr_s) * lmem->width();
|
||||
|
||||
if (adr >= lmem->count()*lmem->width()) {
|
||||
/* Skip assignments with constant
|
||||
addresses that are outside the
|
||||
range of memories. */
|
||||
} else {
|
||||
for (unsigned idx=0; idx<cur->lwidth(); idx += 1)
|
||||
out.add(tmp->pin(adr+idx).nexus());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Put all the bits of the memory into the
|
||||
set. The synthesis will generate a
|
||||
decoder to handle this. */
|
||||
for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1)
|
||||
out.add(tmp->pin(idx).nexus());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Quoting from netlist.h comments for class NetMemory:
|
||||
* "This is not a node because memory objects can only be
|
||||
|
|
@ -69,11 +114,11 @@ void NetBlock::nex_output(NexusSet&out)
|
|||
if (last_ == 0)
|
||||
return;
|
||||
|
||||
NetProc*cur = last_;
|
||||
NetProc*cur = last_->next_;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
cur->nex_output(out);
|
||||
} while (cur != last_);
|
||||
cur = cur->next_;
|
||||
} while (cur != last_->next_);
|
||||
}
|
||||
|
||||
void NetCase::nex_output(NexusSet&out)
|
||||
|
|
@ -122,6 +167,30 @@ void NetWhile::nex_output(NexusSet&out)
|
|||
|
||||
/*
|
||||
* $Log: net_nex_output.cc,v $
|
||||
* Revision 1.11.2.8 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.11.2.7 2006/06/02 23:42:48 steve
|
||||
* Compilation warnings.
|
||||
*
|
||||
* Revision 1.11.2.6 2006/06/01 03:01:48 steve
|
||||
* Handle condit clauses with unassigned outputs.
|
||||
*
|
||||
* Revision 1.11.2.5 2006/05/18 01:47:12 steve
|
||||
* Fix synthesis of l-value bit select in block.
|
||||
*
|
||||
* Revision 1.11.2.4 2006/05/05 01:56:36 steve
|
||||
* Handle memory assignments out of range during synthesis
|
||||
*
|
||||
* Revision 1.11.2.3 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.11 2004/09/16 03:17:33 steve
|
||||
* net_output handles l-value concatenations.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_scope.cc,v 1.33 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: net_scope.cc,v 1.33.2.1 2005/02/19 16:39:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -194,7 +194,7 @@ const NetFuncDef* NetScope::func_def() const
|
|||
void NetScope::set_module_name(perm_string n)
|
||||
{
|
||||
assert(type_ == MODULE);
|
||||
module_name_ = n; /* NOTE: n mus have been permallocated. */
|
||||
module_name_ = n; /* NOTE: n must have been permallocated. */
|
||||
}
|
||||
|
||||
perm_string NetScope::module_name() const
|
||||
|
|
@ -467,6 +467,9 @@ string NetScope::local_hsymbol()
|
|||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.33.2.1 2005/02/19 16:39:31 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.33 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
270
netlist.cc
270
netlist.cc
|
|
@ -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.226 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.226.2.7 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -229,7 +229,7 @@ NetNode::~NetNode()
|
|||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, npins), sig_next_(0), sig_prev_(0),
|
||||
type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
local_flag_(false), eref_count_(0), lref_count_(0), mref_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
|||
: NetObj(s, n, ((ms>ls)?ms-ls:ls-ms) + 1),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
local_flag_(false), eref_count_(0), lref_count_(0), mref_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
|
|
@ -322,6 +322,14 @@ NetNet::~NetNet()
|
|||
dump_net(cerr, 4);
|
||||
}
|
||||
assert(lref_count_ == 0);
|
||||
if (mref_ != 0) {
|
||||
cerr << get_line() << ": internal error: attempt to delete "
|
||||
<< "signal ``" << name() << "'' which has "
|
||||
<< "memory explode references." << endl;
|
||||
dump_net(cerr, 4);
|
||||
}
|
||||
assert(mref_ == 0);
|
||||
|
||||
if (scope())
|
||||
scope()->rem_signal(this);
|
||||
|
||||
|
|
@ -462,6 +470,23 @@ unsigned NetNet::get_refs() const
|
|||
return lref_count_ + eref_count_;
|
||||
}
|
||||
|
||||
void NetNet::mref(NetMemory*mem)
|
||||
{
|
||||
assert(mref_ == 0);
|
||||
assert(mem != 0);
|
||||
mref_ = mem;
|
||||
}
|
||||
|
||||
NetMemory*NetNet::mref()
|
||||
{
|
||||
return mref_;
|
||||
}
|
||||
|
||||
const NetMemory* NetNet::mref() const
|
||||
{
|
||||
return mref_;
|
||||
}
|
||||
|
||||
|
||||
NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
|
||||
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid)
|
||||
|
|
@ -533,6 +558,8 @@ const NetScope* NetProcTop::scope() const
|
|||
NetFF::NetFF(NetScope*s, perm_string n, unsigned wid)
|
||||
: NetNode(s, n, 8 + 2*wid)
|
||||
{
|
||||
demux_ = 0;
|
||||
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Clock().set_name(perm_string::literal("Clock"), 0);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
|
|
@ -684,6 +711,118 @@ const verinum& NetFF::sset_value() const
|
|||
return sset_value_;
|
||||
}
|
||||
|
||||
unsigned NetDecode::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned NetDecode::awidth() const
|
||||
{
|
||||
return pin_count();
|
||||
}
|
||||
|
||||
NetDemux::NetDemux(NetScope*s, perm_string name,
|
||||
unsigned bus_width, unsigned address_width, unsigned size)
|
||||
: NetNode(s, name, bus_width*2+address_width+bus_width/size)
|
||||
{
|
||||
width_ = bus_width;
|
||||
awidth_ = address_width;
|
||||
size_ = size;
|
||||
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
pin_Q(idx).set_dir(Link::OUTPUT);
|
||||
pin_Q(idx).set_name(perm_string::literal("Q"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
pin_Data(idx).set_dir(Link::INPUT);
|
||||
pin_Data(idx).set_name(perm_string::literal("Data"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < awidth_ ; idx += 1) {
|
||||
pin_Address(idx).set_dir(Link::INPUT);
|
||||
pin_Address(idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_/size_ ; idx += 1) {
|
||||
pin_WriteData(idx).set_dir(Link::INPUT);
|
||||
pin_WriteData(idx).set_name(perm_string::literal("Writedata"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetDemux::~NetDemux()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetDemux::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned NetDemux::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
unsigned NetDemux::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Q(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Q(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Data(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(width_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Data(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(width_+idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Address(unsigned idx)
|
||||
{
|
||||
assert(idx < awidth_);
|
||||
return pin(width_+width_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Address(unsigned idx) const
|
||||
{
|
||||
assert(idx < awidth_);
|
||||
return pin(width_+width_+idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_WriteData(unsigned idx)
|
||||
{
|
||||
assert(idx < width_/size_);
|
||||
return pin(width_+width_+awidth_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_WriteData(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_/size_);
|
||||
return pin(width_+width_+awidth_+idx);
|
||||
}
|
||||
|
||||
NetDecode* NetFF::get_demux()
|
||||
{
|
||||
return demux_;
|
||||
}
|
||||
|
||||
const NetDecode* NetFF::get_demux() const
|
||||
{
|
||||
return demux_;
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
|
|
@ -1060,6 +1199,40 @@ const Link& NetCompare::pin_DataB(unsigned idx) const
|
|||
return pin(8+width_+idx);
|
||||
}
|
||||
|
||||
NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem,
|
||||
unsigned awid, unsigned word_width)
|
||||
: NetNode(s, name, awid)
|
||||
{
|
||||
width_ = word_width;
|
||||
assert( mem->width() % width_ == 0 );
|
||||
|
||||
ff_ = mem;
|
||||
ff_->demux_ = this;
|
||||
make_pins_(awid);
|
||||
}
|
||||
|
||||
NetDecode::~NetDecode()
|
||||
{
|
||||
}
|
||||
|
||||
void NetDecode::make_pins_(unsigned awid)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < awid ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
Link& NetDecode::pin_Address(unsigned idx)
|
||||
{
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDecode::pin_Address(unsigned idx) const
|
||||
{
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(sc, n, wr+wa+wb),
|
||||
|
|
@ -1385,10 +1558,7 @@ const Link& NetMux::pin_Data(unsigned w, unsigned s) const
|
|||
return pin(2+width_+swidth_+s*width_+w);
|
||||
}
|
||||
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 3+2*mem->width()+awid),
|
||||
mem_(mem), awidth_(awid)
|
||||
void NetRamDq::make_pins_(unsigned wid)
|
||||
{
|
||||
pin(0).set_dir(Link::INPUT); pin(0).set_name(perm_string::literal("InClock"), 0);
|
||||
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("OutClock"), 0);
|
||||
|
|
@ -1399,39 +1569,49 @@ NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
|||
pin(3+idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
pin(3+awidth_+idx).set_dir(Link::INPUT);
|
||||
pin(3+awidth_+idx).set_name(perm_string::literal("Data"), idx);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
pin(3+awidth_+width()+idx).set_dir(Link::OUTPUT);
|
||||
pin(3+awidth_+width()+idx).set_name(perm_string::literal("Q"), idx);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
pin(3+awidth_+wid+idx).set_dir(Link::OUTPUT);
|
||||
pin(3+awidth_+wid+idx).set_name(perm_string::literal("Q"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 3+2*mem->width()+awid),
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
make_pins_(mem->width());
|
||||
next_ = mem_->ram_list_;
|
||||
mem_->ram_list_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::~NetRamDq()
|
||||
{
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
if (mem_) {
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetRamDq::width() const
|
||||
{
|
||||
return mem_->width();
|
||||
if (mem_) return mem_->width();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::awidth() const
|
||||
|
|
@ -1441,7 +1621,13 @@ unsigned NetRamDq::awidth() const
|
|||
|
||||
unsigned NetRamDq::size() const
|
||||
{
|
||||
return mem_->count();
|
||||
if (mem_) return mem_->count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetMemory* NetRamDq::mem()
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
const NetMemory* NetRamDq::mem() const
|
||||
|
|
@ -2003,6 +2189,7 @@ NetMemory::NetMemory(NetScope*sc, perm_string n, long w, long s, long e)
|
|||
: width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
|
||||
{
|
||||
name_ = n;
|
||||
explode_ = 0;
|
||||
scope_->add_memory(this);
|
||||
}
|
||||
|
||||
|
|
@ -2033,7 +2220,25 @@ unsigned NetMemory::index_to_address(long idx) const
|
|||
return idx - idxl_;
|
||||
}
|
||||
|
||||
NetNet* NetMemory::explode_to_reg()
|
||||
{
|
||||
if (explode_)
|
||||
return explode_;
|
||||
|
||||
explode_ = new NetNet(scope_, name_, NetNet::REG, count()*width_);
|
||||
//explode_->incr_lref();
|
||||
return explode_;
|
||||
}
|
||||
|
||||
NetNet* NetMemory::reg_from_explode()
|
||||
{
|
||||
return explode_;
|
||||
}
|
||||
|
||||
const NetNet* NetMemory::reg_from_explode() const
|
||||
{
|
||||
return explode_;
|
||||
}
|
||||
|
||||
NetEMemory* NetEMemory::dup_expr() const
|
||||
{
|
||||
|
|
@ -2281,6 +2486,27 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.226.2.7 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.226.2.6 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.226.2.5 2006/03/26 23:09:22 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.226.2.4 2006/03/16 05:40:18 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
* Revision 1.226.2.3 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.226.2.2 2006/02/19 00:11:32 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.226.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.226 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
319
netlist.h
319
netlist.h
|
|
@ -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.321 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.321.2.24 2006/11/26 01:54:05 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -48,6 +48,7 @@ class ostream;
|
|||
class Design;
|
||||
class Link;
|
||||
class Nexus;
|
||||
class NetMemory;
|
||||
class NetNode;
|
||||
class NetProc;
|
||||
class NetProcTop;
|
||||
|
|
@ -58,12 +59,22 @@ class NetEvProbe;
|
|||
class NetExpr;
|
||||
class NetESignal;
|
||||
class NetEVariable;
|
||||
class NetFF;
|
||||
class NetFuncDef;
|
||||
|
||||
class NetRamDq;
|
||||
class NetEvTrig;
|
||||
class NetEvWait;
|
||||
|
||||
struct target;
|
||||
struct functor_t;
|
||||
|
||||
struct sync_accounting_cell {
|
||||
NetProc*proc;
|
||||
NetFF*ff;
|
||||
unsigned pin;
|
||||
};
|
||||
|
||||
/* =========
|
||||
* A NetObj is anything that has any kind of behavior in the
|
||||
* netlist. Nodes can be gates, registers, etc. and are linked
|
||||
|
|
@ -215,7 +226,7 @@ class Link {
|
|||
unsigned inst_;
|
||||
|
||||
private:
|
||||
Link *next_;
|
||||
Link *next_, *prev_;
|
||||
Nexus*nexus_;
|
||||
|
||||
private: // not implemented
|
||||
|
|
@ -253,6 +264,9 @@ class Nexus {
|
|||
Link*first_nlink();
|
||||
const Link* first_nlink()const;
|
||||
|
||||
/* Return the number of drivers, or 0 if undriven. */
|
||||
int is_driven() const;
|
||||
|
||||
/* This method returns true if all the possible drivers of
|
||||
this nexus are constant. It will also return true if there
|
||||
are no drivers at all. */
|
||||
|
|
@ -267,6 +281,7 @@ class Nexus {
|
|||
|
||||
private:
|
||||
Link*list_;
|
||||
int list_len_;
|
||||
void unlink(Link*);
|
||||
void relink(Link*);
|
||||
|
||||
|
|
@ -307,6 +322,7 @@ class NexusSet {
|
|||
|
||||
private:
|
||||
Nexus**items_;
|
||||
unsigned*index_;
|
||||
unsigned nitems_;
|
||||
|
||||
unsigned bsearch_(Nexus*that) const;
|
||||
|
|
@ -424,6 +440,11 @@ class NetNet : public NetObj {
|
|||
|
||||
unsigned get_refs() const;
|
||||
|
||||
/* This may be and explode of a memory. */
|
||||
void mref(NetMemory*ref);
|
||||
NetMemory*mref();
|
||||
const NetMemory*mref() const;
|
||||
|
||||
virtual void dump_net(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
|
|
@ -448,6 +469,7 @@ class NetNet : public NetObj {
|
|||
bool local_flag_;
|
||||
unsigned eref_count_;
|
||||
unsigned lref_count_;
|
||||
NetMemory*mref_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -581,6 +603,87 @@ class NetCompare : public NetNode {
|
|||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
* A decoder takes an address input and activates (high) the single
|
||||
* Q bit that is addressed. This can be used, for example, to
|
||||
* generate an enable for a FF from an array of FFs.
|
||||
*/
|
||||
class NetDecode : public NetNode {
|
||||
|
||||
public:
|
||||
NetDecode(NetScope*s, perm_string name, NetFF*mem,
|
||||
unsigned awid, unsigned word_width);
|
||||
~NetDecode();
|
||||
|
||||
// This is the width of the word. The width of the NetFF mem
|
||||
// is an even multiple of this.
|
||||
unsigned width() const;
|
||||
// This is the width of the address. The address value for the
|
||||
// base of a word is the address * width().
|
||||
unsigned awidth() const;
|
||||
|
||||
const NetFF*ff() const;
|
||||
|
||||
Link& pin_Address(unsigned idx);
|
||||
|
||||
const Link& pin_Address(unsigned idx) const;
|
||||
const Link& pin_Q(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
NetFF* ff_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetDemux is similar to the NetDecode, except that it is
|
||||
* combinational. The inputs are an address, Data, and WriteData.
|
||||
* The Q output is the same as the Data input, except for the bit that
|
||||
* is addressed by the address input, which gets WriteData instead.
|
||||
*/
|
||||
class NetDemux : public NetNode {
|
||||
|
||||
public:
|
||||
NetDemux(NetScope*s, perm_string name,
|
||||
unsigned bus_width, unsigned address_width,
|
||||
unsigned size);
|
||||
~NetDemux();
|
||||
|
||||
// This is the width of the bus that passes through the
|
||||
// device. The address addresses into this width.
|
||||
unsigned width() const;
|
||||
// This is the width of the address. The address value for the
|
||||
// base of a word is the address * width().
|
||||
unsigned awidth() const;
|
||||
// This is the number of words in the width that can be
|
||||
// addressed. This implies (by division) the width of a word.
|
||||
unsigned size() const;
|
||||
|
||||
Link& pin_Address(unsigned idx);
|
||||
Link& pin_Data(unsigned idx);
|
||||
Link& pin_Q(unsigned idx);
|
||||
Link& pin_WriteData(unsigned idx);
|
||||
|
||||
const Link& pin_Address(unsigned idx) const;
|
||||
const Link& pin_Data(unsigned idx) const;
|
||||
const Link& pin_Q(unsigned idx) const;
|
||||
const Link& pin_WriteData(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_, awidth_, size_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned wid, unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a theoretical (though not necessarily
|
||||
* practical) integer divider gate. This is not to represent any real
|
||||
|
|
@ -703,10 +806,19 @@ class NetFF : public NetNode {
|
|||
void sset_value(const verinum&val);
|
||||
const verinum& sset_value() const;
|
||||
|
||||
NetDecode* get_demux();
|
||||
const NetDecode* get_demux() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
// If there is a demux associated with this gate, the demux_
|
||||
// member will point to the decoder.
|
||||
friend class NetDecode;
|
||||
NetDecode*demux_;
|
||||
|
||||
private:
|
||||
verinum aset_value_;
|
||||
verinum sset_value_;
|
||||
|
|
@ -735,6 +847,7 @@ class NetMemory {
|
|||
|
||||
// NetScope*scope();
|
||||
const NetScope*scope() const { return scope_; };
|
||||
NetScope*scope() { return scope_; };
|
||||
|
||||
// This is the number of memory positions.
|
||||
unsigned count() const;
|
||||
|
|
@ -744,6 +857,13 @@ class NetMemory {
|
|||
// that are not zero based.
|
||||
unsigned index_to_address(long idx) const;
|
||||
|
||||
// This method returns a NetNet::REG that has the same number
|
||||
// of bits as the memory as a whole. This is used to represent
|
||||
// memories that are synthesized to individual bits.
|
||||
NetNet* explode_to_reg();
|
||||
NetNet* reg_from_explode();
|
||||
const NetNet* reg_from_explode() const;
|
||||
|
||||
void dump(ostream&o, unsigned lm) const;
|
||||
|
||||
private:
|
||||
|
|
@ -753,12 +873,14 @@ class NetMemory {
|
|||
long idxl_;
|
||||
|
||||
friend class NetRamDq;
|
||||
NetRamDq* ram_list_;
|
||||
class NetRamDq* ram_list_;
|
||||
|
||||
friend class NetScope;
|
||||
NetMemory*snext_, *sprev_;
|
||||
NetScope*scope_;
|
||||
|
||||
NetNet*explode_;
|
||||
|
||||
private: // not implemented
|
||||
NetMemory(const NetMemory&);
|
||||
NetMemory& operator= (const NetMemory&);
|
||||
|
|
@ -878,6 +1000,8 @@ class NetRamDq : public NetNode {
|
|||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
|
||||
NetMemory*mem();
|
||||
const NetMemory*mem() const;
|
||||
|
||||
Link& pin_InClock();
|
||||
|
|
@ -908,11 +1032,15 @@ class NetRamDq : public NetNode {
|
|||
// that are ports to the attached memory.
|
||||
unsigned count_partners() const;
|
||||
|
||||
void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetRamDq*next_;
|
||||
unsigned awidth_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned wid);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1315,7 +1443,7 @@ class NetUDP : public NetNode {
|
|||
* linked into the netlist. However, elaborating a process may cause
|
||||
* special nodes to be created to handle things like events.
|
||||
*/
|
||||
class NetProc : public virtual LineInfo {
|
||||
class NetProc : public virtual LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
explicit NetProc();
|
||||
|
|
@ -1346,15 +1474,33 @@ class NetProc : public virtual LineInfo {
|
|||
// process. Most process types are not.
|
||||
virtual bool is_synchronous();
|
||||
|
||||
// synthesize as asynchronous logic, and return true.
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
// synthesize as asynchronous logic, and return true. The
|
||||
// sync_flag is used to tell the async synthesizer that the
|
||||
// output nex_map is ultimately connected to a DFF Q
|
||||
// output. This can affect how cycles are handled.
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
bool synth_async_noaccum(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
|
||||
// Synthesize synchronous logic, and return true. The nex_out
|
||||
// is where outputs are actually connected, and the nex_map
|
||||
// maps nexa to bit positions. The ff is the initial DFF that
|
||||
// was created to receive the Data inputs. The method *may*
|
||||
// delete that DFF in favor of multiple smaller devices, but
|
||||
// in that case it will set the ff argument to nil.
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
void dump_proc_attr(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
friend class NetBlock;
|
||||
|
|
@ -1432,6 +1578,8 @@ class NetAssign_ {
|
|||
// into a wire.
|
||||
void turn_sig_to_wire_on_release();
|
||||
|
||||
void incr_mem_lref();
|
||||
|
||||
// It is possible that l-values can have *inputs*, as well as
|
||||
// being outputs. For example foo[idx] = ... is the l-value
|
||||
// (NetAssign_ object) with a foo l-value and the input
|
||||
|
|
@ -1452,6 +1600,7 @@ class NetAssign_ {
|
|||
bool turn_sig_to_wire_on_release_;
|
||||
unsigned loff_;
|
||||
unsigned lwid_;
|
||||
bool mem_lref_;
|
||||
};
|
||||
|
||||
class NetAssignBase : public NetProc {
|
||||
|
|
@ -1482,13 +1631,24 @@ class NetAssignBase : public NetProc {
|
|||
// accounts for any grouping of NetAssign_ objects that might happen.
|
||||
unsigned lwidth() const;
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This dumps all the lval structures.
|
||||
void dump_lval(ostream&) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
bool synth_async_mem_sync_(Design*des, NetScope*scope,
|
||||
NetAssign_*cur, NetNet*rsig, unsigned&roff,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
private:
|
||||
NetAssign_*lval_;
|
||||
NetExpr *rval_;
|
||||
|
|
@ -1549,11 +1709,13 @@ class NetBlock : public NetProc {
|
|||
|
||||
|
||||
// synthesize as asynchronous logic, and return true.
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This version of emit_recurse scans all the statements of
|
||||
|
|
@ -1604,12 +1766,18 @@ class NetCase : public NetProc {
|
|||
virtual NexusSet* nex_input();
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
bool synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in,
|
||||
NetNet*esig, unsigned hot_items);
|
||||
private:
|
||||
|
||||
TYPE type_;
|
||||
|
|
@ -1686,17 +1854,26 @@ class NetCondit : public NetProc {
|
|||
virtual void nex_output(NexusSet&o);
|
||||
|
||||
bool is_asynchronous();
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual int match_proc(struct proc_match_t*);
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
int connect_set_clr_range_( struct sync_accounting_cell*nex_ff,
|
||||
unsigned bits, NetNet*rst,
|
||||
const verinum&val);
|
||||
int connect_enable_range_(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
unsigned bits, NetNet*ce);
|
||||
private:
|
||||
NetExpr* expr_;
|
||||
NetProc*if_;
|
||||
|
|
@ -1845,12 +2022,12 @@ class NetEvent : public LineInfo {
|
|||
NetEvProbe*probes_;
|
||||
|
||||
// Use these methods to list the triggers attached to me.
|
||||
NetEvTrig* trig_;
|
||||
class NetEvTrig* trig_;
|
||||
|
||||
// Use This member to count references by NetEvWait objects.
|
||||
unsigned waitref_;
|
||||
struct wcell_ {
|
||||
NetEvWait*obj;
|
||||
class NetEvWait*obj;
|
||||
struct wcell_*next;
|
||||
};
|
||||
struct wcell_ *wlist_;
|
||||
|
|
@ -1911,11 +2088,14 @@ class NetEvWait : public NetProc {
|
|||
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -2035,6 +2215,8 @@ class NetFuncDef {
|
|||
const NetNet*return_sig() const;
|
||||
const NetVariable*return_var() const;
|
||||
|
||||
NetNet* synthesize(Design*des, const svector<NetNet*>&inports_);
|
||||
|
||||
void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -2255,6 +2437,8 @@ class NetEUFunc : public NetExpr {
|
|||
virtual NetEUFunc*dup_expr() const;
|
||||
virtual NexusSet* nex_input();
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
NetScope*func_;
|
||||
NetESignal*result_sig_;
|
||||
|
|
@ -2309,6 +2493,10 @@ class NetWhile : public NetProc {
|
|||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
|
||||
|
||||
private:
|
||||
NetExpr* cond_;
|
||||
NetProc*proc_;
|
||||
|
|
@ -2523,7 +2711,7 @@ class NetEBComp : public NetEBinary {
|
|||
NetEConst*eval_eqeq_();
|
||||
NetEConst*eval_less_();
|
||||
NetEConst*eval_leeq_();
|
||||
NetEConst*eval_leeq_real_();
|
||||
NetEConst*eval_leeq_real_(bool gt_flag, bool include_eq_flag);
|
||||
NetEConst*eval_gt_();
|
||||
NetEConst*eval_gteq_();
|
||||
NetEConst*eval_neeq_();
|
||||
|
|
@ -2924,7 +3112,7 @@ class NetEMemory : public NetExpr {
|
|||
const NetExpr* index() const;
|
||||
|
||||
virtual bool set_width(unsigned);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
NetExpr* eval_tree();
|
||||
virtual NetEMemory*dup_expr() const;
|
||||
|
||||
|
|
@ -3004,6 +3192,7 @@ class NetEBitSel : public NetExpr {
|
|||
const NetNet* sig() const;
|
||||
|
||||
NetEBitSel* dup_expr() const;
|
||||
NetNet* synthesize(Design*des);
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
|
|
@ -3357,6 +3546,78 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.321.2.24 2006/11/26 01:54:05 steve
|
||||
* Add synthesis of user defined functions.
|
||||
*
|
||||
* Revision 1.321.2.23 2006/08/15 03:41:24 steve
|
||||
* Improve performance of unlink of heavily connected nexa.
|
||||
*
|
||||
* Revision 1.321.2.22 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.321.2.21 2006/07/23 19:42:33 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.321.2.20 2006/07/10 00:21:51 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.321.2.19 2006/06/23 03:49:46 steve
|
||||
* synthesis of NetCondit handles partial resets.
|
||||
*
|
||||
* Revision 1.321.2.18 2006/06/14 03:02:54 steve
|
||||
* synthesis for NetEBitSel.
|
||||
*
|
||||
* Revision 1.321.2.17 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.321.2.16 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.321.2.15 2006/04/10 03:43:39 steve
|
||||
* Exploded memories accessed by constant indices.
|
||||
*
|
||||
* Revision 1.321.2.14 2006/03/26 23:09:23 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.321.2.13 2006/03/18 18:43:21 steve
|
||||
* Better error messages when synthesis fails.
|
||||
*
|
||||
* Revision 1.321.2.12 2006/03/16 05:40:18 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
* Revision 1.321.2.11 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.321.2.10 2006/02/19 00:11:32 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.321.2.9 2006/01/21 21:42:31 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
* Revision 1.321.2.8 2006/01/18 01:23:24 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.321.2.7 2005/12/31 04:28:14 steve
|
||||
* Fix crashes caused bu synthesis of sqrt32.v.
|
||||
*
|
||||
* Revision 1.321.2.6 2005/12/14 00:54:29 steve
|
||||
* Account for sync vs async muxes.
|
||||
*
|
||||
* Revision 1.321.2.5 2005/11/13 22:28:48 steve
|
||||
* Allow for block output to be set throughout the statements.
|
||||
*
|
||||
* Revision 1.321.2.4 2005/09/09 02:17:08 steve
|
||||
* Evaluate magnitude compare with real operands.
|
||||
*
|
||||
* Revision 1.321.2.3 2005/08/22 01:00:41 steve
|
||||
* Add support for implicit defaults in case and conditions.
|
||||
*
|
||||
* Revision 1.321.2.2 2005/08/13 00:45:54 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.321.2.1 2005/07/06 22:41:34 steve
|
||||
* Fix compile errors with g++-4.
|
||||
*
|
||||
* Revision 1.321 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
25
netmisc.cc
25
netmisc.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $"
|
||||
#ident "$Id: netmisc.cc,v 1.8.2.1 2006/05/15 03:55:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -72,6 +72,26 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
|||
return res;
|
||||
}
|
||||
|
||||
NetNet* reduction_or(Design*des, NetNet*isig)
|
||||
{
|
||||
NetScope*scope = isig->scope();
|
||||
|
||||
NetLogic*olog = new NetLogic(scope, scope->local_symbol(),
|
||||
isig->pin_count()+1, NetLogic::OR);
|
||||
olog->set_line(*isig);
|
||||
des->add_node(olog);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
osig->set_line(*isig);
|
||||
|
||||
connect(olog->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < isig->pin_count() ; idx += 1)
|
||||
connect(olog->pin(1+idx), isig->pin(idx));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
{
|
||||
|
|
@ -90,6 +110,9 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
|||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.8.2.1 2006/05/15 03:55:23 steve
|
||||
* Fix synthesis of expressions with land of vectors.
|
||||
*
|
||||
* Revision 1.8 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
10
netmisc.h
10
netmisc.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.19 2004/03/07 20:04:11 steve Exp $"
|
||||
#ident "$Id: netmisc.h,v 1.19.2.1 2006/05/15 03:55:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -57,6 +57,11 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
|||
*/
|
||||
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
|
||||
/*
|
||||
* Calculate the reduction OR from the input signal.
|
||||
*/
|
||||
extern NetNet*reduction_or(Design*des, NetNet*sig);
|
||||
|
||||
/*
|
||||
* In some cases the lval is accessible as a pointer to the head of
|
||||
* a list of NetAssign_ objects. This function returns the width of
|
||||
|
|
@ -75,6 +80,9 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
|
|||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.19.2.1 2006/05/15 03:55:23 steve
|
||||
* Fix synthesis of expressions with land of vectors.
|
||||
*
|
||||
* Revision 1.19 2004/03/07 20:04:11 steve
|
||||
* MOre thorough use of elab_and_eval function.
|
||||
*
|
||||
|
|
|
|||
14
nodangle.cc
14
nodangle.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: nodangle.cc,v 1.21 2004/02/20 18:53:35 steve Exp $"
|
||||
#ident "$Id: nodangle.cc,v 1.21.2.2 2006/08/23 04:08:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -109,6 +109,9 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
|||
if (sig->get_refs() > 0)
|
||||
return;
|
||||
|
||||
if (sig->mref())
|
||||
return;
|
||||
|
||||
/* Cannot delete the ports of tasks or functions. There are
|
||||
too many places where they are referenced. */
|
||||
if ((sig->port_type() != NetNet::NOT_A_PORT)
|
||||
|
|
@ -160,6 +163,9 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
|||
if (cursig == 0)
|
||||
continue;
|
||||
|
||||
if (cursig == sig)
|
||||
continue;
|
||||
|
||||
if (cursig->local_flag())
|
||||
continue;
|
||||
|
||||
|
|
@ -205,6 +211,12 @@ void nodangle(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: nodangle.cc,v $
|
||||
* Revision 1.21.2.2 2006/08/23 04:08:55 steve
|
||||
* Do not count self as signifincant in nodangle.
|
||||
*
|
||||
* Revision 1.21.2.1 2006/03/16 05:40:19 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
* Revision 1.21 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
128
parse.y
128
parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.201 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.201.2.7 2007/03/23 23:22:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -287,7 +287,7 @@ attribute
|
|||
}
|
||||
| IDENTIFIER '=' expression
|
||||
{ PExpr*tmp = $3;
|
||||
if (!pform_expression_is_constant(tmp)) {
|
||||
if (tmp && !pform_expression_is_constant(tmp)) {
|
||||
yyerror(@3, "error: attribute value "
|
||||
"expression must be constant.");
|
||||
delete tmp;
|
||||
|
|
@ -308,17 +308,14 @@ attribute
|
|||
integers. This rule matches those declarations. The containing
|
||||
rule has presumably set up the scope. */
|
||||
block_item_decl
|
||||
: attribute_list_opt K_reg signed_opt range register_variable_list ';'
|
||||
{ pform_set_net_range($5, $4, $3);
|
||||
if ($1) delete $1;
|
||||
: K_reg signed_opt range register_variable_list ';'
|
||||
{ pform_set_net_range($4, $3, $2);
|
||||
}
|
||||
| attribute_list_opt K_reg signed_opt register_variable_list ';'
|
||||
{ pform_set_net_range($4, 0, $3);
|
||||
if ($1) delete $1;
|
||||
| K_reg signed_opt register_variable_list ';'
|
||||
{ pform_set_net_range($3, 0, $2);
|
||||
}
|
||||
| attribute_list_opt K_integer register_variable_list ';'
|
||||
{ pform_set_reg_integer($3);
|
||||
if ($1) delete $1;
|
||||
| K_integer register_variable_list ';'
|
||||
{ pform_set_reg_integer($2);
|
||||
}
|
||||
| K_time register_variable_list ';'
|
||||
{ pform_set_reg_time($2);
|
||||
|
|
@ -335,15 +332,13 @@ block_item_decl
|
|||
/* Recover from errors that happen within variable lists. Use the
|
||||
trailing semi-colon to resync the parser. */
|
||||
|
||||
| attribute_list_opt K_reg error ';'
|
||||
{ yyerror(@2, "error: syntax error in reg variable list.");
|
||||
| K_reg error ';'
|
||||
{ yyerror(@1, "error: syntax error in reg variable list.");
|
||||
yyerrok;
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| attribute_list_opt K_integer error ';'
|
||||
{ yyerror(@2, "error: syntax error in integer variable list.");
|
||||
| K_integer error ';'
|
||||
{ yyerror(@1, "error: syntax error in integer variable list.");
|
||||
yyerrok;
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| K_time error ';'
|
||||
{ yyerror(@1, "error: syntax error in time variable list.");
|
||||
|
|
@ -981,6 +976,14 @@ expr_primary
|
|||
{ PEConcat*tmp = new PEConcat(*$2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
for (unsigned idx = 0 ; idx < (*$2).count() ; idx += 1) {
|
||||
PExpr*ex = (*$2)[idx];
|
||||
if (ex == 0) {
|
||||
yyerror(@1, "error: Null arguments not allowed"
|
||||
" in repeat expressions.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -990,7 +993,6 @@ expr_primary
|
|||
yyerror(@2, "error: Repeat expression "
|
||||
"must be constant.");
|
||||
delete rep;
|
||||
delete $2;
|
||||
rep = 0;
|
||||
}
|
||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||
|
|
@ -1028,6 +1030,14 @@ function_item
|
|||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have output ports.");
|
||||
}
|
||||
| K_output K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have output ports.");
|
||||
}
|
||||
| K_inout range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, false,
|
||||
|
|
@ -1036,7 +1046,15 @@ function_item
|
|||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have inout ports.");
|
||||
}
|
||||
| block_item_decl
|
||||
| K_inout K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have inout ports.");
|
||||
}
|
||||
| attribute_list_opt block_item_decl
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
|
|
@ -1583,7 +1601,7 @@ module_item
|
|||
/* block_item_decl rule is shared with task blocks and named
|
||||
begin/end. */
|
||||
|
||||
| block_item_decl
|
||||
| attribute_list_opt block_item_decl
|
||||
|
||||
/* */
|
||||
|
||||
|
|
@ -2266,7 +2284,7 @@ specify_item
|
|||
{
|
||||
}
|
||||
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Speriod '(' spec_reference_event ',' delay_value
|
||||
|
|
@ -2274,11 +2292,11 @@ specify_item
|
|||
{ delete $5;
|
||||
}
|
||||
| K_Srecovery '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Ssetup '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Ssetuphold '(' spec_reference_event ',' spec_reference_event
|
||||
|
|
@ -2296,7 +2314,7 @@ specify_item
|
|||
{ delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| K_Swidth '(' spec_reference_event ',' expression ')' ';'
|
||||
| K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
|
||||
{ delete $5;
|
||||
}
|
||||
;
|
||||
|
|
@ -2458,7 +2476,10 @@ spec_notifier
|
|||
| spec_notifier ','
|
||||
{ }
|
||||
| spec_notifier ',' identifier
|
||||
{ delete $3;
|
||||
{ delete $3; }
|
||||
| spec_notifier ',' identifier '[' expr_primary ']'
|
||||
{ delete $3;
|
||||
delete $5;
|
||||
}
|
||||
| IDENTIFIER
|
||||
{ delete $1; }
|
||||
|
|
@ -2541,9 +2562,9 @@ statement
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_begin error K_end
|
||||
/* | K_begin error K_end
|
||||
{ yyerrok; }
|
||||
|
||||
*/
|
||||
/* fork-join blocks are very similar to begin-end blocks. In fact,
|
||||
from the parser's perspective there is no real difference. All we
|
||||
need to do is remember that this is a parallel block so that the
|
||||
|
|
@ -2690,28 +2711,34 @@ statement
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| event_control statement_opt
|
||||
| event_control attribute_list_opt statement_opt
|
||||
{ PEventStatement*tmp = $1;
|
||||
if (tmp == 0) {
|
||||
yyerror(@1, "error: Invalid event control.");
|
||||
$$ = 0;
|
||||
} else {
|
||||
tmp->set_statement($2);
|
||||
pform_attach_attributes($3, $2);
|
||||
tmp->set_statement($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
if ($2) delete $2;
|
||||
}
|
||||
| '@' '*' statement_opt
|
||||
| '@' '*' attribute_list_opt statement_opt
|
||||
{ PEventStatement*tmp = new PEventStatement;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->set_statement($3);
|
||||
pform_attach_attributes($4, $3);
|
||||
tmp->set_statement($4);
|
||||
if ($3) delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '@' '(' '*' ')' statement_opt
|
||||
| '@' '(' '*' ')' attribute_list_opt statement_opt
|
||||
{ PEventStatement*tmp = new PEventStatement;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->set_statement($5);
|
||||
pform_attach_attributes($6, $5);
|
||||
tmp->set_statement($6);
|
||||
if ($5) delete $5;
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue '=' expression ';'
|
||||
|
|
@ -2820,14 +2847,18 @@ statement
|
|||
;
|
||||
|
||||
statement_list
|
||||
: statement_list statement
|
||||
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2);
|
||||
: statement_list attribute_list_opt statement
|
||||
{ pform_attach_attributes($3, $2);
|
||||
svector<Statement*>*tmp = new svector<Statement*>(*$1, $3);
|
||||
delete $1;
|
||||
if ($2) delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| statement
|
||||
{ svector<Statement*>*tmp = new svector<Statement*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
| attribute_list_opt statement
|
||||
{ pform_attach_attributes($2, $1);
|
||||
svector<Statement*>*tmp = new svector<Statement*>(1);
|
||||
(*tmp)[0] = $2;
|
||||
if ($1) delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -2848,6 +2879,13 @@ task_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_input K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT, false,
|
||||
|
|
@ -2855,6 +2893,13 @@ task_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT, false,
|
||||
|
|
@ -2862,6 +2907,13 @@ task_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_item_list
|
||||
|
|
|
|||
11
parse_api.h
11
parse_api.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse_api.h,v 1.3 2004/02/18 17:11:57 steve Exp $"
|
||||
#ident "$Id: parse_api.h,v 1.3.2.1 2005/08/13 00:45:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -35,8 +35,8 @@ class PUdp;
|
|||
* Verilog source into pform for elaboration. The parser adds modules
|
||||
* to these maps as it compiles modules in the verilog source.
|
||||
*/
|
||||
extern map<perm_string,Module*> pform_modules;
|
||||
extern map<perm_string,PUdp*> pform_primitives;
|
||||
extern std::map<perm_string,Module*> pform_modules;
|
||||
extern std::map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
/*
|
||||
* This code actually invokes the parser to make modules. The first
|
||||
|
|
@ -47,10 +47,13 @@ extern map<perm_string,PUdp*> pform_primitives;
|
|||
*/
|
||||
extern int pform_parse(const char*path, FILE*file =0);
|
||||
|
||||
extern string vl_file;
|
||||
extern std::string vl_file;
|
||||
|
||||
/*
|
||||
* $Log: parse_api.h,v $
|
||||
* Revision 1.3.2.1 2005/08/13 00:45:54 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.3 2004/02/18 17:11:57 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
18
pform.cc
18
pform.cc
|
|
@ -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.129 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.129.2.1 2006/07/10 00:21:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -203,6 +203,19 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
|||
return res;
|
||||
}
|
||||
|
||||
void pform_attach_attributes(Statement*obj, svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
if (obj == 0)
|
||||
return;
|
||||
if (attr == 0)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
||||
named_pexpr_t*tmp = (*attr)[idx];
|
||||
obj->attributes[tmp->name] = tmp->parm;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
|
|
@ -1597,6 +1610,9 @@ int pform_parse(const char*path, FILE*file)
|
|||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.129.2.1 2006/07/10 00:21:53 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.129 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
7
pform.h
7
pform.h
|
|
@ -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.81 2004/08/26 04:02:04 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.81.2.1 2006/07/10 00:21:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -219,6 +219,8 @@ extern void pform_set_attrib(perm_string name, perm_string key,
|
|||
extern void pform_set_type_attrib(perm_string name, const string&key,
|
||||
char*value);
|
||||
|
||||
extern void pform_attach_attributes(Statement*obj, svector<named_pexpr_t*>*attr);
|
||||
|
||||
extern void pform_set_parameter(perm_string name,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
|
|
@ -298,6 +300,9 @@ extern void pform_dump(ostream&out, Module*mod);
|
|||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.81.2.1 2006/07/10 00:21:53 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.81 2004/08/26 04:02:04 steve
|
||||
* Add support for localparam ranges.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.88 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.88.2.1 2006/07/10 00:21:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -418,6 +418,19 @@ void Statement::dump(ostream&out, unsigned ind) const
|
|||
out << setw(ind) << "";
|
||||
out << "/* " << get_line() << ": " << typeid(*this).name()
|
||||
<< " */ ;" << endl;
|
||||
dump_attributes(out, ind+2);
|
||||
}
|
||||
|
||||
void Statement::dump_attributes(ostream&out, unsigned ind) const
|
||||
{
|
||||
for (map<perm_string,PExpr*>::const_iterator idx = attributes.begin()
|
||||
; idx != attributes.end()
|
||||
; idx ++) {
|
||||
out << setw(ind) << "" << "(* " << (*idx).first;
|
||||
if ((*idx).second)
|
||||
out << " = " << *(*idx).second;
|
||||
out << " *)" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PAssign::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -487,6 +500,8 @@ void PCase::dump(ostream&out, unsigned ind) const
|
|||
}
|
||||
out << " (" << *expr_ << ") /* " << get_line() << " */" << endl;
|
||||
|
||||
dump_attributes(out, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
PCase::Item*cur = (*items_)[idx];
|
||||
|
||||
|
|
@ -909,6 +924,9 @@ void PUdp::dump(ostream&out) const
|
|||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.88.2.1 2006/07/10 00:21:54 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.88 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
14
set_width.cc
14
set_width.cc
|
|
@ -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.34 2003/08/28 04:11:19 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.34.2.1 2005/03/05 01:36:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -167,12 +167,13 @@ bool NetEBDiv::set_width(unsigned w)
|
|||
return w == expr_width();
|
||||
}
|
||||
|
||||
/*
|
||||
* The logical binary operators do not care what the widths of their
|
||||
* operands are, the output is always 1 bit. The operands are
|
||||
* self-determined, so a set_width is stopped here.
|
||||
*/
|
||||
bool NetEBLogic::set_width(unsigned w)
|
||||
{
|
||||
bool flag;
|
||||
flag = left_->set_width(right_->expr_width());
|
||||
if (!flag)
|
||||
flag = right_->set_width(left_->expr_width());
|
||||
return (w == 1);
|
||||
}
|
||||
|
||||
|
|
@ -411,6 +412,9 @@ bool NetEUReduce::set_width(unsigned w)
|
|||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.34.2.1 2005/03/05 01:36:16 steve
|
||||
* Fix set_width to allow binary logical operands to be self determined.
|
||||
*
|
||||
* Revision 1.34 2003/08/28 04:11:19 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# $Id: README-solaris_pkg.txt,v 1.2 2004/10/04 01:10:56 steve Exp $
|
||||
# $Id: README-solaris_pkg.txt,v 1.2.2.1 2007/02/26 19:51:39 steve Exp $
|
||||
|
||||
Notes about the solaris package.
|
||||
|
||||
I. Installing a prebuild solaris package
|
||||
I. Installing a prebuilt solaris package
|
||||
-----------------------------------------
|
||||
|
||||
To install the solaris package do the following as root on your machine:
|
||||
|
|
@ -24,10 +24,10 @@ To install the solaris package do the following as root on your machine:
|
|||
this will install the package. The package will be registered under the
|
||||
name "IVLver"
|
||||
|
||||
II. Deinstalling the solaris package
|
||||
II. Uninstalling the solaris package
|
||||
-------------------------------------
|
||||
|
||||
To deinstall an installed solaris package do the following as root on your machine:
|
||||
To uninstall an installed solaris package do the following as root on your machine:
|
||||
|
||||
pkgrm IVLver
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
PKG="IVLver"
|
||||
NAME="verilog"
|
||||
ARCH="sparc"
|
||||
VERSION="0.7"
|
||||
VERSION="0.8"
|
||||
CATEGORY="application"
|
||||
VENDOR="Icarus.com"
|
||||
EMAIL="steve@icarus.com"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ 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/_pli_types.h 0644 bin bin
|
||||
f none include/acc_user.h 0644 bin bin
|
||||
f none include/ivl_target.h 0644 bin bin
|
||||
f none include/veriuser.h 0644 bin bin
|
||||
|
|
@ -11,12 +12,21 @@ f none include/vpi_user.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
|
||||
f none lib/ivl/fpga.conf 0644 bin bin
|
||||
f none lib/ivl/fpga-s.conf 0644 bin bin
|
||||
f none lib/ivl/iverilog.conf 0644 bin bin
|
||||
f none lib/ivl/ivl 0755 bin bin
|
||||
f none lib/ivl/ivlpp 0755 bin bin
|
||||
f none lib/ivl/null.tgt 0644 bin bin
|
||||
f none lib/ivl/null.conf 0644 bin bin
|
||||
f none lib/ivl/null-s.conf 0644 bin bin
|
||||
f none lib/ivl/system.vpi 0644 bin bin
|
||||
f none lib/ivl/system.sft 0644 bin bin
|
||||
f none lib/ivl/vvp.tgt 0644 bin bin
|
||||
f none lib/ivl/vvp.conf 0644 bin bin
|
||||
f none lib/ivl/vvp-s.conf 0644 bin bin
|
||||
f none lib/ivl/xnf.conf 0644 bin bin
|
||||
f none lib/ivl/xnf-s.conf 0644 bin bin
|
||||
f none lib/libveriuser.a 0644 bin bin
|
||||
f none lib/libvpi.a 0644 bin bin
|
||||
d none man 0755 bin bin
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: svector.h,v 1.9 2003/07/23 02:35:44 steve Exp $"
|
||||
#ident "$Id: svector.h,v 1.9.2.1 2005/06/14 15:33:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -101,14 +101,17 @@ template <class TYPE> class svector {
|
|||
* Override the implementation of the above template for the string
|
||||
* type parameter. The initialization to nil works different here.
|
||||
*/
|
||||
inline svector<string>::svector<string>(unsigned size)
|
||||
: nitems_(size), items_(new string[size])
|
||||
template <> inline svector<std::string>::svector(unsigned size)
|
||||
: nitems_(size), items_(new std::string[size])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: svector.h,v $
|
||||
* Revision 1.9.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.9 2003/07/23 02:35:44 steve
|
||||
* Inline the svector<string> constructor.
|
||||
*
|
||||
|
|
|
|||
90
t-dll-api.cc
90
t-dll-api.cc
|
|
@ -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.108 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.108.2.5 2006/04/16 19:26:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -620,6 +620,19 @@ extern "C" const char* ivl_udp_name(ivl_udp_t net)
|
|||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_attr_cnt(ivl_lpm_t net)
|
||||
{
|
||||
return net->nattr;
|
||||
}
|
||||
|
||||
extern "C" ivl_attribute_t ivl_lpm_attr_val(ivl_lpm_t net, unsigned idx)
|
||||
{
|
||||
if (idx >= net->nattr)
|
||||
return 0;
|
||||
else
|
||||
return net->attr + idx;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_lpm_basename(ivl_lpm_t net)
|
||||
{
|
||||
return net->name;
|
||||
|
|
@ -752,6 +765,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.a[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width);
|
||||
return net->u_.demux.d[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
|
|
@ -788,6 +805,10 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.b[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width/net->u_.demux.size);
|
||||
return net->u_.demux.bit_in[idx];
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -813,6 +834,22 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
|
|||
return net->u_.ufunc.pins[base+idx];
|
||||
}
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
if (net->u_.ff.a.mem == 0) {
|
||||
// This is an exploded RAM, so we use sdx and idx
|
||||
// to address a nexa into the exploded ram.
|
||||
if (sdx >= net->u_.ff.scnt)
|
||||
return 0;
|
||||
if (idx >= net->u_.ff.width)
|
||||
return 0;
|
||||
unsigned adr = sdx * net->u_.ff.width + idx;
|
||||
return net->u_.ff.d.pins[adr];
|
||||
|
||||
} else {
|
||||
// Normal RAM port does not have data2 nexa
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -833,6 +870,18 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.a.decode;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the hierarchical name for the LPM device. The
|
||||
* name needs to be built up from the scope name and the lpm base
|
||||
|
|
@ -898,6 +947,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.mux.q.pins[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width);
|
||||
return net->u_.demux.q[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
|
|
@ -929,6 +982,7 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.s.pins[idx];
|
||||
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.swid);
|
||||
if (net->u_.mux.swid == 1)
|
||||
|
|
@ -936,6 +990,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.mux.s.pins[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.awid);
|
||||
return net->u_.demux.a[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.select);
|
||||
|
|
@ -952,8 +1010,11 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
|||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.swid;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.awid;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.select;
|
||||
|
|
@ -970,6 +1031,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_MUX:
|
||||
case IVL_LPM_DEMUX:
|
||||
return 0;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
|
|
@ -984,7 +1046,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.signed_flag;
|
||||
return 0;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
default:
|
||||
|
|
@ -996,8 +1058,12 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.size;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.size;
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.scnt;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.ports - 1;
|
||||
default:
|
||||
|
|
@ -1018,8 +1084,11 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
|||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.width;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.width;
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.width;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
|
|
@ -1046,7 +1115,7 @@ extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.mem;
|
||||
return net->u_.ff.a.mem;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1935,6 +2004,21 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.108.2.5 2006/04/16 19:26:40 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.108.2.4 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.108.2.3 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.108.2.2 2006/02/25 05:03:29 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.108.2.1 2006/02/19 00:11:33 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.108 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.39 2004/06/17 16:06:19 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.39.2.2 2006/09/15 23:56:05 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -222,12 +222,73 @@ void dll_target::expr_memory(const NetEMemory*net)
|
|||
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
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());
|
||||
cur->u_.memory_.idx_ = expr_;
|
||||
const NetMemory*mem = net->memory();
|
||||
|
||||
if (const NetNet*reg = mem->reg_from_explode()) {
|
||||
|
||||
if (expr_ == 0) {
|
||||
// If there is no index expression for the
|
||||
// exploded memory, then replace it with the
|
||||
// entire exploded reg.
|
||||
cur->type_ = IVL_EX_SIGNAL;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= reg->pin_count();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.signal_.sig = find_signal(des_, reg);
|
||||
cur->u_.signal_.lsi = 0;
|
||||
cur->u_.signal_.msi = cur->width_ - 1;
|
||||
|
||||
} else {
|
||||
cur->type_ = IVL_EX_SELECT;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_ = net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
// Create an expression form of the exploded
|
||||
// memory. This is what the select will apply to.
|
||||
ivl_expr_t sig = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
sig->type_ = IVL_EX_SIGNAL;
|
||||
sig->value_ = IVL_VT_VECTOR;
|
||||
sig->width_ = reg->pin_count();
|
||||
sig->signed_ = 0;
|
||||
sig->u_.signal_.sig = find_signal(des_, reg);
|
||||
assert(sig->u_.signal_.sig);
|
||||
sig->u_.signal_.lsi = 0;
|
||||
sig->u_.signal_.msi = reg->pin_count()-1;
|
||||
cur->u_.binary_.lef_ = sig;
|
||||
|
||||
// Create an expression of the address calculation.
|
||||
cur->u_.binary_.rig_ = expr_;
|
||||
|
||||
if (cur->width_ > 1) {
|
||||
ivl_expr_t mul = (ivl_expr_t)calloc(2, sizeof(struct ivl_expr_s));
|
||||
ivl_expr_t fac = mul+1;
|
||||
|
||||
fac->type_ = IVL_EX_ULONG;
|
||||
fac->value_ = IVL_VT_VECTOR;
|
||||
fac->width_ = 8*sizeof(cur->width_);
|
||||
fac->signed_= 0;
|
||||
fac->u_.ulong_.value = cur->width_;
|
||||
|
||||
mul->type_ = IVL_EX_BINARY;
|
||||
mul->value_ = IVL_VT_VECTOR;
|
||||
mul->width_ = fac->width_;
|
||||
mul->signed_= 0;
|
||||
mul->u_.binary_.op_ = '*';
|
||||
mul->u_.binary_.lef_ = cur->u_.binary_.rig_;
|
||||
mul->u_.binary_.rig_ = fac;
|
||||
cur->u_.binary_.rig_ = mul;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
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());
|
||||
cur->u_.memory_.idx_ = expr_;
|
||||
}
|
||||
|
||||
expr_ = cur;
|
||||
}
|
||||
|
|
@ -604,6 +665,12 @@ void dll_target::expr_variable(const NetEVariable*net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.39.2.2 2006/09/15 23:56:05 steve
|
||||
* Special handling of exploded memory arguments.
|
||||
*
|
||||
* Revision 1.39.2.1 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.39 2004/06/17 16:06:19 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
|
|
|||
220
t-dll.cc
220
t-dll.cc
|
|
@ -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.131 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.131.2.8 2006/07/23 19:42:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -940,6 +940,8 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
|||
obj->delay[1] = net->fall_time();
|
||||
obj->delay[2] = net->decay_time();
|
||||
|
||||
logic_attributes(obj,net);
|
||||
|
||||
scope_add_logic(scope, obj);
|
||||
}
|
||||
|
||||
|
|
@ -965,6 +967,8 @@ bool dll_target::net_function(const NetUserFunc*net)
|
|||
obj->type = IVL_LPM_UFUNC;
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(obj->scope);
|
||||
|
||||
/* Get the definition of the function and save it. */
|
||||
|
|
@ -1104,9 +1108,11 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
obj->type = IVL_LPM_SUB;
|
||||
else
|
||||
obj->type = IVL_LPM_ADD;
|
||||
obj->name = net->name(); // NetAddSub names are permallocated.
|
||||
obj->name = net->name(); // NetAddSub names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.arith.signed_flag = 0;
|
||||
|
|
@ -1176,6 +1182,8 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_SHIFTL;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1243,6 +1251,8 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
void dll_target::lpm_compare(const NetCompare*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->name = net->name(); // NetCompare names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
|
|
@ -1357,6 +1367,8 @@ void dll_target::lpm_divide(const NetDivide*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DIVIDE;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1427,6 +1439,8 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_MOD;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1489,16 +1503,131 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_decode(const NetDecode*net)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net)
|
||||
{
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DECODE;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
|
||||
obj->u_.mux.swid = net->awidth();
|
||||
obj->u_.mux.size = 0;
|
||||
obj->u_.mux.width = net->width();
|
||||
obj->u_.mux.d = 0;
|
||||
|
||||
if (obj->u_.mux.swid > 1) {
|
||||
obj->u_.mux.s.pins = new ivl_nexus_t[obj->u_.mux.swid];
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->u_.mux.swid ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Address(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s.pins[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
} else {
|
||||
assert(obj->u_.mux.swid == 1);
|
||||
const Nexus*nex = net->pin_Address(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool dll_target::lpm_demux(const NetDemux*net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned width = net->width();
|
||||
unsigned awid = net->awidth();
|
||||
unsigned size = net->size();
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DEMUX;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.demux.width = width;
|
||||
obj->u_.demux.awid = awid;
|
||||
obj->u_.demux.size = net->size();
|
||||
|
||||
ivl_nexus_t*tmp = new ivl_nexus_t [2*width + awid + width/size];
|
||||
obj->u_.demux.q = tmp;
|
||||
obj->u_.demux.d = tmp + width;
|
||||
obj->u_.demux.a = tmp + 2*width;
|
||||
obj->u_.demux.bit_in = tmp + 2*width + awid;
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Q(idx).nexus();
|
||||
obj->u_.demux.q[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
|
||||
/* It is possible, but unlikely, that the Q is unused. */
|
||||
if (obj->u_.demux.q[idx])
|
||||
nexus_lpm_add(obj->u_.demux.q[idx], obj, idx,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Data(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.d[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.d[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < awid ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Address(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.a[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.a[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width/size ; idx += 1) {
|
||||
const Nexus*nex = net->pin_WriteData(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.bit_in[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.bit_in[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
obj->nattr = net->attr_cnt();
|
||||
obj->attr = fill_in_attributes(net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dll_target::lpm_ff(const NetFF*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_FF;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->u_.ff.a.decode = lpm_decode_ff_(net->get_demux());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
|
||||
obj->nattr = net->attr_cnt();
|
||||
obj->attr = fill_in_attributes(net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1607,16 +1736,23 @@ void dll_target::lpm_ff(const NetFF*net)
|
|||
|
||||
void dll_target::lpm_ram_dq(const NetRamDq*net)
|
||||
{
|
||||
ivl_memory_t mem = find_memory(des_, net->mem());
|
||||
assert(mem);
|
||||
|
||||
const NetNet*ereg = net->mem()->reg_from_explode();
|
||||
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_RAM;
|
||||
obj->name = net->name();
|
||||
obj->u_.ff.mem = find_memory(des_, net->mem());
|
||||
assert(obj->u_.ff.mem);
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->u_.ff.a.mem = ereg? 0 : mem;
|
||||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
obj->u_.ff.swid = net->awidth();
|
||||
obj->u_.ff.scnt = net->mem()->count();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
|
|
@ -1626,6 +1762,7 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
|||
// the clock input.
|
||||
|
||||
bool has_write_port = net->pin_InClock().is_linked();
|
||||
assert( ereg? !has_write_port : 1 );
|
||||
|
||||
// Connect the write clock and write enable
|
||||
|
||||
|
|
@ -1717,6 +1854,21 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
|||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
}
|
||||
|
||||
if (ereg) {
|
||||
unsigned count = obj->u_.ff.width * obj->u_.ff.scnt;
|
||||
assert(ereg->pin_count() == count);
|
||||
|
||||
obj->u_.ff.d.pins = new ivl_nexus_t [count];
|
||||
|
||||
for (unsigned idx = 0 ; idx < count ; idx += 1) {
|
||||
nex = ereg->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dll_target::lpm_mult(const NetMult*net)
|
||||
|
|
@ -1724,6 +1876,8 @@ void dll_target::lpm_mult(const NetMult*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_MULT;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1803,7 +1957,9 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_MUX;
|
||||
obj->name = net->name(); // The NetMux perallocates its name.
|
||||
obj->name = net->name(); // NetMux names are permallocated
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
|
|
@ -1828,10 +1984,34 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
|
||||
for (unsigned idx = 0 ; idx < obj->u_.mux.width ; idx += 1) {
|
||||
nex = net->pin_Result(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
#if 0
|
||||
if (! nex->t_cookie()) {
|
||||
cerr << net->get_line() << ": internal error: "
|
||||
<< "broken mux. name=" << net->name()
|
||||
<< ", width=" << obj->u_.mux.width
|
||||
<< ", swid=" << obj->u_.mux.swid << endl;
|
||||
for (unsigned tmp = 0; tmp < obj->u_.mux.width; tmp += 1) {
|
||||
const Nexus*tmpn = net->pin_Result(tmp).nexus();
|
||||
if (tmpn->t_cookie() == 0)
|
||||
continue;
|
||||
|
||||
cerr << net->get_line() << ": XXXX "
|
||||
<< "Result(" << tmp << ") : "
|
||||
<< tmpn->name() << endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
obj->u_.mux.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
/* It is possible (although unlikely) that the
|
||||
result bit of the mux is not used. This can
|
||||
happen, for example, if the output is
|
||||
overridden in the HDL. In that case, skip
|
||||
it. But if the bit is used, then add it to the
|
||||
nexus. */
|
||||
if (obj->u_.mux.q.pins[idx])
|
||||
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2180,6 +2360,30 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.131.2.8 2006/07/23 19:42:35 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.131.2.7 2006/04/16 19:26:40 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.131.2.6 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.131.2.5 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.131.2.4 2006/02/25 05:03:29 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.131.2.3 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.131.2.2 2006/01/21 21:42:33 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
* Revision 1.131.2.1 2005/02/19 16:39:31 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.131 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
38
t-dll.h
38
t-dll.h
|
|
@ -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.115 2004/10/04 01:10:56 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.115.2.5 2006/04/16 19:26:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -76,6 +76,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_add_sub(const NetAddSub*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
bool lpm_decode(const NetDecode*);
|
||||
bool lpm_demux(const NetDemux*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
void lpm_ff(const NetFF*);
|
||||
void lpm_modulo(const NetModulo*);
|
||||
|
|
@ -162,6 +164,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
void add_root(ivl_design_s &des_, const NetScope *s);
|
||||
|
||||
ivl_lpm_t lpm_decode_ff_(const NetDecode*);
|
||||
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
|
|
@ -290,10 +294,14 @@ struct ivl_lpm_s {
|
|||
ivl_scope_t scope;
|
||||
perm_string name;
|
||||
|
||||
struct ivl_attribute_s*attr;
|
||||
unsigned nattr;
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned width;
|
||||
unsigned swid; // ram only
|
||||
unsigned scnt;
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
|
|
@ -312,7 +320,10 @@ struct ivl_lpm_s {
|
|||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_memory_t mem; // ram only
|
||||
union {
|
||||
ivl_memory_t mem; // ram only
|
||||
ivl_lpm_t decode; // FF only
|
||||
} a;
|
||||
ivl_expr_t aset_value;
|
||||
ivl_expr_t sset_value;
|
||||
} ff;
|
||||
|
|
@ -332,6 +343,14 @@ struct ivl_lpm_s {
|
|||
} s;
|
||||
} mux;
|
||||
|
||||
struct ivl_lpm_demux_s {
|
||||
unsigned width;
|
||||
unsigned awid;
|
||||
unsigned size;
|
||||
ivl_nexus_t*bit_in;
|
||||
ivl_nexus_t *q,*d,*a;
|
||||
} demux;
|
||||
|
||||
struct ivl_lpm_shift_s {
|
||||
unsigned width;
|
||||
unsigned select;
|
||||
|
|
@ -684,6 +703,21 @@ struct ivl_variable_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.115.2.5 2006/04/16 19:26:40 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.115.2.4 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.115.2.3 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.115.2.2 2006/02/25 05:03:30 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.115.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.115 2004/10/04 01:10:56 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
22
target.cc
22
target.cc
|
|
@ -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.69 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.69.2.2 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -101,6 +101,20 @@ void target_t::lpm_compare(const NetCompare*)
|
|||
"Unhandled NetCompare." << endl;
|
||||
}
|
||||
|
||||
bool target_t::lpm_decode(const NetDecode*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetDecode." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::lpm_demux(const NetDemux*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetDemux." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_divide(const NetDivide*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -420,6 +434,12 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.69.2.2 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.69.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.69 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
10
target.h
10
target.h
|
|
@ -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.65 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.65.2.2 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -79,6 +79,8 @@ struct target_t {
|
|||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual bool lpm_decode(const NetDecode*);
|
||||
virtual bool lpm_demux(const NetDemux*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
virtual void lpm_modulo(const NetModulo*);
|
||||
virtual void lpm_ff(const NetFF*);
|
||||
|
|
@ -170,6 +172,12 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.65.2.2 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.65.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.65 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
configure
|
||||
Makefile
|
||||
edif.tgt
|
||||
dep
|
||||
config.status
|
||||
config.log
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
The tgt-edif files are licensed differently from the rest of Icarus
|
||||
Verilog. These files are:
|
||||
|
||||
--
|
||||
|
||||
Copyright (c) 2005 Stephen Williams
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--
|
||||
|
||||
The purpose of the different license here is to allow licensees to use
|
||||
these files to make EDIF based code generators that use these common
|
||||
functions without statically linking to GPL files from elsewhere
|
||||
within Icarus Verilog.
|
||||
|
||||
As a reminder, while this more relaxed license is here to allow
|
||||
entities to make closed source (binary) code generators, this is not
|
||||
intended to effect the GPL standing of the rest of Icarus Verilog
|
||||
source. THIS RELAXED LICENSE APPLIES ONLY TO FILES SPECIFICALLY MARKED
|
||||
WITH THIS NEW LICENSE. Furthermore, all rights remain reserved. Note
|
||||
specifically the requirement for you to reproduce notices in your
|
||||
documentation.
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
#
|
||||
# Copyright (c) 2005 Stephen Williams
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.1.2.3 2006/05/08 04:33:36 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
mandir = @mandir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
RANLIB = @RANLIB@
|
||||
MAN = @MAN@
|
||||
PS2pdf = @ps2pdf@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: dep edif.tgt
|
||||
|
||||
dep:
|
||||
mkdir dep
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
D = d-lpm.o d-virtex.o xilinx.o
|
||||
O = edif.o device.o target.o gates.o generic.o $D
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
TGTDEPLIBS=../libivl.a
|
||||
else
|
||||
TGTLDFLAGS=
|
||||
TGTDEPLIBS=
|
||||
endif
|
||||
|
||||
|
||||
edif.tgt: tables.o libedif_tgt.a $(TGTDEPLIBS)
|
||||
$(CC) @shared@ -o $@ tables.o libedif_tgt.a $(TGTLDFLAGS)
|
||||
|
||||
libedif_tgt.a: $O
|
||||
rm -f libedif_tgt.a
|
||||
ar cqv libedif_tgt.a $O
|
||||
$(RANLIB) libedif_tgt.a
|
||||
|
||||
iverilog-edif.ps: $(srcdir)/iverilog-edif.man
|
||||
$(MAN) -t $(srcdir)/iverilog-edif.man > iverilog-edif.ps
|
||||
|
||||
iverilog-edif.pdf: iverilog-edif.ps
|
||||
$(PS2PDF) iverilog-edif.ps iverilog-edif.pdf
|
||||
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
clean:
|
||||
rm -rf *.o dep edif.tgt
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
check: all
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC =
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
#INSTALL_DOC = $(mandir)/man1/iverilog-edif.1
|
||||
else
|
||||
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
|
||||
#all: iverilog-edif.pdf
|
||||
endif
|
||||
endif
|
||||
else
|
||||
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
|
||||
#INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl/edif.tgt $(INSTALL_DOC) $(libdir)/ivl/edif.conf $(libdir)/ivl/edif-s.conf
|
||||
|
||||
$(libdir)/ivl/edif.tgt: ./edif.tgt
|
||||
$(INSTALL_PROGRAM) ./edif.tgt $(libdir)/ivl/edif.tgt
|
||||
|
||||
$(libdir)/ivl/edif.conf: $(srcdir)/edif.conf
|
||||
$(INSTALL_DATA) $(srcdir)/edif.conf $(libdir)/ivl/edif.conf
|
||||
|
||||
$(libdir)/ivl/edif-s.conf: $(srcdir)/edif-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/edif-s.conf $(libdir)/ivl/edif-s.conf
|
||||
|
||||
|
||||
$(mandir)/man1/iverilog-edif.1: $(srcdir)/iverilog-edif.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-edif.man $(mandir)/man1/iverilog-edif.1
|
||||
|
||||
$(prefix)/iverilog-edif.pdf: iverilog-edif.pdf
|
||||
$(INSTALL_DATA) iverilog-edif.pdf $(prefix)/iverilog-edif.pdf
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/edif.tgt
|
||||
rm -f $(INSTALL_DOC)
|
||||
rm -f $(libdir)/ivl/edif-s.conf
|
||||
rm -f $(libdir)/ivl/edif.conf
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(edif.conf)
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_INSTALL
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# linker options when building a shared library
|
||||
AX_LD_SHAREDLIB_OPTS
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
|
|
@ -0,0 +1,979 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-lpm.c,v 1.1.2.2 2005/08/21 14:39:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the driver for a purely generic LPM module writer. This
|
||||
* uses LPM version 2 1 0 devices, without particularly considering
|
||||
* the target technology.
|
||||
*
|
||||
* The LPM standard is EIA-IS/103-A October 1996
|
||||
* The output is EDIF 2 0 0 format.
|
||||
*/
|
||||
|
||||
# include "device.h"
|
||||
# include "edif_priv.h"
|
||||
# include "edif.h"
|
||||
# include "generic.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static edif_cell_t lpm_cell_buf(void)
|
||||
{
|
||||
static edif_cell_t tmp = 0;
|
||||
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
|
||||
tmp = edif_xcell_create(xlib, "BUF", 2);
|
||||
edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
|
||||
|
||||
/* A buffer is an inverted inverter. */
|
||||
edif_cell_port_pstring(tmp, 0, "LPM_Polarity", "INVERT");
|
||||
|
||||
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV");
|
||||
edif_cell_pinteger(tmp, "LPM_Width", 1);
|
||||
edif_cell_pinteger(tmp, "LPM_Size", 1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_inv(void)
|
||||
{
|
||||
static edif_cell_t tmp = 0;
|
||||
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
|
||||
tmp = edif_xcell_create(xlib, "INV", 2);
|
||||
edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
|
||||
|
||||
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV");
|
||||
edif_cell_pinteger(tmp, "LPM_Width", 1);
|
||||
edif_cell_pinteger(tmp, "LPM_Size", 1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_bufif0(void)
|
||||
{
|
||||
static edif_cell_t tmp = 0;
|
||||
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
|
||||
tmp = edif_xcell_create(xlib, "BUFIF1", 3);
|
||||
edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
|
||||
|
||||
edif_cell_port_pstring(tmp, 2, "LPM_Polarity", "INVERT");
|
||||
|
||||
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI");
|
||||
edif_cell_pinteger(tmp, "LPM_Width", 1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_bufif1(void)
|
||||
{
|
||||
static edif_cell_t tmp = 0;
|
||||
|
||||
if (tmp != 0)
|
||||
return tmp;
|
||||
|
||||
tmp = edif_xcell_create(xlib, "BUFIF1", 3);
|
||||
edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
|
||||
|
||||
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI");
|
||||
edif_cell_pinteger(tmp, "LPM_Width", 1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_or(unsigned siz)
|
||||
{
|
||||
unsigned idx;
|
||||
edif_cell_t cell;
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "or%u", siz);
|
||||
|
||||
cell = edif_xlibrary_findcell(xlib, name);
|
||||
if (cell != 0)
|
||||
return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(name), siz+1);
|
||||
|
||||
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
|
||||
|
||||
for (idx = 0 ; idx < siz ; idx += 1) {
|
||||
sprintf(name, "Data%ux0", idx);
|
||||
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR");
|
||||
edif_cell_pinteger(cell, "LPM_Width", 1);
|
||||
edif_cell_pinteger(cell, "LPM_Size", siz);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_and(unsigned siz)
|
||||
{
|
||||
unsigned idx;
|
||||
edif_cell_t cell;
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "and%u", siz);
|
||||
|
||||
cell = edif_xlibrary_findcell(xlib, name);
|
||||
if (cell != 0)
|
||||
return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(name), siz+1);
|
||||
|
||||
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
|
||||
|
||||
for (idx = 0 ; idx < siz ; idx += 1) {
|
||||
sprintf(name, "Data%ux0", idx);
|
||||
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_TYPE", "LPM_AND");
|
||||
edif_cell_pinteger(cell, "LPM_Width", 1);
|
||||
edif_cell_pinteger(cell, "LPM_Size", siz);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_xor(unsigned siz)
|
||||
{
|
||||
unsigned idx;
|
||||
edif_cell_t cell;
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "xor%u", siz);
|
||||
|
||||
cell = edif_xlibrary_findcell(xlib, name);
|
||||
if (cell != 0)
|
||||
return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(name), siz+1);
|
||||
|
||||
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
|
||||
|
||||
for (idx = 0 ; idx < siz ; idx += 1) {
|
||||
sprintf(name, "Data%ux0", idx);
|
||||
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_TYPE", "LPM_XOR");
|
||||
edif_cell_pinteger(cell, "LPM_Width", 1);
|
||||
edif_cell_pinteger(cell, "LPM_Size", siz);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
static edif_cell_t lpm_cell_nor(unsigned siz)
|
||||
{
|
||||
unsigned idx;
|
||||
edif_cell_t cell;
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "nor%u", siz);
|
||||
|
||||
cell = edif_xlibrary_findcell(xlib, name);
|
||||
if (cell != 0)
|
||||
return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(name), siz+1);
|
||||
|
||||
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
|
||||
edif_cell_port_pstring(cell, 0, "LPM_Polarity", "INVERT");
|
||||
|
||||
for (idx = 0 ; idx < siz ; idx += 1) {
|
||||
sprintf(name, "Data%ux0", idx);
|
||||
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR");
|
||||
edif_cell_pinteger(cell, "LPM_Width", 1);
|
||||
edif_cell_pinteger(cell, "LPM_Size", siz);
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
static void lpm_show_header(ivl_design_t des)
|
||||
{
|
||||
unsigned idx;
|
||||
ivl_scope_t root = ivl_design_root(des);
|
||||
unsigned sig_cnt = ivl_scope_sigs(root);
|
||||
unsigned nports = 0, pidx;
|
||||
|
||||
/* Count the ports I'm going to use. */
|
||||
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(root, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_attr(sig, "PAD") != 0)
|
||||
continue;
|
||||
|
||||
nports += ivl_signal_pins(sig);
|
||||
}
|
||||
|
||||
/* Create the base edf object. */
|
||||
edf = edif_create(ivl_scope_basename(root), nports);
|
||||
|
||||
|
||||
pidx = 0;
|
||||
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
ivl_signal_t sig = ivl_scope_sig(root, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_attr(sig, "PAD") != 0)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_pins(sig) == 1) {
|
||||
edif_portconfig(edf, pidx, ivl_signal_basename(sig),
|
||||
ivl_signal_port(sig));
|
||||
|
||||
assert(ivl_signal_pins(sig) == 1);
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
|
||||
edif_port_to_joint(jnt, edf, pidx);
|
||||
|
||||
} else {
|
||||
const char*name = ivl_signal_basename(sig);
|
||||
ivl_signal_port_t dir = ivl_signal_port(sig);
|
||||
char buf[128];
|
||||
unsigned bit;
|
||||
for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) {
|
||||
const char*tmp;
|
||||
sprintf(buf, "%s[%u]", name, bit);
|
||||
tmp = strdup(buf);
|
||||
edif_portconfig(edf, pidx+bit, tmp, dir);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
|
||||
edif_port_to_joint(jnt, edf, pidx+bit);
|
||||
}
|
||||
}
|
||||
|
||||
pidx += ivl_signal_pins(sig);
|
||||
}
|
||||
|
||||
assert(pidx == nports);
|
||||
|
||||
xlib = edif_xlibrary_create(edf, "LPM_LIBRARY");
|
||||
}
|
||||
|
||||
static void lpm_show_footer(ivl_design_t des)
|
||||
{
|
||||
edif_print(xnf, edf);
|
||||
}
|
||||
|
||||
static void hookup_logic_gate(ivl_net_logic_t net, edif_cell_t cell)
|
||||
{
|
||||
unsigned pin, idx;
|
||||
|
||||
edif_joint_t jnt;
|
||||
edif_cellref_t ref = edif_cellref_create(edf, cell);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
pin = edif_cell_port_byname(cell, "Result0");
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) {
|
||||
char name[32];
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
|
||||
sprintf(name, "Data%ux0", idx-1);
|
||||
pin = edif_cell_port_byname(cell, name);
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void lpm_logic(ivl_net_logic_t net)
|
||||
{
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_BUFZ:
|
||||
case IVL_LO_BUF:
|
||||
assert(ivl_logic_pins(net) == 2);
|
||||
cell = lpm_cell_buf();
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, ref, 0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, ref, 1);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF0:
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
cell = lpm_cell_bufif0();
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, ref, 0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, ref, 1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, ref, 2);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF1:
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
cell = lpm_cell_bufif1();
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, ref, 0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, ref, 1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, ref, 2);
|
||||
break;
|
||||
|
||||
case IVL_LO_NOT:
|
||||
assert(ivl_logic_pins(net) == 2);
|
||||
cell = lpm_cell_inv();
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, ref, 0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, ref, 1);
|
||||
break;
|
||||
|
||||
case IVL_LO_OR:
|
||||
cell = lpm_cell_or(ivl_logic_pins(net)-1);
|
||||
hookup_logic_gate(net, cell);
|
||||
break;
|
||||
|
||||
case IVL_LO_NOR:
|
||||
cell = lpm_cell_nor(ivl_logic_pins(net)-1);
|
||||
hookup_logic_gate(net, cell);
|
||||
break;
|
||||
|
||||
case IVL_LO_AND:
|
||||
cell = lpm_cell_and(ivl_logic_pins(net)-1);
|
||||
hookup_logic_gate( net, cell);
|
||||
break;
|
||||
|
||||
case IVL_LO_XOR:
|
||||
cell = lpm_cell_xor(ivl_logic_pins(net)-1);
|
||||
hookup_logic_gate( net, cell);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
|
||||
ivl_logic_type(net));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void lpm_show_dff(ivl_lpm_t net)
|
||||
{
|
||||
char name[64];
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
|
||||
unsigned idx;
|
||||
unsigned pin, wid = ivl_lpm_width(net);
|
||||
|
||||
sprintf(name, "fd%s%s%s%s%s%u",
|
||||
ivl_lpm_enable(net)? "ce" : "",
|
||||
ivl_lpm_async_clr(net)? "cl" : "",
|
||||
ivl_lpm_sync_clr(net)? "sc" : "",
|
||||
ivl_lpm_async_set(net)? "se" : "",
|
||||
ivl_lpm_sync_set(net)? "ss" : "",
|
||||
wid);
|
||||
|
||||
cell = edif_xlibrary_findcell(xlib, name);
|
||||
|
||||
if (cell == 0) {
|
||||
unsigned nports = 2 * wid + 1;
|
||||
pin = 0;
|
||||
if (ivl_lpm_enable(net))
|
||||
nports += 1;
|
||||
if (ivl_lpm_async_clr(net))
|
||||
nports += 1;
|
||||
if (ivl_lpm_sync_clr(net))
|
||||
nports += 1;
|
||||
if (ivl_lpm_async_set(net))
|
||||
nports += 1;
|
||||
if (ivl_lpm_sync_set(net))
|
||||
nports += 1;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(name), nports);
|
||||
edif_cell_pstring(cell, "LPM_Type", "LPM_FF");
|
||||
edif_cell_pinteger(cell, "LPM_Width", wid);
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1) {
|
||||
|
||||
sprintf(name, "Q%u", idx);
|
||||
edif_cell_portconfig(cell, idx*2+0, strdup(name),
|
||||
IVL_SIP_OUTPUT);
|
||||
|
||||
sprintf(name, "Data%u", idx);
|
||||
edif_cell_portconfig(cell, idx*2+1, strdup(name),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
pin = wid*2;
|
||||
|
||||
if (ivl_lpm_enable(net)) {
|
||||
edif_cell_portconfig(cell, pin, "Enable", IVL_SIP_INPUT);
|
||||
pin += 1;
|
||||
}
|
||||
|
||||
if (ivl_lpm_async_clr(net)) {
|
||||
edif_cell_portconfig(cell, pin, "Aclr", IVL_SIP_INPUT);
|
||||
pin += 1;
|
||||
}
|
||||
|
||||
if (ivl_lpm_sync_clr(net)) {
|
||||
edif_cell_portconfig(cell, pin, "Sclr", IVL_SIP_INPUT);
|
||||
pin += 1;
|
||||
}
|
||||
|
||||
if (ivl_lpm_async_set(net)) {
|
||||
edif_cell_portconfig(cell, pin, "Aset", IVL_SIP_INPUT);
|
||||
pin += 1;
|
||||
}
|
||||
|
||||
if (ivl_lpm_sync_set(net)) {
|
||||
edif_cell_portconfig(cell, pin, "Sset", IVL_SIP_INPUT);
|
||||
pin += 1;
|
||||
}
|
||||
|
||||
edif_cell_portconfig(cell, pin, "Clock", IVL_SIP_INPUT);
|
||||
pin += 1;
|
||||
|
||||
assert(pin == nports);
|
||||
}
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
pin = edif_cell_port_byname(cell, "Clock");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
if (ivl_lpm_enable(net)) {
|
||||
pin = edif_cell_port_byname(cell, "Enable");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_enable(net));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
if (ivl_lpm_async_clr(net)) {
|
||||
pin = edif_cell_port_byname(cell, "Aclr");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_async_clr(net));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
if (ivl_lpm_sync_clr(net)) {
|
||||
pin = edif_cell_port_byname(cell, "Sclr");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_clr(net));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
if (ivl_lpm_async_set(net)) {
|
||||
pin = edif_cell_port_byname(cell, "Aset");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_async_set(net));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
if (ivl_lpm_sync_set(net)) {
|
||||
ivl_expr_t svalue = ivl_lpm_sset_value(net);
|
||||
|
||||
pin = edif_cell_port_byname(cell, "Sset");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_set(net));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
edif_cellref_pinteger(ref, "LPM_Svalue", ivl_expr_uvalue(svalue));
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1) {
|
||||
|
||||
sprintf(name, "Q%u", idx);
|
||||
pin = edif_cell_port_byname(cell, name);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
sprintf(name, "Data%u", idx);
|
||||
pin = edif_cell_port_byname(cell, name);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void lpm_show_cmp_eq(ivl_lpm_t net)
|
||||
{
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
unsigned idx;
|
||||
|
||||
char cellname[32];
|
||||
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
sprintf(cellname, "compare%u_eq", width);
|
||||
cell = edif_xlibrary_findcell(xlib, cellname);
|
||||
|
||||
if (cell == 0) {
|
||||
unsigned pins = 2*width + 1;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(cellname), pins);
|
||||
|
||||
/* Make the output port. */
|
||||
sprintf(cellname, "AEB");
|
||||
edif_cell_portconfig(cell, 2*width, strdup(cellname),
|
||||
IVL_SIP_OUTPUT);
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
sprintf(cellname, "DataA%u", idx);
|
||||
edif_cell_portconfig(cell, idx+0, strdup(cellname),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
sprintf(cellname, "DataB%u", idx);
|
||||
edif_cell_portconfig(cell, idx+width, strdup(cellname),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_Type", "LPM_COMPARE");
|
||||
edif_cell_pinteger(cell, "LPM_Width", width);
|
||||
}
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
unsigned pin;
|
||||
|
||||
sprintf(cellname, "DataA%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
unsigned pin;
|
||||
|
||||
sprintf(cellname, "DataB%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
{
|
||||
unsigned pin;
|
||||
|
||||
pin = edif_cell_port_byname(cell, "AEB");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void lpm_show_mux(ivl_lpm_t net)
|
||||
{
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
|
||||
unsigned idx, rdx;
|
||||
|
||||
char cellname[32];
|
||||
|
||||
unsigned wid_r = ivl_lpm_width(net);
|
||||
unsigned wid_s = ivl_lpm_selects(net);
|
||||
unsigned wid_z = ivl_lpm_size(net);
|
||||
|
||||
sprintf(cellname, "mux%u_%u_%u", wid_r, wid_s, wid_z);
|
||||
cell = edif_xlibrary_findcell(xlib, cellname);
|
||||
|
||||
if (cell == 0) {
|
||||
unsigned pins = wid_r + wid_s + wid_r*wid_z;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(cellname), pins);
|
||||
|
||||
/* Make the output ports. */
|
||||
for (idx = 0 ; idx < wid_r ; idx += 1) {
|
||||
sprintf(cellname, "Result%u", idx);
|
||||
edif_cell_portconfig(cell, idx, strdup(cellname),
|
||||
IVL_SIP_OUTPUT);
|
||||
}
|
||||
|
||||
/* Make the select ports. */
|
||||
for (idx = 0 ; idx < wid_s ; idx += 1) {
|
||||
sprintf(cellname, "Sel%u", idx);
|
||||
edif_cell_portconfig(cell, wid_r+idx, strdup(cellname),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid_z ; idx += 1) {
|
||||
unsigned base = wid_r + wid_s + wid_r * idx;
|
||||
unsigned rdx;
|
||||
|
||||
for (rdx = 0 ; rdx < wid_r ; rdx += 1) {
|
||||
sprintf(cellname, "Data%ux%u", idx, rdx);
|
||||
edif_cell_portconfig(cell, base+rdx, strdup(cellname),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_Type", "LPM_MUX");
|
||||
edif_cell_pinteger(cell, "LPM_Width", wid_r);
|
||||
edif_cell_pinteger(cell, "LPM_WidthS", wid_s);
|
||||
edif_cell_pinteger(cell, "LPM_Size", wid_z);
|
||||
}
|
||||
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
/* Connect the pins of the instance to the nexa. Access the
|
||||
cell pins by name. */
|
||||
for (idx = 0 ; idx < wid_r ; idx += 1) {
|
||||
unsigned pin;
|
||||
|
||||
sprintf(cellname, "Result%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid_s ; idx += 1) {
|
||||
unsigned pin;
|
||||
|
||||
sprintf(cellname, "Sel%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid_z ; idx += 1) {
|
||||
for (rdx = 0 ; rdx < wid_r ; rdx += 1) {
|
||||
unsigned pin;
|
||||
|
||||
sprintf(cellname, "Data%ux%u", idx, rdx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, idx, rdx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lpm_show_add(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned cell_width;
|
||||
char cellname[32];
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
|
||||
const char*type = "ADD";
|
||||
|
||||
if (ivl_lpm_type(net) == IVL_LPM_SUB)
|
||||
type = "SUB";
|
||||
|
||||
/* Figure out the width of the cell. Normally, it is the LPM
|
||||
width known by IVL. But if the top data input bits are
|
||||
unconnected, then we really have a width one less, and we
|
||||
can use the cout to fill out the output width. */
|
||||
cell_width = ivl_lpm_width(net);
|
||||
if ( (ivl_lpm_data(net,cell_width-1) == 0)
|
||||
&& (ivl_lpm_datab(net,cell_width-1) == 0) )
|
||||
cell_width -= 1;
|
||||
|
||||
/* Find the correct ADD/SUB device in the library, search by
|
||||
name. If the device is not there, then create it and put it
|
||||
in the library. */
|
||||
sprintf(cellname, "%s%u", type, cell_width);
|
||||
cell = edif_xlibrary_findcell(xlib, cellname);
|
||||
|
||||
if (cell == 0) {
|
||||
unsigned pins = cell_width * 3 + 1;
|
||||
|
||||
cell = edif_xcell_create(xlib, strdup(cellname), pins);
|
||||
|
||||
for (idx = 0 ; idx < cell_width ; idx += 1) {
|
||||
|
||||
sprintf(cellname, "Result%u", idx);
|
||||
edif_cell_portconfig(cell, idx*3+0, strdup(cellname),
|
||||
IVL_SIP_OUTPUT);
|
||||
|
||||
sprintf(cellname, "DataA%u", idx);
|
||||
edif_cell_portconfig(cell, idx*3+1, strdup(cellname),
|
||||
IVL_SIP_INPUT);
|
||||
|
||||
sprintf(cellname, "DataB%u", idx);
|
||||
edif_cell_portconfig(cell, idx*3+2, strdup(cellname),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_portconfig(cell, pins-1, "Cout", IVL_SIP_OUTPUT);
|
||||
|
||||
edif_cell_pstring(cell, "LPM_Type", "LPM_ADD_SUB");
|
||||
edif_cell_pstring(cell, "LPM_Direction", type);
|
||||
edif_cell_pinteger(cell, "LPM_Width", ivl_lpm_width(net));
|
||||
}
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
/* Connect the pins of the instance to the nexa. Access the
|
||||
cell pins by name. */
|
||||
for (idx = 0 ; idx < cell_width ; idx += 1) {
|
||||
unsigned pin;
|
||||
|
||||
sprintf(cellname, "Result%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
sprintf(cellname, "DataA%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
sprintf(cellname, "DataB%u", idx);
|
||||
pin = edif_cell_port_byname(cell, cellname);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
if (cell_width < ivl_lpm_width(net)) {
|
||||
unsigned pin = edif_cell_port_byname(cell, "Cout");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, cell_width));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void lpm_show_mult(ivl_lpm_t net)
|
||||
{
|
||||
char name[64];
|
||||
unsigned idx;
|
||||
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
|
||||
sprintf(name, "mult%u", ivl_lpm_width(net));
|
||||
cell = edif_xlibrary_findcell(xlib, name);
|
||||
|
||||
if (cell == 0) {
|
||||
cell = edif_xcell_create(xlib, strdup(name),
|
||||
3 * ivl_lpm_width(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
|
||||
sprintf(name, "Result%u", idx);
|
||||
edif_cell_portconfig(cell, idx*3+0,
|
||||
strdup(name),
|
||||
IVL_SIP_OUTPUT);
|
||||
|
||||
sprintf(name, "DataA%u", idx);
|
||||
edif_cell_portconfig(cell, idx*3+1,
|
||||
strdup(name),
|
||||
IVL_SIP_INPUT);
|
||||
|
||||
sprintf(name, "DataB%u", idx);
|
||||
edif_cell_portconfig(cell, idx*3+2,
|
||||
strdup(name),
|
||||
IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
edif_cell_pstring(cell, "LPM_Type", "LPM_MULT");
|
||||
edif_cell_pinteger(cell, "LPM_WidthP", ivl_lpm_width(net));
|
||||
edif_cell_pinteger(cell, "LPM_WidthA", ivl_lpm_width(net));
|
||||
edif_cell_pinteger(cell, "LPM_WidthB", ivl_lpm_width(net));
|
||||
}
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
unsigned pin;
|
||||
ivl_nexus_t nex;
|
||||
|
||||
sprintf(name, "Result%u", idx);
|
||||
pin = edif_cell_port_byname(cell, name);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
|
||||
if ( (nex = ivl_lpm_data(net, idx)) ) {
|
||||
sprintf(name, "DataA%u", idx);
|
||||
pin = edif_cell_port_byname(cell, name);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, nex);
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
|
||||
if ( (nex = ivl_lpm_datab(net, idx)) ) {
|
||||
sprintf(name, "DataB%u", idx);
|
||||
pin = edif_cell_port_byname(cell, name);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, nex);
|
||||
edif_add_to_joint(jnt, ref, pin);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void lpm_show_constant(ivl_net_const_t net)
|
||||
{
|
||||
/* We only need one instance each of constant 0 and 1 bits. If
|
||||
we need either of them, then create an instance reference and
|
||||
save that reference here so that later needs for 0 or 1 can
|
||||
find that the reference already lives and can be added to the
|
||||
joint. */
|
||||
static edif_cellref_t cell0_ref = 0;
|
||||
static edif_cellref_t cell1_ref = 0;
|
||||
|
||||
static edif_joint_t cell0_jnt = 0;
|
||||
static edif_joint_t cell1_jnt = 0;
|
||||
|
||||
edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0");
|
||||
edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1");
|
||||
|
||||
const char*bits;
|
||||
unsigned idx;
|
||||
|
||||
if (cell0 == 0) {
|
||||
cell0 = edif_xcell_create(xlib, "cell0", 1);
|
||||
edif_cell_portconfig(cell0, 0, "Result0", IVL_SIP_OUTPUT);
|
||||
|
||||
edif_cell_pstring(cell0, "LPM_Type", "LPM_CONSTANT");
|
||||
edif_cell_pinteger(cell0, "LPM_Width", 1);
|
||||
edif_cell_pinteger(cell0, "LPM_CValue", 0);
|
||||
}
|
||||
|
||||
if (cell1 == 0) {
|
||||
cell1 = edif_xcell_create(xlib, "cell1", 1);
|
||||
edif_cell_portconfig(cell1, 0, "Result0", IVL_SIP_OUTPUT);
|
||||
|
||||
edif_cell_pstring(cell1, "LPM_Type", "LPM_CONSTANT");
|
||||
edif_cell_pinteger(cell1, "LPM_Width", 1);
|
||||
edif_cell_pinteger(cell1, "LPM_CValue", 1);
|
||||
}
|
||||
|
||||
bits = ivl_const_bits(net);
|
||||
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
|
||||
if (bits[idx] == '1') {
|
||||
if (cell1_ref == 0) {
|
||||
cell1_ref = edif_cellref_create(edf, cell1);
|
||||
cell1_jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(cell1_jnt, cell1_ref, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (cell0_ref == 0) {
|
||||
cell0_ref = edif_cellref_create(edf, cell0);
|
||||
cell0_jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(cell0_jnt, cell0_ref, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
|
||||
if (bits[idx] == '1')
|
||||
edif_nexus_to_joint(edf, cell1_jnt, ivl_const_pin(net,idx));
|
||||
else
|
||||
edif_nexus_to_joint(edf, cell0_jnt, ivl_const_pin(net,idx));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const struct device_s d_lpm_edif = {
|
||||
lpm_show_header,
|
||||
lpm_show_footer,
|
||||
0,
|
||||
0, /* show_pad */
|
||||
lpm_logic, /* show_logic */
|
||||
lpm_show_dff, /* show_dff */
|
||||
lpm_show_cmp_eq, /* show_cmp_eq */
|
||||
0, /* show_cmp_ne */
|
||||
0, /* show_cmp_ge */
|
||||
0, /* show_cmp_gt */
|
||||
lpm_show_mux, /* show_mux */
|
||||
lpm_show_add, /* show_add */
|
||||
lpm_show_add, /* show_sub */
|
||||
0, /* show_shiftl */
|
||||
0, /* show_shiftr */
|
||||
lpm_show_mult, /* show_mult */
|
||||
lpm_show_constant /* show_constant */
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: d-lpm.c,v $
|
||||
* Revision 1.1.2.2 2005/08/21 14:39:33 steve
|
||||
* Generate LPM for the CMP_EQ device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,872 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-virtex.c,v 1.1.2.1 2005/09/25 16:35:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the driver for Xilinx Virtex style FPGA devices. The device
|
||||
* table structure at the bottom of this file lists all the various
|
||||
* functions that are used to generate code for virtex devices. In
|
||||
* some cases this table uses entries that are common to all Xilinx
|
||||
* devices, and in some cases Virtex specific entries are used. The
|
||||
* Virtex specific functions are given here, the xilinx_* common
|
||||
* functions are in the xilinx.{hc} source files.
|
||||
*/
|
||||
|
||||
# include "device.h"
|
||||
# include "edif.h"
|
||||
# include "generic.h"
|
||||
# include "xilinx.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* This is a table of cell types that are accessible via the cellref
|
||||
* attribute to a gate.
|
||||
*/
|
||||
const static struct edif_xlib_celltable virtex_celltable[] = {
|
||||
{ "BUFG", xilinx_cell_bufg },
|
||||
{ "MULT_AND", xilinx_cell_mult_and },
|
||||
{ 0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* The show_header function is called before any of the devices of the
|
||||
* netlist are scanned.
|
||||
*
|
||||
* In this function, we look at the ports of the root module to decide
|
||||
* if they are to be made into ports. Modules that have PAD attributes
|
||||
* are *not* to be used as ports, they will be connected to special
|
||||
* PAD devices instead.
|
||||
*/
|
||||
static void virtex_show_header(ivl_design_t des)
|
||||
{
|
||||
const char*part_str = 0;
|
||||
|
||||
xilinx_common_header(des);
|
||||
|
||||
xlib = edif_xlibrary_create(edf, "VIRTEX");
|
||||
edif_xlibrary_set_celltable(xlib, virtex_celltable);
|
||||
|
||||
|
||||
if ( (part_str = ivl_design_flag(des, "part")) && (part_str[0] != 0) ) {
|
||||
edif_pstring(edf, "PART", part_str);
|
||||
}
|
||||
|
||||
cell_0 = edif_xcell_create(xlib, "GND", 1);
|
||||
edif_cell_portconfig(cell_0, 0, "GROUND", IVL_SIP_OUTPUT);
|
||||
|
||||
cell_1 = edif_xcell_create(xlib, "VCC", 1);
|
||||
edif_cell_portconfig(cell_1, 0, "VCC", IVL_SIP_OUTPUT);
|
||||
|
||||
}
|
||||
|
||||
static void virtex_or_wide(ivl_net_logic_t net)
|
||||
{
|
||||
edif_cell_t cell_muxcy_l = xilinx_cell_muxcy_l(xlib);
|
||||
edif_cell_t cell_muxcy = xilinx_cell_muxcy(xlib);
|
||||
edif_cell_t cell_lut4 = xilinx_cell_lut4(xlib);
|
||||
|
||||
edif_cellref_t true_out, false_out;
|
||||
edif_cellref_t lut, muxcy, muxcy_down=NULL;
|
||||
edif_joint_t jnt;
|
||||
|
||||
unsigned idx, inputs, lut4_cnt;
|
||||
|
||||
if (ivl_logic_type(net) == IVL_LO_OR) {
|
||||
true_out = edif_cellref_create(edf, cell_1);
|
||||
false_out = edif_cellref_create(edf, cell_0);
|
||||
} else {
|
||||
true_out = edif_cellref_create(edf, cell_0);
|
||||
false_out = edif_cellref_create(edf, cell_1);
|
||||
}
|
||||
|
||||
inputs = ivl_logic_pins(net) - 1;
|
||||
lut4_cnt = (inputs-1)/4;
|
||||
|
||||
for (idx = 0 ; idx < lut4_cnt ; idx += 1) {
|
||||
muxcy = edif_cellref_create(edf, cell_muxcy_l);
|
||||
lut = edif_cellref_create(edf, cell_lut4);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "0001");
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, true_out, 0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+3));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
|
||||
if (idx > 0) {
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
|
||||
} else {
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, false_out, 0);
|
||||
}
|
||||
|
||||
muxcy_down = muxcy;
|
||||
}
|
||||
|
||||
muxcy = edif_cellref_create(edf, cell_muxcy);
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, true_out, 0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
|
||||
|
||||
switch (ivl_logic_pins(net) - 1 - lut4_cnt*4) {
|
||||
|
||||
case 1:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_inv(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, BUF_I);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "1");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "01");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lut = edif_cellref_create(edf, cell_lut4);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "0001");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+3));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_O);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick off the cases where there is a Virtex specific implementation
|
||||
* that is better then the generic Xilinx implementation. Route the
|
||||
* remaining to the base xilinx_logic implementation.
|
||||
*/
|
||||
void virtex_logic(ivl_net_logic_t net)
|
||||
{
|
||||
/* Nothing I can do if the user expresses a specific
|
||||
opinion. The cellref attribute forces me to let the base
|
||||
xilinx_logic take care of it. */
|
||||
if (ivl_logic_attr(net, "cellref")) {
|
||||
xilinx_logic(net);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_OR:
|
||||
case IVL_LO_NOR:
|
||||
if (ivl_logic_pins(net) <= 5) {
|
||||
xilinx_logic(net);
|
||||
|
||||
} else {
|
||||
virtex_or_wide(net);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
xilinx_logic(net);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void virtex_generic_dff(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
ivl_nexus_t aclr = ivl_lpm_async_clr(net);
|
||||
ivl_nexus_t aset = ivl_lpm_async_set(net);
|
||||
ivl_nexus_t sclr = ivl_lpm_sync_clr(net);
|
||||
ivl_nexus_t sset = ivl_lpm_sync_set(net);
|
||||
const char*abits = 0;
|
||||
|
||||
if (aset) {
|
||||
ivl_expr_t avalue = ivl_lpm_aset_value(net);
|
||||
assert(avalue);
|
||||
abits = ivl_expr_bits(avalue);
|
||||
assert(abits);
|
||||
}
|
||||
|
||||
/* XXXX Can't handle both synchronous and asynchronous clear. */
|
||||
assert( ! (aclr && sclr) );
|
||||
/* XXXX Can't handle synchronous set at all. */
|
||||
assert( ! sset );
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_cellref_t obj;
|
||||
ivl_nexus_t nex;
|
||||
edif_joint_t jnt;
|
||||
|
||||
/* If there is a preset, then select an FDCPE instead of
|
||||
an FDCE device. */
|
||||
if (aset && (abits[idx] == '1')) {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdcpe(xlib));
|
||||
} else if (aclr) {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib));
|
||||
} else if (sclr) {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdre(xlib));
|
||||
} else {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib));
|
||||
}
|
||||
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, obj, FDCE_Q);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, obj, FDCE_D);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
|
||||
edif_add_to_joint(jnt, obj, FDCE_C);
|
||||
|
||||
if ( (nex = ivl_lpm_enable(net)) ) {
|
||||
jnt = edif_joint_of_nexus(edf, nex);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CE);
|
||||
}
|
||||
|
||||
if (aclr) {
|
||||
jnt = edif_joint_of_nexus(edf, aclr);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CLR);
|
||||
} else if (sclr) {
|
||||
jnt = edif_joint_of_nexus(edf, sclr);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CLR);
|
||||
}
|
||||
|
||||
if (aset) {
|
||||
if (abits[idx] == '1') {
|
||||
jnt = edif_joint_of_nexus(edf, aset);
|
||||
edif_add_to_joint(jnt, obj, FDCE_PRE);
|
||||
} else {
|
||||
assert(aclr == 0);
|
||||
jnt = edif_joint_of_nexus(edf, aset);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CLR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This method handles both == and != operators, the identity
|
||||
* comparison operators.
|
||||
*
|
||||
* If the identity compare is applied to small enough input vectors,
|
||||
* it is shoved into a single LUT. Otherwise, it is strung out into a
|
||||
* row of LUT devices chained together by carry muxes. The output of
|
||||
* the comparison is the output of the last mux.
|
||||
*
|
||||
* When the compare is small, a LUT is generated with the appropriate
|
||||
* truth table to cause an == or != result.
|
||||
*
|
||||
* When the compare is too wide for a single LUT, then it is made into
|
||||
* a chain connected by a string of carry mux devices. Each LUT
|
||||
* implements == for up to two pairs of bits, even if the final output
|
||||
* is supposed to be !=. The LUT output is connected to an associated
|
||||
* MUX select input. The CO output of each muxcy is passed up to the
|
||||
* next higher order bits of the compare.
|
||||
*
|
||||
* For identity == compare, a != output from the LUT selects the DI
|
||||
* input of the muxcy, generating a 0 output that is passed up. Since
|
||||
* the next higher muxcy now gets a 0 input to both DI and CI, the
|
||||
* output of the next higher muxcy is guaranteed to be 0, and so on to
|
||||
* the final output of the carry chain. If the output from a LUT is ==,
|
||||
* then the CI input of the muxcy is selected and the truth of this
|
||||
* level depends on lower order bits. The least significant muxcy is
|
||||
* connected to GND and VCC so that its CO follows the least
|
||||
* significant LUT.
|
||||
*
|
||||
* Identity != is the same as == except that the output is
|
||||
* inverted. To get that effect without putting an inverter on the
|
||||
* output of the top muxcy pin CO (which would cost a LUT) the DI
|
||||
* inputs are all connected to VCC instead of GND, and the CI of the
|
||||
* least significant muxcy is connected to GND instead of VCC. The LUT
|
||||
* expressions for the chained compare are configured for ==, with the
|
||||
* changed CI/DI inputs performing the inversion.
|
||||
*/
|
||||
void virtex_eq(ivl_lpm_t net)
|
||||
{
|
||||
edif_cellref_t lut, mux, mux_prev;
|
||||
edif_joint_t jnt, jnt_di;
|
||||
unsigned idx;
|
||||
|
||||
/* True if I'm implementing CMP_EQ instead of CMP_NE */
|
||||
int eq = 1;
|
||||
|
||||
assert(ivl_lpm_width(net) >= 1);
|
||||
|
||||
if (ivl_lpm_type(net) == IVL_LPM_CMP_NE)
|
||||
eq = 0;
|
||||
|
||||
switch (ivl_lpm_width(net)) {
|
||||
|
||||
case 1:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", eq? "9" : "6");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", eq? "9009" : "6FF6");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
return;
|
||||
|
||||
default:
|
||||
{ edif_cellref_t di;
|
||||
di = edif_cellref_create(edf, eq? cell_0 : cell_1);
|
||||
jnt_di = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt_di, di, 0);
|
||||
}
|
||||
|
||||
mux_prev = 0;
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 2) {
|
||||
int subwid = 2;
|
||||
if ((idx + 1) == ivl_lpm_width(net))
|
||||
subwid = 1;
|
||||
|
||||
mux = edif_cellref_create(edf, xilinx_cell_muxcy(xlib));
|
||||
if (subwid == 2) {
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "9009");
|
||||
} else {
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "9");
|
||||
}
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, mux, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
if (subwid > 1) {
|
||||
jnt = edif_joint_of_nexus(edf,
|
||||
ivl_lpm_data(net, idx+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf,
|
||||
ivl_lpm_datab(net, idx+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
}
|
||||
|
||||
edif_add_to_joint(jnt_di, mux, MUXCY_DI);
|
||||
|
||||
if (mux_prev) {
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, mux, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, mux_prev, MUXCY_O);
|
||||
} else {
|
||||
edif_cellref_t ci;
|
||||
ci = edif_cellref_create(edf, eq? cell_1 : cell_0);
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, ci, 0);
|
||||
edif_add_to_joint(jnt, mux, MUXCY_CI);
|
||||
}
|
||||
|
||||
mux_prev = mux;
|
||||
}
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, mux_prev, MUXCY_O);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement hardware for the device (A >= B). We use LUT devices if
|
||||
* it can handle the slices, or carry chain logic if the slices must
|
||||
* span LUT devices.
|
||||
*/
|
||||
void virtex_ge(ivl_lpm_t net)
|
||||
{
|
||||
edif_cellref_t muxcy_prev;
|
||||
edif_cellref_t lut;
|
||||
edif_joint_t jnt;
|
||||
unsigned idx;
|
||||
|
||||
if (ivl_lpm_width(net) == 1) {
|
||||
|
||||
/* If the comparator is a single bit, then use a LUT2
|
||||
with this truth table:
|
||||
|
||||
Q A B
|
||||
--+----
|
||||
1 | 0 0
|
||||
0 | 0 1
|
||||
1 | 1 0
|
||||
1 | 1 1
|
||||
|
||||
Connect the A value to I1 and the B value to I0. */
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "D");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the case where the device is two slices
|
||||
wide. In this case, we can use a LUT4 to do all
|
||||
the calculation. Use this truth table:
|
||||
|
||||
Q AA BB
|
||||
--+------
|
||||
1 | 00 00
|
||||
0 | 00 01
|
||||
0 | 00 10
|
||||
0 | 00 11
|
||||
1 | 01 00
|
||||
1 | 01 01
|
||||
0 | 01 10
|
||||
0 | 01 11
|
||||
1 | 10 00
|
||||
1 | 10 01
|
||||
1 | 10 10
|
||||
0 | 10 11
|
||||
1 | 11 xx
|
||||
|
||||
The I3-I0 inputs are A1 A0 B1 B0 in that order. */
|
||||
|
||||
assert(ivl_lpm_width(net) >= 2);
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "F731");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
/* There are only two slices, so this is all we need. */
|
||||
if (ivl_lpm_width(net) == 2) {
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The general case requires that we make the >= comparator
|
||||
from slices. This is an iterative design. Each slice has
|
||||
the truth table:
|
||||
|
||||
An Bn | A >= B
|
||||
------+-------
|
||||
0 0 | CI
|
||||
0 1 | 0
|
||||
1 0 | 1
|
||||
1 1 | CI
|
||||
|
||||
The CI for each slice is the output of the compare of the
|
||||
next less significant bits. We get this truth table by
|
||||
connecting a LUT2 to the S input of a MUXCY. When the S
|
||||
input is (1), it propagates its CI. This suggests that the
|
||||
init value for the LUT be "9" (XNOR).
|
||||
|
||||
When the MUXCY S input is 0, it propagates a local
|
||||
input. We connect to that input An, and we get the desired
|
||||
and complete truth table for a slice.
|
||||
|
||||
This iterative definition needs to terminate at the least
|
||||
significant bits. In fact, we have a non-iterative was to
|
||||
deal with the two least significant slices. We take the
|
||||
output of the LUT4 device for the least significant bits,
|
||||
and use that to generate the initial CI for the chain. */
|
||||
|
||||
|
||||
muxcy_prev = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
|
||||
jnt = edif_joint_create(edf);
|
||||
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_S);
|
||||
{ edif_cellref_t p0 = edif_cellref_create(edf, cell_0);
|
||||
edif_cellref_t p1 = edif_cellref_create(edf, cell_1);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, p0, 0);
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, p1, 0);
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_CI);
|
||||
}
|
||||
|
||||
for (idx = 2 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_cellref_t muxcy;
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "9");
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
muxcy_prev = muxcy;
|
||||
}
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
|
||||
}
|
||||
|
||||
/*
|
||||
* A 4-input N-wide mux can be made on Virtex devices using MUXF5 and
|
||||
* LUT devices. The MUXF5 selects a LUT device (and is connected to
|
||||
* S[1]) and the LUT devices, connected to S[0], select the input.
|
||||
*/
|
||||
static void virtex_mux4(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
assert(ivl_lpm_selects(net) == 2);
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
edif_cellref_t lut01;
|
||||
edif_cellref_t lut23;
|
||||
edif_cellref_t muxf5;
|
||||
|
||||
lut01 = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
edif_cellref_pstring(lut01, "INIT", "CA");
|
||||
|
||||
lut23 = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
edif_cellref_pstring(lut23, "INIT", "CA");
|
||||
|
||||
muxf5 = edif_cellref_create(edf, xilinx_cell_muxf5(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 0, idx));
|
||||
edif_add_to_joint(jnt, lut01, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 1, idx));
|
||||
edif_add_to_joint(jnt, lut01, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 2, idx));
|
||||
edif_add_to_joint(jnt, lut23, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 3, idx));
|
||||
edif_add_to_joint(jnt, lut23, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 0));
|
||||
edif_add_to_joint(jnt, lut01, LUT_I2);
|
||||
edif_add_to_joint(jnt, lut23, LUT_I2);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxf5, MUXF_I0);
|
||||
edif_add_to_joint(jnt, lut01, LUT_O);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxf5, MUXF_I1);
|
||||
edif_add_to_joint(jnt, lut23, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, muxf5, MUXF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 1));
|
||||
edif_add_to_joint(jnt, muxf5, MUXF_S);
|
||||
}
|
||||
}
|
||||
|
||||
void virtex_mux(ivl_lpm_t net)
|
||||
{
|
||||
|
||||
switch (ivl_lpm_selects(net)) {
|
||||
|
||||
case 2:
|
||||
virtex_mux4(net);
|
||||
break;
|
||||
|
||||
default:
|
||||
xilinx_mux(net);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function generates ADD/SUB devices for Virtex devices,
|
||||
* based on the documented implementations of ADD8/ADD16, etc., from
|
||||
* the Libraries Guide.
|
||||
*
|
||||
* Each slice of the ADD/SUB device is made from a LUT2 device, an
|
||||
* XORCY device that mixes with the LUT2 to make a full adder, and a
|
||||
* MUXCY_L to propagate the carry. The most significant slice does not
|
||||
* have a carry to propagate, so has no MUXCY_L.
|
||||
*
|
||||
* If the device is a wide adder, then the LUT2 devices are configured
|
||||
* to implement an XOR function and a zero is pumped into the least
|
||||
* significant carry input.
|
||||
*
|
||||
* If the device is really an adder, then the input is turned into an
|
||||
* XNOR, which takes a 1-s complement of the B input. Pump a 1 into
|
||||
* the LSB carry input to finish converting the B input into the 2s
|
||||
* complement.
|
||||
*/
|
||||
void virtex_add(ivl_lpm_t net)
|
||||
{
|
||||
const char*ha_init = 0;
|
||||
edif_cellref_t lut, xorcy, muxcy, pad;
|
||||
edif_joint_t jnt;
|
||||
|
||||
unsigned idx;
|
||||
|
||||
if (ivl_lpm_width(net) < 2) {
|
||||
xilinx_add(net);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
ha_init = "6";
|
||||
break;
|
||||
case IVL_LPM_SUB:
|
||||
ha_init = "9";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
assert(ivl_lpm_width(net) > 1);
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
xorcy = edif_cellref_create(edf, xilinx_cell_xorcy(xlib));
|
||||
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", ha_init);
|
||||
|
||||
/* The bottom carry-in takes a constant that primes the add or
|
||||
subtract. */
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
pad = edif_cellref_create(edf, cell_0);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SUB:
|
||||
pad = edif_cellref_create(edf, cell_1);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_CI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_O);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_LI);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
for (idx = 1 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_cellref_t muxcy0 = muxcy;
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
xorcy = edif_cellref_create(edf, xilinx_cell_xorcy(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", ha_init);
|
||||
|
||||
/* If this is the last bit, then there is no further
|
||||
propagation in the carry chain, and I can skip the
|
||||
carry mux MUXCY. */
|
||||
if ((idx+1) < ivl_lpm_width(net))
|
||||
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
|
||||
else
|
||||
muxcy = 0;
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy0, MUXCY_O);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_CI);
|
||||
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_O);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_LI);
|
||||
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const struct device_s d_virtex_edif = {
|
||||
virtex_show_header,
|
||||
xilinx_show_footer,
|
||||
xilinx_show_scope,
|
||||
xilinx_pad,
|
||||
virtex_logic,
|
||||
virtex_generic_dff,
|
||||
virtex_eq,
|
||||
virtex_eq,
|
||||
virtex_ge,
|
||||
0, /* show_cmp_gt */
|
||||
virtex_mux,
|
||||
virtex_add,
|
||||
virtex_add,
|
||||
xilinx_shiftl,
|
||||
0, /* show_shiftr */
|
||||
0, /* show_mult */
|
||||
0 /* show_constant */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: d-virtex.c,v $
|
||||
* Revision 1.1.2.1 2005/09/25 16:35:36 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ident "$Id: device.c,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $"
|
||||
|
||||
# include "device.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
device_t device_from_arch(const char*arch)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
assert(arch);
|
||||
|
||||
for (idx = 0 ; edif_device_table[idx].name ; idx += 1) {
|
||||
if (strcmp(arch, edif_device_table[idx].name) == 0)
|
||||
return edif_device_table[idx].driver;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: device.c,v $
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#ifndef __device_H
|
||||
#define __device_H
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: device.h,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
|
||||
/*
|
||||
* This code generator supports a variety of device types. It does
|
||||
* this by keeping a device "driver" structure for each device
|
||||
* type. The device structure contains pointers to functions that emit
|
||||
* the proper XNF for a given type of device.
|
||||
*
|
||||
* If a device supports a method, the function pointer is filled in
|
||||
* with a pointer to the proper function.
|
||||
*
|
||||
* If a device does not support the method, then the pointer is null.
|
||||
*/
|
||||
typedef const struct device_s* device_t;
|
||||
|
||||
struct device_s {
|
||||
/* These methods draw leading and trailing format text. */
|
||||
void (*show_header)(ivl_design_t des);
|
||||
void (*show_footer)(ivl_design_t des);
|
||||
/* Draw scopes marked by ivl_synthesis_cell */
|
||||
void (*show_cell_scope)(ivl_scope_t net);
|
||||
/* Draw pads connected to the specified signal. */
|
||||
void (*show_pad)(ivl_signal_t sig, const char*str);
|
||||
/* Draw basic logic devices. */
|
||||
void (*show_logic)(ivl_net_logic_t net);
|
||||
/* This method emits a D type Flip-Flop */
|
||||
void (*show_dff)(ivl_lpm_t net);
|
||||
/* These methods show various comparators */
|
||||
void (*show_cmp_eq)(ivl_lpm_t net);
|
||||
void (*show_cmp_ne)(ivl_lpm_t net);
|
||||
void (*show_cmp_ge)(ivl_lpm_t net);
|
||||
void (*show_cmp_gt)(ivl_lpm_t net);
|
||||
/* This method draws MUX devices */
|
||||
void (*show_mux)(ivl_lpm_t net);
|
||||
/* This method draws ADD devices */
|
||||
void (*show_add)(ivl_lpm_t net);
|
||||
void (*show_sub)(ivl_lpm_t net);
|
||||
/* These methods draw SHIFT devices */
|
||||
void (*show_shiftl)(ivl_lpm_t net);
|
||||
void (*show_shiftr)(ivl_lpm_t net);
|
||||
/* Multipliers */
|
||||
void (*show_mult)(ivl_lpm_t net);
|
||||
/* Constants */
|
||||
void (*show_constant)(ivl_net_const_t net);
|
||||
};
|
||||
|
||||
/*
|
||||
* Return the device_t cookie given the name of the architecture. If
|
||||
* the device is not found, return 0.
|
||||
*
|
||||
* This function is used if the user specifies the archetecture
|
||||
* explicitly, with the -parch=name flag.
|
||||
*/
|
||||
extern device_t device_from_arch(const char*arch);
|
||||
|
||||
/*
|
||||
*/
|
||||
extern const struct device_table_s {
|
||||
const char*name;
|
||||
device_t driver;
|
||||
} edif_device_table[];
|
||||
|
||||
/*
|
||||
* $Log: device.h,v $
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=edif.tgt
|
||||
|
|
@ -0,0 +1,690 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: edif.c,v 1.1.2.3 2006/11/11 21:21:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "edif.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
typedef enum property_e {
|
||||
PRP_NONE = 0,
|
||||
PRP_STRING,
|
||||
PRP_INTEGER
|
||||
} property_t;
|
||||
|
||||
struct cellref_property_ {
|
||||
const char*name;
|
||||
property_t ptype;
|
||||
union {
|
||||
const char*str;
|
||||
long num;
|
||||
} value_;
|
||||
struct cellref_property_*next;
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the root of an EDIF design. From here we can get at the
|
||||
* root ports of the design (which are typically the pins of a chip or
|
||||
* FPGA design) a list of external cell libraries, cells properties
|
||||
* and nexa (joints).
|
||||
*/
|
||||
struct edif_s {
|
||||
const char*name;
|
||||
/* List the ports of the design. */
|
||||
unsigned nports;
|
||||
struct __cell_port*ports;
|
||||
/* All the external libraries attached to me. */
|
||||
edif_xlibrary_t xlibs;
|
||||
/* list the cellref instances. */
|
||||
edif_cellref_t celref;
|
||||
/* The root instance has cellref properties as well. */
|
||||
struct cellref_property_*property;
|
||||
/* Keep a list of all the nexa */
|
||||
struct edif_joint_s*nexa;
|
||||
};
|
||||
|
||||
struct edif_xlibrary_s {
|
||||
/* Name of this library. */
|
||||
const char*name;
|
||||
/* The cells that are contained in this library. */
|
||||
struct edif_cell_s*cells;
|
||||
/* point to the optional celltable. */
|
||||
const struct edif_xlib_celltable*celltable;
|
||||
/* used to list libraries in an edif_t. */
|
||||
struct edif_xlibrary_s*next;
|
||||
};
|
||||
|
||||
|
||||
struct __cell_port {
|
||||
const char*name;
|
||||
const char*ename;
|
||||
struct cellref_property_*property;
|
||||
ivl_signal_port_t dir;
|
||||
};
|
||||
|
||||
struct edif_cell_s {
|
||||
const char*name;
|
||||
edif_xlibrary_t xlib;
|
||||
|
||||
unsigned nports;
|
||||
struct __cell_port*ports;
|
||||
|
||||
struct cellref_property_*property;
|
||||
struct edif_cell_s*next;
|
||||
};
|
||||
|
||||
struct edif_cellref_s {
|
||||
struct edif_cell_s* cell;
|
||||
unsigned u;
|
||||
struct cellref_property_*property;
|
||||
struct edif_cellref_s* next;
|
||||
};
|
||||
|
||||
struct joint_cell_ {
|
||||
struct edif_cellref_s*cell;
|
||||
unsigned port;
|
||||
struct joint_cell_*next;
|
||||
};
|
||||
|
||||
/*
|
||||
* Joints link cell ports together. The edif_t object contains a list
|
||||
* of these joints, and each joint lists the ports that are connected
|
||||
* together. The port is represented by a joint_cell_.
|
||||
*
|
||||
* The links list a singly linked list of joint_cell_ objects. To add
|
||||
* a new link, simply push a new joint_cell_ into the links list. See
|
||||
* the edif_add_to_joint and edif_port_to_joint functions.
|
||||
*
|
||||
* The joints themselves are kept in a singly linked list in the
|
||||
* edif_t object. To create a new joint, simply push an initialized
|
||||
* edif_joint_s onto the nexa member of the edif_t object. See the
|
||||
* edif_joint_create function.
|
||||
*/
|
||||
struct edif_joint_s {
|
||||
const char*name;
|
||||
struct joint_cell_*links;
|
||||
struct edif_joint_s*next;
|
||||
};
|
||||
|
||||
|
||||
static int is_edif_name(const char*text)
|
||||
{
|
||||
static const char*edif_name_chars = "abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
return (strspn(text, edif_name_chars) == strlen(text));
|
||||
}
|
||||
|
||||
edif_t edif_create(const char*design_name, unsigned nports)
|
||||
{
|
||||
edif_t edf = malloc(sizeof(struct edif_s));
|
||||
|
||||
edf->name = design_name;
|
||||
edf->nports= nports;
|
||||
edf->ports = nports? calloc(nports, sizeof(struct __cell_port)) : 0;
|
||||
edf->celref= 0;
|
||||
edf->xlibs = 0;
|
||||
edf->property = 0;
|
||||
edf->nexa = 0;
|
||||
|
||||
return edf;
|
||||
}
|
||||
|
||||
void edif_portconfig(edif_t edf, unsigned idx,
|
||||
const char*name, ivl_signal_port_t dir)
|
||||
{
|
||||
assert(idx < edf->nports);
|
||||
|
||||
edf->ports[idx].name = name;
|
||||
if (is_edif_name(name)) {
|
||||
edf->ports[idx].ename = 0;
|
||||
|
||||
} else {
|
||||
char buf[16];
|
||||
sprintf(buf, "PORT%u", idx);
|
||||
edf->ports[idx].ename = strdup(buf);
|
||||
}
|
||||
|
||||
edf->ports[idx].dir = dir;
|
||||
}
|
||||
|
||||
void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port)
|
||||
{
|
||||
struct joint_cell_* jc = malloc(sizeof(struct joint_cell_));
|
||||
|
||||
jc->cell = 0;
|
||||
jc->port = port;
|
||||
jc->next = jnt->links;
|
||||
jnt->links = jc;
|
||||
}
|
||||
|
||||
void edif_pstring(edif_t edf, const char*name, const char*value)
|
||||
{
|
||||
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
|
||||
prp->name = name;
|
||||
prp->ptype = PRP_STRING;
|
||||
prp->value_.str = value;
|
||||
prp->next = edf->property;
|
||||
edf->property = prp;
|
||||
}
|
||||
|
||||
edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name)
|
||||
{
|
||||
edif_xlibrary_t xlib = malloc(sizeof(struct edif_xlibrary_s));
|
||||
|
||||
xlib->name = name;
|
||||
xlib->cells = 0;
|
||||
xlib->celltable = 0;
|
||||
xlib->next = edf->xlibs;
|
||||
edf->xlibs = xlib;
|
||||
|
||||
return xlib;
|
||||
}
|
||||
|
||||
void edif_xlibrary_set_celltable(edif_xlibrary_t xlib,
|
||||
const struct edif_xlib_celltable*tab)
|
||||
{
|
||||
assert(xlib->celltable == 0);
|
||||
xlib->celltable = tab;
|
||||
}
|
||||
|
||||
edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t xlib,
|
||||
const char*cell_name)
|
||||
{
|
||||
const struct edif_xlib_celltable*tcur;
|
||||
edif_cell_t cur;
|
||||
|
||||
for (cur = xlib->cells ; cur ; cur = cur->next) {
|
||||
if (strcmp(cell_name, cur->name) == 0)
|
||||
return cur;
|
||||
}
|
||||
|
||||
if (xlib->celltable == 0)
|
||||
return 0;
|
||||
|
||||
for (tcur = xlib->celltable ; tcur->cell_name ; tcur += 1)
|
||||
if (strcmp(cell_name, tcur->cell_name) == 0) {
|
||||
return (tcur->cell_func)(xlib);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib,
|
||||
ivl_scope_t scope)
|
||||
{
|
||||
unsigned port_count, idx;
|
||||
edif_cell_t cur;
|
||||
|
||||
/* Check to see if the cell is already somehow defined. */
|
||||
cur = edif_xlibrary_findcell(xlib, ivl_scope_tname(scope));
|
||||
if (cur) return cur;
|
||||
|
||||
/* Count the ports of the scope. */
|
||||
port_count = 0;
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
port_count += 1;
|
||||
}
|
||||
|
||||
cur = edif_xcell_create(xlib, ivl_scope_tname(scope), port_count);
|
||||
|
||||
port_count = 0;
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
edif_cell_portconfig(cur, port_count,
|
||||
ivl_signal_basename(sig),
|
||||
ivl_signal_port(sig));
|
||||
port_count += 1;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
edif_cell_t edif_xcell_create(edif_xlibrary_t xlib, const char*name,
|
||||
unsigned nports)
|
||||
{
|
||||
unsigned idx;
|
||||
edif_cell_t cell = malloc(sizeof(struct edif_cell_s));
|
||||
|
||||
cell->name = name;
|
||||
cell->xlib = xlib;
|
||||
cell->nports = nports;
|
||||
cell->ports = calloc(nports, sizeof(struct __cell_port));
|
||||
cell->property = 0;
|
||||
|
||||
for (idx = 0 ; idx < nports ; idx += 1) {
|
||||
cell->ports[idx].name = "?";
|
||||
cell->ports[idx].dir = IVL_SIP_NONE;
|
||||
cell->ports[idx].property = 0;
|
||||
}
|
||||
|
||||
cell->next = xlib->cells;
|
||||
xlib->cells = cell;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
void edif_cell_portconfig(edif_cell_t cell, unsigned idx,
|
||||
const char*name, ivl_signal_port_t dir)
|
||||
{
|
||||
assert(idx < cell->nports);
|
||||
|
||||
cell->ports[idx].name = name;
|
||||
cell->ports[idx].dir = dir;
|
||||
}
|
||||
|
||||
void edif_cell_port_pstring(edif_cell_t cell, unsigned idx,
|
||||
const char*name, const char*value)
|
||||
{
|
||||
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
|
||||
prp->name = name;
|
||||
prp->ptype = PRP_STRING;
|
||||
prp->value_.str = value;
|
||||
prp->next = cell->ports[idx].property;
|
||||
cell->ports[idx].property = prp;
|
||||
}
|
||||
|
||||
unsigned edif_cell_port_byname(edif_cell_t cell, const char*name)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
for (idx = 0 ; idx < cell->nports ; idx += 1) {
|
||||
if (cell->ports[idx].ename) {
|
||||
if (strcmp(name, cell->ports[idx].ename) == 0)
|
||||
break;
|
||||
} else {
|
||||
if (strcmp(name, cell->ports[idx].name) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void edif_cell_pstring(edif_cell_t cell, const char*name,
|
||||
const char*value)
|
||||
{
|
||||
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
|
||||
prp->name = name;
|
||||
prp->ptype = PRP_STRING;
|
||||
prp->value_.str = value;
|
||||
prp->next = cell->property;
|
||||
cell->property = prp;
|
||||
}
|
||||
|
||||
void edif_cell_pinteger(edif_cell_t cell, const char*name,
|
||||
int value)
|
||||
{
|
||||
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
|
||||
prp->name = name;
|
||||
prp->ptype = PRP_INTEGER;
|
||||
prp->value_.num = value;
|
||||
prp->next = cell->property;
|
||||
cell->property = prp;
|
||||
}
|
||||
|
||||
edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell)
|
||||
{
|
||||
static unsigned u_number = 0;
|
||||
edif_cellref_t ref = malloc(sizeof(struct edif_cellref_s));
|
||||
|
||||
u_number += 1;
|
||||
|
||||
assert(cell);
|
||||
assert(edf);
|
||||
|
||||
ref->u = u_number;
|
||||
ref->cell = cell;
|
||||
ref->property = 0;
|
||||
ref->next = edf->celref;
|
||||
edf->celref = ref;
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
void edif_cellref_pstring(edif_cellref_t ref, const char*name,
|
||||
const char*value)
|
||||
{
|
||||
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
|
||||
prp->name = name;
|
||||
prp->ptype = PRP_STRING;
|
||||
prp->value_.str = value;
|
||||
prp->next = ref->property;
|
||||
ref->property = prp;
|
||||
}
|
||||
|
||||
void edif_cellref_pinteger(edif_cellref_t ref, const char*name, int value)
|
||||
{
|
||||
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
|
||||
prp->name = name;
|
||||
prp->ptype = PRP_INTEGER;
|
||||
prp->value_.num = value;
|
||||
prp->next = ref->property;
|
||||
ref->property = prp;
|
||||
}
|
||||
|
||||
edif_joint_t edif_joint_create(edif_t edf)
|
||||
{
|
||||
edif_joint_t jnt = malloc(sizeof(struct edif_joint_s));
|
||||
|
||||
jnt->name = 0;
|
||||
jnt->links = 0;
|
||||
jnt->next = edf->nexa;
|
||||
edf->nexa = jnt;
|
||||
return jnt;
|
||||
}
|
||||
|
||||
edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex)
|
||||
{
|
||||
void*tmp = ivl_nexus_get_private(nex);
|
||||
edif_joint_t jnt;
|
||||
|
||||
if (tmp == 0) {
|
||||
jnt = edif_joint_create(edf);
|
||||
ivl_nexus_set_private(nex, jnt);
|
||||
return jnt;
|
||||
}
|
||||
|
||||
jnt = (edif_joint_t) tmp;
|
||||
return jnt;
|
||||
}
|
||||
|
||||
void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex)
|
||||
{
|
||||
void*tmp = ivl_nexus_get_private(nex);
|
||||
|
||||
if (tmp != 0) {
|
||||
/* There is a joint already on the nexus. Move all the
|
||||
joint cells to the joint I'm joining to. */
|
||||
edif_joint_t njnt = (edif_joint_t)tmp;
|
||||
while (njnt->links) {
|
||||
struct joint_cell_*cell = njnt->links;
|
||||
njnt->links = cell->next;
|
||||
cell->next = jnt->links;
|
||||
jnt->links = cell;
|
||||
}
|
||||
|
||||
/* Now njnt is dead, and should be removed from edif. */
|
||||
/* Or we can ignore it as harmless. */
|
||||
}
|
||||
|
||||
ivl_nexus_set_private(nex, jnt);
|
||||
}
|
||||
|
||||
void edif_joint_rename(edif_joint_t jnt, const char*name)
|
||||
{
|
||||
assert(jnt->name == 0);
|
||||
jnt->name = name;
|
||||
}
|
||||
|
||||
void edif_add_to_joint(edif_joint_t jnt, edif_cellref_t cell, unsigned port)
|
||||
{
|
||||
struct joint_cell_* jc = malloc(sizeof(struct joint_cell_));
|
||||
|
||||
jc->cell = cell;
|
||||
jc->port = port;
|
||||
jc->next = jnt->links;
|
||||
jnt->links = jc;
|
||||
}
|
||||
|
||||
static void fprint_property(FILE*fd, const struct cellref_property_*prp)
|
||||
{
|
||||
fprintf(fd, "(property %s ", prp->name);
|
||||
switch (prp->ptype) {
|
||||
case PRP_NONE:
|
||||
break;
|
||||
case PRP_STRING:
|
||||
fprintf(fd, "(string \"%s\")", prp->value_.str);
|
||||
break;
|
||||
case PRP_INTEGER:
|
||||
fprintf(fd, "(integer %ld)", prp->value_.num);
|
||||
break;
|
||||
}
|
||||
fprintf(fd, ")");
|
||||
}
|
||||
|
||||
/*
|
||||
* This function takes all the data structures that have been
|
||||
* assembled by the code generator, and writes them into an EDIF
|
||||
* formatted file.
|
||||
*/
|
||||
void edif_print(FILE*fd, edif_t edf)
|
||||
{
|
||||
edif_xlibrary_t xlib;
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
struct cellref_property_*prp;
|
||||
unsigned idx;
|
||||
|
||||
fprintf(fd, "(edif %s\n", edf->name);
|
||||
fprintf(fd, " (edifVersion 2 0 0)\n");
|
||||
fprintf(fd, " (edifLevel 0)\n");
|
||||
fprintf(fd, " (keywordMap (keywordLevel 0))\n");
|
||||
fprintf(fd, " (status\n");
|
||||
fprintf(fd, " (written\n");
|
||||
fprintf(fd, " (timeStamp 0 0 0 0 0 0)\n");
|
||||
fprintf(fd, " (author \"unknown\")\n");
|
||||
fprintf(fd, " (program \"Icarus Verilog/edif.tgt\")))\n");
|
||||
fflush(fd);
|
||||
|
||||
for (xlib = edf->xlibs ; xlib ; xlib = xlib->next) {
|
||||
|
||||
fprintf(fd, " (external %s "
|
||||
"(edifLevel 0) "
|
||||
"(technology (numberDefinition))\n",
|
||||
xlib->name);
|
||||
|
||||
for (cell = xlib->cells ; cell ; cell = cell->next) {
|
||||
fprintf(fd, " (cell %s (cellType GENERIC)\n",
|
||||
cell->name);
|
||||
fprintf(fd, " (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface");
|
||||
|
||||
for (idx = 0 ; idx < cell->nports ; idx += 1) {
|
||||
struct __cell_port*pp = cell->ports + idx;
|
||||
fprintf(fd, "\n (port %s", pp->name);
|
||||
switch (pp->dir) {
|
||||
case IVL_SIP_INPUT:
|
||||
fprintf(fd, " (direction INPUT)");
|
||||
break;
|
||||
case IVL_SIP_OUTPUT:
|
||||
fprintf(fd, " (direction OUTPUT)");
|
||||
break;
|
||||
case IVL_SIP_INOUT:
|
||||
fprintf(fd, " (direction INOUT)");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (prp = pp->property ; prp ; prp=prp->next) {
|
||||
fprintf(fd, " ");
|
||||
fprint_property(fd, prp);
|
||||
}
|
||||
|
||||
fprintf(fd, ")");
|
||||
}
|
||||
|
||||
for (prp = cell->property ; prp ; prp = prp->next) {
|
||||
fprintf(fd, "\n ");
|
||||
fprint_property(fd, prp);
|
||||
}
|
||||
fprintf(fd, ")))\n");
|
||||
}
|
||||
|
||||
fprintf(fd, " )\n"); /* terminate (external ...) sexp */
|
||||
}
|
||||
fflush(fd);
|
||||
|
||||
/* Write out the library header */
|
||||
fprintf(fd, " (library DESIGN\n");
|
||||
fprintf(fd, " (edifLevel 0)\n");
|
||||
fprintf(fd, " (technology (numberDefinition))\n");
|
||||
|
||||
/* The root module is a cell in the library. */
|
||||
fprintf(fd, " (cell %s\n", edf->name);
|
||||
fprintf(fd, " (cellType GENERIC)\n");
|
||||
fprintf(fd, " (view net\n");
|
||||
fprintf(fd, " (viewType NETLIST)\n");
|
||||
fprintf(fd, " (interface\n");
|
||||
|
||||
for (idx = 0 ; idx < edf->nports ; idx += 1) {
|
||||
fprintf(fd, " (port ");
|
||||
if (edf->ports[idx].ename == 0)
|
||||
fprintf(fd, "%s ", edf->ports[idx].name);
|
||||
else
|
||||
fprintf(fd, "(rename %s \"%s\") ",
|
||||
edf->ports[idx].ename,
|
||||
edf->ports[idx].name);
|
||||
|
||||
switch (edf->ports[idx].dir) {
|
||||
case IVL_SIP_INPUT:
|
||||
fprintf(fd, "(direction INPUT)");
|
||||
break;
|
||||
case IVL_SIP_OUTPUT:
|
||||
fprintf(fd, "(direction OUTPUT)");
|
||||
break;
|
||||
case IVL_SIP_INOUT:
|
||||
fprintf(fd, "(direction INOUT)");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fprintf(fd, ")\n");
|
||||
}
|
||||
|
||||
fprintf(fd, " )\n"); /* end the (interface ) sexp */
|
||||
fflush(fd);
|
||||
|
||||
fprintf(fd, " (contents\n");
|
||||
|
||||
/* Display all the instances. */
|
||||
for (ref = edf->celref ; ref ; ref = ref->next) {
|
||||
|
||||
assert(ref->cell);
|
||||
|
||||
fprintf(fd, "(instance U%u (viewRef net "
|
||||
"(cellRef %s (libraryRef %s)))",
|
||||
ref->u, ref->cell->name, ref->cell->xlib->name);
|
||||
|
||||
for (prp = ref->property ; prp ; prp = prp->next) {
|
||||
fprintf(fd, " ");
|
||||
fprint_property(fd, prp);
|
||||
}
|
||||
|
||||
fprintf(fd, ")\n");
|
||||
}
|
||||
|
||||
fflush(fd);
|
||||
|
||||
/* Display all the joints. */
|
||||
idx = 0;
|
||||
for (jnt = edf->nexa ; jnt ; jnt = jnt->next, idx += 1) {
|
||||
struct joint_cell_*jc;
|
||||
|
||||
/* Skip nil joints. */
|
||||
if (jnt->links == 0)
|
||||
continue;
|
||||
|
||||
fprintf(fd, "(net ");
|
||||
if (jnt->name != 0)
|
||||
fprintf(fd, "(rename N%u \"%s\")", idx, jnt->name);
|
||||
else
|
||||
fprintf(fd, "N%u", idx);
|
||||
fprintf(fd, " (joined");
|
||||
|
||||
for (jc = jnt->links ; jc ; jc = jc->next) {
|
||||
if (jc->cell) {
|
||||
fprintf(fd, " (portRef %s (instanceRef U%u))",
|
||||
jc->cell->cell->ports[jc->port].name,
|
||||
jc->cell->u);
|
||||
} else {
|
||||
/* Reference to a port of the main cell. */
|
||||
if (edf->ports[jc->port].ename)
|
||||
fprintf(fd, " (portRef %s)",
|
||||
edf->ports[jc->port].ename);
|
||||
else
|
||||
fprintf(fd, " (portRef %s)",
|
||||
edf->ports[jc->port].name);
|
||||
}
|
||||
}
|
||||
fprintf(fd, "))\n");
|
||||
}
|
||||
|
||||
fprintf(fd, " )\n"); /* end the (contents...) sexp */
|
||||
|
||||
fprintf(fd, " )\n"); /* end the (view ) sexp */
|
||||
fprintf(fd, " )\n"); /* end the (cell ) sexp */
|
||||
fprintf(fd, " )\n"); /* end the (library DESIGN) sexp */
|
||||
|
||||
/* Make an instance of the defined object */
|
||||
fprintf(fd, " (design %s\n", edf->name);
|
||||
fprintf(fd, " (cellRef %s (libraryRef DESIGN))\n", edf->name);
|
||||
|
||||
for (prp = edf->property ; prp ; prp = prp->next) {
|
||||
fprintf(fd, " ");
|
||||
fprint_property(fd, prp);
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
|
||||
fprintf(fd, " )\n");
|
||||
|
||||
|
||||
|
||||
fprintf(fd, ")\n");
|
||||
fflush(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: edif.c,v $
|
||||
* Revision 1.1.2.3 2006/11/11 21:21:21 steve
|
||||
* Make signal lookup use extended names.
|
||||
*
|
||||
* Revision 1.1.2.2 2005/08/21 22:25:51 steve
|
||||
* Fix the comment in the EDIT header.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=edif.tgt
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
#ifndef __edif_H
|
||||
#define __edif_H
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: edif.h,v 1.1.2.3 2007/02/26 19:51:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include <ivl_target.h>
|
||||
|
||||
/*
|
||||
* These types and functions support the task of generating and
|
||||
* writing out an EDIF 2 0 0 netlist. These functions work by
|
||||
* supporting the creation of an in-core netlist of the design, then
|
||||
* writing the netlist out all at once. The library manages cells with
|
||||
* ports, but does not otherwise interpret cells. They have no
|
||||
* contents.
|
||||
*
|
||||
* The general structure of netlist creation is as follows:
|
||||
*
|
||||
* Create a netlist with edif_create(<name>);
|
||||
* This creates an edif object that represents the design. The
|
||||
* design is given a name, and that name becomes the name of the
|
||||
* single cell that this netlist handles.
|
||||
*
|
||||
* Add ports to the root with edif_portconfig
|
||||
* The design may, if it is a macro to be included in a larger
|
||||
* design, include ports. These are discovered by looking for port
|
||||
* signals in the root module.
|
||||
*
|
||||
* Declare external libraries with edif_xlibrary_create
|
||||
* Normally, this is the single technology library that contains
|
||||
* the primitive cells that the code generator intends to
|
||||
* use. The library is given a name, such as VIRTEX or whatever
|
||||
* the implementation tools expect. Cells are attached to the
|
||||
* library later. An edif netlist may include multiple external
|
||||
* references.
|
||||
*
|
||||
* Declare primitives with edif_xcell_create and edif_cell_portconfig.
|
||||
* These functions create CELL TYPES that are attached to an
|
||||
* external library. The libraries are created by
|
||||
* edif_xlibrary_create.
|
||||
*
|
||||
* Cells can be created at any time before their first use. It
|
||||
* therefore makes the most sense to not create the cell until it
|
||||
* is certain that they are needed by the design.
|
||||
*
|
||||
* Create instances and join them up
|
||||
* The edif_cellref_t objects represent instances of cells, and
|
||||
* are the devices of the generated netlist. These cellrefs are
|
||||
* connected together by the use of edif_joint_t joints. The
|
||||
* joints can be created from ivl_nexus_t objects, or from their
|
||||
* own ether. This instantiating of cells and joining them
|
||||
* together that is the most fun. It is the technology specific
|
||||
* stuff that the code generator does.
|
||||
*
|
||||
* Finally, print the result with edif_print(fd);
|
||||
* This function writes the netlist in memory to an EDIF file on
|
||||
* the stdio stream specified.
|
||||
*
|
||||
* This library is intended to be used once, to build up a netlist and
|
||||
* print it. All the names that are taken as const char* should be
|
||||
* somehow made permanent by the caller. Either they are constant
|
||||
* strings, or they are strduped as necessary to make them
|
||||
* permanent. The library will not duplicate them.
|
||||
*/
|
||||
|
||||
/* TYPE DECLARATIONS */
|
||||
|
||||
/* This represents the entire EDIF design. You only need one of these
|
||||
to hold everything. */
|
||||
typedef struct edif_s* edif_t;
|
||||
|
||||
/* Each external library of the design gets one of these. */
|
||||
typedef struct edif_xlibrary_s* edif_xlibrary_t;
|
||||
|
||||
/* This represents a type of cell. */
|
||||
typedef struct edif_cell_s* edif_cell_t;
|
||||
|
||||
/* A cellref is an *instance* of a cell. */
|
||||
typedef struct edif_cellref_s* edif_cellref_t;
|
||||
|
||||
/* This represents a generic joint. Cell ports are connected by being
|
||||
associated with a joint. These can be bound to an ivl_nexus_t
|
||||
object, of stand along. */
|
||||
typedef struct edif_joint_s* edif_joint_t;
|
||||
|
||||
/* This structure defines a table that can be attached to an xlibrary
|
||||
to incorporate black-box cells to the library. The cell_name is the
|
||||
name that may be passed to the edif_xlibrary_findcell function, and
|
||||
the function pointer points to a function that creates the cell and
|
||||
defines ports for it. A real celltable is terminated by an entry
|
||||
with a null pointer for the cell_name. */
|
||||
struct edif_xlib_celltable {
|
||||
const char*cell_name;
|
||||
edif_cell_t (*cell_func)(edif_xlibrary_t xlib);
|
||||
};
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
|
||||
/* Start a new EDIF design. The design_name will be used as the name
|
||||
of the top-mode module of the design. */
|
||||
extern edif_t edif_create(const char*design_name, unsigned nports);
|
||||
|
||||
/* macro ports to the design are handled by this library similar to
|
||||
cells. The user creates ports with this function. This function
|
||||
configures the sole "port" of the cell with the name and dir passed
|
||||
in. The direction, in this case, is the *interface* direction. */
|
||||
extern void edif_portconfig(edif_t edf, unsigned idx,
|
||||
const char*name, ivl_signal_port_t dir);
|
||||
|
||||
/* This is like edif_add_to_joint, but works with the edif port. */
|
||||
extern void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port);
|
||||
|
||||
/* The design may have properties attached to it. These properties
|
||||
will be attached to the instance declared in the footer of the EDIF
|
||||
file. */
|
||||
extern void edif_pstring(edif_t edf, const char*name, const char*value);
|
||||
|
||||
/* Create an external library and attach it to the edif design. This
|
||||
will lead to a (external ...) declaration of cells that can be used
|
||||
by the design. */
|
||||
extern edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name);
|
||||
|
||||
extern void edif_xlibrary_set_celltable(edif_xlibrary_t lib,
|
||||
const struct edif_xlib_celltable*table);
|
||||
|
||||
|
||||
/* External libraries can be searched for existing cells, given a
|
||||
string name. This function searches for the cell by name, and
|
||||
returns it. */
|
||||
extern edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t lib,
|
||||
const char*cell_name);
|
||||
|
||||
/* Similar to the above, but it gets the information it needs from the
|
||||
ivl_scope_t object. */
|
||||
extern edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib,
|
||||
ivl_scope_t scope);
|
||||
|
||||
/* Create a new cell, attached to the external library. Specify the
|
||||
number of ports that the cell has. The edif_cell_portconfig
|
||||
function is then used to assign name and direction to each of the
|
||||
ports.
|
||||
|
||||
The cell has a number of pins that are referenced by their number
|
||||
from 0 to nports-1. You need to remember the pin numbers for the
|
||||
named ports for use when joining that pin to an edif_joint_t.
|
||||
|
||||
Cellrefs get their port characteristics from the cell that they are
|
||||
created from. So the pinouts of cellrefs match the pinout of the
|
||||
associated cell. */
|
||||
extern edif_cell_t edif_xcell_create(edif_xlibrary_t, const char*name,
|
||||
unsigned nports);
|
||||
extern void edif_cell_portconfig(edif_cell_t cell, unsigned idx,
|
||||
const char*name, ivl_signal_port_t dir);
|
||||
|
||||
/* Attach a property to a cell port. */
|
||||
extern void edif_cell_port_pstring(edif_cell_t cell, unsigned idx,
|
||||
const char*name, const char*value);
|
||||
|
||||
/* Cells may have properties attached to them. These properties are
|
||||
included in the library declaration for the cell, instead of the
|
||||
cell instances. */
|
||||
extern void edif_cell_pstring(edif_cell_t cell, const char*name,
|
||||
const char*value);
|
||||
extern void edif_cell_pinteger(edif_cell_t cell, const char*name,
|
||||
int value);
|
||||
|
||||
|
||||
/* Ports of cells are normally referenced by their port number. If you
|
||||
forget what that number is, this function can look it up by name. */
|
||||
extern unsigned edif_cell_port_byname(edif_cell_t cell, const char*name);
|
||||
|
||||
|
||||
/* Create and instance from a cell. The instance refers to the cell,
|
||||
which is a type, and contains pips for pins. */
|
||||
extern edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell);
|
||||
|
||||
/* Instances can have properties attached to them. The name and value
|
||||
given here are turned into a (property <name> (string "val"))
|
||||
expression attached to the instance.
|
||||
|
||||
Examples of string properties commonly attached to cellref devices
|
||||
include such things as the INIT=<value> to initialize LUT cells in
|
||||
FPGA devices. */
|
||||
extern void edif_cellref_pstring(edif_cellref_t ref, const char*name,
|
||||
const char*value);
|
||||
extern void edif_cellref_pinteger(edif_cellref_t ref, const char*name,
|
||||
int value);
|
||||
|
||||
/* This function gets the joint associated with a nexus. This will
|
||||
create a joint if necessary. */
|
||||
extern edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex);
|
||||
|
||||
/* For linking cells outside the ivl netlist, this function creates an
|
||||
anonymous joint. */
|
||||
extern edif_joint_t edif_joint_create(edif_t edf);
|
||||
|
||||
/* Renaming a joint causes it to take on a name when external tools
|
||||
view the EDIF file. */
|
||||
extern void edif_joint_rename(edif_joint_t jnt, const char*name);
|
||||
|
||||
/* Given a joint, this function adds the cell reference. */
|
||||
extern void edif_add_to_joint(edif_joint_t jnt,
|
||||
edif_cellref_t cell,
|
||||
unsigned port);
|
||||
|
||||
extern void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex);
|
||||
|
||||
/*
|
||||
* Print the entire design. This should only be done after the design
|
||||
* is completely assembled.
|
||||
*/
|
||||
extern void edif_print(FILE*fd, edif_t design);
|
||||
|
||||
/*
|
||||
* This is the fd that should be passed to the edif_print
|
||||
* function. The name "xnf" is historical. This function is opened and
|
||||
* closed automatically by the edif core (the target_design function)
|
||||
* so generally there is no other use then the edif_print for this
|
||||
* exposed fd.
|
||||
*/
|
||||
extern FILE*xnf;
|
||||
|
||||
|
||||
/*
|
||||
* $Log: edif.h,v $
|
||||
* Revision 1.1.2.3 2007/02/26 19:51:39 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.1.2.2 2005/09/25 16:35:36 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef __fpga_priv_H
|
||||
#define __fpga_priv_H
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: edif_priv.h,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include "device.h"
|
||||
|
||||
extern int show_scope_gates(ivl_scope_t net, void*x);
|
||||
|
||||
|
||||
extern device_t device;
|
||||
|
||||
extern const char*part;
|
||||
extern const char*arch;
|
||||
|
||||
/*
|
||||
* Attribute lookup, should this be provided in ivl_target.h?
|
||||
*/
|
||||
int scope_has_attribute(ivl_scope_t s, const char *name);
|
||||
|
||||
/*
|
||||
* These are mangle functions.
|
||||
*/
|
||||
extern void xnf_mangle_logic_name(ivl_net_logic_t net, char*buf, size_t nbuf);
|
||||
extern void xnf_mangle_lpm_name(ivl_lpm_t net, char*buf, size_t nbuf);
|
||||
|
||||
extern const char*xnf_mangle_nexus_name(ivl_nexus_t net);
|
||||
|
||||
|
||||
/*
|
||||
* $Log: edif_priv.h,v $
|
||||
* Revision 1.1.2.2 2005/09/25 16:35:36 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: gates.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "edif_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
static void show_cell_scope(ivl_scope_t scope)
|
||||
{
|
||||
if (device->show_cell_scope == 0) {
|
||||
fprintf(stderr, "fpga.tgt: ivl_synthesis_cell(scope)"
|
||||
" not supported by this target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
device->show_cell_scope(scope);
|
||||
}
|
||||
|
||||
static void show_gate_logic(ivl_net_logic_t net)
|
||||
{
|
||||
if (device->show_logic == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL LOGIC not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(device->show_logic);
|
||||
device->show_logic(net);
|
||||
}
|
||||
|
||||
static void show_gate_lpm(ivl_lpm_t net)
|
||||
{
|
||||
switch (ivl_lpm_type(net)) {
|
||||
|
||||
case IVL_LPM_ADD:
|
||||
if (device->show_add == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_ADD not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_add(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SUB:
|
||||
if (device->show_sub == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_SUB not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_sub(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_CMP_EQ:
|
||||
if (device->show_cmp_eq == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_EQ not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_cmp_eq(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_CMP_NE:
|
||||
if (device->show_cmp_ne == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_NE not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_cmp_ne(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_CMP_GE:
|
||||
if (device->show_cmp_ge == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GE not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_cmp_ge(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_CMP_GT:
|
||||
if (device->show_cmp_gt == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GT not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_cmp_gt(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
if (device->show_dff == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_FF not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_dff(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
if (device->show_mux == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_MUX not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_mux(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_MULT:
|
||||
if (device->show_mult == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_MULT not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_mult(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
if (device->show_shiftl == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTL not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_shiftl(net);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SHIFTR:
|
||||
if (device->show_shiftr == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTR not supported"
|
||||
" by this target.\n");
|
||||
return;
|
||||
}
|
||||
device->show_shiftr(net);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "fpga.tgt: unknown LPM type %u\n",
|
||||
ivl_lpm_type(net));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int show_scope_gates(ivl_scope_t net, void*x)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
if (scope_has_attribute(net, "ivl_synthesis_cell")) {
|
||||
show_cell_scope(net);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1)
|
||||
show_gate_logic(ivl_scope_log(net, idx));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1)
|
||||
show_gate_lpm(ivl_scope_lpm(net, idx));
|
||||
|
||||
return ivl_scope_children(net, show_scope_gates, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: gates.c,v $
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: generic.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "generic.h"
|
||||
|
||||
edif_t edf = 0;
|
||||
edif_xlibrary_t xlib = 0;
|
||||
|
||||
edif_cell_t cell_0 = 0;
|
||||
edif_cell_t cell_1 = 0;
|
||||
|
||||
edif_cell_t cell_ipad = 0;
|
||||
edif_cell_t cell_opad = 0;
|
||||
edif_cell_t cell_iopad = 0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* $Log: generic.c,v $
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef __generic_H
|
||||
#define __generic_H
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: generic.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "edif.h"
|
||||
|
||||
extern edif_t edf;
|
||||
extern edif_xlibrary_t xlib;
|
||||
|
||||
/*
|
||||
* The cell_* variables below are the various kinds of devices that
|
||||
* this family supports as primitives. If the cell type is used at
|
||||
* least once, then the edif_cell_t is non-zero and will also be
|
||||
* included in the library declaration. The constants underneath are
|
||||
* pin assignments for the cell.
|
||||
*/
|
||||
|
||||
extern edif_cell_t cell_0;
|
||||
extern edif_cell_t cell_1;
|
||||
|
||||
extern edif_cell_t cell_ipad;
|
||||
extern edif_cell_t cell_opad;
|
||||
extern edif_cell_t cell_iopad;
|
||||
|
||||
|
||||
/*
|
||||
* $Log: generic.h,v $
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: tables.c,v 1.1.2.3 2007/02/26 19:51:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* This is where you hook new device types into the module. Simply
|
||||
* declare your struct device_s objects (as done with d_lpm_edif) and
|
||||
* add an entry in to the edif_device_table so that the user may invoke
|
||||
* it via the -parch=<foo> command line switch.
|
||||
*/
|
||||
extern const struct device_s d_lpm_edif;
|
||||
extern const struct device_s d_virtex_edif;
|
||||
|
||||
const struct device_table_s edif_device_table[] = {
|
||||
{ "lpm", &d_lpm_edif },
|
||||
{ "virtex",&d_virtex_edif },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: tables.c,v $
|
||||
* Revision 1.1.2.3 2007/02/26 19:51:39 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.1.2.2 2005/09/25 16:35:37 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This is the EDIF target module.
|
||||
*/
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include <string.h>
|
||||
# include "edif_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
/* This is the opened xnf file descriptor. It is the output that this
|
||||
code generator writes to. */
|
||||
FILE*xnf = 0;
|
||||
|
||||
const char*part = 0;
|
||||
const char*arch = 0;
|
||||
device_t device = 0;
|
||||
|
||||
int scope_has_attribute(ivl_scope_t s, const char *name)
|
||||
{
|
||||
int i;
|
||||
const struct ivl_attribute_s *a;
|
||||
for (i=0; i<ivl_scope_attr_cnt(s); i++) {
|
||||
a = ivl_scope_attr_val(s, i);
|
||||
if (strcmp(a->key,name) == 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_process(ivl_process_t net, void*x)
|
||||
{
|
||||
ivl_scope_t scope = ivl_process_scope(net);
|
||||
|
||||
/* Ignore processes that are within scopes that are cells. The
|
||||
cell_scope will generate a cell to represent the entire
|
||||
scope. */
|
||||
if (scope_has_attribute(scope, "ivl_synthesis_cell"))
|
||||
return 0;
|
||||
|
||||
fprintf(stderr, "fpga target: unsynthesized behavioral code\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_pads(ivl_scope_t scope)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
if (device->show_pad == 0)
|
||||
return;
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, idx);
|
||||
const char*pad;
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
pad = ivl_signal_attr(sig, "PAD");
|
||||
if (pad == 0)
|
||||
continue;
|
||||
|
||||
assert(device->show_pad);
|
||||
device->show_pad(sig, pad);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_constants(ivl_design_t des)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
if (device->show_constant == 0)
|
||||
return;
|
||||
|
||||
for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) {
|
||||
ivl_net_const_t con = ivl_design_const(des, idx);
|
||||
device->show_constant(con);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main entry point that ivl uses to invoke me, the code
|
||||
* generator.
|
||||
*/
|
||||
int target_design(ivl_design_t des)
|
||||
{
|
||||
ivl_scope_t root = ivl_design_root(des);
|
||||
const char*path = ivl_design_flag(des, "-o");
|
||||
|
||||
xnf = fopen(path, "w");
|
||||
if (xnf == 0) {
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
part = ivl_design_flag(des, "part");
|
||||
if (part && (part[0] == 0))
|
||||
part = 0;
|
||||
|
||||
arch = ivl_design_flag(des, "arch");
|
||||
if (arch && (arch[0] == 0))
|
||||
arch = 0;
|
||||
|
||||
if (arch == 0)
|
||||
arch = "lpm";
|
||||
|
||||
device = device_from_arch(arch);
|
||||
if (device == 0) {
|
||||
fprintf(stderr, "Unknown architecture arch=%s\n", arch);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Call the device driver to generate the netlist header. */
|
||||
device->show_header(des);
|
||||
|
||||
/* Catch any behavioral code that is left, and write warnings
|
||||
that it is not supported. */
|
||||
ivl_design_process(des, show_process, 0);
|
||||
|
||||
/* Get the pads from the design, and draw them to connect to
|
||||
the associated signals. */
|
||||
show_pads(root);
|
||||
|
||||
/* Scan the scopes, looking for gates to draw into the output
|
||||
netlist. */
|
||||
show_scope_gates(root, 0);
|
||||
|
||||
show_constants(des);
|
||||
|
||||
/* Call the device driver to close out the file. */
|
||||
device->show_footer(des);
|
||||
|
||||
fclose(xnf);
|
||||
xnf = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function tests whether the nexus has a constant value. It
|
||||
* returns true if the value is constant, or false if there are
|
||||
* non-constant or conflicting drivers.
|
||||
*/
|
||||
int test_nexus_constant(ivl_nexus_t nex, char*val)
|
||||
{
|
||||
int count_drivers = 0;
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_net_const_t con;
|
||||
unsigned pin;
|
||||
const char*cbits;
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
|
||||
|
||||
/* If this nexus link is an input pin to the device (or
|
||||
otherwise does not drive the nexus) then skip it. */
|
||||
if (ivl_nexus_ptr_drive0(ptr) == IVL_DR_HiZ
|
||||
&& ivl_nexus_ptr_drive1(ptr) == IVL_DR_HiZ)
|
||||
continue;
|
||||
|
||||
count_drivers += 1;
|
||||
|
||||
/* If this driver is not a constant, then the test fails
|
||||
certainly. */
|
||||
con = ivl_nexus_ptr_con(ptr);
|
||||
if (con == 0)
|
||||
return 0;
|
||||
|
||||
/* Get the pin number within the constant where this
|
||||
nexus is connected. */
|
||||
pin = ivl_nexus_ptr_pin(ptr);
|
||||
|
||||
/* The pin for the constant that we located is
|
||||
guaranteed to really point to the nexus that we are
|
||||
working with. */
|
||||
assert(ivl_const_pins(con) > pin);
|
||||
assert(ivl_const_pin(con,pin) == nex);
|
||||
|
||||
/* Get the bit value from the constant. If there are
|
||||
multiple constants driving this nexus (an unlikely
|
||||
situation) then allow for them only if their value
|
||||
matches. But the more common case is that this is the
|
||||
only driver for the nexus. Save the constant value in
|
||||
the *val result that we pass back to the user. */
|
||||
cbits = ivl_const_bits(con);
|
||||
if (count_drivers > 1) {
|
||||
if (val[0] != cbits[pin])
|
||||
return 0;
|
||||
} else {
|
||||
val[0] = cbits[pin];
|
||||
}
|
||||
}
|
||||
|
||||
/* If in the end there are no drivers at all for the nexus,
|
||||
then assume the nexus has a constant HiZ value. */
|
||||
if (count_drivers == 0)
|
||||
*val = 'z';
|
||||
|
||||
/* Return TRUE */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: target.c,v $
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,983 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve at icarus.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xilinx.c,v 1.1.2.2 2007/02/26 19:51:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This source file contains common functions used by Xilinx
|
||||
* devices. The functions here do not support any specific Xilinx part
|
||||
* family, but instead provide some core functions that are used by
|
||||
* specific devices.
|
||||
*
|
||||
* For example, some xilinx_* functions are suitable for placing
|
||||
* directly in a device_s table, but there is no "xilinx"
|
||||
* device. These functions can be placed in the tables for devices
|
||||
* that have no better way to handle the device_s function, or these
|
||||
* functions can be called by device specific device_s functions that
|
||||
* fall back on the generic handling in certain cases. For an example
|
||||
* of both cases, see d-virtex.c.
|
||||
*/
|
||||
|
||||
# include "edif.h"
|
||||
# include "generic.h"
|
||||
# include "xilinx.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
edif_cell_t xilinx_cell_buf(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUF", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUFE", 3);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, BUF_T, "E", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUFG", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUFT", 3);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, BUF_T, "T", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "IBUF", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_inv(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "INV", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXF5", 4);
|
||||
edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXF6", 4);
|
||||
edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "OBUF", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "LUT2", 3);
|
||||
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "LUT3", 4);
|
||||
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I2, "I2", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "LUT4", 5);
|
||||
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I2, "I2", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I3, "I3", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "FDCE", 5);
|
||||
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CLR,"CLR", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "FDCPE", 6);
|
||||
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CLR,"CLR", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_PRE,"PRE", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "FDRE", 5);
|
||||
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CLR,"R", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MULT_AND", 3);
|
||||
edif_cell_portconfig(cell, MULT_AND_LO, "LO", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MULT_AND_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MULT_AND_I1, "I1", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXCY", 4);
|
||||
edif_cell_portconfig(cell, MUXCY_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXCY_L", 4);
|
||||
edif_cell_portconfig(cell, MUXCY_O, "LO", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "XORCY", 3);
|
||||
edif_cell_portconfig(cell, XORCY_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, XORCY_CI, "CI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, XORCY_LI, "LI", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function does a lot of the stuff common to the header
|
||||
* functions of various Xilinx families. This includes creating the edf
|
||||
* object that holds the netlist.
|
||||
*/
|
||||
void xilinx_common_header(ivl_design_t des)
|
||||
{
|
||||
unsigned idx;
|
||||
ivl_scope_t root = ivl_design_root(des);
|
||||
unsigned sig_cnt = ivl_scope_sigs(root);
|
||||
unsigned nports = 0, pidx;
|
||||
|
||||
/* Count the ports I'm going to use. */
|
||||
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(root, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_attr(sig, "PAD") != 0)
|
||||
continue;
|
||||
|
||||
nports += ivl_signal_pins(sig);
|
||||
}
|
||||
|
||||
edf = edif_create(ivl_scope_basename(root), nports);
|
||||
|
||||
pidx = 0;
|
||||
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
ivl_signal_t sig = ivl_scope_sig(root, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_attr(sig, "PAD") != 0)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_pins(sig) == 1) {
|
||||
edif_portconfig(edf, pidx, ivl_signal_basename(sig),
|
||||
ivl_signal_port(sig));
|
||||
|
||||
assert(ivl_signal_pins(sig) == 1);
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
|
||||
edif_port_to_joint(jnt, edf, pidx);
|
||||
|
||||
} else {
|
||||
const char*name = ivl_signal_basename(sig);
|
||||
ivl_signal_port_t dir = ivl_signal_port(sig);
|
||||
char buf[128];
|
||||
unsigned bit;
|
||||
for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) {
|
||||
const char*tmp;
|
||||
sprintf(buf, "%s[%u]", name, bit);
|
||||
tmp = strdup(buf);
|
||||
edif_portconfig(edf, pidx+bit, tmp, dir);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
|
||||
edif_port_to_joint(jnt, edf, pidx+bit);
|
||||
}
|
||||
}
|
||||
|
||||
pidx += ivl_signal_pins(sig);
|
||||
}
|
||||
|
||||
assert(pidx == nports);
|
||||
}
|
||||
|
||||
void xilinx_show_footer(ivl_design_t des)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) {
|
||||
unsigned pin;
|
||||
ivl_net_const_t net = ivl_design_const(des, idx);
|
||||
const char*val = ivl_const_bits(net);
|
||||
|
||||
for (pin = 0 ; pin < ivl_const_pins(net) ; pin += 1) {
|
||||
edif_joint_t jnt;
|
||||
edif_cellref_t pad;
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_const_pin(net, pin));
|
||||
switch (val[pin]) {
|
||||
case '0':
|
||||
pad = edif_cellref_create(edf, cell_0);
|
||||
break;
|
||||
case '1':
|
||||
pad = edif_cellref_create(edf, cell_1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
}
|
||||
}
|
||||
|
||||
edif_print(xnf, edf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make (or retrieve) a cell in the external library that reflects the
|
||||
* scope with its ports.
|
||||
*/
|
||||
void xilinx_show_scope(ivl_scope_t scope)
|
||||
{
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
|
||||
unsigned port, idx;
|
||||
|
||||
cell = edif_xlibrary_scope_cell(xlib, scope);
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
port = edif_cell_port_byname(cell, ivl_signal_basename(sig));
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
|
||||
edif_add_to_joint(jnt, ref, port);
|
||||
}
|
||||
}
|
||||
|
||||
void xilinx_pad(ivl_signal_t sig, const char*str)
|
||||
{
|
||||
unsigned idx;
|
||||
char**pins;
|
||||
|
||||
if (cell_ipad == 0) {
|
||||
cell_ipad = edif_xcell_create(xlib, "IPAD", 1);
|
||||
edif_cell_portconfig(cell_ipad, 0, "IPAD", IVL_SIP_OUTPUT);
|
||||
}
|
||||
|
||||
if (cell_opad == 0) {
|
||||
cell_opad = edif_xcell_create(xlib, "OPAD", 1);
|
||||
edif_cell_portconfig(cell_opad, 0, "OPAD", IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
if (cell_iopad == 0) {
|
||||
cell_iopad = edif_xcell_create(xlib, "IOPAD", 1);
|
||||
edif_cell_portconfig(cell_iopad, 0, "IOPAD", IVL_SIP_INOUT);
|
||||
}
|
||||
|
||||
/* Collect an array of pin assignments from the attribute
|
||||
string passed in as str. The format is a comma separated
|
||||
list of location names. */
|
||||
pins = calloc(ivl_signal_pins(sig), sizeof(char*));
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
const char*tmp = strchr(str, ',');
|
||||
if (tmp == 0) tmp = str+strlen(str);
|
||||
|
||||
pins[idx] = malloc(tmp-str+1);
|
||||
strncpy(pins[idx], str, tmp-str);
|
||||
pins[idx][tmp-str] = 0;
|
||||
|
||||
if (*tmp != 0)
|
||||
tmp += 1;
|
||||
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
/* Now go through the pins of the signal, creating pads and
|
||||
bufs and joining them to the signal nexus. */
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
edif_cellref_t pad, buf;
|
||||
|
||||
const char*name_str = ivl_signal_basename(sig);
|
||||
if (ivl_signal_pins(sig) > 1) {
|
||||
char name_buf[128];
|
||||
sprintf(name_buf, "%s[%u]", name_str, idx);
|
||||
name_str = strdup(name_buf);
|
||||
}
|
||||
|
||||
switch (ivl_signal_port(sig)) {
|
||||
case IVL_SIP_INPUT:
|
||||
pad = edif_cellref_create(edf, cell_ipad);
|
||||
buf = edif_cellref_create(edf, xilinx_cell_ibuf(xlib));
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_joint_rename(jnt, name_str);
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
edif_add_to_joint(jnt, buf, BUF_I);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
|
||||
edif_add_to_joint(jnt, buf, BUF_O);
|
||||
break;
|
||||
|
||||
case IVL_SIP_OUTPUT:
|
||||
pad = edif_cellref_create(edf, cell_opad);
|
||||
buf = edif_cellref_create(edf, xilinx_cell_obuf(xlib));
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_joint_rename(jnt, name_str);
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
edif_add_to_joint(jnt, buf, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
|
||||
edif_add_to_joint(jnt, buf, BUF_I);
|
||||
break;
|
||||
|
||||
case IVL_SIP_INOUT:
|
||||
pad = edif_cellref_create(edf, cell_iopad);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (pins[idx])
|
||||
edif_cellref_pstring(pad, "LOC", pins[idx]);
|
||||
|
||||
}
|
||||
|
||||
/* Don't free the allocated pad name strings. The
|
||||
edif_cellref_pstring function attached the string to the
|
||||
LOC attribute, so the reference is permanent. */
|
||||
|
||||
free(pins);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the case where the user specifies the cell to
|
||||
* use by attribute.
|
||||
*/
|
||||
static void edif_cellref_logic(ivl_net_logic_t net, const char*def)
|
||||
{
|
||||
char*str = strdup(def);
|
||||
char*pins;
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
unsigned idx, port;
|
||||
|
||||
pins = strchr(str, ':');
|
||||
assert(pins);
|
||||
*pins++ = 0;
|
||||
|
||||
/* Locate the cell in the library, lookup by name. */
|
||||
cell = edif_xlibrary_findcell(xlib, str);
|
||||
assert(cell);
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
for (idx = 0 ; idx < ivl_logic_pins(net) ; idx += 1) {
|
||||
char*tmp;
|
||||
|
||||
assert(pins);
|
||||
tmp = strchr(pins,',');
|
||||
if (tmp != 0)
|
||||
*tmp++ = 0;
|
||||
else
|
||||
tmp = 0;
|
||||
|
||||
port = edif_cell_port_byname(cell, pins);
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
|
||||
edif_add_to_joint(jnt, ref, port);
|
||||
|
||||
pins = tmp;
|
||||
}
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void lut_logic(ivl_net_logic_t net, const char*init3,
|
||||
const char*init4, const char*init5)
|
||||
{
|
||||
edif_cellref_t lut = NULL; /* initialization shuts up gcc -Wall */
|
||||
edif_joint_t jnt;
|
||||
const char* init = NULL; /* ditto */
|
||||
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
case 3:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
init = init3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
init = init4;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
init = init5;
|
||||
break;
|
||||
}
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", init);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
case 5:
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 4));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
case 4:
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 3));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
case 3:
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
}
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
}
|
||||
|
||||
|
||||
void xilinx_logic(ivl_net_logic_t net)
|
||||
{
|
||||
edif_cellref_t obj;
|
||||
edif_joint_t jnt;
|
||||
|
||||
{ const char*cellref_attribute = ivl_logic_attr(net, "cellref");
|
||||
if (cellref_attribute != 0) {
|
||||
edif_cellref_logic(net, cellref_attribute);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_BUF:
|
||||
case IVL_LO_BUFZ:
|
||||
assert(ivl_logic_pins(net) == 2);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_buf(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF0:
|
||||
/* The Xilinx BUFT devices is a BUF that adds a T
|
||||
input. The output is tri-stated if the T input is
|
||||
1. In other words, it acts just like bufif0. */
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_buft(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, obj, BUF_T);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF1:
|
||||
/* The Xilinx BUFE devices is a BUF that adds an enable
|
||||
input. The output is tri-stated if the E input is 0.
|
||||
In other words, it acts just like bufif1. */
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_bufe(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, obj, BUF_T);
|
||||
break;
|
||||
|
||||
case IVL_LO_NOT:
|
||||
assert(ivl_logic_pins(net) == 2);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_inv(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
break;
|
||||
|
||||
case IVL_LO_AND:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "8", "80", "8000");
|
||||
break;
|
||||
|
||||
case IVL_LO_NOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "1", "01", "0001");
|
||||
break;
|
||||
|
||||
case IVL_LO_OR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "E", "FE", "FFFE");
|
||||
break;
|
||||
|
||||
case IVL_LO_XNOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "9", "69", "9669");
|
||||
break;
|
||||
|
||||
case IVL_LO_XOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "6", "96", "6996");
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
|
||||
ivl_logic_type(net));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A fully generic Xilinx MUX is implemented entirely from LUT
|
||||
* devices.
|
||||
*/
|
||||
void xilinx_mux(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
edif_cellref_t lut;
|
||||
edif_joint_t jnt;
|
||||
|
||||
assert(ivl_lpm_selects(net) == 1);
|
||||
|
||||
/* A/B Mux devices are made from LUT3 devices. I0 is connected
|
||||
to A, I1 to B, and I2 to the Select input. Create as many
|
||||
as are needed to implement the requested width.
|
||||
|
||||
S B A | Q
|
||||
------+--
|
||||
0 0 0 | 0
|
||||
0 0 1 | 1
|
||||
0 1 0 | 0
|
||||
0 1 1 | 1
|
||||
1 0 0 | 0
|
||||
1 0 1 | 0
|
||||
1 1 0 | 1
|
||||
1 1 1 | 1
|
||||
|
||||
INIT = "CA" */
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 0, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 1, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "CA");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Any Xilinx device works with this adder.
|
||||
* Generic Xilinx add only works for single bit slices.
|
||||
*/
|
||||
void xilinx_add(ivl_lpm_t net)
|
||||
{
|
||||
const char*ha_init = 0;
|
||||
edif_cellref_t lut;
|
||||
edif_joint_t jnt;
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
ha_init = "6";
|
||||
break;
|
||||
case IVL_LPM_SUB:
|
||||
ha_init = "9";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* If this is a single bit wide, then generate only a
|
||||
half-adder. Normally this is an XOR, but if this is a SUB
|
||||
then it is an XNOR. */
|
||||
if (ivl_lpm_width(net) == 1) {
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", ha_init);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The left shift is implemented as a matrix of MUX2_1 devices. The
|
||||
* matrix has as many rows as the device width, and a column for each
|
||||
* select.
|
||||
*/
|
||||
void xilinx_shiftl(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned nsel = 0, swid = 0;
|
||||
unsigned sdx, qdx;
|
||||
|
||||
edif_cellref_t* cells;
|
||||
edif_cellref_t**table;
|
||||
|
||||
edif_cellref_t pad0_cell;
|
||||
edif_joint_t pad0;
|
||||
|
||||
|
||||
/* First, find out how many select inputs we really need. We
|
||||
can only use the selects that are enough to shift out the
|
||||
entire width of the device. The excess can be used as an
|
||||
enable for the last column. When disabled, the last column
|
||||
emits zeros. */
|
||||
|
||||
while (nsel < ivl_lpm_selects(net)) {
|
||||
|
||||
nsel += 1;
|
||||
|
||||
swid = 1 << nsel;
|
||||
if (swid >= width)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(nsel > 0);
|
||||
|
||||
/* Allocate a matrix of edif_cellref_t variables. A devices
|
||||
will be addressed by the expression table[sdx][qdx];
|
||||
This should make the algorithm code easier to read. */
|
||||
cells = calloc(nsel * width, sizeof(edif_cellref_t));
|
||||
table = calloc(nsel, sizeof(edif_cellref_t*));
|
||||
|
||||
for (sdx = 0 ; sdx < nsel ; sdx += 1)
|
||||
table[sdx] = cells + sdx*width;
|
||||
|
||||
/* Make a 0 valued pad bit. I will use this for all the shift in
|
||||
values that are beyond the input. */
|
||||
pad0_cell = edif_cellref_create(edf, cell_0);
|
||||
pad0 = edif_joint_create(edf);
|
||||
edif_add_to_joint(pad0, pad0_cell, 0);
|
||||
|
||||
/* The LUT matrix is <nsel> columns of <width> devices, with
|
||||
the last column a LUT4 devices. The extra input of the
|
||||
LUT4s in the last column are used as an enable to collect
|
||||
all the excess select inputs. */
|
||||
|
||||
/* Allocate the LUT devices of the matrix, and connect the
|
||||
select inputs to I2 of all the devices of the column. */
|
||||
for (sdx = 0 ; sdx < nsel ; sdx += 1) {
|
||||
const char*init_string = 0;
|
||||
ivl_nexus_t nex = ivl_lpm_select(net,sdx);
|
||||
edif_joint_t sdx_jnt = edif_joint_of_nexus(edf, nex);
|
||||
|
||||
edif_cell_t lut;
|
||||
|
||||
if (((sdx+1) == nsel) && (nsel < ivl_lpm_selects(net))) {
|
||||
lut = xilinx_cell_lut4(xlib);
|
||||
init_string = "00CA";
|
||||
} else {
|
||||
lut = xilinx_cell_lut3(xlib);
|
||||
init_string = "CA";
|
||||
}
|
||||
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
table[sdx][qdx] = edif_cellref_create(edf, lut);
|
||||
edif_add_to_joint(sdx_jnt, table[sdx][qdx], LUT_I2);
|
||||
|
||||
edif_cellref_pstring(table[sdx][qdx], "INIT", init_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect the inputs of the SHIFTL device to the column 0 LUT
|
||||
inputs. The slice on the low end shifts in a 0 for a select
|
||||
input. */
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
ivl_nexus_t nex0, nex1;
|
||||
edif_joint_t jnt0;
|
||||
edif_joint_t jnt1;
|
||||
|
||||
nex0 = ivl_lpm_data(net,qdx);
|
||||
jnt0 = edif_joint_of_nexus(edf, nex0);
|
||||
|
||||
if (qdx > 0) {
|
||||
nex1 = ivl_lpm_data(net,qdx-1);
|
||||
jnt1 = edif_joint_of_nexus(edf, nex1);
|
||||
} else {
|
||||
jnt1 = pad0;
|
||||
}
|
||||
|
||||
edif_add_to_joint(jnt0, table[0][qdx], LUT_I0);
|
||||
edif_add_to_joint(jnt1, table[0][qdx], LUT_I1);
|
||||
}
|
||||
|
||||
/* Make the inner connections between LUT devices. Each column
|
||||
connects to the previous column, shifted by the power of
|
||||
the column value. If the shifted input falls off the end,
|
||||
then pad with zero. */
|
||||
for (sdx = 1 ; sdx < nsel ; sdx += 1) {
|
||||
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
unsigned shift = 1 << sdx;
|
||||
edif_joint_t jnt0 = edif_joint_create(edf);
|
||||
edif_joint_t jnt1 = (qdx >= shift)
|
||||
? edif_joint_create(edf)
|
||||
: pad0;
|
||||
|
||||
edif_add_to_joint(jnt0, table[sdx][qdx], LUT_I0);
|
||||
edif_add_to_joint(jnt1, table[sdx][qdx], LUT_I1);
|
||||
|
||||
edif_add_to_joint(jnt0, table[sdx-1][qdx], LUT_O);
|
||||
if (qdx >= shift)
|
||||
edif_add_to_joint(jnt1, table[sdx-1][qdx-shift], LUT_O);
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect the output of the last column to the output of the
|
||||
SHIFTL device. */
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_q(net,qdx);
|
||||
edif_joint_t jnt = edif_joint_of_nexus(edf, nex);
|
||||
|
||||
edif_add_to_joint(jnt, table[nsel-1][qdx], LUT_O);
|
||||
}
|
||||
|
||||
/* Connect the excess select inputs to the enable inputs of
|
||||
the LUT4 devices in the last column. */
|
||||
if (nsel < ivl_lpm_selects(net)) {
|
||||
edif_joint_t jnt;
|
||||
|
||||
/* XXXX Only support 1 excess bit for now. */
|
||||
assert((nsel + 1) == ivl_lpm_selects(net));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net,nsel));
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1)
|
||||
edif_add_to_joint(jnt, table[nsel-1][qdx], LUT_I3);
|
||||
}
|
||||
|
||||
free(cells);
|
||||
free(table);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: xilinx.c,v $
|
||||
* Revision 1.1.2.2 2007/02/26 19:51:39 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.1.2.1 2005/09/25 16:35:37 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
#ifndef __xilinx_H
|
||||
#define __xilinx_H
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve at icarus.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xilinx.h,v 1.1.2.2 2007/02/26 19:51:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file includes XILINX library support functions. They
|
||||
* manage the creation and reference of cells from the library. Use
|
||||
* the xilinx_cell_* functions to get an edif_cell_t from the
|
||||
* library. The function will create the cell in the library if
|
||||
* needed, or will return the existing cell if it was already called.
|
||||
*
|
||||
* Note that these functions are *not* part of the baseline EDIF. They
|
||||
* are intended to be Xilinx specific and sometimes do things that
|
||||
* would be flat-out wrong for non-xilinx devices.
|
||||
*/
|
||||
# include "edif.h"
|
||||
|
||||
|
||||
/* === BUF Devices === */
|
||||
|
||||
/* Buffer types of devices have the BUF_O and BUF_I pin
|
||||
assignments. The BUF, INV, and certain specialized devices fit in
|
||||
this category. */
|
||||
extern edif_cell_t xilinx_cell_buf (edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_inv (edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib);
|
||||
#define BUF_O 0
|
||||
#define BUF_I 1
|
||||
/* Only bufe and buft buffers have this input. */
|
||||
#define BUF_T 2
|
||||
|
||||
/* === LUT Devices === */
|
||||
|
||||
/* Most Xilinx devices have LUT2/3/4 devices that take, respectively,
|
||||
2, 3 or 4 inputs. All forms have a single bit output. Also, the
|
||||
real behavior of the device will need to be specified by an INIT
|
||||
parameter string. */
|
||||
extern edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib);
|
||||
#define LUT_O 0
|
||||
#define LUT_I0 1
|
||||
#define LUT_I1 2
|
||||
#define LUT_I2 3
|
||||
#define LUT_I3 4
|
||||
|
||||
|
||||
/* === Flip-Flop Devices === */
|
||||
|
||||
/*
|
||||
* These are flip-flops of various sort, but similar pinouts.
|
||||
*/
|
||||
extern edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib);
|
||||
#define FDCE_Q 0
|
||||
#define FDCE_C 1
|
||||
#define FDCE_D 2
|
||||
#define FDCE_CE 3
|
||||
#define FDCE_CLR 4
|
||||
#define FDCE_PRE 5
|
||||
|
||||
|
||||
/* === Virtex/Virtex2 Carry Chain Logic === */
|
||||
|
||||
extern edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib);
|
||||
#define MULT_AND_LO 0
|
||||
#define MULT_AND_I0 1
|
||||
#define MULT_AND_I1 2
|
||||
|
||||
extern edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib);
|
||||
#define MUXCY_O 0
|
||||
#define MUXCY_DI 1
|
||||
#define MUXCY_CI 2
|
||||
#define MUXCY_S 3
|
||||
|
||||
extern edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib);
|
||||
#define XORCY_O 0
|
||||
#define XORCY_CI 1
|
||||
#define XORCY_LI 2
|
||||
|
||||
/* === Virtex/Virtex2 MUX devices */
|
||||
extern edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxf7(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxf8(edif_xlibrary_t xlib);
|
||||
#define MUXF_O 0
|
||||
#define MUXF_I0 1
|
||||
#define MUXF_I1 2
|
||||
#define MUXF_S 3
|
||||
|
||||
/* === Inheritable Methods === */
|
||||
|
||||
extern void virtex_logic(ivl_net_logic_t net);
|
||||
extern void virtex_generic_dff(ivl_lpm_t net);
|
||||
extern void virtex_eq(ivl_lpm_t net);
|
||||
extern void virtex_ge(ivl_lpm_t net);
|
||||
extern void virtex_mux(ivl_lpm_t net);
|
||||
extern void virtex_add(ivl_lpm_t net);
|
||||
|
||||
extern void xilinx_common_header(ivl_design_t des);
|
||||
extern void xilinx_show_footer(ivl_design_t des);
|
||||
extern void xilinx_show_scope(ivl_scope_t scope);
|
||||
extern void xilinx_pad(ivl_signal_t, const char*str);
|
||||
extern void xilinx_logic(ivl_net_logic_t net);
|
||||
extern void xilinx_mux(ivl_lpm_t net);
|
||||
extern void xilinx_add(ivl_lpm_t net);
|
||||
extern void xilinx_shiftl(ivl_lpm_t net);
|
||||
|
||||
/*
|
||||
* $Log: xilinx.h,v $
|
||||
* Revision 1.1.2.2 2007/02/26 19:51:39 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.1.2.1 2005/09/25 16:35:37 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.16 2004/02/10 19:25:01 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.16.2.2 2006/05/08 04:33:36 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -39,6 +39,8 @@ CC = @CC@
|
|||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
|
|
@ -83,13 +85,22 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
check: all
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-fpga.1
|
||||
else
|
||||
ifeq (@PS2PDF@,none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-fpga.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-fpga.pdf $(mandir)/man1/iverilog-fpga.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: iverilog-fpga.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-fpga.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ dnl Checks for programs.
|
|||
AC_PROG_CC
|
||||
|
||||
AC_PROG_INSTALL
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
|
@ -17,7 +19,7 @@ AC_CHECK_HEADERS(malloc.h)
|
|||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# linker options when building a shared library
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-lpm.c,v 1.12 2004/10/04 01:10:56 steve Exp $"
|
||||
#ident "$Id: d-lpm.c,v 1.12.2.1 2005/08/25 18:52:32 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -804,9 +804,19 @@ static void lpm_show_mult(ivl_lpm_t net)
|
|||
|
||||
static void lpm_show_constant(ivl_net_const_t net)
|
||||
{
|
||||
/* We only need one instance each of constant 0 and 1 bits. If
|
||||
we need either of them, then create an instance reference and
|
||||
save that reference here so that later needs for 0 or 1 can
|
||||
find that the reference already lives and can be added to the
|
||||
joint. */
|
||||
static edif_cellref_t cell0_ref = 0;
|
||||
static edif_cellref_t cell1_ref = 0;
|
||||
|
||||
static edif_joint_t cell0_jnt = 0;
|
||||
static edif_joint_t cell1_jnt = 0;
|
||||
|
||||
edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0");
|
||||
edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1");
|
||||
edif_cellref_t ref0 = 0, ref1 = 0;
|
||||
|
||||
const char*bits;
|
||||
unsigned idx;
|
||||
|
|
@ -832,23 +842,26 @@ static void lpm_show_constant(ivl_net_const_t net)
|
|||
bits = ivl_const_bits(net);
|
||||
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
|
||||
if (bits[idx] == '1') {
|
||||
if (ref1 == 0)
|
||||
ref1 = edif_cellref_create(edf, cell1);
|
||||
if (cell1_ref == 0) {
|
||||
cell1_ref = edif_cellref_create(edf, cell1);
|
||||
cell1_jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(cell1_jnt, cell1_ref, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (ref0 == 0)
|
||||
ref0 = edif_cellref_create(edf, cell0);
|
||||
if (cell0_ref == 0) {
|
||||
cell0_ref = edif_cellref_create(edf, cell0);
|
||||
cell0_jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(cell0_jnt, cell0_ref, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_const_pin(net,idx));
|
||||
if (bits[idx] == '1')
|
||||
edif_add_to_joint(jnt, ref1, 0);
|
||||
edif_nexus_to_joint(edf, cell1_jnt, ivl_const_pin(net,idx));
|
||||
else
|
||||
edif_add_to_joint(jnt, ref0, 0);
|
||||
edif_nexus_to_joint(edf, cell0_jnt, ivl_const_pin(net,idx));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -876,6 +889,9 @@ const struct device_s d_lpm_edif = {
|
|||
|
||||
/*
|
||||
* $Log: d-lpm.c,v $
|
||||
* Revision 1.12.2.1 2005/08/25 18:52:32 steve
|
||||
* Join cell0 and cell1 instances in LPM target.
|
||||
*
|
||||
* Revision 1.12 2004/10/04 01:10:56 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue