mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-24 23:06:56 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aed885ecc5 | ||
|
|
d365c144a8 | ||
|
|
f001d0001a | ||
|
|
decfbff2b1 | ||
|
|
3e45f4302b | ||
|
|
77a0d7f4db | ||
|
|
e8efa6df53 | ||
|
|
276f2d0032 | ||
|
|
13a660b591 | ||
|
|
f4a44df2cc | ||
|
|
5b3ba8c306 | ||
|
|
8defa4bcd0 | ||
|
|
dabdcf0fc9 | ||
|
|
8ff70410ab | ||
|
|
6f46d12e07 | ||
|
|
5f5a6b5396 | ||
|
|
1b911ad87a | ||
|
|
b0b614ae0e | ||
|
|
9c16c34422 | ||
|
|
170e57d662 | ||
|
|
065f342278 | ||
|
|
a721586acb | ||
|
|
50ad415c0d | ||
|
|
4ba2afbbe1 | ||
|
|
d3f89e0d4f | ||
|
|
457cf15b3b | ||
|
|
d0de678d57 | ||
|
|
fa6e4a69a6 | ||
|
|
d434dd7296 | ||
|
|
3158e2caa1 | ||
|
|
e1ce72e245 | ||
|
|
368c27c9e4 | ||
|
|
a4116efd57 | ||
|
|
58f182a159 | ||
|
|
b7861fa6e8 | ||
|
|
1721799050 | ||
|
|
df226c5d13 | ||
|
|
e9bf00dff6 | ||
|
|
c071cc1bbe | ||
|
|
101b373293 | ||
|
|
5cf64dfa70 | ||
|
|
1021e5acc8 | ||
|
|
4f7e7a2296 | ||
|
|
0c73f209de | ||
|
|
0873c52474 | ||
|
|
64d46630e0 | ||
|
|
8ed504b064 | ||
|
|
6161904bf8 | ||
|
|
908955c72c | ||
|
|
bab70ccbed | ||
|
|
2b8fd28a95 | ||
|
|
0e044d6684 | ||
|
|
7efa6be236 | ||
|
|
35951510c5 | ||
|
|
3f108f08ed | ||
|
|
244844c067 | ||
|
|
b416ae047b | ||
|
|
c02b3b8ac6 | ||
|
|
bebcc05aab | ||
|
|
8d49abf967 | ||
|
|
c87223170b | ||
|
|
8e2898e51a | ||
|
|
9c8c541f5d | ||
|
|
3cdf655c79 | ||
|
|
560c5a2584 | ||
|
|
c75f0a930e | ||
|
|
bb3f3c1f46 | ||
|
|
07f345da4d | ||
|
|
fb22bcc96b | ||
|
|
2842a65fd1 | ||
|
|
a652719876 | ||
|
|
16dc3ab4d4 | ||
|
|
cf85c19f7b | ||
|
|
01a6dd61ca | ||
|
|
bf8b085159 | ||
|
|
ee22550047 | ||
|
|
2b07c7a685 | ||
|
|
be73be8c98 | ||
|
|
e2a1b90b12 | ||
|
|
d22d88923d | ||
|
|
2729d6cd2e | ||
|
|
21af0dbe3f | ||
|
|
c4d8ab8509 | ||
|
|
988a0a7048 | ||
|
|
672aa61ae7 | ||
|
|
7235706923 | ||
|
|
a256613fa6 | ||
|
|
5ec7dde52f | ||
|
|
19a1ae8d4f | ||
|
|
14d79a655e | ||
|
|
293976bacc | ||
|
|
4dfdc147c5 | ||
|
|
c946f27d9b | ||
|
|
9fd16575d9 | ||
|
|
b9c0b8aa79 | ||
|
|
65584e6dde | ||
|
|
c39976fbf1 | ||
|
|
4902c222fb | ||
|
|
ad761069c7 | ||
|
|
b69f59f2ec | ||
|
|
3ff2488d4f | ||
|
|
efd7825964 | ||
|
|
70f146924a | ||
|
|
7c19eb51e7 | ||
|
|
6f839aa5df | ||
|
|
dac11c2468 | ||
|
|
5cf2ce6499 | ||
|
|
73453996a9 | ||
|
|
bc489a7761 | ||
|
|
4a8be3db9c | ||
|
|
8232b621f1 | ||
|
|
4cbffc6b77 | ||
|
|
9a16e030b5 | ||
|
|
d353ddb660 | ||
|
|
bc9f286954 | ||
|
|
fde4ff72f6 | ||
|
|
a8d49921ee | ||
|
|
9cae53988a | ||
|
|
559a1fd359 | ||
|
|
5bfdd52391 | ||
|
|
b094ccc3f7 | ||
|
|
b9799cf6ec | ||
|
|
75ad90534b | ||
|
|
3ac79c294a | ||
|
|
e7f3340513 | ||
|
|
60b9121c6c | ||
|
|
e3f300f4c2 | ||
|
|
1c6be44724 | ||
|
|
6bf7556d65 | ||
|
|
c46f978dbb | ||
|
|
9cac88330b | ||
|
|
de1dd2f2b3 | ||
|
|
6c8e1f7834 | ||
|
|
b58705b829 | ||
|
|
7091915b73 | ||
|
|
5513974b78 | ||
|
|
ad78af2f91 | ||
|
|
1b30bac9f3 | ||
|
|
66a579dd67 | ||
|
|
094dd7e4de | ||
|
|
3b91db96cd | ||
|
|
657ac8168e | ||
|
|
a79fee39e9 | ||
|
|
4cc421b3b7 | ||
|
|
290c604c62 | ||
|
|
466ab5c2c7 | ||
|
|
4ba195282d | ||
|
|
cd14ee77ae | ||
|
|
21c7abf090 | ||
|
|
4413dd3c81 | ||
|
|
73f3589ea6 | ||
|
|
9278dad244 | ||
|
|
a0dce80eba | ||
|
|
af5f713c0f | ||
|
|
80cac983c6 | ||
|
|
f5ba93eeb6 | ||
|
|
668781788b | ||
|
|
86729f52ca | ||
|
|
fb8ddbbfde | ||
|
|
2736859d8f | ||
|
|
a59f3b1fa6 | ||
|
|
dd4f765b06 | ||
|
|
f465bca305 | ||
|
|
cb967c10fe | ||
|
|
3607fb584d | ||
|
|
77792dcc2f | ||
|
|
2f7ec71a78 | ||
|
|
42433f4df9 | ||
|
|
aa2e178667 | ||
|
|
015d280c6a | ||
|
|
739a1839ed | ||
|
|
b6fd4f610b | ||
|
|
06e08dbdf0 | ||
|
|
28168e0f57 | ||
|
|
7796c8bcfb | ||
|
|
82be4ab189 | ||
|
|
3a8e2e688d | ||
|
|
037ab9efe9 | ||
|
|
d6a89a40cf | ||
|
|
3bd09d1470 | ||
|
|
d0ade1d082 | ||
|
|
fcb02ee9c2 | ||
|
|
870395e627 | ||
|
|
c701fb615b | ||
|
|
adbe734b6c | ||
|
|
c34e44dad0 | ||
|
|
5a2dd3393f | ||
|
|
ed78c5b677 | ||
|
|
7dd0d255a6 | ||
|
|
48aa0f0075 | ||
|
|
5277124c76 | ||
|
|
f6da64e2ec | ||
|
|
06816e79fe | ||
|
|
a1d899112a | ||
|
|
d548c9a5f8 | ||
|
|
2894cdefc7 | ||
|
|
df271c9fa3 | ||
|
|
99aff5f10b | ||
|
|
e9bf021f6c | ||
|
|
aed8474944 | ||
|
|
af7e196518 | ||
|
|
365cfedd55 | ||
|
|
f884652c19 | ||
|
|
6244dc1194 | ||
|
|
a3f696cd06 | ||
|
|
061fdf5a0d | ||
|
|
fe91ebe77c | ||
|
|
e8a6835d36 | ||
|
|
800e2c6a17 | ||
|
|
29fa9e7321 | ||
|
|
65c7ec00e7 | ||
|
|
d62661257a | ||
|
|
c5cf77dc7e | ||
|
|
20d3a8508e | ||
|
|
f16b69c1e5 | ||
|
|
573e07225d | ||
|
|
236ff2b278 | ||
|
|
b7ef2fcb0a | ||
|
|
becda0e26c | ||
|
|
d8a456bd67 | ||
|
|
8184dfaed8 | ||
|
|
ca488dff4e | ||
|
|
23925b636e | ||
|
|
53da6e9a33 | ||
|
|
0f914bf35a | ||
|
|
f556452403 | ||
|
|
ab1ca54df2 | ||
|
|
bae8507c90 | ||
|
|
313502f360 | ||
|
|
1c5b4881d7 | ||
|
|
53af2949b4 | ||
|
|
789c95b1c1 | ||
|
|
72240c460e | ||
|
|
8e135a1020 | ||
|
|
0fb1fd36ee | ||
|
|
e7c2e06260 | ||
|
|
73997f813c | ||
|
|
75af32bd3c | ||
|
|
4ccbb4f0b2 | ||
|
|
85286cc086 | ||
|
|
04604188df | ||
|
|
f7dc4307bd | ||
|
|
257e1f9516 | ||
|
|
5fe5d9184d | ||
|
|
589eb1d315 | ||
|
|
2fcaac4060 | ||
|
|
4051f7d986 | ||
|
|
02d0719529 | ||
|
|
aaf35ab1a9 | ||
|
|
c5e7e2ec0a | ||
|
|
ff067bb959 | ||
|
|
1d7235b4f1 | ||
|
|
97e0723bd1 | ||
|
|
d4eb4d38bc | ||
|
|
d00e3fc9a9 | ||
|
|
9ec00e1288 | ||
|
|
85d9ebded8 | ||
|
|
d74177634c | ||
|
|
eca4f4fa97 | ||
|
|
6b7b82758a | ||
|
|
355ead0002 | ||
|
|
4fce321900 | ||
|
|
2e6d2f8e98 | ||
|
|
55b5bf9d39 | ||
|
|
1979fca239 | ||
|
|
a0583ef124 | ||
|
|
ee5bb5fcaf | ||
|
|
ca1bbc79a3 | ||
|
|
e74127e1fc | ||
|
|
b48abb2148 | ||
|
|
97f83ffbe3 | ||
|
|
018014368b | ||
|
|
20be0351ae | ||
|
|
68a788221e | ||
|
|
84b3e8e2dc | ||
|
|
e6cdd32c19 | ||
|
|
c23a35a033 | ||
|
|
609b6a7baa | ||
|
|
0609c5f18c | ||
|
|
d51503ffd8 | ||
|
|
7625a6c3e7 | ||
|
|
695718d691 | ||
|
|
e04fb5c083 | ||
|
|
07f64bc603 | ||
|
|
bf3679b7d4 | ||
|
|
ade5bdcafe | ||
|
|
7250337941 | ||
|
|
99ace10774 | ||
|
|
6be34bba4d | ||
|
|
a5b431ad20 | ||
|
|
a121e703f3 | ||
|
|
dfb7c7ba6f | ||
|
|
edeb9d8eca | ||
|
|
14f557e6f4 | ||
|
|
25de448d34 | ||
|
|
cb4e0d4724 | ||
|
|
6a23f16860 | ||
|
|
a4710f375e | ||
|
|
6c5e840617 | ||
|
|
e28636776a | ||
|
|
b86fdd6bbc | ||
|
|
1d1dda5a5d | ||
|
|
3222031970 | ||
|
|
bf6a5d0f50 | ||
|
|
1c3668ea7f | ||
|
|
ead2481793 | ||
|
|
fcaaec0464 | ||
|
|
4d139b58aa | ||
|
|
8c18c9152d | ||
|
|
399dfe5c44 | ||
|
|
9e94afe399 | ||
|
|
6c711ee4d8 | ||
|
|
9735b0e8b3 | ||
|
|
d5c33420ab | ||
|
|
34a14b983b | ||
|
|
d1e2538aba | ||
|
|
8bfc75d1ee | ||
|
|
b1b93f860c | ||
|
|
8f2d679c8a | ||
|
|
83423c978b | ||
|
|
1674d692b7 | ||
|
|
7166598ed0 | ||
|
|
5eb25e44e1 | ||
|
|
59566158c4 | ||
|
|
e11ac0b1d8 | ||
|
|
8939467ac5 | ||
|
|
26d97558c4 | ||
|
|
59bac26f4f | ||
|
|
78dda42493 | ||
|
|
36f36bd2ac | ||
|
|
0193daa436 | ||
|
|
4444079409 | ||
|
|
3947d7dd33 | ||
|
|
7973dad9f5 | ||
|
|
d19e76a193 | ||
|
|
ffedf32476 | ||
|
|
527ddea811 | ||
|
|
65e9b6be12 |
+6
-1
@@ -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.8 2005/06/14 19:13:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* This class holds line information for an internal object.
|
||||
*
|
||||
@@ -52,6 +54,9 @@ class LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.8 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
* Revision 1.7 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
||||
+12
-22
@@ -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.175 2006/04/10 00:37:42 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.9.devel
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -60,15 +60,9 @@ CXXFLAGS = -Wall @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
||||
# The TARGETS variable lists the target modules that can be build and
|
||||
# installed. Some of them depend on external things, so are only
|
||||
# compiled if the prerequisites are installed.
|
||||
TARGETS = tgt-null
|
||||
|
||||
all: dep ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in ivlpp tgt-verilog tgt-stub; \
|
||||
for dir in ivlpp tgt-verilog ; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
cd driver ; $(MAKE) VERSION=$(VERSION) $@
|
||||
|
||||
@@ -90,8 +84,7 @@ check: all
|
||||
|
||||
clean:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
for dir in vpi ivlpp tgt-verilog driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f *.o parse.cc parse.cc.output parse.h lexor.cc
|
||||
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc*
|
||||
@@ -99,27 +92,26 @@ clean:
|
||||
|
||||
distclean: clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
for dir in vpi ivlpp tgt-verilog driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
|
||||
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
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
|
||||
|
||||
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
|
||||
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
|
||||
elab_sig.o emit.o eval.o eval_attrib.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
|
||||
net_proc.o net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o symbol_search.o sync.o sys_funcs.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o PGenerate.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
@@ -209,9 +201,8 @@ endif
|
||||
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL)
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
|
||||
@@ -275,7 +266,6 @@ installdirs: mkinstalldirs
|
||||
|
||||
uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl; \
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.h,v 1.37 2004/06/13 04:56:53 steve Exp $"
|
||||
#ident "$Id: Module.h,v 1.40 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -30,11 +30,11 @@
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include "netlist.h"
|
||||
class PData;
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
class PGenerate;
|
||||
class PTask;
|
||||
class PFunction;
|
||||
class PWire;
|
||||
@@ -108,15 +108,20 @@ class Module : public LineInfo {
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
/* Keep a table of datum variables declared in the module. */
|
||||
map<hname_t,PData*>datum;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
|
||||
/* The module has a list of genvars that may be used in
|
||||
various generate schemes. */
|
||||
list<perm_string> genvars;
|
||||
|
||||
/* the module has a list of generate schemes that appear in
|
||||
the module definition. These are used at elaboration time. */
|
||||
list<PGenerate*> generate_schemes;
|
||||
|
||||
perm_string mod_name() const { return name_; }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
@@ -146,7 +151,8 @@ class Module : public LineInfo {
|
||||
void dump(ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
bool elaborate_scope(Design*, NetScope*scope) const;
|
||||
typedef map<perm_string,NetExpr*> replace_t;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
@@ -167,45 +173,13 @@ class Module : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.37 2004/06/13 04:56:53 steve
|
||||
* Add support for the default_nettype directive.
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.36 2004/05/25 19:21:06 steve
|
||||
* More identifier lists use perm_strings.
|
||||
* Revision 1.39 2006/03/30 01:49:07 steve
|
||||
* Fix instance arrays indexed by overridden parameters.
|
||||
*
|
||||
* Revision 1.35 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.34 2004/02/20 06:22:56 steve
|
||||
* parameter keys are per_strings.
|
||||
*
|
||||
* Revision 1.33 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.32 2003/06/20 00:53:19 steve
|
||||
* Module attributes from the parser
|
||||
* through to elaborated form.
|
||||
*
|
||||
* Revision 1.31 2003/06/13 19:10:45 steve
|
||||
* Properly manage real variables in subscopes.
|
||||
*
|
||||
* Revision 1.30 2003/03/06 04:37:12 steve
|
||||
* lex_strings.add module names earlier.
|
||||
*
|
||||
* Revision 1.29 2003/02/27 06:45:11 steve
|
||||
* specparams as far as pform.
|
||||
*
|
||||
* Revision 1.28 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.27 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.26 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.25 2002/05/19 23:37:28 steve
|
||||
* Parse port_declaration_lists from the 2001 Standard.
|
||||
* Revision 1.38 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#ifndef __PData_H
|
||||
#define __PData_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "HName.h"
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
|
||||
/*
|
||||
* The PData object represents declaration of atomic datum such as
|
||||
* real and realtime variables. These are variables that cannot be bit
|
||||
* or part selected, but can be used in expressions.
|
||||
*/
|
||||
|
||||
class PData : public LineInfo {
|
||||
|
||||
public:
|
||||
PData(const hname_t&hname);
|
||||
~PData();
|
||||
|
||||
// Return a hierarchical name.
|
||||
const hname_t&name() const;
|
||||
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
private:
|
||||
hname_t hname_;
|
||||
|
||||
private:
|
||||
PData(const PData&);
|
||||
PData& operator= (const PData&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PData.h,v $
|
||||
* Revision 1.1 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+37
-14
@@ -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.13 2006/01/03 05:22:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -62,8 +62,7 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
|
||||
delete_flag_ = df;
|
||||
}
|
||||
|
||||
static unsigned long calculate_val(Design*des, NetScope*scope,
|
||||
const PExpr*expr)
|
||||
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
{
|
||||
|
||||
NetExpr*dex = expr->elaborate_expr(des, scope);
|
||||
@@ -85,7 +84,9 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
|
||||
delay = 0;
|
||||
|
||||
delete tmp;
|
||||
return delay;
|
||||
NetEConst*tmp2 = new NetEConst(verinum(delay));
|
||||
tmp2->set_line(*expr);
|
||||
return tmp2;
|
||||
}
|
||||
|
||||
|
||||
@@ -96,35 +97,51 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
|
||||
des->scale_to_precision(fn.as_ulong(), scope);
|
||||
|
||||
delete tmp;
|
||||
return delay;
|
||||
NetEConst*tmp2 = new NetEConst(verinum(delay));
|
||||
tmp2->set_line(*expr);
|
||||
return tmp2;
|
||||
}
|
||||
|
||||
/* Oops, cannot evaluate down to a constant. Error message. */
|
||||
delete dex;
|
||||
/* Oops, cannot evaluate down to a constant. */
|
||||
return dex;
|
||||
}
|
||||
|
||||
cerr << expr->get_line() << ": sorry: non-constant "
|
||||
<< "delays not supported here: " << *expr << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
|
||||
{
|
||||
if (dynamic_cast<NetESignal*> (expr))
|
||||
return expr;
|
||||
|
||||
if (dynamic_cast<NetEConst*> (expr))
|
||||
return expr;
|
||||
|
||||
NetNet*sig = expr->synthesize(des);
|
||||
expr = new NetESignal(sig);
|
||||
return expr;
|
||||
}
|
||||
|
||||
void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
bool as_nets_flag) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
|
||||
if (delay_[0]) {
|
||||
rise_time = calculate_val(des, scope, delay_[0]);
|
||||
if (as_nets_flag)
|
||||
rise_time = make_delay_nets(des, rise_time);
|
||||
|
||||
if (delay_[1]) {
|
||||
fall_time = calculate_val(des, scope, delay_[1]);
|
||||
if (as_nets_flag)
|
||||
fall_time = make_delay_nets(des, fall_time);
|
||||
|
||||
if (delay_[2]) {
|
||||
decay_time = calculate_val(des, scope, delay_[2]);
|
||||
if (as_nets_flag)
|
||||
decay_time = make_delay_nets(des, decay_time);
|
||||
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
@@ -146,6 +163,12 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.13 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.12 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.11 2003/06/21 01:21:42 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.h,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: PDelays.h,v 1.9 2006/01/03 05:22:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
@@ -34,6 +34,7 @@ using namespace std;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class NetExpr;
|
||||
class PExpr;
|
||||
|
||||
/*
|
||||
@@ -53,9 +54,10 @@ class PDelays {
|
||||
void set_delays(const svector<PExpr*>*del, bool delete_flag=true);
|
||||
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const;
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
bool as_nets_flag =false) const;
|
||||
|
||||
void dump_delays(ostream&out) const;
|
||||
|
||||
@@ -72,6 +74,12 @@ ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
/*
|
||||
* $Log: PDelays.h,v $
|
||||
* Revision 1.9 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.8 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.cc,v 1.35 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: PExpr.cc,v 1.37 2005/10/04 04:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -53,6 +53,14 @@ NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_bi_net(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_line() << ": error: "
|
||||
<< "expression not valid as argument to inout port: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
@@ -140,7 +148,7 @@ bool PEFNumber::is_constant(Module*) const
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const hname_t&s)
|
||||
: path_(s), msb_(0), lsb_(0), idx_(0)
|
||||
: path_(s), msb_(0), lsb_(0), sel_(SEL_NONE), idx_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -262,6 +270,12 @@ bool PEUnary::is_constant(Module*m) const
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.37 2005/10/04 04:09:25 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
* Revision 1.36 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.35 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
* 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.78 2006/03/25 02:36:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include "netlist.h"
|
||||
# include "verinum.h"
|
||||
# include "LineInfo.h"
|
||||
@@ -66,30 +67,37 @@ class PExpr : public LineInfo {
|
||||
// continuous assign or other wholly structural context.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG)
|
||||
const;
|
||||
|
||||
// This method elaborates the expression as NetNet objects. It
|
||||
// only allows regs suitable for procedural continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
|
||||
// This is similar to elaborate_lnet, except that the
|
||||
// expression is evaluated to be bi-directional. This is
|
||||
// useful for arguments to inout ports of module instances and
|
||||
// ports of tran primitives.
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
// assignments can be elaborated with this method. If the
|
||||
// is_force flag is true, then the set of valid l-value types
|
||||
// is slightly modified to accomodate the Verilog force
|
||||
// statement
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
// a verinum as a result. If the expression cannot be
|
||||
// evaluated, return 0.
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
// This method returns true if that expression is the same as
|
||||
// this expression. This method is used for comparing
|
||||
@@ -115,25 +123,24 @@ class PEConcat : public PExpr {
|
||||
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Concatenated Regs can be on the left of procedural
|
||||
// continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
@@ -182,7 +189,7 @@ class PEFNumber : public PExpr {
|
||||
/* The eval_const method as applied to a floating point number
|
||||
gets the *integer* value of the number. This accounts for
|
||||
any rounding that is needed to get the value. */
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
/* A PEFNumber is a constant, so this returns true. */
|
||||
virtual bool is_constant(Module*) const;
|
||||
@@ -191,6 +198,14 @@ class PEFNumber : public PExpr {
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
@@ -205,22 +220,23 @@ class PEIdent : public PExpr {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Regs can be on the left of procedural continuous assignments
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are also allowed as procedural assignment l-values.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
// Structural r-values are OK.
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
@@ -233,33 +249,62 @@ class PEIdent : public PExpr {
|
||||
NetNet* elaborate_port(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
const hname_t& path() const;
|
||||
|
||||
private:
|
||||
NetExpr*elaborate_expr_param(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
hname_t path_;
|
||||
|
||||
public:
|
||||
// Use these to support bit- and part-select operators.
|
||||
// Use these to support part-select operators.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
// If this is a reference to a memory, this is the index
|
||||
// expression.
|
||||
PExpr*idx_;
|
||||
enum { SEL_NONE, SEL_PART, SEL_IDX_UP, SEL_IDX_DO } sel_;
|
||||
|
||||
// If this is a reference to a memory/array, this is the index
|
||||
// expression. If this is a reference to a vector, this is a
|
||||
// bit select.
|
||||
std::vector<PExpr*> idx_;
|
||||
|
||||
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
@@ -267,6 +312,15 @@ class PEIdent : public PExpr {
|
||||
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const;
|
||||
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
|
||||
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
|
||||
|
||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
unsigned&midx, unsigned&lidx) const;
|
||||
|
||||
};
|
||||
|
||||
class PENumber : public PExpr {
|
||||
@@ -280,17 +334,19 @@ class PENumber : public PExpr {
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
@@ -316,15 +372,15 @@ class PEString : public PExpr {
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
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*, NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -341,15 +397,15 @@ class PEUnary : public PExpr {
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -369,15 +425,15 @@ class PEBinary : public PExpr {
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
char op_;
|
||||
@@ -388,44 +444,44 @@ class PEBinary : public PExpr {
|
||||
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -443,15 +499,15 @@ class PETernary : public PExpr {
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -473,9 +529,9 @@ class PECallFunction : public PExpr {
|
||||
virtual void dump(ostream &) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
@@ -492,6 +548,51 @@ class PECallFunction : public PExpr {
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.78 2006/03/25 02:36:26 steve
|
||||
* Get rid of excess PESTring:: prefix within class declaration.
|
||||
*
|
||||
* Revision 1.77 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.76 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.75 2005/12/07 04:04:23 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
* Revision 1.74 2005/11/27 17:01:56 steve
|
||||
* Fix for stubborn compiler.
|
||||
*
|
||||
* Revision 1.73 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.72 2005/11/10 13:28:11 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.71 2005/10/04 04:09:25 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
* Revision 1.70 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.69 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.68 2005/01/09 20:16:00 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.67 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.66 2004/10/04 01:10:51 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: PGate.cc,v 1.16 2004/02/18 17:11:54 steve Exp $"
|
||||
#ident "$Id: PGate.cc,v 1.18 2006/01/03 05:22:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -90,12 +90,69 @@ void PGate::elaborate_scope(Design*, NetScope*) const
|
||||
* parameters. This method understands how to handle the different
|
||||
* numbers of expressions.
|
||||
*/
|
||||
|
||||
void PGate::eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_expr,
|
||||
NetExpr*&fall_expr,
|
||||
NetExpr*&decay_expr,
|
||||
bool as_net_flag) const
|
||||
{
|
||||
delay_.eval_delays(des, scope,
|
||||
rise_expr, fall_expr, decay_expr,
|
||||
as_net_flag);
|
||||
}
|
||||
|
||||
void PGate::eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
{
|
||||
delay_.eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
NetExpr*rise_expr, *fall_expr, *decay_expr;
|
||||
delay_.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
|
||||
|
||||
if (rise_expr == 0) {
|
||||
rise_time = 0;
|
||||
fall_time = 0;
|
||||
decay_time = 0;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*> (rise_expr)) {
|
||||
rise_time = tmp->value().as_ulong();
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Delay expressions must be "
|
||||
<< "constant here." << endl;
|
||||
cerr << get_line() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
rise_time = 0;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*> (fall_expr)) {
|
||||
fall_time = tmp->value().as_ulong();
|
||||
|
||||
} else {
|
||||
if (fall_expr != rise_expr) {
|
||||
cerr << get_line() << ": error: Delay expressions must be "
|
||||
<< "constant here." << endl;
|
||||
cerr << get_line() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
fall_time = 0;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*> (decay_expr)) {
|
||||
decay_time = tmp->value().as_ulong();
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Delay expressions must be "
|
||||
<< "constant here." << endl;
|
||||
cerr << get_line() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
decay_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PGAssign::PGAssign(svector<PExpr*>*pins)
|
||||
@@ -191,6 +248,12 @@ perm_string PGModule::get_type()
|
||||
|
||||
/*
|
||||
* $Log: PGate.cc,v $
|
||||
* Revision 1.18 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.17 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.16 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGate.h,v 1.29 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
@@ -66,11 +66,23 @@ class PGate : public LineInfo {
|
||||
|
||||
perm_string get_name() const { return name_; }
|
||||
|
||||
// This method evaluates the delays all the way to an
|
||||
// integer. If the delay is non-constant, then set the times
|
||||
// to 0, print an error message and mark an error to the
|
||||
// design.
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const;
|
||||
|
||||
// This evaluates the delays as far as possible, but returns
|
||||
// an expression, and do not signal errors.
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
bool as_net_flag =false) const;
|
||||
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
@@ -82,7 +94,7 @@ class PGate : public LineInfo {
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -116,7 +128,7 @@ class PGAssign : public PGate {
|
||||
explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels);
|
||||
~PGAssign();
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -153,7 +165,7 @@ class PGBuiltin : public PGate {
|
||||
Type type() const { return type_; }
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -196,7 +208,7 @@ class PGModule : public PGate {
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -227,6 +239,15 @@ class PGModule : public PGate {
|
||||
|
||||
/*
|
||||
* $Log: PGate.h,v $
|
||||
* Revision 1.32 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.31 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.30 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.29 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.cc,v 1.1 2006/04/10 02:40:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PGenerate.h"
|
||||
# include "PWire.h"
|
||||
|
||||
PGenerate::PGenerate(unsigned id)
|
||||
: id_number(id)
|
||||
{
|
||||
}
|
||||
|
||||
PGenerate::~PGenerate()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::add_wire(PWire*wire)
|
||||
{
|
||||
PWire*&ep = wires[wire->path()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(const hname_t&name) const
|
||||
{
|
||||
map<hname_t,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
void PGenerate::add_gate(PGate*gate)
|
||||
{
|
||||
gates.push_back(gate);
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.h,v 1.1 2006/04/10 02:40:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PExpr;
|
||||
class PGate;
|
||||
class PWire;
|
||||
|
||||
/*
|
||||
* This represents a generate scheme.
|
||||
*/
|
||||
class PGenerate : public LineInfo {
|
||||
|
||||
public:
|
||||
PGenerate(unsigned id_number);
|
||||
~PGenerate();
|
||||
|
||||
// Generate schemes have an ID number, for when the scope is
|
||||
// implicit.
|
||||
const unsigned id_number;
|
||||
perm_string scope_name;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT};
|
||||
scheme_t scheme_type;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
// expressions: for (index = <init>; <test>; index=<step>)
|
||||
perm_string loop_index;
|
||||
PExpr*loop_init;
|
||||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<hname_t,PWire*>wires;
|
||||
PWire* add_wire(PWire*);
|
||||
PWire* get_wire(const hname_t&name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
// This method is called by the elaboration of a module to
|
||||
// generate scopes. the container is the scope that is to
|
||||
// contain the generated scope.
|
||||
bool generate_scope(Design*des, NetScope*container);
|
||||
|
||||
bool elaborate_sig(Design*des) const;
|
||||
bool elaborate(Design*des) const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
|
||||
private:
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
|
||||
// These are the scopes created by generate_scope.
|
||||
list<NetScope*>scope_list_;
|
||||
// internal function called on each scope generated by this scheme.
|
||||
bool elaborate_sig_(Design*des, NetScope*scope) const;
|
||||
bool elaborate_(Design*des, NetScope*scope) const;
|
||||
|
||||
private: // not implemented
|
||||
PGenerate(const PGenerate&);
|
||||
PGenerate& operator= (const PGenerate&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,15 +17,19 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.cc,v 1.10 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: PWire.cc,v 1.11 2005/07/07 16:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const hname_t&n, NetNet::Type t, NetNet::PortType pt)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
|
||||
PWire::PWire(const hname_t&n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false), isint_(false),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
@@ -35,8 +39,12 @@ lidx_(0), ridx_(0)
|
||||
}
|
||||
}
|
||||
|
||||
PWire::PWire(char*n, NetNet::Type t, NetNet::PortType pt)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
|
||||
PWire::PWire(char*n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false), isint_(false),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
@@ -108,6 +116,19 @@ bool PWire::set_port_type(NetNet::PortType pt)
|
||||
}
|
||||
}
|
||||
|
||||
bool PWire::set_data_type(ivl_variable_type_t dt)
|
||||
{
|
||||
if (data_type_ != IVL_VT_NO_TYPE)
|
||||
if (data_type_ != dt)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
||||
assert(data_type_ == IVL_VT_NO_TYPE);
|
||||
data_type_ = dt;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PWire::set_signed(bool flag)
|
||||
{
|
||||
signed_ = flag;
|
||||
@@ -140,6 +161,9 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.11 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.10 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.h,v 1.17 2004/02/20 18:53:33 steve Exp $"
|
||||
#ident "$Id: PWire.h,v 1.19 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -49,8 +49,14 @@ class Design;
|
||||
class PWire : public LineInfo {
|
||||
|
||||
public:
|
||||
PWire(const hname_t&hname, NetNet::Type t, NetNet::PortType pt);
|
||||
PWire(char*name, NetNet::Type t, NetNet::PortType pt);
|
||||
PWire(const hname_t&hname,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
PWire(char*name,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
|
||||
// Return a hierarchical name.
|
||||
const hname_t&path() const;
|
||||
@@ -65,6 +71,9 @@ class PWire : public LineInfo {
|
||||
bool get_signed() const;
|
||||
bool get_isint() const;
|
||||
|
||||
bool set_data_type(ivl_variable_type_t dt);
|
||||
ivl_variable_type_t get_data_type() const;
|
||||
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
@@ -72,7 +81,7 @@ class PWire : public LineInfo {
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out) const;
|
||||
void dump(ostream&out, unsigned ind=4) const;
|
||||
|
||||
void elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
@@ -80,6 +89,7 @@ class PWire : public LineInfo {
|
||||
hname_t hname_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
bool signed_;
|
||||
bool isint_; // original type of integer
|
||||
|
||||
@@ -100,6 +110,12 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.19 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.18 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.17 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
||||
+17
-51
@@ -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 complicated command:
|
||||
|
||||
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
|
||||
|
||||
@@ -359,7 +359,8 @@ constructs.
|
||||
Icarus Verilog includes some features that are not part of the
|
||||
IEEE1364 standard, but have well defined meaning, and also sometimes
|
||||
gives nonstandard (but extended) meanings to some features of the
|
||||
language that are defined.
|
||||
language that are defined. See the "extensions.txt" documentation for
|
||||
more details.
|
||||
|
||||
$is_signed(<expr>)
|
||||
This system function returns 1 if the expression contained is
|
||||
@@ -470,6 +471,20 @@ language that are defined.
|
||||
combinational always blocks to be triggered when the values in
|
||||
the sensitivity list are initialized by initial threads.
|
||||
|
||||
Nets with Types
|
||||
|
||||
Icarus Verilog support an extension syntax that allows nets
|
||||
and regs to be explicitly typed. The currently supported types
|
||||
are logic, bool and real. This implies that "logic" and "bool"
|
||||
are new keywords. Typical syntax is:
|
||||
|
||||
wire real foo = 1.0;
|
||||
reg logic bar, bat;
|
||||
|
||||
... and so forth. The syntax can be turned off by using the
|
||||
-g2 flag to iverilog, and turned on explicitly with the -g2x
|
||||
flag to iverilog.
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
@@ -479,52 +494,3 @@ Verilog guidance, and especially testing from many people. Testers in
|
||||
particular include a larger community of people interested in a GPL
|
||||
Verilog for Linux.
|
||||
|
||||
|
||||
6.1 PORT MAINTAINERS
|
||||
|
||||
This is a list of people who have created ports and precompiled
|
||||
packages for various operating systems. These folks have graciously
|
||||
taken on the task of building Icarus Verilog on their systems and
|
||||
bundled it into neat packages.(+) If you want to be added to the list (or
|
||||
removed from the list) send e-mail to me.
|
||||
|
||||
FreeBSD/{Intel,alpha}
|
||||
Ying-Chieh Liao <[email protected]>
|
||||
|
||||
Linux/{alpha,AMD64,Intel} (RPMS)
|
||||
Stephen Williams <[email protected]>
|
||||
|
||||
Linux/* (.debs)
|
||||
Hamish Moffatt <[email protected]>
|
||||
|
||||
Macintosh -- MacO/S
|
||||
Yasuhisa Kato <[email protected]>
|
||||
|
||||
Mac O/S X
|
||||
Timothy J. Wood <[email protected]>
|
||||
|
||||
NetBSD/*
|
||||
Dan McMahill <[email protected]>
|
||||
|
||||
Solaris/SPARC packages (.pkg)
|
||||
Dan McMahill <[email protected]>
|
||||
|
||||
Cygwin32/*
|
||||
Venkat Iyer <[email protected]>
|
||||
|
||||
Mingw32
|
||||
Venkat Iyer <[email protected]>
|
||||
|
||||
(+) These are not the only systems where Icarus Verilog has been run,
|
||||
just the systems where precompiled binaries are publicly available.
|
||||
|
||||
|
||||
6.2 TEST SUITE MANAGER
|
||||
|
||||
Steve Wilson <[email protected]> has taken on the large task of managing
|
||||
the test suite. He has maintained the regression test scripts, the
|
||||
driver list, received submissions from myself and others, and has
|
||||
written a great many tests on his own. Any compiler writer, for any
|
||||
language, will tell you that the test suite is at least as important
|
||||
as the compiler code itself.
|
||||
|
||||
|
||||
+12
-2
@@ -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.42 2005/12/05 21:21:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -36,6 +36,7 @@ class Design;
|
||||
class NetAssign_;
|
||||
class NetCAssign;
|
||||
class NetDeassign;
|
||||
class NetForce;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
@@ -345,7 +346,7 @@ class PForce : public Statement {
|
||||
explicit PForce(PExpr*l, PExpr*r);
|
||||
~PForce();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -393,6 +394,7 @@ class PNoop : public Statement {
|
||||
|
||||
public:
|
||||
PNoop() { }
|
||||
~PNoop() { }
|
||||
};
|
||||
|
||||
class PRepeat : public Statement {
|
||||
@@ -456,6 +458,14 @@ class PWhile : public Statement {
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.42 2005/12/05 21:21:18 steve
|
||||
* Fixes for stubborn compilers.
|
||||
*
|
||||
* Revision 1.41 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.40 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
||||
+6
-1
@@ -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.6 2005/06/14 19:13:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class perm_string {
|
||||
|
||||
public:
|
||||
@@ -120,6 +122,9 @@ class StringHeapLex : private StringHeap {
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.6 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
* Revision 1.5 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+4
-2
@@ -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.12 2006/02/15 18:42:42 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -55,7 +55,7 @@ ifeq (@enable_vvp32@,yes)
|
||||
vpidir32 = $(libdir)/ivl/@vpidir2@
|
||||
ALL32 = all32
|
||||
INSTALL32 = install32
|
||||
UNINSTALL32 = uninistall32
|
||||
UNINSTALL32 = uninstall32
|
||||
include $(srcdir)/enable_vvp32.mk
|
||||
endif
|
||||
|
||||
@@ -98,6 +98,8 @@ installdirs: ../mkinstalldirs
|
||||
uninstall: $(UNINSTALL32)
|
||||
rm -f $(vpidir)/cadpli.vpl
|
||||
|
||||
uninstall32:
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
include $(srcdir)/enable_vvp32.mk
|
||||
endif
|
||||
|
||||
+23
-4
@@ -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.30 2005/07/11 16:56:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -84,6 +84,7 @@ extern bool verbose_flag;
|
||||
extern bool debug_scopes;
|
||||
extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth2;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
@@ -93,15 +94,21 @@ extern list<const char*>library_suff;
|
||||
extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
|
||||
/* This is the generation of Verilog that the compiler is asked to
|
||||
support. */
|
||||
support. Then there are also more detailed controls for more
|
||||
specific language features. */
|
||||
enum generation_t {
|
||||
GN_VER1995 = 1,
|
||||
GN_VER2001 = 2,
|
||||
GN_SYSVER30 = 3,
|
||||
GN_VER2001X = 3,
|
||||
GN_DEFAULT = 3
|
||||
};
|
||||
|
||||
extern generation_t generation_flag;
|
||||
extern bool gn_cadence_types_flag;
|
||||
|
||||
/* These functions test that specific features are enabled. */
|
||||
inline bool gn_cadence_types_enabled()
|
||||
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
|
||||
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
@@ -126,7 +133,7 @@ extern StringHeapLex lex_strings;
|
||||
*/
|
||||
struct sfunc_return_type {
|
||||
const char* name;
|
||||
NetExpr::TYPE type;
|
||||
ivl_variable_type_t type;
|
||||
unsigned wid;
|
||||
int signed_flag;
|
||||
};
|
||||
@@ -136,6 +143,18 @@ extern int load_sys_func_table(const char*path);
|
||||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.30 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.29 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.28 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
*
|
||||
* Revision 1.27 2005/04/24 23:44:01 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.26 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+3
-2
@@ -141,6 +141,7 @@ AC_SUBST(vpidir1)
|
||||
AC_SUBST(vpidir2)
|
||||
AC_MSG_RESULT(${vpidir1} ${vpidir2})
|
||||
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-fpga libveriuser cadpli)
|
||||
# XXX disable tgt-fpga for the moment
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2003 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.54 2005/07/15 19:22:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -55,86 +55,6 @@ void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
// For now, only additions are handled.
|
||||
if (obj->attribute(perm_string::literal("LPM_Direction")) != verinum("ADD"))
|
||||
return;
|
||||
|
||||
// If the low bit on the A side is 0, then eliminate it from
|
||||
// the adder, and pass the B side directly to the
|
||||
// result. Don't reduce the adder smaller then a 1-bit
|
||||
// adder. These will be eliminated later.
|
||||
while ((obj->width() > 1)
|
||||
&& obj->pin_DataA(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataA(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// Now do the same thing on the B side.
|
||||
while ((obj->width() > 1)
|
||||
&& obj->pin_DataB(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataB(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataA(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// If the adder is only 1 bit wide, then replace it with the
|
||||
// simple logic gate.
|
||||
if (obj->width() == 1) {
|
||||
NetLogic*tmp;
|
||||
if (obj->pin_Cout().is_linked()) {
|
||||
tmp = new NetLogic(obj->scope(),
|
||||
obj->scope()->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(tmp->pin(0), obj->pin_Cout());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
des->add_node(tmp);
|
||||
}
|
||||
tmp = new NetLogic(obj->scope(), obj->name(), 3, NetLogic::XOR);
|
||||
connect(tmp->pin(0), obj->pin_Result(0));
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
@@ -153,6 +73,8 @@ void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
|
||||
void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
{
|
||||
#if 0
|
||||
/* XXXX Need to reimplement this code to account for vectors. */
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
unsigned const_count = 0;
|
||||
@@ -248,7 +170,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
with a simple XOR gate. */
|
||||
if (top == 1) {
|
||||
NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
|
||||
NetLogic::XNOR);
|
||||
NetLogic::XNOR, 1);
|
||||
connect(tmp->pin(0), obj->pin_AEB());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
@@ -271,6 +193,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
@@ -278,54 +201,15 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
// Look for and count unlinked FF outputs. Note that if the
|
||||
// Data and Q pins are connected together, they can be removed
|
||||
// from the circuit, since it doesn't do anything.
|
||||
unsigned unlinked_count = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))
|
||||
&& (! obj->pin_Sclr().is_linked())
|
||||
&& (! obj->pin_Sset().is_linked())
|
||||
&& (! obj->pin_Aclr().is_linked())
|
||||
&& (! obj->pin_Aset().is_linked())) {
|
||||
obj->pin_Data(idx).unlink();
|
||||
obj->pin_Q(idx).unlink();
|
||||
}
|
||||
if (! obj->pin_Q(idx).is_linked())
|
||||
unlinked_count += 1;
|
||||
}
|
||||
|
||||
// If the entire FF is unlinked, remove the whole thing.
|
||||
if (unlinked_count == obj->width()) {
|
||||
if (connected(obj->pin_Data(), obj->pin_Q())
|
||||
&& (! obj->pin_Sclr().is_linked())
|
||||
&& (! obj->pin_Sset().is_linked())
|
||||
&& (! obj->pin_Aclr().is_linked())
|
||||
&& (! obj->pin_Aset().is_linked())) {
|
||||
obj->pin_Data().unlink();
|
||||
obj->pin_Q().unlink();
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// If some of the FFs are unconnected, make a new FF array
|
||||
// that does not include the useless FF devices.
|
||||
if (unlinked_count > 0) {
|
||||
NetFF*tmp = new NetFF(obj->scope(), obj->name(),
|
||||
obj->width()-unlinked_count);
|
||||
connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
connect(tmp->pin_Enable(), obj->pin_Enable());
|
||||
connect(tmp->pin_Aload(), obj->pin_Aload());
|
||||
connect(tmp->pin_Aset(), obj->pin_Aset());
|
||||
connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
connect(tmp->pin_Sload(), obj->pin_Sload());
|
||||
connect(tmp->pin_Sset(), obj->pin_Sset());
|
||||
connect(tmp->pin_Sclr(), obj->pin_Sclr());
|
||||
|
||||
unsigned tidx = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
if (obj->pin_Q(idx).is_linked()) {
|
||||
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
|
||||
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
|
||||
tidx += 1;
|
||||
}
|
||||
|
||||
assert(tidx == obj->width() - unlinked_count);
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +218,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
switch (obj->type()) {
|
||||
|
||||
#if 0
|
||||
/* XXXX This old code assumed that the individual bit
|
||||
slices could be replaced with different gates. They
|
||||
cannot when the device takes atomic vectors, so this
|
||||
needs to be rewritten. XXXX */
|
||||
case NetLogic::NAND:
|
||||
case NetLogic::AND: {
|
||||
unsigned top = obj->pin_count();
|
||||
@@ -449,12 +337,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
case NetLogic::AND:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
break;
|
||||
case NetLogic::NAND:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -480,7 +368,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
obj->type(), 1);
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
@@ -497,7 +385,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
/* XXXX This old code assumed that the individual bit
|
||||
slices could be replaced with different gates. They
|
||||
cannot when the device takes atomic vectors, so this
|
||||
needs to be rewritten. XXXX */
|
||||
|
||||
case NetLogic::NOR:
|
||||
case NetLogic::OR: {
|
||||
@@ -597,12 +490,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
case NetLogic::OR:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
break;
|
||||
case NetLogic::NOR:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -619,7 +512,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
v }
|
||||
|
||||
/* Finally, this cleans up the gate by creating a
|
||||
new [N]OR gate that has the right number of
|
||||
@@ -627,7 +520,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
obj->type(), 1);
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
@@ -644,7 +537,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
/* XXXX This old code assumed that the individual bit
|
||||
slices could be replaced with different gates. They
|
||||
cannot when the device takes atomic vectors, so this
|
||||
needs to be rewritten. XXXX */
|
||||
case NetLogic::XNOR:
|
||||
case NetLogic::XOR: {
|
||||
unsigned top = obj->pin_count();
|
||||
@@ -766,11 +664,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
if (obj->type() == NetLogic::XOR)
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
else
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
@@ -795,11 +693,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
if (obj->type() == NetLogic::XOR)
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
NetLogic::BUF, 1);
|
||||
else
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
NetLogic::NOT, 1);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
@@ -821,7 +719,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
obj->type(), 1);
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -834,7 +732,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -856,29 +754,53 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
connected to the select input. */
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1);
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1, obj->width());
|
||||
|
||||
connect(obj->pin_Result(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);
|
||||
des->add_node(tmp);
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(1), tmp->pin(1));
|
||||
|
||||
if (obj->width() == 1) {
|
||||
/* Special case that the expression is 1 bit
|
||||
wide. Connect the select directly to the
|
||||
enable. */
|
||||
connect(obj->pin_Sel(), tmp->pin(2));
|
||||
|
||||
} else {
|
||||
/* General case that the expression is arbitrarily
|
||||
wide. Replicate the enable signal (which we
|
||||
assume is 1 bit wide) to match the expression,
|
||||
and connect the enable vector to the enable
|
||||
input of the gate. */
|
||||
NetReplicate*rtmp = new NetReplicate(scope,
|
||||
scope->local_symbol(),
|
||||
obj->width(),
|
||||
obj->width());
|
||||
des->add_node(rtmp);
|
||||
|
||||
|
||||
connect(obj->pin_Sel(), rtmp->pin(1));
|
||||
connect(tmp->pin(2), rtmp->pin(0));
|
||||
|
||||
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
rsig->local_flag(true);
|
||||
rsig->data_type(IVL_VT_LOGIC);
|
||||
connect(tmp->pin(2), rsig->pin(0));
|
||||
}
|
||||
|
||||
count += 1;
|
||||
@@ -886,33 +808,29 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* 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(1).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0);
|
||||
|
||||
connect(obj->pin_Result(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);
|
||||
}
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0, obj->width());
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
@@ -1038,6 +956,31 @@ void cprop(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.54 2005/07/15 19:22:52 steve
|
||||
* bufif enable is LOGIC.
|
||||
*
|
||||
* Revision 1.53 2005/05/15 04:44:30 steve
|
||||
* Disable obsolete logic constant fixup code.
|
||||
*
|
||||
* Revision 1.52 2005/04/24 23:44:01 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.51 2005/02/12 22:52:45 steve
|
||||
* Fix copyright notice.
|
||||
*
|
||||
* Revision 1.50 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.49 2005/01/16 04:20:32 steve
|
||||
* Implement LPM_COMPARE nodes as two-input vector functors.
|
||||
*
|
||||
* Revision 1.48 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.47 2004/02/20 18:53:34 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
||||
+217
-76
@@ -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.165 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -68,6 +68,28 @@ ostream& operator << (ostream&o, Link::strength_t str)
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&o, ivl_variable_type_t val)
|
||||
{
|
||||
switch (val) {
|
||||
case IVL_VT_VOID:
|
||||
o << "void";
|
||||
break;
|
||||
case IVL_VT_NO_TYPE:
|
||||
o << "<no_type>";
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
o << "real";
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
o << "bool";
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
o << "logic";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/* Dump a net. This can be a wire or register. */
|
||||
void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
@@ -75,6 +97,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
pin_count() << "]";
|
||||
if (local_flag_)
|
||||
o << " (local)";
|
||||
o << " " << data_type_;
|
||||
if (signed_)
|
||||
o << " signed";
|
||||
switch (port_type_) {
|
||||
@@ -96,8 +119,10 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope()->name();
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") init=";
|
||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||
<< decay_time() << ") vector_width=" << vector_width()
|
||||
<< " pin_count=" << pin_count()
|
||||
<< " init=";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << pin(idx-1).get_init();
|
||||
|
||||
@@ -117,13 +142,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSubnet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "** " << name() << " is a NetSubnet **"
|
||||
<< endl;
|
||||
NetNet::dump_net(o, ind);
|
||||
}
|
||||
|
||||
void NetMemory::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << name_ << "[" << width_ << "] " <<
|
||||
@@ -189,18 +207,13 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
|
||||
|
||||
void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
|
||||
<< " width=" << width() << " pin_count=" << pin_count()
|
||||
<< endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCAssign::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
@@ -216,6 +229,16 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConcat::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetConcat: "
|
||||
<< name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " width=" << width_ << 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;
|
||||
@@ -223,12 +246,6 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetForce::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force " << lval_->name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
|
||||
@@ -239,6 +256,7 @@ void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
void NetMux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
|
||||
<< " width=" << width_ << " swidth=" << swidth_ << " size=" << size_
|
||||
<< " scope=" << scope()->name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -249,20 +267,24 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "NetBUFZ: " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ")" << endl;
|
||||
decay_time() << ") width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
if (eeq_)
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "case compare !== : " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant ";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << setw(ind) << "" << "constant " << width_ << "'b";
|
||||
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -278,6 +300,13 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetLiteral::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant real " << real_
|
||||
<< ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "logic: ";
|
||||
@@ -353,6 +382,26 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
const char*pt = "";
|
||||
switch (dir_) {
|
||||
case VP:
|
||||
pt = "VP";
|
||||
break;
|
||||
case PV:
|
||||
pt = "PV";
|
||||
break;
|
||||
case BI:
|
||||
pt = "BI";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
|
||||
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
@@ -361,6 +410,58 @@ void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetReplicate: "
|
||||
<< name() << " wid=" << width_ << ", repeat_=" << repeat_
|
||||
<< ", input wid=" << width_/repeat_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetSignExtend: "
|
||||
<< name() << " output width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "reduction logic: ";
|
||||
switch (type_) {
|
||||
case NONE:
|
||||
o << "NONE";
|
||||
break;
|
||||
case AND:
|
||||
o << "and";
|
||||
break;
|
||||
case OR:
|
||||
o << "or";
|
||||
break;
|
||||
case XOR:
|
||||
o << "xor";
|
||||
break;
|
||||
case NAND:
|
||||
o << "nand";
|
||||
break;
|
||||
case NOR:
|
||||
o << "nor";
|
||||
break;
|
||||
case XNOR:
|
||||
o << "xnor";
|
||||
break;
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name() << "(";
|
||||
@@ -436,8 +537,8 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||
if (bmux_) {
|
||||
o << "[" << *bmux_ << "]";
|
||||
|
||||
} else {
|
||||
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]";
|
||||
} else if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
} else if (mem_) {
|
||||
// Is there an obvious way to flag memories in the dump
|
||||
@@ -447,8 +548,10 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
} else if (var_) {
|
||||
o << "<real " << var_->basename() << ">";
|
||||
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
} else {
|
||||
o << "";
|
||||
}
|
||||
@@ -474,10 +577,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const
|
||||
dump_lval(o);
|
||||
|
||||
o << " = ";
|
||||
#if 0
|
||||
if (l_val(0)->rise_time())
|
||||
o << "#" << l_val(0)->rise_time() << " ";
|
||||
#endif
|
||||
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
|
||||
o << *rval() << ";" << endl;
|
||||
}
|
||||
|
||||
@@ -487,10 +590,10 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
dump_lval(o);
|
||||
|
||||
o << " <= ";
|
||||
#if 0
|
||||
if (l_val(0)->rise_time())
|
||||
o << "#" << l_val(0)->rise_time() << " ";
|
||||
#endif
|
||||
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
|
||||
o << *rval() << ";" << endl;
|
||||
|
||||
}
|
||||
@@ -557,8 +660,9 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCAssign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "cassign " << lval_->name() << " = "
|
||||
<< name() << ";" << endl;
|
||||
o << setw(ind) << "" << "cassign ";
|
||||
dump_lval(o);
|
||||
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
@@ -578,8 +682,9 @@ void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "deassign " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "deassign ";
|
||||
dump_lval(o);
|
||||
o << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetDisable::dump(ostream&o, unsigned ind) const
|
||||
@@ -632,8 +737,9 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetForce::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force " << lval_->name() << " = "
|
||||
<< name() << ";" << endl;
|
||||
o << setw(ind) << "" << "force ";
|
||||
dump_lval(o);
|
||||
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetForever::dump(ostream&o, unsigned ind) const
|
||||
@@ -648,10 +754,6 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
if (result_sig_)
|
||||
o << setw(ind+2) << "" << "Return signal: "
|
||||
<< result_sig_->name() << endl;
|
||||
if (result_var_)
|
||||
o << setw(ind+2) << "" << "Return variable: "
|
||||
<< result_var_->basename() << endl;
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
else
|
||||
@@ -677,12 +779,9 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetRelease::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (lval_)
|
||||
o << setw(ind) << "" << "release " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "release (null); "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "release ";
|
||||
dump_lval(o);
|
||||
o << "; /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
@@ -712,6 +811,9 @@ void NetScope::dump(ostream&o) const
|
||||
case TASK:
|
||||
o << " task";
|
||||
break;
|
||||
case GENBLOCK:
|
||||
o << " generate block";
|
||||
break;
|
||||
}
|
||||
o << endl;
|
||||
|
||||
@@ -757,11 +859,6 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
}
|
||||
|
||||
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) {
|
||||
o << " real " << cur->basename() << " // "
|
||||
<< cur->get_line() << endl;
|
||||
}
|
||||
|
||||
/* Dump the events in this scope. */
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
|
||||
o << " event " << cur->name() << "; nprobe="
|
||||
@@ -937,7 +1034,7 @@ void NetEConstParam::dump(ostream&o) const
|
||||
{
|
||||
o << "<" << name_ << "=";
|
||||
NetEConst::dump(o);
|
||||
o << ">";
|
||||
o << ", wid=" << expr_width() << ">";
|
||||
}
|
||||
|
||||
void NetECReal::dump(ostream&o) const
|
||||
@@ -995,15 +1092,7 @@ void NetESignal::dump(ostream&o) const
|
||||
{
|
||||
if (has_sign())
|
||||
o << "+";
|
||||
o << name() << "[" << msi_<<":"<<lsi_ << "]";
|
||||
}
|
||||
|
||||
void NetEBitSel::dump(ostream&o) const
|
||||
{
|
||||
sig_->dump(o);
|
||||
o << "[";
|
||||
idx_->dump(o);
|
||||
o << "]";
|
||||
o << name() << "[" << msi()<<":"<<lsi() << "]";
|
||||
}
|
||||
|
||||
void NetEMemory::dump(ostream&o) const
|
||||
@@ -1055,11 +1144,6 @@ void NetEUnary::dump(ostream&o) const
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEVariable::dump(ostream&o) const
|
||||
{
|
||||
o << var_->basename();
|
||||
}
|
||||
|
||||
void Design::dump(ostream&o) const
|
||||
{
|
||||
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
|
||||
@@ -1089,6 +1173,63 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.165 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.164 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.163 2005/08/27 04:32:08 steve
|
||||
* Handle synthesis of fully packed case statements.
|
||||
*
|
||||
* Revision 1.162 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.161 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.160 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.159 2005/05/17 20:56:55 steve
|
||||
* Parameters cannot have their width changed.
|
||||
*
|
||||
* Revision 1.158 2005/05/07 03:13:30 steve
|
||||
* Include delay expressions for assignments in dump.
|
||||
*
|
||||
* Revision 1.157 2005/03/09 05:52:03 steve
|
||||
* Handle case inequality in netlists.
|
||||
*
|
||||
* Revision 1.156 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.155 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.154 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.153 2005/01/22 18:16:00 steve
|
||||
* Remove obsolete NetSubnet class.
|
||||
*
|
||||
* Revision 1.152 2005/01/09 20:16:00 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.151 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.150 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.149 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
.TH iverilog 1 "$Date: 2004/10/04 01:10:56 $" Version "$Date: 2004/10/04 01:10:56 $"
|
||||
.TH iverilog 1 "$Date: 2005/06/28 04:25:55 $" Version "$Date: 2005/06/28 04:25:55 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g3.0] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
|
||||
@@ -48,10 +48,10 @@ is the Verilog input, but with file inclusions and macro references
|
||||
expanded and removed. This is useful, for example, to preprocess
|
||||
Verilog source for use by other compilers.
|
||||
.TP 8
|
||||
.B -g1\fI|\fP-g2\fI|\fP-g3.0
|
||||
.B -g1\fI|\fP-g2\fI|\fP-g2x
|
||||
Select the Verilog language \fIgeneration\fP to support in the
|
||||
compiler. This selects between \fIIEEE1364-1995\fP(1),
|
||||
\fIIEEE1364-2001\fP(2), or \fISystemVerilog 3.0\fP(3.0). Normally,
|
||||
\fIIEEE1364-2001\fP(2), or \fIVerilog with extension\fP(2x). Normally,
|
||||
Icarus Verilog defaults to the latest known generation of the
|
||||
language. This flag is most useful to restrict the language to a set
|
||||
supported by tools of specific generations, for compatibility with
|
||||
|
||||
+13
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2001 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.65 2004/06/17 14:47:22 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.67 2005/07/14 23:38:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -39,7 +39,7 @@ const char NOTICE[] =
|
||||
;
|
||||
|
||||
const char HELP[] =
|
||||
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g3.0]\n"
|
||||
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g2x]\n"
|
||||
" [-D macro[=defn]] [-I includedir] [-M depfile] [-m module]\n"
|
||||
" [-N file] [-o filename] [-p flag=value]\n"
|
||||
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
||||
@@ -107,7 +107,7 @@ const char*npath = 0;
|
||||
const char*targ = "vvp";
|
||||
const char*depfile = 0;
|
||||
|
||||
const char*generation = "3.0";
|
||||
const char*generation = "2x";
|
||||
|
||||
char warning_flags[16] = "";
|
||||
|
||||
@@ -393,8 +393,8 @@ int process_generation(const char*name)
|
||||
else if (strcmp(name,"2") == 0)
|
||||
generation = "2";
|
||||
|
||||
else if (strcmp(name,"3.0") == 0)
|
||||
generation = "3.0";
|
||||
else if (strcmp(name,"2x") == 0)
|
||||
generation = "2x";
|
||||
|
||||
else {
|
||||
fprintf(stderr, "Unknown/Unsupported Language generation "
|
||||
@@ -402,7 +402,7 @@ int process_generation(const char*name)
|
||||
fprintf(stderr, "Supported generations are:\n");
|
||||
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
|
||||
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
|
||||
" 3.0 -- SystemVerilog 3.0\n");
|
||||
" 2x -- Verilog with extensions\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -735,6 +735,12 @@ int main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.67 2005/07/14 23:38:44 steve
|
||||
* Display as version 0.9.devel
|
||||
*
|
||||
* Revision 1.66 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
*
|
||||
* Revision 1.65 2004/06/17 14:47:22 steve
|
||||
* Add a .sft file for the system functions.
|
||||
*
|
||||
|
||||
+11
-13
@@ -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.20 2005/07/11 16:56:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -87,7 +87,7 @@ NetESFunc* NetESFunc::dup_expr() const
|
||||
|
||||
NetESignal* NetESignal::dup_expr() const
|
||||
{
|
||||
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
|
||||
NetESignal*tmp = new NetESignal(net_);
|
||||
assert(tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
return tmp;
|
||||
@@ -111,11 +111,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
||||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = 0;
|
||||
if (result_sig_)
|
||||
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
|
||||
if (result_var_)
|
||||
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
|
||||
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
|
||||
|
||||
assert(tmp);
|
||||
return tmp;
|
||||
@@ -135,14 +131,16 @@ NetEUReduce* NetEUReduce::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEVariable* NetEVariable::dup_expr() const
|
||||
{
|
||||
NetEVariable*tmp = new NetEVariable(var_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
||||
+5
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_anet.cc,v 1.10 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elab_anet.cc,v 1.11 2005/07/11 16:56:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -109,11 +109,10 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
NetVariable* var = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, var, par, eve);
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
|
||||
if (mem != 0) {
|
||||
@@ -167,6 +166,9 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_anet.cc,v $
|
||||
* Revision 1.11 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.10 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+667
-286
File diff suppressed because it is too large
Load Diff
+127
-131
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.33 2006/02/02 02:43:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -66,7 +66,9 @@
|
||||
* is to try to make a net elaboration, and see if the result is
|
||||
* suitable for assignment.
|
||||
*/
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet*ll = 0;
|
||||
if (ll == 0) {
|
||||
@@ -92,7 +94,9 @@ NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
|
||||
* NetAssign_ object.
|
||||
*/
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
{
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": error: Repeat concatenations make "
|
||||
@@ -112,7 +116,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
continue;
|
||||
}
|
||||
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
|
||||
|
||||
/* If the l-value doesn't elaborate, the error was
|
||||
already detected and printed. We just skip it and let
|
||||
@@ -140,23 +144,28 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
* Handle the ident as an l-value. This includes bit and part selects
|
||||
* of that ident.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
NetMemory* mem = 0;
|
||||
NetVariable* var = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, mem, var, par, eve);
|
||||
symbol_search(des, scope, path_, reg, mem, par, eve);
|
||||
|
||||
if (mem) {
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
if (is_force) {
|
||||
cerr << get_line() << ": error: Memories "
|
||||
<< "(" << path_ << " in this case)"
|
||||
<< " are not allowed"
|
||||
<< " as l-values to force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (var) {
|
||||
NetAssign_*cur = new NetAssign_(var);
|
||||
return cur;
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
|
||||
if (reg == 0) {
|
||||
@@ -171,8 +180,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
assert(reg);
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. (Wires are not allows in this context. */
|
||||
if (reg->type() != NetNet::REG) {
|
||||
it is a register. Wires are not allows in this context,
|
||||
unless this is the l-value of a force. */
|
||||
if ((reg->type() != NetNet::REG) && !is_force) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
"." << endl;
|
||||
@@ -185,7 +195,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
if (msb_ || lsb_) {
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
@@ -215,17 +227,19 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
lsb = vl->as_long();
|
||||
mux = 0;
|
||||
|
||||
} else if (msb_) {
|
||||
} else if (! idx_.empty()) {
|
||||
|
||||
/* If there is only a single select expression, it is a
|
||||
bit select. Evaluate the constant value and treat it
|
||||
as a part select with a bit width of 1. If the
|
||||
expression it not constant, then return the
|
||||
expression as a mux. */
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
verinum*v = msb_->eval_const(des, scope);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*v = idx_[0]->eval_const(des, scope);
|
||||
if (v == 0) {
|
||||
NetExpr*m = msb_->elaborate_expr(des, scope);
|
||||
NetExpr*m = idx_[0]->elaborate_expr(des, scope);
|
||||
assert(m);
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
@@ -261,6 +275,12 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
|
||||
lv->set_bmux(mux);
|
||||
|
||||
} else if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
/* If the bit/part select is constant, then make the
|
||||
@@ -283,7 +303,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->pin_count()) {
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
cerr << get_line() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
@@ -292,9 +312,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(loff, wid);
|
||||
|
||||
assert(moff < reg->pin_count());
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,7 +322,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
if (msb_ == 0) {
|
||||
if (idx_.empty()) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
@@ -312,37 +330,86 @@ NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": error: Cannot use part select on "
|
||||
<< "memory \"" << mem->name() << ".\"" << endl;
|
||||
if (idx_.size() != mem->dimensions()) {
|
||||
cerr << get_line() << ": error: " << idx_.size()
|
||||
<< " indices do not properly address a "
|
||||
<< mem->dimensions() << "-dimension memory/array."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ && !lsb_);
|
||||
// XXXX For now, require exactly 1 index.
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
NetExpr*ix = msb_->elaborate_expr(des, scope);
|
||||
/* Elaborate the address expression. */
|
||||
NetExpr*ix = elab_and_eval(des, scope, idx_[0]);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
/* Evaluate the memory index expression down as must as
|
||||
possible. Ideally, we can get it down to a constant. */
|
||||
if (! dynamic_cast<NetEConst*>(ix)) {
|
||||
NetExpr*tmp = ix->eval_tree();
|
||||
if (tmp) {
|
||||
tmp->set_line(*ix);
|
||||
delete ix;
|
||||
ix = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
|
||||
/* If there is no extra part select, then we are done. */
|
||||
if (msb_ == 0 && lsb_ == 0) {
|
||||
lv->set_part(0U, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ != SEL_NONE);
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return lv;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
lv->set_part(lec, wid);
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return lv;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*base_ex = elab_and_eval(des, scope, msb_);
|
||||
if (base_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
base_ex = make_add_expr(base_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
lv->set_part(base_ex, wid);
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
{
|
||||
cerr << get_line() << ": error: Constant values not allowed "
|
||||
<< "in l-value expressions." << endl;
|
||||
@@ -352,6 +419,25 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.33 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.32 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.31 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.30 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.29 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
@@ -360,95 +446,5 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
*
|
||||
* Revision 1.27 2003/09/19 03:30:05 steve
|
||||
* Fix name search in elab_lval.
|
||||
*
|
||||
* Revision 1.26 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.25 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.24 2003/01/19 00:35:39 steve
|
||||
* Detect null arguments to concatenation operator.
|
||||
*
|
||||
* Revision 1.23 2002/11/21 23:27:51 steve
|
||||
* Precalculate indices to l-value arrays.
|
||||
*
|
||||
* Revision 1.22 2002/11/21 18:15:40 steve
|
||||
* Fix const test of msb in assignment l-values.
|
||||
*
|
||||
* Revision 1.21 2002/11/02 01:10:49 steve
|
||||
* Detect memories without work index in l-value.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.18 2002/03/09 04:02:26 steve
|
||||
* Constant expressions are not l-values for task ports.
|
||||
*
|
||||
* Revision 1.17 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.16 2001/11/08 05:15:50 steve
|
||||
* Remove string paths from PExpr elaboration.
|
||||
*
|
||||
* Revision 1.15 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
*
|
||||
* Revision 1.14 2001/08/25 23:50:02 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.13 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.12 2001/02/09 03:16:48 steve
|
||||
* Report bit/part select out of range errors. (PR#133)
|
||||
*
|
||||
* Revision 1.11 2001/01/10 03:13:23 steve
|
||||
* Build task outputs as lval instead of nets. (PR#98)
|
||||
*
|
||||
* Revision 1.10 2001/01/06 06:31:58 steve
|
||||
* declaration initialization for time variables.
|
||||
*
|
||||
* Revision 1.9 2001/01/06 02:29:36 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.8 2000/12/12 06:14:51 steve
|
||||
* sorry for concatenated memories in l-values. (PR#76)
|
||||
*
|
||||
* Revision 1.7 2000/12/01 02:55:37 steve
|
||||
* Detect part select errors on l-values.
|
||||
*
|
||||
* Revision 1.6 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.5 2000/10/26 17:09:46 steve
|
||||
* Fix handling of errors in behavioral lvalues. (PR#28)
|
||||
*
|
||||
* Revision 1.4 2000/09/10 15:43:59 steve
|
||||
* Some error checking.
|
||||
*
|
||||
* Revision 1.3 2000/09/10 03:59:59 steve
|
||||
* Agressively merge NetAssign_ within concatenations.
|
||||
*
|
||||
* Revision 1.2 2000/09/10 02:18:16 steve
|
||||
* elaborate complex l-values
|
||||
*
|
||||
* Revision 1.1 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1118
-1007
File diff suppressed because it is too large
Load Diff
+16
-5
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.21 2004/02/20 06:22:56 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.23 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -140,7 +140,9 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
perm_string perm_name = lex_strings.make(name);
|
||||
delete name;
|
||||
|
||||
const NetExpr*ex = pscope->get_parameter(perm_name);
|
||||
const NetExpr*ex_msb;
|
||||
const NetExpr*ex_lsb;
|
||||
const NetExpr*ex = pscope->get_parameter(perm_name, ex_msb, ex_lsb);
|
||||
if (ex == 0) {
|
||||
cerr << get_line() << ": error: identifier ``" << path_ <<
|
||||
"'' is not a parameter in " << scope->name() << "." << endl;
|
||||
@@ -152,17 +154,20 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
res->set_line(*this);
|
||||
assert(res);
|
||||
|
||||
assert(idx_ == 0);
|
||||
if (msb_ && lsb_) {
|
||||
assert(idx_.empty());
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (msb_) {
|
||||
} else if (!idx_.empty()) {
|
||||
assert(msb_==0);
|
||||
assert(lsb_==0);
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
|
||||
NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
@@ -231,6 +236,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.23 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.22 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.21 2004/02/20 06:22:56 steve
|
||||
* parameter keys are per_strings.
|
||||
*
|
||||
|
||||
+176
-57
@@ -17,11 +17,12 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.35 2004/09/10 00:15:17 steve Exp $"
|
||||
#ident "$Id: elab_scope.cc,v 1.39 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
# include <stdio.h>
|
||||
|
||||
@@ -33,10 +34,10 @@
|
||||
*/
|
||||
|
||||
# include "Module.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
@@ -45,7 +46,8 @@
|
||||
# include <typeinfo>
|
||||
# include <assert.h>
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
const replace_t&replacements) const
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: Elaborate scope "
|
||||
@@ -75,8 +77,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
}
|
||||
@@ -107,7 +108,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = false;
|
||||
bool signed_flag = (*cur).second.signed_flag;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
@@ -118,16 +119,47 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
|
||||
signed_flag = (*cur).second.signed_flag;
|
||||
}
|
||||
|
||||
val->cast_signed(signed_flag);
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if ((*cur).second.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
val = scope->set_parameter((*cur).first, val,
|
||||
msb, lsb, signed_flag);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
|
||||
/* run parameter replacements that were collected from the
|
||||
containing scope and meant for me. */
|
||||
for (replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; cur ++) {
|
||||
|
||||
NetExpr*val = (*cur).second;
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_line() << "." << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope->name() << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
@@ -189,6 +221,17 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
delete[]attr;
|
||||
|
||||
// Generate schemes can create new scopes in the form of
|
||||
// generated code. Scan the generate schemes, and *generate*
|
||||
// new scopes, which is slightly different from simple
|
||||
// elaboration.
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> generate_scope(des, scope);
|
||||
}
|
||||
|
||||
|
||||
// Tasks introduce new scopes, so scan the tasks in this
|
||||
// module. Create a scope for the task and pass that to the
|
||||
@@ -255,13 +298,102 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
for (map<hname_t,PData*>::const_iterator cur = datum.begin()
|
||||
; cur != datum.end() ; cur ++ ) {
|
||||
return des->errors == 0;
|
||||
}
|
||||
|
||||
(*cur).second->elaborate_scope(des, scope);
|
||||
bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
{
|
||||
switch (scheme_type) {
|
||||
case GS_LOOP:
|
||||
return generate_scope_loop_(des, container);
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": sorry: Generate of this sort"
|
||||
<< " is not supported yet!" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the elaborate scope method for a generate loop.
|
||||
*/
|
||||
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
{
|
||||
// We're going to need a genvar...
|
||||
int genvar;
|
||||
|
||||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
// the same way any other paramter value is evaluated.
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
cerr << get_line() << ": error: Cannot evaluate genvar"
|
||||
<< " init expression: " << *loop_init << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return des->errors == 0;
|
||||
genvar = init->value().as_long();
|
||||
delete init_ex;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: genvar init = " << genvar << endl;
|
||||
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = 0;
|
||||
verinum*test = loop_test->eval_const(des, container);
|
||||
assert(test);
|
||||
while (test->as_long()) {
|
||||
|
||||
// The actual name of the scope includes the genvar so
|
||||
// that each instance has a unique name in the
|
||||
// container. The format of using [] is part of the
|
||||
// Verilog standard.
|
||||
char name_buf[128];
|
||||
snprintf(name_buf, sizeof name_buf,
|
||||
"%s[%d]", scope_name.str(), genvar);
|
||||
perm_string use_name = lex_strings.make(name_buf);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Create generated scope " << use_name << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
|
||||
// Set in the scope a localparam for the value of the
|
||||
// genvar within this instance of the generate
|
||||
// block. Code within this scope thus has access to the
|
||||
// genvar as a constant.
|
||||
{
|
||||
verinum genvar_verinum(genvar);
|
||||
genvar_verinum.has_sign(true);
|
||||
NetEConstParam*gp = new NetEConstParam(scope,
|
||||
loop_index,
|
||||
genvar_verinum);
|
||||
scope->set_localparam(loop_index, gp);
|
||||
}
|
||||
|
||||
scope_list_.push_back(scope);
|
||||
|
||||
// Calculate the step for the loop variable.
|
||||
verinum*step = loop_step->eval_const(des, container);
|
||||
assert(step);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: genvar step from "
|
||||
<< genvar << " to " << step->as_long() << endl;
|
||||
|
||||
genvar = step->as_long();
|
||||
container->genvar_tmp_val = genvar;
|
||||
delete step;
|
||||
delete test;
|
||||
test = loop_test->eval_const(des, container);
|
||||
}
|
||||
|
||||
container->genvar_tmp = perm_string();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
@@ -310,8 +442,10 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
return;
|
||||
}
|
||||
|
||||
verinum*msb = msb_ ? msb_->eval_const(des, sc) : 0;
|
||||
verinum*lsb = lsb_ ? lsb_->eval_const(des, sc) : 0;
|
||||
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_) : 0;
|
||||
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_) : 0;
|
||||
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
|
||||
assert( (msb == 0) || (lsb != 0) );
|
||||
|
||||
@@ -322,12 +456,15 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
if (msb) {
|
||||
instance_array = true;
|
||||
instance_high = msb->as_long();
|
||||
instance_low = lsb->as_long();
|
||||
instance_high = msb->value().as_long();
|
||||
instance_low = lsb->value().as_long();
|
||||
if (instance_high > instance_low)
|
||||
instance_count = instance_high - instance_low + 1;
|
||||
else
|
||||
instance_count = instance_low - instance_high + 1;
|
||||
|
||||
delete mse;
|
||||
delete lse;
|
||||
}
|
||||
|
||||
NetScope::scope_vec_t instances (instance_count);
|
||||
@@ -375,13 +512,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
my_scope->time_precision(mod->time_precision);
|
||||
des->set_precision(mod->time_precision);
|
||||
|
||||
// This call actually arranges for the description of the
|
||||
// module type to process this instance and handle parameters
|
||||
// and sub-scopes that might occur. Parameters are also
|
||||
// created in that scope, as they exist. (I'll override them
|
||||
// later.)
|
||||
mod->elaborate_scope(des, my_scope);
|
||||
|
||||
// Look for module parameter replacements. The "replace" map
|
||||
// maps parameter name to replacement expression that is
|
||||
// passed. It is built up by the ordered overrides or named
|
||||
@@ -424,6 +554,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
}
|
||||
|
||||
|
||||
Module::replace_t replace_net;
|
||||
|
||||
// And here we scan the replacements we collected. Elaborate
|
||||
// the expression in my context, then replace the sub-scope
|
||||
// parameter value with the new expression.
|
||||
@@ -433,13 +565,16 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
PExpr*tmp = (*cur).second;
|
||||
NetExpr*val = tmp->elaborate_pexpr(des, sc);
|
||||
bool flag = my_scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< sc->name() << "." << endl;
|
||||
}
|
||||
replace_net[(*cur).first] = val;
|
||||
}
|
||||
|
||||
// This call actually arranges for the description of the
|
||||
// module type to process this instance and handle parameters
|
||||
// and sub-scopes that might occur. Parameters are also
|
||||
// created in that scope, as they exist. (I'll override them
|
||||
// later.)
|
||||
mod->elaborate_scope(des, my_scope, replace_net);
|
||||
|
||||
}
|
||||
|
||||
/* Stash the instance array of scopes into the parent
|
||||
@@ -448,34 +583,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
sc->instance_arrays[get_name()] = instances;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the datum within the module. This variable may be
|
||||
* within a subscope (i.e., a function or task) so use the components
|
||||
* of the name to find the precise scope where this item goes.
|
||||
*/
|
||||
void PData::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*sub_scope = scope;
|
||||
for (unsigned idx = 0 ; idx < (hname_.component_count()-1); idx += 1) {
|
||||
sub_scope = sub_scope->child(hname_.peek_name(idx));
|
||||
|
||||
if (sub_scope == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Could not find sub-scope "
|
||||
<< hname_.peek_name(idx) << " of "
|
||||
<< hname_ << " in module " << scope->name()
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char*basename = hname_.peek_tail_name();
|
||||
NetVariable*tmp = new NetVariable(lex_strings.make(basename));
|
||||
tmp->set_line(*this);
|
||||
sub_scope->add_variable(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* The isn't really able to create new scopes, but it does create the
|
||||
* event name in the current scope, so can be done during the
|
||||
@@ -635,6 +742,18 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.39 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.38 2006/03/30 01:49:07 steve
|
||||
* Fix instance arrays indexed by overridden parameters.
|
||||
*
|
||||
* Revision 1.37 2006/03/18 22:53:38 steve
|
||||
* Support more parameter syntax.
|
||||
*
|
||||
* Revision 1.36 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.35 2004/09/10 00:15:17 steve
|
||||
* Missing stdio.h header for warnings.
|
||||
*
|
||||
|
||||
+120
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_sig.cc,v 1.36 2004/09/27 22:34:10 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.41 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -27,6 +27,7 @@
|
||||
# include "Module.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "compiler.h"
|
||||
@@ -158,6 +159,16 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Run through all the generate schemes to enaborate the
|
||||
// signals that they hold. Note that the generate schemes hold
|
||||
// the scopes that they instantiated, so we don't pass any
|
||||
// scope in.
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> elaborate_sig(des);
|
||||
}
|
||||
|
||||
// Get all the gates of the module and elaborate them by
|
||||
@@ -238,6 +249,44 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig(Design*des) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
typedef list<NetScope*>::const_iterator scope_list_it_t;
|
||||
for (scope_list_it_t cur = scope_list_.begin()
|
||||
; cur != scope_list_.end() ; cur ++ ) {
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate nets in "
|
||||
<< "scope " << (*cur)->name() << endl;
|
||||
flag = elaborate_sig_(des, *cur) & flag;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Scan the declared PWires to elaborate the obvious signals
|
||||
// in the current scope.
|
||||
typedef map<hname_t,PWire*>::const_iterator wires_it_t;
|
||||
for (wires_it_t wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate PWire "
|
||||
<< cur->path() << " in scope " << scope->name() << endl;
|
||||
|
||||
cur->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A function definition exists within an elaborated module. This
|
||||
* matters when elaborating signals, as the ports of the function are
|
||||
@@ -261,7 +310,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
NetNet*ret_sig = 0;
|
||||
NetVariable*ret_real = 0;
|
||||
|
||||
/* Create the signals/variables of the return value and write
|
||||
them into the function scope. */
|
||||
@@ -302,6 +350,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_LOGIC);
|
||||
break;
|
||||
|
||||
case PTF_INTEGER:
|
||||
@@ -310,6 +359,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
ret_sig->set_signed(true);
|
||||
ret_sig->set_isint(true);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_LOGIC);
|
||||
break;
|
||||
|
||||
case PTF_TIME:
|
||||
@@ -318,13 +368,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
ret_sig->set_signed(false);
|
||||
ret_sig->set_isint(false);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_LOGIC);
|
||||
break;
|
||||
|
||||
case PTF_REAL:
|
||||
case PTF_REALTIME:
|
||||
ret_real = new NetVariable(fname);
|
||||
ret_real->set_line(*this);
|
||||
scope->add_variable(ret_real);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->set_signed(true);
|
||||
ret_sig->set_isint(false);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_REAL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -370,7 +424,6 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
NetFuncDef*def = 0;
|
||||
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
||||
if (ret_real) def = new NetFuncDef(scope, ret_real, ports);
|
||||
|
||||
assert(def);
|
||||
scope->set_func_def(def);
|
||||
@@ -609,13 +662,57 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
} else {
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
with a simple wire with a pulldown/pullup with supply
|
||||
strength. In other words, transform:
|
||||
|
||||
supply0 foo;
|
||||
|
||||
to:
|
||||
|
||||
wire foo;
|
||||
pulldown #(supply0) (foo);
|
||||
|
||||
This reduces the backend burden, and behaves exactly
|
||||
the same. */
|
||||
|
||||
NetLogic*pull = 0;
|
||||
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
||||
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
||||
? NetLogic::PULLUP
|
||||
: NetLogic::PULLDOWN;
|
||||
pull = new NetLogic(scope, scope->local_symbol(),
|
||||
1, pull_type, wid);
|
||||
pull->set_line(*this);
|
||||
pull->pin(0).drive0(Link::SUPPLY);
|
||||
pull->pin(0).drive1(Link::SUPPLY);
|
||||
des->add_node(pull);
|
||||
wtype = NetNet::WIRE;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Generate a SUPPLY pulldown for the "
|
||||
<< "supply0 net." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Create signal "
|
||||
<< name << "["<<msb<<":"<<lsb<<"]"
|
||||
<< " in scope " << scope->name() << endl;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
|
||||
sig->data_type(data_type_);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
if (pull)
|
||||
connect(sig->pin(0), pull->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||
}
|
||||
@@ -623,6 +720,23 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.41 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.40 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.39 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.38 2005/02/13 01:15:07 steve
|
||||
* Replace supply nets with wires connected to pullup/down supply devices.
|
||||
*
|
||||
* Revision 1.37 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.36 2004/09/27 22:34:10 steve
|
||||
* Cleanup and factoring of autoconf.
|
||||
*
|
||||
|
||||
+635
-289
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2005 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: emit.cc,v 1.77 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.86 2005/07/11 16:56:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -63,12 +63,6 @@ bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCAssign::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_cassign(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(this);
|
||||
@@ -81,6 +75,11 @@ bool NetCompare::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetConcat::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->concat(this);
|
||||
}
|
||||
|
||||
bool NetConst::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_const(this);
|
||||
@@ -98,10 +97,9 @@ bool NetFF::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetForce::emit_node(struct target_t*tgt) const
|
||||
bool NetLiteral::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_force(this);
|
||||
return true;
|
||||
return tgt->net_literal(this);
|
||||
}
|
||||
|
||||
bool NetModulo::emit_node(struct target_t*tgt) const
|
||||
@@ -122,12 +120,33 @@ bool NetMux::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetPartSelect::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->part_select(this);
|
||||
}
|
||||
|
||||
bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ram_dq(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetReplicate::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->replicate(this);
|
||||
}
|
||||
|
||||
bool NetSignExtend::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->sign_extend(this);
|
||||
}
|
||||
|
||||
bool NetUReduce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->ureduce(this);
|
||||
}
|
||||
|
||||
|
||||
bool NetUserFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_function(this);
|
||||
@@ -312,9 +331,6 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
|
||||
tgt->event(cur);
|
||||
|
||||
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_)
|
||||
tgt->variable(cur);
|
||||
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_scope(tgt);
|
||||
|
||||
@@ -363,13 +379,12 @@ void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
bool Design::emit(struct target_t*tgt) const
|
||||
int Design::emit(struct target_t*tgt) const
|
||||
{
|
||||
bool rc = true;
|
||||
int rc = 0;
|
||||
|
||||
rc = rc && tgt->start_design(this);
|
||||
if (rc == false)
|
||||
return false;
|
||||
if (tgt->start_design(this) == false)
|
||||
return -2;
|
||||
|
||||
// enumerate the scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
@@ -378,27 +393,36 @@ bool Design::emit(struct target_t*tgt) const
|
||||
|
||||
|
||||
// emit nodes
|
||||
bool nodes_rc = true;
|
||||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
rc = rc && cur->emit_node(tgt);
|
||||
nodes_rc = nodes_rc && cur->emit_node(tgt);
|
||||
cur = cur->node_next_;
|
||||
} while (cur != nodes_->node_next_);
|
||||
}
|
||||
|
||||
|
||||
// emit task and function definitions
|
||||
bool tasks_rc = true;
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); scope++)
|
||||
rc &= (*scope)->emit_defs(tgt);
|
||||
tasks_rc &= (*scope)->emit_defs(tgt);
|
||||
|
||||
|
||||
// emit the processes
|
||||
bool proc_rc = true;
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
rc = rc && idx->emit(tgt);
|
||||
proc_rc &= idx->emit(tgt);
|
||||
|
||||
if (tgt->end_design(this) != 0)
|
||||
rc = false;
|
||||
rc = tgt->end_design(this);
|
||||
|
||||
if (nodes_rc == false)
|
||||
return -1;
|
||||
if (tasks_rc == false)
|
||||
return -2;
|
||||
if (proc_rc == false)
|
||||
return -3;
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -474,11 +498,6 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_signal(this);
|
||||
}
|
||||
|
||||
void NetEBitSel::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_subsignal(this);
|
||||
}
|
||||
|
||||
void NetETernary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ternary(this);
|
||||
@@ -489,12 +508,7 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_variable(this);
|
||||
}
|
||||
|
||||
bool emit(const Design*des, const char*type)
|
||||
int emit(const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
const struct target*tgt = target_table[idx];
|
||||
@@ -505,12 +519,48 @@ bool emit(const Design*des, const char*type)
|
||||
|
||||
cerr << "error: Code generator type " << type
|
||||
<< " not found." << endl;
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.86 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.85 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.84 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.83 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.82 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.81 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.80 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.79 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.78 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.77 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
@@ -536,131 +586,5 @@ bool emit(const Design*des, const char*type)
|
||||
* Revision 1.71 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.70 2002/11/03 20:36:10 steve
|
||||
* Error message for mising code generator type.
|
||||
*
|
||||
* Revision 1.69 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.68 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.67 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.66 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.65 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.64 2002/01/19 19:02:08 steve
|
||||
* Pass back target errors processing conditionals.
|
||||
*
|
||||
* Revision 1.63 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.62 2001/08/25 23:50:02 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.61 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.60 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.59 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.58 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.57 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.56 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.55 2000/11/04 01:54:01 steve
|
||||
* Modifications in support of gcc 2.96
|
||||
*
|
||||
* Revision 1.54 2000/09/26 01:35:42 steve
|
||||
* Remove the obsolete NetEIdent class.
|
||||
*
|
||||
* Revision 1.53 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.52 2000/09/02 20:54:20 steve
|
||||
* Rearrange NetAssign to make NetAssign_ separate.
|
||||
*
|
||||
* Revision 1.51 2000/08/14 04:39:56 steve
|
||||
* add th t-dll functions for net_const, net_bufz and processes.
|
||||
*
|
||||
* Revision 1.50 2000/08/09 03:43:45 steve
|
||||
* Move all file manipulation out of target class.
|
||||
*
|
||||
* Revision 1.49 2000/08/08 01:50:42 steve
|
||||
* target methods need not take a file stream.
|
||||
*
|
||||
* Revision 1.48 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.47 2000/07/29 16:21:08 steve
|
||||
* Report code generation errors through proc_delay.
|
||||
*
|
||||
* Revision 1.46 2000/07/27 05:13:44 steve
|
||||
* Support elaboration of disable statements.
|
||||
*
|
||||
* Revision 1.45 2000/05/11 23:37:27 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.44 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.43 2000/05/02 03:13:31 steve
|
||||
* Move memories to the NetScope object.
|
||||
*
|
||||
* Revision 1.42 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.41 2000/04/23 03:45:24 steve
|
||||
* Add support for the procedural release statement.
|
||||
*
|
||||
* Revision 1.40 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.39 2000/04/12 04:23:58 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.40 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,14 +26,15 @@
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
verinum* PExpr::eval_const(const Design*, const NetScope*) const
|
||||
verinum* PExpr::eval_const(const Design*, NetScope*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
||||
verinum* PEBinary::eval_const(const Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*l = left_->eval_const(des, scope);
|
||||
if (l == 0) return 0;
|
||||
@@ -142,16 +143,46 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
||||
delete r;
|
||||
return res;
|
||||
}
|
||||
verinum* PEConcat::eval_const(const Design*des, 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);
|
||||
assert(tmp);
|
||||
|
||||
*accum = concat(*accum, *tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
* possible if the identifier is that of a parameter.
|
||||
*/
|
||||
verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
|
||||
verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
const NetExpr*expr = des->find_parameter(scope, path_);
|
||||
NetNet*net;
|
||||
NetMemory*mem;
|
||||
NetEvent*eve;
|
||||
const NetExpr*expr;
|
||||
|
||||
// Handle the special case that this ident is a genvar
|
||||
// variable name. In that case, the genvar meaning preempts
|
||||
// everything and we just return that value immediately.
|
||||
if (scope->genvar_tmp
|
||||
&& strcmp(path_.peek_tail_name(),scope->genvar_tmp) == 0) {
|
||||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
@@ -173,23 +204,23 @@ verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
|
||||
return new verinum(eval->value());
|
||||
}
|
||||
|
||||
verinum* PEFNumber::eval_const(const Design*, const NetScope*) const
|
||||
verinum* PEFNumber::eval_const(const Design*, NetScope*) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new verinum(val);
|
||||
}
|
||||
|
||||
verinum* PENumber::eval_const(const Design*, const NetScope*) const
|
||||
verinum* PENumber::eval_const(const Design*, NetScope*) const
|
||||
{
|
||||
return new verinum(value());
|
||||
}
|
||||
|
||||
verinum* PEString::eval_const(const Design*, const NetScope*) const
|
||||
verinum* PEString::eval_const(const Design*, NetScope*) const
|
||||
{
|
||||
return new verinum(string(text_));
|
||||
}
|
||||
|
||||
verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
|
||||
verinum* PETernary::eval_const(const Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*test = expr_->eval_const(des, scope);
|
||||
if (test == 0)
|
||||
@@ -209,7 +240,7 @@ verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
||||
verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*val = expr_->eval_const(des, scope);
|
||||
if (val == 0)
|
||||
@@ -240,6 +271,18 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.39 2005/12/07 04:04:23 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
* Revision 1.38 2005/11/27 17:01:57 steve
|
||||
* Fix for stubborn compiler.
|
||||
*
|
||||
* Revision 1.37 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.36 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_attrib.cc,v 1.7 2004/02/20 18:53:35 steve Exp $"
|
||||
#ident "$Id: eval_attrib.cc,v 1.8 2005/11/27 17:01:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -36,7 +36,7 @@
|
||||
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
unsigned&natt,
|
||||
const Design*des,
|
||||
const NetScope*scope)
|
||||
NetScope*scope)
|
||||
{
|
||||
natt = att.size();
|
||||
if (natt == 0)
|
||||
@@ -74,6 +74,9 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
|
||||
/*
|
||||
* $Log: eval_attrib.cc,v $
|
||||
* Revision 1.8 2005/11/27 17:01:57 steve
|
||||
* Fix for stubborn compiler.
|
||||
*
|
||||
* Revision 1.7 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
||||
+160
-100
@@ -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.68 2006/03/18 22:52:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -55,26 +55,64 @@ NetEConst* NetEBAdd::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
/* If both operands are constant, then replace the entire
|
||||
expression with a constant value. */
|
||||
if (lc != 0 && rc != 0) {
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
verinum val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = lval + rval;
|
||||
break;
|
||||
case '-':
|
||||
val = lval - rval;
|
||||
break;
|
||||
default:
|
||||
verinum val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = lval + rval;
|
||||
break;
|
||||
case '-':
|
||||
val = lval - rval;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
/* Try to combine a right constant value with the right
|
||||
constant value of a sub-expression add. For example, the
|
||||
expression (a + 2) - 1 can be rewritten as a + 1. */
|
||||
|
||||
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
|
||||
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
|
||||
|
||||
if (lc != 0 && rc != 0) {
|
||||
assert(se != 0);
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
verinum val;
|
||||
if (op_ == se->op_) {
|
||||
/* (a + lval) + rval --> a + (rval+lval) */
|
||||
/* (a - lval) - rval --> a - (rval+lval) */
|
||||
val = rval + lval;
|
||||
} else {
|
||||
/* (a - lval) + rval --> a + (rval-lval) */
|
||||
/* (a + lval) - rval --> a - (rval-lval) */
|
||||
val = rval - lval;
|
||||
}
|
||||
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
left_ = se->left_->dup_expr();
|
||||
delete se;
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
/* We've changed the subexpression, but the result is
|
||||
still not constant, so return nil here anyhow. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(val);
|
||||
/* Nothing more to be done, the value is not constant. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBBits::eval_tree()
|
||||
@@ -175,43 +213,6 @@ NetEConst* NetEBBits::eval_tree()
|
||||
return new NetEConst(res);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
unsigned s_len = lv.len();
|
||||
if (rv.len() < s_len) s_len = rv.len();
|
||||
|
||||
verinum result(verinum::V1, 1);
|
||||
for (unsigned idx = 0 ; idx < s_len; idx += 1) {
|
||||
if (lv[idx] != rv[idx])
|
||||
result = verinum::V0;
|
||||
}
|
||||
|
||||
// If one operand was wider than the other, check that the
|
||||
// remaining bits are all zero
|
||||
if (lv.len() > s_len) {
|
||||
for (unsigned idx = s_len; idx < lv.len(); idx += 1) {
|
||||
if (lv[idx] != 0)
|
||||
result = verinum::V0;
|
||||
}
|
||||
}
|
||||
if (rv.len() > s_len) {
|
||||
for (unsigned idx = s_len; idx < rv.len(); idx += 1) {
|
||||
if (rv[idx] != 0)
|
||||
result = verinum::V0;
|
||||
}
|
||||
}
|
||||
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
{
|
||||
@@ -224,20 +225,27 @@ NetEConst* NetEBComp::eval_less_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
|
||||
/* Detect the case where the right side is greater than 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 result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
have. Use the width of the left expression as all 1's to
|
||||
calculate the maximum possible width for the left_
|
||||
expression. This test only works of the compare is
|
||||
unsigned. */
|
||||
if (! (rv.has_sign() || left_->has_sign())) {
|
||||
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
if (lv < rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
lv = l->value();
|
||||
verinum lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
@@ -266,7 +274,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
double lv, rv;
|
||||
|
||||
switch (left_->expr_type()) {
|
||||
case ET_REAL:
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (left_);
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
@@ -274,7 +282,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
lv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case ET_VECTOR:
|
||||
case IVL_VT_LOGIC:
|
||||
vtmp = dynamic_cast<NetEConst*> (left_);
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
@@ -288,7 +296,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
|
||||
|
||||
switch (right_->expr_type()) {
|
||||
case ET_REAL:
|
||||
case IVL_VT_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (right_);
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
@@ -296,7 +304,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
rv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case ET_VECTOR:
|
||||
case IVL_VT_LOGIC:
|
||||
vtmp = dynamic_cast<NetEConst*> (right_);
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
@@ -317,9 +325,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_();
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_();
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -374,8 +382,8 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
if ((left_->expr_type() == IVL_VT_REAL)
|
||||
&& (right_->expr_type() == IVL_VT_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
@@ -413,7 +421,7 @@ NetEConst* NetEBComp::eval_gt_()
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == NetExpr::ET_REAL) {
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
@@ -450,8 +458,8 @@ NetEConst* NetEBComp::eval_gt_()
|
||||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
if ((left_->expr_type() == IVL_VT_REAL)
|
||||
&& (right_->expr_type() == IVL_VT_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
@@ -479,7 +487,7 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
|
||||
/* Detect the case where the left side is greater than the
|
||||
largest value the right side can possibly have. */
|
||||
if (right_->expr_type() == NetExpr::ET_VECTOR) {
|
||||
if (right_->expr_type() == IVL_VT_LOGIC) {
|
||||
assert(right_->expr_width() > 0);
|
||||
verinum rv (verinum::V1, right_->expr_width());
|
||||
if (lv >= rv) {
|
||||
@@ -489,7 +497,7 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == NetExpr::ET_REAL) {
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
@@ -510,21 +518,25 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() >= rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (lv.has_sign() && rv.has_sign()) {
|
||||
|
||||
if (lv.as_ulong() >= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
if (lv.as_long() >= rv.as_long()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (lv.as_ulong() >= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_neeq_()
|
||||
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
@@ -534,7 +546,10 @@ NetEConst* NetEBComp::eval_neeq_()
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
verinum::V res = verinum::V0;
|
||||
const verinum::V eq_res = ne_flag? verinum::V0 : verinum::V1;
|
||||
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
|
||||
|
||||
verinum::V res = eq_res;
|
||||
unsigned top = lv.len();
|
||||
if (rv.len() < top)
|
||||
top = rv.len();
|
||||
@@ -567,10 +582,18 @@ NetEConst* NetEBComp::eval_neeq_()
|
||||
break;
|
||||
|
||||
if (rv.get(idx) != lv.get(idx))
|
||||
res = verinum::V1;
|
||||
res = ne_res;
|
||||
}
|
||||
|
||||
if (res != verinum::Vx) {
|
||||
verinum::V lpad = verinum::V0;
|
||||
verinum::V rpad = verinum::V0;
|
||||
|
||||
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
|
||||
lpad = verinum::V1;
|
||||
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
|
||||
rpad = verinum::V1;
|
||||
|
||||
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
|
||||
switch (lv.get(idx)) {
|
||||
|
||||
@@ -579,9 +602,14 @@ NetEConst* NetEBComp::eval_neeq_()
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
case verinum::V0:
|
||||
if (res != verinum::Vx && rpad != verinum::V0)
|
||||
res = ne_res;
|
||||
break;
|
||||
|
||||
case verinum::V1:
|
||||
if (res != verinum::Vx)
|
||||
res = verinum::V1;
|
||||
if (res != verinum::Vx && rpad != verinum::V1)
|
||||
res = ne_res;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -596,9 +624,14 @@ NetEConst* NetEBComp::eval_neeq_()
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
case verinum::V0:
|
||||
if (res != verinum::Vx && lpad != verinum::V0)
|
||||
res = ne_res;
|
||||
break;
|
||||
|
||||
case verinum::V1:
|
||||
if (res != verinum::Vx)
|
||||
res = verinum::V1;
|
||||
if (res != verinum::Vx && lpad != verinum::V1)
|
||||
res = ne_res;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -666,7 +699,7 @@ NetEConst* NetEBComp::eval_tree()
|
||||
return eval_eqeqeq_();
|
||||
|
||||
case 'e': // Equality (==)
|
||||
return eval_eqeq_();
|
||||
return eval_eqeq_(false);
|
||||
|
||||
case 'G': // >=
|
||||
return eval_gteq_();
|
||||
@@ -678,7 +711,7 @@ NetEConst* NetEBComp::eval_tree()
|
||||
return eval_neeqeq_();
|
||||
|
||||
case 'n': // not-equal (!=)
|
||||
return eval_neeq_();
|
||||
return eval_eqeq_(true);
|
||||
|
||||
case '<': // Less than
|
||||
return eval_less_();
|
||||
@@ -699,7 +732,7 @@ NetExpr* NetEBDiv::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (expr_type() == NetExpr::ET_REAL) {
|
||||
if (expr_type() == IVL_VT_REAL) {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
|
||||
@@ -744,7 +777,7 @@ NetExpr* NetEBDiv::eval_tree()
|
||||
|
||||
|
||||
} else {
|
||||
assert(expr_type() == NetExpr::ET_VECTOR);
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -837,14 +870,15 @@ NetExpr* NetEBMult::eval_tree_real_()
|
||||
verireal rval;
|
||||
|
||||
switch (left_->expr_type()) {
|
||||
case ET_REAL: {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
|
||||
if (lc == 0) return 0;
|
||||
lval = lc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case ET_VECTOR: {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
verinum tmp = lc->value();
|
||||
@@ -857,14 +891,15 @@ NetExpr* NetEBMult::eval_tree_real_()
|
||||
}
|
||||
|
||||
switch (right_->expr_type()) {
|
||||
case ET_REAL: {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
|
||||
if (rc == 0) return 0;
|
||||
rval = rc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case ET_VECTOR: {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
verinum tmp = rc->value();
|
||||
@@ -886,10 +921,10 @@ NetExpr* NetEBMult::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (expr_type() == ET_REAL)
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
return eval_tree_real_();
|
||||
|
||||
assert(expr_type() == ET_VECTOR);
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
@@ -1124,7 +1159,9 @@ NetExpr* NetEParam::eval_tree()
|
||||
return 0;
|
||||
|
||||
assert(scope_);
|
||||
const NetExpr*expr = scope_->get_parameter(name_);
|
||||
const NetExpr*expr_msb;
|
||||
const NetExpr*expr_lsb;
|
||||
const NetExpr*expr = scope_->get_parameter(name_, expr_msb, expr_lsb);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to match "
|
||||
<< "parameter " << name_ << " in scope "
|
||||
@@ -1175,7 +1212,8 @@ NetExpr* NetEParam::eval_tree()
|
||||
|
||||
switch (res->expr_type()) {
|
||||
|
||||
case NetExpr::ET_VECTOR:
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
{ NetEConst*tmp = dynamic_cast<NetEConst*>(res);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: parameter "
|
||||
@@ -1192,7 +1230,7 @@ NetExpr* NetEParam::eval_tree()
|
||||
return ptmp;
|
||||
}
|
||||
|
||||
case NetExpr::ET_REAL:
|
||||
case IVL_VT_REAL:
|
||||
{ NetECReal*tmp = dynamic_cast<NetECReal*>(res);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: parameter "
|
||||
@@ -1551,6 +1589,28 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.68 2006/03/18 22:52:27 steve
|
||||
* Properly handle signedness in compare.
|
||||
*
|
||||
* Revision 1.67 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.66 2005/11/10 13:28:12 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.65 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.64 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.63 2005/06/17 05:05:53 steve
|
||||
* Watch out for signed constants in magnitude compare.
|
||||
*
|
||||
* Revision 1.62 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+308
-286
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2005 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: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.74 2006/01/03 05:15:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -45,14 +45,14 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
assert(expr_width() >= lsig->pin_count());
|
||||
assert(expr_width() >= rsig->pin_count());
|
||||
assert(expr_width() >= lsig->vector_width());
|
||||
assert(expr_width() >= rsig->vector_width());
|
||||
|
||||
lsig = pad_to_width(des, lsig, expr_width());
|
||||
rsig = pad_to_width(des, rsig, expr_width());
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
unsigned width=lsig->pin_count();
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
unsigned width=lsig->vector_width();
|
||||
|
||||
perm_string path = lsig->scope()->local_symbol();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
@@ -60,11 +60,9 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
|
||||
perm_string oname = osig->scope()->local_symbol();
|
||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(lsig->pin(idx), adder->pin_DataA(idx));
|
||||
connect(rsig->pin(idx), adder->pin_DataB(idx));
|
||||
connect(osig->pin(idx), adder->pin_Result(idx));
|
||||
}
|
||||
connect(lsig->pin(0), adder->pin_DataA());
|
||||
connect(rsig->pin(0), adder->pin_DataB());
|
||||
connect(osig->pin(0), adder->pin_Result());
|
||||
des->add_node(adder);
|
||||
|
||||
switch (op()) {
|
||||
@@ -94,148 +92,58 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
if (lsig->pin_count() != rsig->pin_count()) {
|
||||
if (lsig->vector_width() != rsig->vector_width()) {
|
||||
cerr << get_line() << ": internal error: bitwise (" << op_
|
||||
<< ") widths do not match: " << lsig->pin_count()
|
||||
<< " != " << rsig->pin_count() << endl;
|
||||
<< ") widths do not match: " << lsig->vector_width()
|
||||
<< " != " << rsig->vector_width() << endl;
|
||||
cerr << get_line() << ": : width="
|
||||
<< lsig->pin_count() << ": " << *left_ << endl;
|
||||
<< lsig->vector_width() << ": " << *left_ << endl;
|
||||
cerr << get_line() << ": : width="
|
||||
<< rsig->pin_count() << ": " << *right_ << endl;
|
||||
<< rsig->vector_width() << ": " << *right_ << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, lsig->pin_count());
|
||||
NetNet::IMPLICIT, lsig->vector_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
perm_string oname = scope->local_symbol();
|
||||
NetLogic*gate;
|
||||
perm_string oname = scope->local_symbol();
|
||||
unsigned wid = lsig->vector_width();
|
||||
NetLogic*gate;
|
||||
|
||||
/* If the rsig bit is constant, then look for special
|
||||
cases that I can use to reduce the generated
|
||||
logic. If I find one, then handle it immediately and
|
||||
skip the rest of the processing of this bit. */
|
||||
if (rsig->pin(idx).nexus()->drivers_constant()) {
|
||||
verinum::V bval = rsig->pin(idx).nexus()->driven_value();
|
||||
|
||||
/* (A & 0) is (0) */
|
||||
if ((op() == '&') && bval == verinum::V0) {
|
||||
connect(osig->pin(idx), rsig->pin(idx));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* (A & 1) is A */
|
||||
if ((op() == '&') && bval == verinum::V1) {
|
||||
connect(osig->pin(idx), lsig->pin(idx));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR);
|
||||
break;
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR);
|
||||
break;
|
||||
case 'O':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR);
|
||||
break;
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(osig->pin(idx), gate->pin(0));
|
||||
connect(lsig->pin(idx), gate->pin(1));
|
||||
connect(rsig->pin(idx), gate->pin(2));
|
||||
|
||||
des->add_node(gate);
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND, wid);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR, wid);
|
||||
break;
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, wid);
|
||||
break;
|
||||
case 'O':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, wid);
|
||||
break;
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, wid);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(osig->pin(0), gate->pin(0));
|
||||
connect(lsig->pin(0), gate->pin(1));
|
||||
connect(rsig->pin(0), gate->pin(2));
|
||||
|
||||
gate->set_line(*this);
|
||||
des->add_node(gate);
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBComp::synthesize(Design*des)
|
||||
{
|
||||
NetEConst*lcon = reinterpret_cast<NetEConst*>(left_);
|
||||
NetEConst*rcon = reinterpret_cast<NetEConst*>(right_);
|
||||
|
||||
/* Handle the special case where one of the inputs is constant
|
||||
0. We can use an OR gate to do the comparison. Synthesize
|
||||
the non-const side as normal, then or(nor) the signals
|
||||
together to get result. */
|
||||
if ((rcon && (rcon->value() == verinum(0UL,rcon->expr_width())))
|
||||
|| (lcon && (lcon->value() == verinum(0UL,lcon->expr_width())))) {
|
||||
|
||||
NetNet*lsig = rcon
|
||||
? left_->synthesize(des)
|
||||
: right_->synthesize(des);
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
|
||||
NetLogic*gate;
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
case 'E':
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
break;
|
||||
case 'n':
|
||||
case 'N':
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
/* sig > 0 is true if any bit in sig is set. This
|
||||
is very much like sig != 0. (0 > sig) shouldn't
|
||||
happen. */
|
||||
if (rcon) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
/* 0 < sig is handled like sig > 0. */
|
||||
if (! rcon) {
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, scope->local_symbol(),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(gate->pin(idx+1), lsig->pin(idx));
|
||||
|
||||
des->add_node(gate);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
@@ -243,22 +151,25 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = lsig->pin_count();
|
||||
if (rsig->pin_count() > lsig->pin_count())
|
||||
width = rsig->pin_count();
|
||||
unsigned width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width)
|
||||
width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
/* Handle the special case of a single bit equality
|
||||
operation. Make an XNOR gate instead of a comparator. */
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR);
|
||||
3, NetLogic::XNOR, 1);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
@@ -271,7 +182,8 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
an XOR instead of an XNOR gate. */
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR);
|
||||
3, NetLogic::XOR, 1);
|
||||
gate->set_line(*this);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
connect(gate->pin(1), lsig->pin(0));
|
||||
connect(gate->pin(2), rsig->pin(0));
|
||||
@@ -281,13 +193,11 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
|
||||
|
||||
NetCompare*dev = new NetCompare(scope, scope->local_symbol(), width);
|
||||
dev->set_line(*this);
|
||||
des->add_node(dev);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(dev->pin_DataA(idx), lsig->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(dev->pin_DataB(idx), rsig->pin(idx));
|
||||
connect(dev->pin_DataA(), lsig->pin(0));
|
||||
connect(dev->pin_DataB(), rsig->pin(0));
|
||||
|
||||
|
||||
switch (op_) {
|
||||
@@ -338,25 +248,22 @@ NetNet* NetEBMult::synthesize(Design*des)
|
||||
|
||||
NetMult*mult = new NetMult(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
des->add_node(mult);
|
||||
|
||||
mult->set_signed( has_sign() );
|
||||
mult->set_line(*this);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(mult->pin_DataA(idx), lsig->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(mult->pin_DataB(idx), rsig->pin(idx));
|
||||
connect(mult->pin_DataA(), lsig->pin(0));
|
||||
connect(mult->pin_DataB(), rsig->pin(0));
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
|
||||
connect(mult->pin_Result(idx), osig->pin(idx));
|
||||
connect(mult->pin_Result(), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
@@ -370,6 +277,8 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->set_line(*this);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
switch (op()) {
|
||||
@@ -377,32 +286,28 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
case '/': {
|
||||
NetDivide*div = new NetDivide(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
des->add_node(div);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(div->pin_DataA(idx), lsig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(div->pin_DataB(idx), rsig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
|
||||
connect(div->pin_Result(idx), osig->pin(idx));
|
||||
connect(div->pin_DataA(), lsig->pin(0));
|
||||
connect(div->pin_DataB(), rsig->pin(0));
|
||||
connect(div->pin_Result(),osig->pin(0));
|
||||
break;
|
||||
}
|
||||
|
||||
case '%': {
|
||||
NetModulo*div = new NetModulo(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
des->add_node(div);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
connect(div->pin_DataA(idx), lsig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
|
||||
connect(div->pin_DataB(idx), rsig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
|
||||
connect(div->pin_Result(idx), osig->pin(idx));
|
||||
connect(div->pin_DataA(), lsig->pin(0));
|
||||
connect(div->pin_DataB(), rsig->pin(0));
|
||||
connect(div->pin_Result(),osig->pin(0));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -449,7 +354,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
|
||||
NetLogic*olog = new NetLogic(scope, oname,
|
||||
lsig->pin_count()+rsig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
NetLogic::OR, 1);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
|
||||
@@ -471,7 +376,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
NetLogic*olog;
|
||||
perm_string oname = scope->local_symbol();
|
||||
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND, 1);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
des->add_node(olog);
|
||||
@@ -530,30 +435,40 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
verinum::V0);
|
||||
des->add_node(zcon);
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
unsigned long ushift = shift>=0? shift : -shift;
|
||||
if (ushift > osig->vector_width())
|
||||
ushift = osig->vector_width();
|
||||
|
||||
if (shift > 0) {
|
||||
unsigned long ushift = shift;
|
||||
for (unsigned idx = 0; idx < osig->pin_count(); idx += 1)
|
||||
if (idx < ushift) {
|
||||
connect(osig->pin(idx), zsig->pin(0));
|
||||
} else {
|
||||
connect(osig->pin(idx), lsig->pin(idx-ushift));
|
||||
}
|
||||
} else {
|
||||
unsigned long dshift = 0-shift;
|
||||
for (unsigned idx = 0; idx < osig->pin_count() ; idx += 1)
|
||||
if (idx+dshift < lsig->pin_count())
|
||||
connect(osig->pin(idx), lsig->pin(idx+dshift));
|
||||
else
|
||||
connect(osig->pin(idx), zsig->pin(0));
|
||||
verinum znum (verinum::V0, ushift, true);
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
znum);
|
||||
des->add_node(zcon);
|
||||
|
||||
/* Detect the special case that the shift is the size of
|
||||
the whole expression. Simply connect the pad to the
|
||||
osig and escape. */
|
||||
if (ushift >= osig->vector_width()) {
|
||||
connect(zcon->pin(0), osig->pin(0));
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
|
||||
osig->vector_width(), 2);
|
||||
ccat->set_line(*this);
|
||||
des->add_node(ccat);
|
||||
|
||||
connect(ccat->pin(0), osig->pin(0));
|
||||
if (shift > 0) {
|
||||
connect(ccat->pin(1), zsig->pin(0));
|
||||
connect(ccat->pin(2), lsig->pin(0));
|
||||
} else {
|
||||
connect(ccat->pin(1), lsig->pin(0));
|
||||
connect(ccat->pin(2), zsig->pin(0));
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
@@ -568,20 +483,18 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
|
||||
assert(op() == 'l');
|
||||
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
|
||||
osig->pin_count(),
|
||||
rsig->pin_count(),
|
||||
osig->vector_width(),
|
||||
rsig->vector_width(),
|
||||
right_flag, signed_flag);
|
||||
dev->set_line(*this);
|
||||
des->add_node(dev);
|
||||
|
||||
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
|
||||
connect(dev->pin_Result(idx), osig->pin(idx));
|
||||
connect(dev->pin_Result(), osig->pin(0));
|
||||
|
||||
assert(lsig->pin_count() >= dev->width());
|
||||
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
|
||||
connect(dev->pin_Data(idx), lsig->pin(idx));
|
||||
assert(lsig->vector_width() == dev->width());
|
||||
connect(dev->pin_Data(), lsig->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < dev->width_dist() ; idx += 1)
|
||||
connect(dev->pin_Distance(idx), rsig->pin(idx));
|
||||
connect(dev->pin_Distance(), rsig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
@@ -590,8 +503,15 @@ NetNet* NetEConcat::synthesize(Design*des)
|
||||
{
|
||||
/* First, synthesize the operands. */
|
||||
NetNet**tmp = new NetNet*[parms_.count()];
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
tmp[idx] = parms_[idx]->synthesize(des);
|
||||
if (tmp[idx] == 0)
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag == false)
|
||||
return 0;
|
||||
|
||||
assert(tmp[0]);
|
||||
NetScope*scope = tmp[0]->scope();
|
||||
@@ -601,20 +521,16 @@ NetNet* NetEConcat::synthesize(Design*des)
|
||||
perm_string path = scope->local_symbol();
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
osig->data_type(tmp[0]->data_type());
|
||||
|
||||
/* Connect the output vector to the operands. */
|
||||
unsigned obit = 0;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetConcat*concat = new NetConcat(scope, scope->local_symbol(),
|
||||
osig->vector_width(), parms_.count());
|
||||
concat->set_line(*this);
|
||||
des->add_node(concat);
|
||||
connect(concat->pin(0), osig->pin(0));
|
||||
|
||||
assert(tmp[idx-1]);
|
||||
|
||||
for (unsigned bit = 0; bit < tmp[idx-1]->pin_count(); bit += 1) {
|
||||
connect(osig->pin(obit), tmp[idx-1]->pin(bit));
|
||||
obit += 1;
|
||||
}
|
||||
|
||||
if (tmp[idx-1]->local_flag() && tmp[idx-1]->get_refs() == 0)
|
||||
delete tmp[idx-1];
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
connect(concat->pin(idx+1), tmp[parms_.count()-idx-1]->pin(0));
|
||||
}
|
||||
|
||||
delete[]tmp;
|
||||
@@ -629,12 +545,12 @@ NetNet* NetEConst::synthesize(Design*des)
|
||||
perm_string path = scope->local_symbol();
|
||||
unsigned width=expr_width();
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width);
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->set_signed(has_sign());
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1)
|
||||
connect(osig->pin(idx), con->pin(idx));
|
||||
connect(osig->pin(0), con->pin(0));
|
||||
|
||||
des->add_node(con);
|
||||
return osig;
|
||||
@@ -659,28 +575,27 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = isig->vector_width();
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, isig->pin_count());
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
perm_string oname = scope->local_symbol();
|
||||
NetLogic*gate;
|
||||
perm_string oname = scope->local_symbol();
|
||||
NetLogic*gate;
|
||||
|
||||
switch (op()) {
|
||||
case '~':
|
||||
gate = new NetLogic(scope, oname, 2, NetLogic::NOT);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(osig->pin(idx), gate->pin(0));
|
||||
connect(isig->pin(idx), gate->pin(1));
|
||||
|
||||
des->add_node(gate);
|
||||
switch (op()) {
|
||||
case '~':
|
||||
gate = new NetLogic(scope, oname, 2, NetLogic::NOT, width);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(osig->pin(0), gate->pin(0));
|
||||
connect(isig->pin(0), gate->pin(1));
|
||||
|
||||
des->add_node(gate);
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
@@ -702,32 +617,32 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
case 'N':
|
||||
case '!':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NOR);
|
||||
NetLogic::NOR, 1);
|
||||
break;
|
||||
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::AND);
|
||||
NetLogic::AND, 1);
|
||||
break;
|
||||
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
NetLogic::OR, 1);
|
||||
break;
|
||||
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XOR);
|
||||
NetLogic::XOR, 1);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NAND);
|
||||
NetLogic::NAND, 1);
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XNOR);
|
||||
NetLogic::XNOR, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -744,39 +659,114 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEMemory::synthesize(Design *des)
|
||||
{
|
||||
NetNet*adr = idx_->synthesize(des);
|
||||
|
||||
NetScope*scope = adr->scope();
|
||||
|
||||
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
|
||||
mem_, adr->vector_width());
|
||||
des->add_node(ram);
|
||||
ram->set_line(*this);
|
||||
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
|
||||
/* Create an output signal to receive the data. Assume that
|
||||
memories return LOGIC. */
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, ram->width());
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->local_flag(true);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(ram->pin_Q(), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
|
||||
}
|
||||
|
||||
NetNet* NetESelect::synthesize(Design *des)
|
||||
{
|
||||
// XXXX For now, only support pad form
|
||||
assert(base_ == 0);
|
||||
|
||||
NetNet*sub = expr_->synthesize(des);
|
||||
if (sub == 0)
|
||||
return 0;
|
||||
|
||||
NetScope*scope = sub->scope();
|
||||
|
||||
unsigned off = 0;
|
||||
|
||||
if (base_ != 0) {
|
||||
// For now, only handle constant part selects in this
|
||||
// context.
|
||||
NetEConst*bcon = dynamic_cast<NetEConst*>(base_);
|
||||
assert(bcon);
|
||||
|
||||
long bval = bcon->value().as_long();
|
||||
off = sub->sb_to_idx(bval);
|
||||
}
|
||||
|
||||
/* If there is a part select, then generate a PartSelect node
|
||||
to actually do the part select. This does not expansion,
|
||||
that is handled later. */
|
||||
if ((off != 0) || (off+expr_width() < sub->vector_width())) {
|
||||
unsigned wid = expr_width();
|
||||
if ((wid + off) > sub->vector_width())
|
||||
wid = sub->vector_width() - off;
|
||||
|
||||
NetPartSelect*sel = new NetPartSelect(sub, off, wid,
|
||||
NetPartSelect::VP);
|
||||
sel->set_line(*this);
|
||||
des->add_node(sel);
|
||||
|
||||
sub = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
sub->local_flag(true);
|
||||
sub->set_line(*this);
|
||||
connect(sub->pin(0), sel->pin(0));
|
||||
}
|
||||
|
||||
/* Done? Vector is already the right width? then stop now. */
|
||||
if (sub->vector_width() == expr_width())
|
||||
return sub;
|
||||
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
if (has_sign()) {
|
||||
unsigned idx;
|
||||
NetSignExtend*pad = new NetSignExtend(scope,
|
||||
scope->local_symbol(),
|
||||
expr_width());
|
||||
pad->set_line(*this);
|
||||
des->add_node(pad);
|
||||
|
||||
for (idx = 0 ; idx < sub->pin_count() ; idx += 1)
|
||||
connect(sub->pin(idx), net->pin(idx));
|
||||
|
||||
for ( ; idx < net->pin_count(); idx += 1)
|
||||
connect(sub->pin(sub->pin_count()-1), net->pin(idx));
|
||||
connect(pad->pin(1), sub->pin(0));
|
||||
connect(pad->pin(0), net->pin(0));
|
||||
|
||||
} else {
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < sub->pin_count() ; idx += 1)
|
||||
connect(sub->pin(idx), net->pin(idx));
|
||||
|
||||
NetConst*tmp = new NetConst(scope, scope->local_symbol(),
|
||||
verinum::V0);
|
||||
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
|
||||
expr_width(), 2);
|
||||
cat->set_line(*this);
|
||||
des->add_node(cat);
|
||||
|
||||
for ( ; idx < net->pin_count() ; idx += 1)
|
||||
connect(net->pin(idx), tmp->pin(0));
|
||||
assert(expr_width() > sub->vector_width());
|
||||
unsigned pad_width = expr_width() - sub->vector_width();
|
||||
verinum pad(0UL, pad_width);
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(),
|
||||
pad);
|
||||
con->set_line(*this);
|
||||
des->add_node(con);
|
||||
|
||||
des->add_node(tmp);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, pad_width);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(tmp->pin(0), con->pin(0));
|
||||
|
||||
connect(cat->pin(0), net->pin(0));
|
||||
connect(cat->pin(1), sub->pin(0));
|
||||
connect(cat->pin(2), con->pin(0));
|
||||
}
|
||||
|
||||
return net;
|
||||
@@ -796,28 +786,27 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
|
||||
perm_string path = csig->scope()->local_symbol();
|
||||
|
||||
assert(csig->pin_count() == 1);
|
||||
assert(csig->vector_width() == 1);
|
||||
|
||||
unsigned width=expr_width();
|
||||
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
|
||||
/* Make sure both value operands are the right width. */
|
||||
tsig = pad_to_width(des, tsig, width);
|
||||
fsig = pad_to_width(des, fsig, width);
|
||||
tsig = crop_to_width(des, pad_to_width(des, tsig, width), width);
|
||||
fsig = crop_to_width(des, pad_to_width(des, fsig, width), width);
|
||||
|
||||
assert(width <= tsig->pin_count());
|
||||
assert(width <= fsig->pin_count());
|
||||
assert(width == tsig->vector_width());
|
||||
assert(width == fsig->vector_width());
|
||||
|
||||
perm_string oname = csig->scope()->local_symbol();
|
||||
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
|
||||
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));
|
||||
connect(osig->pin(idx), mux->pin_Result(idx));
|
||||
}
|
||||
NetMux *mux = new NetMux(csig->scope(), oname, width,
|
||||
2, csig->vector_width());
|
||||
connect(tsig->pin(0), mux->pin_Data(1));
|
||||
connect(fsig->pin(0), mux->pin_Data(0));
|
||||
connect(osig->pin(0), mux->pin_Result());
|
||||
connect(csig->pin(0), mux->pin_Sel());
|
||||
des->add_node(mux);
|
||||
connect(csig->pin(0), mux->pin_Sel(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
@@ -854,27 +843,60 @@ NetNet* NetETernary::synthesize(Design *des)
|
||||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
|
||||
return net_;
|
||||
|
||||
assert(msi_ >= lsi_);
|
||||
unsigned wid = msi_ - lsi_ + 1;
|
||||
|
||||
NetScope*scope = net_->scope();
|
||||
assert(scope);
|
||||
|
||||
perm_string name = scope->local_symbol();
|
||||
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net_->pin(idx+lsi_));
|
||||
|
||||
return tmp;
|
||||
return net_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.74 2006/01/03 05:15:33 steve
|
||||
* Fix the return type of a synthesized divide.
|
||||
*
|
||||
* Revision 1.73 2005/09/15 23:04:09 steve
|
||||
* Make sure div, mod and mult nodes have line number info.
|
||||
*
|
||||
* Revision 1.72 2005/08/31 05:07:31 steve
|
||||
* Handle memory references is continuous assignments.
|
||||
*
|
||||
* Revision 1.71 2005/06/13 23:22:14 steve
|
||||
* use NetPartSelect to shrink part from high bits.
|
||||
*
|
||||
* Revision 1.70 2005/06/13 22:26:03 steve
|
||||
* Make synthesized padding vector-aware.
|
||||
*
|
||||
* Revision 1.69 2005/05/15 04:47:00 steve
|
||||
* synthesis of Logic and shifts using vector gates.
|
||||
*
|
||||
* Revision 1.68 2005/05/06 00:25:13 steve
|
||||
* Handle synthesis of concatenation expressions.
|
||||
*
|
||||
* Revision 1.67 2005/04/25 01:30:31 steve
|
||||
* synthesis of add and unary get vector widths right.
|
||||
*
|
||||
* Revision 1.66 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.65 2005/03/12 06:43:35 steve
|
||||
* Update support for LPM_MOD.
|
||||
*
|
||||
* Revision 1.64 2005/02/19 02:43:38 steve
|
||||
* Support shifts and divide.
|
||||
*
|
||||
* Revision 1.63 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.62 2005/01/28 05:39:33 steve
|
||||
* Simplified NetMult and IVL_LPM_MULT.
|
||||
*
|
||||
* Revision 1.61 2005/01/16 04:20:32 steve
|
||||
* Implement LPM_COMPARE nodes as two-input vector functors.
|
||||
*
|
||||
* Revision 1.60 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.59 2004/06/30 02:16:26 steve
|
||||
* Implement signed divide and signed right shift in nets.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
Icarus Verilog Extensions
|
||||
|
||||
Icarus Verilog supports certain extensions to the baseline IEEE1364
|
||||
standard. Some of these are picked from extended variants of the
|
||||
language, such as SystemVerilog, and some are expressions of internal
|
||||
behavior of Icarus Verilog, made available as a tool debugging aid.
|
||||
|
||||
* Builtin System Functions
|
||||
|
||||
** Extended Verilog Data Types
|
||||
|
||||
This feature is turned off if the generation flag "-g" is set to other
|
||||
then the default "2x". For example, "iverilog -g2x" enables extended
|
||||
data types, and "iverilog -g2" disables them.
|
||||
|
||||
Icarus Verilog adds support for extended data types. This extended
|
||||
type syntax is based on a proposal by Cadence Design Systems,
|
||||
originally as an update to the IEEE1364. That original proposal has
|
||||
apparently been absorbed by the IEEE1800 SystemVerilog
|
||||
standard. Icarus Verilog currently only takes the new primitive types
|
||||
from the proposal.
|
||||
|
||||
Extended data types separates the concept of net/variable from the
|
||||
data type. Both nets and variables can declared with any data
|
||||
type. The primitive types available are:
|
||||
|
||||
logic - The familiar 0, 1, x and z, optionally with strength.
|
||||
bool - Limited to only 0 and 1
|
||||
real - 64bit real values
|
||||
|
||||
Nets with logic type may have multiple drivers with strength, and the
|
||||
value is resolved the usual way. Only logic values may be driven to
|
||||
logic nets, so bool values driven onto logic nets are implicitly
|
||||
converted to logic.
|
||||
|
||||
Nets with any other type may not have multiple drivers. The compiler
|
||||
should detect the multiple drivers and report an error.
|
||||
|
||||
- Declarations
|
||||
|
||||
The declaration of a net is extended to include the type of the wire,
|
||||
with the syntax:
|
||||
|
||||
wire <type> <wire-assignment-list>... ;
|
||||
|
||||
The <type>, if omitted, is taken to be logic. The "wire" can be any of
|
||||
the net keywords. Wires can be logic, bool, real, or vectors of logic
|
||||
or bool. Some valid examples:
|
||||
|
||||
wire real foo = 1.0;
|
||||
tri logic bus[31:0];
|
||||
wire bool addr[23:0];
|
||||
... and so on.
|
||||
|
||||
The declarations of variables is similar. The "reg" keyword is used to
|
||||
specify that this is a variable. Variables can have the same data
|
||||
types as nets.
|
||||
|
||||
- Ports
|
||||
|
||||
Module and task ports in standard verilog are restricted to logic
|
||||
types. This extension removes that restriction, allowing any type to
|
||||
pass through the port consistent with the continuous assignment
|
||||
connectivity that is implied by the type.
|
||||
|
||||
- Expressions
|
||||
|
||||
Expressions in the face of real values is covered by the baseline
|
||||
Verilog standard.
|
||||
|
||||
The bool type supports the same operators as the logic type, with the
|
||||
obvious differences imposed by the limited domain.
|
||||
|
||||
Comparison operators (not case compare) return logic if either of
|
||||
their operands is logic. If both are bool or real (including mix of
|
||||
bool and real) then the result is bool. This is because comparison of
|
||||
bools and reals always return exactly true or false.
|
||||
|
||||
Case comparison returns bool. This differs from baseline Verilog,
|
||||
which strictly speaking returns a logic, but only 0 or 1 values.
|
||||
|
||||
All the arithmetic operators return bool if both of their operands are
|
||||
bool or real. Otherwise, they return logic.
|
||||
+38
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2005 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: functor.cc,v 1.32 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.35 2005/07/07 16:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -59,6 +59,10 @@ void functor_t::lpm_divide(class Design*, class NetDivide*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_literal(class Design*, class NetLiteral*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_modulo(class Design*, class NetModulo*)
|
||||
{
|
||||
}
|
||||
@@ -79,6 +83,14 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::sign_extend(class Design*, class NetSignExtend*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ureduce(class Design*, class NetUReduce*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
{
|
||||
@@ -186,6 +198,11 @@ void NetFF::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_ff(des, this);
|
||||
}
|
||||
|
||||
void NetLiteral::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_literal(des, this);
|
||||
}
|
||||
|
||||
void NetLogic::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_logic(des, this);
|
||||
@@ -206,6 +223,16 @@ void NetMux::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
void NetSignExtend::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->sign_extend(des, this);
|
||||
}
|
||||
|
||||
void NetUReduce::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ureduce(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
{
|
||||
}
|
||||
@@ -267,6 +294,15 @@ int proc_match_t::event_wait(NetEvWait*)
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.35 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.34 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.33 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.32 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.20 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.23 2005/07/07 16:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -63,6 +63,9 @@ struct functor_t {
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_divide(class Design*des, class NetDivide*);
|
||||
|
||||
/* Constant literals. */
|
||||
virtual void lpm_literal(class Design*des, class NetLiteral*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_modulo(class Design*des, class NetModulo*);
|
||||
|
||||
@@ -77,6 +80,11 @@ struct functor_t {
|
||||
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
|
||||
/* This method is called for each unary reduction gate. */
|
||||
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
|
||||
|
||||
virtual void sign_extend(class Design*des, class NetSignExtend*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
@@ -92,6 +100,15 @@ struct proc_match_t {
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.23 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.22 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.21 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+3
-2
@@ -17,11 +17,11 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.14 2004/05/20 00:40:34 steve Exp $"
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.15 2006/02/21 02:38:44 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=gcc
|
||||
CXX=gcc
|
||||
CXX=g++
|
||||
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
|
||||
|
||||
# These are used for linking...
|
||||
@@ -63,6 +63,7 @@ do
|
||||
;;
|
||||
|
||||
*.cc) CXSRC="$CXSRC $parm"
|
||||
LD=$CXX
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cc`
|
||||
fi
|
||||
|
||||
@@ -62,6 +62,7 @@ ivl_logic_udp
|
||||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_base
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
|
||||
+700
-97
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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.
|
||||
|
||||
@@ -19,7 +19,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.90 2006/03/30 05:44:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -154,7 +154,7 @@ W [ \t\b\f\r]+
|
||||
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
|
||||
and ")", but since I know that this is really ( * ), replace it
|
||||
with "*" and return that. */
|
||||
"(*"{W}*")" { return '*'; }
|
||||
"("{W}*"*"{W}*")" { return '*'; }
|
||||
|
||||
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
@@ -179,6 +179,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'; }
|
||||
@@ -198,12 +200,27 @@ W [ \t\b\f\r]+
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
int rc = lexor_keyword_code(yytext, yyleng);
|
||||
if (rc == IDENTIFIER) {
|
||||
switch (rc) {
|
||||
case IDENTIFIER:
|
||||
yylval.text = strdup(yytext);
|
||||
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
|
||||
rc = PATHPULSE_IDENTIFIER;
|
||||
} else {
|
||||
break;
|
||||
|
||||
case K_bool:
|
||||
case K_logic:
|
||||
case K_wone:
|
||||
if (! gn_cadence_types_enabled()) {
|
||||
yylval.text = strdup(yytext);
|
||||
rc = IDENTIFIER;
|
||||
} else {
|
||||
yylval.text = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
yylval.text = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -276,10 +293,10 @@ W [ \t\b\f\r]+
|
||||
^{W}?`disable_portfaults{W}?.* { }
|
||||
^{W}?`enable_portfaults{W}?.* { }
|
||||
^{W}?`endcelldefine{W}?.* { }
|
||||
^{W}?`endprotect{W}?.* { }
|
||||
`endprotect { }
|
||||
^{W}?`nosuppress_faults{W}?.* { }
|
||||
^{W}?`nounconnected_drive{W}?.* { }
|
||||
^{W}?`protect{W}?.* { }
|
||||
`protect { }
|
||||
^{W}?`resetall{W}?.* { }
|
||||
^{W}?`suppress_faults{W}?.* { }
|
||||
^{W}?`unconnected_drive{W}?.* { }
|
||||
|
||||
@@ -14,6 +14,7 @@ always, K_always
|
||||
and, K_and
|
||||
assign, K_assign
|
||||
begin, K_begin
|
||||
bool, K_bool
|
||||
buf, K_buf
|
||||
bufif0, K_bufif0
|
||||
bufif1, K_bufif1
|
||||
@@ -30,6 +31,7 @@ else, K_else
|
||||
end, K_end
|
||||
endcase, K_endcase
|
||||
endfunction, K_endfunction
|
||||
endgenerate, K_endgenerate
|
||||
endmodule, K_endmodule
|
||||
endprimitive, K_endprimitive
|
||||
endspecify, K_endspecify
|
||||
@@ -41,6 +43,8 @@ force, K_force
|
||||
forever, K_forever
|
||||
fork, K_fork
|
||||
function, K_function
|
||||
generate, K_generate
|
||||
genvar, K_genvar
|
||||
highz0, K_highz0
|
||||
highz1, K_highz1
|
||||
if, K_if
|
||||
@@ -51,6 +55,7 @@ integer, K_integer
|
||||
join, K_join
|
||||
large, K_large
|
||||
localparam, K_localparam
|
||||
logic, K_logic
|
||||
macromodule, K_macromodule
|
||||
medium, K_medium
|
||||
module, K_module
|
||||
@@ -110,6 +115,7 @@ weak0, K_weak0
|
||||
weak1, K_weak1
|
||||
while, K_while
|
||||
wire, K_wire
|
||||
wone, K_wone
|
||||
wor, K_wor
|
||||
xnor, K_xnor
|
||||
xor, K_xor
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: getinstance.c,v 1.4 2003/05/18 00:16:35 steve Exp $"
|
||||
#ident "$Id: getinstance.c,v 1.5 2005/09/20 18:34:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <veriuser.h>
|
||||
@@ -28,11 +28,14 @@
|
||||
*/
|
||||
PLI_BYTE8* tf_getinstance(void)
|
||||
{
|
||||
return (char *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
|
||||
return (PLI_BYTE8 *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: getinstance.c,v $
|
||||
* Revision 1.5 2005/09/20 18:34:01 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
* Revision 1.4 2003/05/18 00:16:35 steve
|
||||
* Add PLI_TRACE tracing of PLI1 modules.
|
||||
*
|
||||
|
||||
+5
-2
@@ -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.13 2005/03/22 15:53:48 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.13 2005/03/22 15:53:48 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,6 +1,6 @@
|
||||
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-2004 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2005 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -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.92 2005/07/14 23:38:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -81,7 +81,13 @@ const char*basedir = ".";
|
||||
|
||||
const char*target = "null";
|
||||
|
||||
/*
|
||||
* These are the language support control flags. These support which
|
||||
* language features (the generation) to support. The generation_flag
|
||||
* is a major moce, and the gn_* flags control specifc sub-features.
|
||||
*/
|
||||
generation_t generation_flag = GN_DEFAULT;
|
||||
bool gn_cadence_types_flag = true;
|
||||
|
||||
map<string,const char*> flags;
|
||||
char*vpi_module_list = 0;
|
||||
@@ -112,6 +118,7 @@ bool error_implicit = false;
|
||||
bool debug_scopes = false;
|
||||
bool debug_eval_tree = false;
|
||||
bool debug_elaborate = false;
|
||||
bool debug_synth2 = false;
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
*/
|
||||
@@ -137,7 +144,9 @@ extern void synth(Design*des);
|
||||
extern void synth2(Design*des);
|
||||
extern void syn_rules(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
#ifdef WITH_T_XNF
|
||||
extern void xnfio(Design*des);
|
||||
#endif
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
@@ -149,7 +158,9 @@ static struct net_func_map {
|
||||
{ "synth", &synth },
|
||||
{ "synth2", &synth2 },
|
||||
{ "syn-rules", &syn_rules },
|
||||
#ifdef WITH_T_XNF
|
||||
{ "xnfio", &xnfio },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -181,8 +192,8 @@ static void process_generation_flag(const char*gen)
|
||||
else if (strcmp(gen,"2") == 0)
|
||||
generation_flag = GN_VER2001;
|
||||
|
||||
else if (strcmp(gen,"3.0") == 0)
|
||||
generation_flag = GN_SYSVER30;
|
||||
else if (strcmp(gen,"2x") == 0)
|
||||
generation_flag = GN_VER2001X;
|
||||
|
||||
else
|
||||
generation_flag = GN_DEFAULT;
|
||||
@@ -314,6 +325,9 @@ 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,"synth2") == 0) {
|
||||
debug_synth2 = true;
|
||||
cerr << "debug: Enable synth2 debug" << endl;
|
||||
} else {
|
||||
}
|
||||
|
||||
@@ -540,8 +554,8 @@ int main(int argc, char*argv[])
|
||||
case GN_VER2001:
|
||||
cout << "IEEE1364-2001";
|
||||
break;
|
||||
case GN_SYSVER30:
|
||||
cout << "SystemVerilog 3.0";
|
||||
case GN_VER2001X:
|
||||
cout << "IEEE1364-2001+Extensions";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -697,12 +711,18 @@ int main(int argc, char*argv[])
|
||||
cout << "CODE GENERATION -t "<<target<< endl;
|
||||
}
|
||||
|
||||
bool emit_rc;
|
||||
int emit_rc;
|
||||
emit_rc = emit(des, target);
|
||||
if (!emit_rc) {
|
||||
cerr << "error: Code generation had errors." << endl;
|
||||
if (emit_rc > 0) {
|
||||
cerr << "error: Code generation had "
|
||||
<< emit_rc << " errors."
|
||||
<< endl;
|
||||
return 1;
|
||||
}
|
||||
if (emit_rc < 0) {
|
||||
cerr << "error: Code generator failure: " << emit_rc << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
@@ -744,6 +764,26 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.92 2005/07/14 23:38:43 steve
|
||||
* Display as version 0.9.devel
|
||||
*
|
||||
* Revision 1.91 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.90 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
*
|
||||
* Revision 1.89 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.88 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.87 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.86 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+59
-66
@@ -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.21 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -39,30 +39,20 @@ unsigned count_lval_width(const NetAssign_*idx)
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), mem_(0), var_(0), bmux_(0)
|
||||
: sig_(s), mem_(0), bmux_(0), base_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = sig_->pin_count();
|
||||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
: sig_(0), mem_(s), var_(0), bmux_(0)
|
||||
: sig_(0), mem_(s), bmux_(0), base_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetVariable*s)
|
||||
: sig_(0), mem_(0), var_(s), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = 0;
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
{
|
||||
if (sig_) {
|
||||
@@ -91,6 +81,11 @@ const NetExpr* NetAssign_::bmux() const
|
||||
return bmux_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::get_base() const
|
||||
{
|
||||
return base_;
|
||||
}
|
||||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
if (mem_) return lwid_;
|
||||
@@ -119,27 +114,10 @@ NetMemory* NetAssign_::mem() const
|
||||
return mem_;
|
||||
}
|
||||
|
||||
NetVariable* NetAssign_::var() const
|
||||
void NetAssign_::set_part(NetExpr*base, unsigned wid)
|
||||
{
|
||||
return var_;
|
||||
}
|
||||
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
{
|
||||
loff_ = lo;
|
||||
lwid_ = lw;
|
||||
if (sig_) {
|
||||
assert(sig_->pin_count() >= (lo + lw));
|
||||
} else {
|
||||
assert(mem_);
|
||||
assert(lwid_ == mem_->width());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetAssign_::get_loff() const
|
||||
{
|
||||
return loff_;
|
||||
base_ = base;
|
||||
lwid_ = wid;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,8 +237,55 @@ NetAssignNB::~NetAssignNB()
|
||||
{
|
||||
}
|
||||
|
||||
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetAssign_*l)
|
||||
: NetAssignBase(l, 0)
|
||||
{
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
}
|
||||
|
||||
NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetAssign_*l)
|
||||
: NetAssignBase(l, 0)
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.21 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/08/28 15:08:31 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
*
|
||||
@@ -270,37 +295,5 @@ NetAssignNB::~NetAssignNB()
|
||||
* Revision 1.16 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.15 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.14 2002/08/04 18:28:15 steve
|
||||
* Do not use hierarchical names of memories to
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
*
|
||||
* Revision 1.13 2002/07/02 03:02:57 steve
|
||||
* Change the signal to a net when assignments go away.
|
||||
*
|
||||
* Revision 1.12 2002/06/08 23:42:46 steve
|
||||
* Add NetRamDq synthsesis from memory l-values.
|
||||
*
|
||||
* Revision 1.11 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.10 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.
|
||||
*
|
||||
* Revision 1.9 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*/
|
||||
|
||||
|
||||
+13
-68
@@ -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.48 2005/11/27 05:56:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -173,71 +173,6 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
|
||||
return find_scope(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a parameter from within a specified context. If the name is
|
||||
* not here, keep looking up until I run out of up to look at. The
|
||||
* method works by scanning scopes, starting with the passed scope and
|
||||
* working up towards the root, looking for the named parameter. The
|
||||
* name in this case can be hierarchical, so there is an inner loop to
|
||||
* follow the scopes of the name down to to key.
|
||||
*
|
||||
* The expression value of the parameter is returned as the result,
|
||||
* and the scope that contains the parameter is returned in the out
|
||||
* argument found_in.
|
||||
*/
|
||||
const NetExpr* Design::find_parameter(NetScope*scope,
|
||||
const hname_t&path,
|
||||
NetScope*&found_in) const
|
||||
{
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
unsigned hidx = 0;
|
||||
|
||||
NetScope*cur = scope;
|
||||
while (path.peek_name(hidx+1)) {
|
||||
cur = cur->child(path.peek_name(hidx));
|
||||
if (cur == 0)
|
||||
break;
|
||||
hidx += 1;
|
||||
}
|
||||
|
||||
if (cur == 0)
|
||||
continue;
|
||||
|
||||
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx))) {
|
||||
found_in = cur;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetExpr* Design::find_parameter(const NetScope*scope,
|
||||
const hname_t&path) const
|
||||
{
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
unsigned hidx = 0;
|
||||
|
||||
const NetScope*cur = scope;
|
||||
while (path.peek_name(hidx+1)) {
|
||||
cur = cur->child(path.peek_name(hidx));
|
||||
if (cur == 0)
|
||||
break;
|
||||
hidx += 1;
|
||||
}
|
||||
|
||||
if (cur == 0)
|
||||
continue;
|
||||
|
||||
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx)))
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This method runs through the scope, noticing the defparam
|
||||
* statements that were collected during the elaborate_scope pass and
|
||||
@@ -390,7 +325,7 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
assert(expr);
|
||||
|
||||
switch (expr->expr_type()) {
|
||||
case NetExpr::ET_REAL:
|
||||
case IVL_VT_REAL:
|
||||
if (! dynamic_cast<const NetECReal*>(expr)) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
@@ -401,7 +336,8 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
}
|
||||
break;
|
||||
|
||||
case NetExpr::ET_VECTOR:
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
if (! dynamic_cast<const NetEConst*>(expr)) {
|
||||
|
||||
// Try to evaluate the expression.
|
||||
@@ -618,6 +554,15 @@ void Design::delete_process(NetProcTop*top)
|
||||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.48 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.47 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.46 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.45 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+52
-33
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_expr.cc,v 1.23 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: net_expr.cc,v 1.26 2005/11/26 00:35:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,9 +25,12 @@
|
||||
# include "compiler.h"
|
||||
# include <iostream>
|
||||
|
||||
NetExpr::TYPE NetExpr::expr_type() const
|
||||
/*
|
||||
* the grand default data type is a logic vector.
|
||||
*/
|
||||
ivl_variable_type_t NetExpr::expr_type() const
|
||||
{
|
||||
return ET_VECTOR;
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -96,15 +99,15 @@ NetEBAdd* NetEBAdd::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEBAdd::expr_type() const
|
||||
ivl_variable_type_t NetEBAdd::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -161,6 +164,21 @@ bool NetEBComp::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBComp::expr_type() const
|
||||
{
|
||||
// Case compare always returns BOOL
|
||||
if (op() == 'E' || op() == 'N')
|
||||
return IVL_VT_BOOL;
|
||||
|
||||
if (left()->expr_type() == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
if (right()->expr_type() == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
return IVL_VT_BOOL;
|
||||
}
|
||||
|
||||
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
@@ -183,15 +201,15 @@ NetEBDiv* NetEBDiv::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEBDiv::expr_type() const
|
||||
ivl_variable_type_t NetEBDiv::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
@@ -219,15 +237,15 @@ NetEBMult* NetEBMult::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEBMult::expr_type() const
|
||||
ivl_variable_type_t NetEBMult::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return ET_VECTOR;
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
|
||||
@@ -372,9 +390,9 @@ NetECReal* NetECReal::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetECReal::expr_type() const
|
||||
ivl_variable_type_t NetECReal::expr_type() const
|
||||
{
|
||||
return ET_REAL;
|
||||
return IVL_VT_REAL;
|
||||
}
|
||||
|
||||
NetECRealParam::NetECRealParam(NetScope*s, perm_string n, const verireal&v)
|
||||
@@ -450,15 +468,7 @@ bool NetESelect::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetESelect::set_width(unsigned w)
|
||||
{
|
||||
if (expr_width() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
NetESFunc::NetESFunc(const char*n, NetExpr::TYPE t,
|
||||
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
|
||||
unsigned width, unsigned np)
|
||||
: name_(0), type_(t)
|
||||
{
|
||||
@@ -509,13 +519,22 @@ NetExpr* NetESFunc::parm(unsigned idx)
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetESFunc::expr_type() const
|
||||
ivl_variable_type_t NetESFunc::expr_type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_expr.cc,v $
|
||||
* Revision 1.26 2005/11/26 00:35:43 steve
|
||||
* More precise about r-value width of constants.
|
||||
*
|
||||
* Revision 1.25 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.24 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.23 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+6
-102
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_force.cc,v 1.12 2004/02/18 17:11:56 steve Exp $"
|
||||
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -33,110 +33,14 @@
|
||||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* Construct the procedural continuous assignment statement. This is a
|
||||
* bit different from a normal assignment because the the lval is only
|
||||
* intermittently connected. The deassign in particular disconnects
|
||||
* the signals when they are not being assigned anymore. Because of
|
||||
* this, there is no other reference to the lval to make it stay put
|
||||
* so we increment the eref.
|
||||
*
|
||||
* XXXX I'm not sure this is the right way. Perhaps I should create
|
||||
* output pins to connect to the netlist? But that would cause the
|
||||
* link ring to grow, and that is not quite correct either. Hmm...
|
||||
*/
|
||||
NetCAssign::NetCAssign(NetScope*s, perm_string n, NetNet*l)
|
||||
: NetNode(s, n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet* NetCAssign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
const Link& NetCAssign::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet*NetDeassign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetForce::NetForce(NetScope*s, perm_string n, NetNet*l)
|
||||
: NetNode(s, n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const Link& NetForce::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
const NetNet* NetForce::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
/* Put myself into a release list that the net is
|
||||
keeping. This is so that the NetNet can detach itself if
|
||||
and when it is deleted by the optimizer. */
|
||||
release_next_ = lval_->release_list_;
|
||||
lval_->release_list_ = this;
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
assert(lval_ == 0);
|
||||
}
|
||||
|
||||
const NetNet*NetRelease::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_force.cc,v $
|
||||
* Revision 1.13 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.12 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+20
-67
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_func.cc,v 1.6 2004/05/31 23:34:37 steve Exp $"
|
||||
#ident "$Id: net_func.cc,v 1.7 2005/03/18 02:56:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,42 +26,25 @@
|
||||
# include "PExpr.h"
|
||||
# include <iostream>
|
||||
|
||||
static unsigned count_def_pins(const NetFuncDef*def)
|
||||
{
|
||||
assert(def->return_sig());
|
||||
|
||||
unsigned sum = def->return_sig()->pin_count();
|
||||
for (unsigned idx = 0 ; idx < def->port_count() ; idx += 1)
|
||||
sum += def->port(idx)->pin_count();
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* To make a NetUserFunc device, make as many pins as there are ports
|
||||
* in the function. Get the port count from the function definition,
|
||||
* which accounts for all the inputs, plus one for the phantom output
|
||||
* that is the result.
|
||||
*/
|
||||
NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
|
||||
: NetNode(s, n, count_def_pins(d->func_def())),
|
||||
: NetNode(s, n, d->func_def()->port_count()+1),
|
||||
def_(d)
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(def_->basename(), 0);
|
||||
|
||||
unsigned port_wid = port_width(0);
|
||||
for (unsigned idx = 0 ; idx < port_wid ; idx += 1) {
|
||||
pin(idx).set_dir(Link::OUTPUT);
|
||||
pin(idx).set_name(def_->basename(), idx);
|
||||
}
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
unsigned pin_base = port_wid;
|
||||
for (unsigned idx = 1 ; idx < port_count() ; idx += 1) {
|
||||
|
||||
const NetNet*port_sig = def->port(idx-1);
|
||||
unsigned bits = port_width(idx);
|
||||
for (unsigned bit = 0; bit < bits; bit += 1) {
|
||||
pin(pin_base+bit).set_dir(Link::INPUT);
|
||||
pin(pin_base+bit).set_name(port_sig->name(), bit);
|
||||
pin(pin_base+bit).drive0(Link::HIGHZ);
|
||||
pin(pin_base+bit).drive1(Link::HIGHZ);
|
||||
}
|
||||
|
||||
pin_base += bits;
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +52,6 @@ NetUserFunc::~NetUserFunc()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetUserFunc::port_count() const
|
||||
{
|
||||
return def_->func_def()->port_count() + 1;
|
||||
}
|
||||
|
||||
unsigned NetUserFunc::port_width(unsigned port) const
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
@@ -82,44 +60,16 @@ unsigned NetUserFunc::port_width(unsigned port) const
|
||||
if (port == 0) {
|
||||
const NetNet*sig = def->return_sig();
|
||||
assert(sig);
|
||||
return sig->pin_count();
|
||||
return sig->vector_width();
|
||||
}
|
||||
|
||||
port -= 1;
|
||||
assert(port < def->port_count());
|
||||
const NetNet*port_sig = def->port(port);
|
||||
|
||||
return port_sig->pin_count();
|
||||
return port_sig->vector_width();
|
||||
}
|
||||
|
||||
Link& NetUserFunc::port_pin(unsigned port, unsigned idx)
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
unsigned pin_base = 0;
|
||||
const NetNet*port_sig;
|
||||
|
||||
if (port == 0)
|
||||
return pin(idx);
|
||||
|
||||
port_sig = def->return_sig();
|
||||
pin_base += port_sig->pin_count();
|
||||
port -= 1;
|
||||
|
||||
assert(port < def->port_count());
|
||||
|
||||
for (unsigned port_idx = 0 ; port_idx < port ; port_idx += 1) {
|
||||
port_sig = def->port(port_idx);
|
||||
pin_base += port_sig->pin_count();
|
||||
}
|
||||
|
||||
port_sig = def->port(port);
|
||||
assert(idx < port_sig->pin_count());
|
||||
assert((pin_base+idx) < pin_count());
|
||||
|
||||
return pin(pin_base+idx);
|
||||
}
|
||||
|
||||
|
||||
const NetScope* NetUserFunc::def() const
|
||||
{
|
||||
return def_;
|
||||
@@ -164,6 +114,9 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
||||
|
||||
/*
|
||||
* $Log: net_func.cc,v $
|
||||
* Revision 1.7 2005/03/18 02:56:03 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
* Revision 1.6 2004/05/31 23:34:37 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
||||
+53
-12
@@ -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.19 2006/02/02 02:43:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -58,7 +58,10 @@ void connect(Nexus*l, Link&r)
|
||||
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
|
||||
connect(l.nexus_, r);
|
||||
}
|
||||
|
||||
Link::Link()
|
||||
@@ -313,6 +316,30 @@ void* Nexus::t_cookie(void*val)const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned Nexus::vector_width() const
|
||||
{
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj());
|
||||
if (sig == 0)
|
||||
continue;
|
||||
|
||||
return sig->vector_width();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* Nexus::pick_any_net()
|
||||
{
|
||||
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
NetNet*sig = dynamic_cast<NetNet*>(cur->get_obj());
|
||||
if (sig != 0)
|
||||
return sig;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* Nexus::name() const
|
||||
{
|
||||
if (name_)
|
||||
@@ -364,7 +391,7 @@ const char* Nexus::name() const
|
||||
}
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << sig->name();
|
||||
tmp << sig->scope()->name() << "." << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
|
||||
@@ -407,13 +434,14 @@ void NexusSet::add(Nexus*that)
|
||||
}
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr < nitems_) && (items_[ptr] == that))
|
||||
if (ptr < nitems_) {
|
||||
assert(items_[ptr] == that);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ptr == nitems_);
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1)
|
||||
items_[idx] = items_[idx-1];
|
||||
|
||||
items_[ptr] = that;
|
||||
nitems_ += 1;
|
||||
}
|
||||
@@ -430,7 +458,7 @@ void NexusSet::rem(Nexus*that)
|
||||
return;
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr >= nitems_) || (items_[ptr] != that))
|
||||
if (ptr >= nitems_)
|
||||
return;
|
||||
|
||||
if (nitems_ == 1) {
|
||||
@@ -462,10 +490,8 @@ Nexus* NexusSet::operator[] (unsigned idx) const
|
||||
unsigned NexusSet::bsearch_(Nexus*that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
if (items_[idx] < that)
|
||||
continue;
|
||||
|
||||
return idx;
|
||||
if (items_[idx] == that)
|
||||
return idx;
|
||||
}
|
||||
|
||||
return nitems_;
|
||||
@@ -499,6 +525,21 @@ bool NexusSet::intersect(const NexusSet&that) const
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.19 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.18 2005/09/25 23:40:11 steve
|
||||
* Simplify NexusSet set handling.
|
||||
*
|
||||
* Revision 1.17 2005/06/13 23:22:37 steve
|
||||
* Fix compile errors.
|
||||
*
|
||||
* Revision 1.16 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.15 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.14 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+32
-35
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_modulo.cc,v 1.7 2004/02/18 17:11:56 steve Exp $"
|
||||
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -30,25 +30,22 @@
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
|
||||
|
||||
/*
|
||||
* 0 -- Result
|
||||
* 1 -- DataA
|
||||
* 2 -- DataB
|
||||
*/
|
||||
NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(s, n, wr+wa+wb),
|
||||
: NetNode(s, n, 3),
|
||||
width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
unsigned p = 0;
|
||||
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::OUTPUT);
|
||||
pin(p).set_name(perm_string::literal("Result"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::INPUT);
|
||||
pin(p).set_name(perm_string::literal("DataA"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::INPUT);
|
||||
pin(p).set_name(perm_string::literal("DataB"), idx);
|
||||
}
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
}
|
||||
|
||||
NetModulo::~NetModulo()
|
||||
@@ -70,44 +67,44 @@ unsigned NetModulo::width_b() const
|
||||
return width_b_;
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_Result(unsigned idx)
|
||||
Link& NetModulo::pin_Result()
|
||||
{
|
||||
assert(idx < width_r_);
|
||||
return pin(idx);
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_Result(unsigned idx) const
|
||||
const Link& NetModulo::pin_Result() const
|
||||
{
|
||||
assert(idx < width_r_);
|
||||
return pin(idx);
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_DataA(unsigned idx)
|
||||
Link& NetModulo::pin_DataA()
|
||||
{
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+width_r_);
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_DataA(unsigned idx) const
|
||||
const Link& NetModulo::pin_DataA() const
|
||||
{
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+width_r_);
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_DataB(unsigned idx)
|
||||
Link& NetModulo::pin_DataB()
|
||||
{
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+width_r_+width_a_);
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_DataB(unsigned idx) const
|
||||
const Link& NetModulo::pin_DataB() const
|
||||
{
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+width_r_+width_a_);
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_modulo.cc,v $
|
||||
* Revision 1.9 2005/09/15 22:54:47 steve
|
||||
* Fix bug configuring NetModulo pins.
|
||||
*
|
||||
* Revision 1.8 2005/03/12 06:43:35 steve
|
||||
* Update support for LPM_MOD.
|
||||
*
|
||||
* Revision 1.7 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+9
-15
@@ -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.14 2005/07/11 16:56:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -54,15 +54,6 @@ NexusSet* NetEBinary::nex_input()
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEBitSel::nex_input()
|
||||
{
|
||||
NexusSet*result = sig_->nex_input();
|
||||
NexusSet*tmp = idx_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEConcat::nex_input()
|
||||
{
|
||||
NexusSet*result = parms_[0]->nex_input();
|
||||
@@ -177,11 +168,6 @@ NexusSet* NetEUnary::nex_input()
|
||||
return expr_->nex_input();
|
||||
}
|
||||
|
||||
NexusSet* NetEVariable::nex_input()
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetAssign_::nex_input()
|
||||
{
|
||||
if (bmux_ == 0)
|
||||
@@ -398,6 +384,14 @@ NexusSet* NetWhile::nex_input()
|
||||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.14 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.13 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.12 2004/09/04 04:24:15 steve
|
||||
* PR1026: assignment statements can have sensitivities in the l-values.
|
||||
*
|
||||
|
||||
+5
-5
@@ -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.12 2005/02/14 04:58:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -47,10 +47,7 @@ void NetAssignBase::nex_output(NexusSet&out)
|
||||
{
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
if (NetNet*lsig = cur->sig()) {
|
||||
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
|
||||
unsigned off = cur->get_loff() + idx;
|
||||
out.add(lsig->pin(off).nexus());
|
||||
}
|
||||
out.add(lsig->pin(0).nexus());
|
||||
} else {
|
||||
/* Quoting from netlist.h comments for class NetMemory:
|
||||
* "This is not a node because memory objects can only be
|
||||
@@ -122,6 +119,9 @@ void NetWhile::nex_output(NexusSet&out)
|
||||
|
||||
/*
|
||||
* $Log: net_nex_output.cc,v $
|
||||
* Revision 1.12 2005/02/14 04:58:50 steve
|
||||
* l-value input may be a vector.
|
||||
*
|
||||
* Revision 1.11 2004/09/16 03:17:33 steve
|
||||
* net_output handles l-value concatenations.
|
||||
*
|
||||
|
||||
+18
-22
@@ -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.35 2005/11/27 05:56:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -41,7 +41,6 @@ NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
|
||||
memories_ = 0;
|
||||
signals_ = 0;
|
||||
events_ = 0;
|
||||
vars_ = 0;
|
||||
lcounter_ = 0;
|
||||
|
||||
if (up) {
|
||||
@@ -133,17 +132,25 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
|
||||
* perm_string::literal method to fake the compiler into doing the
|
||||
* compare without actually creating a perm_string.
|
||||
*/
|
||||
const NetExpr* NetScope::get_parameter(const char* key) const
|
||||
const NetExpr* NetScope::get_parameter(const char* key,
|
||||
const NetExpr*&msb,
|
||||
const NetExpr*&lsb) const
|
||||
{
|
||||
map<perm_string,param_expr_t>::const_iterator idx;
|
||||
|
||||
idx = parameters.find(perm_string::literal(key));
|
||||
if (idx != parameters.end())
|
||||
if (idx != parameters.end()) {
|
||||
msb = (*idx).second.msb;
|
||||
lsb = (*idx).second.lsb;
|
||||
return (*idx).second.expr;
|
||||
}
|
||||
|
||||
idx = localparams.find(perm_string::literal(key));
|
||||
if (idx != localparams.end())
|
||||
if (idx != localparams.end()) {
|
||||
msb = (*idx).second.msb;
|
||||
lsb = (*idx).second.lsb;
|
||||
return (*idx).second.expr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -283,15 +290,6 @@ NetEvent* NetScope::find_event(const char*name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetVariable* NetScope::find_variable(const char*name)
|
||||
{
|
||||
for (NetVariable*cur = vars_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->basename(), name) == 0)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_signal(NetNet*net)
|
||||
{
|
||||
if (signals_ == 0) {
|
||||
@@ -404,14 +402,6 @@ NetMemory* NetScope::find_memory(const string&key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NetScope::add_variable(NetVariable*var)
|
||||
{
|
||||
assert(var->scope_ == 0);
|
||||
var->scope_ = this;
|
||||
var->snext_ = vars_;
|
||||
vars_ = var;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a child scope by name. The name is the simple
|
||||
* name of the child, no hierarchy is searched.
|
||||
@@ -467,6 +457,12 @@ string NetScope::local_hsymbol()
|
||||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.35 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.34 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.33 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_variable.cc,v 1.3 2004/02/19 07:06:57 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "netlist.h"
|
||||
|
||||
NetVariable::NetVariable(perm_string name)
|
||||
{
|
||||
name_ = name;
|
||||
scope_ = 0;
|
||||
snext_ = 0;
|
||||
}
|
||||
|
||||
NetVariable::~NetVariable()
|
||||
{
|
||||
}
|
||||
|
||||
perm_string NetVariable::basename() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
NetScope* NetVariable::scope()
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
const NetScope* NetVariable::scope() const
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
NetEVariable::NetEVariable(NetVariable*v)
|
||||
: var_(v)
|
||||
{
|
||||
}
|
||||
|
||||
NetEVariable::~NetEVariable()
|
||||
{
|
||||
}
|
||||
|
||||
NetExpr::TYPE NetEVariable::expr_type() const
|
||||
{
|
||||
return NetExpr::ET_REAL;
|
||||
}
|
||||
|
||||
const NetVariable* NetEVariable::variable() const
|
||||
{
|
||||
return var_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_variable.cc,v $
|
||||
* Revision 1.3 2004/02/19 07:06:57 steve
|
||||
* LPM, logic and Variables have perm_string names.
|
||||
*
|
||||
* Revision 1.2 2003/03/06 00:28:42 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.1 2003/01/28 16:23:27 steve
|
||||
* Add missing net_variable.cc to CVS.
|
||||
*
|
||||
*/
|
||||
+553
-529
File diff suppressed because it is too large
Load Diff
+65
-2
@@ -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.11 2005/04/08 04:50:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -30,7 +30,7 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
||||
{
|
||||
if (val == 0)
|
||||
return sig;
|
||||
|
||||
#if 0
|
||||
NetScope*scope = sig->scope();
|
||||
unsigned long abs_val = (val >= 0)? val : (-val);
|
||||
unsigned width = sig->pin_count();
|
||||
@@ -70,8 +70,58 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
||||
des->add_node(val_c);
|
||||
|
||||
return res;
|
||||
#else
|
||||
cerr << sig->get_line() << ": XXXX: Forgot how to implement add_to_net" << endl;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a signed constant to an existing expression. Generate a new
|
||||
* NetEBAdd node that has the input expression and an expression made
|
||||
* from the constant value.
|
||||
*/
|
||||
NetExpr* make_add_expr(NetExpr*expr, long val)
|
||||
{
|
||||
if (val == 0)
|
||||
return expr;
|
||||
|
||||
// If the value to be added is <0, then instead generate a
|
||||
// SUBTRACT node and turn the value positive.
|
||||
char add_op = '+';
|
||||
if (val < 0) {
|
||||
add_op = '-';
|
||||
val = -val;
|
||||
}
|
||||
|
||||
verinum val_v (val);
|
||||
val_v.has_sign(true);
|
||||
|
||||
if (expr->has_width()) {
|
||||
val_v = verinum(val_v, expr->expr_width());
|
||||
}
|
||||
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
val_c->set_line(*expr);
|
||||
|
||||
NetEBAdd*res = new NetEBAdd(add_op, expr, val_c);
|
||||
res->set_line(*expr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||
{
|
||||
verinum val_v (val, expr->expr_width());
|
||||
val_v.has_sign(true);
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
val_c->set_line(*expr);
|
||||
|
||||
NetEBAdd*res = new NetEBAdd('-', val_c, expr);
|
||||
res->set_line(*expr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
{
|
||||
@@ -90,6 +140,19 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.11 2005/04/08 04:50:31 steve
|
||||
* Don not give to make_add express an unwanted width.
|
||||
*
|
||||
* Revision 1.10 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.9 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.8 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
||||
@@ -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.24 2005/11/27 05:56:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -33,13 +33,30 @@
|
||||
* If the symbol was not found, return 0. The output arguments
|
||||
* get 0 except for the pointer to the object that represents
|
||||
* the located symbol.
|
||||
*
|
||||
* The ex1 and ex2 output arguments are extended results. If the
|
||||
* symbol is a parameter (par!=0) then ex1 is the msb expression and
|
||||
* ex2 is the lsb expression for the range. If there is no range, then
|
||||
* these values are set to 0.
|
||||
*/
|
||||
extern NetScope* symbol_search(Design*des, NetScope*start, hname_t path,
|
||||
extern NetScope* symbol_search(const Design*des,
|
||||
NetScope*start, hname_t path,
|
||||
NetNet*&net, /* net/reg */
|
||||
NetMemory*&mem, /* memory */
|
||||
NetVariable*&var, /* real/realtime */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */);
|
||||
NetEvent*&eve, /* named event */
|
||||
const NetExpr*&ex1, const NetExpr*&ex2);
|
||||
|
||||
inline NetScope* symbol_search(const Design*des,
|
||||
NetScope*start, const hname_t&path,
|
||||
NetNet*&net, /* net/reg */
|
||||
NetMemory*&mem, /* memory */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */)
|
||||
{
|
||||
const NetExpr*ex1, *ex2;
|
||||
return symbol_search(des, start, path, net, mem, par, eve, ex1, ex2);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function transforms an expression by padding the high bits
|
||||
@@ -50,6 +67,15 @@ extern NetScope* symbol_search(Design*des, NetScope*start, hname_t path,
|
||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
|
||||
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* This function transforms an expression by cropping the high bits
|
||||
* off with a part select. The result has the width w passed in. This
|
||||
* function does not pad, use pad_to_width if padding is desired.
|
||||
*/
|
||||
extern NetNet*crop_to_width(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* This function takes as input a NetNet signal and adds a constant
|
||||
* value to it. If the val is 0, then simply return sig. Otherwise,
|
||||
@@ -57,6 +83,23 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
||||
*/
|
||||
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
|
||||
/*
|
||||
* These functions make various sorts of expressions, given operands
|
||||
* of certain type. The order of the operands is preserved in cases
|
||||
* where order matters.
|
||||
*
|
||||
* make_add_expr
|
||||
* Make a NetEBAdd expresion with <expr> the first argument and
|
||||
* <val> the second. This may get turned into a subtract if <val> is
|
||||
* less then zero. If val is exactly zero, then return <expr> as is.
|
||||
*
|
||||
* make_sub_expr
|
||||
* Make a NetEBAdd(subtract) node that subtracts the given
|
||||
* expression from the integer value.
|
||||
*/
|
||||
extern NetExpr*make_add_expr(NetExpr*expr, long val);
|
||||
extern NetExpr*make_sub_expr(long val, NetExpr*expr);
|
||||
|
||||
/*
|
||||
* 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 +118,23 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
|
||||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.24 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.23 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.22 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.21 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.20 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.19 2004/03/07 20:04:11 steve
|
||||
* MOre thorough use of elab_and_eval function.
|
||||
*
|
||||
|
||||
+92
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2005 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: pad_to_width.cc,v 1.15 2004/02/18 17:11:57 steve Exp $"
|
||||
#ident "$Id: pad_to_width.cc,v 1.20 2005/12/22 15:43:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -56,47 +56,116 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* Do it the hard way, with a concatenation. */
|
||||
verinum pad(verinum::V0, wid - expr->expr_width());
|
||||
NetEConst*co = new NetEConst(pad);
|
||||
co->set_line(*expr);
|
||||
NetEConcat*cc = new NetEConcat(2);
|
||||
cc->set_line(*expr);
|
||||
cc->set(0, co);
|
||||
cc->set(1, expr);
|
||||
cc->set_width(wid);
|
||||
expr = cc;
|
||||
|
||||
return expr;
|
||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||
tmp->set_line(*expr);
|
||||
tmp->cast_signed(expr->has_sign());
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pad a NetNet to the desired vector width by concatenating a
|
||||
* NetConst of constant zeros. Use a NetConcat node to do the
|
||||
* concatenation.
|
||||
*/
|
||||
NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
|
||||
{
|
||||
NetScope*scope = net->scope();
|
||||
const string path = scope->name();
|
||||
assert(scope);
|
||||
|
||||
if (net->pin_count() >= wid)
|
||||
if (net->vector_width() >= wid)
|
||||
return net;
|
||||
|
||||
verinum pad(verinum::V0, wid - net->pin_count());
|
||||
// Make the NetConcat and connect the input net to the lsb input.
|
||||
NetConcat*cc = new NetConcat(scope, scope->local_symbol(), wid, 2);
|
||||
des->add_node(cc);
|
||||
connect(cc->pin(1), net->pin(0));
|
||||
|
||||
// Make a NetConst of the desired width and connect in to the
|
||||
// lsb input of the NetConcat.
|
||||
verinum pad(verinum::V0, wid - net->vector_width());
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(), pad);
|
||||
des->add_node(con);
|
||||
connect(cc->pin(2), con->pin(0));
|
||||
|
||||
// Make a NetNet for the NetConst to NetConcat link.
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, wid - net->vector_width());
|
||||
tmp->data_type( net->data_type() );
|
||||
tmp->local_flag(true);
|
||||
connect(cc->pin(2), tmp->pin(0));
|
||||
|
||||
// Create a NetNet of the output width and connect it to the
|
||||
// NetConcat node output pin.
|
||||
tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, wid);
|
||||
tmp->data_type( net->data_type() );
|
||||
tmp->local_flag(true);
|
||||
connect(cc->pin(0), tmp->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet*pad_to_width_signed(Design*des, NetNet*net, unsigned wid)
|
||||
{
|
||||
NetScope*scope = net->scope();
|
||||
|
||||
if (net->vector_width() >= wid)
|
||||
return net;
|
||||
|
||||
NetSignExtend*se
|
||||
= new NetSignExtend(scope, scope->local_symbol(), wid);
|
||||
se->set_line(*net);
|
||||
des->add_node(se);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, wid);
|
||||
tmp->set_line(*net);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(net->data_type());
|
||||
tmp->set_signed(true);
|
||||
|
||||
connect(tmp->pin(0), se->pin(0));
|
||||
connect(se->pin(1), net->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet*crop_to_width(Design*des, NetNet*net, unsigned wid)
|
||||
{
|
||||
NetScope*scope = net->scope();
|
||||
|
||||
if (net->vector_width() <= wid)
|
||||
return net;
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(net, 0, wid, NetPartSelect::VP);
|
||||
des->add_node(ps);
|
||||
ps->set_line(*net);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, wid);
|
||||
tmp->data_type(net->data_type());
|
||||
tmp->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
connect(tmp->pin(idx), net->pin(idx));
|
||||
for (unsigned idx = net->pin_count() ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), con->pin(idx-net->pin_count()));
|
||||
tmp->set_line(*tmp);
|
||||
connect(ps->pin(0), tmp->pin(0));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: pad_to_width.cc,v $
|
||||
* Revision 1.20 2005/12/22 15:43:47 steve
|
||||
* pad_to_width handles signed expressions.
|
||||
*
|
||||
* Revision 1.19 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.18 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.17 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.16 2005/01/12 03:17:37 steve
|
||||
* Properly pad vector widths in pgassign.
|
||||
*
|
||||
* Revision 1.15 2004/02/18 17:11:57 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
@@ -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.135 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,9 +26,9 @@
|
||||
# include "pform.h"
|
||||
# include "parse_misc.h"
|
||||
# include "parse_api.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include "PUdp.h"
|
||||
# include "PGenerate.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <assert.h>
|
||||
@@ -45,7 +45,17 @@ string vl_file = "";
|
||||
|
||||
extern int VLparse();
|
||||
|
||||
/* This tracks the current module being processed. There can only be
|
||||
exactly one module currently being parsed, since verilog does not
|
||||
allow nested module definitions. */
|
||||
static Module*pform_cur_module = 0;
|
||||
/* increment this for generate schemes within a module, and set it
|
||||
to zero when a new module starts. */
|
||||
static unsigned scope_generate_counter = 1;
|
||||
|
||||
/* This tracks the current generate scheme being processed. This is
|
||||
always within a module. */
|
||||
static PGenerate*pform_cur_generate = 0;
|
||||
|
||||
static NetNet::Type pform_default_nettype = NetNet::WIRE;
|
||||
|
||||
@@ -64,10 +74,13 @@ static unsigned pform_timescale_line = 0;
|
||||
* of scope. As I enter a scope, the push function is called, and as I
|
||||
* leave a scope the pop function is called. Entering tasks, functions
|
||||
* and named blocks causes scope to be pushed and popped. The module
|
||||
* name is not included it this scope stack.
|
||||
* name is not included in this scope stack.
|
||||
*
|
||||
* The hier_name function, therefore, returns the name path of a
|
||||
* function relative the current function.
|
||||
* The hier_name function, therefore, converts the name to the scope
|
||||
* of the module currently in progress.
|
||||
*
|
||||
* The scope stack does not include any scope created by a generate
|
||||
* scheme.
|
||||
*/
|
||||
|
||||
static hname_t scope_stack;
|
||||
@@ -91,6 +104,18 @@ static hname_t hier_name(const char*tail)
|
||||
return name;
|
||||
}
|
||||
|
||||
static PWire*get_wire_in_module(const hname_t&name)
|
||||
{
|
||||
/* Note that if we are processing a generate, then the
|
||||
scope depth will be empty because generate schemes
|
||||
cannot be within sub-scopes. Only directly in
|
||||
modules. */
|
||||
if (pform_cur_generate)
|
||||
return pform_cur_generate->get_wire(name);
|
||||
|
||||
return pform_cur_module->get_wire(name);
|
||||
}
|
||||
|
||||
void pform_set_default_nettype(NetNet::Type type,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
@@ -217,6 +242,10 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||
pform_cur_module->set_file(file);
|
||||
pform_cur_module->set_lineno(lineno);
|
||||
|
||||
/* The generate scheme numbering starts with *1*, not
|
||||
zero. That's just the way it is, thanks to the standard. */
|
||||
scope_generate_counter = 1;
|
||||
|
||||
if (warn_timescale && pform_timescale_file
|
||||
&& (strcmp(pform_timescale_file,file) != 0)) {
|
||||
|
||||
@@ -293,6 +322,58 @@ void pform_endmodule(const char*name)
|
||||
pform_cur_module = 0;
|
||||
}
|
||||
|
||||
void pform_genvars(list<perm_string>*names)
|
||||
{
|
||||
list<perm_string>::const_iterator cur;
|
||||
for (cur = names->begin(); cur != names->end() ; *cur++) {
|
||||
pform_cur_module->genvars.push_back( *cur );
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
void pform_start_generate_for(const struct vlltype&li,
|
||||
char*ident1, PExpr*init,
|
||||
PExpr*test,
|
||||
char*ident2, PExpr*next)
|
||||
{
|
||||
PGenerate*gen = new PGenerate(scope_generate_counter++);
|
||||
|
||||
gen->set_file(li.text);
|
||||
gen->set_lineno(li.first_line);
|
||||
|
||||
// For now, assume that generates do not nest.
|
||||
assert(pform_cur_generate == 0);
|
||||
pform_cur_generate = gen;
|
||||
|
||||
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
|
||||
|
||||
pform_cur_generate->loop_index = lex_strings.make(ident1);
|
||||
pform_cur_generate->loop_init = init;
|
||||
pform_cur_generate->loop_test = test;
|
||||
pform_cur_generate->loop_step = next;
|
||||
|
||||
delete[]ident1;
|
||||
delete[]ident2;
|
||||
}
|
||||
|
||||
void pform_generate_block_name(char*name)
|
||||
{
|
||||
assert(pform_cur_generate != 0);
|
||||
assert(pform_cur_generate->scope_name == 0);
|
||||
pform_cur_generate->scope_name = lex_strings.make(name);
|
||||
delete[]name;
|
||||
}
|
||||
|
||||
void pform_endgenerate()
|
||||
{
|
||||
assert(pform_cur_generate != 0);
|
||||
assert(pform_cur_module);
|
||||
|
||||
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
|
||||
pform_cur_generate = 0;
|
||||
}
|
||||
|
||||
bool pform_expression_is_constant(const PExpr*ex)
|
||||
{
|
||||
return ex->is_constant(pform_cur_module);
|
||||
@@ -614,7 +695,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
/* Make the PWire for the output port. */
|
||||
pins[0] = new PWire(hier_name(out_name),
|
||||
synchronous_flag? NetNet::REG : NetNet::WIRE,
|
||||
NetNet::POUTPUT);
|
||||
NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC);
|
||||
pins[0]->set_file(file);
|
||||
pins[0]->set_lineno(lineno);
|
||||
|
||||
@@ -627,7 +709,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
assert(idx < pins.count());
|
||||
pins[idx] = new PWire(hier_name(*cur),
|
||||
NetNet::WIRE,
|
||||
NetNet::PINPUT);
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
pins[idx]->set_file(file);
|
||||
pins[idx]->set_lineno(lineno);
|
||||
}
|
||||
@@ -691,10 +774,10 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
*/
|
||||
static void pform_set_net_range(const char* name,
|
||||
const svector<PExpr*>*range,
|
||||
bool signed_flag)
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
{
|
||||
|
||||
PWire*cur = pform_cur_module->get_wire(hier_name(name));
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
if (cur == 0) {
|
||||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
@@ -712,11 +795,15 @@ static void pform_set_net_range(const char* name,
|
||||
cur->set_range((*range)[0], (*range)[1]);
|
||||
}
|
||||
cur->set_signed(signed_flag);
|
||||
|
||||
if (dt != IVL_VT_NO_TYPE)
|
||||
cur->set_data_type(dt);
|
||||
}
|
||||
|
||||
void pform_set_net_range(list<perm_string>*names,
|
||||
svector<PExpr*>*range,
|
||||
bool signed_flag)
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
{
|
||||
assert((range == 0) || (range->count() == 2));
|
||||
|
||||
@@ -724,7 +811,7 @@ void pform_set_net_range(list<perm_string>*names,
|
||||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_net_range(txt, range, signed_flag);
|
||||
pform_set_net_range(txt, range, signed_flag, dt);
|
||||
}
|
||||
|
||||
delete names;
|
||||
@@ -755,26 +842,6 @@ void pform_make_events(list<perm_string>*names, const char*fn, unsigned ln)
|
||||
delete names;
|
||||
}
|
||||
|
||||
static void pform_make_datum(perm_string name, const char*fn, unsigned ln)
|
||||
{
|
||||
hname_t hname = hier_name(name);
|
||||
PData*datum = new PData(hname);
|
||||
datum->set_file(fn);
|
||||
datum->set_lineno(ln);
|
||||
pform_cur_module->datum[hname] = datum;
|
||||
}
|
||||
|
||||
void pform_make_reals(list<perm_string>*names, const char*fn, unsigned ln)
|
||||
{
|
||||
list<perm_string>::iterator cur;
|
||||
for (cur = names->begin() ; cur != names->end() ; cur++) {
|
||||
perm_string txt = *cur;
|
||||
pform_make_datum(txt, fn, ln);
|
||||
}
|
||||
|
||||
delete names;
|
||||
}
|
||||
|
||||
/*
|
||||
* pform_makegates is called when a list of gates (with the same type)
|
||||
* are ready to be instantiated. The function runs through the list of
|
||||
@@ -810,7 +877,10 @@ void pform_makegate(PGBuiltin::Type type,
|
||||
cur->set_file(info.file);
|
||||
cur->set_lineno(info.lineno);
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_gate(cur);
|
||||
else
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
void pform_makegates(PGBuiltin::Type type,
|
||||
@@ -868,7 +938,10 @@ static void pform_make_modgate(perm_string type,
|
||||
cur->set_parameters(overrides->by_order);
|
||||
}
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_gate(cur);
|
||||
else
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
static void pform_make_modgate(perm_string type,
|
||||
@@ -952,7 +1025,7 @@ void pform_make_modgates(perm_string type,
|
||||
delete gates;
|
||||
}
|
||||
|
||||
PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
static PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
svector<PExpr*>*del,
|
||||
struct str_pair_t str)
|
||||
{
|
||||
@@ -970,7 +1043,11 @@ PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
cur->strength0(str.str0);
|
||||
cur->strength1(str.str1);
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_gate(cur);
|
||||
else
|
||||
pform_cur_module->add_gate(cur);
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
@@ -1060,7 +1137,7 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
}
|
||||
|
||||
|
||||
cur = new PWire(name, type, port_type);
|
||||
cur = new PWire(name, type, port_type, IVL_VT_LOGIC);
|
||||
cur->set_file(li.text);
|
||||
cur->set_lineno(li.first_line);
|
||||
|
||||
@@ -1103,12 +1180,22 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
* do check to see if the name has already been declared, as this
|
||||
* function is called for every declaration.
|
||||
*/
|
||||
|
||||
/*
|
||||
* this is the basic form of pform_makwire. This takes a single simple
|
||||
* name, port type, net type, data type, and attributes, and creates
|
||||
* the variable/net. Other forms of pform_makewire ultimately call
|
||||
* this one to create the wire and stash it.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li, const char*nm,
|
||||
NetNet::Type type, NetNet::PortType pt,
|
||||
ivl_variable_type_t dt,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
hname_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
|
||||
if (cur) {
|
||||
if ((cur->get_wire_type() != NetNet::IMPLICIT)
|
||||
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
|
||||
@@ -1132,7 +1219,7 @@ void pform_makewire(const vlltype&li, const char*nm,
|
||||
return;
|
||||
}
|
||||
|
||||
cur = new PWire(name, type, pt);
|
||||
cur = new PWire(name, type, pt, dt);
|
||||
cur->set_file(li.text);
|
||||
cur->set_lineno(li.first_line);
|
||||
|
||||
@@ -1143,23 +1230,32 @@ void pform_makewire(const vlltype&li, const char*nm,
|
||||
}
|
||||
}
|
||||
|
||||
pform_cur_module->add_wire(cur);
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_wire(cur);
|
||||
else
|
||||
pform_cur_module->add_wire(cur);
|
||||
}
|
||||
|
||||
/*
|
||||
* This form takes a list of names and some type information, and
|
||||
* generates a bunch of variables/nets. We hse the basic
|
||||
* pform_makewire above.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
list<perm_string>*names,
|
||||
NetNet::Type type,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_makewire(li, txt, type, pt, attr);
|
||||
pform_set_net_range(txt, range, signed_flag);
|
||||
pform_makewire(li, txt, type, pt, dt, attr);
|
||||
pform_set_net_range(txt, range, signed_flag, dt);
|
||||
}
|
||||
|
||||
delete names;
|
||||
@@ -1167,13 +1263,17 @@ void pform_makewire(const vlltype&li,
|
||||
delete range;
|
||||
}
|
||||
|
||||
/*
|
||||
* This form makes nets with delays and continuous assignments.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*delay,
|
||||
str_pair_t str,
|
||||
net_decl_assign_t*decls,
|
||||
NetNet::Type type)
|
||||
NetNet::Type type,
|
||||
ivl_variable_type_t dt)
|
||||
{
|
||||
net_decl_assign_t*first = decls->next;
|
||||
decls->next = 0;
|
||||
@@ -1181,16 +1281,19 @@ void pform_makewire(const vlltype&li,
|
||||
while (first) {
|
||||
net_decl_assign_t*next = first->next;
|
||||
|
||||
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, 0);
|
||||
pform_set_net_range(first->name, range, signed_flag);
|
||||
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, dt, 0);
|
||||
pform_set_net_range(first->name, range, signed_flag, dt);
|
||||
|
||||
hname_t name = hier_name(first->name);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
if (cur != 0) {
|
||||
PEIdent*lval = new PEIdent(hname_t(first->name));
|
||||
lval->set_file(li.text);
|
||||
lval->set_lineno(li.first_line);
|
||||
pform_make_pgassign(lval, first->expr, delay, str);
|
||||
PGAssign*ass = pform_make_pgassign(lval, first->expr,
|
||||
delay, str);
|
||||
ass->set_file(li.text);
|
||||
ass->set_lineno(li.first_line);
|
||||
}
|
||||
|
||||
free(first->name);
|
||||
@@ -1205,7 +1308,7 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
hname_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT);
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_LOGIC);
|
||||
cur->set_file(file);
|
||||
cur->set_lineno(lineno);
|
||||
pform_cur_module->add_wire(cur);
|
||||
@@ -1274,6 +1377,7 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
* no output or inout ports.
|
||||
*/
|
||||
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
list<perm_string>*names,
|
||||
@@ -1294,7 +1398,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt);
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
curw->set_file(file);
|
||||
curw->set_lineno(lineno);
|
||||
pform_cur_module->add_wire(curw);
|
||||
@@ -1452,7 +1556,7 @@ void pform_set_port_type(const struct vlltype&li,
|
||||
perm_string txt = *cur;
|
||||
pform_set_port_type(txt, pt, li.text, li.first_line);
|
||||
if (range)
|
||||
pform_set_net_range(txt, range, signed_flag);
|
||||
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE);
|
||||
}
|
||||
|
||||
delete names;
|
||||
@@ -1465,12 +1569,15 @@ static void pform_set_reg_integer(const char*nm)
|
||||
hname_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::INTEGER, NetNet::NOT_A_PORT);
|
||||
cur = new PWire(name, NetNet::INTEGER,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_LOGIC);
|
||||
cur->set_signed(true);
|
||||
pform_cur_module->add_wire(cur);
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::INTEGER);
|
||||
assert(rc);
|
||||
cur->set_data_type(IVL_VT_LOGIC);
|
||||
cur->set_signed(true);
|
||||
}
|
||||
assert(cur);
|
||||
@@ -1496,11 +1603,13 @@ static void pform_set_reg_time(const char*nm)
|
||||
hname_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT);
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
pform_cur_module->add_wire(cur);
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::REG);
|
||||
assert(rc);
|
||||
rc = cur->set_data_type(IVL_VT_LOGIC);
|
||||
assert(rc);
|
||||
}
|
||||
assert(cur);
|
||||
|
||||
@@ -1530,7 +1639,8 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
perm_string txt = *cur;
|
||||
PWire*pp = new PWire(hname_t(txt),
|
||||
NetNet::IMPLICIT,
|
||||
NetNet::PINPUT);
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
(*out)[idx] = pp;
|
||||
idx += 1;
|
||||
}
|
||||
@@ -1597,6 +1707,26 @@ int pform_parse(const char*path, FILE*file)
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.135 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.134 2006/03/30 05:22:34 steve
|
||||
* task/function ports can have types.
|
||||
*
|
||||
* Revision 1.133 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.132 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.131 2005/05/06 00:25:13 steve
|
||||
* Handle synthesis of concatenation expressions.
|
||||
*
|
||||
* Revision 1.130 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.129 2004/10/04 01:10:55 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: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.86 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -77,7 +77,8 @@ PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max);
|
||||
/* This is information about port name information for named port
|
||||
connections. */
|
||||
|
||||
typedef struct named<PExpr*> named_pexpr_t;
|
||||
//typedef struct named<PExpr*> named_pexpr_t;
|
||||
typedef named<PExpr*> named_pexpr_t;
|
||||
|
||||
struct parmvalue_t {
|
||||
svector<PExpr*>*by_order;
|
||||
@@ -166,28 +167,52 @@ extern void pform_pop_scope();
|
||||
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
||||
const char*file, unsigned loneno);
|
||||
|
||||
/*
|
||||
* This function takes the list of names as new genvars to declare in
|
||||
* the current module scope.
|
||||
*/
|
||||
extern void pform_genvars(list<perm_string>*names);
|
||||
|
||||
extern void pform_start_generate_for(const struct vlltype&li,
|
||||
char*ident1,
|
||||
PExpr*init,
|
||||
PExpr*test,
|
||||
char*ident2,
|
||||
PExpr*next);
|
||||
extern void pform_generate_block_name(char*name);
|
||||
extern void pform_endgenerate();
|
||||
|
||||
|
||||
/*
|
||||
* The makewire functions announce to the pform code new wires. These
|
||||
* go into a module that is currently opened.
|
||||
*/
|
||||
extern void pform_makewire(const struct vlltype&li, const char*name,
|
||||
NetNet::Type type, NetNet::PortType pt,
|
||||
NetNet::Type type,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t,
|
||||
svector<named_pexpr_t*>*attr);
|
||||
|
||||
/* This form handles simple declarations */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
list<perm_string>*names,
|
||||
NetNet::Type type,
|
||||
NetNet::PortType,
|
||||
ivl_variable_type_t,
|
||||
svector<named_pexpr_t*>*attr);
|
||||
|
||||
/* This form handles assignment declarations. */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*delay,
|
||||
str_pair_t str,
|
||||
net_decl_assign_t*assign_list,
|
||||
NetNet::Type type);
|
||||
NetNet::Type type,
|
||||
ivl_variable_type_t);
|
||||
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
const char*name, PExpr*expr);
|
||||
|
||||
@@ -203,7 +228,9 @@ extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
extern void pform_set_net_range(list<perm_string>*names,
|
||||
svector<PExpr*>*, bool);
|
||||
svector<PExpr*>*,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t);
|
||||
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
@@ -270,9 +297,6 @@ extern void pform_make_modgates(perm_string type,
|
||||
svector<lgate>*gates);
|
||||
|
||||
/* Make a continuous assignment node, with optional bit- or part- select. */
|
||||
extern PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
svector<PExpr*>*delays,
|
||||
struct str_pair_t str);
|
||||
extern void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
svector<PExpr*>*del,
|
||||
struct str_pair_t str,
|
||||
@@ -281,6 +305,7 @@ extern void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
/* Given a port type and a list of names, make a list of wires that
|
||||
can be used as task port information. */
|
||||
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
list<perm_string>*names,
|
||||
@@ -298,6 +323,23 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.86 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.85 2006/03/30 05:22:34 steve
|
||||
* task/function ports can have types.
|
||||
*
|
||||
* Revision 1.84 2005/12/05 21:21:18 steve
|
||||
* Fixes for stubborn compilers.
|
||||
*
|
||||
* Revision 1.83 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.82 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.81 2004/08/26 04:02:04 steve
|
||||
* Add support for localparam ranges.
|
||||
*
|
||||
|
||||
+104
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2004 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: pform_dump.cc,v 1.88 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.92 2006/04/10 00:37:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,8 +29,8 @@
|
||||
* module in question.
|
||||
*/
|
||||
# include "pform.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include "PGenerate.h"
|
||||
# include <iostream>
|
||||
# include <iomanip>
|
||||
# include <typeinfo>
|
||||
@@ -146,8 +146,19 @@ void PEIdent::dump(ostream&out) const
|
||||
out << path_;
|
||||
if (msb_) {
|
||||
out << "[" << *msb_;
|
||||
if (lsb_) {
|
||||
if (lsb_) switch (sel_) {
|
||||
case SEL_IDX_UP:
|
||||
out << "+:" << *lsb_;
|
||||
break;
|
||||
case SEL_IDX_DO:
|
||||
out << "-:" << *lsb_;
|
||||
break;
|
||||
case SEL_PART:
|
||||
out << ":" << *lsb_;
|
||||
break;
|
||||
default:
|
||||
out << ":?:" << *lsb_;
|
||||
break;
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
@@ -201,27 +212,29 @@ void PEBinary::dump(ostream&out) const
|
||||
}
|
||||
|
||||
|
||||
void PWire::dump(ostream&out) const
|
||||
void PWire::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << " " << type_;
|
||||
out << setw(ind) << "" << type_;
|
||||
|
||||
switch (port_type_) {
|
||||
case NetNet::PIMPLICIT:
|
||||
out << " (implicit input)";
|
||||
out << " implicit input";
|
||||
break;
|
||||
case NetNet::PINPUT:
|
||||
out << " (input)";
|
||||
out << " input";
|
||||
break;
|
||||
case NetNet::POUTPUT:
|
||||
out << " (output)";
|
||||
out << " output";
|
||||
break;
|
||||
case NetNet::PINOUT:
|
||||
out << " (input output)";
|
||||
out << " inout";
|
||||
break;
|
||||
case NetNet::NOT_A_PORT:
|
||||
break;
|
||||
}
|
||||
|
||||
out << " " << data_type_;
|
||||
|
||||
if (signed_) {
|
||||
out << " signed";
|
||||
}
|
||||
@@ -291,9 +304,9 @@ void PGate::dump_delays(ostream&out) const
|
||||
delay_.dump_delays(out);
|
||||
}
|
||||
|
||||
void PGate::dump(ostream&out) const
|
||||
void PGate::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << " " << typeid(*this).name() << " ";
|
||||
out << setw(ind) << "" << typeid(*this).name() << " ";
|
||||
delay_.dump_delays(out);
|
||||
out << " " << get_name() << "(";
|
||||
dump_pins(out);
|
||||
@@ -301,45 +314,47 @@ void PGate::dump(ostream&out) const
|
||||
|
||||
}
|
||||
|
||||
void PGAssign::dump(ostream&out) const
|
||||
void PGAssign::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << " assign (" << strength0() << "0 " << strength1() << "1) ";
|
||||
out << setw(ind) << "";
|
||||
out << "assign (" << strength0() << "0 " << strength1() << "1) ";
|
||||
dump_delays(out);
|
||||
out << " " << *pin(0) << " = " << *pin(1) << ";" << endl;
|
||||
}
|
||||
|
||||
void PGBuiltin::dump(ostream&out) const
|
||||
void PGBuiltin::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "";
|
||||
switch (type()) {
|
||||
case PGBuiltin::BUFIF0:
|
||||
out << " bufif0 ";
|
||||
out << "bufif0 ";
|
||||
break;
|
||||
case PGBuiltin::BUFIF1:
|
||||
out << " bufif1 ";
|
||||
out << "bufif1 ";
|
||||
break;
|
||||
case PGBuiltin::NOTIF0:
|
||||
out << " bufif0 ";
|
||||
out << "bufif0 ";
|
||||
break;
|
||||
case PGBuiltin::NOTIF1:
|
||||
out << " bufif1 ";
|
||||
out << "bufif1 ";
|
||||
break;
|
||||
case PGBuiltin::NAND:
|
||||
out << " nand ";
|
||||
out << "nand ";
|
||||
break;
|
||||
case PGBuiltin::NMOS:
|
||||
out << " nmos ";
|
||||
out << "nmos ";
|
||||
break;
|
||||
case PGBuiltin::RNMOS:
|
||||
out << " rnmos ";
|
||||
out << "rnmos ";
|
||||
break;
|
||||
case PGBuiltin::RPMOS:
|
||||
out << " rpmos ";
|
||||
out << "rpmos ";
|
||||
break;
|
||||
case PGBuiltin::PMOS:
|
||||
out << " pmos ";
|
||||
out << "pmos ";
|
||||
break;
|
||||
default:
|
||||
out << " builtin gate ";
|
||||
out << "builtin gate ";
|
||||
}
|
||||
|
||||
out << "(" << strength0() << "0 " << strength1() << "1) ";
|
||||
@@ -355,9 +370,9 @@ void PGBuiltin::dump(ostream&out) const
|
||||
out << ");" << endl;
|
||||
}
|
||||
|
||||
void PGModule::dump(ostream&out) const
|
||||
void PGModule::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << " " << type_ << " ";
|
||||
out << setw(ind) << "" << type_ << " ";
|
||||
|
||||
// If parameters are overridden by order, dump them.
|
||||
if (overrides_) {
|
||||
@@ -719,6 +734,44 @@ void PProcess::dump(ostream&out, unsigned ind) const
|
||||
statement_->dump(out, ind+2);
|
||||
}
|
||||
|
||||
void PGenerate::dump(ostream&out) const
|
||||
{
|
||||
out << " generate(" << id_number << ")";
|
||||
|
||||
switch (scheme_type) {
|
||||
case GS_NONE:
|
||||
break;
|
||||
case GS_LOOP:
|
||||
out << " for ("
|
||||
<< loop_index
|
||||
<< "=" << *loop_init
|
||||
<< "; " << *loop_test
|
||||
<< "; " << loop_index
|
||||
<< "=" << *loop_step << ")";
|
||||
break;
|
||||
case GS_CONDIT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (scope_name)
|
||||
out << " : " << scope_name;
|
||||
|
||||
out << endl;
|
||||
|
||||
for (map<hname_t,PWire*>::const_iterator idx = wires.begin()
|
||||
; idx != wires.end() ; idx++) {
|
||||
|
||||
(*idx).second->dump(out, 6);
|
||||
}
|
||||
|
||||
for (list<PGate*>::const_iterator idx = gates.begin()
|
||||
; idx != gates.end() ; idx++) {
|
||||
(*idx)->dump(out, 6);
|
||||
}
|
||||
|
||||
out << " endgenerate" << endl;
|
||||
}
|
||||
|
||||
void Module::dump(ostream&out) const
|
||||
{
|
||||
if (attributes.begin() != attributes.end()) {
|
||||
@@ -784,6 +837,18 @@ void Module::dump(ostream&out) const
|
||||
out << "/* ERROR */;" << endl;
|
||||
}
|
||||
|
||||
typedef list<perm_string>::const_iterator genvar_iter_t;
|
||||
for (genvar_iter_t cur = genvars.begin()
|
||||
; cur != genvars.end() ; cur++) {
|
||||
out << " genvar " << (*cur) << ";" << endl;
|
||||
}
|
||||
|
||||
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
|
||||
for (genscheme_iter_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur++) {
|
||||
(*cur)->dump(out);
|
||||
}
|
||||
|
||||
typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t;
|
||||
for (specparm_iter_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; cur ++) {
|
||||
@@ -807,13 +872,6 @@ void Module::dump(ostream&out) const
|
||||
<< ev->get_line() << endl;
|
||||
}
|
||||
|
||||
for (map<hname_t,PData*>::const_iterator cur = datum.begin()
|
||||
; cur != datum.end() ; cur ++ ) {
|
||||
PData*tmp = (*cur).second;
|
||||
out << " real " << tmp->name() << "; // "
|
||||
<< tmp->get_line() << endl;
|
||||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
@@ -909,6 +967,18 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.92 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.91 2005/10/04 04:09:26 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
* Revision 1.90 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.89 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.88 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+61
-37
@@ -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.37 2005/11/26 00:35:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -36,7 +36,7 @@
|
||||
# include <typeinfo>
|
||||
|
||||
|
||||
bool NetExpr::set_width(unsigned w)
|
||||
bool NetExpr::set_width(unsigned w, bool)
|
||||
{
|
||||
cerr << get_line() << ": internal warning: "
|
||||
<<typeid(*this).name() << ": set_width(unsigned) "
|
||||
@@ -45,7 +45,7 @@ bool NetExpr::set_width(unsigned w)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetEBinary::set_width(unsigned w)
|
||||
bool NetEBinary::set_width(unsigned w, bool)
|
||||
{
|
||||
bool flag = true;
|
||||
switch (op_) {
|
||||
@@ -80,7 +80,7 @@ bool NetEBinary::set_width(unsigned w)
|
||||
* The bitwise logical operators have operands the same size as the
|
||||
* result. Anything else is a mess.
|
||||
*/
|
||||
bool NetEBAdd::set_width(unsigned w)
|
||||
bool NetEBAdd::set_width(unsigned w, bool)
|
||||
{
|
||||
|
||||
unsigned wid = w;
|
||||
@@ -113,7 +113,7 @@ bool NetEBAdd::set_width(unsigned w)
|
||||
* result. Anything else is a mess. I first try to get the operands to
|
||||
* shrink to the desired size. I then expand operands that are too small.
|
||||
*/
|
||||
bool NetEBBits::set_width(unsigned w)
|
||||
bool NetEBBits::set_width(unsigned w, bool)
|
||||
{
|
||||
/* First, give the operands a chance to adjust themselves to
|
||||
the requested width. */
|
||||
@@ -153,7 +153,7 @@ bool NetEBBits::set_width(unsigned w)
|
||||
* their own natural width, but the comparison operator result has a
|
||||
* fixed width of 1.
|
||||
*/
|
||||
bool NetEBComp::set_width(unsigned w)
|
||||
bool NetEBComp::set_width(unsigned w, bool)
|
||||
{
|
||||
return (w == 1);
|
||||
}
|
||||
@@ -162,12 +162,12 @@ bool NetEBComp::set_width(unsigned w)
|
||||
* There is nothing we can do to the operands of a division to make it
|
||||
* confirm to the requested width. Force the context to pad or truncate.
|
||||
*/
|
||||
bool NetEBDiv::set_width(unsigned w)
|
||||
bool NetEBDiv::set_width(unsigned w, bool)
|
||||
{
|
||||
return w == expr_width();
|
||||
}
|
||||
|
||||
bool NetEBLogic::set_width(unsigned w)
|
||||
bool NetEBLogic::set_width(unsigned w, bool)
|
||||
{
|
||||
bool flag;
|
||||
flag = left_->set_width(right_->expr_width());
|
||||
@@ -180,7 +180,7 @@ bool NetEBLogic::set_width(unsigned w)
|
||||
* There is nothing we can do to the operands of a multiply to make it
|
||||
* confirm to the requested width. Force the context to pad or truncate.
|
||||
*/
|
||||
bool NetEBMult::set_width(unsigned w)
|
||||
bool NetEBMult::set_width(unsigned w, bool)
|
||||
{
|
||||
return w == expr_width();
|
||||
}
|
||||
@@ -190,7 +190,7 @@ bool NetEBMult::set_width(unsigned w)
|
||||
* natural width. The width of the operator result is the width of the
|
||||
* left operand, the value that is to be shifted.
|
||||
*/
|
||||
bool NetEBShift::set_width(unsigned w)
|
||||
bool NetEBShift::set_width(unsigned w, bool)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
@@ -228,7 +228,7 @@ bool NetEBShift::set_width(unsigned w)
|
||||
* matter because the null expression is indication of an error and
|
||||
* the compiler will not go beyond elaboration.
|
||||
*/
|
||||
bool NetEConcat::set_width(unsigned w)
|
||||
bool NetEConcat::set_width(unsigned w, bool)
|
||||
{
|
||||
unsigned sum = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
@@ -241,7 +241,7 @@ bool NetEConcat::set_width(unsigned w)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEConst::set_width(unsigned w)
|
||||
bool NetEConst::set_width(unsigned w, bool last_chance)
|
||||
{
|
||||
if (w == value_.len()) {
|
||||
expr_width(w);
|
||||
@@ -289,17 +289,19 @@ bool NetEConst::set_width(unsigned w)
|
||||
? value_[value_.len() - 1]
|
||||
: verinum::V0;
|
||||
|
||||
// Don't reduce a number too small to hold all the
|
||||
// significant bits.
|
||||
for (unsigned idx = w ; idx < value_.len() ; idx += 1)
|
||||
if (value_[idx] != pad_bit)
|
||||
use_w = idx+1;
|
||||
if (! last_chance) {
|
||||
// Don't reduce a number too small to hold all the
|
||||
// significant bits.
|
||||
for (unsigned idx = w ; idx < value_.len() ; idx += 1)
|
||||
if (value_[idx] != pad_bit)
|
||||
use_w = idx+1;
|
||||
|
||||
// Correct for the special case of signed value. We
|
||||
// cannot have the result change sign on us.
|
||||
if (value_.has_sign() && (use_w < value_.len())
|
||||
&& (value_[use_w-1] != pad_bit))
|
||||
use_w += 1;
|
||||
// Correct for the special case of signed value. We
|
||||
// cannot have the result change sign on us.
|
||||
if (value_.has_sign() && (use_w < value_.len())
|
||||
&& (value_[use_w-1] != pad_bit))
|
||||
use_w += 1;
|
||||
}
|
||||
|
||||
verinum tmp (verinum::V0, use_w, has_width());
|
||||
for (unsigned idx = 0 ; idx < use_w ; idx += 1)
|
||||
@@ -312,18 +314,27 @@ bool NetEConst::set_width(unsigned w)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parameter vectors cannot be resized because they refer to a common
|
||||
* value.
|
||||
*/
|
||||
bool NetEConstParam::set_width(unsigned w, bool)
|
||||
{
|
||||
return w == expr_width();
|
||||
}
|
||||
|
||||
/*
|
||||
* Real constants can have whatever width the environment wants,
|
||||
* because it isn't really a vector. The environment will convert this
|
||||
* to a vector at the right time.
|
||||
*/
|
||||
bool NetECReal::set_width(unsigned w)
|
||||
bool NetECReal::set_width(unsigned w, bool)
|
||||
{
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEMemory::set_width(unsigned w)
|
||||
bool NetEMemory::set_width(unsigned w, bool)
|
||||
{
|
||||
if (w != mem_->width())
|
||||
return false;
|
||||
@@ -332,12 +343,20 @@ bool NetEMemory::set_width(unsigned w)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEParam::set_width(unsigned)
|
||||
bool NetEParam::set_width(unsigned, bool)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetESFunc::set_width(unsigned w)
|
||||
bool NetESelect::set_width(unsigned w, bool)
|
||||
{
|
||||
if (expr_width() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetESFunc::set_width(unsigned w, bool)
|
||||
{
|
||||
return w == expr_width();
|
||||
}
|
||||
@@ -346,7 +365,7 @@ bool NetESFunc::set_width(unsigned w)
|
||||
* The signal should automatically pad with zeros to get to the desired
|
||||
* width. Do not allow signal bits to be truncated, however.
|
||||
*/
|
||||
bool NetESignal::set_width(unsigned w)
|
||||
bool NetESignal::set_width(unsigned w, bool)
|
||||
{
|
||||
if (w != bit_count())
|
||||
return false;
|
||||
@@ -354,13 +373,7 @@ bool NetESignal::set_width(unsigned w)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEBitSel::set_width(unsigned w)
|
||||
{
|
||||
if (w != 1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetETernary::set_width(unsigned w)
|
||||
bool NetETernary::set_width(unsigned w, bool)
|
||||
{
|
||||
bool flag = true;
|
||||
flag = flag && true_val_->set_width(w);
|
||||
@@ -374,13 +387,13 @@ bool NetETernary::set_width(unsigned w)
|
||||
* width. What I really need to do is note the width of the output
|
||||
* parameter of the function definition and take that into account.
|
||||
*/
|
||||
bool NetEUFunc::set_width(unsigned wid)
|
||||
bool NetEUFunc::set_width(unsigned wid, bool)
|
||||
{
|
||||
expr_width(wid);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEUnary::set_width(unsigned w)
|
||||
bool NetEUnary::set_width(unsigned w, bool)
|
||||
{
|
||||
bool flag = true;
|
||||
switch (op_) {
|
||||
@@ -403,7 +416,7 @@ bool NetEUnary::set_width(unsigned w)
|
||||
* Unary reduction operators allow its operand to have any width. The
|
||||
* result is defined to be 1.
|
||||
*/
|
||||
bool NetEUReduce::set_width(unsigned w)
|
||||
bool NetEUReduce::set_width(unsigned w, bool)
|
||||
{
|
||||
return w == 1;
|
||||
}
|
||||
@@ -411,6 +424,17 @@ bool NetEUReduce::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.37 2005/11/26 00:35:44 steve
|
||||
* More precise about r-value width of constants.
|
||||
*
|
||||
* Revision 1.36 2005/05/17 20:56:55 steve
|
||||
* Parameters cannot have their width changed.
|
||||
*
|
||||
* Revision 1.35 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.34 2003/08/28 04:11:19 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
|
||||
@@ -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.10 2005/06/14 19:13:43 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.10 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
* Revision 1.9 2003/07/23 02:35:44 steve
|
||||
* Inline the svector<string> constructor.
|
||||
*
|
||||
|
||||
+11
-11
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: symbol_search.cc,v 1.1 2003/09/19 03:30:05 steve Exp $"
|
||||
#ident "$Id: symbol_search.cc,v 1.3 2005/11/27 05:56:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -27,12 +27,12 @@
|
||||
/*
|
||||
* Search for the hierarchical name.
|
||||
*/
|
||||
NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
|
||||
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
||||
NetNet*&net,
|
||||
NetMemory*&mem,
|
||||
NetVariable*&var,
|
||||
const NetExpr*&par,
|
||||
NetEvent*&eve)
|
||||
NetEvent*&eve,
|
||||
const NetExpr*&ex1, const NetExpr*&ex2)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
@@ -42,7 +42,6 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
|
||||
/* Initialize output argument to cleared. */
|
||||
net = 0;
|
||||
mem = 0;
|
||||
var = 0;
|
||||
par = 0;
|
||||
eve = 0;
|
||||
|
||||
@@ -62,17 +61,12 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (var = scope->find_variable(key)) ) {
|
||||
delete key;
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (eve = scope->find_event(key)) ) {
|
||||
delete key;
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (par = scope->get_parameter(key)) ) {
|
||||
if ( (par = scope->get_parameter(key, ex1, ex2)) ) {
|
||||
delete key;
|
||||
return scope;
|
||||
}
|
||||
@@ -89,6 +83,12 @@ NetScope*symbol_search(Design*des, NetScope*scope, hname_t path,
|
||||
|
||||
/*
|
||||
* $Log: symbol_search.cc,v $
|
||||
* Revision 1.3 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.2 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.1 2003/09/19 03:30:05 steve
|
||||
* Fix name search in elab_lval.
|
||||
*
|
||||
|
||||
+7
-14
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: syn-rules.y,v 1.31 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: syn-rules.y,v 1.33 2005/04/24 23:44:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -118,11 +118,8 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
||||
// where lval is really a "reg [7:0]". In other words, part
|
||||
// selects in the l-value are handled by loff and the lwidth().
|
||||
|
||||
int loff = a->get_loff();
|
||||
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
|
||||
connect(ff->pin_Data(idx), d->bit(idx+rval_pinoffset));
|
||||
connect(ff->pin_Q(idx), a->sig()->pin(idx+loff));
|
||||
}
|
||||
connect(ff->pin_Data(), d->bit(0));
|
||||
connect(ff->pin_Q(), a->sig()->pin(0));
|
||||
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
if (ce) connect(ff->pin_Enable(), ce->pin(0));
|
||||
@@ -149,15 +146,11 @@ static void hookup_RAMDQ(NetRamDq*ram, NetESignal*d, NetNet*adr,
|
||||
|
||||
/* Connect the input Data bits of the RAM, from the r-value of
|
||||
the assignment. */
|
||||
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
|
||||
connect(ram->pin_Data(idx), d->bit(idx+rval_pinoffset));
|
||||
}
|
||||
connect(ram->pin_Data(), d->bit(rval_pinoffset));
|
||||
|
||||
/* Connect the Address pins from the addr net discovered by the
|
||||
caller. */
|
||||
for (unsigned idx = 0 ; idx < ram->awidth() ; idx += 1) {
|
||||
connect(ram->pin_Address(idx), adr->pin(idx));
|
||||
}
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
|
||||
/* Connect the input clock and the WE of the RAM. */
|
||||
assert(pclk);
|
||||
@@ -211,7 +204,7 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
|
||||
if (a->sig()) {
|
||||
// cerr << "new NetFF named " << a->name() << endl;
|
||||
NetFF*ff = new NetFF(top->scope(), a->name(),
|
||||
a->lwidth());
|
||||
a->sig()->vector_width());
|
||||
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ff);
|
||||
} else if (a->mem()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2005 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,42 +17,28 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: synth2.cc,v 1.39 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.45 2005/08/27 04:32:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
# include <assert.h>
|
||||
|
||||
static int debug_synth2=0;
|
||||
|
||||
#ifdef __FUNCTION__
|
||||
|
||||
#define DEBUG_SYNTH2_ENTRY(class) if (debug_synth2) { cerr << "Enter " << class << "::" \
|
||||
<< __FUNCTION__ << endl; dump(cerr, 4); }
|
||||
#define DEBUG_SYNTH2_EXIT(class,val) if (debug_synth2) { cerr << "Exit " << class << "::" \
|
||||
<< __FUNCTION__ << ", result " << val << endl; }
|
||||
|
||||
#else
|
||||
#define DEBUG_SYNTH2_ENTRY(class)
|
||||
#define DEBUG_SYNTH2_EXIT(class,val)
|
||||
#endif
|
||||
|
||||
bool NetProc::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
const NetBus&nex_map, NetBus&nex_out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const NetBus&nex_map, NetBus&nex_out,
|
||||
const svector<NetEvProbe*>&events)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetProc")
|
||||
|
||||
if (events.count() > 0) {
|
||||
cerr << get_line() << ": error: Events are unaccounted"
|
||||
<< " for in process synthesis." << endl;
|
||||
@@ -63,15 +49,17 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
return synth_async(des, scope, nex_map, nex_out);
|
||||
}
|
||||
|
||||
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
|
||||
#if 0
|
||||
static unsigned find_nexus_in_set(const NetBus&nset, const Nexus*nex)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
for (idx = 0 ; idx < nset->pin_count() ; idx += 1)
|
||||
if (nset->pin(idx).nexus() == nex)
|
||||
for (idx = 0 ; idx < nset.pin_count() ; idx += 1)
|
||||
if (nset.pin(idx).nexus() == nex)
|
||||
return idx;
|
||||
|
||||
return idx;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Async synthesis of assignments is done by synthesizing the rvalue
|
||||
@@ -84,36 +72,42 @@ static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
|
||||
* r-value.
|
||||
*/
|
||||
bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
const NetBus&nex_map, NetBus&nex_out)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetAssignBase")
|
||||
|
||||
NetNet*rsig = rval_->synthesize(des);
|
||||
assert(rsig);
|
||||
|
||||
NetNet*lsig = lval_->sig();
|
||||
if (!lsig) {
|
||||
cerr << get_line() << ": error: NetAssignBase::synth_async on unsupported lval ";
|
||||
cerr << get_line() << ": error: "
|
||||
<< "NetAssignBase::synth_async on unsupported lval ";
|
||||
dump_lval(cerr);
|
||||
cerr << endl;
|
||||
DEBUG_SYNTH2_EXIT("NetAssignBase",false)
|
||||
return false;
|
||||
}
|
||||
assert(lval_->more == 0);
|
||||
|
||||
if (lval_->lwidth() != nex_map->pin_count()) {
|
||||
cerr << get_line() << ": error: NetAssignBase::synth_async pin count mismatch, "
|
||||
<< lval_->lwidth() << " != " << nex_map->pin_count() << endl;
|
||||
DEBUG_SYNTH2_EXIT("NetAssignBase",false)
|
||||
if (debug_synth2) {
|
||||
cerr << get_line() << ": debug: l-value signal is "
|
||||
<< lsig->vector_width() << " bits, r-value signal is "
|
||||
<< rsig->vector_width() << " bits." << endl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* The l-value and r-value map must have the same width. */
|
||||
if (lval_->lwidth() != nex_map->vector_width()) {
|
||||
cerr << get_line() << ": error: Assignment synthesis: "
|
||||
<< "vector width mismatch, "
|
||||
<< lval_->lwidth() << " bits != "
|
||||
<< nex_map->vector_width() << " bits." << endl;
|
||||
return false;
|
||||
}
|
||||
assert(nex_map->pin_count() <= rsig->pin_count());
|
||||
#else
|
||||
/* For now, assume there is exactly one output. */
|
||||
assert(nex_out.pin_count() == 1);
|
||||
#endif
|
||||
|
||||
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
|
||||
unsigned off = lval_->get_loff()+idx;
|
||||
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
|
||||
connect(nex_out->pin(ptr), rsig->pin(idx));
|
||||
}
|
||||
connect(nex_out.pin(0), rsig->pin(0));
|
||||
|
||||
/* This lval_ represents a reg that is a WIRE in the
|
||||
synthesized results. This function signals the destructor
|
||||
@@ -122,7 +116,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
synthesis can continue to work with it as a WIRE. */
|
||||
lval_->turn_sig_to_wire_on_release();
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetAssignBase",true)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -133,191 +126,144 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
* substatements.
|
||||
*/
|
||||
bool NetBlock::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
const NetBus&nex_map, NetBus&nex_out)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetBlock")
|
||||
if (last_ == 0) {
|
||||
DEBUG_SYNTH2_EXIT("NetBlock",true)
|
||||
return true;
|
||||
}
|
||||
|
||||
const perm_string tmp1 = perm_string::literal("tmp1");
|
||||
const perm_string tmp2 = perm_string::literal("tmp2");
|
||||
|
||||
bool flag = true;
|
||||
NetProc*cur = last_;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
|
||||
/* Create a temporary nex_map for the substatement. */
|
||||
/* Create a temporary map of the output only from this
|
||||
statement. */
|
||||
NexusSet tmp_set;
|
||||
cur->nex_output(tmp_set);
|
||||
NetNet*tmp_map = new NetNet(scope, tmp1, NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
|
||||
connect(tmp_set[idx], tmp_map->pin(idx));
|
||||
NetBus tmp_map (scope, tmp_set.count());
|
||||
for (unsigned idx = 0 ; idx < tmp_set.count() ; idx += 1)
|
||||
connect(tmp_set[idx], tmp_map.pin(idx));
|
||||
|
||||
/* Create also a temporary net_out to collect the
|
||||
output. */
|
||||
NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
/* Create also a temporary NetBus to collect the
|
||||
output from the synthesis. */
|
||||
NetBus tmp_out (scope, tmp_set.count());
|
||||
|
||||
bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
flag = flag && ok_flag;
|
||||
if (ok_flag == false)
|
||||
continue;
|
||||
|
||||
/* Use the nex_map to link up the output from the
|
||||
substatement to the output of the block as a whole. */
|
||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
||||
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
|
||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
||||
}
|
||||
/* Now find the tmp_map pins in the nex_map global map,
|
||||
and use that to direct the connection to the nex_out
|
||||
output bus. Look for the nex_map pin that is linked
|
||||
to the tmp_map.pin(idx) pin, and link that to the
|
||||
tmp_out.pin(idx) output link. */
|
||||
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
||||
unsigned ptr = 0;
|
||||
while (ptr < nex_map.pin_count()
|
||||
&& ! nex_map.pin(ptr).is_linked(tmp_map.pin(idx)))
|
||||
ptr += 1;
|
||||
|
||||
delete tmp_map;
|
||||
delete tmp_out;
|
||||
assert(ptr < nex_out.pin_count());
|
||||
connect(nex_out.pin(ptr), tmp_out.pin(idx));
|
||||
}
|
||||
|
||||
} while (cur != last_);
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetBlock",flag)
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
const NetBus&nex_map, NetBus&nex_out)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetCase")
|
||||
unsigned cur;
|
||||
|
||||
/* Synthesize the select expression. */
|
||||
NetNet*esig = expr_->synthesize(des);
|
||||
|
||||
/* Scan the select vector looking for constant bits. The
|
||||
constant bits will be elided from the select input connect,
|
||||
but we still need to keep track of them. */
|
||||
unsigned sel_pins = 0;
|
||||
unsigned long sel_mask = 0;
|
||||
unsigned long sel_ref = 0;
|
||||
for (unsigned idx = 0 ; idx < esig->pin_count() ; idx += 1) {
|
||||
unsigned sel_width = esig->vector_width();
|
||||
assert(sel_width > 0);
|
||||
|
||||
if (esig->pin(idx).nexus()->drivers_constant()) {
|
||||
verinum::V bit = esig->pin(idx).nexus()->driven_value();
|
||||
if (bit == verinum::V1)
|
||||
sel_ref |= 1 << idx;
|
||||
unsigned mux_width = 0;
|
||||
for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1)
|
||||
mux_width += nex_out.pin(idx).nexus()->vector_width();
|
||||
|
||||
} else {
|
||||
sel_pins += 1;
|
||||
sel_mask |= 1 << idx;
|
||||
}
|
||||
}
|
||||
/* Collect all the statements into a map of index to
|
||||
statement. The guard expression it evaluated to be the
|
||||
index of the mux value, and the statement is bound to that
|
||||
index. */
|
||||
|
||||
/* Build a map of guard values to mux select values. This
|
||||
helps account for constant select bits that are being
|
||||
elided. */
|
||||
map<unsigned long,unsigned long>guard2sel;
|
||||
cur = 0;
|
||||
for (unsigned idx = 0 ; idx < (1U<<esig->pin_count()) ; idx += 1) {
|
||||
if ((idx & ~sel_mask) == sel_ref) {
|
||||
guard2sel[idx] = cur;
|
||||
cur += 1;
|
||||
}
|
||||
}
|
||||
assert(cur == (1U << sel_pins));
|
||||
unsigned long max_guard_value = 0;
|
||||
map<unsigned long,NetProc*>statement_map;
|
||||
NetProc*statement_default = 0;
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
nex_out->pin_count(),
|
||||
1U << sel_pins, sel_pins);
|
||||
|
||||
/* Connect the non-constant select bits to the select input of
|
||||
the mux device. */
|
||||
cur = 0;
|
||||
for (unsigned idx = 0 ; idx < esig->pin_count() ; idx += 1) {
|
||||
/* skip bits that are known to be constant. */
|
||||
if ((sel_mask & (1U << idx)) == 0)
|
||||
continue;
|
||||
|
||||
connect(mux->pin_Sel(cur), esig->pin(idx));
|
||||
cur += 1;
|
||||
}
|
||||
assert(cur == sel_pins);
|
||||
|
||||
/* Hook up the output of the mux to the mapped output pins. */
|
||||
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
|
||||
connect(nex_out->pin(idx), mux->pin_Result(idx));
|
||||
|
||||
NetProc**statement_map = new NetProc*[1 << sel_pins];
|
||||
for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1)
|
||||
statement_map[item] = 0;
|
||||
|
||||
/* Assign the input statements to MUX inputs. This involves
|
||||
calculating the guard value, passing that through the
|
||||
guard2sel map, then saving the statement in the
|
||||
statement_map. If I find a default case, then save that for
|
||||
use later. */
|
||||
NetProc*default_statement = 0;
|
||||
for (unsigned item = 0 ; item < nitems_ ; item += 1) {
|
||||
/* Skip the default case this pass. */
|
||||
if (items_[item].guard == 0) {
|
||||
default_statement = items_[item].statement;
|
||||
statement_default = items_[item].statement;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetEConst*ge = dynamic_cast<NetEConst*>(items_[item].guard);
|
||||
assert(ge);
|
||||
verinum gval = ge->value();
|
||||
unsigned sel_idx = guard2sel[gval.as_ulong()];
|
||||
|
||||
unsigned sel_idx = gval.as_ulong();
|
||||
|
||||
assert(items_[item].statement);
|
||||
statement_map[sel_idx] = items_[item].statement;
|
||||
|
||||
if (sel_idx > max_guard_value)
|
||||
max_guard_value = sel_idx;
|
||||
}
|
||||
|
||||
/* Now that statements match with mux inputs, synthesize the
|
||||
sub-statements. If I get to an input that has no statement,
|
||||
then use the default statement there. */
|
||||
NetNet*default_sig = 0;
|
||||
for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1) {
|
||||
unsigned mux_size = max_guard_value + 1;
|
||||
|
||||
/* Detect the case that this is a default input, and I
|
||||
have a precalculated default_sig. */
|
||||
if ((statement_map[item] == 0) && (default_sig != 0)) {
|
||||
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
|
||||
connect(mux->pin_Data(idx, item), default_sig->pin(idx));
|
||||
continue;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, nex_map->pin_count());
|
||||
sig->local_flag(true);
|
||||
|
||||
if (statement_map[item] == 0) {
|
||||
statement_map[item] = default_statement;
|
||||
default_statement = 0;
|
||||
default_sig = sig;
|
||||
}
|
||||
|
||||
if (statement_map[item] == 0) {
|
||||
/* Missing case and no default; this could still be
|
||||
* synthesizable with synchronous logic, but not here. */
|
||||
DEBUG_SYNTH2_EXIT("NetCase", false)
|
||||
return false;
|
||||
}
|
||||
statement_map[item]->synth_async(des, scope, nex_map, sig);
|
||||
|
||||
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
|
||||
connect(mux->pin_Data(idx, item), sig->pin(idx));
|
||||
}
|
||||
|
||||
delete[]statement_map;
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
mux_width, mux_size, sel_width);
|
||||
des->add_node(mux);
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetCase", true)
|
||||
/* The select signal is already synthesized. Simply hook it up. */
|
||||
connect(mux->pin_Sel(), esig->pin(0));
|
||||
|
||||
/* For now, assume that the output is only 1 signal. */
|
||||
assert(nex_out.pin_count() == 1);
|
||||
connect(mux->pin_Result(), nex_out.pin(0));
|
||||
|
||||
/* For now, only support logic types. */
|
||||
ivl_variable_type_t mux_data_type = IVL_VT_LOGIC;
|
||||
|
||||
/* Forgot to support default statements? */
|
||||
assert(statement_default == 0);
|
||||
|
||||
NetNet*isig;
|
||||
for (unsigned idx = 0 ; idx < mux_size ; idx += 1) {
|
||||
|
||||
NetProc*stmt = statement_map[idx];
|
||||
if (stmt == 0) {
|
||||
cerr << get_line() << ": error: case " << idx
|
||||
<< " is not accounted for in asynchronous mux." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
isig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, mux_width);
|
||||
isig->local_flag(true);
|
||||
isig->data_type(mux_data_type);
|
||||
|
||||
connect(mux->pin_Data(idx), isig->pin(0));
|
||||
|
||||
NetBus tmp (scope, 1);
|
||||
connect(tmp.pin(0), isig->pin(0));
|
||||
stmt->synth_async(des, scope, tmp, tmp);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
const NetBus&nex_map, NetBus&nex_out)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetCondit")
|
||||
#if 0
|
||||
NetNet*ssig = expr_->synthesize(des);
|
||||
assert(ssig);
|
||||
|
||||
@@ -360,50 +306,56 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
nex_out->pin_count(), 2, 1);
|
||||
nex_out->vector_width(), 2, 1);
|
||||
|
||||
connect(mux->pin_Sel(0), ssig->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Data(idx, 1), asig->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < bsig->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Data(idx, 0), bsig->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < mux->width() ; idx += 1)
|
||||
connect(nex_out->pin(idx), mux->pin_Result(idx));
|
||||
connect(mux->pin_Sel(), ssig->pin(0));
|
||||
connect(mux->pin_Data(1), asig->pin(0));
|
||||
connect(mux->pin_Data(0), bsig->pin(0));
|
||||
connect(nex_out->pin(0), mux->pin_Result());
|
||||
|
||||
des->add_node(mux);
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",true)
|
||||
return true;
|
||||
|
||||
#else
|
||||
cerr << get_line() << ": sorry: "
|
||||
<< "Forgot to implement NetCondit::synth_async" << endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NetEvWait::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
const NetBus&nex_map, NetBus&nex_out)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetEvWait")
|
||||
bool flag = statement_->synth_async(des, scope, nex_map, nex_out);
|
||||
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called when the process is shown to be
|
||||
* asynchronous. Figure out the nexus set of outputs from this
|
||||
* process, and pass that to the synth_async method for the statement
|
||||
* of the process. The statement will connect its output to the
|
||||
* nex_out set, using the nex_map as a guide. Starting from the top,
|
||||
* the nex_map is the same as the nex_map.
|
||||
*/
|
||||
bool NetProcTop::synth_async(Design*des)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetProcTop")
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
|
||||
const perm_string tmp1 = perm_string::literal("tmp");
|
||||
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));
|
||||
if (debug_synth2) {
|
||||
cerr << get_line() << ": debug: Process has "
|
||||
<< nex_set.count() << " outputs." << endl;
|
||||
}
|
||||
|
||||
bool flag = statement_->synth_async(des, scope(), nex_out, nex_out);
|
||||
NetBus nex_q (scope(), nex_set.count());
|
||||
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
|
||||
connect(nex_set[idx], nex_q.pin(idx));
|
||||
}
|
||||
|
||||
delete nex_out;
|
||||
DEBUG_SYNTH2_EXIT("NetProcTop",flag)
|
||||
bool flag = statement_->synth_async(des, scope(), nex_q, nex_q);
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -422,15 +374,14 @@ bool NetProcTop::synth_async(Design*des)
|
||||
* the statements may each infer different reset and enable signals.
|
||||
*/
|
||||
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const NetBus&nex_map, NetBus&nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetBlock")
|
||||
if (last_ == 0) {
|
||||
DEBUG_SYNTH2_EXIT("NetBlock",true)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool flag = true;
|
||||
|
||||
const perm_string tmp1 = perm_string::literal("tmp1");
|
||||
@@ -572,8 +523,14 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
taken up by the smaller NetFF devices. */
|
||||
delete ff;
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetBlock",flag)
|
||||
return flag;
|
||||
|
||||
#else
|
||||
cerr << get_line() << ": sorry: "
|
||||
<< "Forgot to implement NetBlock::synth_sync"
|
||||
<< endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -583,10 +540,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
* expression is connected to an event, or not.
|
||||
*/
|
||||
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const NetBus&nex_map, NetBus&nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetCondit")
|
||||
#if 0
|
||||
/* First try to turn the condition expression into an
|
||||
asynchronous set/reset. If the condition expression has
|
||||
inputs that are included in the sensitivity list, then it
|
||||
@@ -768,7 +725,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
if (ff->pin_Enable().is_linked()) {
|
||||
NetLogic*ce_and = new NetLogic(scope,
|
||||
scope->local_symbol(), 3,
|
||||
NetLogic::AND);
|
||||
NetLogic::AND, 1);
|
||||
des->add_node(ce_and);
|
||||
connect(ff->pin_Enable(), ce_and->pin(1));
|
||||
connect(ce->pin(0), ce_and->pin(2));
|
||||
@@ -788,15 +745,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
|
||||
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",flag)
|
||||
return flag;
|
||||
|
||||
#else
|
||||
cerr << get_line() << ": sorry: "
|
||||
<< "Forgot to implement NetCondit::synth_sync" << endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const NetBus&nex_map, NetBus&nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetEvWait")
|
||||
if (events_in.count() > 0) {
|
||||
cerr << get_line() << ": error: Events are unaccounted"
|
||||
<< " for in process synthesis." << endl;
|
||||
@@ -814,7 +775,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
svector<NetEvProbe*>events (ev->nprobe() - 1);
|
||||
|
||||
/* Get the input set from the substatement. This will be used
|
||||
to figure out which of the probes in the clock. */
|
||||
to figure out which of the probes is the clock. */
|
||||
NexusSet*statement_input = statement_ -> nex_input();
|
||||
|
||||
/* Search for a clock input. The clock input is the edge event
|
||||
@@ -848,62 +809,117 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
<< " are valid clock inputs." << endl;
|
||||
cerr << get_line() << ": : Perhaps the clock"
|
||||
<< " is read by a statement or expression?" << endl;
|
||||
DEBUG_SYNTH2_EXIT("NetEvWait",false)
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
||||
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT"));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE) {
|
||||
perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
|
||||
ff->attribute(polarity, verinum("INVERT"));
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Detected a NEGEDGE clock for the synthesized ff."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope, ff,
|
||||
nex_map, nex_out, events);
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetEvWait",flag)
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called for a process that is determined to be
|
||||
* synchronous. Create a NetFF device to hold the output from the
|
||||
* statement, and synthesize that statement in place.
|
||||
*/
|
||||
bool NetProcTop::synth_sync(Design*des)
|
||||
{
|
||||
DEBUG_SYNTH2_ENTRY("NetProcTop")
|
||||
if (debug_synth2) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Process is apparently synchronous. Making NetFFs."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
|
||||
/* Make a model FF that will connect to the first item in the
|
||||
set, and will also take the initial connection of clocks
|
||||
and resets. */
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Top level making a "
|
||||
<< nex_set[0]->vector_width() << "-wide "
|
||||
<< "NetFF device." << endl;
|
||||
}
|
||||
|
||||
NetFF*ff = new NetFF(scope(), scope()->local_symbol(),
|
||||
nex_set.count());
|
||||
nex_set[0]->vector_width());
|
||||
des->add_node(ff);
|
||||
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
||||
|
||||
/* The D inputs to the DFF device will receive the output from
|
||||
the statements of the process. */
|
||||
NetNet*nex_d = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::WIRE, nex_set.count());
|
||||
nex_d->local_flag(true);
|
||||
NetBus nex_d (scope(), nex_set.count());
|
||||
NetBus nex_q (scope(), nex_set.count());
|
||||
|
||||
/* The Q of the NetFF devices is connected to the output that
|
||||
we are. The nex_q is a bundle of the outputs. We will also
|
||||
pass the nex_q as a map to the statement's synth_sync
|
||||
method to map it to the correct nex_d pin. */
|
||||
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
|
||||
connect(nex_d->pin(idx), ff->pin_Data(idx));
|
||||
connect(nex_set[idx], nex_q.pin(idx));
|
||||
}
|
||||
|
||||
/* The Q outputs of the DFF will connect to the actual outputs
|
||||
of the process. Thus, the DFF will be between the outputs
|
||||
of the process and the outputs of the substatement. */
|
||||
const perm_string tmpq = perm_string::literal("tmpq");
|
||||
NetNet*nex_q = new NetNet(scope(), tmpq, NetNet::WIRE,
|
||||
nex_set.count());
|
||||
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
|
||||
connect(nex_set[idx], nex_q->pin(idx));
|
||||
connect(nex_q->pin(idx), ff->pin_Q(idx));
|
||||
}
|
||||
// Connect the input later.
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope(), ff,
|
||||
nex_q, nex_d,
|
||||
svector<NetEvProbe*>());
|
||||
if (! flag) {
|
||||
delete ff;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete nex_q;
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetProcTop",flag)
|
||||
return flag;
|
||||
NetNet*tmp = nex_d.pin(0).nexus()->pick_any_net();
|
||||
assert(tmp);
|
||||
|
||||
tmp = crop_to_width(des, tmp, ff->width());
|
||||
connect(tmp->pin(0), ff->pin_Data());
|
||||
connect(nex_q.pin(0), ff->pin_Q());
|
||||
|
||||
for (unsigned idx = 1 ; idx < nex_set.count() ; idx += 1) {
|
||||
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
|
||||
nex_set[idx]->vector_width());
|
||||
des->add_node(ff2);
|
||||
|
||||
tmp = nex_d.pin(idx).nexus()->pick_any_net();
|
||||
assert(tmp);
|
||||
|
||||
tmp = crop_to_width(des, tmp, ff2->width());
|
||||
|
||||
connect(nex_q.pin(idx), ff2->pin_Q());
|
||||
connect(tmp->pin(0), ff2->pin_Data());
|
||||
|
||||
connect(ff->pin_Clock(), ff2->pin_Clock());
|
||||
if (ff->pin_Enable().is_linked())
|
||||
connect(ff->pin_Enable(), ff2->pin_Enable());
|
||||
if (ff->pin_Aset().is_linked())
|
||||
connect(ff->pin_Aset(), ff2->pin_Aset());
|
||||
if (ff->pin_Aclr().is_linked())
|
||||
connect(ff->pin_Aclr(), ff2->pin_Aclr());
|
||||
if (ff->pin_Sset().is_linked())
|
||||
connect(ff->pin_Sset(), ff2->pin_Sset());
|
||||
if (ff->pin_Sclr().is_linked())
|
||||
connect(ff->pin_Sclr(), ff2->pin_Sclr());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class synth2_f : public functor_t {
|
||||
@@ -978,74 +994,23 @@ void synth2_f::process(class Design*des, class NetProcTop*top)
|
||||
|
||||
void synth2(Design*des)
|
||||
{
|
||||
debug_synth2 = atoi(des->get_flag("ivl-synth2-debug"));
|
||||
synth2_f synth_obj;
|
||||
des->functor(&synth_obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.39 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
* Revision 1.45 2005/08/27 04:32:08 steve
|
||||
* Handle synthesis of fully packed case statements.
|
||||
*
|
||||
* Revision 1.38 2004/08/28 15:08:32 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
* Revision 1.44 2005/05/15 04:45:50 steve
|
||||
* Debug text.
|
||||
*
|
||||
* Revision 1.37 2004/03/15 18:40:12 steve
|
||||
* Only include DEBUG_SYNTH2 if __FUNCTION__ defined.
|
||||
* Revision 1.43 2005/04/25 01:35:58 steve
|
||||
* Reimplement basic asynchronous processes.
|
||||
*
|
||||
* Revision 1.36 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
* Revision 1.42 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.35 2004/02/18 17:11:58 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.34 2003/12/20 00:59:31 steve
|
||||
* Synthesis debug messages.
|
||||
*
|
||||
* Revision 1.33 2003/12/17 16:52:39 steve
|
||||
* Debug dumps for synth2.
|
||||
*
|
||||
* Revision 1.32 2003/10/27 02:18:04 steve
|
||||
* Handle special case of FF with enable and constant data.
|
||||
*
|
||||
* Revision 1.31 2003/08/28 04:11:19 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
* Revision 1.30 2003/08/15 02:23:53 steve
|
||||
* Add synthesis support for synchronous reset.
|
||||
*
|
||||
* Revision 1.29 2003/08/14 02:41:05 steve
|
||||
* Fix dangling pointer in NexusSet handling blocks.
|
||||
*
|
||||
* Revision 1.28 2003/08/10 17:04:23 steve
|
||||
* Detect asynchronous FF inputs that are expressions.
|
||||
*
|
||||
* Revision 1.27 2003/06/23 00:14:44 steve
|
||||
* ivl_synthesis_cell cuts off synthesis within a module.
|
||||
*
|
||||
* Revision 1.26 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
* Revision 1.25 2003/04/03 04:30:00 steve
|
||||
* Prevent overrun comparing verinums to zero.
|
||||
*
|
||||
* Revision 1.24 2003/03/25 04:04:29 steve
|
||||
* Handle defaults in synthesized case statements.
|
||||
*
|
||||
* Revision 1.23 2003/03/06 00:28:42 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.22 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.21 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.20 2002/11/09 23:29:29 steve
|
||||
* Handle nested-if chip enables.
|
||||
*
|
||||
* Revision 1.19 2002/11/09 20:22:57 steve
|
||||
* Detect synthesis conflicts blocks statements share outputs.
|
||||
*/
|
||||
|
||||
|
||||
+15
-12
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_funcs.cc,v 1.6 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: sys_funcs.cc,v 1.7 2005/07/11 16:56:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -31,14 +31,14 @@
|
||||
*/
|
||||
|
||||
static const struct sfunc_return_type sfunc_table[] = {
|
||||
{ "$realtime", NetExpr::ET_REAL, 0, 0 },
|
||||
{ "$bitstoreal", NetExpr::ET_REAL, 0, 0 },
|
||||
{ "$itor", NetExpr::ET_REAL, 0, 0 },
|
||||
{ "$realtobits", NetExpr::ET_VECTOR, 64, 0 },
|
||||
{ "$time", NetExpr::ET_VECTOR, 64, 0 },
|
||||
{ "$stime", NetExpr::ET_VECTOR, 32, 0 },
|
||||
{ "$simtime", NetExpr::ET_VECTOR, 64, 0 },
|
||||
{ 0, NetExpr::ET_VECTOR, 32, 0 }
|
||||
{ "$realtime", IVL_VT_REAL, 0, 0 },
|
||||
{ "$bitstoreal", IVL_VT_REAL, 0, 0 },
|
||||
{ "$itor", IVL_VT_REAL, 0, 0 },
|
||||
{ "$realtobits", IVL_VT_LOGIC, 64, 0 },
|
||||
{ "$time", IVL_VT_LOGIC, 64, 0 },
|
||||
{ "$stime", IVL_VT_LOGIC, 32, 0 },
|
||||
{ "$simtime", IVL_VT_LOGIC, 64, 0 },
|
||||
{ 0, IVL_VT_LOGIC, 32, 0 }
|
||||
};
|
||||
|
||||
struct sfunc_return_type_cell : sfunc_return_type {
|
||||
@@ -124,7 +124,7 @@ int load_sys_func_table(const char*path)
|
||||
if (strcmp(stype,"vpiSysFuncReal") == 0) {
|
||||
cell = new struct sfunc_return_type_cell;
|
||||
cell->name = lex_strings.add(name);
|
||||
cell->type = NetExpr::ET_REAL;
|
||||
cell->type = IVL_VT_REAL;
|
||||
cell->wid = 0;
|
||||
cell->signed_flag = true;
|
||||
cell->next = sfunc_stack;
|
||||
@@ -135,7 +135,7 @@ int load_sys_func_table(const char*path)
|
||||
if (strcmp(stype,"vpiSysFuncInt") == 0) {
|
||||
cell = new struct sfunc_return_type_cell;
|
||||
cell->name = lex_strings.add(name);
|
||||
cell->type = NetExpr::ET_VECTOR;
|
||||
cell->type = IVL_VT_LOGIC;
|
||||
cell->wid = 32;
|
||||
cell->signed_flag = true;
|
||||
cell->next = sfunc_stack;
|
||||
@@ -176,7 +176,7 @@ int load_sys_func_table(const char*path)
|
||||
|
||||
cell = new struct sfunc_return_type_cell;
|
||||
cell->name = lex_strings.add(name);
|
||||
cell->type = NetExpr::ET_VECTOR;
|
||||
cell->type = IVL_VT_LOGIC;
|
||||
cell->wid = width;
|
||||
cell->signed_flag = signed_flag;
|
||||
cell->next = sfunc_stack;
|
||||
@@ -193,6 +193,9 @@ int load_sys_func_table(const char*path)
|
||||
|
||||
/*
|
||||
* $Log: sys_funcs.cc,v $
|
||||
* Revision 1.7 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.6 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+375
-191
@@ -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.133 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -50,6 +50,9 @@ extern "C" int ivl_design_process(ivl_design_t des,
|
||||
|
||||
extern "C" ivl_scope_t ivl_design_root(ivl_design_t des)
|
||||
{
|
||||
cerr << "ANACHRONISM: ivl_design_root called. "
|
||||
"Use ivl_design_roots instead." << endl;
|
||||
|
||||
assert (des->nroots_);
|
||||
return des->roots_[0];
|
||||
}
|
||||
@@ -120,29 +123,39 @@ extern "C" unsigned ivl_memory_width(ivl_memory_t net)
|
||||
}
|
||||
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->type;
|
||||
}
|
||||
|
||||
extern "C" const char*ivl_const_bits(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->width_ <= sizeof(char*))
|
||||
return net->b.bit_;
|
||||
else
|
||||
return net->b.bits_;
|
||||
switch (net->type) {
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
if (net->width_ <= sizeof(net->b.bit_))
|
||||
return net->b.bit_;
|
||||
else
|
||||
return net->b.bits_;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx)
|
||||
extern "C" ivl_nexus_t ivl_const_nex(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->width_);
|
||||
if (net->width_ == 1)
|
||||
return net->n.pin_;
|
||||
else
|
||||
return net->n.pins_[idx];
|
||||
return net->pin_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_const_pins(ivl_net_const_t net)
|
||||
extern "C" double ivl_const_real(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
assert(net->type == IVL_VT_REAL);
|
||||
return net->b.real_value;
|
||||
}
|
||||
|
||||
extern "C" int ivl_const_signed(ivl_net_const_t net)
|
||||
@@ -151,6 +164,12 @@ extern "C" int ivl_const_signed(ivl_net_const_t net)
|
||||
return net->signed_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_const_width(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_event_name(ivl_event_t net)
|
||||
{
|
||||
static char*name_buffer = 0;
|
||||
@@ -180,6 +199,10 @@ extern "C" const char* ivl_event_basename(ivl_event_t net)
|
||||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" ivl_scope_t ivl_event_scope(ivl_event_t net)
|
||||
{
|
||||
return net->scope;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_event_nany(ivl_event_t net)
|
||||
{
|
||||
@@ -248,20 +271,6 @@ extern "C" double ivl_expr_dvalue(ivl_expr_t net)
|
||||
return net->u_.real_.value;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_expr_lsi(ivl_expr_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
return net->u_.signal_.lsi;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_expr_name(ivl_expr_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
@@ -272,9 +281,6 @@ extern "C" const char* ivl_expr_name(ivl_expr_t net)
|
||||
case IVL_EX_SIGNAL:
|
||||
return net->u_.signal_.sig->name_;
|
||||
|
||||
case IVL_EX_VARIABLE:
|
||||
return net->u_.variable_.var->name;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -305,9 +311,6 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
|
||||
case IVL_EX_SELECT:
|
||||
return net->u_.binary_.lef_;
|
||||
|
||||
case IVL_EX_BITSEL:
|
||||
return net->u_.bitsel_.bit;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
return net->u_.unary_.sub_;
|
||||
|
||||
@@ -438,8 +441,6 @@ extern "C" ivl_signal_t ivl_expr_signal(ivl_expr_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type_) {
|
||||
case IVL_EX_BITSEL:
|
||||
return net->u_.bitsel_.sig;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
return net->u_.signal_.sig;
|
||||
@@ -503,12 +504,6 @@ extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net)
|
||||
return net->u_.memory_.mem_;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_t ivl_expr_variable(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_VARIABLE);
|
||||
return net->u_.variable_.var;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key)
|
||||
{
|
||||
assert(net);
|
||||
@@ -537,6 +532,40 @@ extern "C" ivl_attribute_t ivl_logic_attr_val(ivl_net_logic_t net,
|
||||
return net->attr + idx;
|
||||
}
|
||||
|
||||
extern "C" ivl_drive_t ivl_logic_drive0(ivl_net_logic_t net)
|
||||
{
|
||||
ivl_nexus_t nex = ivl_logic_pin(net, 0);
|
||||
|
||||
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_nexus_ptr_t cur = ivl_nexus_ptr(nex, idx);
|
||||
if (ivl_nexus_ptr_log(cur) != net)
|
||||
continue;
|
||||
if (ivl_nexus_ptr_pin(cur) != 0)
|
||||
continue;
|
||||
return ivl_nexus_ptr_drive0(cur);
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
extern "C" ivl_drive_t ivl_logic_drive1(ivl_net_logic_t net)
|
||||
{
|
||||
ivl_nexus_t nex = ivl_logic_pin(net, 0);
|
||||
|
||||
for (unsigned idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_nexus_ptr_t cur = ivl_nexus_ptr(nex, idx);
|
||||
if (ivl_nexus_ptr_log(cur) != net)
|
||||
continue;
|
||||
if (ivl_nexus_ptr_pin(cur) != 0)
|
||||
continue;
|
||||
return ivl_nexus_ptr_drive1(cur);
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return IVL_DR_STRONG;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_logic_name(ivl_net_logic_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -579,14 +608,19 @@ extern "C" ivl_udp_t ivl_logic_udp(ivl_net_logic_t net)
|
||||
return net->udp;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_logic_delay(ivl_net_logic_t net, unsigned transition)
|
||||
extern "C" ivl_expr_t ivl_logic_delay(ivl_net_logic_t net, unsigned transition)
|
||||
{
|
||||
assert(transition < 3);
|
||||
return net->delay[transition];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_logic_width(ivl_net_logic_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_udp_sequ(ivl_udp_t net)
|
||||
extern "C" int ivl_udp_sequ(ivl_udp_t net)
|
||||
{
|
||||
return net->sequ;
|
||||
}
|
||||
@@ -673,6 +707,20 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
case IVL_LPM_PART_BI:
|
||||
return net->u_.part.base;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -741,29 +789,73 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.a[idx];
|
||||
assert(idx <= 1);
|
||||
if (idx == 0)
|
||||
return net->u_.arith.a;
|
||||
else
|
||||
return net->u_.arith.b;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.size);
|
||||
return net->u_.mux.d[idx];
|
||||
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
assert(idx == 0);
|
||||
return net->u_.reduce.a;
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
return net->u_.shift.d[idx];
|
||||
assert(idx <= 1);
|
||||
if (idx == 0)
|
||||
return net->u_.shift.d;
|
||||
else
|
||||
return net->u_.shift.s;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.d.pin;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx < net->u_.ff.width);
|
||||
if (net->u_.ff.width == 1)
|
||||
return net->u_.ff.d.pin;
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.d.pin;
|
||||
|
||||
case IVL_LPM_CONCAT:
|
||||
assert(idx < net->u_.concat.inputs);
|
||||
return net->u_.concat.pins[idx+1];
|
||||
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
case IVL_LPM_PART_BI:
|
||||
assert(idx <= 1);
|
||||
if (idx == 0)
|
||||
return net->u_.part.a;
|
||||
else
|
||||
return net->u_.ff.d.pins[idx];
|
||||
return net->u_.part.s;
|
||||
|
||||
case IVL_LPM_REPEAT:
|
||||
assert(idx == 0);
|
||||
return net->u_.repeat.a;
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
// Skip the return port.
|
||||
assert(idx < (net->u_.ufunc.ports-1));
|
||||
return net->u_.ufunc.pins[idx+1];
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
@@ -773,6 +865,7 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
||||
{
|
||||
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_datab." << endl;
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
|
||||
@@ -785,8 +878,8 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.b[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.b;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
@@ -794,14 +887,12 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
|
||||
{
|
||||
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_data2." << endl;
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_MUX:
|
||||
assert(sdx < net->u_.mux.size);
|
||||
assert(idx < net->u_.mux.width);
|
||||
return net->u_.mux.d[sdx*net->u_.mux.width + idx];
|
||||
|
||||
case IVL_LPM_UFUNC: {
|
||||
sdx += 1; /* skip the output port. */
|
||||
@@ -818,7 +909,8 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
|
||||
{
|
||||
assert(net);
|
||||
@@ -832,6 +924,7 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function returns the hierarchical name for the LPM device. The
|
||||
@@ -873,39 +966,61 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.q[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q[0];
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.q.pin;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx < net->u_.ff.width);
|
||||
if (net->u_.ff.width == 1)
|
||||
return net->u_.ff.q.pin;
|
||||
else
|
||||
return net->u_.ff.q.pins[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.q.pin;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.width);
|
||||
if (net->u_.mux.width == 1)
|
||||
return net->u_.mux.q.pin;
|
||||
else
|
||||
return net->u_.mux.q.pins[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.mux.q;
|
||||
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
assert(idx == 0);
|
||||
return net->u_.reduce.q;
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
return net->u_.shift.q[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.shift.q;
|
||||
|
||||
case IVL_LPM_UFUNC:
|
||||
assert(idx < net->u_.ufunc.port_wid[0]);
|
||||
return net->u_.ufunc.pins[idx];
|
||||
assert(idx == 0);
|
||||
return net->u_.ufunc.pins[0];
|
||||
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.pins[0];
|
||||
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
case IVL_LPM_PART_BI:
|
||||
assert(idx == 0);
|
||||
return net->u_.part.q;
|
||||
|
||||
case IVL_LPM_REPEAT:
|
||||
assert(idx == 0);
|
||||
return net->u_.repeat.q;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
@@ -919,27 +1034,14 @@ extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net)
|
||||
return net->scope;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
||||
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx < net->u_.ff.swid);
|
||||
if (net->u_.ff.swid == 1)
|
||||
return net->u_.ff.s.pin;
|
||||
else
|
||||
return net->u_.ff.s.pins[idx];
|
||||
return net->u_.ff.s.pin;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.swid);
|
||||
if (net->u_.mux.swid == 1)
|
||||
return net->u_.mux.s.pin;
|
||||
else
|
||||
return net->u_.mux.s.pins[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.select);
|
||||
return net->u_.shift.s[idx];
|
||||
return net->u_.mux.s;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
@@ -954,9 +1056,8 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
||||
return net->u_.ff.swid;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.select;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -972,21 +1073,39 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
||||
case IVL_LPM_MUX:
|
||||
return 0;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
return net->u_.arith.signed_flag;
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
return 0;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.signed_flag;
|
||||
return 0;
|
||||
case IVL_LPM_SIGN_EXT: // Sign extend is always signed.
|
||||
return 1;
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
case IVL_LPM_CONCAT: // Concatenations are always unsigned
|
||||
return 0;
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
case IVL_LPM_PART_BI:
|
||||
return net->u_.part.signed_flag;
|
||||
case IVL_LPM_REPEAT:
|
||||
return 0;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1000,6 +1119,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
||||
return net->u_.mux.size;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.ports - 1;
|
||||
case IVL_LPM_REPEAT:
|
||||
return net->u_.repeat.count;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1021,20 +1142,39 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.width;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EEQ:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
case IVL_LPM_CMP_NE:
|
||||
case IVL_LPM_CMP_NEE:
|
||||
case IVL_LPM_DIVIDE:
|
||||
case IVL_LPM_MOD:
|
||||
case IVL_LPM_MULT:
|
||||
case IVL_LPM_SUB:
|
||||
return net->u_.arith.width;
|
||||
case IVL_LPM_RE_AND:
|
||||
case IVL_LPM_RE_OR:
|
||||
case IVL_LPM_RE_XOR:
|
||||
case IVL_LPM_RE_NAND:
|
||||
case IVL_LPM_RE_NOR:
|
||||
case IVL_LPM_RE_XNOR:
|
||||
case IVL_LPM_SIGN_EXT:
|
||||
return net->u_.reduce.width;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.width;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.port_wid[0];
|
||||
return net->u_.ufunc.width;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.width;
|
||||
case IVL_LPM_PART_VP:
|
||||
case IVL_LPM_PART_PV:
|
||||
return net->u_.part.width;
|
||||
case IVL_LPM_PART_BI:
|
||||
return net->u_.part.width;
|
||||
case IVL_LPM_REPEAT:
|
||||
return net->u_.repeat.width;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1077,26 +1217,26 @@ extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_t ivl_lval_var(ivl_lval_t net)
|
||||
extern "C" ivl_expr_t ivl_lval_part_off(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->type_ == IVL_LVAL_VAR)
|
||||
return net->n.var;
|
||||
return 0x0;
|
||||
return net->loff;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lval_part_off(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->loff_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
|
||||
extern "C" unsigned ivl_lval_width(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
#if 0
|
||||
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->width_;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1104,11 +1244,19 @@ extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
|
||||
assert(net->type_ != IVL_LVAL_MEM);
|
||||
return ivl_signal_pin(net->n.sig, idx+net->loff_);
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->n.sig;
|
||||
switch (net->type_) {
|
||||
case IVL_LVAL_REG:
|
||||
case IVL_LVAL_NET:
|
||||
case IVL_LVAL_MUX:
|
||||
return net->n.sig;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_nexus_name(ivl_nexus_t net)
|
||||
@@ -1293,19 +1441,6 @@ extern "C" ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx)
|
||||
return net->event_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_vars(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->nvar_;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_t ivl_scope_var(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->nvar_);
|
||||
return net->var_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_logs(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1504,21 +1639,9 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
|
||||
return name_buffer;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx)
|
||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->width_);
|
||||
if (net->width_ == 1) {
|
||||
return net->n.pin_;
|
||||
|
||||
} else {
|
||||
return net->n.pins_[idx];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_pins(ivl_signal_t net)
|
||||
{
|
||||
return net->width_;
|
||||
return net->pin_;
|
||||
}
|
||||
|
||||
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
||||
@@ -1532,6 +1655,11 @@ extern "C" int ivl_signal_lsb(ivl_signal_t net)
|
||||
return net->lsb_index;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_width(ivl_signal_t net)
|
||||
{
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" ivl_signal_port_t ivl_signal_port(ivl_signal_t net)
|
||||
{
|
||||
return net->port_;
|
||||
@@ -1552,6 +1680,11 @@ extern "C" int ivl_signal_integer(ivl_signal_t net)
|
||||
return net->isint_;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net)
|
||||
{
|
||||
return net->data_type;
|
||||
}
|
||||
|
||||
extern "C" ivl_signal_type_t ivl_signal_type(ivl_signal_t net)
|
||||
{
|
||||
return net->type_;
|
||||
@@ -1760,15 +1893,12 @@ extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx)
|
||||
switch (net->type_) {
|
||||
case IVL_ST_ASSIGN:
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
assert(idx < net->u_.assign_.lvals_);
|
||||
return net->u_.assign_.lval_ + idx;
|
||||
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_DEASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
case IVL_ST_RELEASE:
|
||||
assert(idx < net->u_.cassign_.lvals);
|
||||
return net->u_.cassign_.lval + idx;
|
||||
assert(idx < net->u_.assign_.lvals_);
|
||||
return net->u_.assign_.lval_ + idx;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
@@ -1781,13 +1911,11 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
|
||||
switch (net->type_) {
|
||||
case IVL_ST_ASSIGN:
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
return net->u_.assign_.lvals_;
|
||||
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_DEASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
case IVL_ST_RELEASE:
|
||||
return net->u_.cassign_.lvals;
|
||||
return net->u_.assign_.lvals_;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
@@ -1798,24 +1926,31 @@ extern "C" unsigned ivl_stmt_lvals(ivl_statement_t net)
|
||||
extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
||||
{
|
||||
assert((net->type_ == IVL_ST_ASSIGN)
|
||||
|| (net->type_ == IVL_ST_ASSIGN_NB));
|
||||
|| (net->type_ == IVL_ST_ASSIGN_NB)
|
||||
|| (net->type_ == IVL_ST_CASSIGN)
|
||||
|| (net->type_ == IVL_ST_DEASSIGN)
|
||||
|| (net->type_ == IVL_ST_FORCE)
|
||||
|| (net->type_ == IVL_ST_RELEASE));
|
||||
|
||||
unsigned sum = 0;
|
||||
for (unsigned idx = 0 ; idx < net->u_.assign_.lvals_ ; idx += 1) {
|
||||
ivl_lval_t cur = net->u_.assign_.lval_ + idx;
|
||||
|
||||
unsigned nlvals;
|
||||
struct ivl_lval_s*lvals;
|
||||
nlvals = net->u_.assign_.lvals_;
|
||||
lvals = net->u_.assign_.lval_;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nlvals ; idx += 1) {
|
||||
ivl_lval_t cur = lvals + idx;
|
||||
switch(cur->type_) {
|
||||
case IVL_LVAL_MUX:
|
||||
sum += 1;
|
||||
break;
|
||||
case IVL_LVAL_REG:
|
||||
sum += ivl_lval_pins(cur);
|
||||
sum += ivl_lval_width(cur);
|
||||
break;
|
||||
case IVL_LVAL_MEM:
|
||||
sum += ivl_memory_width(ivl_lval_mem(cur));
|
||||
break;
|
||||
case IVL_LVAL_VAR:
|
||||
sum += 0;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -1836,33 +1971,6 @@ extern "C" const char* ivl_stmt_name(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
assert(idx < net->u_.cassign_.npins);
|
||||
return net->u_.cassign_.pins[idx];
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_stmt_nexus_count(ivl_statement_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
return net->u_.cassign_.npins;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
@@ -1892,6 +2000,8 @@ extern "C" ivl_expr_t ivl_stmt_rval(ivl_statement_t net)
|
||||
switch (net->type_) {
|
||||
case IVL_ST_ASSIGN:
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
case IVL_ST_CASSIGN:
|
||||
case IVL_ST_FORCE:
|
||||
return net->u_.assign_.rval_;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -1921,20 +2031,94 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_variable_name(ivl_variable_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->type;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.133 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.132 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.131 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.130 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.129 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.128 2005/06/13 23:22:37 steve
|
||||
* Fix compile errors.
|
||||
*
|
||||
* Revision 1.127 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.126 2005/05/08 23:44:08 steve
|
||||
* Add support for variable part select.
|
||||
*
|
||||
* Revision 1.125 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.124 2005/04/13 06:35:11 steve
|
||||
* Make logic aware of strength.
|
||||
*
|
||||
* Revision 1.123 2005/04/06 05:29:08 steve
|
||||
* Rework NetRamDq and IVL_LPM_RAM nodes.
|
||||
*
|
||||
* Revision 1.122 2005/04/01 06:04:30 steve
|
||||
* Clean up handle of UDPs.
|
||||
*
|
||||
* Revision 1.121 2005/03/18 02:56:04 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
* Revision 1.120 2005/03/09 05:52:04 steve
|
||||
* Handle case inequality in netlists.
|
||||
*
|
||||
* Revision 1.119 2005/02/19 02:43:38 steve
|
||||
* Support shifts and divide.
|
||||
*
|
||||
* Revision 1.118 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.117 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.116 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.115 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.114 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.113 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.112 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.111 2004/12/18 18:56:18 steve
|
||||
* Add ivl_event_scope, and better document ivl_event_X methods.
|
||||
*
|
||||
* Revision 1.110 2004/12/15 17:10:40 steve
|
||||
* Fixup force statement elaboration.
|
||||
*
|
||||
* Revision 1.109 2004/12/11 02:31:27 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.108 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+20
-137
@@ -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.43 2005/09/14 02:53:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -38,18 +38,7 @@
|
||||
*/
|
||||
static ivl_variable_type_t get_expr_type(const NetExpr*net)
|
||||
{
|
||||
switch (net->expr_type()) {
|
||||
case NetExpr::ET_VOID:
|
||||
return IVL_VT_VOID;
|
||||
|
||||
case NetExpr::ET_REAL:
|
||||
return IVL_VT_REAL;
|
||||
|
||||
case NetExpr::ET_VECTOR:
|
||||
return IVL_VT_VECTOR;
|
||||
}
|
||||
|
||||
return IVL_VT_VOID;
|
||||
return net->expr_type();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -238,7 +227,7 @@ void dll_target::expr_const(const NetEConst*net)
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr_);
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
expr_->value_= net->expr_type();
|
||||
|
||||
if (net->value().is_string()) {
|
||||
expr_->type_ = IVL_EX_STRING;
|
||||
@@ -369,18 +358,7 @@ void dll_target::expr_sfunc(const NetESFunc*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_SFUNC;
|
||||
switch (net->expr_type()) {
|
||||
case NetExpr::ET_VECTOR:
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
break;
|
||||
case NetExpr::ET_REAL:
|
||||
expr->value_= IVL_VT_REAL;
|
||||
break;
|
||||
case NetExpr::ET_VOID:
|
||||
assert(0);
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
break;
|
||||
}
|
||||
expr->value_= net->expr_type();
|
||||
expr->width_= net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
/* system function names are lex_strings strings. */
|
||||
@@ -438,109 +416,12 @@ void dll_target::expr_signal(const NetESignal*net)
|
||||
assert(expr_);
|
||||
|
||||
expr_->type_ = IVL_EX_SIGNAL;
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
expr_->value_= net->expr_type();
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
expr_->u_.signal_.sig = find_signal(des_, net->sig());
|
||||
expr_->u_.signal_.lsi = net->lsi();
|
||||
expr_->u_.signal_.msi = net->msi();
|
||||
}
|
||||
|
||||
void dll_target::expr_subsignal(const NetEBitSel*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
||||
ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_BITSEL;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->width_= net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
expr->u_.bitsel_.sig = find_signal(des_, net->sig());
|
||||
|
||||
assert(expr->u_.bitsel_.sig->lsb_index == net->sig()->lsb());
|
||||
|
||||
net->index()->expr_scan(this);
|
||||
assert(expr_);
|
||||
expr->u_.bitsel_.bit = expr_;
|
||||
|
||||
/* If the lsb of the signal is not 0, then we are about to
|
||||
lose the proper offset to the normalized vector. Modify the
|
||||
expression to subtract the offset:
|
||||
|
||||
reg [7:4] a;
|
||||
... = a[x];
|
||||
|
||||
becomes
|
||||
|
||||
reg [3:0] a;
|
||||
... = a[x-4];
|
||||
|
||||
to reflect the normalizing of vectors that is done by the
|
||||
compiler. */
|
||||
|
||||
if (expr->u_.bitsel_.sig->lsb_index != 0) {
|
||||
|
||||
/* Create in tmpc the constant offset (4 in the above
|
||||
example) to be subtracted from the index. */
|
||||
char*bits;
|
||||
long lsb = expr->u_.bitsel_.sig->lsb_index;
|
||||
ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmpc->type_ = IVL_EX_NUMBER;
|
||||
tmpc->width_ = expr->u_.bitsel_.bit->width_;
|
||||
tmpc->signed_ = net->index()->has_sign()? 1 : 0;
|
||||
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
|
||||
for (unsigned idx = 0 ; idx < tmpc->width_ ; idx += 1) {
|
||||
bits[idx] = (lsb & 1)? '1' : '0';
|
||||
lsb >>= 1;
|
||||
}
|
||||
|
||||
/* Now make the subtractor (x-4 in the above example)
|
||||
that has as input A the index expression and input B
|
||||
the constant to subtract. */
|
||||
ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmps->type_ = IVL_EX_BINARY;
|
||||
tmps->width_ = tmpc->width_;
|
||||
tmps->signed_ = net->index()->has_sign()? 1 : 0;
|
||||
tmps->u_.binary_.op_ = '-';
|
||||
tmps->u_.binary_.lef_ = expr->u_.bitsel_.bit;
|
||||
tmps->u_.binary_.rig_ = tmpc;
|
||||
|
||||
/* Replace (x) with (x-4) */
|
||||
expr->u_.bitsel_.bit = tmps;
|
||||
|
||||
/* If the index item distance (the distance to the next
|
||||
most significant bit) is not 1, then multiply the
|
||||
previous result to convert the index. */
|
||||
if (expr->u_.bitsel_.sig->lsb_dist != 1) {
|
||||
long dist = expr->u_.bitsel_.sig->lsb_dist;
|
||||
|
||||
tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmpc->type_ = IVL_EX_NUMBER;
|
||||
tmpc->width_ = expr->u_.bitsel_.bit->width_;
|
||||
tmpc->signed_ = 1;
|
||||
tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
|
||||
for (unsigned idx = 0 ; idx < tmpc->width_ ; idx += 1) {
|
||||
bits[idx] = (dist & 1)? '1' : '0';
|
||||
dist >>= 1;
|
||||
}
|
||||
|
||||
tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
tmps->type_ = IVL_EX_BINARY;
|
||||
tmps->width_ = tmpc->width_;
|
||||
tmps->signed_ = 1;
|
||||
tmps->u_.binary_.op_ = '*';
|
||||
tmps->u_.binary_.lef_ = expr->u_.bitsel_.bit;
|
||||
tmps->u_.binary_.rig_ = tmpc;
|
||||
|
||||
expr->u_.bitsel_.bit = tmps;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
expr_ = expr;
|
||||
}
|
||||
|
||||
void dll_target::expr_ufunc(const NetEUFunc*net)
|
||||
{
|
||||
@@ -550,7 +431,7 @@ void dll_target::expr_ufunc(const NetEUFunc*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_UFUNC;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->value_= net->expr_type();
|
||||
expr->width_= net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
@@ -590,20 +471,22 @@ void dll_target::expr_unary(const NetEUnary*net)
|
||||
expr_->u_.unary_.sub_ = sub;
|
||||
}
|
||||
|
||||
void dll_target::expr_variable(const NetEVariable*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
expr_->type_ = IVL_EX_VARIABLE;
|
||||
expr_->value_ = IVL_VT_REAL;
|
||||
expr_->width_ = 0;
|
||||
expr_->signed_= net->has_sign()? 1 : 0;
|
||||
expr_->u_.variable_.var = find_variable(des_, net->variable());
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.43 2005/09/14 02:53:15 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.42 2005/07/13 04:51:36 steve
|
||||
* Functions get type from their output signal.
|
||||
*
|
||||
* Revision 1.41 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.40 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.39 2004/06/17 16:06:19 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
||||
+85
-205
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-proc.cc,v 1.65 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.68 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -130,13 +130,6 @@ bool dll_target::func_def(const NetScope*net)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const NetVariable*ret_var = def->return_var()) {
|
||||
cerr << ret_var->get_line() << ": internal error: "
|
||||
<< "Function " << net->name() << " has an unsupported "
|
||||
<< "return type." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
cerr << "?:0" << ": internal error: "
|
||||
<< "Function " << net->name() << " has a return type"
|
||||
<< " that I do not understand." << endl;
|
||||
@@ -145,90 +138,15 @@ bool dll_target::func_def(const NetScope*net)
|
||||
}
|
||||
|
||||
/*
|
||||
* This private function makes the assignment lvals for the various
|
||||
* kinds of assignment statements.
|
||||
*/
|
||||
void dll_target::proc_assign(const NetAssign*net)
|
||||
void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
||||
{
|
||||
unsigned cnt;
|
||||
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN;
|
||||
|
||||
stmt_cur_->u_.assign_.lvals_ = cnt = net->l_val_count();
|
||||
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
||||
/* The assignment may have multiple concatenated
|
||||
l-values. Scan them and accumulate an ivl_lval_t list. */
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
|
||||
const NetAssign_*asn = net->l_val(idx);
|
||||
|
||||
cur->width_ = asn->lwidth();
|
||||
cur->loff_ = asn->get_loff();
|
||||
if (asn->sig()) {
|
||||
cur->type_ = IVL_LVAL_REG;
|
||||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
|
||||
cur->idx = 0;
|
||||
if (asn->bmux()) {
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
|
||||
if (cur->n.sig->lsb_index != 0)
|
||||
sub_off_from_expr_(asn->sig()->lsb());
|
||||
if (cur->n.sig->lsb_dist != 1)
|
||||
mul_expr_by_const_(cur->n.sig->lsb_dist);
|
||||
|
||||
cur->type_ = IVL_LVAL_MUX;
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
} else if (asn->var()) {
|
||||
cur->type_ = IVL_LVAL_VAR;
|
||||
cur->idx = 0;
|
||||
cur->n.var = find_variable(des_, asn->var());
|
||||
|
||||
} else {
|
||||
assert(asn->mem());
|
||||
cur->type_ = IVL_LVAL_MEM;
|
||||
cur->n.mem = find_memory(des_, asn->mem());
|
||||
assert(cur->n.mem);
|
||||
cur->width_ = ivl_memory_width(cur->n.mem);
|
||||
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
const NetExpr*del = net->get_delay();
|
||||
if (del) {
|
||||
del->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.delay = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dll_target::proc_assign_nb(const NetAssignNB*net)
|
||||
{
|
||||
unsigned cnt = net->l_val_count();
|
||||
|
||||
const NetExpr* delay_exp = net->get_delay();
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
|
||||
|
||||
stmt_cur_->u_.assign_.lvals_ = cnt;
|
||||
stmt_cur_->u_.assign_.lval_ = new struct ivl_lval_s[cnt];
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
@@ -236,9 +154,18 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
struct ivl_lval_s*cur = stmt_cur_->u_.assign_.lval_ + idx;
|
||||
const NetAssign_*asn = net->l_val(idx);
|
||||
const NetExpr*loff = asn->get_base();
|
||||
|
||||
if (loff == 0) {
|
||||
cur->loff = 0;
|
||||
} else {
|
||||
loff->expr_scan(this);
|
||||
cur->loff = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
cur->width_ = asn->lwidth();
|
||||
cur->loff_ = asn->get_loff();
|
||||
|
||||
if (asn->sig()) {
|
||||
cur->type_ = IVL_LVAL_REG;
|
||||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
@@ -269,14 +196,52 @@ void dll_target::proc_assign_nb(const NetAssignNB*net)
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
} else {
|
||||
assert(asn->var());
|
||||
cur->type_ = IVL_LVAL_VAR;
|
||||
cur->idx = 0;
|
||||
cur->n.var = find_variable(des_, asn->var());
|
||||
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void dll_target::proc_assign(const NetAssign*net)
|
||||
{
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN;
|
||||
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
||||
/* Make the lval fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
const NetExpr*del = net->get_delay();
|
||||
if (del) {
|
||||
del->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.delay = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dll_target::proc_assign_nb(const NetAssignNB*net)
|
||||
{
|
||||
const NetExpr* delay_exp = net->get_delay();
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_ASSIGN_NB;
|
||||
stmt_cur_->u_.assign_.delay = 0;
|
||||
|
||||
/* Make the lval fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
/* Make the rval field. */
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
@@ -428,27 +393,13 @@ bool dll_target::proc_cassign(const NetCAssign*net)
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_CASSIGN;
|
||||
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
const NetNet*lsig = net->lval();
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
|
||||
|
||||
stmt_cur_->u_.cassign_.npins = net->pin_count();
|
||||
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
|
||||
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
|
||||
|
||||
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
|
||||
assert(ntmp[idx]);
|
||||
}
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -485,19 +436,9 @@ bool dll_target::proc_deassign(const NetDeassign*net)
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_DEASSIGN;
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
|
||||
const NetNet*lsig = net->lval();
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = IVL_LVAL_REG;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = find_signal(des_, lsig);
|
||||
stmt_cur_->u_.cassign_.npins = 0;
|
||||
stmt_cur_->u_.cassign_.pins = 0;
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -554,52 +495,19 @@ bool dll_target::proc_disable(const NetDisable*net)
|
||||
|
||||
bool dll_target::proc_force(const NetForce*net)
|
||||
{
|
||||
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_FORCE;
|
||||
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
const NetNet*lsig = net->lval();
|
||||
assert(lsig);
|
||||
ivl_signal_t sig = find_signal(des_, lsig);
|
||||
assert(sig);
|
||||
|
||||
ivl_lval_type_t ltype;
|
||||
switch (sig->type_) {
|
||||
case IVL_SIT_REG:
|
||||
ltype = IVL_LVAL_REG;
|
||||
break;
|
||||
case IVL_SIT_TRI:
|
||||
case IVL_SIT_TRI0:
|
||||
case IVL_SIT_TRI1:
|
||||
ltype = IVL_LVAL_NET;
|
||||
break;
|
||||
default:
|
||||
cerr << net->get_line() << ": internal error: Sorry, "
|
||||
<< "force to nets not supported by this target."
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
|
||||
|
||||
stmt_cur_->u_.cassign_.npins = net->pin_count();
|
||||
stmt_cur_->u_.cassign_.pins = (ivl_nexus_t*)
|
||||
calloc(stmt_cur_->u_.cassign_.npins, sizeof(ivl_nexus_t));
|
||||
|
||||
ivl_nexus_t*ntmp = stmt_cur_->u_.cassign_.pins;
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
ntmp[idx] = (ivl_nexus_t)net->pin(idx).nexus()->t_cookie();
|
||||
assert(ntmp[idx]);
|
||||
}
|
||||
assert(expr_ == 0);
|
||||
net->rval()->expr_scan(this);
|
||||
stmt_cur_->u_.assign_.rval_ = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -630,47 +538,8 @@ bool dll_target::proc_release(const NetRelease*net)
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_RELEASE;
|
||||
|
||||
/* If there is no signal attached to the release, then it is
|
||||
the victim of an elided net. In that case, simply state
|
||||
that there are no lvals, and that's all. */
|
||||
const NetNet*lsig = net->lval();
|
||||
if (lsig == 0) {
|
||||
stmt_cur_->u_.cassign_.lvals = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(lsig);
|
||||
stmt_cur_->u_.cassign_.lvals = 1;
|
||||
stmt_cur_->u_.cassign_.lval = (struct ivl_lval_s*)
|
||||
calloc(1, sizeof(struct ivl_lval_s));
|
||||
|
||||
|
||||
ivl_signal_t sig = find_signal(des_, lsig);
|
||||
assert(sig);
|
||||
|
||||
ivl_lval_type_t ltype;
|
||||
switch (sig->type_) {
|
||||
case IVL_SIT_REG:
|
||||
ltype = IVL_LVAL_REG;
|
||||
break;
|
||||
case IVL_SIT_TRI:
|
||||
case IVL_SIT_TRI0:
|
||||
case IVL_SIT_TRI1:
|
||||
ltype = IVL_LVAL_NET;
|
||||
break;
|
||||
default:
|
||||
cerr << net->get_line() << ": internal error: Sorry, "
|
||||
<< "force/release to nets not supported by this target."
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
stmt_cur_->u_.cassign_.lval[0].width_ = lsig->pin_count();
|
||||
stmt_cur_->u_.cassign_.lval[0].loff_ = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].type_ = ltype;
|
||||
stmt_cur_->u_.cassign_.lval[0].idx = 0;
|
||||
stmt_cur_->u_.cassign_.lval[0].n.sig = sig;
|
||||
/* Make the l-value fields. */
|
||||
make_assign_lvals_(net);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -872,6 +741,17 @@ void dll_target::proc_while(const NetWhile*net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.68 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.67 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.66 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.65 2004/10/04 01:10:55 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: t-dll.h,v 1.115 2004/10/04 01:10:56 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -69,8 +69,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
bool bufz(const NetBUFZ*);
|
||||
void event(const NetEvent*);
|
||||
void variable(const NetVariable*);
|
||||
void logic(const NetLogic*);
|
||||
bool ureduce(const NetUReduce*);
|
||||
void net_case_cmp(const NetCaseCmp*);
|
||||
void udp(const NetUDP*);
|
||||
void lpm_add_sub(const NetAddSub*);
|
||||
@@ -82,12 +82,15 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void lpm_mult(const NetMult*);
|
||||
void lpm_mux(const NetMux*);
|
||||
void lpm_ram_dq(const NetRamDq*);
|
||||
bool concat(const NetConcat*);
|
||||
bool part_select(const NetPartSelect*);
|
||||
bool replicate(const NetReplicate*);
|
||||
void net_assign(const NetAssign_*);
|
||||
bool net_cassign(const NetCAssign*);
|
||||
bool net_force(const NetForce*);
|
||||
bool net_function(const NetUserFunc*);
|
||||
bool net_const(const NetConst*);
|
||||
bool net_literal(const NetLiteral*);
|
||||
void net_probe(const NetEvProbe*);
|
||||
bool sign_extend(const NetSignExtend*);
|
||||
|
||||
bool process(const NetProcTop*);
|
||||
void scope(const NetScope*);
|
||||
@@ -137,12 +140,10 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void expr_scope(const NetEScope*);
|
||||
void expr_select(const NetESelect*);
|
||||
void expr_sfunc(const NetESFunc*);
|
||||
void expr_subsignal(const NetEBitSel*);
|
||||
void expr_ternary(const NetETernary*);
|
||||
void expr_ufunc(const NetEUFunc*);
|
||||
void expr_unary(const NetEUnary*);
|
||||
void expr_signal(const NetESignal*);
|
||||
void expr_variable(const NetEVariable*);
|
||||
|
||||
ivl_scope_t lookup_scope_(const NetScope*scope);
|
||||
|
||||
@@ -155,16 +156,17 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
|
||||
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
|
||||
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
|
||||
static ivl_variable_t find_variable(ivl_design_s &des, const NetVariable*net);
|
||||
|
||||
static ivl_parameter_t scope_find_param(ivl_scope_t scope,
|
||||
const char*name);
|
||||
|
||||
void add_root(ivl_design_s &des_, const NetScope *s);
|
||||
|
||||
void make_assign_lvals_(const NetAssignBase*net);
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
void make_logic_delays_(struct ivl_net_logic_s*obj, const NetObj*net);
|
||||
void make_scope_parameters(ivl_scope_t scope, const NetScope*net);
|
||||
|
||||
static ivl_expr_t expr_from_value_(const verinum&that);
|
||||
@@ -201,11 +203,6 @@ struct ivl_expr_s {
|
||||
ivl_expr_t rig_;
|
||||
} binary_;
|
||||
|
||||
struct {
|
||||
ivl_signal_t sig;
|
||||
ivl_expr_t bit;
|
||||
} bitsel_;
|
||||
|
||||
struct {
|
||||
unsigned rept;
|
||||
unsigned parms;
|
||||
@@ -227,7 +224,6 @@ struct ivl_expr_s {
|
||||
|
||||
struct {
|
||||
ivl_signal_t sig;
|
||||
unsigned lsi, msi;
|
||||
} signal_;
|
||||
|
||||
struct {
|
||||
@@ -272,9 +268,6 @@ struct ivl_expr_s {
|
||||
ivl_expr_t sub_;
|
||||
} unary_;
|
||||
|
||||
struct {
|
||||
ivl_variable_t var;
|
||||
} variable_;
|
||||
} u_;
|
||||
};
|
||||
|
||||
@@ -322,35 +315,51 @@ struct ivl_lpm_s {
|
||||
unsigned size;
|
||||
unsigned swid;
|
||||
ivl_nexus_t*d;
|
||||
union {
|
||||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} q;
|
||||
union {
|
||||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_nexus_t q, s;
|
||||
} mux;
|
||||
|
||||
struct ivl_lpm_shift_s {
|
||||
unsigned width;
|
||||
unsigned select;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t*q;
|
||||
ivl_nexus_t*d;
|
||||
ivl_nexus_t*s;
|
||||
ivl_nexus_t q, d, s;
|
||||
} shift;
|
||||
|
||||
struct ivl_lpm_arith_s {
|
||||
unsigned width;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t*q, *a, *b;
|
||||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_concat_s {
|
||||
unsigned width;
|
||||
unsigned inputs;
|
||||
ivl_nexus_t*pins;
|
||||
} concat;
|
||||
|
||||
struct ivl_part_s {
|
||||
unsigned width;
|
||||
unsigned base;
|
||||
unsigned signed_flag :1;
|
||||
ivl_nexus_t q, a, s;
|
||||
} part;
|
||||
|
||||
// IVL_LPM_RE_* and IVL_LPM_SIGN_EXT use this.
|
||||
struct ivl_lpm_reduce_s {
|
||||
unsigned width;
|
||||
ivl_nexus_t q, a;
|
||||
} reduce;
|
||||
|
||||
struct ivl_lpm_repeat_s {
|
||||
unsigned width;
|
||||
unsigned count;
|
||||
ivl_nexus_t q, a;
|
||||
} repeat;
|
||||
|
||||
struct ivl_lpm_ufunc_s {
|
||||
ivl_scope_t def;
|
||||
unsigned ports;
|
||||
unsigned *port_wid;
|
||||
unsigned width;
|
||||
ivl_nexus_t*pins;
|
||||
} ufunc;
|
||||
} u_;
|
||||
@@ -366,39 +375,36 @@ enum ivl_lval_type_t {
|
||||
IVL_LVAL_REG = 0,
|
||||
IVL_LVAL_MUX = 1,
|
||||
IVL_LVAL_MEM = 2,
|
||||
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
|
||||
IVL_LVAL_VAR = 4
|
||||
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
|
||||
};
|
||||
|
||||
struct ivl_lval_s {
|
||||
unsigned width_;
|
||||
unsigned loff_;
|
||||
unsigned type_ : 8;
|
||||
ivl_expr_t loff;
|
||||
ivl_expr_t idx;
|
||||
unsigned width_;
|
||||
unsigned type_ : 8;
|
||||
union {
|
||||
ivl_signal_t sig;
|
||||
ivl_memory_t mem;
|
||||
ivl_variable_t var;
|
||||
} n;
|
||||
};
|
||||
|
||||
/*
|
||||
* This object represents a vector constant, possibly signed, in a
|
||||
* This object represents a literal constant, possibly signed, in a
|
||||
* structural context.
|
||||
*/
|
||||
struct ivl_net_const_s {
|
||||
ivl_variable_type_t type;
|
||||
unsigned width_;
|
||||
unsigned signed_ : 1;
|
||||
|
||||
union {
|
||||
double real_value;
|
||||
char bit_[sizeof(char*)];
|
||||
char *bits_;
|
||||
} b;
|
||||
|
||||
union {
|
||||
ivl_nexus_t pin_;
|
||||
ivl_nexus_t*pins_;
|
||||
} n;
|
||||
ivl_nexus_t pin_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -407,6 +413,7 @@ struct ivl_net_const_s {
|
||||
*/
|
||||
struct ivl_net_logic_s {
|
||||
ivl_logic_t type_;
|
||||
unsigned width_;
|
||||
ivl_udp_t udp;
|
||||
|
||||
perm_string name_;
|
||||
@@ -418,7 +425,7 @@ struct ivl_net_logic_s {
|
||||
struct ivl_attribute_s*attr;
|
||||
unsigned nattr;
|
||||
|
||||
unsigned delay[3];
|
||||
ivl_expr_t delay[3];
|
||||
};
|
||||
|
||||
|
||||
@@ -428,7 +435,7 @@ struct ivl_net_logic_s {
|
||||
struct ivl_udp_s {
|
||||
perm_string name;
|
||||
unsigned nin;
|
||||
unsigned sequ;
|
||||
int sequ; /* boolen */
|
||||
char init;
|
||||
unsigned nrows;
|
||||
typedef const char*ccharp_t;
|
||||
@@ -537,9 +544,6 @@ struct ivl_scope_s {
|
||||
unsigned nmem_;
|
||||
ivl_memory_t* mem_;
|
||||
|
||||
unsigned nvar_;
|
||||
ivl_variable_t* var_;
|
||||
|
||||
unsigned nparam_;
|
||||
ivl_parameter_t param_;
|
||||
|
||||
@@ -564,6 +568,7 @@ struct ivl_scope_s {
|
||||
struct ivl_signal_s {
|
||||
ivl_signal_type_t type_;
|
||||
ivl_signal_port_t port_;
|
||||
ivl_variable_type_t data_type;
|
||||
|
||||
unsigned width_;
|
||||
unsigned signed_ : 1;
|
||||
@@ -578,10 +583,7 @@ struct ivl_signal_s {
|
||||
perm_string name_;
|
||||
ivl_scope_t scope_;
|
||||
|
||||
union {
|
||||
ivl_nexus_t pin_;
|
||||
ivl_nexus_t*pins_;
|
||||
} n;
|
||||
ivl_nexus_t pin_;
|
||||
|
||||
struct ivl_attribute_s*attr;
|
||||
unsigned nattr;
|
||||
@@ -595,7 +597,8 @@ struct ivl_signal_s {
|
||||
struct ivl_statement_s {
|
||||
enum ivl_statement_type_e type_;
|
||||
union {
|
||||
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB */
|
||||
struct { /* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB
|
||||
IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
|
||||
unsigned lvals_;
|
||||
struct ivl_lval_s*lval_;
|
||||
ivl_expr_t rval_;
|
||||
@@ -615,13 +618,6 @@ struct ivl_statement_s {
|
||||
struct ivl_statement_s*case_st;
|
||||
} case_;
|
||||
|
||||
struct { /* IVL_ST_CASSIGN, IVL_ST_DEASSIGN */
|
||||
unsigned lvals;
|
||||
struct ivl_lval_s*lval;
|
||||
unsigned npins;
|
||||
ivl_nexus_t*pins;
|
||||
} cassign_;
|
||||
|
||||
struct { /* IVL_ST_CONDIT */
|
||||
/* This is the condition expression */
|
||||
ivl_expr_t cond_;
|
||||
@@ -673,17 +669,64 @@ struct ivl_statement_s {
|
||||
} u_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This holds the details about a variable object.
|
||||
*/
|
||||
struct ivl_variable_s {
|
||||
ivl_variable_type_t type;
|
||||
perm_string name;
|
||||
ivl_scope_t scope;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.129 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.128 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.127 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.126 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.125 2005/05/08 23:44:08 steve
|
||||
* Add support for variable part select.
|
||||
*
|
||||
* Revision 1.124 2005/04/01 06:04:30 steve
|
||||
* Clean up handle of UDPs.
|
||||
*
|
||||
* Revision 1.123 2005/03/18 02:56:04 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
* Revision 1.122 2005/02/19 02:43:39 steve
|
||||
* Support shifts and divide.
|
||||
*
|
||||
* Revision 1.121 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.120 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.119 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.118 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.117 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.116 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.115 2004/10/04 01:10:56 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: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.77 2005/07/11 16:56:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -47,12 +47,6 @@ void target_t::memory(const NetMemory*)
|
||||
"Unhandled memory." << endl;
|
||||
}
|
||||
|
||||
void target_t::variable(const NetVariable*that)
|
||||
{
|
||||
cerr << that->get_line() << ": error: target (" << typeid(*this).name()
|
||||
<< "): Unhandled variable <" << that->basename() << ">." << endl;
|
||||
}
|
||||
|
||||
bool target_t::func_def(const NetScope*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -68,6 +62,8 @@ void target_t::task_def(const NetScope*)
|
||||
|
||||
void target_t::logic(const NetLogic*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled logic gate" << endl;
|
||||
}
|
||||
|
||||
bool target_t::bufz(const NetBUFZ*)
|
||||
@@ -83,6 +79,13 @@ void target_t::udp(const NetUDP*)
|
||||
"Unhandled UDP." << endl;
|
||||
}
|
||||
|
||||
bool target_t::ureduce(const NetUReduce*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled unary reduction logic gate." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_add_sub(const NetAddSub*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -137,20 +140,33 @@ void target_t::lpm_ram_dq(const NetRamDq*)
|
||||
"Unhandled NetRamDq." << endl;
|
||||
}
|
||||
|
||||
bool target_t::concat(const NetConcat*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetConcat." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::part_select(const NetPartSelect*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetPartSelect." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::replicate(const NetReplicate*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetReplicate." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::net_case_cmp(const NetCaseCmp*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled case compare node." << endl;
|
||||
}
|
||||
|
||||
bool target_t::net_cassign(const NetCAssign*dev)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): ";
|
||||
cerr << dev->get_line();
|
||||
cerr << ": Target does not support procedural continuous assignment." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_const(const NetConst*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -158,13 +174,6 @@ bool target_t::net_const(const NetConst*)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_force(const NetForce*dev)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetForce node." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_function(const NetUserFunc*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -172,6 +181,13 @@ bool target_t::net_function(const NetUserFunc*net)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::net_literal(const NetLiteral*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled LITERAL node." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::net_probe(const NetEvProbe*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -179,6 +195,13 @@ void target_t::net_probe(const NetEvProbe*net)
|
||||
net->dump_node(cerr, 4);
|
||||
}
|
||||
|
||||
bool target_t::sign_extend(const NetSignExtend*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetSignExtend node." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::process(const NetProcTop*top)
|
||||
{
|
||||
return top->statement()->emit_proc(this);
|
||||
@@ -382,12 +405,6 @@ void expr_scan_t::expr_signal(const NetESignal*)
|
||||
"unhandled expr_signal." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_subsignal(const NetEBitSel*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled bit select expression." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_ternary(const NetETernary*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
@@ -406,12 +423,6 @@ void expr_scan_t::expr_unary(const NetEUnary*)
|
||||
"unhandled expr_unary." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_variable(const NetEVariable*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_variable." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
@@ -420,6 +431,39 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.77 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.76 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.75 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.74 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.73 2005/02/03 04:56:21 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.72 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.71 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.70 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.69 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
||||
@@ -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.74 2005/07/11 16:56:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -68,9 +68,6 @@ struct target_t {
|
||||
/* Output a memory (called for each memory object) */
|
||||
virtual void memory(const NetMemory*);
|
||||
|
||||
/* Output an event object. Called for each named event in the scope. */
|
||||
virtual void variable(const NetVariable*);
|
||||
|
||||
/* Output a defined task. */
|
||||
virtual void task_def(const NetScope*);
|
||||
virtual bool func_def(const NetScope*);
|
||||
@@ -86,16 +83,21 @@ struct target_t {
|
||||
virtual void lpm_mux(const NetMux*);
|
||||
virtual void lpm_ram_dq(const NetRamDq*);
|
||||
|
||||
virtual bool concat(const NetConcat*);
|
||||
virtual bool part_select(const NetPartSelect*);
|
||||
virtual bool replicate(const NetReplicate*);
|
||||
|
||||
/* Output a gate (called for each gate) */
|
||||
virtual void logic(const NetLogic*);
|
||||
virtual bool ureduce(const NetUReduce*); /* unary reduction operator */
|
||||
virtual bool bufz(const NetBUFZ*);
|
||||
virtual void udp(const NetUDP*);
|
||||
virtual void net_case_cmp(const NetCaseCmp*);
|
||||
virtual bool net_cassign(const NetCAssign*);
|
||||
virtual bool net_const(const NetConst*);
|
||||
virtual bool net_force(const NetForce*);
|
||||
virtual bool net_function(const NetUserFunc*);
|
||||
virtual bool net_literal(const NetLiteral*);
|
||||
virtual void net_probe(const NetEvProbe*);
|
||||
virtual bool sign_extend(const NetSignExtend*);
|
||||
|
||||
/* Output a process (called for each process). It is up to the
|
||||
target to recurse if desired. */
|
||||
@@ -141,11 +143,9 @@ struct expr_scan_t {
|
||||
virtual void expr_select(const NetESelect*);
|
||||
virtual void expr_sfunc(const NetESFunc*);
|
||||
virtual void expr_signal(const NetESignal*);
|
||||
virtual void expr_subsignal(const NetEBitSel*);
|
||||
virtual void expr_ternary(const NetETernary*);
|
||||
virtual void expr_ufunc(const NetEUFunc*);
|
||||
virtual void expr_unary(const NetEUnary*);
|
||||
virtual void expr_variable(const NetEVariable*);
|
||||
virtual void expr_binary(const NetEBinary*);
|
||||
};
|
||||
|
||||
@@ -153,7 +153,7 @@ struct expr_scan_t {
|
||||
/* The emit functions take a design and emit it to the output stream
|
||||
using the specified target. If the target is given by name, it is
|
||||
located in the target_table and used. */
|
||||
extern bool emit(const Design*des, const char*type);
|
||||
extern int emit(const Design*des, const char*type);
|
||||
|
||||
/* This function takes a fully qualified verilog name (which may have,
|
||||
for example, dots in it) and produces a mangled version that can be
|
||||
@@ -170,6 +170,42 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.74 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.73 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.72 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.71 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.70 2005/02/03 04:56:21 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.69 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.68 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.67 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.66 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.65 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
||||
+10
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: targets.cc,v 1.11 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: targets.cc,v 1.12 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,17 +25,25 @@
|
||||
# include "target.h"
|
||||
|
||||
extern const struct target tgt_dll;
|
||||
#ifdef WITH_T_XNF
|
||||
extern const struct target tgt_xnf;
|
||||
|
||||
#endif
|
||||
|
||||
const struct target *target_table[] = {
|
||||
&tgt_dll,
|
||||
#ifdef WITH_T_XNF
|
||||
&tgt_xnf,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: targets.cc,v $
|
||||
* Revision 1.12 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.11 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+5
-2
@@ -2,7 +2,7 @@
|
||||
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
|
||||
|
||||
Copyright 2001 Stephen Williams
|
||||
$Id: fpga.txt,v 1.11 2003/08/07 05:17:34 steve Exp $
|
||||
$Id: fpga.txt,v 1.12 2005/09/19 21:45:36 steve Exp $
|
||||
|
||||
The FPGA code generator supports a variety of FPGA devices, writing
|
||||
XNF or EDIF depending on the target. You can select the architecture
|
||||
@@ -44,7 +44,7 @@ map to target gates if desired.
|
||||
If this is selected, then the output is formatted as an XNF file,
|
||||
suitable for most any type of device. The devices that it emits
|
||||
are generic devices from the unified library. Some devices are macros,
|
||||
youmay need to further resolve the generated XNF to get working
|
||||
you may need to further resolve the generated XNF to get working
|
||||
code for your part.
|
||||
|
||||
* arch=virtex
|
||||
@@ -188,6 +188,9 @@ Compile a single-file design with command line tools like so:
|
||||
|
||||
---
|
||||
$Log: fpga.txt,v $
|
||||
Revision 1.12 2005/09/19 21:45:36 steve
|
||||
Spelling patches from Larry.
|
||||
|
||||
Revision 1.11 2003/08/07 05:17:34 steve
|
||||
Add arch=lpm to the documentation.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.13 2004/02/10 19:25:01 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.15 2005/03/03 04:34:42 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -52,7 +52,7 @@ dep:
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = stub.o
|
||||
O = stub.o memory.o statement.o
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2005 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,34 +17,18 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PData.cc,v 1.2 2003/11/10 20:11:01 steve Exp $"
|
||||
#ident "$Id: memory.c,v 1.1 2005/03/03 04:34:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "PData.h"
|
||||
# include "config.h"
|
||||
# include "priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
PData::PData(const hname_t&h)
|
||||
: hname_(h)
|
||||
void show_memory(ivl_memory_t mem)
|
||||
{
|
||||
fprintf(out, " mem [%u] %s [%u] <root=%d>\n",
|
||||
ivl_memory_width(mem),
|
||||
ivl_memory_basename(mem),
|
||||
ivl_memory_size(mem),
|
||||
ivl_memory_root(mem));
|
||||
}
|
||||
|
||||
PData::~PData()
|
||||
{
|
||||
}
|
||||
|
||||
const hname_t&PData::name() const
|
||||
{
|
||||
return hname_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PData.cc,v $
|
||||
* Revision 1.2 2003/11/10 20:11:01 steve
|
||||
* missing include of config.h
|
||||
*
|
||||
* Revision 1.1 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: priv.h,v 1.3 2005/03/05 05:47:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include <stdio.h>
|
||||
|
||||
/*
|
||||
* This is the output file where the generated result should be
|
||||
* written.
|
||||
*/
|
||||
extern FILE*out;
|
||||
|
||||
/*
|
||||
* Keep a running count of errors that the stub detects. This will be
|
||||
* the error count returned to the ivl_target environment.
|
||||
*/
|
||||
extern int stub_errors;
|
||||
|
||||
/*
|
||||
* Show the details of the expression.
|
||||
*/
|
||||
extern void show_expression(ivl_expr_t net, unsigned ind);
|
||||
|
||||
extern void show_memory(ivl_memory_t mem);
|
||||
|
||||
/*
|
||||
* Show the statement.
|
||||
*/
|
||||
extern void show_statement(ivl_statement_t net, unsigned ind);
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: statement.c,v 1.9 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
|
||||
{
|
||||
ivl_memory_t mem;
|
||||
unsigned wid = 0;
|
||||
|
||||
if ( (mem = ivl_lval_mem(lval)) ) {
|
||||
|
||||
ivl_scope_t scope = ivl_memory_scope(mem);
|
||||
fprintf(out, "%*s{ %s.%s width=%u }\n", ind, "",
|
||||
ivl_scope_name(scope),
|
||||
ivl_memory_basename(mem),
|
||||
ivl_lval_width(lval));
|
||||
|
||||
fprintf(out, "%*sAddress-0 expression:\n", ind+4, "");
|
||||
show_expression(ivl_lval_idx(lval), ind+8);
|
||||
|
||||
if (ivl_lval_part_off(lval)) {
|
||||
fprintf(out, "%*sPart select base:\n", ind+4, "");
|
||||
show_expression(ivl_lval_part_off(lval), ind+8);
|
||||
}
|
||||
|
||||
/* When the l-value is a memory word, the lval_width
|
||||
must exactly match the word width. */
|
||||
if (ivl_lval_width(lval) != ivl_memory_width(mem)) {
|
||||
fprintf(out, "%*sERROR: l-value width mismatch with "
|
||||
" memory word width=%u\n", ind, "",
|
||||
ivl_memory_width(mem));
|
||||
stub_errors += 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
|
||||
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
|
||||
ind, "",
|
||||
ivl_signal_name(sig),
|
||||
ivl_signal_width(sig),
|
||||
ivl_lval_width(lval));
|
||||
if (ivl_lval_mux(lval)) {
|
||||
fprintf(out, "%*sBit select expression:\n", ind+4, "");
|
||||
show_expression(ivl_lval_mux(lval), ind+8);
|
||||
}
|
||||
if (ivl_lval_part_off(lval)) {
|
||||
fprintf(out, "%*sPart select base:\n", ind+4, "");
|
||||
show_expression(ivl_lval_part_off(lval), ind+8);
|
||||
}
|
||||
|
||||
wid = ivl_lval_width(lval);
|
||||
}
|
||||
|
||||
return wid;
|
||||
}
|
||||
|
||||
static void show_stmt_cassign(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned lwid = 0;
|
||||
|
||||
fprintf(out, "%*sCONTINUOUS ASSIGN <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) {
|
||||
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
}
|
||||
|
||||
fprintf(out, "%*sTotal expected l-value width: %u bits\n",
|
||||
ind+4, "", lwid);
|
||||
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
}
|
||||
|
||||
static void show_stmt_delayx(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
fprintf(out, "%*s#(X) /* calculated delay */\n", ind, "");
|
||||
show_expression(ivl_stmt_delay_expr(net), ind+4);
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
}
|
||||
|
||||
static void show_stmt_force(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned lwid = 0;
|
||||
|
||||
fprintf(out, "%*sforce <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) {
|
||||
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
}
|
||||
|
||||
fprintf(out, "%*sTotal expected l-value width: %u bits\n",
|
||||
ind+4, "", lwid);
|
||||
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
}
|
||||
|
||||
static void show_stmt_release(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned lwid = 0;
|
||||
|
||||
fprintf(out, "%*srelease <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1) {
|
||||
lwid += show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
}
|
||||
|
||||
fprintf(out, "%*sTotal l-value width: %u bits\n",
|
||||
ind+4, "", lwid);
|
||||
}
|
||||
|
||||
/*
|
||||
* A trigger statement is the "-> name;" syntax in verilog, where a
|
||||
* trigger signal is sent to a named event. The trigger statement is
|
||||
* actually a very simple object.
|
||||
*/
|
||||
static void show_stmt_trigger(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
unsigned cnt = ivl_stmt_nevent(net);
|
||||
unsigned idx;
|
||||
|
||||
fprintf(out, "%*s->", ind, "");
|
||||
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
ivl_event_t event = ivl_stmt_events(net, idx);
|
||||
fprintf(out, " %s", ivl_event_basename(event));
|
||||
}
|
||||
|
||||
/* The compiler should make exactly one target event, so if we
|
||||
find more or less, then print some error text. */
|
||||
if (cnt != 1) {
|
||||
fprintf(out, " /* ERROR: Expect one target event, got %u */", cnt);
|
||||
}
|
||||
|
||||
fprintf(out, ";\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* The wait statement contains simply an array of events to wait on,
|
||||
* and a sub-statement to execute when an event triggers.
|
||||
*/
|
||||
void show_stmt_wait(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
const char*comma = "";
|
||||
fprintf(out, "%*s@(", ind, "");
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_nevent(net) ; idx += 1) {
|
||||
ivl_event_t evnt = ivl_stmt_events(net, idx);
|
||||
|
||||
if (evnt == 0)
|
||||
fprintf(out, "%s/*ERROR*/", comma);
|
||||
else
|
||||
fprintf(out, "%s%s.%s", comma,
|
||||
ivl_scope_name(ivl_event_scope(evnt)),
|
||||
ivl_event_basename(evnt));
|
||||
|
||||
comma = ", ";
|
||||
}
|
||||
|
||||
fprintf(out, ")\n");
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+4);
|
||||
}
|
||||
|
||||
void show_statement(ivl_statement_t net, unsigned ind)
|
||||
{
|
||||
unsigned idx;
|
||||
const ivl_statement_type_t code = ivl_statement_type(net);
|
||||
|
||||
switch (code) {
|
||||
|
||||
case IVL_ST_ASSIGN:
|
||||
fprintf(out, "%*sASSIGN <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
||||
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
|
||||
if (ivl_stmt_delay_expr(net))
|
||||
show_expression(ivl_stmt_delay_expr(net), idx+4);
|
||||
|
||||
if (ivl_stmt_rval(net))
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_ST_ASSIGN_NB:
|
||||
fprintf(out, "%*sASSIGN_NB <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
||||
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
|
||||
if (ivl_stmt_delay_expr(net)) {
|
||||
fprintf(out, "%*s<internal delay>\n", ind+4, "");
|
||||
show_expression(ivl_stmt_delay_expr(net), ind+6);
|
||||
}
|
||||
|
||||
if (ivl_stmt_rval(net))
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_ST_BLOCK: {
|
||||
unsigned cnt = ivl_stmt_block_count(net);
|
||||
ivl_scope_t sscope = ivl_stmt_block_scope(net);
|
||||
if (sscope)
|
||||
fprintf(out, "%*sbegin : %s\n", ind, "",
|
||||
ivl_scope_name(sscope));
|
||||
else
|
||||
fprintf(out, "%*sbegin\n", ind, "");
|
||||
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
ivl_statement_t cur = ivl_stmt_block_stmt(net, idx);
|
||||
show_statement(cur, ind+4);
|
||||
}
|
||||
fprintf(out, "%*send\n", ind, "");
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
case IVL_ST_CASER:
|
||||
case IVL_ST_CASE: {
|
||||
unsigned cnt = ivl_stmt_case_count(net);
|
||||
unsigned idx;
|
||||
fprintf(out, "%*scase (...) <%u cases>\n", ind, "", cnt);
|
||||
show_expression(ivl_stmt_cond_expr(net), ind+4);
|
||||
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
ivl_expr_t ex = ivl_stmt_case_expr(net, idx);
|
||||
ivl_statement_t st = ivl_stmt_case_stmt(net, idx);
|
||||
if (ex == 0)
|
||||
fprintf(out, "%*sdefault\n", ind+4, "");
|
||||
else
|
||||
show_expression(ex, ind+4);
|
||||
|
||||
show_statement(st, ind+4);
|
||||
}
|
||||
|
||||
fprintf(out, "%*sendcase\n", ind, "");
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_CASSIGN:
|
||||
show_stmt_cassign(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_CONDIT: {
|
||||
ivl_expr_t ex = ivl_stmt_cond_expr(net);
|
||||
ivl_statement_t t = ivl_stmt_cond_true(net);
|
||||
ivl_statement_t f = ivl_stmt_cond_false(net);
|
||||
|
||||
fprintf(out, "%*sif (...)\n", ind, "");
|
||||
show_expression(ex, ind+4);
|
||||
if (t)
|
||||
show_statement(t, ind+4);
|
||||
else
|
||||
fprintf(out, "%*s;\n", ind+4, "");
|
||||
|
||||
if (f) {
|
||||
fprintf(out, "%*selse\n", ind, "");
|
||||
show_statement(f, ind+4);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_DEASSIGN:
|
||||
fprintf(out, "%*sDEASSIGN <lwidth=%u>\n", ind, "",
|
||||
ivl_stmt_lwidth(net));
|
||||
|
||||
for (idx = 0 ; idx < ivl_stmt_lvals(net) ; idx += 1)
|
||||
show_assign_lval(ivl_stmt_lval(net, idx), ind+4);
|
||||
|
||||
break;
|
||||
|
||||
case IVL_ST_DELAY:
|
||||
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
break;
|
||||
|
||||
case IVL_ST_DELAYX:
|
||||
show_stmt_delayx(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_FORCE:
|
||||
show_stmt_force(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_FORK: {
|
||||
unsigned cnt = ivl_stmt_block_count(net);
|
||||
fprintf(out, "%*sfork\n", ind, "");
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
ivl_statement_t cur = ivl_stmt_block_stmt(net, idx);
|
||||
show_statement(cur, ind+4);
|
||||
}
|
||||
fprintf(out, "%*sjoin\n", ind, "");
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_NOOP:
|
||||
fprintf(out, "%*s/* noop */;\n", ind, "");
|
||||
break;
|
||||
|
||||
case IVL_ST_RELEASE:
|
||||
show_stmt_release(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_STASK: {
|
||||
fprintf(out, "%*sCall %s(%u parameters);\n", ind, "",
|
||||
ivl_stmt_name(net), ivl_stmt_parm_count(net));
|
||||
for (idx = 0 ; idx < ivl_stmt_parm_count(net) ; idx += 1)
|
||||
if (ivl_stmt_parm(net, idx))
|
||||
show_expression(ivl_stmt_parm(net, idx), ind+4);
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_TRIGGER:
|
||||
show_stmt_trigger(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_UTASK:
|
||||
fprintf(out, "%*scall task ...\n", ind, "");
|
||||
break;
|
||||
|
||||
case IVL_ST_WAIT:
|
||||
show_stmt_wait(net, ind);
|
||||
break;
|
||||
|
||||
case IVL_ST_WHILE:
|
||||
fprintf(out, "%*swhile\n", ind, "");
|
||||
show_expression(ivl_stmt_cond_expr(net), ind+4);
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(out, "%*sunknown statement type (%u)\n", ind, "", code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
+1278
-504
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
@@ -6,3 +6,5 @@ config.log
|
||||
autom4te.cache
|
||||
dep
|
||||
vvp.tgt
|
||||
vvp.conf
|
||||
vvp-s.conf
|
||||
|
||||
+3
-2
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.22 2004/02/10 19:25:01 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.24 2005/09/14 02:53:15 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -51,7 +51,8 @@ dep:
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvp.o draw_mux.o draw_vpi.o eval_expr.o eval_real.o vector.o \
|
||||
O = vvp.o draw_mux.o draw_ufunc.o draw_vpi.o eval_bool.o eval_expr.o \
|
||||
eval_real.o vector.o \
|
||||
vvp_process.o vvp_scope.o
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
|
||||
@@ -13,7 +13,7 @@ AC_CANONICAL_HOST
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
AC_CHECK_HEADERS(malloc.h stdint.h)
|
||||
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
+94
-132
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_mux.c,v 1.7 2003/12/19 01:27:10 steve Exp $"
|
||||
#ident "$Id: draw_mux.c,v 1.13 2005/10/12 17:26:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -28,163 +28,125 @@
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
/*
|
||||
* This draws a general mux, a slice at a time. Use MUXX so that
|
||||
* unknows lead to unknown output.
|
||||
*/
|
||||
static void draw_lpm_mux_bitslice(ivl_lpm_t net, unsigned slice)
|
||||
{
|
||||
unsigned sel = ivl_lpm_selects(net);
|
||||
unsigned size = ivl_lpm_size(net);
|
||||
unsigned sel_from_size;
|
||||
unsigned seldx, idx;
|
||||
ivl_nexus_t s;
|
||||
|
||||
sel_from_size = 0;
|
||||
seldx = size - 1;
|
||||
while (seldx > 0) {
|
||||
seldx >>= 1;
|
||||
sel_from_size += 1;
|
||||
}
|
||||
if (sel_from_size > sel) {
|
||||
fprintf(stderr, "internal error: MUX size=%u, selects=%u\n",
|
||||
size, sel);
|
||||
}
|
||||
assert(sel_from_size <= sel);
|
||||
|
||||
s = ivl_lpm_select(net, 0);
|
||||
|
||||
/* Draw the leaf mux devices that take inputs from the
|
||||
net. These also use up the least significant bit of the
|
||||
select vector. */
|
||||
for (idx = 0 ; idx < size ; idx += 2) {
|
||||
|
||||
fprintf(vvp_out, "L_%s.%s/%u/%u/%u .functor MUXX, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)), slice, sel, idx);
|
||||
|
||||
{
|
||||
ivl_nexus_t a = ivl_lpm_data2(net, idx+0, slice);
|
||||
draw_input_from_net(a);
|
||||
fprintf(vvp_out, ", ");
|
||||
}
|
||||
|
||||
if ((idx+1) < size) {
|
||||
ivl_nexus_t b = ivl_lpm_data2(net, idx+1, slice);
|
||||
draw_input_from_net(b);
|
||||
fprintf(vvp_out, ", ");
|
||||
} else {
|
||||
fprintf(vvp_out, "C<x>, ");
|
||||
}
|
||||
|
||||
draw_input_from_net(s);
|
||||
fprintf(vvp_out, ", C<1>;\n");
|
||||
}
|
||||
|
||||
/* Draw the tree of MUXX devices to connect the inner tree
|
||||
nodes. */
|
||||
for (seldx = 1 ; seldx < (sel-1) ; seldx += 1) {
|
||||
unsigned level = sel - seldx;
|
||||
unsigned span = 2 << seldx;
|
||||
s = ivl_lpm_select(net, seldx);
|
||||
|
||||
for (idx = 0 ; idx < size ; idx += span) {
|
||||
fprintf(vvp_out, "L_%s.%s/%u/%u/%u .functor MUXX, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)),
|
||||
slice, level, idx);
|
||||
|
||||
fprintf(vvp_out, "L_%s.%s/%u/%u/%u, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)),
|
||||
slice, level+1, idx);
|
||||
|
||||
if ((idx + span/2) < size) {
|
||||
fprintf(vvp_out, "L_%s.%s/%u/%u/%u, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)),
|
||||
slice, level+1, idx+span/2);
|
||||
} else {
|
||||
fprintf(vvp_out, "C<x>, ");
|
||||
}
|
||||
|
||||
draw_input_from_net(s);
|
||||
fprintf(vvp_out, ", C<1>;\n");
|
||||
}
|
||||
}
|
||||
|
||||
s = ivl_lpm_select(net, sel-1);
|
||||
|
||||
fprintf(vvp_out, "L_%s.%s/%u .functor MUXX, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)), slice);
|
||||
|
||||
fprintf(vvp_out, "L_%s.%s/%u/2/0, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)), slice);
|
||||
|
||||
|
||||
if ((2U << (sel-1))/2 < size) {
|
||||
fprintf(vvp_out, "L_%s.%s/%u/2/%u, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)),
|
||||
slice, (2U << (sel-1))/2);
|
||||
} else {
|
||||
fprintf(vvp_out, "C<x>, ");
|
||||
}
|
||||
|
||||
draw_input_from_net(s);
|
||||
fprintf(vvp_out, ", C<1>;\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* This draws a simple A/B mux. The mux can have any width, enough
|
||||
* MUXZ nodes are created to support the vector.
|
||||
*/
|
||||
static void draw_lpm_mux_ab(ivl_lpm_t net)
|
||||
static void draw_lpm_mux_ab(ivl_lpm_t net, const char*muxz)
|
||||
{
|
||||
ivl_nexus_t s;
|
||||
unsigned idx, width;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
|
||||
/* Only support A-B muxes at this oint. */
|
||||
/* Only support A-B muxes in this function. */
|
||||
assert(ivl_lpm_size(net) == 2);
|
||||
assert(ivl_lpm_selects(net) == 1);
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
s = ivl_lpm_select(net, 0);
|
||||
fprintf(vvp_out, "L_%p .functor %s %u", net, muxz, width);
|
||||
fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_data(net,0)));
|
||||
fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_data(net,1)));
|
||||
fprintf(vvp_out, ", %s", draw_input_from_net(ivl_lpm_select(net)));
|
||||
fprintf(vvp_out, ", C4<>;\n");
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t a = ivl_lpm_data2(net, 0, idx);
|
||||
ivl_nexus_t b = ivl_lpm_data2(net, 1, idx);
|
||||
fprintf(vvp_out, "L_%s.%s/%u .functor MUXZ, ",
|
||||
vvp_mangle_id(ivl_scope_name(ivl_lpm_scope(net))),
|
||||
vvp_mangle_id(ivl_lpm_basename(net)), idx);
|
||||
draw_input_from_net(a);
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(b);
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(s);
|
||||
fprintf(vvp_out, ", C<1>;\n");
|
||||
static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz)
|
||||
{
|
||||
int idx, level;
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned swidth = ivl_lpm_selects(net);
|
||||
char*select_input;
|
||||
|
||||
assert(ivl_lpm_size(net) == (1 << swidth));
|
||||
|
||||
select_input = strdup(draw_net_input(ivl_lpm_select(net)));
|
||||
|
||||
fprintf(vvp_out, "L_%p/0s .part %s, 0, 1; Bit 0 of the select\n",
|
||||
net, select_input);
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 2) {
|
||||
fprintf(vvp_out, "L_%p/0/%d .functor %s %u",
|
||||
net, idx/2, muxz, width);
|
||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx+0)));
|
||||
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx+1)));
|
||||
fprintf(vvp_out, ", L_%p/0s, C4<>;\n", net);
|
||||
}
|
||||
|
||||
for (level = 1 ; level < swidth-1 ; level += 1) {
|
||||
fprintf(vvp_out, "L_%p/%ds .part %s, %d, 1;\n",
|
||||
net, level, select_input, level);
|
||||
|
||||
for (idx = 0 ; idx < (ivl_lpm_size(net) >> level); idx += 2) {
|
||||
fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
|
||||
net, width, level, muxz, idx);
|
||||
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+0);
|
||||
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+1);
|
||||
fprintf(vvp_out, ", L_%p/%ds", net, level);
|
||||
fprintf(vvp_out, ", C4<>;\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fprintf(vvp_out, "L_%p/%ds .part %s, %d, 1; Bit %d of the select\n",
|
||||
net, swidth-1, select_input, swidth-1, swidth-1);
|
||||
|
||||
|
||||
fprintf(vvp_out, "L_%p .functor %s %u", net, muxz, width);
|
||||
fprintf(vvp_out, ", L_%p/%d/0", net, swidth-2);
|
||||
fprintf(vvp_out, ", L_%p/%d/1", net, swidth-2);
|
||||
fprintf(vvp_out, ", L_%p/%ds", net, swidth-1);
|
||||
fprintf(vvp_out, ", C4<>;\n");
|
||||
|
||||
free(select_input);
|
||||
}
|
||||
|
||||
void draw_lpm_mux(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
const char*muxz = "MUXZ";
|
||||
|
||||
/* The output of the mux defines the type of the mux. the
|
||||
ivl_target should guarantee that all the inputs are the
|
||||
same type as the output. */
|
||||
switch (data_type_of_nexus(ivl_lpm_q(net,0))) {
|
||||
case IVL_VT_REAL:
|
||||
muxz = "MUXR";
|
||||
break;
|
||||
default:
|
||||
muxz = "MUXZ";
|
||||
break;
|
||||
}
|
||||
|
||||
if ((ivl_lpm_size(net) == 2) && (ivl_lpm_selects(net) == 1)) {
|
||||
draw_lpm_mux_ab(net);
|
||||
draw_lpm_mux_ab(net, muxz);
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1)
|
||||
draw_lpm_mux_bitslice(net, idx);
|
||||
|
||||
/* Here we are at the worst case, we generate a tree of MUXZ
|
||||
devices to handle the arbitrary size. */
|
||||
draw_lpm_mux_nest(net, muxz);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: draw_mux.c,v $
|
||||
* Revision 1.13 2005/10/12 17:26:17 steve
|
||||
* MUX nodes get inputs from nets, not from net inputs,
|
||||
* Detect and draw alias nodes to reduce net size and
|
||||
* handle force confusion.
|
||||
*
|
||||
* Revision 1.12 2005/09/01 04:11:37 steve
|
||||
* Generate code to handle real valued muxes.
|
||||
*
|
||||
* Revision 1.11 2005/08/27 04:32:08 steve
|
||||
* Handle synthesis of fully packed case statements.
|
||||
*
|
||||
* Revision 1.10 2005/06/17 03:46:52 steve
|
||||
* Make functors know their own width.
|
||||
*
|
||||
* Revision 1.9 2005/04/06 05:29:09 steve
|
||||
* Rework NetRamDq and IVL_LPM_RAM nodes.
|
||||
*
|
||||
* Revision 1.8 2005/02/12 22:54:29 steve
|
||||
* Implement a-b muxes as vector devices
|
||||
*
|
||||
* Revision 1.7 2003/12/19 01:27:10 steve
|
||||
* Fix various unsigned compare warnings.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_ufunc.c,v 1.1 2005/07/13 04:52:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
|
||||
assert(res.wid <= ivl_signal_width(port));
|
||||
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
|
||||
vvp_signal_label(port), res.base, res.wid);
|
||||
|
||||
clr_vector(res);
|
||||
}
|
||||
|
||||
static void function_argument_real(ivl_signal_t port, ivl_expr_t exp)
|
||||
{
|
||||
int res = draw_eval_real(exp);
|
||||
|
||||
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
|
||||
vvp_signal_label(port), res);
|
||||
}
|
||||
|
||||
static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp)
|
||||
{
|
||||
ivl_variable_type_t dtype = ivl_signal_data_type(port);
|
||||
switch (dtype) {
|
||||
case IVL_VT_LOGIC:
|
||||
function_argument_logic(port, exp);
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
function_argument_real(port, exp);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
|
||||
ivl_signal_basename(port), dtype);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A call to a user defined function generates a result that is the
|
||||
* result of this expression.
|
||||
*
|
||||
* The result of the function is placed by the function execution into
|
||||
* a signal within the scope of the function that also has a basename
|
||||
* the same as the function. The ivl_target API handled the result
|
||||
* mapping already, and we get the name of the result signal as
|
||||
* parameter 0 of the function definition.
|
||||
*/
|
||||
|
||||
struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_scope_t def = ivl_expr_def(exp);
|
||||
ivl_signal_t retval = ivl_scope_port(def, 0);
|
||||
struct vector_info res;
|
||||
|
||||
/* evaluate the expressions and send the results to the
|
||||
function ports. */
|
||||
|
||||
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
|
||||
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx+1);
|
||||
draw_function_argument(port, ivl_expr_parm(exp,idx));
|
||||
}
|
||||
|
||||
|
||||
/* Call the function */
|
||||
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
|
||||
fprintf(vvp_out, ", S_%p;\n", def);
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
|
||||
/* Fresh basic block starts after the join. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
/* The return value is in a signal that has the name of the
|
||||
expression. Load that into the thread and return the
|
||||
vector result. */
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
{ unsigned load_wid = swid;
|
||||
if (load_wid > ivl_signal_width(retval))
|
||||
load_wid = ivl_signal_width(retval);
|
||||
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
|
||||
res.base, vvp_signal_label(retval), load_wid);
|
||||
|
||||
if (load_wid < swid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+load_wid, swid-load_wid);
|
||||
}
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, wid-swid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int draw_ufunc_real(ivl_expr_t exp)
|
||||
{
|
||||
ivl_scope_t def = ivl_expr_def(exp);
|
||||
ivl_signal_t retval = ivl_scope_port(def, 0);
|
||||
int res = 0;
|
||||
int idx;
|
||||
|
||||
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
|
||||
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx+1);
|
||||
draw_function_argument(port, ivl_expr_parm(exp,idx));
|
||||
}
|
||||
|
||||
|
||||
/* Call the function */
|
||||
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
|
||||
fprintf(vvp_out, ", S_%p;\n", def);
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
|
||||
/* Load the result into a word. */
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
|
||||
res, vvp_signal_label(retval));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
+21
-12
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: draw_vpi.c,v 1.9 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: draw_vpi.c,v 1.13 2005/10/11 18:30:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -79,7 +79,6 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||
case IVL_EX_STRING:
|
||||
case IVL_EX_EVENT:
|
||||
case IVL_EX_SCOPE:
|
||||
case IVL_EX_VARIABLE:
|
||||
continue;
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
@@ -102,7 +101,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||
it as I'll be passing the handle to the signal
|
||||
itself. */
|
||||
if (ivl_expr_width(expr) !=
|
||||
ivl_signal_pins(ivl_expr_signal(expr))) {
|
||||
ivl_signal_width(ivl_expr_signal(expr))) {
|
||||
break;
|
||||
|
||||
} else if (ivl_expr_signed(expr) !=
|
||||
@@ -170,7 +169,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||
calculated above. Otherwise, just pass the
|
||||
signal. */
|
||||
if (ivl_expr_width(expr) !=
|
||||
ivl_signal_pins(ivl_expr_signal(expr))) {
|
||||
ivl_signal_width(ivl_expr_signal(expr))) {
|
||||
break;
|
||||
|
||||
} else if (ivl_expr_signed(expr) !=
|
||||
@@ -182,12 +181,9 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||
vvp_signal_label(ivl_expr_signal(expr)));
|
||||
continue;
|
||||
}
|
||||
|
||||
case IVL_EX_VARIABLE: {
|
||||
ivl_variable_t var = ivl_expr_variable(expr);
|
||||
fprintf(vvp_out, ", W_%s", vvp_word_label(var));
|
||||
continue;
|
||||
}
|
||||
fprintf(vvp_out, ", V_%s",
|
||||
vvp_signal_label(ivl_expr_signal(expr)));
|
||||
continue;
|
||||
|
||||
case IVL_EX_STRING:
|
||||
if (( par = ivl_expr_parameter(expr) )) {
|
||||
@@ -216,8 +212,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
|
||||
|
||||
case IVL_EX_MEMORY:
|
||||
if (!ivl_expr_oper1(expr)) {
|
||||
fprintf(vvp_out, ", M_%s",
|
||||
vvp_memory_label(ivl_expr_memory(expr)));
|
||||
fprintf(vvp_out, ", M_%p", ivl_expr_memory(expr)) ;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -296,6 +291,20 @@ int draw_vpi_rfunc_call(ivl_expr_t fnet)
|
||||
|
||||
/*
|
||||
* $Log: draw_vpi.c,v $
|
||||
* Revision 1.13 2005/10/11 18:30:50 steve
|
||||
* Remove obsolete vvp_memory_label function.
|
||||
*
|
||||
* Revision 1.12 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.11 2005/06/18 15:55:21 steve
|
||||
* Handle signed display of unsigned signals.
|
||||
*
|
||||
* Revision 1.10 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.9 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: eval_bool.c,v 1.4 2005/12/07 03:43:30 steve Exp $"
|
||||
|
||||
/*
|
||||
* This file includes functions for evaluating REAL expressions.
|
||||
*/
|
||||
# include "vvp_config.h"
|
||||
# include "vvp_priv.h"
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
# include <math.h>
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* Evaluate the bool64 the hard way, by evaluating the logic vector
|
||||
* and converting it to a bool64.
|
||||
*/
|
||||
static int eval_bool64_logic(ivl_expr_t exp)
|
||||
{
|
||||
int res;
|
||||
struct vector_info tmp;
|
||||
|
||||
tmp = draw_eval_expr(exp, STUFF_OK_XZ);
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/get %d, %u, %u;\n", res, tmp.base, tmp.wid);
|
||||
clr_vector(tmp);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int draw_number_bool64(ivl_expr_t exp)
|
||||
{
|
||||
int res;
|
||||
const char*bits = ivl_expr_bits(exp);
|
||||
uint64_t val = 0;
|
||||
unsigned long idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_expr_width(exp) ; idx += 1) {
|
||||
if (bits[idx] == '1')
|
||||
val |= 1UL << idx;
|
||||
}
|
||||
|
||||
res = allocate_word();
|
||||
fprintf(vvp_out, " %%ix/load %d, %lu;\n", res, val);
|
||||
return res;
|
||||
}
|
||||
|
||||
int draw_eval_bool64(ivl_expr_t exp)
|
||||
{
|
||||
int res;
|
||||
|
||||
switch (ivl_expr_type(exp)) {
|
||||
case IVL_EX_NUMBER:
|
||||
res = draw_number_bool64(exp);
|
||||
break;
|
||||
default:
|
||||
res = eval_bool64_logic(exp);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_bool.c,v $
|
||||
* Revision 1.4 2005/12/07 03:43:30 steve
|
||||
* Include stdint.h if it is present.
|
||||
*
|
||||
* Revision 1.3 2005/12/05 21:20:55 steve
|
||||
* Some systems donot have stding.h?
|
||||
*
|
||||
* Revision 1.2 2005/09/19 20:17:59 steve
|
||||
* Include vvp_config.h instead of config.h
|
||||
*
|
||||
* Revision 1.1 2005/09/14 02:53:15 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
*/
|
||||
|
||||
+322
-186
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_expr.c,v 1.110 2004/10/04 01:10:57 steve Exp $"
|
||||
#ident "$Id: eval_expr.c,v 1.130 2006/02/02 02:43:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -57,7 +57,9 @@ int number_is_immediate(ivl_expr_t ex, unsigned lim_wid)
|
||||
const char*bits;
|
||||
unsigned idx;
|
||||
|
||||
assert(ivl_expr_type(ex) == IVL_EX_NUMBER);
|
||||
if (ivl_expr_type(ex) != IVL_EX_NUMBER
|
||||
&& ivl_expr_type(ex) != IVL_EX_ULONG)
|
||||
return 0;
|
||||
|
||||
bits = ivl_expr_bits(ex);
|
||||
for (idx = lim_wid ; idx < ivl_expr_width(ex) ; idx += 1)
|
||||
@@ -99,6 +101,38 @@ unsigned long get_number_immediate(ivl_expr_t ex)
|
||||
return imm;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function, in addition to setting the value into index 0, sets
|
||||
* bit 4 to 1 if the value is unknown.
|
||||
*/
|
||||
void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
|
||||
{
|
||||
struct vector_info vec;
|
||||
int word;
|
||||
|
||||
switch (ivl_expr_value(expr)) {
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
vec = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
|
||||
ix, vec.base, vec.wid);
|
||||
clr_vector(vec);
|
||||
break;
|
||||
|
||||
case IVL_VT_REAL:
|
||||
word = draw_eval_real(expr);
|
||||
clr_word(word);
|
||||
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "XXXX ivl_expr_value == %d\n",
|
||||
ivl_expr_value(expr));
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The STUFF_OK_XZ bit is true if the output is going to be further
|
||||
* processed so that x and z values are equivilent. This may allow for
|
||||
@@ -265,15 +299,17 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
|
||||
&& number_is_immediate(re, 16))
|
||||
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
|
||||
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
|
||||
assert(ivl_expr_value(le) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(le) == IVL_VT_BOOL);
|
||||
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(re) == IVL_VT_BOOL);
|
||||
|
||||
wid = ivl_expr_width(le);
|
||||
if (ivl_expr_width(re) > wid)
|
||||
wid = ivl_expr_width(re);
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&STUFF_OK_XZ);
|
||||
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&~STUFF_OK_47);
|
||||
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&~STUFF_OK_47);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'E': /* === */
|
||||
@@ -556,6 +592,63 @@ static struct vector_info draw_binary_expr_le_real(ivl_expr_t exp)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le_bool(ivl_expr_t exp,
|
||||
unsigned wid)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
|
||||
int lw, rw;
|
||||
struct vector_info tmp;
|
||||
|
||||
char s_flag = (ivl_expr_signed(le) && ivl_expr_signed(re)) ? 's' : 'u';
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_BOOL);
|
||||
assert(ivl_expr_value(re) == IVL_VT_BOOL);
|
||||
|
||||
lw = draw_eval_bool64(le);
|
||||
rw = draw_eval_bool64(re);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'G':
|
||||
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, rw, lw);
|
||||
fprintf(vvp_out, " %%or 5, 4, 1;\n");
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, lw, rw);
|
||||
fprintf(vvp_out, " %%or 5, 4, 1;\n");
|
||||
break;
|
||||
|
||||
case '<':
|
||||
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, lw, rw);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
fprintf(vvp_out, " %%cmp/w%c %u, %u;\n", s_flag, rw, lw);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
clr_word(lw);
|
||||
clr_word(rw);
|
||||
|
||||
/* Move the result out out the 4-7 bit that the compare
|
||||
uses. This is because that bit may be clobbered by other
|
||||
expressions. */
|
||||
{ unsigned base = allocate_vector(wid);
|
||||
fprintf(vvp_out, " %%mov %u, 5, 1;\n", base);
|
||||
tmp.base = base;
|
||||
tmp.wid = wid;
|
||||
if (wid > 1)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, wid-1);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
|
||||
unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
@@ -578,8 +671,17 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
|
||||
if (ivl_expr_value(re) == IVL_VT_REAL)
|
||||
return draw_binary_expr_le_real(exp);
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_VECTOR);
|
||||
assert(ivl_expr_value(re) == IVL_VT_VECTOR);
|
||||
/* Detect the special case that we can do this with integers. */
|
||||
if (ivl_expr_value(le) == IVL_VT_BOOL
|
||||
&& ivl_expr_value(re) == IVL_VT_BOOL
|
||||
&& owid < 64) {
|
||||
return draw_binary_expr_le_bool(exp, wid);
|
||||
}
|
||||
|
||||
assert(ivl_expr_value(le) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(le) == IVL_VT_BOOL);
|
||||
assert(ivl_expr_value(re) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(re) == IVL_VT_BOOL);
|
||||
|
||||
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
|
||||
@@ -989,7 +1091,7 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
||||
return draw_mul_immediate(le, re, wid);
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ|STUFF_OK_RO);
|
||||
|
||||
if (lv.wid != wid) {
|
||||
fprintf(stderr, "XXXX ivl_expr_opcode(exp) = %c,"
|
||||
@@ -1125,49 +1227,19 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp,
|
||||
return rv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
ivl_expr_t sel = ivl_expr_oper1(exp);
|
||||
|
||||
/* Evaluate the bit select expression and save the result into
|
||||
index register 0. */
|
||||
res = draw_eval_expr(sel, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u,%u;\n", res.base, res.wid);
|
||||
clr_vector(res);
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
switch (ivl_signal_type(sig)) {
|
||||
case IVL_SIT_TRI:
|
||||
case IVL_SIT_TRI0:
|
||||
case IVL_SIT_TRI1:
|
||||
fprintf(vvp_out, " %%load/nx %u, V_%s, 0;\n", res.base,
|
||||
vvp_signal_label(sig));
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, " %%load/x %u, V_%s, 0;\n", res.base,
|
||||
vvp_signal_label(sig));
|
||||
break;
|
||||
}
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* The concatenation operator is evaluated by evaluating each sub-
|
||||
* expression, then copying it into the continguous vector of the
|
||||
* result. Do this until the result vector is filled.
|
||||
*/
|
||||
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
|
||||
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
unsigned off, rep;
|
||||
struct vector_info res;
|
||||
|
||||
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;
|
||||
|
||||
/* Allocate a vector to hold the result. */
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
@@ -1197,7 +1269,7 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
/* Try to locate the subexpression in the
|
||||
lookaside map. */
|
||||
avec.base = allocate_vector_exp(arg, awid);
|
||||
avec.base = allocate_vector_exp(arg, awid, alloc_exclusive);
|
||||
avec.wid = awid;
|
||||
|
||||
trans = awid;
|
||||
@@ -1281,6 +1353,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||
case 'z':
|
||||
res.base = 3;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
res.base = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -1457,29 +1532,15 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
||||
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned lsi = ivl_expr_lsi(exp);
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
|
||||
if (swid > res.wid)
|
||||
swid = res.wid;
|
||||
|
||||
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
||||
/* If this is a REG (a variable) then I can do a vector
|
||||
read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
|
||||
res.base, vvp_signal_label(sig), lsi, swid);
|
||||
|
||||
} else {
|
||||
/* Vector reads of nets do not in general work because
|
||||
they are not really functors but references to
|
||||
scattered functors. So generate an array of loads. */
|
||||
for (idx = 0 ; idx < swid ; idx += 1) {
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, vvp_signal_label(sig), idx+lsi);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a REG (a variable) then I can do a vector read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
|
||||
res.base, vvp_signal_label(sig), swid);
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < res.wid) {
|
||||
@@ -1496,15 +1557,21 @@ static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
|
||||
}
|
||||
}
|
||||
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO) ? 0 : 1;
|
||||
|
||||
/* Already in the vector lookaside? */
|
||||
res.base = allocate_vector_exp(exp, wid);
|
||||
res.base = allocate_vector_exp(exp, wid, alloc_exclusive);
|
||||
res.wid = wid;
|
||||
if (res.base != 0)
|
||||
if (res.base != 0) {
|
||||
fprintf(vvp_out, "; Reuse signal base=%u wid=%u from lookaside.\n",
|
||||
res.base, res.wid);
|
||||
return res;
|
||||
}
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
@@ -1514,11 +1581,14 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw code to evaluate a memory word index expression and write the
|
||||
* value into index register 3. This expression converts the run-time
|
||||
* calculated value to canonical form that the %load/mv takes.
|
||||
*/
|
||||
void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
|
||||
{
|
||||
int root = ivl_memory_root(mem);
|
||||
unsigned width = ivl_memory_width(mem);
|
||||
width = (width+3) & ~3;
|
||||
|
||||
switch (ivl_expr_type(ae)) {
|
||||
case IVL_EX_NUMBER: {
|
||||
@@ -1540,14 +1610,14 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
|
||||
unknown_flag = 1;
|
||||
break;
|
||||
}
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu;\n", (v-root)*width);
|
||||
fprintf(vvp_out, " %%ix/load 3, %lu;\n", v-root);
|
||||
fprintf(vvp_out, " %%mov 4, %c, 1;\n",
|
||||
unknown_flag?'1':'0');
|
||||
break;
|
||||
}
|
||||
case IVL_EX_ULONG: {
|
||||
unsigned v = ivl_expr_uvalue(ae);
|
||||
fprintf(vvp_out, " %%ix/load 3, %u;\n", (v-root)*width);
|
||||
fprintf(vvp_out, " %%ix/load 3, %u;\n", v-root);
|
||||
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
|
||||
break;
|
||||
}
|
||||
@@ -1558,8 +1628,6 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
|
||||
clr_vector(addr);
|
||||
if (root>0)
|
||||
fprintf(vvp_out, " %%ix/sub 3, %u;\n", root);
|
||||
if (width>1)
|
||||
fprintf(vvp_out, " %%ix/mul 3, %u;\n", width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1570,7 +1638,6 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_memory_t mem = ivl_expr_memory(exp);
|
||||
struct vector_info res;
|
||||
unsigned idx;
|
||||
|
||||
draw_memory_index_expr(mem, ivl_expr_oper1(exp));
|
||||
|
||||
@@ -1580,12 +1647,8 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
for (idx = 0 ; idx < swid ; idx += 1) {
|
||||
if (idx)
|
||||
fprintf(vvp_out, " %%ix/add 3, 1;\n");
|
||||
fprintf(vvp_out, " %%load/m %u, M_%s;\n",
|
||||
res.base+idx, vvp_memory_label(mem));
|
||||
}
|
||||
fprintf(vvp_out, " %%load/mv %u, M_%p, %u;\n",
|
||||
res.base, mem, swid);
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < wid)
|
||||
@@ -1598,12 +1661,104 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
static struct vector_info draw_select_signal(ivl_expr_t sube,
|
||||
ivl_expr_t bit_idx,
|
||||
unsigned bit_wid,
|
||||
unsigned wid)
|
||||
{
|
||||
ivl_signal_t sig = ivl_expr_signal(sube);
|
||||
struct vector_info shiv;
|
||||
struct vector_info res;
|
||||
unsigned idx;
|
||||
|
||||
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
|
||||
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
if (shiv.base >= 8)
|
||||
clr_vector(shiv);
|
||||
|
||||
/* Try the special case that the base is 0 and the width
|
||||
exactly matches the signal. Just load the signal in one
|
||||
instruction. */
|
||||
if (shiv.base == 0 && ivl_expr_width(sube) == wid) {
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
fprintf(vvp_out, " %%load/v %u, V_%p, %u;\n",
|
||||
res.base, sig, ivl_expr_width(sube));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Try the special case that hte part is at the beginning and
|
||||
nearly the width of the signal. In this case, just load the
|
||||
entire signal in one go then simply drop the excess bits. */
|
||||
if (shiv.base == 0
|
||||
&& (ivl_expr_width(sube) > wid)
|
||||
&& (ivl_expr_width(sube) < (wid+wid/10))) {
|
||||
|
||||
res.base = allocate_vector(ivl_expr_width(sube));
|
||||
res.wid = ivl_expr_width(sube);
|
||||
fprintf(vvp_out, " %%load/v %u, V_%p, %u; Only need %u bits\n",
|
||||
res.base, sig, ivl_expr_width(sube), wid);
|
||||
|
||||
save_signal_lookaside(res.base, sig, res.wid);
|
||||
|
||||
{
|
||||
struct vector_info tmp;
|
||||
tmp.base = res.base + wid;
|
||||
tmp.wid = res.wid - wid;
|
||||
clr_vector(tmp);
|
||||
res.wid = wid;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Alas, do it the hard way. */
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
for (idx = 0 ; idx < res.wid ; idx += 1) {
|
||||
if (idx >= bit_wid) {
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u; Pad from %u to %u\n",
|
||||
res.base+idx, res.wid-idx,
|
||||
ivl_expr_width(sube), wid);
|
||||
break;
|
||||
}
|
||||
fprintf(vvp_out, " %%load/x.p %u, V_%p, 0;\n",
|
||||
res.base+idx, sig);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
struct vector_info subv, shiv, res;
|
||||
ivl_expr_t sube = ivl_expr_oper1(exp);
|
||||
ivl_expr_t shift = ivl_expr_oper2(exp);
|
||||
|
||||
int alloc_exclusive = (stuff_ok_flag&STUFF_OK_RO)? 0 : 1;
|
||||
|
||||
res.wid = wid;
|
||||
|
||||
/* First look for the self expression in the lookaside, and
|
||||
allocate that if possible. If I find it, then immediatly
|
||||
return that. */
|
||||
if ( (res.base = allocate_vector_exp(exp, wid, alloc_exclusive)) != 0) {
|
||||
fprintf(vvp_out, "; Reuse base=%u wid=%u from lookaside.\n",
|
||||
res.base, wid);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (ivl_expr_type(sube) == IVL_EX_SIGNAL) {
|
||||
res = draw_select_signal(sube, shift, ivl_expr_width(exp), wid);
|
||||
fprintf(vvp_out, "; Save base=%u wid=%u in lookaside.\n",
|
||||
res.base, wid);
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Evaluate the sub-expression. */
|
||||
subv = draw_eval_expr(sube, 0);
|
||||
|
||||
@@ -1617,6 +1772,16 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
/* Evaluate the bit select base expression and store the
|
||||
result into index register 0. */
|
||||
shiv = draw_eval_expr(shift, STUFF_OK_XZ);
|
||||
|
||||
/* Detect and handle the special case that the shift is a
|
||||
constant 0. Skip the shift, and return the subexpression
|
||||
with the width trimmed down to the desired width. */
|
||||
if (shiv.base == 0) {
|
||||
assert(subv.wid >= wid);
|
||||
res.base = subv.base;
|
||||
return res;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
clr_vector(shiv);
|
||||
|
||||
@@ -1632,20 +1797,24 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", subv.base, subv.wid);
|
||||
|
||||
assert(subv.wid >= wid);
|
||||
if (subv.wid > wid) {
|
||||
res.base = subv.base;
|
||||
res.wid = wid;
|
||||
|
||||
subv.base += wid;
|
||||
subv.wid -= wid;
|
||||
clr_vector(subv);
|
||||
|
||||
} else if (subv.wid == wid) {
|
||||
} else {
|
||||
assert(subv.wid == wid);
|
||||
res = subv;
|
||||
}
|
||||
|
||||
if (res.base >= 8)
|
||||
if (res.base >= 8) {
|
||||
fprintf(vvp_out, "; Save expression base=%u wid=%u in lookaside\n",
|
||||
res.base, wid);
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1665,7 +1834,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
/* Evaluate the condition expression, and if necessary reduce
|
||||
it to a single bit. */
|
||||
tst = draw_eval_expr(cond, STUFF_OK_XZ);
|
||||
tst = draw_eval_expr(cond, STUFF_OK_XZ|STUFF_OK_RO);
|
||||
if ((tst.base >= 4) && (tst.wid > 1)) {
|
||||
struct vector_info tmp;
|
||||
|
||||
@@ -1744,7 +1913,8 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
/* If the function has no parameters, then use this short-form
|
||||
to draw the statement. */
|
||||
if (parm_count == 0) {
|
||||
assert(ivl_expr_value(exp) == IVL_VT_VECTOR);
|
||||
assert(ivl_expr_value(exp) == IVL_VT_LOGIC
|
||||
|| ivl_expr_value(exp) == IVL_VT_BOOL);
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
fprintf(vvp_out, " %%vpi_func \"%s\", %u, %u;\n",
|
||||
@@ -1761,86 +1931,6 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* A call to a user defined function generates a result that is the
|
||||
* result of this expression.
|
||||
*
|
||||
* The result of the function is placed by the function execution into
|
||||
* a signal within the scope of the function that also has a basename
|
||||
* the same as the function. The ivl_target API handled the result
|
||||
* mapping already, and we get the name of the result signal as
|
||||
* parameter 0 of the function definition.
|
||||
*/
|
||||
|
||||
static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_scope_t def = ivl_expr_def(exp);
|
||||
ivl_signal_t retval = ivl_scope_port(def, 0);
|
||||
struct vector_info res;
|
||||
|
||||
/* evaluate the expressions and send the results to the
|
||||
function ports. */
|
||||
|
||||
assert(ivl_expr_parms(exp) == (ivl_scope_ports(def)-1));
|
||||
for (idx = 0 ; idx < ivl_expr_parms(exp) ; idx += 1) {
|
||||
ivl_signal_t port = ivl_scope_port(def, idx+1);
|
||||
unsigned pin, bit;
|
||||
|
||||
res = draw_eval_expr_wid(ivl_expr_parm(exp, idx),
|
||||
ivl_signal_pins(port), 0);
|
||||
bit = res.base;
|
||||
assert(res.wid <= ivl_signal_pins(port));
|
||||
for (pin = 0 ; pin < res.wid ; pin += 1) {
|
||||
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
|
||||
vvp_signal_label(port),
|
||||
pin, bit);
|
||||
if (bit >= 4)
|
||||
bit += 1;
|
||||
}
|
||||
|
||||
clr_vector(res);
|
||||
}
|
||||
|
||||
|
||||
/* Call the function */
|
||||
fprintf(vvp_out, " %%fork TD_%s", vvp_mangle_id(ivl_scope_name(def)));
|
||||
fprintf(vvp_out, ", S_%p;\n", def);
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
|
||||
/* Fresh basic block starts after the join. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
/* The return value is in a signal that has the name of the
|
||||
expression. Load that into the thread and return the
|
||||
vector result. */
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
{ unsigned load_wid = swid;
|
||||
if (load_wid > ivl_signal_pins(retval))
|
||||
load_wid = ivl_signal_pins(retval);
|
||||
|
||||
for (idx = 0 ; idx < load_wid ; idx += 1)
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx,
|
||||
vvp_signal_label(retval), idx);
|
||||
|
||||
if (load_wid < swid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+load_wid, swid-load_wid);
|
||||
}
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, wid-swid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
@@ -2007,18 +2097,6 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_variable_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
ivl_variable_t var = ivl_expr_variable(exp);
|
||||
fprintf(vvp_out, " ; XXXX Read variable %s\n",
|
||||
ivl_variable_name(var));
|
||||
|
||||
res.base = 0;
|
||||
res.wid = wid;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sometimes we know ahead of time where we want the expression value
|
||||
* to go. In that case, call this function. It will check to see if
|
||||
@@ -2077,12 +2155,8 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
res = draw_binary_expr(exp, wid, stuff_ok_flag);
|
||||
break;
|
||||
|
||||
case IVL_EX_BITSEL:
|
||||
res = draw_bitsel_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_CONCAT:
|
||||
res = draw_concat_expr(exp, wid);
|
||||
res = draw_concat_expr(exp, wid, stuff_ok_flag);
|
||||
break;
|
||||
|
||||
case IVL_EX_NUMBER:
|
||||
@@ -2097,11 +2171,11 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
if (ivl_expr_oper2(exp) == 0)
|
||||
res = draw_pad_expr(exp, wid);
|
||||
else
|
||||
res = draw_select_expr(exp, wid);
|
||||
res = draw_select_expr(exp, wid, stuff_ok_flag);
|
||||
break;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
res = draw_signal_expr(exp, wid);
|
||||
res = draw_signal_expr(exp, wid, stuff_ok_flag);
|
||||
break;
|
||||
|
||||
case IVL_EX_TERNARY:
|
||||
@@ -2123,10 +2197,6 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
case IVL_EX_UNARY:
|
||||
res = draw_unary_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_VARIABLE:
|
||||
res = draw_variable_expr(exp, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -2139,6 +2209,72 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
||||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.130 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.129 2006/01/02 05:33:20 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.128 2005/12/22 15:42:22 steve
|
||||
* Pad part selects
|
||||
*
|
||||
* Revision 1.127 2005/10/11 18:54:10 steve
|
||||
* Remove the $ from signal labels. They do not help.
|
||||
*
|
||||
* Revision 1.126 2005/10/11 18:30:50 steve
|
||||
* Remove obsolete vvp_memory_label function.
|
||||
*
|
||||
* Revision 1.125 2005/09/19 21:45:36 steve
|
||||
* Spelling patches from Larry.
|
||||
*
|
||||
* Revision 1.124 2005/09/19 20:18:20 steve
|
||||
* Fix warnings about uninitialized variables.
|
||||
*
|
||||
* Revision 1.123 2005/09/17 04:01:32 steve
|
||||
* Improve loading of part selects when easy.
|
||||
*
|
||||
* Revision 1.122 2005/09/17 01:01:00 steve
|
||||
* More robust use of precalculated expressions, and
|
||||
* Separate lookaside for written variables that can
|
||||
* also be reused.
|
||||
*
|
||||
* Revision 1.121 2005/09/15 02:49:47 steve
|
||||
* Better reuse of IVL_EX_SELECT expressions.
|
||||
*
|
||||
* Revision 1.120 2005/09/14 02:53:15 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.119 2005/07/13 04:52:31 steve
|
||||
* Handle functions with real values.
|
||||
*
|
||||
* Revision 1.118 2005/07/11 16:56:51 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.117 2005/03/12 23:45:33 steve
|
||||
* Handle function/task port vectors.
|
||||
*
|
||||
* Revision 1.116 2005/03/03 04:34:42 steve
|
||||
* Rearrange how memories are supported as vvp_vector4 arrays.
|
||||
*
|
||||
* Revision 1.115 2005/02/15 07:12:55 steve
|
||||
* Support constant part select writes to l-values, and large part select reads from signals.
|
||||
*
|
||||
* Revision 1.114 2005/01/28 05:37:48 steve
|
||||
* Special handling of constant shift 0.
|
||||
*
|
||||
* Revision 1.113 2005/01/24 05:28:31 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.112 2005/01/24 05:08:02 steve
|
||||
* Part selects are done in the compiler, not here.
|
||||
*
|
||||
* Revision 1.111 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.110 2004/10/04 01:10:57 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user