mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-27 08:16:13 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e29ecdc234 | ||
|
|
0f6eea7024 | ||
|
|
97dd559fca | ||
|
|
a4c722b195 | ||
|
|
b3a3b888d8 | ||
|
|
2f1d258acb | ||
|
|
7aa9bc9892 | ||
|
|
4a058632b2 | ||
|
|
6a72b4c10e | ||
|
|
00d44222dd | ||
|
|
b36b6d0ca0 | ||
|
|
386958f9a0 | ||
|
|
f6eb581aff | ||
|
|
966f7a4bff | ||
|
|
2cb76cabef | ||
|
|
609d5fe727 | ||
|
|
522d0ec864 | ||
|
|
ad8565f8a6 | ||
|
|
b0c003dc34 | ||
|
|
a4e528f0c3 | ||
|
|
c8d9ade58c | ||
|
|
61e3eed49c | ||
|
|
afb8e285db | ||
|
|
79ce94b585 | ||
|
|
f7f5ccce05 | ||
|
|
25d25ff7fe | ||
|
|
31b0037299 | ||
|
|
16f514739f | ||
|
|
604ce0db09 | ||
|
|
a71dbd3987 | ||
|
|
417186b06f | ||
|
|
ac91dc38b8 | ||
|
|
6d0be3de3a | ||
|
|
2d4f33a0dd | ||
|
|
c6088c8820 | ||
|
|
5134636932 | ||
|
|
5d051ffbde | ||
|
|
97985bba64 | ||
|
|
9ec5fa972e | ||
|
|
9e04ef4abd | ||
|
|
68dc83b322 | ||
|
|
97e9b62080 | ||
|
|
4072021ba4 | ||
|
|
c901945871 | ||
|
|
95281e5d82 | ||
|
|
2858c2f09b | ||
|
|
034cdae445 | ||
|
|
e71ea8c9de | ||
|
|
b2a136e07e | ||
|
|
c2dc3fe5c3 | ||
|
|
548ff4f89a | ||
|
|
b3c24adb11 | ||
|
|
e81d0d9f23 | ||
|
|
715d140d85 | ||
|
|
fa46de1021 | ||
|
|
aa31884d3b | ||
|
|
aacce5ef1b | ||
|
|
565088160e | ||
|
|
b24011b84b | ||
|
|
2b8d9abd3e | ||
|
|
e24facfaf6 | ||
|
|
27e717839a | ||
|
|
52c7108782 | ||
|
|
90ed3dd124 | ||
|
|
8118203766 | ||
|
|
e8518c5056 | ||
|
|
f02d4574f9 | ||
|
|
f1ff1149f7 | ||
|
|
034a38ea36 | ||
|
|
f8c3b84f68 | ||
|
|
d8ef63efd1 | ||
|
|
a240be73e7 | ||
|
|
1563643c92 | ||
|
|
5b89249f10 | ||
|
|
bf70673380 | ||
|
|
6779f01f3a | ||
|
|
66f7ef97da | ||
|
|
e03859b834 | ||
|
|
f2c1902984 | ||
|
|
32f3881344 | ||
|
|
264e629c74 | ||
|
|
8969ab03d7 | ||
|
|
952ebe8516 | ||
|
|
f355cf334c | ||
|
|
01c5321208 | ||
|
|
970ba895c9 | ||
|
|
cbc3be0304 | ||
|
|
cb65ee5e00 | ||
|
|
debe707097 | ||
|
|
79b60da54c | ||
|
|
84c7795d16 | ||
|
|
410a93b52c | ||
|
|
78355b6038 | ||
|
|
59b69c6dd1 | ||
|
|
d3bff8a451 | ||
|
|
43ddd97426 | ||
|
|
4399042b8d | ||
|
|
2b0aaec8ab | ||
|
|
7d7ccd4f08 | ||
|
|
93463b6ff5 | ||
|
|
4b0c56c3a8 | ||
|
|
1bae567728 | ||
|
|
7d7beeecc1 | ||
|
|
f5d0211864 | ||
|
|
1f4232187c | ||
|
|
f45ba008d8 | ||
|
|
ac629b313c | ||
|
|
563065053e | ||
|
|
2b903f5d0e | ||
|
|
7ef3b44ab1 | ||
|
|
8376553349 | ||
|
|
3885f17d0f | ||
|
|
4b0e5bd173 | ||
|
|
d78c7392c2 | ||
|
|
cf3f1b38c3 | ||
|
|
2fbc0af1ea | ||
|
|
94a1d59817 | ||
|
|
57d1bfaf29 |
+17
-4
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.90 2001/01/14 23:04:55 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.95 2001/03/25 05:59:46 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -27,6 +27,8 @@ prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
SUBDIRS = @subdirs@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
@@ -58,6 +60,7 @@ endif
|
||||
|
||||
|
||||
all: ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) all); done
|
||||
cd vvm ; $(MAKE) all
|
||||
cd vpi ; $(MAKE) all
|
||||
cd ivlpp ; $(MAKE) all
|
||||
@@ -69,8 +72,9 @@ all: ivl@EXEEXT@
|
||||
# This rule rules the compiler in the trivial hello.vl program to make
|
||||
# sure the basics were compiled properly.
|
||||
check: all
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) check); done
|
||||
driver/iverilog -Ccheck.conf -ocheck -tvvm-check -B./ivlpp examples/hello.vl
|
||||
$(CXX) -o check $(rdynamic) -fno-exceptions -Ivvm -Ivpi -Lvvm check.cc -lvvm -lvpip $(dllib)
|
||||
$(CXX) -o check $(rdynamic) -fno-exceptions -I$(srcdir) -I$(srcdir)/vvm -I$(srcdir)/vpip -Lvvm -Lvpip check.cc -lvvm -lvpip $(dllib)
|
||||
./check | grep 'Hello, World'
|
||||
|
||||
clean:
|
||||
@@ -81,9 +85,12 @@ clean:
|
||||
cd ivlpp ; $(MAKE) clean
|
||||
cd tgt-verilog ; $(MAKE) clean
|
||||
cd tgt-stub ; $(MAKE) clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) clean); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) clean); done
|
||||
|
||||
distclean: clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) distclean); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) distclean); done
|
||||
rm -f vvm/Makefile
|
||||
rm -f vpi/Makefile
|
||||
rm -f ivlpp/Makefile
|
||||
@@ -98,7 +105,7 @@ O = main.o cprop.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_sig.o emit.o eval.o eval_rconst.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
mangle.o netlist.o net_assign.o \
|
||||
mangle.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_force.o net_link.o net_modulo.o net_proc.o \
|
||||
net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
@@ -153,11 +160,12 @@ lexor_keyword.cc: lexor_keyword.gperf
|
||||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h
|
||||
cd vvm ; $(MAKE) install
|
||||
cd vpi ; $(MAKE) install
|
||||
cd ivlpp ; $(MAKE) install
|
||||
cd driver ; $(MAKE) install
|
||||
for tgt in $(SUBDIRS); do (cd $$tgt ; $(MAKE) install); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
|
||||
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
@@ -170,6 +178,9 @@ $(libdir)/ivl/iverilog.conf: $(srcdir)/iverilog.conf
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl
|
||||
|
||||
@@ -178,10 +189,12 @@ uninstall:
|
||||
rm -f $(bindir)/verilog
|
||||
rm -f $(bindir)/gverilog@EXEEXT@
|
||||
rm -f $(includedir)/ivl_target.h
|
||||
rm -f $(includedir)/vpi_user.h
|
||||
cd driver ; $(MAKE) uninstall
|
||||
cd vpi ; $(MAKE) uninstall
|
||||
cd vvm ; $(MAKE) uninstall
|
||||
cd ivlpp ; $(MAKE) uninstall
|
||||
for tgt in $(SUBDIRS); do (cd $$tgt ; $(MAKE) uninstall); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) uninstall); done
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -388,7 +388,7 @@ 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}
|
||||
*maintainer needed*
|
||||
Ying-Chieh Liao <[email protected]>
|
||||
|
||||
Linux/{alpha,Intel} (RPMS)
|
||||
Stephen Williams <[email protected]>
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# This shell script exists to run autoconf on source distributions
|
||||
# that are pulled from CVS. The configure scripts are not included
|
||||
# in CVS, and there are several configure.in files, so it is easiest
|
||||
# to just run this script to autoconf wherever needed.
|
||||
#
|
||||
echo "Autoconf in root..."
|
||||
autoconf
|
||||
|
||||
for dir
|
||||
in vpip vvp tgt-vvp
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd $dir ; autoconf )
|
||||
done
|
||||
@@ -148,5 +148,6 @@ AC_SUBST(shared)
|
||||
AC_MSG_RESULT($shared)
|
||||
|
||||
|
||||
AC_CONFIG_SUBDIRS(vpip vvp tgt-vvp)
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: cprop.cc,v 1.23 2000/12/30 03:11:15 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.26 2001/02/18 01:07:32 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -38,12 +38,19 @@ struct cprop_functor : public functor_t {
|
||||
|
||||
unsigned count;
|
||||
|
||||
virtual void signal(Design*des, NetNet*obj);
|
||||
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
||||
virtual void lpm_compare(Design*des, NetCompare*obj);
|
||||
virtual void lpm_compare_eq_(Design*des, NetCompare*obj);
|
||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
{
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
// For now, only additions are handled.
|
||||
@@ -128,6 +135,110 @@ void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
{
|
||||
if (obj->pin_AEB().is_linked()) {
|
||||
assert( ! obj->pin_AGB().is_linked() );
|
||||
assert( ! obj->pin_AGEB().is_linked() );
|
||||
assert( ! obj->pin_ALB().is_linked() );
|
||||
assert( ! obj->pin_ALEB().is_linked() );
|
||||
assert( ! obj->pin_AGB().is_linked() );
|
||||
assert( ! obj->pin_ANEB().is_linked() );
|
||||
lpm_compare_eq_(des, obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
{
|
||||
|
||||
/* First, look for the case where constant bits on matching A
|
||||
and B inputs are different. This this is so, the device can
|
||||
be completely eliminated and replaced with a constant 0. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! link_drivers_constant(obj->pin_DataA(idx)))
|
||||
continue;
|
||||
if (! link_drivers_constant(obj->pin_DataB(idx)))
|
||||
continue;
|
||||
if (driven_value(obj->pin_DataA(idx)) ==
|
||||
driven_value(obj->pin_DataB(idx)))
|
||||
continue;
|
||||
|
||||
NetConst*zero = new NetConst(obj->name(), verinum::V0);
|
||||
connect(zero->pin(0), obj->pin_AEB());
|
||||
delete obj;
|
||||
des->add_node(zero);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Still may need the gate. Run through the inputs again, and
|
||||
look for pairs of constants. Those inputs can be removed. */
|
||||
|
||||
unsigned top = obj->width();
|
||||
for (unsigned idx = 0 ; idx < top ; ) {
|
||||
if (! link_drivers_constant(obj->pin_DataA(idx))) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
if (! link_drivers_constant(obj->pin_DataB(idx))) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
obj->pin_DataA(idx).unlink();
|
||||
obj->pin_DataB(idx).unlink();
|
||||
|
||||
top -= 1;
|
||||
for (unsigned jj = idx ; jj < top ; jj += 1) {
|
||||
connect(obj->pin_DataA(jj), obj->pin_DataA(jj+1));
|
||||
connect(obj->pin_DataB(jj), obj->pin_DataB(jj+1));
|
||||
obj->pin_DataA(jj+1).unlink();
|
||||
obj->pin_DataB(jj+1).unlink();
|
||||
}
|
||||
}
|
||||
|
||||
/* If we wound up disconnecting all the inputs, then remove
|
||||
the device and replace it with a constant. */
|
||||
if (top == 0) {
|
||||
NetConst*one = new NetConst(obj->name(), verinum::V1);
|
||||
connect(one->pin(0), obj->pin_AEB());
|
||||
delete obj;
|
||||
des->add_node(one);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is only one bit left, then replace the comparator
|
||||
with a simple XOR gate. */
|
||||
if (top == 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(), obj->name(), 3,
|
||||
NetLogic::XOR);
|
||||
connect(tmp->pin(0), obj->pin_AEB());
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
if (top == obj->width())
|
||||
return;
|
||||
|
||||
NetCompare*tmp = new NetCompare(obj->name(), top);
|
||||
connect(tmp->pin_AEB(), obj->pin_AEB());
|
||||
for (unsigned idx = 0 ; idx < top ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx));
|
||||
}
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
{
|
||||
// Look for and count unlinked FF outputs. Note that if the
|
||||
@@ -783,7 +894,22 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
clnk->cur_link(cur, pin);
|
||||
|
||||
NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
if (tmp && tmp->get_eref() > 0)
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
|
||||
assert(tmp->scope());
|
||||
|
||||
// If the net has an eref, then there is an
|
||||
// expression somewhere that reads this signal. So
|
||||
// the constant does get read.
|
||||
if (tmp->get_eref() > 0)
|
||||
return;
|
||||
|
||||
// If the net is a port of the root module, then
|
||||
// the constant may be driving something outside
|
||||
// the design, so do not eliminate it.
|
||||
if ((tmp->port_type() != NetNet::NOT_A_PORT)
|
||||
&& (tmp->scope()->parent() == 0))
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -811,6 +937,15 @@ void cprop(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.26 2001/02/18 01:07:32 steve
|
||||
* check signals in the cprop functor.
|
||||
*
|
||||
* Revision 1.25 2001/02/16 03:27:31 steve
|
||||
* Constant propagation for compare ==.
|
||||
*
|
||||
* Revision 1.24 2001/02/10 04:50:54 steve
|
||||
* Catch constants driving root module ports. (PR#130)
|
||||
*
|
||||
* Revision 1.23 2000/12/30 03:11:15 steve
|
||||
* Propagate initial value of constants into wires.
|
||||
*
|
||||
|
||||
+5
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: design_dump.cc,v 1.110 2001/01/18 03:16:35 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.111 2001/02/17 05:13:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -344,6 +344,7 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
o << setw(ind+4) << "";
|
||||
assert(ports_[idx]);
|
||||
switch (ports_[idx]->port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
o << "input ";
|
||||
@@ -1000,6 +1001,9 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.111 2001/02/17 05:13:36 steve
|
||||
* Check that the port really exists here.
|
||||
*
|
||||
* Revision 1.110 2001/01/18 03:16:35 steve
|
||||
* NetMux needs a scope. (PR#115)
|
||||
*
|
||||
|
||||
+84
-11
@@ -17,12 +17,13 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_expr.cc,v 1.34 2001/01/14 23:04:55 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.36 2001/02/10 20:29:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pform.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*) const
|
||||
{
|
||||
@@ -145,6 +146,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a call to a system function, generate the proper expression
|
||||
* nodes to represent the call in the netlist. Since we don't support
|
||||
* size_tf functions, make assumptions about widths based on some
|
||||
* known function names.
|
||||
*/
|
||||
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
{
|
||||
unsigned wid = 32;
|
||||
@@ -152,11 +159,52 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
if (name_ == "$time")
|
||||
wid = 64;
|
||||
|
||||
NetESFunc*fun = new NetESFunc(name_, wid, parms_.count());
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
/* How many parameters are there? The Verilog language allows
|
||||
empty parameters in certain contexts, so the parser will
|
||||
allow things like func(1,,3). It will also cause func() to
|
||||
be interpreted as a single empty parameter.
|
||||
|
||||
Functions cannot really take empty parameters, but the
|
||||
case ``func()'' is the same as no parmaters at all. So
|
||||
catch that special case here. */
|
||||
unsigned nparms = parms_.count();
|
||||
if ((nparms == 1) && (parms_[0] == 0))
|
||||
nparms = 0;
|
||||
|
||||
NetESFunc*fun = new NetESFunc(name_, wid, nparms);
|
||||
|
||||
/* Now run through the expected parameters. If we find that
|
||||
there are missing parameters, print an error message.
|
||||
|
||||
While we're at it, try to evaluate the function parameter
|
||||
expression as much as possible, and use the reduced
|
||||
expression if one is created. */
|
||||
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*expr = parms_[idx];
|
||||
NetExpr*tmp = expr->elaborate_expr(des, scope);
|
||||
fun->parm(idx, tmp);
|
||||
if (expr) {
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope);
|
||||
if (NetExpr*tmp2 = tmp1->eval_tree()) {
|
||||
delete tmp1;
|
||||
fun->parm(idx, tmp2);
|
||||
} else {
|
||||
fun->parm(idx, tmp1);
|
||||
}
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
fun->parm(idx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_line() << ": error: The function " << name_
|
||||
<< " has been called with empty parameters." << endl;
|
||||
cerr << get_line() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return fun;
|
||||
@@ -195,10 +243,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const
|
||||
of the function being called. The scope of the called
|
||||
function is elaborated when the definition is elaborated. */
|
||||
|
||||
unsigned missing_parms = 0;
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
assert(tmp);
|
||||
parms[idx] = tmp->elaborate_expr(des, scope);
|
||||
if (tmp) {
|
||||
parms[idx] = tmp->elaborate_expr(des, scope);
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
parms[idx] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_line() << ": error: The function " << name_
|
||||
<< " has been called with empty parameters." << endl;
|
||||
cerr << get_line() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,17 +293,21 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, scope->name());
|
||||
if (vrep == 0) {
|
||||
NetExpr*tmp = elab_and_eval(des, scope, repeat_);
|
||||
assert(tmp);
|
||||
NetEConst*rep = dynamic_cast<NetEConst*>(tmp);
|
||||
|
||||
if (rep == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
cerr << get_line() << ": : The expression is: "
|
||||
<< *tmp << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = vrep->as_ulong();
|
||||
delete vrep;
|
||||
repeat = rep->value().as_ulong();
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
@@ -545,6 +611,13 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.36 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.35 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.34 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
|
||||
+11
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_lval.cc,v 1.11 2001/01/10 03:13:23 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.12 2001/02/09 03:16:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -284,8 +284,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wid > reg->pin_count()) {
|
||||
cerr << get_line() << ": error: part select "
|
||||
/* If the part select extends beyond the extreme of the
|
||||
variable, then report an error. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->pin_count()) {
|
||||
cerr << get_line() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
@@ -306,6 +311,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* 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)
|
||||
*
|
||||
|
||||
+28
-18
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_net.cc,v 1.61 2001/01/25 02:05:16 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.64 2001/02/15 06:59:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -167,13 +167,7 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
|
||||
if (rsig->pin_count() > lsig->pin_count())
|
||||
width = rsig->pin_count();
|
||||
|
||||
// If the desired output size if creater then the largest
|
||||
// operand, then include the carry of the adder as an output.
|
||||
#if 0
|
||||
unsigned owidth = width;
|
||||
if (lwidth > owidth)
|
||||
owidth = width + 1;
|
||||
#else
|
||||
|
||||
/* The owidth is the output width of the lpm_add_sub
|
||||
device. If the desired with is greater then the width of
|
||||
the operands, then widen the adder and let code below pad
|
||||
@@ -196,15 +190,15 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Pad out the operands, if necessary, the match the width of
|
||||
// the adder device.
|
||||
if (lsig->pin_count() < width)
|
||||
lsig = pad_to_width(des, path, lsig, width);
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
|
||||
if (rsig->pin_count() < width)
|
||||
rsig = pad_to_width(des, path, rsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
// Make the adder as wide as the widest operand
|
||||
osig = new NetNet(scope, des->local_symbol(path),
|
||||
@@ -270,9 +264,9 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, const string&path,
|
||||
}
|
||||
|
||||
if (lsig->pin_count() < rsig->pin_count())
|
||||
lsig = pad_to_width(des, path, lsig, rsig->pin_count());
|
||||
lsig = pad_to_width(des, lsig, rsig->pin_count());
|
||||
if (rsig->pin_count() < lsig->pin_count())
|
||||
rsig = pad_to_width(des, path, rsig, lsig->pin_count());
|
||||
rsig = pad_to_width(des, rsig, lsig->pin_count());
|
||||
|
||||
if (lsig->pin_count() != rsig->pin_count()) {
|
||||
cerr << get_line() << ": internal error: lsig pin count ("
|
||||
@@ -1142,9 +1136,16 @@ NetNet* PEIdent::elaborate_net(Design*des, const string&path,
|
||||
NetNet*tmp = new NetNet(scope, des->local_symbol(path),
|
||||
sig->type(), midx-lidx+1);
|
||||
tmp->local_flag(true);
|
||||
if (tmp->pin_count() > sig->pin_count()) {
|
||||
cerr << get_line() << ": bit select out of "
|
||||
<< "range for " << sig->name() << endl;
|
||||
|
||||
/* Check that the bit or part select of the signal is
|
||||
within the range of the part. The lidx is the
|
||||
normalized index of the LSB, so that plus the desired
|
||||
width must be <= the width of the references signal. */
|
||||
if ((lidx + tmp->pin_count()) > sig->pin_count()) {
|
||||
cerr << get_line() << ": error: bit/part select ["
|
||||
<< mval->as_long() << ":" << lval->as_long()
|
||||
<< "] out of range for " << sig->name() << endl;
|
||||
des->errors += 1;
|
||||
return sig;
|
||||
}
|
||||
|
||||
@@ -1640,10 +1641,10 @@ NetNet* PETernary::elaborate_net(Design*des, const string&path,
|
||||
sig->local_flag(true);
|
||||
|
||||
if (fal_sig->pin_count() < dwidth)
|
||||
fal_sig = pad_to_width(des, path, fal_sig, dwidth);
|
||||
fal_sig = pad_to_width(des, fal_sig, dwidth);
|
||||
|
||||
if (tru_sig->pin_count() < dwidth)
|
||||
tru_sig = pad_to_width(des, path, tru_sig, dwidth);
|
||||
tru_sig = pad_to_width(des, tru_sig, dwidth);
|
||||
|
||||
|
||||
/* Make the device and connect its outputs to the osig and
|
||||
@@ -1902,6 +1903,15 @@ NetNet* PEUnary::elaborate_net(Design*des, const string&path,
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.64 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.63 2001/02/09 20:18:15 steve
|
||||
* Detect part select out of range in nets. (PR#138)
|
||||
*
|
||||
* Revision 1.62 2001/02/08 01:10:30 steve
|
||||
* Remove dead code.
|
||||
*
|
||||
* Revision 1.61 2001/01/25 02:05:16 steve
|
||||
* Handle wide net constants with unary minus.
|
||||
*
|
||||
|
||||
+27
-10
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_sig.cc,v 1.10 2001/01/13 22:20:08 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.12 2001/02/17 05:15:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "Module.h"
|
||||
@@ -26,6 +26,7 @@
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
/*
|
||||
@@ -310,6 +311,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
unsigned wid = 1;
|
||||
long lsb = 0, msb = 0;
|
||||
|
||||
assert(msb_.count() == lsb_.count());
|
||||
if (msb_.count()) {
|
||||
svector<long>mnum (msb_.count());
|
||||
svector<long>lnum (msb_.count());
|
||||
@@ -320,27 +322,35 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
here. I will resolve the values later. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
|
||||
verinum*mval = msb_[idx]->eval_const(des,path);
|
||||
if (mval == 0) {
|
||||
|
||||
NetEConst*tmp;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*msb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
verinum*lval = lsb_[idx]->eval_const(des, path);
|
||||
if (lval == 0) {
|
||||
cerr << lsb_[idx]->get_line() << ": error: "
|
||||
|
||||
mnum[idx] = tmp->value().as_long();
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx]);
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*lsb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
mnum[idx] = mval->as_long();
|
||||
lnum[idx] = lval->as_long();
|
||||
delete mval;
|
||||
delete lval;
|
||||
lnum[idx] = tmp->value().as_long();
|
||||
delete texpr;
|
||||
|
||||
}
|
||||
|
||||
/* Make sure all the values for msb and lsb match by
|
||||
@@ -404,6 +414,13 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.12 2001/02/17 05:15:33 steve
|
||||
* Allow task ports to be given real types.
|
||||
*
|
||||
* Revision 1.11 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.10 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
|
||||
+30
-9
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elaborate.cc,v 1.205 2001/01/14 23:04:56 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.208 2001/02/15 06:59:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1280,7 +1280,7 @@ NetProc* PCondit::elaborate(Design*des, const string&path) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (! expr->set_width(1)) {
|
||||
if (expr->expr_width() > 1) {
|
||||
assert(expr->expr_width() > 1);
|
||||
verinum zero (verinum::V0, expr->expr_width());
|
||||
NetEConst*ezero = new NetEConst(zero);
|
||||
@@ -1497,7 +1497,7 @@ NetCAssign* PCAssign::elaborate(Design*des, const string&path) const
|
||||
return 0;
|
||||
|
||||
if (rval->pin_count() < lval->pin_count())
|
||||
rval = pad_to_width(des, path, rval, lval->pin_count());
|
||||
rval = pad_to_width(des, rval, lval->pin_count());
|
||||
|
||||
NetCAssign* dev = new NetCAssign(des->local_symbol(path), lval);
|
||||
des->add_node(dev);
|
||||
@@ -1930,7 +1930,7 @@ NetProc* PForce::elaborate(Design*des, const string&path) const
|
||||
return 0;
|
||||
|
||||
if (rval->pin_count() < lval->pin_count())
|
||||
rval = pad_to_width(des, path, rval, lval->pin_count());
|
||||
rval = pad_to_width(des, rval, lval->pin_count());
|
||||
|
||||
NetForce* dev = new NetForce(des->local_symbol(path), lval);
|
||||
des->add_node(dev);
|
||||
@@ -1955,6 +1955,7 @@ NetProc* PForce::elaborate(Design*des, const string&path) const
|
||||
*/
|
||||
NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
||||
{
|
||||
NetExpr*etmp;
|
||||
NetScope*scope = des->find_scope(path);
|
||||
assert(scope);
|
||||
|
||||
@@ -1980,7 +1981,13 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
||||
for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1)
|
||||
connect(lv->pin(idx), sig->pin(idx));
|
||||
des->add_node(lv);
|
||||
NetAssign*init = new NetAssign(lv, expr1_->elaborate_expr(des, scope));
|
||||
|
||||
/* Make the r-value of the initial assignment, and size it
|
||||
properly. Then use it to build the assignment statement. */
|
||||
etmp = expr1_->elaborate_expr(des, scope);
|
||||
etmp->set_width(lv->lwidth());
|
||||
|
||||
NetAssign*init = new NetAssign(lv, etmp);
|
||||
|
||||
top->append(init);
|
||||
|
||||
@@ -2004,7 +2011,12 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
||||
for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1)
|
||||
connect(lv->pin(idx), sig->pin(idx));
|
||||
des->add_node(lv);
|
||||
NetAssign*step = new NetAssign(lv, expr2_->elaborate_expr(des, scope));
|
||||
|
||||
/* Make the rvalue of the increment expression, and size it
|
||||
for the lvalue. */
|
||||
etmp = expr2_->elaborate_expr(des, scope);
|
||||
etmp->set_width(lv->lwidth());
|
||||
NetAssign*step = new NetAssign(lv, etmp);
|
||||
|
||||
body->append(step);
|
||||
|
||||
@@ -2019,10 +2031,10 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const
|
||||
}
|
||||
|
||||
if (NetExpr*tmp = ce->eval_tree()) {
|
||||
if (dynamic_cast<NetEConst*>(tmp))
|
||||
if (dynamic_cast<NetEConst*>(tmp)) {
|
||||
cerr << get_line() << ": warning: condition expression "
|
||||
"is constant." << endl;
|
||||
|
||||
"of for-loop is constant." << endl;
|
||||
}
|
||||
ce = tmp;
|
||||
}
|
||||
|
||||
@@ -2355,6 +2367,15 @@ Design* elaborate(const map<string,Module*>&modules,
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.208 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.207 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.206 2001/02/07 21:47:13 steve
|
||||
* Fix expression widths for rvalues and parameters (PR#131,132)
|
||||
*
|
||||
* Revision 1.205 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: emit.cc,v 1.55 2000/11/04 01:54:01 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.56 2001/03/27 03:31:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -398,7 +398,9 @@ bool Design::emit(struct target_t*tgt) const
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
rc = rc && idx->emit(tgt);
|
||||
|
||||
tgt->end_design(this);
|
||||
if (tgt->end_design(this) != 0)
|
||||
rc = false;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -476,6 +478,9 @@ bool emit(const Design*des, const char*type)
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* 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
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval.cc,v 1.19 2001/01/27 05:41:48 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.20 2001/02/09 02:49:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -123,7 +123,7 @@ verinum* PEIdent::eval_const(const Design*des, const string&path) const
|
||||
|
||||
if (dynamic_cast<const NetEParam*>(expr)) {
|
||||
cerr << get_line() << ": sorry: I cannot evaluate ``" <<
|
||||
text_ << "'' in this context." << endl;
|
||||
text_ << "'' in this scope: " << scope->name() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,9 @@ verinum* PEUnary::eval_const(const Design*des, const string&path) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.20 2001/02/09 02:49:59 steve
|
||||
* Be more clear about scope of failure.
|
||||
*
|
||||
* Revision 1.19 2001/01/27 05:41:48 steve
|
||||
* Fix sign extension of evaluated constants. (PR#91)
|
||||
*
|
||||
|
||||
+171
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_tree.cc,v 1.21 2001/01/14 23:04:56 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.24 2001/02/10 20:29:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -161,6 +161,50 @@ NetEConst* NetEBComp::eval_eqeq_()
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
if (lv < rv) {
|
||||
verinum 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();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
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.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_leeq_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -205,6 +249,92 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the left side is greater than the
|
||||
largest value the right side can possibly have. */
|
||||
assert(right_->expr_width() > 0);
|
||||
verinum rv (verinum::V1, right_->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*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
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.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_gteq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
||||
verinum lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Detect the case where the left side is greater than the
|
||||
largest value the right side can possibly have. */
|
||||
assert(right_->expr_width() > 0);
|
||||
verinum rv (verinum::V1, right_->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*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
rv = r->value();
|
||||
if (! rv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
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.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*l = dynamic_cast<NetEConst*>(left_);
|
||||
@@ -349,6 +479,9 @@ NetEConst* NetEBComp::eval_tree()
|
||||
case 'e': // Equality (==)
|
||||
return eval_eqeq_();
|
||||
|
||||
case 'G': // >=
|
||||
return eval_gteq_();
|
||||
|
||||
case 'L': // <=
|
||||
return eval_leeq_();
|
||||
|
||||
@@ -358,14 +491,41 @@ NetEConst* NetEBComp::eval_tree()
|
||||
case 'n': // not-equal (!=)
|
||||
return eval_neeq_();
|
||||
|
||||
case '<': // Less than
|
||||
return eval_less_();
|
||||
|
||||
case '>': // Greater then
|
||||
return eval_gt_();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetEBDiv operator includes the / and % opeators. First evaluate
|
||||
* the sub-expressions, then perform the required operation.
|
||||
*/
|
||||
NetEConst* NetEBDiv::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();
|
||||
|
||||
switch (op_) {
|
||||
case '/':
|
||||
return new NetEConst(lval / rval);
|
||||
|
||||
case '%':
|
||||
return new NetEConst(lval % rval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -822,6 +982,16 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.24 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.23 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.22 2001/02/07 02:46:31 steve
|
||||
* Support constant evaluation of / and % (PR#124)
|
||||
*
|
||||
* Revision 1.21 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
|
||||
+8
-2
@@ -17,11 +17,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: expr_synth.cc,v 1.19 2001/01/18 03:16:35 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.20 2001/02/15 06:59:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
# include "netmisc.h"
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
@@ -135,6 +135,9 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
if (rsig->pin_count() > lsig->pin_count())
|
||||
width = rsig->pin_count();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
|
||||
@@ -444,6 +447,9 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.20 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.19 2001/01/18 03:16:35 steve
|
||||
* NetMux needs a scope. (PR#115)
|
||||
*
|
||||
|
||||
+77
-1
@@ -139,6 +139,13 @@ match the range of the integer/time declaration, but the range of
|
||||
integers is unspecified. This, by the way, also applies to module
|
||||
ports.
|
||||
|
||||
With the above in mind, I have decided to *allow* function and task
|
||||
ports to be declared with types, as long as the types are variable
|
||||
types, such ag reg or integer. Without this, there would be no
|
||||
portable way to pass integers into functions/tasks. The standard does
|
||||
not say it is allowed, but it doesn't *disallow* it, and other
|
||||
commercial tools seem to work similarly.
|
||||
|
||||
|
||||
* ROUNDING OF TIME
|
||||
|
||||
@@ -197,9 +204,78 @@ well as all the other major Verilog tools, but the standard does not
|
||||
say this.
|
||||
|
||||
|
||||
* UNSIZED EXPRESSIONS AS PARAMETERS TO CONCATENATION {}
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.5 2001/01/02 17:28:08 steve Exp $
|
||||
The Verilog standard clearly states in 4.1.14:
|
||||
|
||||
"Unsized constant numbers shall not be allowed in
|
||||
concatenations. This is because the size of each
|
||||
operand in the concatenation is needed to calculate
|
||||
the complete size of the concatenation."
|
||||
|
||||
So for example the expression {1'b0, 16} is clearly illegal. It
|
||||
also stands to reason that {1'b0, 15+1} is illegal, for exactly the
|
||||
same justification. What is the size of the expression (15+1)?
|
||||
Furthermore, it is reasonable to expect that (16) and (15+1) are
|
||||
exactly the same so far as the compiler is concerned.
|
||||
|
||||
Unfortunately, Cadence seems to feel otherwise. In particular, it has
|
||||
been reported that although {1'b0, 16} causes an error, {1'b0, 15+1}
|
||||
is accepted. Further testing shows that any expression other then a
|
||||
simple unsized constant is accepted there, even if all the operands of
|
||||
all the operators that make up the expression are unsized integers.
|
||||
|
||||
This is a semantic problem. Icarus Verilog doesn't limit the size of
|
||||
integer constants. This is valid as stated in 2.5.1 Note 3:
|
||||
|
||||
"The number of bits that make up an unsized number
|
||||
(which is a simple decimal number or a number without
|
||||
the size specification) shall be *at*least* 32."
|
||||
[emphasis added]
|
||||
|
||||
Icarus Verilog will hold any integer constant, so the size will be as
|
||||
large as it needs to be, whether that is 64bits, 128bits, or
|
||||
more. With this in mind, what is the value of these expressions?
|
||||
|
||||
{'h1_00_00_00_00}
|
||||
{'h1 << 32}
|
||||
{'h0_00_00_00_01 << 32}
|
||||
{'h5_00_00_00_00 + 1}
|
||||
|
||||
These examples show that the standard is justified in requiring that
|
||||
the operands of concatenation have size. The dispute is what it takes
|
||||
to cause an expression to have a size, and what that size is.
|
||||
Verilog-XL claims that (16) does not have a size, but (15+1) does. The
|
||||
size of the expression (15+1) is the size of the adder that is
|
||||
created, but how wide is the adder when adding unsized constants?
|
||||
|
||||
One might note that the quote from section 4.1.14 says "Unsized
|
||||
*constant*numbers* shall not be allowed." It does not say "Unsized
|
||||
expressions...", so arguably accepting (15+1) or even (16+0) as an
|
||||
operand to a concatenation is not a violation of the letter of the
|
||||
law. However, the very next sentence of the quote expresses the
|
||||
intent, and accepting (15+1) as having a more defined size then (16)
|
||||
seems to be a violation of that intent.
|
||||
|
||||
Whatever a compiler decides the size is, the user has no way to
|
||||
predict it, and the compiler should not have the right to treat (15+1)
|
||||
any differently then (16). Therefore, Icarus Verilog takes the
|
||||
position that such expressions are *unsized* and are not allowed as
|
||||
operands to concatenations. Icarus Verilog will in general assume that
|
||||
operations on unsized numbers produce unsized results. There are
|
||||
exceptions when the operator itself does define a size, such as the
|
||||
comparison operators or the reduction operators. Icarus Verilog will
|
||||
generate appropriate error messages.
|
||||
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.7 2001/02/17 05:27:31 steve Exp $
|
||||
$Log: ieee1364-notes.txt,v $
|
||||
Revision 1.7 2001/02/17 05:27:31 steve
|
||||
I allow function ports to have types.
|
||||
|
||||
Revision 1.6 2001/02/12 16:48:04 steve
|
||||
Rant about bit widths.
|
||||
|
||||
Revision 1.5 2001/01/02 17:28:08 steve
|
||||
Resolve repeat ambiguity in favor of loop.
|
||||
|
||||
|
||||
@@ -61,6 +61,16 @@
|
||||
[-tnull]
|
||||
<ivl>%B/ivl %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
|
||||
|
||||
# --
|
||||
# The vvp target generates code that the vvp simulation engine can execute.
|
||||
# These rules support synthesized and non-synthesized variants.
|
||||
|
||||
[-tvvp -S]
|
||||
<ivl>%B/ivl %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
[-tvvp]
|
||||
<ivl>%B/ivl %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
# --
|
||||
# The vvm target uses the <ivl> string to take the preprocessed code from
|
||||
# standard input, compile it with the vvm code generator and write the
|
||||
|
||||
+89
-7
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: ivl_target.h,v 1.34 2001/01/15 22:05:14 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.40 2001/03/31 17:36:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -61,6 +61,11 @@ _BEGIN_DECL
|
||||
* This object represents the entire elaborated design. Various
|
||||
* global properties and methods are available from this.
|
||||
*
|
||||
* ivl_event_t
|
||||
* This object represents an event node. An event node stands for
|
||||
* named events written explicitly in the Verilog, and net events
|
||||
* that are implicit when @ statements are used.
|
||||
*
|
||||
* ivl_expr_t
|
||||
* This object represents a node of an expression. If the
|
||||
* expression has sub-expressions, they can be accessed from
|
||||
@@ -123,12 +128,12 @@ _BEGIN_DECL
|
||||
* they include the instance name of the module that contains them.
|
||||
*/
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
typedef struct ivl_expr_s *ivl_expr_t;
|
||||
typedef struct ivl_lpm_s *ivl_lpm_t;
|
||||
typedef struct ivl_lpm_ff_s *ivl_lpm_ff_t;
|
||||
typedef struct ivl_lval_s *ivl_lval_t;
|
||||
typedef struct ivl_net_const_s*ivl_net_const_t;
|
||||
typedef struct ivl_net_event_s*ivl_net_event_t;
|
||||
typedef struct ivl_net_logic_s*ivl_net_logic_t;
|
||||
typedef struct ivl_net_probe_s*ivl_net_probe_t;
|
||||
typedef struct ivl_nexus_s *ivl_nexus_t;
|
||||
@@ -144,6 +149,14 @@ typedef struct ivl_statement_s*ivl_statement_t;
|
||||
* changes and additions to the enumerations.
|
||||
*/
|
||||
|
||||
|
||||
typedef enum ivl_edge_type_e {
|
||||
IVL_EDGE_NONE = 0,
|
||||
IVL_EDGE_ANY = 1,
|
||||
IVL_EDGE_POS = 2,
|
||||
IVL_EDGE_NEG = 3
|
||||
} ivl_edge_type_t;
|
||||
|
||||
/* This is the type of an ivl_expr_t object. */
|
||||
typedef enum ivl_expr_type_e {
|
||||
IVL_EX_NONE = 0,
|
||||
@@ -154,6 +167,7 @@ typedef enum ivl_expr_type_e {
|
||||
IVL_EX_SIGNAL,
|
||||
IVL_EX_STRING,
|
||||
IVL_EX_SUBSIG,
|
||||
IVL_EX_UNARY
|
||||
} ivl_expr_type_t;
|
||||
|
||||
/* This is the type code for an ivl_net_logic_t object. */
|
||||
@@ -233,9 +247,13 @@ typedef enum ivl_statement_type_e {
|
||||
IVL_ST_NOOP = 1,
|
||||
IVL_ST_ASSIGN,
|
||||
IVL_ST_BLOCK,
|
||||
IVL_ST_CASE,
|
||||
IVL_ST_CASEX,
|
||||
IVL_ST_CASEZ,
|
||||
IVL_ST_CONDIT,
|
||||
IVL_ST_DELAY,
|
||||
IVL_ST_DELAYX,
|
||||
IVL_ST_FORK,
|
||||
IVL_ST_STASK,
|
||||
IVL_ST_TRIGGER,
|
||||
IVL_ST_WAIT,
|
||||
@@ -293,6 +311,31 @@ extern ivl_nexus_t ivl_const_pin(ivl_net_const_t net, unsigned idx);
|
||||
extern unsigned ivl_const_pins(ivl_net_const_t net);
|
||||
extern int ivl_const_signed(ivl_net_const_t net);
|
||||
|
||||
/* EVENTS
|
||||
*
|
||||
* Events are a unification of named events and implicit events
|
||||
* generated by the @ statements.
|
||||
*
|
||||
* ivl_event_name
|
||||
* ivl_event_basename
|
||||
*
|
||||
* ivl_event_edge
|
||||
* Return the edge type for the event. If this is a named event
|
||||
* that has no network input, then the edge is IVL_EDGE_NONE.
|
||||
*
|
||||
* ivl_event_pins
|
||||
* ivl_event_pin
|
||||
* Events of edge other then NONE have pins that are the connection
|
||||
* of the event to the net.
|
||||
*/
|
||||
extern const char* ivl_event_name(ivl_event_t net);
|
||||
extern const char* ivl_event_basename(ivl_event_t net);
|
||||
extern ivl_edge_type_t ivl_event_edge(ivl_event_t net);
|
||||
|
||||
extern unsigned ivl_event_pins(ivl_event_t net);
|
||||
extern ivl_nexus_t ivl_event_pin(ivl_event_t net, unsigned idx);
|
||||
|
||||
|
||||
/* EXPRESSIONS
|
||||
*
|
||||
* These methods operate on expression objects from the
|
||||
@@ -323,9 +366,9 @@ extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
|
||||
extern const char* ivl_expr_bits(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC */
|
||||
extern const char* ivl_expr_name(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY */
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
extern char ivl_expr_opcode(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY */
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
extern ivl_expr_t ivl_expr_oper1(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY */
|
||||
extern ivl_expr_t ivl_expr_oper2(ivl_expr_t net);
|
||||
@@ -502,6 +545,10 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* If the scope has no children, this method will return 0 and
|
||||
* otherwise do nothing.
|
||||
*
|
||||
* ivl_scope_event
|
||||
* ivl_scope_events
|
||||
* Scopes have 0 or more event objects in them.
|
||||
*
|
||||
* ivl_scope_log
|
||||
* ivl_scope_logs
|
||||
* Scopes have 0 or more logic devices in them. A logic device is
|
||||
@@ -527,6 +574,8 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
|
||||
extern int ivl_scope_children(ivl_scope_t net,
|
||||
ivl_scope_f func, void*cd);
|
||||
extern unsigned ivl_scope_events(ivl_scope_t net);
|
||||
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_logs(ivl_scope_t net);
|
||||
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_lpms(ivl_scope_t net);
|
||||
@@ -593,12 +642,18 @@ extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
|
||||
* The ivl_process_type function gets the type of the process,
|
||||
* an "inital" or "always" statement.
|
||||
*
|
||||
* A process is placed in a scope. The statement within the process
|
||||
* operates within the scope of the process unless there are calls
|
||||
* outside the scope.
|
||||
*
|
||||
* The ivl_process_stmt function gets the statement that forms the
|
||||
* process. See the statement related functions for how to manipulate
|
||||
* statements.
|
||||
*/
|
||||
extern ivl_process_type_t ivl_process_type(ivl_process_t net);
|
||||
|
||||
extern ivl_scope_t ivl_process_scope(ivl_process_t net);
|
||||
|
||||
extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
|
||||
|
||||
/*
|
||||
@@ -620,11 +675,17 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
||||
* statement types can be passed to the function.
|
||||
*/
|
||||
|
||||
/* IVL_ST_BLOCK */
|
||||
/* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
extern unsigned ivl_stmt_block_count(ivl_statement_t net);
|
||||
/* IVL_ST_BLOCK */
|
||||
/* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i);
|
||||
/* IVL_ST_CONDIT */
|
||||
/* IVL_ST_CASE */
|
||||
extern unsigned ivl_stmt_case_count(ivl_statement_t net);
|
||||
/* IVL_ST_CASE */
|
||||
extern ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned i);
|
||||
/* IVL_ST_CASE */
|
||||
extern ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned i);
|
||||
/* IVL_ST_CONDIT, IVL_ST_CASE */
|
||||
extern ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net);
|
||||
/* IVL_ST_CONDIT */
|
||||
extern ivl_statement_t ivl_stmt_cond_false(ivl_statement_t net);
|
||||
@@ -632,6 +693,8 @@ extern ivl_statement_t ivl_stmt_cond_false(ivl_statement_t net);
|
||||
extern ivl_statement_t ivl_stmt_cond_true(ivl_statement_t net);
|
||||
/* IVL_ST_DELAY */
|
||||
extern unsigned long ivl_stmt_delay_val(ivl_statement_t net);
|
||||
/* IVL_ST_WAIT */
|
||||
extern ivl_event_t ivl_stmt_event(ivl_statement_t net);
|
||||
/* IVL_ST_ASSIGN */
|
||||
extern ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx);
|
||||
/* IVL_ST_ASSIGN */
|
||||
@@ -667,6 +730,25 @@ _END_DECL
|
||||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.40 2001/03/31 17:36:38 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.39 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.38 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.37 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.36 2001/03/27 06:27:40 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.35 2001/03/20 01:44:13 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.34 2001/01/15 22:05:14 steve
|
||||
* Declare ivl_scope_type functions.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.54 2000/12/12 06:13:44 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.55 2001/02/07 01:08:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
//# define YYSTYPE lexval
|
||||
@@ -159,8 +159,10 @@ W [ \t\b\f\r]+
|
||||
<UDPTABLE>\(\?\?\) { return '*'; }
|
||||
<UDPTABLE>\(01\) { return 'r'; }
|
||||
<UDPTABLE>\(0[xX]\) { return 'P'; }
|
||||
<UDPTABLE>\(0\?\) { return 'p'; }
|
||||
<UDPTABLE>\(10\) { return 'f'; }
|
||||
<UDPTABLE>\(1[xX]\) { return 'N'; }
|
||||
<UDPTABLE>\(1\?\) { return 'n'; }
|
||||
<UDPTABLE>\([xX]0\) { return 'F'; }
|
||||
<UDPTABLE>\([xX]1\) { return 'R'; }
|
||||
<UDPTABLE>[bB] { return 'b'; }
|
||||
|
||||
+23
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: link_const.cc,v 1.7 2000/11/20 01:41:12 steve Exp $"
|
||||
#ident "$Id: link_const.cc,v 1.8 2001/02/16 03:27:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -35,12 +35,31 @@ bool link_drivers_constant(const Link&lnk)
|
||||
|
||||
for (const Link*cur = nex->first_nlink()
|
||||
; cur ; cur = cur->next_nlink()) {
|
||||
const NetNet*sig;
|
||||
|
||||
if (cur == &lnk)
|
||||
continue;
|
||||
if (cur->get_dir() == Link::INPUT)
|
||||
continue;
|
||||
|
||||
/* If this is an input or input port of a root module,
|
||||
then the is probably not a constant value. I
|
||||
certainly don't know what the value is, anyhow. */
|
||||
|
||||
if (sig = dynamic_cast<const NetNet*>(cur->get_obj())) do {
|
||||
if (sig->port_type() == NetNet::NOT_A_PORT)
|
||||
break;
|
||||
|
||||
if (sig->port_type() == NetNet::POUTPUT)
|
||||
break;
|
||||
|
||||
if (sig->scope()->parent())
|
||||
break;
|
||||
|
||||
flag = false;
|
||||
} while(0);
|
||||
|
||||
|
||||
/* If the link is PASSIVE then it doesn't count as a
|
||||
driver if its initial value is Vz. This is pertinant
|
||||
because REGs are PASSIVE but can receive values from
|
||||
@@ -95,6 +114,9 @@ verinum::V driven_value(const Link&lnk)
|
||||
|
||||
/*
|
||||
* $Log: link_const.cc,v $
|
||||
* Revision 1.8 2001/02/16 03:27:07 steve
|
||||
* links to root inputs are not constant.
|
||||
*
|
||||
* Revision 1.7 2000/11/20 01:41:12 steve
|
||||
* Whoops, return the calculated constant value rom driven_value.
|
||||
*
|
||||
|
||||
+24
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: net_event.cc,v 1.12 2000/12/15 17:45:07 steve Exp $"
|
||||
#ident "$Id: net_event.cc,v 1.14 2001/03/29 02:52:19 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -58,6 +58,12 @@ string NetEvent::full_name() const
|
||||
return scope_->name() + "." + name_;
|
||||
}
|
||||
|
||||
const NetScope* NetEvent::scope() const
|
||||
{
|
||||
assert(scope_);
|
||||
return scope_;
|
||||
}
|
||||
|
||||
unsigned NetEvent::nprobe() const
|
||||
{
|
||||
unsigned cnt = 0;
|
||||
@@ -80,6 +86,16 @@ NetEvProbe* NetEvent::probe(unsigned idx)
|
||||
return cur;
|
||||
}
|
||||
|
||||
const NetEvProbe* NetEvent::probe(unsigned idx) const
|
||||
{
|
||||
NetEvProbe*cur = probes_;
|
||||
while (cur && idx) {
|
||||
cur = cur->enext_;
|
||||
idx -= 1;
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
unsigned NetEvent::ntrig() const
|
||||
{
|
||||
unsigned cnt = 0;
|
||||
@@ -433,6 +449,13 @@ NetProc* NetEvWait::statement()
|
||||
|
||||
/*
|
||||
* $Log: net_event.cc,v $
|
||||
* Revision 1.14 2001/03/29 02:52:19 steve
|
||||
* Add const probe method to NetEvent.
|
||||
*
|
||||
* Revision 1.13 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.12 2000/12/15 17:45:07 steve
|
||||
* Remove limits from the similar events search.
|
||||
*
|
||||
|
||||
+32
-35
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netlist.cc,v 1.154 2001/01/18 03:16:35 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.157 2001/02/10 21:20:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cassert>
|
||||
@@ -1780,21 +1780,15 @@ bool NetExpr::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a bitwise operator node from the opcode and the left and
|
||||
* right expressions. Don't worry about the width of the expression
|
||||
* yet, we'll get that from the l-value, whatever that turns out to
|
||||
* be.
|
||||
*/
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
if (l->expr_width() > r->expr_width())
|
||||
r->set_width(l->expr_width());
|
||||
|
||||
if (r->expr_width() > l->expr_width())
|
||||
l->set_width(r->expr_width());
|
||||
|
||||
if (l->expr_width() < r->expr_width())
|
||||
r->set_width(l->expr_width());
|
||||
|
||||
if (r->expr_width() < l->expr_width())
|
||||
l->set_width(r->expr_width());
|
||||
|
||||
if (r->expr_width() > l->expr_width())
|
||||
expr_width(r->expr_width());
|
||||
else
|
||||
@@ -1812,32 +1806,20 @@ NetEBAdd* NetEBAdd::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a bitwise operator node from the opcode and the left and
|
||||
* right expressions. Don't worry about the width of the expression
|
||||
* yet, we'll get that from the l-value, whatever that turns out to
|
||||
* be. However, if we don't, our default will be the width of the
|
||||
* largest operand.
|
||||
*/
|
||||
NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
/* First try to naturally adjust the size of the
|
||||
expressions to match. */
|
||||
if (l->expr_width() > r->expr_width())
|
||||
r->set_width(l->expr_width());
|
||||
|
||||
if (r->expr_width() > l->expr_width())
|
||||
l->set_width(r->expr_width());
|
||||
|
||||
if (l->expr_width() < r->expr_width())
|
||||
r->set_width(l->expr_width());
|
||||
|
||||
if (r->expr_width() < l->expr_width())
|
||||
l->set_width(r->expr_width());
|
||||
|
||||
/* If the expressions cannot be matched, pad them to fit. */
|
||||
if (l->expr_width() > r->expr_width())
|
||||
right_ = pad_to_width(r, l->expr_width());
|
||||
|
||||
if (r->expr_width() > l->expr_width())
|
||||
left_ = pad_to_width(l, r->expr_width());
|
||||
|
||||
assert(left_->expr_width() == right_->expr_width());
|
||||
expr_width(left_->expr_width());
|
||||
expr_width(r->expr_width());
|
||||
else
|
||||
expr_width(l->expr_width());
|
||||
}
|
||||
|
||||
NetEBBits::~NetEBBits()
|
||||
@@ -1900,6 +1882,11 @@ NetEBinary::~NetEBinary()
|
||||
delete right_;
|
||||
}
|
||||
|
||||
bool NetEBinary::has_width() const
|
||||
{
|
||||
return left_->has_width() && right_->has_width();
|
||||
}
|
||||
|
||||
NetEBinary* NetEBinary::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
@@ -2473,6 +2460,16 @@ bool NetUDP::sequ_glob_(string input, char output)
|
||||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.157 2001/02/10 21:20:38 steve
|
||||
* Binary operators with operands of indefinite width
|
||||
* has itself an indefinite width.
|
||||
*
|
||||
* Revision 1.156 2001/02/08 01:10:30 steve
|
||||
* Remove dead code.
|
||||
*
|
||||
* Revision 1.155 2001/02/07 21:47:13 steve
|
||||
* Fix expression widths for rvalues and parameters (PR#131,132)
|
||||
*
|
||||
* Revision 1.154 2001/01/18 03:16:35 steve
|
||||
* NetMux needs a scope. (PR#115)
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netlist.h,v 1.195 2001/01/18 03:16:35 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.200 2001/03/29 02:52:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -459,6 +459,10 @@ class NetCLShift : public NetNode {
|
||||
/*
|
||||
* This class supports the LPM_COMPARE device.
|
||||
*
|
||||
* The width of the device is the width of the inputs. If one of the
|
||||
* inputs is narrower then the other, it is up to the generator to
|
||||
* make sure all the data pins are properly driven.
|
||||
*
|
||||
* NOTE: This is not the same as the device used to support case
|
||||
* compare. Case comparisons handle Vx and Vz values, whereas this
|
||||
* device need not.
|
||||
@@ -843,9 +847,14 @@ class NetExpr : public LineInfo {
|
||||
// This returns true if the expression has a definite
|
||||
// width. This is generally true, but in some cases the
|
||||
// expression is amorphous and desires a width from its
|
||||
// environment.
|
||||
// environment. For example, 'd5 has indefinite width, but
|
||||
// 5'd5 has a definite width.
|
||||
|
||||
// This method is only really used within concatenation
|
||||
// expressions to check validity.
|
||||
virtual bool has_width() const;
|
||||
|
||||
|
||||
// This method evaluates the expression and returns an
|
||||
// equivilent expression that is reduced as far as compile
|
||||
// time knows how. Essentially, this is designed to fold
|
||||
@@ -1591,6 +1600,7 @@ class NetEvent : public LineInfo {
|
||||
// Get information about probes connected to me.
|
||||
unsigned nprobe() const;
|
||||
NetEvProbe* probe(unsigned);
|
||||
const NetEvProbe* probe(unsigned) const;
|
||||
|
||||
// Return the number of NetEvWait nodes that reference me.
|
||||
unsigned nwait() const;
|
||||
@@ -2078,6 +2088,11 @@ class NetEBinary : public NetExpr {
|
||||
|
||||
virtual bool set_width(unsigned w);
|
||||
|
||||
// A binary expression node only has a definite
|
||||
// self-determinable width if the operands both have definite
|
||||
// widths.
|
||||
virtual bool has_width() const;
|
||||
|
||||
virtual NetEBinary* dup_expr() const;
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
@@ -2182,7 +2197,10 @@ class NetEBComp : public NetEBinary {
|
||||
|
||||
private:
|
||||
NetEConst*eval_eqeq_();
|
||||
NetEConst*eval_less_();
|
||||
NetEConst*eval_leeq_();
|
||||
NetEConst*eval_gt_();
|
||||
NetEConst*eval_gteq_();
|
||||
NetEConst*eval_neeq_();
|
||||
NetEConst*eval_eqeqeq_();
|
||||
NetEConst*eval_neeqeq_();
|
||||
@@ -2852,6 +2870,23 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.200 2001/03/29 02:52:01 steve
|
||||
* Add const probe method to NetEvent.
|
||||
*
|
||||
* Revision 1.199 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.198 2001/02/10 21:20:38 steve
|
||||
* Binary operators with operands of indefinite width
|
||||
* has itself an indefinite width.
|
||||
*
|
||||
* Revision 1.197 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.196 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.195 2001/01/18 03:16:35 steve
|
||||
* NetMux needs a scope. (PR#115)
|
||||
*
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netmisc.cc,v 1.1 2001/02/11 02:15:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "PExpr.h"
|
||||
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
{
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
if (NetExpr*tmp2 = tmp->eval_tree()) {
|
||||
delete tmp;
|
||||
tmp = tmp2;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.1 2001/02/11 02:15:52 steve
|
||||
* Add the netmisc.cc source file.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netmisc.h,v 1.10 2000/11/20 00:58:40 steve Exp $"
|
||||
#ident "$Id: netmisc.h,v 1.12 2001/02/15 06:59:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -31,7 +31,7 @@
|
||||
* enough.
|
||||
*/
|
||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
|
||||
extern NetNet*pad_to_width(Design*des, const string&p, NetNet*n, unsigned w);
|
||||
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* This local function returns true if all the the possible drivers of
|
||||
@@ -54,9 +54,23 @@ extern verinum::V driven_value(const Link&lnk);
|
||||
*/
|
||||
extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
|
||||
/*
|
||||
* This function elaborates an expression, and tries to evaluate it
|
||||
* right away. It is useful for those places where the user is
|
||||
* supposed to supply a constant expression.
|
||||
*/
|
||||
class PExpr;
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
|
||||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.12 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.11 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.10 2000/11/20 00:58:40 steve
|
||||
* Add support for supply nets (PR#17)
|
||||
*
|
||||
@@ -69,32 +83,5 @@ extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
*
|
||||
* Revision 1.7 2000/05/14 17:55:04 steve
|
||||
* Support initialization of FF Q value.
|
||||
*
|
||||
* Revision 1.6 2000/05/07 04:37:56 steve
|
||||
* Carry strength values from Verilog source to the
|
||||
* pform and netlist for gates.
|
||||
*
|
||||
* Change vvm constants to use the driver_t to drive
|
||||
* a constant value. This works better if there are
|
||||
* multiple drivers on a signal.
|
||||
*
|
||||
* Revision 1.5 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.4 2000/03/16 19:03:03 steve
|
||||
* Revise the VVM backend to use nexus objects so that
|
||||
* drivers and resolution functions can be used, and
|
||||
* the t-vvm module doesn't need to write a zillion
|
||||
* output functions.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.1 1999/09/29 00:42:51 steve
|
||||
* Allow expanding of additive operators.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+10
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: nodangle.cc,v 1.10 2000/11/19 20:48:53 steve Exp $"
|
||||
#ident "$Id: nodangle.cc,v 1.11 2001/02/17 05:14:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -58,6 +58,12 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
||||
if (sig->get_eref() > 0)
|
||||
return;
|
||||
|
||||
/* Cannot delete the ports of tasks. There are too many places
|
||||
where they are referenced. */
|
||||
if ((sig->port_type() != NetNet::NOT_A_PORT)
|
||||
&& (sig->scope()->type() == NetScope::TASK))
|
||||
return;
|
||||
|
||||
/* Check to see if the signal is completely unconnected. If
|
||||
all the bits are unlinked, then delete it. */
|
||||
unsigned unlinked = 0;
|
||||
@@ -118,6 +124,9 @@ void nodangle(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: nodangle.cc,v $
|
||||
* Revision 1.11 2001/02/17 05:14:35 steve
|
||||
* Cannot elide task ports.
|
||||
*
|
||||
* Revision 1.10 2000/11/19 20:48:53 steve
|
||||
* Killing some signals might make others killable.
|
||||
*
|
||||
|
||||
+12
-5
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pad_to_width.cc,v 1.5 2000/05/02 00:58:12 steve Exp $"
|
||||
#ident "$Id: pad_to_width.cc,v 1.7 2001/02/16 03:25:09 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -45,19 +45,20 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
|
||||
return expr;
|
||||
}
|
||||
|
||||
NetNet*pad_to_width(Design*des, const string&path, NetNet*net, unsigned wid)
|
||||
NetNet*pad_to_width(Design*des, NetNet*net, unsigned wid)
|
||||
{
|
||||
NetScope*scope = des->find_scope(path);
|
||||
NetScope*scope = net->scope();
|
||||
const string path = scope->name();
|
||||
assert(scope);
|
||||
|
||||
if (net->pin_count() >= wid)
|
||||
return net;
|
||||
|
||||
verinum pad(verinum::V0, wid - net->pin_count());
|
||||
NetConst*con = new NetConst(des->local_symbol(path), pad);
|
||||
NetConst*con = new NetConst(path + "." + scope->local_symbol(), pad);
|
||||
des->add_node(con);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, des->local_symbol(path),
|
||||
NetNet*tmp = new NetNet(scope, path + "." + scope->local_symbol(),
|
||||
NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
|
||||
@@ -71,6 +72,12 @@ NetNet*pad_to_width(Design*des, const string&path, NetNet*net, unsigned wid)
|
||||
|
||||
/*
|
||||
* $Log: pad_to_width.cc,v $
|
||||
* Revision 1.7 2001/02/16 03:25:09 steve
|
||||
* Missing . in names generated from scope locals.
|
||||
*
|
||||
* Revision 1.6 2001/02/15 06:59:36 steve
|
||||
* FreeBSD port has a maintainer now.
|
||||
*
|
||||
* Revision 1.5 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform.cc,v 1.73 2001/01/15 00:47:01 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.74 2001/02/17 05:15:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compiler.h"
|
||||
@@ -645,14 +645,21 @@ void pform_makewire(const vlltype&li, const string&nm,
|
||||
const string name = scoped_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur) {
|
||||
if (cur->get_wire_type() != NetNet::IMPLICIT) {
|
||||
if ((cur->get_wire_type() != NetNet::IMPLICIT)
|
||||
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
|
||||
strstream msg;
|
||||
msg << name << " previously defined at " <<
|
||||
cur->get_line() << "." << ends;
|
||||
VLerror(msg.str());
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
assert(rc);
|
||||
if (rc == false) {
|
||||
strstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< "." << ends;
|
||||
VLerror(msg.str());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1003,6 +1010,9 @@ int pform_parse(const char*path, map<string,Module*>&modules,
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.74 2001/02/17 05:15:33 steve
|
||||
* Allow task ports to be given real types.
|
||||
*
|
||||
* Revision 1.73 2001/01/15 00:47:01 steve
|
||||
* Pass scope type information to the target module.
|
||||
*
|
||||
|
||||
+38
-8
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: set_width.cc,v 1.15 2001/01/27 05:41:48 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.17 2001/02/08 01:10:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -105,18 +105,42 @@ bool NetEBAdd::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* The bitwise logical operators have operands the same size as the
|
||||
* result. Anything else is a mess.
|
||||
* 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 flag = true;
|
||||
/* First, give the operands a chance to adjust themselves to
|
||||
the requested width. */
|
||||
left_->set_width(w);
|
||||
right_->set_width(w);
|
||||
|
||||
flag = left_->set_width(w) && flag;
|
||||
flag = right_->set_width(w) && flag;
|
||||
if (flag)
|
||||
expr_width(w);
|
||||
|
||||
return flag;
|
||||
/* */
|
||||
|
||||
unsigned use_width = w;
|
||||
|
||||
|
||||
/* If the operands end up too small, then pad them to suit. */
|
||||
|
||||
if (left_->expr_width() < use_width) {
|
||||
NetExpr*tmp = pad_to_width(left_, use_width);
|
||||
assert(tmp);
|
||||
left_ = tmp;
|
||||
}
|
||||
|
||||
if (right_->expr_width() < w) {
|
||||
NetExpr*tmp = pad_to_width(right_, use_width);
|
||||
assert(tmp);
|
||||
right_ = tmp;
|
||||
}
|
||||
|
||||
|
||||
/* And here is the final width. If this is not the size the
|
||||
caller requested, then return false. Otherwise, return
|
||||
true. */
|
||||
expr_width(use_width);
|
||||
return w == use_width;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -313,6 +337,12 @@ bool NetEUnary::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.17 2001/02/08 01:10:30 steve
|
||||
* Remove dead code.
|
||||
*
|
||||
* Revision 1.16 2001/02/07 21:47:13 steve
|
||||
* Fix expression widths for rvalues and parameters (PR#131,132)
|
||||
*
|
||||
* Revision 1.15 2001/01/27 05:41:48 steve
|
||||
* Fix sign extension of evaluated constants. (PR#91)
|
||||
*
|
||||
|
||||
+165
-8
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-dll-api.cc,v 1.21 2001/01/15 00:47:02 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.28 2001/03/31 17:36:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "t-dll.h"
|
||||
@@ -85,6 +85,39 @@ extern "C" int ivl_const_signed(ivl_net_const_t net)
|
||||
return net->signed_ == 1;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_event_name(ivl_event_t net)
|
||||
{
|
||||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_event_basename(ivl_event_t net)
|
||||
{
|
||||
const char*nam = net->name;
|
||||
nam += strlen(ivl_scope_name(net->scope));
|
||||
assert(*nam == '.');
|
||||
nam += 1;
|
||||
return nam;
|
||||
}
|
||||
|
||||
extern "C" ivl_edge_type_t ivl_event_edge(ivl_event_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->edge;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_event_pins(ivl_event_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->npins;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_event_pin(ivl_event_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->npins);
|
||||
return net->pins[idx];
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_expr_bits(ivl_expr_t net)
|
||||
{
|
||||
assert(net && (net->type_ == IVL_EX_NUMBER));
|
||||
@@ -114,6 +147,9 @@ extern "C" char ivl_expr_opcode(ivl_expr_t net)
|
||||
case IVL_EX_BINARY:
|
||||
return net->u_.binary_.op_;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
return net->u_.unary_.op_;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -127,6 +163,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
|
||||
case IVL_EX_BINARY:
|
||||
return net->u_.binary_.lef_;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
return net->u_.unary_.sub_;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -362,6 +401,11 @@ extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net)
|
||||
return net->type_;
|
||||
}
|
||||
|
||||
extern "C" ivl_scope_t ivl_process_scope(ivl_process_t net)
|
||||
{
|
||||
return net->scope_;
|
||||
}
|
||||
|
||||
extern "C" ivl_statement_t ivl_process_stmt(ivl_process_t net)
|
||||
{
|
||||
return net->stmt_;
|
||||
@@ -380,6 +424,19 @@ extern "C" int ivl_scope_children(ivl_scope_t net,
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_events(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->nevent_;
|
||||
}
|
||||
|
||||
extern "C" ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->nevent_);
|
||||
return net->event_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_logs(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -500,22 +557,87 @@ extern "C" ivl_statement_type_t ivl_statement_type(ivl_statement_t net)
|
||||
|
||||
extern "C" unsigned ivl_stmt_block_count(ivl_statement_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_ST_BLOCK);
|
||||
return net->u_.block_.nstmt_;
|
||||
switch (net->type_) {
|
||||
case IVL_ST_BLOCK:
|
||||
case IVL_ST_FORK:
|
||||
return net->u_.block_.nstmt_;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net,
|
||||
unsigned i)
|
||||
{
|
||||
assert(net->type_ == IVL_ST_BLOCK);
|
||||
assert(i < net->u_.block_.nstmt_);
|
||||
return net->u_.block_.stmt_ + i;
|
||||
switch (net->type_) {
|
||||
case IVL_ST_BLOCK:
|
||||
case IVL_ST_FORK:
|
||||
return net->u_.block_.stmt_ + i;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_stmt_case_count(ivl_statement_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASE:
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
return net->u_.case_.ncase;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_stmt_case_expr(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASE:
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
assert(idx < net->u_.case_.ncase);
|
||||
return net->u_.case_.case_ex[idx];
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_statement_t ivl_stmt_case_stmt(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CASE:
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
assert(idx < net->u_.case_.ncase);
|
||||
return net->u_.case_.case_st + idx;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_stmt_cond_expr(ivl_statement_t net)
|
||||
{
|
||||
assert(net && (net->type_ == IVL_ST_CONDIT));
|
||||
return net->u_.condit_.cond_;
|
||||
switch (net->type_) {
|
||||
case IVL_ST_CONDIT:
|
||||
return net->u_.condit_.cond_;
|
||||
|
||||
case IVL_ST_CASE:
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
return net->u_.case_.cond;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_statement_t ivl_stmt_cond_false(ivl_statement_t net)
|
||||
@@ -542,6 +664,19 @@ extern "C" unsigned long ivl_stmt_delay_val(ivl_statement_t net)
|
||||
return net->u_.delay_.delay_;
|
||||
}
|
||||
|
||||
extern "C" ivl_event_t ivl_stmt_event(ivl_statement_t net)
|
||||
{
|
||||
switch (net->type_) {
|
||||
case IVL_ST_WAIT:
|
||||
return net->u_.wait_.event_;
|
||||
case IVL_ST_TRIGGER:
|
||||
return net->u_.trig_.event_;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" ivl_lval_t ivl_stmt_lval(ivl_statement_t net, unsigned idx)
|
||||
{
|
||||
switch (net->type_) {
|
||||
@@ -646,6 +781,28 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.28 2001/03/31 17:36:38 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.27 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.26 2001/03/29 03:47:38 steve
|
||||
* Behavioral trigger statements.
|
||||
*
|
||||
* Revision 1.25 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.24 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.23 2001/03/27 06:27:40 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.22 2001/03/20 01:44:13 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.21 2001/01/15 00:47:02 steve
|
||||
* Pass scope type information to the target module.
|
||||
*
|
||||
|
||||
+20
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) & !defined(macintosh)
|
||||
#ident "$Id: t-dll-expr.cc,v 1.7 2000/10/28 22:32:34 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.8 2001/03/29 02:52:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "t-dll.h"
|
||||
@@ -144,8 +144,27 @@ void dll_target::expr_signal(const NetESignal*net)
|
||||
expr_->u_.subsig_.name_ = strdup(net->name().c_str());
|
||||
}
|
||||
|
||||
void dll_target::expr_unary(const NetEUnary*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
|
||||
net->expr()->expr_scan(this);
|
||||
assert(expr_);
|
||||
|
||||
ivl_expr_t sub = expr_;
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
expr_->type_ = IVL_EX_UNARY;
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->u_.unary_.op_ = net->op();
|
||||
expr_->u_.unary_.sub_ = sub;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.8 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.7 2000/10/28 22:32:34 steve
|
||||
* API for concatenation expressions.
|
||||
*
|
||||
|
||||
+135
-2
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-dll-proc.cc,v 1.10 2000/10/18 20:04:39 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.17 2001/03/31 17:36:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -44,6 +44,10 @@ bool dll_target::process(const NetProcTop*net)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Save the scope of the process. */
|
||||
obj->scope_ = lookup_scope_(net->scope());
|
||||
|
||||
|
||||
/* This little bit causes the process to be completely
|
||||
generated so that it can be passed to the DLL. The
|
||||
stmt_cur_ member us used to hold a pointer to the current
|
||||
@@ -148,7 +152,9 @@ bool dll_target::proc_block(const NetBlock*net)
|
||||
it, so fill in the block fields of the existing statement,
|
||||
and generate the contents for the statement array. */
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_BLOCK;
|
||||
stmt_cur_->type_ = (net->type() == NetBlock::SEQU)
|
||||
? IVL_ST_BLOCK
|
||||
: IVL_ST_FORK;
|
||||
stmt_cur_->u_.block_.nstmt_ = count;
|
||||
stmt_cur_->u_.block_.stmt_ = (struct ivl_statement_s*)
|
||||
calloc(count, sizeof(struct ivl_statement_s));
|
||||
@@ -171,6 +177,54 @@ bool dll_target::proc_block(const NetBlock*net)
|
||||
return flag;
|
||||
}
|
||||
|
||||
void dll_target::proc_case(const NetCase*net)
|
||||
{
|
||||
assert(stmt_cur_);
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
switch (net->type()) {
|
||||
case NetCase::EQ:
|
||||
stmt_cur_->type_ = IVL_ST_CASE;
|
||||
break;
|
||||
case NetCase::EQX:
|
||||
stmt_cur_->type_ = IVL_ST_CASEX;
|
||||
break;
|
||||
case NetCase::EQZ:
|
||||
stmt_cur_->type_ = IVL_ST_CASEZ;
|
||||
break;
|
||||
}
|
||||
assert(stmt_cur_->type_ != IVL_ST_NONE);
|
||||
|
||||
assert(expr_ == 0);
|
||||
net->expr()->expr_scan(this);
|
||||
stmt_cur_->u_.case_.cond = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
unsigned ncase = net->nitems();
|
||||
stmt_cur_->u_.case_.ncase = ncase;
|
||||
|
||||
stmt_cur_->u_.case_.case_ex = new ivl_expr_t[ncase];
|
||||
stmt_cur_->u_.case_.case_st = new struct ivl_statement_s[ncase];
|
||||
|
||||
ivl_statement_t save_cur = stmt_cur_;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ncase ; idx += 1) {
|
||||
const NetExpr*ex = net->expr(idx);
|
||||
if (ex) {
|
||||
net->expr(idx)->expr_scan(this);
|
||||
save_cur->u_.case_.case_ex[idx] = expr_;
|
||||
expr_ = 0;
|
||||
} else {
|
||||
save_cur->u_.case_.case_ex[idx] = 0;
|
||||
}
|
||||
|
||||
stmt_cur_ = save_cur->u_.case_.case_st + idx;
|
||||
net->stat(idx)->emit_proc(this);
|
||||
}
|
||||
|
||||
stmt_cur_ = save_cur;
|
||||
}
|
||||
|
||||
void dll_target::proc_condit(const NetCondit*net)
|
||||
{
|
||||
assert(stmt_cur_);
|
||||
@@ -258,6 +312,21 @@ bool dll_target::proc_trigger(const NetEvTrig*net)
|
||||
assert(stmt_cur_->type_ == IVL_ST_NONE);
|
||||
|
||||
stmt_cur_->type_ = IVL_ST_TRIGGER;
|
||||
|
||||
/* Locate the event by name. Save the ivl_event_t in the
|
||||
statement so that the generator can find it easily. */
|
||||
const NetEvent*ev = net->event();
|
||||
ivl_scope_t ev_scope = lookup_scope_(ev->scope());
|
||||
|
||||
for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
|
||||
const char*ename = ivl_event_basename(ev_scope->event_[idx]);
|
||||
if (strcmp(ev->name(), ename) == 0) {
|
||||
stmt_cur_->u_.wait_.event_ = ev_scope->event_[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -270,9 +339,51 @@ bool dll_target::proc_wait(const NetEvWait*net)
|
||||
stmt_cur_->u_.wait_.stmt_ = (struct ivl_statement_s*)
|
||||
calloc(1, sizeof(struct ivl_statement_s));
|
||||
|
||||
if (net->nevents() != 1) {
|
||||
cerr << "internal error: multiple events not supported." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Locate the event by name. Save the ivl_event_t in the
|
||||
statement so that the generator can find it easily. */
|
||||
const NetEvent*ev = net->event(0);
|
||||
ivl_scope_t ev_scope = lookup_scope_(ev->scope());
|
||||
|
||||
for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
|
||||
const char*ename = ivl_event_basename(ev_scope->event_[idx]);
|
||||
if (strcmp(ev->name(), ename) == 0) {
|
||||
stmt_cur_->u_.wait_.event_ = ev_scope->event_[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is an event with a probe, then connect up the
|
||||
pins. This wasn't done during the ::event method because
|
||||
the signals weren't scanned yet. */
|
||||
|
||||
if (ev->nprobe() == 1) {
|
||||
const NetEvProbe*pr = ev->probe(0);
|
||||
ivl_event_t evnt = stmt_cur_->u_.wait_.event_;
|
||||
|
||||
assert(pr->pin_count() == evnt->npins);
|
||||
|
||||
for (unsigned idx = 0 ; idx < evnt->npins ; idx += 1) {
|
||||
ivl_nexus_t nex = (ivl_nexus_t)
|
||||
pr->pin(idx).nexus()->t_cookie();
|
||||
assert(nex);
|
||||
evnt->pins[idx] = nex;
|
||||
}
|
||||
}
|
||||
|
||||
/* The ivl_statement_t for the wait statement is not complete
|
||||
until we calculate the sub-statement. */
|
||||
|
||||
ivl_statement_t save_cur_ = stmt_cur_;
|
||||
stmt_cur_ = stmt_cur_->u_.wait_.stmt_;
|
||||
bool flag = net->emit_recurse(this);
|
||||
if (flag && (stmt_cur_->type_ == IVL_ST_NONE))
|
||||
stmt_cur_->type_ = IVL_ST_NOOP;
|
||||
|
||||
stmt_cur_ = save_cur_;
|
||||
|
||||
return flag;
|
||||
@@ -301,6 +412,28 @@ void dll_target::proc_while(const NetWhile*net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.17 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.16 2001/03/30 23:24:02 steve
|
||||
* Make empty event sub-expression a noop.
|
||||
*
|
||||
* Revision 1.15 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.14 2001/03/29 03:47:38 steve
|
||||
* Behavioral trigger statements.
|
||||
*
|
||||
* Revision 1.13 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.12 2001/03/27 06:27:40 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.11 2001/03/20 01:44:14 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.10 2000/10/18 20:04:39 steve
|
||||
* Add ivl_lval_t and support for assignment l-values.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-dll.cc,v 1.27 2001/01/15 22:08:32 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.31 2001/03/30 06:10:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compiler.h"
|
||||
@@ -78,6 +78,11 @@ static ivl_scope_t find_scope(ivl_scope_t root, const NetScope*cur)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_scope_t dll_target::lookup_scope_(const NetScope*cur)
|
||||
{
|
||||
return find_scope(des_.root_, cur);
|
||||
}
|
||||
|
||||
static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
|
||||
{
|
||||
ivl_nexus_t tmp = new struct ivl_nexus_s;
|
||||
@@ -155,6 +160,22 @@ void scope_add_logic(ivl_scope_t scope, ivl_net_logic_t net)
|
||||
|
||||
}
|
||||
|
||||
void scope_add_event(ivl_scope_t scope, ivl_event_t net)
|
||||
{
|
||||
if (scope->nevent_ == 0) {
|
||||
scope->nevent_ = 1;
|
||||
scope->event_ = (ivl_event_t*)malloc(sizeof(ivl_event_t));
|
||||
scope->event_[0] = net;
|
||||
|
||||
} else {
|
||||
scope->nevent_ += 1;
|
||||
scope->event_ = (ivl_event_t*)
|
||||
realloc(scope->event_, scope->nevent_*sizeof(ivl_event_t));
|
||||
scope->event_[scope->nevent_-1] = net;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void scope_add_lpm(ivl_scope_t scope, ivl_lpm_t net)
|
||||
{
|
||||
if (scope->nlpm_ == 0) {
|
||||
@@ -194,6 +215,8 @@ bool dll_target::start_design(const Design*des)
|
||||
des_.root_->sigs_ = 0;
|
||||
des_.root_->nlog_ = 0;
|
||||
des_.root_->log_ = 0;
|
||||
des_.root_->nevent_ = 0;
|
||||
des_.root_->event_ = 0;
|
||||
des_.root_->nlpm_ = 0;
|
||||
des_.root_->lpm_ = 0;
|
||||
des_.root_->type_ = IVL_SCT_MODULE;
|
||||
@@ -213,10 +236,11 @@ bool dll_target::start_design(const Design*des)
|
||||
* Here ivl is telling us that the design is scanned completely, and
|
||||
* here is where we call the API to process the constructed design.
|
||||
*/
|
||||
void dll_target::end_design(const Design*)
|
||||
int dll_target::end_design(const Design*)
|
||||
{
|
||||
(target_)(&des_);
|
||||
int rc = (target_)(&des_);
|
||||
ivl_dlclose(dll_);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -267,6 +291,38 @@ bool dll_target::bufz(const NetBUFZ*net)
|
||||
|
||||
void dll_target::event(const NetEvent*net)
|
||||
{
|
||||
struct ivl_event_s *obj = new struct ivl_event_s;
|
||||
|
||||
ivl_scope_t scope = find_scope(des_.root_, net->scope());
|
||||
obj->name = strdup(net->full_name().c_str());
|
||||
obj->scope = scope;
|
||||
scope_add_event(scope, obj);
|
||||
|
||||
assert(net->nprobe() <= 1);
|
||||
|
||||
if (net->nprobe() == 1) {
|
||||
const NetEvProbe*pr = net->probe(0);
|
||||
switch (pr->edge()) {
|
||||
case NetEvProbe::ANYEDGE:
|
||||
obj->edge = IVL_EDGE_ANY;
|
||||
break;
|
||||
case NetEvProbe::NEGEDGE:
|
||||
obj->edge = IVL_EDGE_NEG;
|
||||
break;
|
||||
case NetEvProbe::POSEDGE:
|
||||
obj->edge = IVL_EDGE_POS;
|
||||
break;
|
||||
}
|
||||
|
||||
obj->npins = pr->pin_count();
|
||||
obj->pins = (ivl_nexus_t*)calloc(obj->npins, sizeof(ivl_nexus_t));
|
||||
|
||||
} else {
|
||||
obj->npins = 0;
|
||||
obj->pins = 0;
|
||||
obj->edge = IVL_EDGE_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void dll_target::logic(const NetLogic*net)
|
||||
@@ -483,6 +539,8 @@ void dll_target::scope(const NetScope*net)
|
||||
scope->sigs_ = 0;
|
||||
scope->nlog_ = 0;
|
||||
scope->log_ = 0;
|
||||
scope->nevent_ = 0;
|
||||
scope->event_ = 0;
|
||||
scope->nlpm_ = 0;
|
||||
scope->lpm_ = 0;
|
||||
|
||||
@@ -685,6 +743,19 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.31 2001/03/30 06:10:15 steve
|
||||
* Initialize the event_ list of new scopes.
|
||||
*
|
||||
* Revision 1.30 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.29 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.28 2001/03/20 01:44:14 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.27 2001/01/15 22:08:32 steve
|
||||
* Add missing NetLogic gate types to ::logic method.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-dll.h,v 1.21 2001/01/15 00:47:02 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.28 2001/03/31 17:36:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -52,7 +52,7 @@ struct ivl_design_s {
|
||||
struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
bool start_design(const Design*);
|
||||
void end_design(const Design*);
|
||||
int end_design(const Design*);
|
||||
|
||||
bool bufz(const NetBUFZ*);
|
||||
void event(const NetEvent*);
|
||||
@@ -79,6 +79,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
struct ivl_statement_s*stmt_cur_;
|
||||
void proc_assign(const NetAssign*);
|
||||
bool proc_block(const NetBlock*);
|
||||
void proc_case(const NetCase*);
|
||||
void proc_condit(const NetCondit*);
|
||||
bool proc_delay(const NetPDelay*);
|
||||
void proc_stask(const NetSTask*);
|
||||
@@ -91,13 +92,24 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void expr_concat(const NetEConcat*);
|
||||
void expr_const(const NetEConst*);
|
||||
void expr_sfunc(const NetESFunc*);
|
||||
void expr_unary(const NetEUnary*);
|
||||
void expr_signal(const NetESignal*);
|
||||
|
||||
ivl_scope_t lookup_scope_(const NetScope*scope);
|
||||
};
|
||||
|
||||
/*
|
||||
* These are various private declarations used by the t-dll target.
|
||||
*/
|
||||
|
||||
struct ivl_event_s {
|
||||
char*name;
|
||||
ivl_scope_t scope;
|
||||
ivl_edge_type_t edge;
|
||||
unsigned npins;
|
||||
ivl_nexus_t*pins;
|
||||
};
|
||||
|
||||
/*
|
||||
* The ivl_expr_t is an opaque reference to one of these
|
||||
* structures. This structure holds all the information we need about
|
||||
@@ -140,6 +152,12 @@ struct ivl_expr_s {
|
||||
ivl_expr_t msb_;
|
||||
ivl_expr_t lsb_;
|
||||
} subsig_;
|
||||
|
||||
struct {
|
||||
char op_;
|
||||
ivl_expr_t sub_;
|
||||
} unary_;
|
||||
|
||||
} u_;
|
||||
};
|
||||
|
||||
@@ -247,10 +265,12 @@ struct ivl_nexus_s {
|
||||
|
||||
/*
|
||||
* All we know about a process it its type (initial or always) and the
|
||||
* single statement that is it.
|
||||
* single statement that is it. A process also has a scope, although
|
||||
* that generally only matters for VPI calls.
|
||||
*/
|
||||
struct ivl_process_s {
|
||||
ivl_process_type_t type_;
|
||||
ivl_scope_t scope_;
|
||||
ivl_statement_t stmt_;
|
||||
|
||||
ivl_process_t next_;
|
||||
@@ -275,6 +295,9 @@ struct ivl_scope_s {
|
||||
unsigned nlog_;
|
||||
ivl_net_logic_t*log_;
|
||||
|
||||
unsigned nevent_;
|
||||
ivl_event_t* event_;
|
||||
|
||||
unsigned nlpm_;
|
||||
ivl_lpm_t* lpm_;
|
||||
};
|
||||
@@ -319,11 +342,18 @@ struct ivl_statement_s {
|
||||
ivl_expr_t rval_;
|
||||
} assign_;
|
||||
|
||||
struct { /* IVL_ST_BLOCK */
|
||||
struct { /* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
struct ivl_statement_s*stmt_;
|
||||
unsigned nstmt_;
|
||||
} block_;
|
||||
|
||||
struct { /* IVL_ST_CASE, IVL_ST_CASEX, IVL_ST_CASEZ */
|
||||
ivl_expr_t cond;
|
||||
unsigned ncase;
|
||||
ivl_expr_t*case_ex;
|
||||
struct ivl_statement_s*case_st;
|
||||
} case_;
|
||||
|
||||
struct { /* IVL_ST_CONDIT */
|
||||
/* This is the condition expression */
|
||||
ivl_expr_t cond_;
|
||||
@@ -348,11 +378,11 @@ struct ivl_statement_s {
|
||||
} stask_;
|
||||
|
||||
struct { /* IVL_ST_TRIGGER */
|
||||
ivl_net_event_t event_;
|
||||
ivl_event_t event_;
|
||||
} trig_;
|
||||
|
||||
struct { /* IVL_ST_WAIT */
|
||||
int cond_; /* XXXX */
|
||||
ivl_event_t event_;
|
||||
ivl_statement_t stmt_;
|
||||
} wait_;
|
||||
|
||||
@@ -365,6 +395,28 @@ struct ivl_statement_s {
|
||||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.28 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.27 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.26 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.25 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.24 2001/03/27 06:27:40 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.23 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.22 2001/03/20 01:44:14 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.21 2001/01/15 00:47:02 steve
|
||||
* Pass scope type information to the target module.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-vvm.cc,v 1.201 2001/01/16 03:57:46 steve Exp $"
|
||||
#ident "$Id: t-vvm.cc,v 1.203 2001/03/27 03:31:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
@@ -203,7 +203,7 @@ class target_vvm : public target_t {
|
||||
virtual void proc_utask( const NetUTask*);
|
||||
virtual bool proc_wait( const NetEvWait*);
|
||||
virtual void proc_while(const NetWhile*);
|
||||
virtual void end_design(const Design*);
|
||||
virtual int end_design(const Design*);
|
||||
|
||||
void start_process(ostream&os, const NetProcTop*);
|
||||
void end_process(ostream&os, const NetProcTop*);
|
||||
@@ -1047,7 +1047,7 @@ void target_vvm::event(const NetEvent*event)
|
||||
<< event->get_line() << ": event " << event->full_name() << endl;
|
||||
}
|
||||
|
||||
void target_vvm::end_design(const Design*mod)
|
||||
int target_vvm::end_design(const Design*mod)
|
||||
{
|
||||
if (string_counter > 0)
|
||||
out << "static struct __vpiStringConst string_table[" <<
|
||||
@@ -1157,6 +1157,7 @@ void target_vvm::end_design(const Design*mod)
|
||||
out << "}" << endl;
|
||||
out.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool target_vvm::process(const NetProcTop*top)
|
||||
@@ -3196,7 +3197,11 @@ void target_vvm::proc_condit(const NetCondit*net)
|
||||
out << "static bool " << thread_class_ << "_step_"
|
||||
<< out_step << "_(vvm_thread*thr);" << endl;
|
||||
|
||||
defn << " if (B_IS1(" << expr << "[0]))" << endl;
|
||||
if (net->expr()->expr_width() == 1)
|
||||
defn << " if (B_IS1(" << expr << "[0]))" << endl;
|
||||
else
|
||||
defn << " if (B_IS1(vvm_unop_or(" << expr << ")))" << endl;
|
||||
|
||||
defn << " thr->step_ = &" << thread_class_ << "_step_" <<
|
||||
if_step << "_;" << endl;
|
||||
defn << " else" << endl;
|
||||
@@ -3548,7 +3553,11 @@ void target_vvm::proc_while(const NetWhile*net)
|
||||
|
||||
defn << "// " << net->expr()->get_line() <<
|
||||
": test while condition." << endl;
|
||||
defn << " if (!B_IS1(" << expr << "[0])) {" << endl;
|
||||
if (net->expr()->expr_width() == 1) {
|
||||
defn << " if (!B_IS1(" << expr << "[0])) {" << endl;
|
||||
} else {
|
||||
defn << " if (!B_IS1(vvm_unop_or(" << expr << "))) {" << endl;
|
||||
}
|
||||
defn << " thr->step_ = &" << thread_class_ << "_step_"
|
||||
<< out_step << "_;" << endl;
|
||||
defn << " return true;" << endl;
|
||||
@@ -3627,6 +3636,12 @@ extern const struct target tgt_vvm = {
|
||||
};
|
||||
/*
|
||||
* $Log: t-vvm.cc,v $
|
||||
* Revision 1.203 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.202 2001/02/13 04:11:24 steve
|
||||
* Generate proper code for wide condition expressions.
|
||||
*
|
||||
* Revision 1.201 2001/01/16 03:57:46 steve
|
||||
* Get rid of gate templates.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-xnf.cc,v 1.39 2000/11/29 23:15:54 steve Exp $"
|
||||
#ident "$Id: t-xnf.cc,v 1.41 2001/03/27 03:31:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* XNF BACKEND
|
||||
@@ -95,7 +95,7 @@ class target_xnf : public target_t {
|
||||
|
||||
public:
|
||||
bool start_design(const Design*);
|
||||
void end_design(const Design*);
|
||||
int end_design(const Design*);
|
||||
void memory(const NetMemory*);
|
||||
void signal(const NetNet*);
|
||||
|
||||
@@ -238,10 +238,11 @@ bool target_xnf::start_design(const Design*des)
|
||||
return true;
|
||||
}
|
||||
|
||||
void target_xnf::end_design(const Design*)
|
||||
int target_xnf::end_design(const Design*)
|
||||
{
|
||||
out_ << "EOF" << endl;
|
||||
ncf_.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scrape_pad_info(string str, char&dir, unsigned&num)
|
||||
@@ -771,19 +772,31 @@ void target_xnf::lpm_ram_dq(const NetRamDq*ram)
|
||||
|
||||
bool target_xnf::net_const(const NetConst*c)
|
||||
{
|
||||
unsigned x_bits = 0;
|
||||
for (unsigned idx = 0 ; idx < c->pin_count() ; idx += 1) {
|
||||
verinum::V v=c->value(idx);
|
||||
assert(v==verinum::V0 || v==verinum::V1);
|
||||
const Link& lnk = c->pin(idx);
|
||||
// Code parallels draw_pin above, some smart c++ guru should
|
||||
// find a way to make a method out of this.
|
||||
unsigned cpin;
|
||||
const NetObj*cur;
|
||||
|
||||
out_ << " PWR, " << v << ", " << choose_sig_name(&lnk) << endl;
|
||||
switch (v) {
|
||||
case verinum::V0:
|
||||
out_ << " PWR, 0, " << choose_sig_name(&lnk) << endl;
|
||||
break;
|
||||
case verinum::V1:
|
||||
out_ << " PWR, 1, " << choose_sig_name(&lnk) << endl;
|
||||
break;
|
||||
case verinum::Vz:
|
||||
break;
|
||||
default:
|
||||
x_bits += 1;
|
||||
if (x_bits == 1)
|
||||
cerr << "xnf: error: Unknown (x) const bit value"
|
||||
<< " assigned to " << choose_sig_name(&lnk)
|
||||
<< endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return x_bits == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -910,6 +923,12 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-xnf.cc,v $
|
||||
* Revision 1.41 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.40 2001/02/10 03:22:49 steve
|
||||
* Report errors when XNF code has constant X values. (PR#128)
|
||||
*
|
||||
* Revision 1.39 2000/11/29 23:15:54 steve
|
||||
* More informative BUFZ warning.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: target.cc,v 1.49 2000/09/26 01:35:42 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.50 2001/03/27 03:31:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -312,8 +312,9 @@ void target_t::proc_while(const NetWhile*net)
|
||||
net->dump(cerr, 6);
|
||||
}
|
||||
|
||||
void target_t::end_design(const Design*)
|
||||
int target_t::end_design(const Design*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr_scan_t::~expr_scan_t()
|
||||
@@ -388,6 +389,9 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.50 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.49 2000/09/26 01:35:42 steve
|
||||
* Remove the obsolete NetEIdent class.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: target.h,v 1.48 2000/11/04 01:54:01 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.49 2001/03/27 03:31:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -121,8 +121,9 @@ struct target_t {
|
||||
virtual bool proc_wait(const NetEvWait*);
|
||||
virtual void proc_while(const NetWhile*);
|
||||
|
||||
/* Done with the design. */
|
||||
virtual void end_design(const Design*);
|
||||
/* Done with the design. The target returns !0 if there is
|
||||
some error in the code generation. */
|
||||
virtual int end_design(const Design*);
|
||||
};
|
||||
|
||||
/* This class is used by the NetExpr class to help with the scanning
|
||||
@@ -159,6 +160,9 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.49 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.48 2000/11/04 01:54:01 steve
|
||||
* Modifications in support of gcc 2.96
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,14 +17,14 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: null.c,v 1.1 2000/12/02 04:50:32 steve Exp $"
|
||||
#ident "$Id: null.c,v 1.2 2001/02/07 22:21:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a null target module. It does nothing.
|
||||
*/
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "ivl_target.h"
|
||||
|
||||
|
||||
int target_design(ivl_design_t des)
|
||||
@@ -39,6 +39,9 @@ DECLARE_CYGWIN_DLL(DllMain);
|
||||
|
||||
/*
|
||||
* $Log: null.c,v $
|
||||
* Revision 1.2 2001/02/07 22:21:59 steve
|
||||
* ivl_target header search path fixes.
|
||||
*
|
||||
* Revision 1.1 2000/12/02 04:50:32 steve
|
||||
* Make the null target into a loadable target.
|
||||
*
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.6 2001/01/18 03:09:45 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7 2001/02/07 22:22:00 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -47,7 +47,7 @@ all: pal.tgt
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) -I$(srcdir)/.. -MD -c $< -o $*.o
|
||||
$(CC) -Wall -I$(srcdir)/.. $(CPPFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = imain.o dump_final.o emit_jed.o enables.o fit_log.o fit_reg.o pads.o
|
||||
|
||||
+5
-2
@@ -16,9 +16,9 @@
|
||||
* 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: enables.c,v 1.2 2000/12/09 03:42:52 steve Exp $"
|
||||
#ident "$Id: enables.c,v 1.3 2001/02/07 22:22:00 steve Exp $"
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "ivl_target.h"
|
||||
# include <assert.h>
|
||||
# include "priv.h"
|
||||
|
||||
@@ -77,6 +77,9 @@ void absorb_pad_enables(void)
|
||||
|
||||
/*
|
||||
* $Log: enables.c,v $
|
||||
* Revision 1.3 2001/02/07 22:22:00 steve
|
||||
* ivl_target header search path fixes.
|
||||
*
|
||||
* Revision 1.2 2000/12/09 03:42:52 steve
|
||||
* Stuff registers into macrocells.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,10 +17,10 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: fit_log.c,v 1.1 2000/12/14 23:37:47 steve Exp $"
|
||||
#ident "$Id: fit_log.c,v 1.2 2001/02/07 22:22:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
@@ -126,6 +126,9 @@ int fit_logic(void)
|
||||
|
||||
/*
|
||||
* $Log: fit_log.c,v $
|
||||
* Revision 1.2 2001/02/07 22:22:00 steve
|
||||
* ivl_target header search path fixes.
|
||||
*
|
||||
* Revision 1.1 2000/12/14 23:37:47 steve
|
||||
* Start support for fitting the logic.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,10 +17,10 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: fit_reg.c,v 1.3 2001/01/15 00:05:39 steve Exp $"
|
||||
#ident "$Id: fit_reg.c,v 1.4 2001/02/07 22:22:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
# include "priv.h"
|
||||
@@ -136,6 +136,9 @@ int scan_ff_q(ivl_lpm_ff_t ff, unsigned q)
|
||||
|
||||
/*
|
||||
* $Log: fit_reg.c,v $
|
||||
* Revision 1.4 2001/02/07 22:22:00 steve
|
||||
* ivl_target header search path fixes.
|
||||
*
|
||||
* Revision 1.3 2001/01/15 00:05:39 steve
|
||||
* Add client data pointer for scope and process scanners.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.6 2000/12/14 23:38:04 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7 2001/02/07 22:22:00 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -47,7 +47,7 @@ all: stub.tgt
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) -I$(srcdir)/.. -MD -c $< -o $*.o
|
||||
$(CC) -Wall -I$(srcdir)/.. $(CPPFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = stub.o
|
||||
|
||||
+93
-9
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: stub.c,v 1.28 2001/01/15 00:47:02 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.33 2001/03/31 17:36:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -27,7 +27,7 @@
|
||||
* understand the behavior of the core as it uses a target module.
|
||||
*/
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
|
||||
static FILE*out;
|
||||
@@ -82,6 +82,11 @@ static void show_expression(ivl_expr_t net, unsigned ind)
|
||||
ivl_expr_name(net), width, sign);
|
||||
break;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
fprintf(out, "%*s<unary \"%c\" width=%u, %s>\n", ind, "",
|
||||
ivl_expr_opcode(net), width, sign);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
|
||||
break;
|
||||
@@ -144,7 +149,8 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
||||
fprintf(out, "}\n");
|
||||
}
|
||||
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
if (ivl_stmt_rval(net))
|
||||
show_expression(ivl_stmt_rval(net), ind+4);
|
||||
break;
|
||||
|
||||
case IVL_ST_BLOCK: {
|
||||
@@ -158,6 +164,29 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_CASEX:
|
||||
case IVL_ST_CASEZ:
|
||||
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_CONDIT: {
|
||||
ivl_statement_t t = ivl_stmt_cond_true(net);
|
||||
ivl_statement_t f = ivl_stmt_cond_false(net);
|
||||
@@ -181,6 +210,17 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
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;
|
||||
@@ -189,7 +229,8 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
||||
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)
|
||||
show_expression(ivl_stmt_parm(net, idx), ind+4);
|
||||
if (ivl_stmt_parm(net, idx))
|
||||
show_expression(ivl_stmt_parm(net, idx), ind+4);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -197,11 +238,12 @@ static void show_statement(ivl_statement_t net, unsigned ind)
|
||||
fprintf(out, "%*s-> ...\n", ind, "");
|
||||
break;
|
||||
|
||||
|
||||
case IVL_ST_WAIT:
|
||||
fprintf(out, "%*s@(...)\n", ind, "");
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+2);
|
||||
break;
|
||||
case IVL_ST_WAIT: {
|
||||
ivl_event_t evnt = ivl_stmt_event(net);
|
||||
fprintf(out, "%*s@(%s)\n", ind, "", ivl_event_name(evnt));
|
||||
show_statement(ivl_stmt_sub_stmt(net), ind+4);
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_WHILE:
|
||||
fprintf(out, "%*swhile (<?>)\n", ind, "");
|
||||
@@ -229,6 +271,29 @@ static int show_process(ivl_process_t net, void*x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_event(ivl_event_t net)
|
||||
{
|
||||
ivl_edge_type_t edge = ivl_event_edge(net);
|
||||
|
||||
switch (edge) {
|
||||
case IVL_EDGE_NONE:
|
||||
fprintf(out, " event %s;\n", ivl_event_name(net));
|
||||
break;
|
||||
|
||||
case IVL_EDGE_ANY:
|
||||
fprintf(out, " event %s @(", ivl_event_name(net));
|
||||
fprintf(out, ");\n");
|
||||
break;
|
||||
case IVL_EDGE_NEG:
|
||||
fprintf(out, " event %s @(negedge ", ivl_event_name(net));
|
||||
fprintf(out, ");\n");
|
||||
break;
|
||||
case IVL_EDGE_POS:
|
||||
fprintf(out, " event %s @(posedge ", ivl_event_name(net));
|
||||
fprintf(out, ");\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_signal(ivl_signal_t net)
|
||||
{
|
||||
@@ -372,6 +437,9 @@ static int show_scope(ivl_scope_t net, void*x)
|
||||
break;
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1)
|
||||
show_event(ivl_scope_event(net, idx));
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1)
|
||||
show_signal(ivl_scope_sig(net, idx));
|
||||
|
||||
@@ -415,6 +483,22 @@ DECLARE_CYGWIN_DLL(DllMain);
|
||||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.33 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.32 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.31 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.30 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.29 2001/02/07 22:22:00 steve
|
||||
* ivl_target header search path fixes.
|
||||
*
|
||||
* Revision 1.28 2001/01/15 00:47:02 steve
|
||||
* Pass scope type information to the target module.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.5 2000/12/14 23:38:04 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.6 2001/02/07 22:22:00 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -47,7 +47,7 @@ all: verilog.tgt
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) -I$(srcdir)/.. -MD -c $< -o $*.o
|
||||
$(CC) -Wall -I$(srcdir)/.. $(CPPFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = verilog.o
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verilog.c,v 1.19 2001/01/15 00:05:39 steve Exp $"
|
||||
#ident "$Id: verilog.c,v 1.20 2001/02/07 22:22:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -26,7 +26,7 @@
|
||||
* the design, but is internally the complete design.
|
||||
*/
|
||||
|
||||
# include <ivl_target.h>
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
|
||||
@@ -440,6 +440,9 @@ DECLARE_CYGWIN_DLL(DllMain);
|
||||
|
||||
/*
|
||||
* $Log: verilog.c,v $
|
||||
* Revision 1.20 2001/02/07 22:22:00 steve
|
||||
* ivl_target header search path fixes.
|
||||
*
|
||||
* Revision 1.19 2001/01/15 00:05:39 steve
|
||||
* Add client data pointer for scope and process scanners.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Makefile
|
||||
configure
|
||||
config.status
|
||||
config.log
|
||||
dep
|
||||
vvp.tgt
|
||||
@@ -0,0 +1,87 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.5 2001/03/31 19:29:23 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: vvp.tgt
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall -I$(srcdir)/.. $(CPPFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvp.o eval_expr.o vvp_process.o vvp_scope.o
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
TGTDEPLIBS=../libivl.a
|
||||
else
|
||||
TGTLDFLAGS=
|
||||
TGTDEPLIBS=
|
||||
endif
|
||||
|
||||
|
||||
vvp.tgt: $O $(TGTDEPLIBS)
|
||||
$(CC) @shared@ -o $@ $O $(TGTLDFLAGS)
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d
|
||||
|
||||
check: all
|
||||
|
||||
install: all installdirs $(libdir)/ivl/vvp.tgt
|
||||
|
||||
$(libdir)/ivl/vvp.tgt: ./vvp.tgt
|
||||
$(INSTALL_DATA) ./vvp.tgt $(libdir)/ivl/vvp.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/vvp.tgt
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
THE VVP TARGET
|
||||
|
||||
SYMBOL NAME CONVENTIONS
|
||||
|
||||
There are some naming conventions that the vp target uses for
|
||||
generating symbol names.
|
||||
|
||||
* wires and regs
|
||||
|
||||
Nets and variables are named V_<full-name> where <full-name> is the
|
||||
full hierarchical name of the signal.
|
||||
|
||||
* Logic devices
|
||||
|
||||
Logic devices (and, or, buf, bufz, etc.) are named L_<full_name>. In
|
||||
this case the symbol is attached to a functor that is the output of
|
||||
the logic device.
|
||||
@@ -0,0 +1,53 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(vvp.c)
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
AC_CYGWIN
|
||||
AC_SUBST(CYGWIN)
|
||||
|
||||
# The -fPIC flag is used to tell the compiler to make position
|
||||
# independent code. It is needed when making shared objects.
|
||||
|
||||
AC_MSG_CHECKING("for flag to make position independent code")
|
||||
PICFLAG=-fPIC
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
PICFLAG=
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
PICFLAG=+z
|
||||
;;
|
||||
|
||||
esac
|
||||
AC_SUBST(PICFLAG)
|
||||
AC_MSG_RESULT($PICFLAG)
|
||||
|
||||
AC_MSG_CHECKING("for shared library link flag")
|
||||
shared=-shared
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
shared="-mdll -Wl,--enable-auto-image-base"
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
shared="-b"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
AC_SUBST(shared)
|
||||
|
||||
AC_MSG_RESULT($shared)
|
||||
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: eval_expr.c,v 1.7 2001/03/31 17:36:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid);
|
||||
|
||||
static unsigned char allocation_map[0x10000/8];
|
||||
|
||||
static inline int peek_bit(unsigned addr)
|
||||
{
|
||||
unsigned bit = addr % 8;
|
||||
addr /= 8;
|
||||
return 1 & (allocation_map[addr] >> bit);
|
||||
}
|
||||
|
||||
static inline void set_bit(unsigned addr)
|
||||
{
|
||||
unsigned bit = addr % 8;
|
||||
addr /= 8;
|
||||
allocation_map[addr] |= (1 << bit);
|
||||
}
|
||||
|
||||
static inline void clr_bit(unsigned addr)
|
||||
{
|
||||
unsigned bit = addr % 8;
|
||||
addr /= 8;
|
||||
allocation_map[addr] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
void clr_vector(struct vector_info vec)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < vec.wid ; idx += 1)
|
||||
clr_bit(vec.base + idx);
|
||||
}
|
||||
|
||||
static unsigned short allocate_vector(unsigned short wid)
|
||||
{
|
||||
unsigned short base = 8;
|
||||
|
||||
unsigned short idx = 0;
|
||||
while (idx < wid) {
|
||||
assert((base + idx) < 0x10000);
|
||||
if (peek_bit(base+idx)) {
|
||||
base = base + idx + 1;
|
||||
idx = 0;
|
||||
|
||||
} else {
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1)
|
||||
set_bit(base+idx);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
|
||||
struct vector_info lv;
|
||||
struct vector_info rv;
|
||||
|
||||
unsigned wid = ivl_expr_width(le);
|
||||
if (ivl_expr_width(re) > wid)
|
||||
wid = ivl_expr_width(re);
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
rv = draw_eval_expr_wid(re, wid);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'E': /* === */
|
||||
assert(lv.wid == rv.wid);
|
||||
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base,
|
||||
rv.base, lv.wid);
|
||||
clr_vector(lv);
|
||||
clr_vector(rv);
|
||||
lv.base = 6;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
|
||||
case 'e': /* == */
|
||||
assert(lv.wid == rv.wid);
|
||||
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base,
|
||||
rv.base, lv.wid);
|
||||
clr_vector(lv);
|
||||
clr_vector(rv);
|
||||
lv.base = 4;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
|
||||
case 'N': /* !== */
|
||||
assert(lv.wid == rv.wid);
|
||||
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base,
|
||||
rv.base, lv.wid);
|
||||
fprintf(vvp_out, " %%inv 6, 1;\n");
|
||||
|
||||
clr_vector(lv);
|
||||
clr_vector(rv);
|
||||
lv.base = 6;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
|
||||
case 'n': /* != */
|
||||
assert(lv.wid == rv.wid);
|
||||
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", lv.base,
|
||||
rv.base, lv.wid);
|
||||
fprintf(vvp_out, " %%inv 4, 1;\n");
|
||||
|
||||
clr_vector(lv);
|
||||
clr_vector(rv);
|
||||
lv.base = 4;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_plus(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
|
||||
struct vector_info lv;
|
||||
struct vector_info rv;
|
||||
|
||||
assert(ivl_expr_width(le) == wid);
|
||||
assert(ivl_expr_width(re) == wid);
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
rv = draw_eval_expr_wid(re, wid);
|
||||
|
||||
fprintf(vvp_out, " %%add %u, %u, %u;\n", lv.base, rv.base, wid);
|
||||
|
||||
clr_vector(rv);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info rv;
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'E': /* === */
|
||||
case 'e': /* == */
|
||||
case 'N': /* !== */
|
||||
case 'n': /* != */
|
||||
assert(wid == 1);
|
||||
rv = draw_binary_expr_eq(exp);
|
||||
break;
|
||||
|
||||
case '+':
|
||||
rv = draw_binary_expr_plus(exp, wid);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp.tgt error: unsupported binary (%c)\n",
|
||||
ivl_expr_opcode(exp));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
unsigned idx, off;
|
||||
struct vector_info res;
|
||||
|
||||
assert(wid >= ivl_expr_width(exp));
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
idx = ivl_expr_parms(exp);
|
||||
off = 0;
|
||||
while (idx > 0) {
|
||||
ivl_expr_t arg = ivl_expr_parm(exp, idx-1);
|
||||
unsigned awid = ivl_expr_width(arg);
|
||||
|
||||
struct vector_info avec = draw_eval_expr_wid(arg, awid);
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base+off,
|
||||
avec.base, avec.wid);
|
||||
clr_vector(avec);
|
||||
|
||||
idx -= 1;
|
||||
off += awid;
|
||||
}
|
||||
|
||||
if (off < wid) {
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+off, wid-off);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* A number in an expression is made up by copying constant bits into
|
||||
* the allocated vector.
|
||||
*/
|
||||
static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned nwid;
|
||||
struct vector_info res;
|
||||
const char*bits = ivl_expr_bits(exp);
|
||||
|
||||
res.wid = wid;
|
||||
|
||||
nwid = wid;
|
||||
if (ivl_expr_width(exp) < nwid)
|
||||
nwid = ivl_expr_width(exp);
|
||||
|
||||
/* If all the bits of the number have the same value, then we
|
||||
can use a constant bit. There is no need to allocate wr
|
||||
bits, and there is no need to generate any code. */
|
||||
|
||||
for (idx = 1 ; idx < nwid ; idx += 1) {
|
||||
if (bits[idx] != bits[0])
|
||||
break;
|
||||
}
|
||||
|
||||
if (idx >= res.wid) {
|
||||
switch (bits[0]) {
|
||||
case '0':
|
||||
res.base = 0;
|
||||
break;
|
||||
case '1':
|
||||
res.base = 1;
|
||||
break;
|
||||
case 'x':
|
||||
res.base = 2;
|
||||
break;
|
||||
case 'z':
|
||||
res.base = 3;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The number value needs to be represented as an allocated
|
||||
vector. Allocate the vector and use %mov instructions to
|
||||
load the constant bit values. */
|
||||
res.base = allocate_vector(wid);
|
||||
|
||||
idx = 0;
|
||||
while (idx < nwid) {
|
||||
unsigned cnt;
|
||||
char src = '?';
|
||||
switch (bits[idx]) {
|
||||
case '0':
|
||||
src = '0';
|
||||
break;
|
||||
case '1':
|
||||
src = '1';
|
||||
break;
|
||||
case 'x':
|
||||
src = '2';
|
||||
break;
|
||||
case 'z':
|
||||
src = '3';
|
||||
break;
|
||||
}
|
||||
|
||||
for (cnt = 1 ; idx+cnt < wid ; cnt += 1)
|
||||
if (bits[idx+cnt] != bits[idx])
|
||||
break;
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %c, %u;\n",
|
||||
res.base+idx, src, cnt);
|
||||
|
||||
idx += cnt;
|
||||
}
|
||||
|
||||
/* Pad the number up to the expression width. */
|
||||
if (idx < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
const char*name = ivl_expr_name(exp);
|
||||
struct vector_info res;
|
||||
|
||||
if (swid > wid)
|
||||
swid = wid;
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
|
||||
for (idx = 0 ; idx < swid ; idx += 1)
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, name, idx);
|
||||
|
||||
/* 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;
|
||||
ivl_expr_t sub = ivl_expr_oper1(exp);
|
||||
res = draw_eval_expr_wid(sub, wid);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case '~':
|
||||
fprintf(vvp_out, " %%inv %u, %u;\n", res.base, res.wid);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp error: unhandled unary: %c\n",
|
||||
ivl_expr_opcode(exp));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
switch (ivl_expr_type(exp)) {
|
||||
default:
|
||||
fprintf(stderr, "vvp error: unhandled expr type: %u\n",
|
||||
ivl_expr_type(exp));
|
||||
case IVL_EX_NONE:
|
||||
assert(0);
|
||||
res.base = 0;
|
||||
res.wid = 0;
|
||||
break;
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
res = draw_binary_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_CONCAT:
|
||||
res = draw_concat_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_NUMBER:
|
||||
res = draw_number_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
res = draw_signal_expr(exp, wid);
|
||||
break;
|
||||
|
||||
case IVL_EX_UNARY:
|
||||
res = draw_unary_expr(exp, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct vector_info draw_eval_expr(ivl_expr_t exp)
|
||||
{
|
||||
return draw_eval_expr_wid(exp, ivl_expr_width(exp));
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.7 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.6 2001/03/31 02:00:44 steve
|
||||
* Generate code for + and concat expressions.
|
||||
*
|
||||
* Revision 1.5 2001/03/29 05:16:25 steve
|
||||
* Handle truncation/padding of numbers.
|
||||
*
|
||||
* Revision 1.4 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.3 2001/03/27 06:43:27 steve
|
||||
* Evaluate === and !==
|
||||
*
|
||||
* Revision 1.2 2001/03/23 01:10:24 steve
|
||||
* Assure that operands are the correct width.
|
||||
*
|
||||
* Revision 1.1 2001/03/22 05:06:21 steve
|
||||
* Geneate code for conditional statements.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vvp.c,v 1.4 2001/03/27 03:31:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
FILE*vvp_out = 0;
|
||||
|
||||
static void draw_module_declarations(ivl_design_t des)
|
||||
{
|
||||
const char*cp = ivl_design_flag(des, "VPI_MODULE_LIST");
|
||||
|
||||
while (*cp) {
|
||||
char buffer[128];
|
||||
const char*comma = strchr(cp, ',');
|
||||
|
||||
if (comma == 0)
|
||||
comma = cp + strlen(cp);
|
||||
|
||||
strncpy(buffer, cp, comma-cp);
|
||||
buffer[comma-cp] = 0;
|
||||
fprintf(vvp_out, ":vpi_module \"%s\";\n", buffer);
|
||||
|
||||
cp = comma;
|
||||
}
|
||||
}
|
||||
|
||||
int target_design(ivl_design_t des)
|
||||
{
|
||||
int rc;
|
||||
ivl_scope_t root;
|
||||
const char*path = ivl_design_flag(des, "-o");
|
||||
assert(path);
|
||||
|
||||
vvp_out = fopen(path, "w");
|
||||
if (vvp_out == 0) {
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
draw_module_declarations(des);
|
||||
|
||||
root = ivl_design_root(des);
|
||||
draw_scope(root, 0);
|
||||
|
||||
rc = ivl_design_process(des, draw_process, 0);
|
||||
|
||||
fclose(vvp_out);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef __CYGWIN32__
|
||||
#include <cygwin/cygwin_dll.h>
|
||||
DECLARE_CYGWIN_DLL(DllMain);
|
||||
#endif
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifndef __vvp_priv_H
|
||||
#define __vvp_priv_H
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvp_priv.h,v 1.6 2001/03/31 17:36:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "ivl_target.h"
|
||||
# include <stdio.h>
|
||||
|
||||
/*
|
||||
* The target_design entry opens the output file that receives the
|
||||
* compiled design, and sets the vvp_out to the descripter.
|
||||
*/
|
||||
extern FILE* vvp_out;
|
||||
|
||||
/*
|
||||
* This function draws a process (initial or always) into the output
|
||||
* file. It normally returns 0, but returns !0 of there is some sort
|
||||
* of error.
|
||||
*/
|
||||
extern int draw_process(ivl_process_t net, void*x);
|
||||
|
||||
extern int draw_scope(ivl_scope_t scope, ivl_scope_t parent);
|
||||
|
||||
/*
|
||||
* Given a nexus, draw a string that represents the functor output
|
||||
* that feeds the nexus. This function can be used to get the input to
|
||||
* a functor, event, or even a %load in cases where I have the
|
||||
* ivl_nexus_t object.
|
||||
*/
|
||||
extern void draw_nexus_input(ivl_nexus_t nex);
|
||||
|
||||
|
||||
/*
|
||||
* The draw_eval_expr function writes out the code to evaluate a
|
||||
* behavioral expression.
|
||||
*
|
||||
* Expression results are placed into a vector allocated in the bit
|
||||
* space of the thread. The vector_info structure represents that
|
||||
* allocation. When the caller is done with the bits, it must release
|
||||
* the vector with clr_vector so that the code generator can reuse
|
||||
* those bits.
|
||||
*/
|
||||
struct vector_info {
|
||||
unsigned short base;
|
||||
unsigned short wid;
|
||||
};
|
||||
|
||||
extern struct vector_info draw_eval_expr(ivl_expr_t exp);
|
||||
extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w);
|
||||
|
||||
extern void clr_vector(struct vector_info vec);
|
||||
|
||||
/*
|
||||
* $Log: vvp_priv.h,v $
|
||||
* Revision 1.6 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.5 2001/03/27 06:27:41 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.4 2001/03/27 03:31:07 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.3 2001/03/22 05:06:21 steve
|
||||
* Geneate code for conditional statements.
|
||||
*
|
||||
* Revision 1.2 2001/03/21 01:49:43 steve
|
||||
* Scan the scopes of a design, and draw behavioral
|
||||
* blocking assignments of constants to vectors.
|
||||
*
|
||||
* Revision 1.1 2001/03/19 01:20:46 steve
|
||||
* Add the tgt-vvp code generator target.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvp_process.c,v 1.15 2001/03/31 19:08:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
static int show_statement(ivl_statement_t net);
|
||||
|
||||
static unsigned local_count = 0;
|
||||
static unsigned thread_count = 0;
|
||||
|
||||
/*
|
||||
* This file includes the code needed to generate VVP code for
|
||||
* processes. Scopes are already declared, we generate here the
|
||||
* executable code for the processes.
|
||||
*/
|
||||
|
||||
unsigned bitchar_to_idx(char bit)
|
||||
{
|
||||
switch (bit) {
|
||||
case '0':
|
||||
return 0;
|
||||
case '1':
|
||||
return 1;
|
||||
case 'x':
|
||||
return 2;
|
||||
case 'z':
|
||||
return 3;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions handle the blocking assignment. Use the %set
|
||||
* instruction to perform the actual assignment, and calculate any
|
||||
* lvalues and rvalues that need calculating.
|
||||
*
|
||||
* The set_to_nexus function takes a particular nexus and generates
|
||||
* the %set statements to assign the value.
|
||||
*
|
||||
* The show_stmt_assign function looks at the assign statement, scans
|
||||
* the l-values, and matches bits of the r-value with the correct
|
||||
* nexus.
|
||||
*/
|
||||
|
||||
static void set_to_nexus(ivl_nexus_t nex, unsigned bit)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
|
||||
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
|
||||
unsigned pin = ivl_nexus_ptr_pin(ptr);
|
||||
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
|
||||
|
||||
if (sig == 0)
|
||||
continue;
|
||||
|
||||
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
|
||||
ivl_signal_name(sig), pin, bit);
|
||||
}
|
||||
}
|
||||
|
||||
static int show_stmt_assign(ivl_statement_t net)
|
||||
{
|
||||
ivl_lval_t lval;
|
||||
ivl_expr_t rval = ivl_stmt_rval(net);
|
||||
|
||||
|
||||
/* Handle the special case that the r-value is a constant. We
|
||||
can generate the %set statement directly, without any worry
|
||||
about generating code to evaluate the r-value expressions. */
|
||||
|
||||
if (ivl_expr_type(rval) == IVL_EX_NUMBER) {
|
||||
unsigned idx;
|
||||
const char*bits = ivl_expr_bits(rval);
|
||||
|
||||
/* XXXX Only single l-value supported for now */
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
/* XXXX No mux support yet. */
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
set_to_nexus(ivl_lval_pin(lval, idx),
|
||||
bitchar_to_idx(bits[idx]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
{ struct vector_info res = draw_eval_expr(rval);
|
||||
unsigned wid = res.wid;
|
||||
unsigned idx;
|
||||
|
||||
/* XXXX Only single l-value supported for now */
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
/* XXXX No mux support yet. */
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
|
||||
if (ivl_lval_pins(lval) < wid)
|
||||
wid = ivl_lval_pins(lval);
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1)
|
||||
set_to_nexus(ivl_lval_pin(lval, idx), res.base+idx);
|
||||
|
||||
for (idx = wid ; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
set_to_nexus(ivl_lval_pin(lval, idx), 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_case(ivl_statement_t net)
|
||||
{
|
||||
ivl_expr_t exp = ivl_stmt_cond_expr(net);
|
||||
struct vector_info cond = draw_eval_expr(exp);
|
||||
unsigned count = ivl_stmt_case_count(net);
|
||||
|
||||
unsigned local_base = local_count;
|
||||
|
||||
unsigned idx, default_case;
|
||||
|
||||
local_count += count + 1;
|
||||
|
||||
/* First draw the branch table. All the non-default cases
|
||||
generate a branch out of here, to the code that implements
|
||||
the case. The default will fall through all the tests. */
|
||||
default_case = count;
|
||||
|
||||
for (idx = 0 ; idx < count ; idx += 1) {
|
||||
ivl_expr_t cex = ivl_stmt_case_expr(net, idx);
|
||||
struct vector_info cvec;
|
||||
|
||||
if (cex == 0) {
|
||||
default_case = idx;
|
||||
continue;
|
||||
}
|
||||
|
||||
cvec = draw_eval_expr_wid(cex, cond.wid);
|
||||
assert(cvec.wid == cond.wid);
|
||||
|
||||
fprintf(vvp_out, " %%cmp/u %u, %u, %u;\n", cond.base,
|
||||
cvec.base, cond.wid);
|
||||
fprintf(vvp_out, " %%jmp/1 T_%d.%d, 6;\n",
|
||||
thread_count, local_base+idx);
|
||||
|
||||
|
||||
/* Done with the case expression */
|
||||
clr_vector(cvec);
|
||||
}
|
||||
|
||||
/* Done with the condition expression */
|
||||
clr_vector(cond);
|
||||
|
||||
/* Emit code for the default case. */
|
||||
if (default_case < count) {
|
||||
ivl_statement_t cst = ivl_stmt_case_stmt(net, default_case);
|
||||
show_statement(cst);
|
||||
}
|
||||
|
||||
/* Jump to the out of the case. */
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count,
|
||||
local_base+count);
|
||||
|
||||
for (idx = 0 ; idx < count ; idx += 1) {
|
||||
ivl_statement_t cst = ivl_stmt_case_stmt(net, idx);
|
||||
|
||||
if (idx == default_case)
|
||||
continue;
|
||||
|
||||
fprintf(vvp_out, "T_%d.%d\n", thread_count, local_base+idx);
|
||||
show_statement(cst);
|
||||
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count,
|
||||
local_base+count);
|
||||
|
||||
}
|
||||
|
||||
/* The out of the case. */
|
||||
fprintf(vvp_out, "T_%d.%d\n", thread_count, local_base+count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_condit(ivl_statement_t net)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned lab_false, lab_out;
|
||||
ivl_expr_t exp = ivl_stmt_cond_expr(net);
|
||||
struct vector_info cond = draw_eval_expr(exp);
|
||||
|
||||
assert(cond.wid == 1);
|
||||
|
||||
lab_false = local_count++;
|
||||
lab_out = local_count++;
|
||||
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, %u;\n",
|
||||
thread_count, lab_false, cond.base);
|
||||
|
||||
/* Done with the condition expression. */
|
||||
clr_vector(cond);
|
||||
|
||||
rc += show_statement(ivl_stmt_cond_true(net));
|
||||
|
||||
if (ivl_stmt_cond_false(net)) {
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
|
||||
fprintf(vvp_out, "T_%d.%u\n", thread_count, lab_false);
|
||||
|
||||
rc += show_statement(ivl_stmt_cond_false(net));
|
||||
|
||||
fprintf(vvp_out, "T_%d.%u\n", thread_count, lab_out);
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, "T_%d.%u\n", thread_count, lab_false);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* The delay statement is easy. Simply write a ``%delay <n>''
|
||||
* instruction to delay the thread, then draw the included statement.
|
||||
* The delay statement comes from verilog code like this:
|
||||
*
|
||||
* ...
|
||||
* #<delay> <stmt>;
|
||||
*/
|
||||
static int show_stmt_delay(ivl_statement_t net)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned long delay = ivl_stmt_delay_val(net);
|
||||
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
||||
|
||||
fprintf(vvp_out, " %%delay %lu;\n", delay);
|
||||
rc += show_statement(stmt);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int show_stmt_fork(ivl_statement_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
int rc = 0;
|
||||
static int transient_id = 0;
|
||||
unsigned cnt = ivl_stmt_block_count(net);
|
||||
|
||||
int out = transient_id++;
|
||||
|
||||
/* Draw a fork statement for all but one of the threads of the
|
||||
fork/join. Send the threads off to a bit of code where they
|
||||
are implemented. */
|
||||
for (idx = 0 ; idx < cnt-1 ; idx += 1) {
|
||||
fprintf(vvp_out, " %%fork t_%u;\n", transient_id+idx);
|
||||
}
|
||||
|
||||
/* Draw code to execute the remaining thread in the current
|
||||
thread, then generate enough joins to merge back together. */
|
||||
rc += show_statement(ivl_stmt_block_stmt(net, cnt-1));
|
||||
|
||||
for (idx = 0 ; idx < cnt-1 ; idx += 1) {
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
}
|
||||
fprintf(vvp_out, " %%jmp t_%u;\n", out);
|
||||
|
||||
for (idx = 0 ; idx < cnt-1 ; idx += 1) {
|
||||
fprintf(vvp_out, "t_%u\n", transient_id+idx);
|
||||
rc += show_statement(ivl_stmt_block_stmt(net, idx));
|
||||
fprintf(vvp_out, " %%end;\n");
|
||||
}
|
||||
|
||||
/* This is the label for the out. Use this to branck around
|
||||
the implementations of all the child threads. */
|
||||
fprintf(vvp_out, "t_%u\n", out);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* noop statements are implemented by doing nothing.
|
||||
*/
|
||||
static int show_stmt_noop(ivl_statement_t net)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_trigger(ivl_statement_t net)
|
||||
{
|
||||
ivl_event_t ev = ivl_stmt_event(net);
|
||||
assert(ev);
|
||||
fprintf(vvp_out, " %%set E_%s, 0;\n", ivl_event_name(ev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_stmt_wait(ivl_statement_t net)
|
||||
{
|
||||
ivl_event_t ev = ivl_stmt_event(net);
|
||||
fprintf(vvp_out, " %%wait E_%s;\n", ivl_event_name(ev));
|
||||
|
||||
return show_statement(ivl_stmt_sub_stmt(net));
|
||||
}
|
||||
|
||||
static int show_system_task_call(ivl_statement_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned parm_count = ivl_stmt_parm_count(net);
|
||||
|
||||
if (parm_count == 0) {
|
||||
fprintf(vvp_out, " %%vpi_call \"%s\";\n", ivl_stmt_name(net));
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%vpi_call \"%s\"", ivl_stmt_name(net));
|
||||
for (idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
ivl_expr_t expr = ivl_stmt_parm(net, idx);
|
||||
|
||||
switch (ivl_expr_type(expr)) {
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
fprintf(vvp_out, ", V_%s", ivl_expr_name(expr));
|
||||
break;
|
||||
|
||||
case IVL_EX_STRING:
|
||||
fprintf(vvp_out, ", \"%s\"", ivl_expr_string(expr));
|
||||
break;
|
||||
|
||||
case IVL_EX_SFUNC:
|
||||
if (strcmp("$time", ivl_expr_name(expr)) == 0)
|
||||
fprintf(vvp_out, ", $time");
|
||||
else
|
||||
fprintf(vvp_out, ", ?");
|
||||
break;
|
||||
default:
|
||||
fprintf(vvp_out, ", ?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function draws a statement as vvp assembly. It basically
|
||||
* switches on the statement type and draws code based on the type and
|
||||
* further specifics.
|
||||
*/
|
||||
static int show_statement(ivl_statement_t net)
|
||||
{
|
||||
const ivl_statement_type_t code = ivl_statement_type(net);
|
||||
int rc = 0;
|
||||
|
||||
switch (code) {
|
||||
|
||||
case IVL_ST_ASSIGN:
|
||||
rc += show_stmt_assign(net);
|
||||
break;
|
||||
|
||||
/* Begin-end blocks simply draw their contents. */
|
||||
case IVL_ST_BLOCK: {
|
||||
unsigned idx;
|
||||
unsigned cnt = ivl_stmt_block_count(net);
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
rc += show_statement(ivl_stmt_block_stmt(net, idx));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_ST_CASE:
|
||||
rc += show_stmt_case(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_CONDIT:
|
||||
rc += show_stmt_condit(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_DELAY:
|
||||
rc += show_stmt_delay(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_FORK:
|
||||
rc += show_stmt_fork(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_NOOP:
|
||||
rc += show_stmt_noop(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_STASK:
|
||||
rc += show_system_task_call(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_TRIGGER:
|
||||
rc += show_stmt_trigger(net);
|
||||
break;
|
||||
|
||||
case IVL_ST_WAIT:
|
||||
rc += show_stmt_wait(net);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp.tgt: Unable to draw statement type %u\n",
|
||||
code);
|
||||
rc += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The process as a whole is surrounded by this code. We generate a
|
||||
* start label that the .thread statement can use, and we generate
|
||||
* code to terminate the thread.
|
||||
*/
|
||||
|
||||
int draw_process(ivl_process_t net, void*x)
|
||||
{
|
||||
int rc = 0;
|
||||
ivl_scope_t scope = ivl_process_scope(net);
|
||||
ivl_statement_t stmt = ivl_process_stmt(net);
|
||||
|
||||
local_count = 0;
|
||||
fprintf(vvp_out, " .scope S_%s;\n", ivl_scope_name(scope));
|
||||
|
||||
/* Generate the entry label. Just give the thread a number so
|
||||
that we ar certain the label is unique. */
|
||||
fprintf(vvp_out, "T_%d\n", thread_count);
|
||||
|
||||
/* Draw the contents of the thread. */
|
||||
rc += show_statement(stmt);
|
||||
|
||||
|
||||
/* Terminate the thread with either an %end instruction (initial
|
||||
statements) or a %jmp back to the beginning of the thread. */
|
||||
|
||||
switch (ivl_process_type(net)) {
|
||||
|
||||
case IVL_PR_INITIAL:
|
||||
fprintf(vvp_out, " %%end;\n");
|
||||
break;
|
||||
|
||||
case IVL_PR_ALWAYS:
|
||||
fprintf(vvp_out, " %%jmp T_%d;\n", thread_count);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now write out the .thread directive that tells vvp where
|
||||
the thread starts. */
|
||||
fprintf(vvp_out, " .thread T_%d;\n", thread_count);
|
||||
|
||||
|
||||
thread_count += 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.15 2001/03/31 19:08:22 steve
|
||||
* Handle $time as system task parameter.
|
||||
*
|
||||
* Revision 1.14 2001/03/31 19:02:13 steve
|
||||
* Clear results of condition expressions.
|
||||
*
|
||||
* Revision 1.13 2001/03/31 17:36:39 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.12 2001/03/30 05:49:53 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.11 2001/03/29 03:47:38 steve
|
||||
* Behavioral trigger statements.
|
||||
*
|
||||
* Revision 1.10 2001/03/28 06:07:40 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.9 2001/03/27 06:27:41 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.8 2001/03/27 03:31:07 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.7 2001/03/25 03:53:24 steve
|
||||
* Skip true clause if condition ix 0, x or z
|
||||
*
|
||||
* Revision 1.6 2001/03/25 03:24:10 steve
|
||||
* Draw signal inputs to system tasks.
|
||||
*
|
||||
* Revision 1.5 2001/03/23 01:54:32 steve
|
||||
* assignments with non-trival r-values.
|
||||
*
|
||||
* Revision 1.4 2001/03/22 05:06:21 steve
|
||||
* Geneate code for conditional statements.
|
||||
*
|
||||
* Revision 1.3 2001/03/21 01:49:43 steve
|
||||
* Scan the scopes of a design, and draw behavioral
|
||||
* blocking assignments of constants to vectors.
|
||||
*
|
||||
* Revision 1.2 2001/03/20 01:44:14 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.1 2001/03/19 01:20:46 steve
|
||||
* Add the tgt-vvp code generator target.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvp_scope.c,v 1.9 2001/03/31 19:29:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* The draw_scope function draws the major functional items within a
|
||||
* scope. This includes the scopes themselves, of course. All the
|
||||
* other functions in this file are in support of that task.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This function takes a nexus and looks for an input functor. It then
|
||||
* draws to the output a string that represents that functor.
|
||||
*
|
||||
* XXXX This function does not yet support multiple drivers.
|
||||
*/
|
||||
void draw_nexus_input(ivl_nexus_t nex)
|
||||
{
|
||||
ivl_net_logic_t lptr;
|
||||
ivl_signal_t sptr;
|
||||
unsigned ndx;
|
||||
|
||||
for (ndx = 0 ; ndx < ivl_nexus_ptrs(nex) ; ndx += 1) {
|
||||
ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, ndx);
|
||||
|
||||
lptr = ivl_nexus_ptr_log(nptr);
|
||||
if (lptr && (ivl_logic_type(lptr) == IVL_LO_BUFZ)) {
|
||||
draw_nexus_input(ivl_logic_pin(lptr, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (lptr && (ivl_nexus_ptr_pin(nptr) == 0)) {
|
||||
fprintf(vvp_out, "L_%s", ivl_logic_name(lptr));
|
||||
return;
|
||||
}
|
||||
|
||||
sptr = ivl_nexus_ptr_sig(nptr);
|
||||
if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
|
||||
fprintf(vvp_out, "V_%s[%u]", ivl_signal_name(sptr),
|
||||
ivl_nexus_ptr_pin(nptr));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function draws a reg/int/variable in the scope. This is a very
|
||||
* simple device to draw as there are no inputs to connect so no need
|
||||
* to scan the nexus.
|
||||
*/
|
||||
static void draw_reg_in_scope(ivl_signal_t sig)
|
||||
{
|
||||
int msb = ivl_signal_pins(sig) - 1;
|
||||
int lsb = 0;
|
||||
|
||||
fprintf(vvp_out, "V_%s .var \"%s\", %d, %d;\n",
|
||||
ivl_signal_name(sig), ivl_signal_basename(sig),
|
||||
msb, lsb);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function draws a net. This is a bit more complicated as we
|
||||
* have to find an appropriate functor to connect to the input.
|
||||
*/
|
||||
static void draw_net_in_scope(ivl_signal_t sig)
|
||||
{
|
||||
unsigned idx;
|
||||
int msb = ivl_signal_pins(sig) - 1;
|
||||
int lsb = 0;
|
||||
|
||||
fprintf(vvp_out, "V_%s .net \"%s\", %d, %d",
|
||||
ivl_signal_name(sig), ivl_signal_basename(sig),
|
||||
msb, lsb);
|
||||
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_signal_pin(sig, idx);
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_nexus_input(nex);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_logic_in_scope(ivl_net_logic_t lptr)
|
||||
{
|
||||
unsigned pdx;
|
||||
const char*ltype = "?";
|
||||
unsigned init_val = 0;
|
||||
|
||||
/* Skip BUFZ objects. Things that have a bufz as input
|
||||
will use the input to bufz instead. */
|
||||
if (ivl_logic_type(lptr) == IVL_LO_BUFZ)
|
||||
return;
|
||||
|
||||
|
||||
switch (ivl_logic_type(lptr)) {
|
||||
|
||||
case IVL_LO_AND:
|
||||
ltype = "AND";
|
||||
init_val = 0x55;
|
||||
break;
|
||||
|
||||
case IVL_LO_NOR:
|
||||
ltype = "NOR";
|
||||
break;
|
||||
|
||||
case IVL_LO_NOT:
|
||||
ltype = "NOT";
|
||||
break;
|
||||
|
||||
case IVL_LO_OR:
|
||||
ltype = "OR";
|
||||
break;
|
||||
|
||||
default:
|
||||
ltype = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
assert(ivl_logic_pins(lptr) <= 5);
|
||||
|
||||
for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
|
||||
unsigned mask = 3 << (pdx - 1);
|
||||
init_val = (init_val & ~mask) | (2 << (pdx - 1));
|
||||
}
|
||||
|
||||
fprintf(vvp_out, "L_%s .functor %s, 0x%x",
|
||||
ivl_logic_name(lptr), ltype, init_val);
|
||||
|
||||
for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
|
||||
ivl_nexus_t nex = ivl_logic_pin(lptr, pdx);
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_nexus_input(nex);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
static void draw_event_in_scope(ivl_event_t obj)
|
||||
{
|
||||
ivl_edge_type_t edge = ivl_event_edge(obj);
|
||||
|
||||
if (edge == IVL_EDGE_NONE) {
|
||||
fprintf(vvp_out, "E_%s .event \"%s\";\n",
|
||||
ivl_event_name(obj), ivl_event_basename(obj));
|
||||
|
||||
} else {
|
||||
unsigned idx;
|
||||
unsigned pins = ivl_event_pins(obj);
|
||||
assert(pins <= 4);
|
||||
fprintf(vvp_out, "E_%s .event ", ivl_event_name(obj));
|
||||
switch (edge) {
|
||||
case IVL_EDGE_POS:
|
||||
fprintf(vvp_out, "posedge");
|
||||
break;
|
||||
case IVL_EDGE_NEG:
|
||||
fprintf(vvp_out, "posedge");
|
||||
break;
|
||||
case IVL_EDGE_ANY:
|
||||
fprintf(vvp_out, "edge");
|
||||
break;
|
||||
case IVL_EDGE_NONE:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < pins ; idx += 1) {
|
||||
ivl_nexus_t nex = ivl_event_pin(obj, idx);
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_nexus_input(nex);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
}
|
||||
|
||||
int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
if (parent)
|
||||
fprintf(vvp_out, "S_%s .scope \"%s\", S_%s;\n",
|
||||
ivl_scope_name(net), ivl_scope_name(net),
|
||||
ivl_scope_name(parent));
|
||||
else
|
||||
fprintf(vvp_out, "S_%s .scope \"%s\";\n",
|
||||
ivl_scope_name(net), ivl_scope_name(net));
|
||||
|
||||
|
||||
/* Scan the scope for logic devices. For each device, draw out
|
||||
a functor that connects pin 0 to the output, and the
|
||||
remaining pins to inputs. */
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) {
|
||||
ivl_net_logic_t lptr = ivl_scope_log(net, idx);
|
||||
draw_logic_in_scope(lptr);
|
||||
}
|
||||
|
||||
|
||||
/* Scan the signals (reg and net) and draw the appropriate
|
||||
statements to make the signal function. */
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(net, idx);
|
||||
|
||||
switch (ivl_signal_type(sig)) {
|
||||
case IVL_SIT_REG:
|
||||
draw_reg_in_scope(sig);
|
||||
break;
|
||||
default:
|
||||
draw_net_in_scope(sig);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) {
|
||||
ivl_event_t event = ivl_scope_event(net, idx);
|
||||
draw_event_in_scope(event);
|
||||
}
|
||||
|
||||
ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.9 2001/03/31 19:29:23 steve
|
||||
* Fix compilation warnings.
|
||||
*
|
||||
* Revision 1.8 2001/03/29 03:47:13 steve
|
||||
* events can take up to 4 inputs.
|
||||
*
|
||||
* Revision 1.7 2001/03/28 06:07:40 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.6 2001/03/27 06:27:41 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.5 2001/03/25 19:36:12 steve
|
||||
* Draw AND NOR and NOT gates.
|
||||
*
|
||||
* Revision 1.4 2001/03/25 05:59:47 steve
|
||||
* Recursive make check target.
|
||||
*
|
||||
* Revision 1.3 2001/03/25 03:53:40 steve
|
||||
* Include signal bit index in functor input.
|
||||
*
|
||||
* Revision 1.2 2001/03/25 03:25:43 steve
|
||||
* Generate .net statements, and nexus inputs.
|
||||
*
|
||||
* Revision 1.1 2001/03/21 01:49:43 steve
|
||||
* Scan the scopes of a design, and draw behavioral
|
||||
* blocking assignments of constants to vectors.
|
||||
*
|
||||
*/
|
||||
|
||||
+6
-4
@@ -1,10 +1,10 @@
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog
|
||||
Version: 0.4
|
||||
Release: 1
|
||||
Version: 0.5
|
||||
Release: 0
|
||||
Copyright: GPL
|
||||
Group: Applications/Engineering
|
||||
Source: ftp://icarus.com/pub/eda/verilog/v0.4/verilog-0.4.tar.gz
|
||||
Source: ftp://icarus.com/pub/eda/verilog/v0.5/verilog-0.5.tar.gz
|
||||
URL: http://www.icarus.com/eda/verilog/index.html
|
||||
Packager: Stephen Williams <[email protected]>
|
||||
|
||||
@@ -20,7 +20,7 @@ engineering formats, including simulation. It strives to be true
|
||||
to the IEEE-1364 standard.
|
||||
|
||||
%prep
|
||||
%setup -n verilog-0.4
|
||||
%setup -n verilog-0.5
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
@@ -37,10 +37,12 @@ make prefix=$RPM_BUILD_ROOT/usr install
|
||||
%attr(-,root,root) /usr/man/man1/iverilog.1.gz
|
||||
|
||||
%attr(-,root,root) /usr/bin/iverilog
|
||||
%attr(-,root,root) /usr/bin/vvp
|
||||
%attr(-,root,root) /usr/lib/ivl/ivl
|
||||
%attr(-,root,root) /usr/lib/ivl/ivlpp
|
||||
%attr(-,root,root) /usr/lib/ivl/system.vpi
|
||||
%attr(-,root,root) /usr/lib/ivl/null.tgt
|
||||
%attr(-,root,root) /usr/lib/ivl/vvp.tgt
|
||||
%attr(-,root,root) /usr/lib/ivl/iverilog.conf
|
||||
%attr(-,root,root) /usr/lib/libvvm.a
|
||||
%attr(-,root,root) /usr/lib/libvpip.a
|
||||
|
||||
+208
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verinum.cc,v 1.22 2001/01/02 03:23:40 steve Exp $"
|
||||
#ident "$Id: verinum.cc,v 1.26 2001/02/09 05:44:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "verinum.h"
|
||||
@@ -60,8 +60,8 @@ verinum::verinum(const string&str)
|
||||
}
|
||||
}
|
||||
|
||||
verinum::verinum(verinum::V val, unsigned n)
|
||||
: has_len_(true), has_sign_(false), string_flag_(false)
|
||||
verinum::verinum(verinum::V val, unsigned n, bool h)
|
||||
: has_len_(h), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = n;
|
||||
bits_ = new V[nbits_];
|
||||
@@ -144,11 +144,13 @@ verinum& verinum::operator= (const verinum&that)
|
||||
|
||||
verinum::V verinum::get(unsigned idx) const
|
||||
{
|
||||
assert(idx < nbits_);
|
||||
return bits_[idx];
|
||||
}
|
||||
|
||||
verinum::V verinum::set(unsigned idx, verinum::V val)
|
||||
{
|
||||
assert(idx < nbits_);
|
||||
return bits_[idx] = val;
|
||||
}
|
||||
|
||||
@@ -267,6 +269,59 @@ bool verinum::is_defined() const
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns a version of the verinum that has only as
|
||||
* many bits as are needed to accurately represent the value. It takes
|
||||
* into account the signedness of the value.
|
||||
*
|
||||
* If the input value has a definite length, then that value is just
|
||||
* returned as is.
|
||||
*/
|
||||
static verinum trim_vnum(const verinum&that)
|
||||
{
|
||||
unsigned tlen;
|
||||
|
||||
if (that.has_len())
|
||||
return that;
|
||||
|
||||
if (that.len() < 2)
|
||||
return that;
|
||||
|
||||
if (that.has_sign()) {
|
||||
unsigned top = that.len()-1;
|
||||
verinum::V sign = that.get(top);
|
||||
|
||||
while ((top > 0) && (that.get(top) == sign))
|
||||
top -= 1;
|
||||
|
||||
/* top points to the first digit that is not the
|
||||
sign. Set the length to include this and one proper
|
||||
sign bit. */
|
||||
|
||||
if (that.get(top) != sign)
|
||||
top += 1;
|
||||
|
||||
tlen = top+1;
|
||||
|
||||
} else {
|
||||
|
||||
/* If the result is unsigned and has an indefinite
|
||||
length, then trim off leading zeros. */
|
||||
tlen = 1;
|
||||
for (unsigned idx = tlen ; idx < that.len() ; idx += 1)
|
||||
if (that.get(idx) != verinum::V0)
|
||||
tlen = idx;
|
||||
|
||||
}
|
||||
|
||||
verinum tmp (verinum::V0, tlen, false);
|
||||
tmp.has_sign(that.has_sign());
|
||||
for (unsigned idx = 0 ; idx < tmp.len() ; idx += 1)
|
||||
tmp.set(idx, that.get(idx));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&o, verinum::V v)
|
||||
{
|
||||
switch (v) {
|
||||
@@ -365,7 +420,7 @@ verinum::V operator <= (const verinum&left, const verinum&right)
|
||||
}
|
||||
|
||||
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
|
||||
if (right[idx-1] != verinum::V0) return verinum::V0;
|
||||
if (right[idx-1] != verinum::V0) return verinum::V1;
|
||||
}
|
||||
|
||||
while (idx > 0) {
|
||||
@@ -380,6 +435,29 @@ verinum::V operator <= (const verinum&left, const verinum&right)
|
||||
return verinum::V1;
|
||||
}
|
||||
|
||||
verinum::V operator < (const verinum&left, const verinum&right)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
|
||||
if (left[idx-1] != verinum::V0) return verinum::V0;
|
||||
}
|
||||
|
||||
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
|
||||
if (right[idx-1] != verinum::V0) return verinum::V1;
|
||||
}
|
||||
|
||||
while (idx > 0) {
|
||||
if (left[idx-1] == verinum::Vx) return verinum::Vx;
|
||||
if (left[idx-1] == verinum::Vz) return verinum::Vx;
|
||||
if (right[idx-1] == verinum::Vx) return verinum::Vx;
|
||||
if (right[idx-1] == verinum::Vz) return verinum::Vx;
|
||||
if (left[idx-1] > right[idx-1]) return verinum::V0;
|
||||
idx -= 1;
|
||||
}
|
||||
|
||||
return verinum::V0;
|
||||
}
|
||||
|
||||
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c)
|
||||
{
|
||||
unsigned sum = 0;
|
||||
@@ -523,13 +601,19 @@ verinum operator - (const verinum&left, const verinum&r)
|
||||
*/
|
||||
verinum operator * (const verinum&left, const verinum&right)
|
||||
{
|
||||
const bool has_len_flag = left.has_len() && right.has_len();
|
||||
|
||||
/* If either operand is not fully defined, then the entire
|
||||
result is undefined. Create a result that is the right size
|
||||
and is filled with 'bx bits. */
|
||||
if (! (left.is_defined() && right.is_defined())) {
|
||||
verinum result (verinum::Vx, left.len() + right.len());
|
||||
verinum result (verinum::Vx, left.len()+right.len(), has_len_flag);
|
||||
result.has_sign(left.has_sign() || right.has_sign());
|
||||
return result;
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, left.len() + right.len());
|
||||
verinum result(verinum::V0, left.len() + right.len(), has_len_flag);
|
||||
result.has_sign(left.has_sign() || right.has_sign());
|
||||
|
||||
for (unsigned rdx = 0 ; rdx < right.len() ; rdx += 1) {
|
||||
|
||||
@@ -544,7 +628,113 @@ verinum operator * (const verinum&left, const verinum&right)
|
||||
}
|
||||
}
|
||||
|
||||
return trim_vnum(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* This operator divides the left number by the right number. If
|
||||
* either value is signed, the result is signed. If both values have a
|
||||
* defined length, then the result has a defined length.
|
||||
*/
|
||||
verinum operator / (const verinum&left, const verinum&right)
|
||||
{
|
||||
const bool has_len_flag = left.has_len() && right.has_len();
|
||||
|
||||
unsigned use_len = left.len();
|
||||
|
||||
/* If either operand is not fully defined, then the entire
|
||||
result is undefined. Create a result that is the right size
|
||||
and is filled with 'bx bits. */
|
||||
if (! (left.is_defined() && right.is_defined())) {
|
||||
verinum result (verinum::Vx, use_len, has_len_flag);
|
||||
result.has_sign(left.has_sign() || right.has_sign());
|
||||
return result;
|
||||
}
|
||||
|
||||
verinum result(verinum::Vz, use_len, has_len_flag);
|
||||
result.has_sign(left.has_sign() || right.has_sign());
|
||||
|
||||
/* do the operation differently, depending on whether the
|
||||
result is signed or not. */
|
||||
if (result.has_sign()) {
|
||||
|
||||
/* XXXX FIXME XXXX Use native unsigned division to do
|
||||
the work. This does not work if the result is too
|
||||
large for the native integer. */
|
||||
assert(use_len <= 8*sizeof(long));
|
||||
long l = left.as_long();
|
||||
long r = right.as_long();
|
||||
long v = l / r;
|
||||
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
|
||||
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
|
||||
v >>= 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* XXXX FIXME XXXX Use native unsigned division to do
|
||||
the work. This does not work if the result is too
|
||||
large for the native integer. */
|
||||
assert(use_len <= 8*sizeof(unsigned long));
|
||||
unsigned long l = left.as_ulong();
|
||||
unsigned long r = right.as_ulong();
|
||||
unsigned long v = l / r;
|
||||
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
|
||||
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return trim_vnum(result);
|
||||
}
|
||||
|
||||
verinum operator % (const verinum&left, const verinum&right)
|
||||
{
|
||||
const bool has_len_flag = left.has_len() && right.has_len();
|
||||
|
||||
unsigned use_len = left.len();
|
||||
|
||||
/* If either operand is not fully defined, then the entire
|
||||
result is undefined. Create a result that is the right size
|
||||
and is filled with 'bx bits. */
|
||||
if (! (left.is_defined() && right.is_defined())) {
|
||||
verinum result (verinum::Vx, use_len, has_len_flag);
|
||||
result.has_sign(left.has_sign() || right.has_sign());
|
||||
return result;
|
||||
}
|
||||
|
||||
verinum result(verinum::Vz, use_len, has_len_flag);
|
||||
result.has_sign(left.has_sign() || right.has_sign());
|
||||
|
||||
if (result.has_sign()) {
|
||||
|
||||
/* XXXX FIXME XXXX Use native unsigned division to do
|
||||
the work. This does not work if the result is too
|
||||
large for the native integer. */
|
||||
assert(use_len <= 8*sizeof(long));
|
||||
long l = left.as_long();
|
||||
long r = right.as_long();
|
||||
long v = l % r;
|
||||
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
|
||||
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
|
||||
v >>= 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* XXXX FIXME XXXX Use native unsigned division to do
|
||||
the work. This does not work if the result is too
|
||||
large for the native integer. */
|
||||
assert(use_len <= 8*sizeof(unsigned long));
|
||||
unsigned long l = left.as_ulong();
|
||||
unsigned long r = right.as_ulong();
|
||||
unsigned long v = l % r;
|
||||
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
|
||||
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -576,6 +766,18 @@ verinum::V operator & (verinum::V l, verinum::V r)
|
||||
|
||||
/*
|
||||
* $Log: verinum.cc,v $
|
||||
* Revision 1.26 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.25 2001/02/08 05:38:18 steve
|
||||
* trim the length of unsized numbers.
|
||||
*
|
||||
* Revision 1.24 2001/02/07 21:47:13 steve
|
||||
* Fix expression widths for rvalues and parameters (PR#131,132)
|
||||
*
|
||||
* Revision 1.23 2001/02/07 02:46:31 steve
|
||||
* Support constant evaluation of / and % (PR#124)
|
||||
*
|
||||
* Revision 1.22 2001/01/02 03:23:40 steve
|
||||
* Evaluate constant &, | and unary ~.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verinum.h,v 1.15 2001/01/16 02:44:18 steve Exp $"
|
||||
#ident "$Id: verinum.h,v 1.18 2001/02/10 20:29:39 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -44,7 +44,7 @@ class verinum {
|
||||
verinum();
|
||||
verinum(const string&str);
|
||||
verinum(const V*v, unsigned nbits, bool has_len =true);
|
||||
verinum(V, unsigned nbits =1);
|
||||
verinum(V, unsigned nbits =1, bool has_len =true);
|
||||
verinum(unsigned long val, unsigned bits);
|
||||
verinum(const verinum&);
|
||||
|
||||
@@ -110,15 +110,33 @@ extern verinum::V operator & (verinum::V l, verinum::V r);
|
||||
|
||||
extern verinum::V operator == (const verinum&left, const verinum&right);
|
||||
extern verinum::V operator <= (const verinum&left, const verinum&right);
|
||||
extern verinum::V operator < (const verinum&left, const verinum&right);
|
||||
extern verinum operator + (const verinum&left, const verinum&right);
|
||||
extern verinum operator - (const verinum&left, const verinum&right);
|
||||
extern verinum operator * (const verinum&left, const verinum&right);
|
||||
extern verinum operator / (const verinum&left, const verinum&right);
|
||||
extern verinum operator % (const verinum&left, const verinum&right);
|
||||
|
||||
inline verinum::V operator > (const verinum&left, const verinum&right)
|
||||
{ return right < left; }
|
||||
|
||||
inline verinum::V operator >= (const verinum&left, const verinum&right)
|
||||
{ return right <= left; }
|
||||
|
||||
extern verinum v_not(const verinum&left);
|
||||
|
||||
/*
|
||||
* $Log: verinum.h,v $
|
||||
* Revision 1.18 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
*
|
||||
* Revision 1.17 2001/02/09 05:44:23 steve
|
||||
* support evaluation of constant < in expressions.
|
||||
*
|
||||
* Revision 1.16 2001/02/07 02:46:31 steve
|
||||
* Support constant evaluation of / and % (PR#124)
|
||||
*
|
||||
* Revision 1.15 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
|
||||
+8
-13
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.20 2001/01/09 03:11:28 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.24 2001/03/31 19:29:23 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -50,15 +50,16 @@ all: system.vpi
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) -I$(srcdir) -MD -c $< -o $*.o
|
||||
$(CC) -Wall -I$(srcdir) -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = sys_table.o sys_display.o sys_finish.o sys_random.o \
|
||||
sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o
|
||||
sys_readmem.o sys_readmem_lex.o sys_time.o sys_vcd.o \
|
||||
mt19937int.o
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
SYSTEM_VPI_LDFLAGS=-Wl,--enable-auto-image-base -L../vvm -lvvm -lvpip
|
||||
VPI_DEPLIBS=../vvm/libvpip.a
|
||||
SYSTEM_VPI_LDFLAGS=-Wl,--enable-auto-image-base -L../vvm -lvvm -L../vpip -lvpip
|
||||
VPI_DEPLIBS=../vpip/libvpip.a
|
||||
else
|
||||
SYSTEM_VPI_LDFLAGS=
|
||||
VPI_DEPLIBS=
|
||||
@@ -73,23 +74,17 @@ sys_readmem_lex.c: sys_readmem_lex.lex
|
||||
clean:
|
||||
rm -f *.o dep/*.d
|
||||
|
||||
install: all installdirs $(libdir)/ivl/system.vpi \
|
||||
$(includedir)/vpi_user.h
|
||||
install: all installdirs $(libdir)/ivl/system.vpi
|
||||
|
||||
$(libdir)/ivl/system.vpi: ./system.vpi
|
||||
$(INSTALL_PROGRAM) ./system.vpi $(libdir)/ivl/system.vpi
|
||||
$(STRIP) $(libdir)/ivl/system.vpi
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/system.vpi
|
||||
rm -f $(includedir)/vpi_user.h
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
|
||||
/*
|
||||
* NOTE: This code as been slightly modified to interface with the
|
||||
* PLI implementations of $random. The copyright and license
|
||||
* information are given in the comment block below.
|
||||
*
|
||||
* The Modifications include:
|
||||
*
|
||||
* Remove the "main" function, as this is being used for its functions.
|
||||
*
|
||||
* Change the function prototypes to use ANSI/ISO C syntax.
|
||||
*/
|
||||
|
||||
/* A C-program for MT19937: Integer version (1998/4/6) */
|
||||
/* genrand() generates one pseudorandom unsigned integer (32bit) */
|
||||
/* which is uniformly distributed among 0 to 2^32-1 for each */
|
||||
/* call. sgenrand(seed) set initial values to the working area */
|
||||
/* of 624 words. Before genrand(), sgenrand(seed) must be */
|
||||
/* called once. (seed is any 32-bit integer except for 0). */
|
||||
/* Coded by Takuji Nishimura, considering the suggestions by */
|
||||
/* Topher Cooper and Marc Rieffel in July-Aug. 1997. */
|
||||
|
||||
/* This library is free software; you can redistribute it and/or */
|
||||
/* modify it under the terms of the GNU Library General Public */
|
||||
/* License as published by the Free Software Foundation; either */
|
||||
/* version 2 of the License, or (at your option) any later */
|
||||
/* version. */
|
||||
/* This library is distributed in the hope that it will be useful, */
|
||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
|
||||
/* See the GNU Library General Public License for more details. */
|
||||
/* You should have received a copy of the GNU Library General */
|
||||
/* Public License along with this library; if not, write to the */
|
||||
/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
|
||||
/* 02111-1307 USA */
|
||||
|
||||
/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
|
||||
/* When you use this, send an email to: [email protected] */
|
||||
/* with an appropriate reference to your work. */
|
||||
|
||||
/* REFERENCE */
|
||||
/* M. Matsumoto and T. Nishimura, */
|
||||
/* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform */
|
||||
/* Pseudo-Random Number Generator", */
|
||||
/* ACM Transactions on Modeling and Computer Simulation, */
|
||||
/* Vol. 8, No. 1, January 1998, pp 3--30. */
|
||||
|
||||
|
||||
/* Period parameters */
|
||||
#define N 624
|
||||
#define M 397
|
||||
#define MATRIX_A 0x9908b0df /* constant vector a */
|
||||
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
|
||||
#define LOWER_MASK 0x7fffffff /* least significant r bits */
|
||||
|
||||
/* Tempering parameters */
|
||||
#define TEMPERING_MASK_B 0x9d2c5680
|
||||
#define TEMPERING_MASK_C 0xefc60000
|
||||
#define TEMPERING_SHIFT_U(y) (y >> 11)
|
||||
#define TEMPERING_SHIFT_S(y) (y << 7)
|
||||
#define TEMPERING_SHIFT_T(y) (y << 15)
|
||||
#define TEMPERING_SHIFT_L(y) (y >> 18)
|
||||
|
||||
static unsigned long mt[N]; /* the array for the state vector */
|
||||
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
|
||||
|
||||
/* initializing the array with a NONZERO seed */
|
||||
void
|
||||
sgenrand(unsigned long seed)
|
||||
{
|
||||
/* setting initial seeds to mt[N] using */
|
||||
/* the generator Line 25 of Table 1 in */
|
||||
/* [KNUTH 1981, The Art of Computer Programming */
|
||||
/* Vol. 2 (2nd Ed.), pp102] */
|
||||
mt[0]= seed & 0xffffffff;
|
||||
for (mti=1; mti<N; mti++)
|
||||
mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
genrand()
|
||||
{
|
||||
unsigned long y;
|
||||
static unsigned long mag01[2]={0x0, MATRIX_A};
|
||||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
|
||||
if (mti >= N) { /* generate N words at one time */
|
||||
int kk;
|
||||
|
||||
if (mti == N+1) /* if sgenrand() has not been called, */
|
||||
sgenrand(4357); /* a default initial seed is used */
|
||||
|
||||
for (kk=0;kk<N-M;kk++) {
|
||||
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
}
|
||||
for (;kk<N-1;kk++) {
|
||||
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
}
|
||||
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
|
||||
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
|
||||
|
||||
mti = 0;
|
||||
}
|
||||
|
||||
y = mt[mti++];
|
||||
y ^= TEMPERING_SHIFT_U(y);
|
||||
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
|
||||
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
|
||||
y ^= TEMPERING_SHIFT_L(y);
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
+141
-15
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_display.c,v 1.21 2000/12/02 02:40:56 steve Exp $"
|
||||
#ident "$Id: sys_display.c,v 1.24 2001/03/22 02:23:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
@@ -35,18 +35,24 @@ struct strobe_cb_info {
|
||||
|
||||
static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||
{
|
||||
vpiHandle item;
|
||||
unsigned nitems = 1;
|
||||
vpiHandle*items = malloc(sizeof(vpiHandle));
|
||||
items[0] = vpi_scan(argv);
|
||||
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
||||
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
||||
items[nitems] = item;
|
||||
nitems += 1;
|
||||
}
|
||||
if (argv) {
|
||||
vpiHandle item;
|
||||
unsigned nitems = 1;
|
||||
vpiHandle*items = malloc(sizeof(vpiHandle));
|
||||
items[0] = vpi_scan(argv);
|
||||
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
||||
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
||||
items[nitems] = item;
|
||||
nitems += 1;
|
||||
}
|
||||
|
||||
info->nitems = nitems;
|
||||
info->items = items;
|
||||
info->nitems = nitems;
|
||||
info->items = items;
|
||||
|
||||
} else {
|
||||
info->nitems = 0;
|
||||
info->items = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -414,11 +420,13 @@ static int sys_monitor_calltf(char*name)
|
||||
*/
|
||||
static int sys_fopen_calltf(char *name)
|
||||
{
|
||||
s_vpi_value val, value;
|
||||
s_vpi_value val, value, modevalue;
|
||||
unsigned char *mode_string;
|
||||
|
||||
vpiHandle call_handle = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, call_handle);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
vpiHandle mode = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: file name parameter missing.\n", name);
|
||||
@@ -432,16 +440,35 @@ static int sys_fopen_calltf(char *name)
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, item) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_printf("ERROR: %s parameter must be a string.\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mode == 0) {
|
||||
mode_string = "w";
|
||||
} else {
|
||||
if (vpi_get(vpiType, mode) != vpiConstant) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, mode) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a string.\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
modevalue.format = vpiStringVal;
|
||||
vpi_get_value(mode, &modevalue);
|
||||
mode_string = modevalue.value.str;
|
||||
}
|
||||
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(item, &value);
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = vpi_mcd_open( value.value.str );
|
||||
val.value.integer = vpi_mcd_open_x( value.value.str, mode_string );
|
||||
|
||||
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
|
||||
|
||||
@@ -527,6 +554,80 @@ static int sys_fclose_calltf(char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fputc_calltf(char *name)
|
||||
{
|
||||
unsigned int mcd;
|
||||
int type;
|
||||
unsigned char x;
|
||||
s_vpi_value value, xvalue;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: mcd parameter missing.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
type = vpi_get(vpiType, item);
|
||||
if (type != vpiReg && type != vpiRealVal) {
|
||||
vpi_printf("ERROR: %s mcd parameter must be of integral, got vpiType=%d\n",
|
||||
name, type);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value.format = vpiIntVal;
|
||||
vpi_get_value(item, &value);
|
||||
mcd = value.value.integer;
|
||||
|
||||
item = vpi_scan(argv);
|
||||
|
||||
xvalue.format = vpiIntVal;
|
||||
vpi_get_value(item, &xvalue);
|
||||
x = xvalue.value.integer;
|
||||
|
||||
return vpi_mcd_fputc( mcd, x );
|
||||
}
|
||||
|
||||
static int sys_fgetc_calltf(char *name)
|
||||
{
|
||||
unsigned int mcd;
|
||||
int type;
|
||||
s_vpi_value value, rval;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: mcd parameter missing.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
type = vpi_get(vpiType, item);
|
||||
if (type != vpiReg && type != vpiRealVal) {
|
||||
vpi_printf("ERROR: %s mcd parameter must be of integral, got vpiType=%d\n",
|
||||
name, type);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value.format = vpiIntVal;
|
||||
vpi_get_value(item, &value);
|
||||
mcd = value.value.integer;
|
||||
|
||||
rval.format = vpiIntVal;
|
||||
rval.value.integer = vpi_mcd_fgetc( mcd );
|
||||
|
||||
vpi_put_value(sys, &rval, 0, vpiNoDelay);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fgetc_sizetf(char*x)
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
void sys_display_register()
|
||||
{
|
||||
@@ -595,11 +696,36 @@ void sys_display_register()
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$fwrite";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$fputc";
|
||||
tf_data.calltf = sys_fputc_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$fputc";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.tfname = "$fgetc";
|
||||
tf_data.calltf = sys_fgetc_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = sys_fgetc_sizetf;
|
||||
tf_data.user_data = "$fgetc";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: sys_display.c,v $
|
||||
* Revision 1.24 2001/03/22 02:23:40 steve
|
||||
* fgetc patch from Peter Monta.
|
||||
*
|
||||
* Revision 1.23 2001/03/18 00:31:32 steve
|
||||
* $display can take 0 arguments.
|
||||
*
|
||||
* Revision 1.22 2001/02/10 19:50:33 steve
|
||||
* Slightly more specific error message.
|
||||
*
|
||||
* Revision 1.21 2000/12/02 02:40:56 steve
|
||||
* Support for %s in $display (PR#62)
|
||||
*
|
||||
|
||||
+15
-83
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_random.c,v 1.2 2000/07/08 22:41:07 steve Exp $"
|
||||
#ident "$Id: sys_random.c,v 1.3 2001/02/16 00:26:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vpi_user.h>
|
||||
@@ -26,84 +26,10 @@
|
||||
# include <math.h>
|
||||
# include <limits.h>
|
||||
|
||||
#if 0
|
||||
double uniform(long*seed, long start, long end)
|
||||
{
|
||||
union u_s {
|
||||
float s;
|
||||
unsigned stemp;
|
||||
} u;
|
||||
extern void sgenrand(unsigned long seed);
|
||||
extern unsigned long genrand(void);
|
||||
|
||||
double d = 0.00000011920928955078125;
|
||||
double a, b, c;
|
||||
|
||||
if ((*seed) == 0)
|
||||
*seed = 259341593;
|
||||
|
||||
if (start >= end) {
|
||||
a = 0.0;
|
||||
b = 2147483647.0;
|
||||
|
||||
} else {
|
||||
a = (double) start;
|
||||
b = (double) end;
|
||||
}
|
||||
|
||||
*seed = 69069 * (*seed) + 1;
|
||||
u.stemp = *seed;
|
||||
|
||||
u.stemp = (u.stemp >> 9) | 0x3f800000;
|
||||
|
||||
c = (double) u.s;
|
||||
c = c + (c*d);
|
||||
c = ((b - a) * (c - 1.0)) + a;
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static long rtl_dist_uniform(long*seed, long start, long end)
|
||||
{
|
||||
double r;
|
||||
long i;
|
||||
|
||||
if (start >= end)
|
||||
return start;
|
||||
|
||||
if (end != LONG_MAX) {
|
||||
end += 1;
|
||||
r = uniform(seed, start, end);
|
||||
if (r >= 0)
|
||||
i = (long) r;
|
||||
else
|
||||
i = (long) (r-1);
|
||||
|
||||
if (i < start) i = start;
|
||||
if (i >= end) i = end - 1;
|
||||
|
||||
} else if (start != LONG_MIN) {
|
||||
start -= 1;
|
||||
r = uniform(seed, start, end);
|
||||
if (r >= 0)
|
||||
i = (long) r;
|
||||
else
|
||||
i = (long) (r-1);
|
||||
|
||||
if (i <= start) i = start;
|
||||
if (i > end) i = end;
|
||||
|
||||
} else {
|
||||
r = (uniform(seed, start, end) + 2147483648.0) / 4294967295.0;
|
||||
r = r * 4294967296.0 - 2147483648.0;
|
||||
if (r >= 0)
|
||||
i = (long) r;
|
||||
else
|
||||
i = (long) (r-1);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#else
|
||||
static long rtl_dist_uniform(long*seed, long start, long end)
|
||||
{
|
||||
if (start >= end)
|
||||
@@ -116,7 +42,6 @@ static long rtl_dist_uniform(long*seed, long start, long end)
|
||||
return random();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int sys_dist_uniform_calltf(char*name)
|
||||
@@ -174,12 +99,11 @@ static int sys_dist_uniform_sizetf(char*x)
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the $random system function. For now, ignore any
|
||||
* parameters and only produce a random number.
|
||||
* Implement the $random system function using the ``Mersenne
|
||||
* Twister'' random number generator MT19937.
|
||||
*/
|
||||
static int sys_random_calltf(char*name)
|
||||
{
|
||||
static long i_seed = 0;
|
||||
s_vpi_value val;
|
||||
vpiHandle call_handle;
|
||||
vpiHandle argv;
|
||||
@@ -188,6 +112,8 @@ static int sys_random_calltf(char*name)
|
||||
call_handle = vpi_handle(vpiSysTfCall, 0);
|
||||
assert(call_handle);
|
||||
|
||||
/* Get the argument list and look for a seed. If it is there,
|
||||
get the value and reseed the random number generator. */
|
||||
argv = vpi_iterate(vpiArgument, call_handle);
|
||||
if (argv) {
|
||||
seed = vpi_scan(argv);
|
||||
@@ -195,19 +121,21 @@ static int sys_random_calltf(char*name)
|
||||
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(seed, &val);
|
||||
i_seed = val.value.integer;
|
||||
sgenrand(val.value.integer);
|
||||
}
|
||||
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = rtl_dist_uniform(&i_seed, LONG_MIN, LONG_MAX);
|
||||
val.value.integer = genrand();
|
||||
|
||||
vpi_put_value(call_handle, &val, 0, vpiNoDelay);
|
||||
|
||||
#if 0
|
||||
if (seed) {
|
||||
val.format = vpiIntVal;
|
||||
val.value.integer = i_seed;
|
||||
vpi_put_value(seed, &val, 0, vpiNoDelay);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -240,6 +168,10 @@ void sys_random_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_random.c,v $
|
||||
* Revision 1.3 2001/02/16 00:26:38 steve
|
||||
* Use Mersenne Twister 19937 pseudo-random number generator
|
||||
* for the $random system task, and support the seed paramter.
|
||||
*
|
||||
* Revision 1.2 2000/07/08 22:41:07 steve
|
||||
* Add the dist_uniform function.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_user.h,v 1.25 2001/01/06 22:22:17 steve Exp $"
|
||||
#ident "$Id: vpi_user.h,v 1.2 2001/03/22 02:23:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -177,7 +177,10 @@ extern void vpi_printf(const char*fmt, ...);
|
||||
extern unsigned int vpi_mcd_close(unsigned int mcd);
|
||||
extern char *vpi_mcd_name(unsigned int mcd);
|
||||
extern unsigned int vpi_mcd_open(char *name);
|
||||
extern unsigned int vpi_mcd_open_x(char *name, char *mode);
|
||||
extern int vpi_mcd_printf(unsigned int mcd, const char*fmt, ...);
|
||||
extern int vpi_mcd_fputc(unsigned int mcd, unsigned char x);
|
||||
extern int vpi_mcd_fgetc(unsigned int mcd);
|
||||
|
||||
/*
|
||||
* support for VPI callback functions.
|
||||
@@ -266,6 +269,12 @@ extern DLLEXPORT void (*vlog_startup_routines[])();
|
||||
|
||||
/*
|
||||
* $Log: vpi_user.h,v $
|
||||
* Revision 1.2 2001/03/22 02:23:17 steve
|
||||
* fgetc patch from Peter Monta.
|
||||
*
|
||||
* Revision 1.1 2001/03/19 01:21:45 steve
|
||||
* vpi_user header file is a root header.
|
||||
*
|
||||
* Revision 1.25 2001/01/06 22:22:17 steve
|
||||
* Support signed decimal display of variables.
|
||||
*
|
||||
@@ -0,0 +1,6 @@
|
||||
libvpip.a
|
||||
Makefile
|
||||
configure
|
||||
config.log
|
||||
config.status
|
||||
dep
|
||||
@@ -0,0 +1,122 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version. In order to redistribute the software in
|
||||
# binary form, you will need a Picture Elements Binary Software
|
||||
# License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.3 2001/03/25 05:59:47 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@ -I$(srcdir) -I$(srcdir)/..
|
||||
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/..
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
STRIP = @STRIP@
|
||||
|
||||
P = vpi_bit.o vpi_callback.o \
|
||||
vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \
|
||||
vpi_priv.o vpi_scope.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o \
|
||||
vpi_mcd.o vpi_vlog_info.o
|
||||
|
||||
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
# In the DOS world, we make libvpip differently.
|
||||
all: libvpip.a vpip.dll
|
||||
|
||||
libvpip.a vpip.dll: $P vpip.def
|
||||
$(CC) -shared -Wl,--enable-auto-image-base,--out-implib,libvpip.a -o vpip.dll vpip.def $P
|
||||
|
||||
else
|
||||
|
||||
all: libvpip.a
|
||||
|
||||
check: all
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
libvpip.a: $P
|
||||
ld -r -o vpip.o $P
|
||||
rm -f $@
|
||||
ar cvq $@ vpip.o
|
||||
endif
|
||||
|
||||
libvvm.a: $O
|
||||
rm -f $@
|
||||
ar cvq $@ $O
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d libvpip.a vpip.dll
|
||||
|
||||
install:: all installdirs \
|
||||
$(libdir)/libvpip.a \
|
||||
$(includedir)/vpi_priv.h
|
||||
|
||||
$(libdir)/libvpip.a: ./libvpip.a
|
||||
$(INSTALL_DATA) ./libvpip.a $(libdir)/libvpip.a
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
install :: $(bindir)/vpip.dll
|
||||
|
||||
$(bindir)/vpip.dll: ./vpip.dll
|
||||
$(INSTALL_PROGRAM) ./vpip.dll $(bindir)/vpip.dll
|
||||
$(STRIP) $(bindir)/vpip.dll
|
||||
|
||||
endif
|
||||
|
||||
$(includedir)/vpi_priv.h: $(srcdir)/vpi_priv.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_priv.h $(includedir)/vpi_priv.h
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
|
||||
uninstall::
|
||||
rm -f $(libdir)/libvpip.a
|
||||
rm -f $(includedir)/vpi_priv.h
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
uninstall::
|
||||
rm -f $(bindir)/vpip.dll
|
||||
endif
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O $P)
|
||||
@@ -0,0 +1,11 @@
|
||||
AC_INIT(Makefile.in)
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_CYGWIN
|
||||
AC_EXEEXT
|
||||
AC_SUBST(CYGWIN)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
#! /bin/sh
|
||||
# mkinstalldirs --- make directory hierarchy
|
||||
# Author: Noah Friedman <[email protected]>
|
||||
# Created: 1993-05-16
|
||||
# Public domain
|
||||
|
||||
# $Id: mkinstalldirs,v 1.1 2001/03/14 19:27:44 steve Exp $
|
||||
|
||||
errstatus=0
|
||||
|
||||
for file
|
||||
do
|
||||
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
|
||||
shift
|
||||
|
||||
pathcomp=
|
||||
for d
|
||||
do
|
||||
pathcomp="$pathcomp$d"
|
||||
case "$pathcomp" in
|
||||
-* ) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp" 1>&2
|
||||
|
||||
mkdir "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
errstatus=$lasterr
|
||||
fi
|
||||
fi
|
||||
|
||||
pathcomp="$pathcomp/"
|
||||
done
|
||||
done
|
||||
|
||||
exit $errstatus
|
||||
|
||||
# mkinstalldirs ends here
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_bit.c,v 1.5 2000/05/11 01:37:33 steve Exp $"
|
||||
#ident "$Id: vpi_bit.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -134,6 +134,9 @@ vpip_bit_t vpip_bits_resolve(const vpip_bit_t*bits, unsigned nbits)
|
||||
|
||||
/*
|
||||
* $Log: vpi_bit.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.5 2000/05/11 01:37:33 steve
|
||||
* Calculate the X output value from drive0 and drive1
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_callback.c,v 1.8 2000/08/20 17:49:05 steve Exp $"
|
||||
#ident "$Id: vpi_callback.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -191,6 +191,9 @@ int vpi_remove_cb(vpiHandle ref)
|
||||
|
||||
/*
|
||||
* $Log: vpi_callback.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.8 2000/08/20 17:49:05 steve
|
||||
* Clean up warnings and portability issues.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_const.c,v 1.17 2001/01/07 18:22:15 steve Exp $"
|
||||
#ident "$Id: vpi_const.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -456,6 +456,9 @@ vpiHandle vpip_make_number_const(struct __vpiNumberConst*ref,
|
||||
|
||||
/*
|
||||
* $Log: vpi_const.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.17 2001/01/07 18:22:15 steve
|
||||
* Assert on length of bit vector.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_iter.c,v 1.3 2000/02/23 02:56:56 steve Exp $"
|
||||
#ident "$Id: vpi_iter.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -68,6 +68,9 @@ vpiHandle vpi_scan(vpiHandle ref)
|
||||
|
||||
/*
|
||||
* $Log: vpi_iter.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_mcd.c,v 1.2 2000/08/20 17:49:05 steve Exp $"
|
||||
#ident "$Id: vpi_mcd.c,v 1.2 2001/03/22 02:23:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -80,6 +80,11 @@ char *vpi_mcd_name(unsigned int mcd)
|
||||
}
|
||||
|
||||
unsigned int vpi_mcd_open(char *name)
|
||||
{
|
||||
return vpi_mcd_open_x(name, "w");
|
||||
}
|
||||
|
||||
unsigned int vpi_mcd_open_x(char *name, char *mode)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 31; i++) {
|
||||
@@ -89,7 +94,7 @@ unsigned int vpi_mcd_open(char *name)
|
||||
return 0; /* too many open mcd's */
|
||||
|
||||
got_entry:
|
||||
mcd_table[i].fp = fopen(name, "w");
|
||||
mcd_table[i].fp = fopen(name, mode);
|
||||
if(mcd_table[i].fp == NULL)
|
||||
return 0;
|
||||
mcd_table[i].filename = strdup(name);
|
||||
@@ -121,3 +126,26 @@ int vpi_mcd_printf(unsigned int mcd, const char*fmt, ...)
|
||||
return len;
|
||||
}
|
||||
|
||||
int vpi_mcd_fputc(unsigned int mcd, unsigned char x)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 31; i++) {
|
||||
if( (mcd>>i) & 1) {
|
||||
return fputc(x, mcd_table[i].fp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vpi_mcd_fgetc(unsigned int mcd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 31; i++) {
|
||||
if( (mcd>>i) & 1) {
|
||||
return fgetc(mcd_table[i].fp);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_memory.c,v 1.9 2001/01/06 22:22:17 steve Exp $"
|
||||
#ident "$Id: vpi_memory.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -201,6 +201,9 @@ vpiHandle vpip_make_memory(struct __vpiMemory*ref, const char*name,
|
||||
}
|
||||
/*
|
||||
* $Log: vpi_memory.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.9 2001/01/06 22:22:17 steve
|
||||
* Support signed decimal display of variables.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_null.c,v 1.4 2000/10/06 23:11:39 steve Exp $"
|
||||
#ident "$Id: vpi_null.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -43,6 +43,9 @@ extern struct __vpiNull *vpip_get_null(void)
|
||||
|
||||
/*
|
||||
* $Log: vpi_null.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.4 2000/10/06 23:11:39 steve
|
||||
* Replace data references with function calls. (Venkat)
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_priv.c,v 1.11 2000/10/28 00:51:42 steve Exp $"
|
||||
#ident "$Id: vpi_priv.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -235,6 +235,9 @@ void vpi_register_systf(const struct t_vpi_systf_data*systf)
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.11 2000/10/28 00:51:42 steve
|
||||
* Add scope to threads in vvm, pass that scope
|
||||
* to vpi sysTaskFunc objects, and add vpi calls
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_priv.h,v 1.31 2001/01/06 22:22:17 steve Exp $"
|
||||
#ident "$Id: vpi_priv.h,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -28,7 +28,7 @@
|
||||
* methods declared here to manage the VPI structures and provide the
|
||||
* needed behaviors.
|
||||
*/
|
||||
# include <vpi_user.h>
|
||||
# include "vpi_user.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -412,6 +412,9 @@ extern int vpip_finished();
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.31 2001/01/06 22:22:17 steve
|
||||
* Support signed decimal display of variables.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_scope.c,v 1.11 2001/01/01 08:10:35 steve Exp $"
|
||||
#ident "$Id: vpi_scope.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -150,6 +150,9 @@ void vpip_attach_to_scope(struct __vpiScope*ref, vpiHandle obj)
|
||||
|
||||
/*
|
||||
* $Log: vpi_scope.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.11 2001/01/01 08:10:35 steve
|
||||
* Handle function scopes in dumpvars scn (PR#95)
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_signal.c,v 1.12 2001/01/06 22:22:17 steve Exp $"
|
||||
#ident "$Id: vpi_signal.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -127,6 +127,9 @@ vpiHandle vpip_make_reg(struct __vpiSignal*ref, const char*name,
|
||||
|
||||
/*
|
||||
* $Log: vpi_signal.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.12 2001/01/06 22:22:17 steve
|
||||
* Support signed decimal display of variables.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_simulation.c,v 1.5 2000/10/06 23:11:39 steve Exp $"
|
||||
#ident "$Id: vpi_simulation.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -210,6 +210,9 @@ void vpip_simulation_run()
|
||||
|
||||
/*
|
||||
* $Log: vpi_simulation.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.5 2000/10/06 23:11:39 steve
|
||||
* Replace data references with function calls. (Venkat)
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_systask.c,v 1.9 2000/11/01 03:19:36 steve Exp $"
|
||||
#ident "$Id: vpi_systask.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -125,6 +125,9 @@ DECLARE_CYGWIN_DLL(DllMain);
|
||||
|
||||
/*
|
||||
* $Log: vpi_systask.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.9 2000/11/01 03:19:36 steve
|
||||
* Add the general $time system function.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_time.c,v 1.3 2000/02/23 02:56:56 steve Exp $"
|
||||
#ident "$Id: vpi_time.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -75,6 +75,9 @@ vpiHandle vpip_make_time_var(struct __vpiTimeVar*ref, const char*val)
|
||||
|
||||
/*
|
||||
* $Log: vpi_time.c,v $
|
||||
* Revision 1.1 2001/03/14 19:27:44 steve
|
||||
* Rearrange VPI support libraries.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_vlog_info.c,v 1.3 2000/09/30 03:20:48 steve Exp $"
|
||||
#ident "$Id: vpi_vlog_info.c,v 1.1 2001/03/14 19:27:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <vpi_priv.h>
|
||||
+5
-53
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.41 2000/12/15 20:05:16 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.43 2001/03/19 04:37:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -35,8 +35,8 @@ bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@ -I$(srcdir) -I$(srcdir)/../vpi
|
||||
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/../vpi
|
||||
CC = @CC@ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../vpip
|
||||
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../vpip
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
@@ -52,29 +52,8 @@ vvm_event.o vvm_ff.o vvm_force.o \
|
||||
vvm_func.o vvm_gates.o vvm_idiv.o vvm_imod.o vvm_memory.o vvm_mult.o \
|
||||
vvm_mux.o vvm_nexus.o vvm_pevent.o vvm_signal.o vvm_thread.o vvm_udp.o
|
||||
|
||||
P = vpi_bit.o vpi_callback.o \
|
||||
vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \
|
||||
vpi_priv.o vpi_scope.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o \
|
||||
vpi_mcd.o vpi_vlog_info.o
|
||||
|
||||
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
# In the DOS world, we make libvpip differently.
|
||||
all: libvvm.a libvpip.a vpip.dll
|
||||
|
||||
libvpip.a vpip.dll: $P vpip.def
|
||||
$(CC) -shared -Wl,--enable-auto-image-base,--out-implib,libvpip.a -o vpip.dll vpip.def $P
|
||||
|
||||
else
|
||||
|
||||
all: libvvm.a libvpip.a
|
||||
|
||||
libvpip.a: $P
|
||||
ld -r -o vpip.o $P
|
||||
rm -f $@
|
||||
ar cvq $@ vpip.o
|
||||
endif
|
||||
all: libvvm.a
|
||||
|
||||
libvvm.a: $O
|
||||
rm -f $@
|
||||
@@ -85,20 +64,13 @@ libvvm.a: $O
|
||||
$(CXX) -Wall -fno-exceptions $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d libvvm.a libvpip.a vpip.dll
|
||||
rm -f *.o dep/*.d libvvm.a
|
||||
|
||||
install:: all installdirs \
|
||||
$(libdir)/libvvm.a \
|
||||
$(libdir)/libvpip.a \
|
||||
$(includedir)/vvm.h \
|
||||
$(includedir)/vpi_priv.h \
|
||||
$(includedir)/vvm_func.h \
|
||||
$(includedir)/vvm_gates.h \
|
||||
$(includedir)/vvm_nexus.h \
|
||||
@@ -109,17 +81,6 @@ install:: all installdirs \
|
||||
$(libdir)/libvvm.a: ./libvvm.a
|
||||
$(INSTALL_DATA) ./libvvm.a $(libdir)/libvvm.a
|
||||
|
||||
$(libdir)/libvpip.a: ./libvpip.a
|
||||
$(INSTALL_DATA) ./libvpip.a $(libdir)/libvpip.a
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
install :: $(bindir)/vpip.dll
|
||||
|
||||
$(bindir)/vpip.dll: ./vpip.dll
|
||||
$(INSTALL_PROGRAM) ./vpip.dll $(bindir)/vpip.dll
|
||||
$(STRIP) $(bindir)/vpip.dll
|
||||
|
||||
endif
|
||||
|
||||
$(includedir)/vvm.h: $(srcdir)/vvm.h
|
||||
$(INSTALL_DATA) $(srcdir)/vvm.h $(includedir)/vvm.h
|
||||
@@ -142,15 +103,11 @@ $(includedir)/vvm_signal.h: $(srcdir)/vvm_signal.h
|
||||
$(includedir)/vvm_thread.h: $(srcdir)/vvm_thread.h
|
||||
$(INSTALL_DATA) $(srcdir)/vvm_thread.h $(includedir)/vvm_thread.h
|
||||
|
||||
$(includedir)/vpi_priv.h: $(srcdir)/vpi_priv.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_priv.h $(includedir)/vpi_priv.h
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
|
||||
uninstall::
|
||||
rm -f $(libdir)/libvvm.a
|
||||
rm -f $(libdir)/libvpip.a
|
||||
rm -f $(includedir)/vvm.h
|
||||
rm -f $(includedir)/vvm_calltf.h
|
||||
rm -f $(includedir)/vvm_func.h
|
||||
@@ -158,11 +115,6 @@ uninstall::
|
||||
rm -f $(includedir)/vvm_nexus.h
|
||||
rm -f $(includedir)/vvm_signal.h
|
||||
rm -f $(includedir)/vvm_thread.h
|
||||
rm -f $(includedir)/vpi_priv.h
|
||||
|
||||
ifeq (@CYGWIN@,yes)
|
||||
uninstall::
|
||||
rm -f $(bindir)/vpip.dll
|
||||
endif
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O $P)
|
||||
|
||||
+55
-14
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vvm_func.cc,v 1.13 2000/12/11 00:31:44 steve Exp $"
|
||||
#ident "$Id: vvm_func.cc,v 1.16 2001/02/13 03:38:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm_func.h"
|
||||
@@ -122,27 +122,59 @@ void vvm_binop_minus(vvm_bitset_t&v, const vvm_bitset_t&l,
|
||||
|
||||
void vvm_binop_nor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
|
||||
{
|
||||
assert(v.nbits == l.nbits);
|
||||
assert(v.nbits == r.nbits);
|
||||
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
|
||||
unsigned min = v.nbits;
|
||||
if (r.nbits < min) min = r.nbits;
|
||||
if (l.nbits < min) min = l.nbits;
|
||||
|
||||
for (unsigned idx = 0 ; idx < min ; idx += 1)
|
||||
v[idx] = B_NOT(B_OR(l[idx], r[idx]));
|
||||
|
||||
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
|
||||
v[idx] = B_NOT(r.nbits > min? r[idx] : l[idx]);
|
||||
}
|
||||
|
||||
void vvm_binop_or(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
|
||||
{
|
||||
assert(v.nbits == l.nbits);
|
||||
assert(v.nbits == r.nbits);
|
||||
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
|
||||
unsigned min = v.nbits;
|
||||
if (r.nbits < min) min = r.nbits;
|
||||
if (l.nbits < min) min = l.nbits;
|
||||
|
||||
for (unsigned idx = 0 ; idx < min ; idx += 1)
|
||||
v[idx] = B_OR(l[idx], r[idx]);
|
||||
|
||||
for (unsigned idx = min ; idx < v.nbits ; idx += 1)
|
||||
v[idx] = r.nbits > min? r[idx] : l[idx];
|
||||
}
|
||||
|
||||
/*
|
||||
* This function adds two vectors to make a result vector. The
|
||||
* operands and the result have their sizes already determined, so we
|
||||
* take those into account.
|
||||
*/
|
||||
void vvm_binop_plus(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
|
||||
{
|
||||
assert(v.nbits == l.nbits);
|
||||
assert(v.nbits == r.nbits);
|
||||
vpip_bit_t carry = St0;
|
||||
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
|
||||
|
||||
unsigned top = v.nbits;
|
||||
if (l.nbits < top)
|
||||
top = l.nbits;
|
||||
if (r.nbits < top)
|
||||
top = r.nbits;
|
||||
|
||||
unsigned idx;
|
||||
|
||||
/* First do the addition for the part of the vector where we
|
||||
know that the bits from both inputs are present. */
|
||||
for (idx = 0 ; idx < top ; idx += 1)
|
||||
v[idx] = add_with_carry(l[idx], r[idx], carry);
|
||||
|
||||
/* Now continue the addition, padding the shorter vector with
|
||||
St0 until we fill the result vector. */
|
||||
for ( ; idx < v.nbits ; idx += 1) {
|
||||
vpip_bit_t lv = (idx < l.nbits) ? l[idx] : St0;
|
||||
vpip_bit_t rv = (idx < r.nbits) ? r[idx] : St0;
|
||||
v[idx] = add_with_carry(lv, rv, carry);
|
||||
}
|
||||
}
|
||||
|
||||
void vvm_binop_shiftl(vvm_bitset_t&v,
|
||||
@@ -167,16 +199,16 @@ void vvm_binop_shiftr(vvm_bitset_t&v,
|
||||
|
||||
void vvm_binop_xnor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
|
||||
{
|
||||
assert(v.nbits == l.nbits);
|
||||
assert(v.nbits == r.nbits);
|
||||
assert(v.nbits <= l.nbits);
|
||||
assert(v.nbits <= r.nbits);
|
||||
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
|
||||
v[idx] = B_NOT(B_XOR(l[idx], r[idx]));
|
||||
}
|
||||
|
||||
void vvm_binop_xor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r)
|
||||
{
|
||||
assert(v.nbits == l.nbits);
|
||||
assert(v.nbits == r.nbits);
|
||||
assert(v.nbits <= l.nbits);
|
||||
assert(v.nbits <= r.nbits);
|
||||
for (unsigned idx = 0 ; idx < v.nbits ; idx += 1)
|
||||
v[idx] = B_XOR(l[idx], r[idx]);
|
||||
}
|
||||
@@ -607,6 +639,15 @@ void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c,
|
||||
|
||||
/*
|
||||
* $Log: vvm_func.cc,v $
|
||||
* Revision 1.16 2001/02/13 03:38:55 steve
|
||||
* Binary or and nor resilient to bit widths.
|
||||
*
|
||||
* Revision 1.15 2001/02/10 01:57:18 steve
|
||||
* Make the add func resilient to bit widths (PR#141)
|
||||
*
|
||||
* Revision 1.14 2001/02/07 21:47:13 steve
|
||||
* Fix expression widths for rvalues and parameters (PR#131,132)
|
||||
*
|
||||
* Revision 1.13 2000/12/11 00:31:44 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
configure
|
||||
config.log
|
||||
config.status
|
||||
config.h
|
||||
dep
|
||||
Makefile
|
||||
lexor.cc
|
||||
parse.cc
|
||||
parse.cc.output
|
||||
parse.h
|
||||
tables.cc
|
||||
vvp
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.12 2001/03/31 19:00:43 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@ -Wall
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
|
||||
CPPFLAGS = -I. -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ -DMODULE_DIR=\"$(libdir)/ivl\"
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
dllib=@DLLIB@
|
||||
rdynamic=@rdynamic@
|
||||
|
||||
all: vvp
|
||||
|
||||
clean:
|
||||
rm -rf vvp *.o *~ parse.cc parse.cc.output parse.h lexor.cc dep
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h Makefile config.cache config.log config.status
|
||||
|
||||
check: all
|
||||
./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.'
|
||||
|
||||
V = vpi_modules.o vpi_const.o vpi_iter.o vpi_mcd.o vpi_priv.o \
|
||||
vpi_scope.o vpi_signal.o vpi_tasks.o vpi_time.o
|
||||
|
||||
O = main.o parse.o parse_misc.o lexor.o compile.o functor.o symbols.o \
|
||||
codes.o vthread.o schedule.o tables.o $V
|
||||
|
||||
vvp: $O
|
||||
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(dllib)
|
||||
|
||||
|
||||
%.o: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
tables.cc: draw_tt.c
|
||||
$(CC) -o draw_tt draw_tt.c
|
||||
./draw_tt > tables.cc
|
||||
rm draw_tt
|
||||
|
||||
lexor.o: lexor.cc parse.h
|
||||
|
||||
parse.o: parse.cc
|
||||
|
||||
parse.h parse.cc: $(srcdir)/parse.y
|
||||
bison --verbose -t -d $(srcdir)/parse.y -o parse.cc
|
||||
mv parse.cc.h parse.h
|
||||
|
||||
lexor.cc: $(srcdir)/lexor.lex
|
||||
flex -s -olexor.cc $(srcdir)/lexor.lex
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
|
||||
install: all installdirs $(bindir)/vvp
|
||||
|
||||
$(bindir)/vvp: ./vvp
|
||||
$(INSTALL_PROGRAM) ./vvp $(bindir)/vvp
|
||||
|
||||
installdirs: $(srcdir)/mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(bindir)
|
||||
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/vvp
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
+476
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams ([email protected])
|
||||
*
|
||||
* $Id: README.txt,v 1.11 2001/03/30 04:55:22 steve Exp $
|
||||
*/
|
||||
|
||||
VVP SIMULATION ENGINE
|
||||
|
||||
The VVP simulator takes as input source code not unlike assembly
|
||||
language for a conventional processor. It is intended to be machine
|
||||
generated code emitted by other tools, including the Icarus Verilog
|
||||
compiler, so the syntax, though readable, is not necessarily
|
||||
convenient for humans.
|
||||
|
||||
|
||||
GENERAL FORMAT
|
||||
|
||||
The source file is a collection of statements. Each statement may have
|
||||
a label, an opcode, and operands that depend on the opcode. For some
|
||||
opcodes, the label is optional (or meaningless) and for others it is
|
||||
required.
|
||||
|
||||
Every statement is terminated by a semicolon. The semicolon is also
|
||||
the start of a comment line, so you can put comment text after the
|
||||
semicolon that terminates a statement. Like so:
|
||||
|
||||
Label .functor and, 0x5a, x, y ; This is a comment.
|
||||
|
||||
The semicolon is required, whether the comment is there or not.
|
||||
|
||||
Statements may span multiple lines, as long as there is no text (other
|
||||
then the first character of a label) in the first column of the
|
||||
continuation line.
|
||||
|
||||
HEADER SYNTAX
|
||||
|
||||
Before any other non-commentary code starts, the source may contain
|
||||
some header statements. These are used for passing parameters or
|
||||
global details from the compiler to the vvp run-time. In all cases,
|
||||
the header statement starts with a left-justified keyword, and ends
|
||||
with a string.
|
||||
|
||||
* :module "name" ;
|
||||
|
||||
This header statement names a vpi module that vvp should load before
|
||||
the rest of the program is compiled. The compiler looks in the
|
||||
standard VPI_MODULE_PATH for files named "name.vpi", and tries to
|
||||
dynamic load them.
|
||||
|
||||
LABELS AND SYMBOLS
|
||||
|
||||
Labels and symbols consist of the characters:
|
||||
|
||||
a-z
|
||||
A-Z
|
||||
0-9
|
||||
.$_<>
|
||||
|
||||
Labels and symbols may not start with a digit or a '.', so that they
|
||||
are easily distinguished from keywords and numbers. A Label is a
|
||||
symbol that starts a statement. If a label is present in a statement,
|
||||
it must start in the first text column. This is how the lexical
|
||||
analyzer distinguishes a label from a symbol. If a symbol is present
|
||||
in a statement, it is in the operand. Opcodes of statements must be a
|
||||
keyword.
|
||||
|
||||
Symbols are references to labels. It is not necessary for a label to
|
||||
be declared before its use in a symbol, but it must be declared
|
||||
eventually. When symbols refer to functors, the symbol represents the
|
||||
vvp_ipoint_t pointer to the output. (Inputs cannot, and need not, be
|
||||
references symbolically.)
|
||||
|
||||
If the functor is part of a vector, then the symbol is the
|
||||
vvp_ipoint_t for the first functor. The [] operator can then be used
|
||||
to reference a functor other then the first in the vector.
|
||||
|
||||
|
||||
FUNCTOR STATEMENTS:
|
||||
|
||||
A functor statement is a statement that uses the ``.functor''
|
||||
opcode. Functors are the basic structural units of a simulation, and
|
||||
include a type (in the form of a truth table) and up to four inputs. A
|
||||
label is required for functors.
|
||||
|
||||
The general syntax of a functor is:
|
||||
|
||||
<label> .functor <type>, <init> [, symbol_list]
|
||||
|
||||
The symbol list is 0-4 names of labels of other functors. These
|
||||
connect inputs of the functor of the statement to the output of other
|
||||
functors. The type is the label of a .ftype statement elsewhere in the
|
||||
program. The references .ftype describes the behavoir of the
|
||||
functor.
|
||||
|
||||
The <init> value is the 8-bit initial value of the 4 input ports. The
|
||||
LSB is port 0, and the MSB port 3.
|
||||
|
||||
Almost all of the structural aspects of a simulation can be
|
||||
represented by functors, which perform the very basic task of
|
||||
combining up to four inputs down to one output.
|
||||
|
||||
VARIABLE STATEMENTS:
|
||||
|
||||
A variable is a bit vector that can be written by behavioral code (so
|
||||
has no structural input) and propagates its output to a functor. The
|
||||
general syntax of a variable is:
|
||||
|
||||
<label> .var "name", <msb>, <lsb>;
|
||||
|
||||
The "name" is the declared base name of the original variable, for the
|
||||
sake of VPI code that might access it. The variable is placed in the
|
||||
current scope. The variable also has a width, defined by the indices
|
||||
for the mst significant and lest significant bits. If the indices are
|
||||
equal (normally 0) the vector has width of one. If the width is greater
|
||||
then one, a contiguous array of functors is created and the value of
|
||||
the label is the address of the least significant bit.
|
||||
|
||||
A variable does not take inputs, since its value is set behaviorally
|
||||
by assignment events. It does have output, though, and its output is
|
||||
propagated into the net of functors in the usual way.
|
||||
|
||||
Therefore, the .var statement implicitly also creates .functors
|
||||
addressed by the label of the variable. It is in fact the functors
|
||||
that behavioral code reads when the value of the variable (or net) is
|
||||
read by behavioral code. If the .var represents a vector of .functors,
|
||||
the index of the LSB is always, from the perspective of vvp, ZERO. The
|
||||
<msb>,<lsb> details are there only for the benefit of VPI support.
|
||||
|
||||
The variable .functor implicitly has three inputs. The first is the
|
||||
value that gets set by assignments or procedural continuous
|
||||
assignments. The second is a forced value that can be connected to a
|
||||
force expression (as a functor) when a value is being forced. And the
|
||||
third input selects the source to use. The default is to select the
|
||||
assignment input.
|
||||
|
||||
The variable statement also creates a VPI object of the appropriate
|
||||
type. See the vpi.txt file for details about that object.
|
||||
|
||||
Note that nets in a design do not necessarily have a specific functor
|
||||
or object allocated to them. Nets are just something that behavioral
|
||||
code can read, so it is enough to give to the behavioral code the
|
||||
vvp_ipoint_t object of the .functor that drives the net.
|
||||
|
||||
|
||||
NET STATEMENTS:
|
||||
|
||||
A net is similar to a variable, except that a thread cannot write to
|
||||
it (unless it uses a force) and it is given a different VPI type
|
||||
code. The syntax of a .net statement is also similar to but not
|
||||
exactly the same as the .var statement:
|
||||
|
||||
<label> .net "name", <msb>, <lsb>, <symbols_list>;
|
||||
|
||||
A .net statement creates a functor for each bit of the vector in
|
||||
exactly the same way that a .var creates functors. The truth table for
|
||||
a .net functor is the same, as well. The net has an output that may be
|
||||
connected to something, but need not. The 0 (zero) input of each bit
|
||||
functor is the normal input, and is connected to the output of a
|
||||
functor or another net.
|
||||
|
||||
The second functor input is a force net. This connects to an
|
||||
expression that is announced by a force statement of some sort. The
|
||||
third input is the only input settable by behavioral code, it selects
|
||||
between the normal input and the force input. These inputs work
|
||||
exactly the same as those for the .var functors.
|
||||
|
||||
Since .var items are written by behavioral code, there is no worry
|
||||
about how to connect their inputs. You don't. But .net items do have
|
||||
inputs that need to be connected to the outputs of other
|
||||
functors. Nets are also complicated by the fact that they come in
|
||||
vectors, so the inputs of all the functors in the array need to be
|
||||
connected. Fortunately, there is only one input per .net functor that
|
||||
can be connected, and that is input 0.
|
||||
|
||||
The force input and selector input are manipulated exactly the same
|
||||
way as with .var force and selector inputs, so there is no need for a
|
||||
syntax to handle them.
|
||||
|
||||
Since there is exactly one input per bit in the vector, it is easy
|
||||
enough to just list the vvp_ipoint_t symbols in order. Each symbol
|
||||
references a functor, and connects the corresponding .net input to the
|
||||
output of that functor, as if the .net is an <N> bit wide functor. The
|
||||
bits of the vector are connected least-significant-bit first. It is
|
||||
legal to leave a bit unconnected. To do that, simply leave the
|
||||
position for that bit blank. Bits of .nets are initialized to
|
||||
z. Unconnected bits keep the value z throughout the simulation.
|
||||
|
||||
|
||||
EVENT STATEMENTS
|
||||
|
||||
Threads need to interact with the functors of a netlist synchronously,
|
||||
as well as asynchronously. There are cases where the web of functors
|
||||
needs to wake up a waiting thread. The web of functors signals threads
|
||||
through .event objects, that are declare like so:
|
||||
|
||||
<label> .event <type>, <symbols_list>;
|
||||
<label> .event "name";
|
||||
|
||||
|
||||
This event statement declares an object that a %wait instruction
|
||||
can take as an operand. When a thread executes a %wait, it puts
|
||||
itself in the notification list of the event and suspends. The
|
||||
<symbols_list> is a set of inputs that can trigger the event.
|
||||
|
||||
The <type> describes the conditions needed to trigger the event. It
|
||||
may be posedge, negedge or edge. If the type is instead a "name"
|
||||
string, then this is a named event which receives events by the %set
|
||||
instruction instead of from the output of a functor.
|
||||
|
||||
If the event has inputs (a requirement unless it is a named event)
|
||||
then it has up to 4 symbols that address functors. The event then
|
||||
detects the appropriate edge on any of the inputs and signals when the
|
||||
event is true. Normally (in Verilog) a posedge or negedge event only
|
||||
watches a single bit, so the generated code would only include a
|
||||
single symbol for the addressed bit. However, if there are several
|
||||
events of the same edge in an event OR expression, the compiler may
|
||||
combine up to 4 into a single event.
|
||||
|
||||
|
||||
THREAD STATEMENTS:
|
||||
|
||||
Thread statements create the initial threads for a simulation. These
|
||||
represent the initial and always blocks, and possibly other causes to
|
||||
create threads at startup.
|
||||
|
||||
.thread <symbol>
|
||||
|
||||
This statement creates a thread with a starting address at the
|
||||
instruction given by <symbol>.
|
||||
|
||||
|
||||
THREADS IN GENERAL:
|
||||
|
||||
Thread statements create the initial threads of a design. These
|
||||
include the ``initial'' and ``always'' statements of the original
|
||||
Verilog, and possibly some other synthetic threads for various
|
||||
purposes. It is also possible to create transient threads from
|
||||
behavioral code. These are needed to support such constructs as
|
||||
fork/join, named blocks and task activation.
|
||||
|
||||
A transient thread is created with a %fork instruction. When a
|
||||
transient thread is created this way, the operand to the %fork gives
|
||||
the starting address, and the new thread is said to be a child of the
|
||||
forking thread. The children of a thread are pushed onto a stack of
|
||||
children.
|
||||
|
||||
A transient thread is reaped with a %join instruction. %join waits for
|
||||
the top thread in the stack of children to complete, then
|
||||
continues. It is an error to %join when there are no children.
|
||||
|
||||
TRUTH TABLES
|
||||
|
||||
The logic that a functor represents is expressed as a truth table. The
|
||||
functor has four inputs and one output. Each input and output has one
|
||||
of four possible values (0, 1, x and z) so two bits are needed to
|
||||
represent them. So the input of the functor is 8 bits, and the output
|
||||
2 bits. A complete lookup table for generating the 2-bit output from
|
||||
an 8-bit input is 512 bits. That can be packed into 64 bytes. This is
|
||||
small enough that the table should take less space then the code to
|
||||
implement the logic.
|
||||
|
||||
To implement the truth table, we need to assign 2-bit encodings for
|
||||
the 4-value signals. I choose, pseudo-randomly, the following
|
||||
encoding:
|
||||
|
||||
1'b0 : 00
|
||||
1'b1 : 01
|
||||
1'bx : 10
|
||||
1'bz : 11
|
||||
|
||||
The table is an array of 64 bytes, each byte holding 4 2-bit
|
||||
outputs. Construct a 6-bit byte address with inputs 1, 2 and 3 like
|
||||
so:
|
||||
332211
|
||||
|
||||
The input 0 2-bits can then be used to select which of the 4 2-bit
|
||||
pairs in the 8-bit byte are the output:
|
||||
|
||||
MSB -> zzxx1100 <- LSB
|
||||
|
||||
A complete truth table, then is described as 64 8-bit bytes.
|
||||
|
||||
The vvp engine includes truth tables for the primitive gate types, so
|
||||
none needs to be given by the programmer. It is sufficient to name the
|
||||
type to get that truth table.
|
||||
|
||||
|
||||
EXECUTABLE INSTRUCTIONS
|
||||
|
||||
Threads run executable code, much like a processor executes machine
|
||||
code. VVP has a variety of opcodes for executable instructions. All of
|
||||
those instructions start with '%' and go into a single address
|
||||
space. Labels attached to executable instructions get assigned the
|
||||
address of the instruction, and can be the target of %jmp instructions
|
||||
and starting points for threads.
|
||||
|
||||
The opcodes.txt file has a more detailed description of all the
|
||||
various instructions.
|
||||
|
||||
|
||||
THE RELATIONSHIP BETWEEN FUNCTORS, THREADS AND EVENTS
|
||||
|
||||
Given the above summary of the major components of vvp, some
|
||||
description of their relationship is warrented. Functors provide a
|
||||
structural description of the design (so far as it can be described
|
||||
structurally) and these functors run independently of the threads. In
|
||||
particular, when an input to a functor is set, it calculates a new
|
||||
output value; and if that output is different from the existing
|
||||
output, a propagation event is created. Functor output is calculated
|
||||
by truth table lookup, without the aid of threads.
|
||||
|
||||
Propagation events are one of three kinds of events in vvp. They are
|
||||
scheduled to execute at some time, and they simply point to the functor
|
||||
that is to have its output propagated. When the event expires, the
|
||||
output of the referenced functor is propagated to all the inputs that
|
||||
it is connected to, and those functors in turn create new events if
|
||||
needed.
|
||||
|
||||
Assignment events (the second of three types of events) are created
|
||||
by non-blocking assignments in behavioral code. When the ``<='' is
|
||||
executed (a %assign in vvp) an assign event is created, which includes
|
||||
the vvp_ipoint_t pointer to the functor input to receive the value,
|
||||
as well as the value. These are distinct from propagation events because:
|
||||
|
||||
a) There is no functor that has as its output the value to be
|
||||
assigned (this is how values get into the functor net in
|
||||
the first place), and
|
||||
|
||||
b) This allows for behavioral code to create waveforms of
|
||||
arbitrary length that feed into a variable. Verilog allows
|
||||
this of non-blocking assignments, but not of gate outputs.
|
||||
|
||||
The last type of event is the thread schedule event. This event simply
|
||||
points to a thread to be executed. Threads are made up of a virtual
|
||||
processor with a program counter and some private storage. Threads
|
||||
can execute %assign instructions to create assignment events, and can
|
||||
execute %set instructions to do blocking assignments. Threads can also
|
||||
use %load to read the output of functors.
|
||||
|
||||
The core event scheduler takes these three kinds of events and calls
|
||||
the right kind of code to cause things to happen in the design. If the
|
||||
event is a propagate or assignment event, the network of functors is
|
||||
tickled; if the event is a thread schedule, then a thread is run. The
|
||||
implementation of the event queue is not important, but currently is
|
||||
implemented as a ``skip list''. That is, it is a sorted singly linked
|
||||
list with skip pointers that skip over delta-time events.
|
||||
|
||||
The functor net and the threads are distinct. They communicate through
|
||||
thread instructions %set, %assign, %waitfor and %load. So far as a thread
|
||||
is concerned, the functor net is a blob of structure that it pokes and
|
||||
prods via certain functor access instructions.
|
||||
|
||||
|
||||
VVP COMPILATION AND EXECUTION
|
||||
|
||||
The vvp program operates in a few steps:
|
||||
|
||||
1) Initialization
|
||||
Data structures are cleared to empty, and tables are
|
||||
readied for compilation.
|
||||
|
||||
2) Compilation
|
||||
The input file is read and compiled. Symbol tables are
|
||||
build up as needed, objects are allocated and linked
|
||||
together.
|
||||
|
||||
3) Cleanup
|
||||
Symbol tables and other resources used only for
|
||||
compilation are released to reduce the memory
|
||||
footprint.
|
||||
|
||||
4) Simulation
|
||||
Event simulation is run.
|
||||
|
||||
|
||||
The initialization step is performed by the compile_init() function in
|
||||
compile.cc. This function in turn calls all the *_init() functions in
|
||||
other parts of the source that need initialization for compile. All
|
||||
the various sub-init functions are called <foo>_init().
|
||||
|
||||
Compilation is controlled by the parser, it parse.y. As the parser
|
||||
reads and parses input, the compilation proceeds in the rules by
|
||||
calling various compile_* functions. All these functions live in the
|
||||
compile.cc file. Compilation calls other sections of the code as
|
||||
needed.
|
||||
|
||||
When the parser completes compilation, compile_cleanup() is called to
|
||||
finish the compilation process. Unresolved references are completed,
|
||||
then all the symbol tables and other compile-time-only resources are
|
||||
released. Once compile_cleanup() returns, there is no more use for the
|
||||
parser for the function in compile.cc.
|
||||
|
||||
After cleanup, the simulation is started. This is done by executing
|
||||
the schedule_simulate() function. This does any final setup and starts
|
||||
the simulation running and the event queue running.
|
||||
|
||||
|
||||
HOW TO GET FROM THERE TO HERE
|
||||
|
||||
The vvp simulation engine is designed to be able to take as input a
|
||||
compiled form of Verilog. That implies that there is a compiler that
|
||||
compiles Verilog into a form that the vvp engine can read.
|
||||
|
||||
|
||||
* Boolean logic gates
|
||||
|
||||
Gates like AND, OR and NAND are implemented simply and obviously by
|
||||
functor statements. Any logic up to 4 inputs can be implemented with a
|
||||
single functor. For example:
|
||||
|
||||
and gate (out, i1, i2, i3);
|
||||
|
||||
becomes:
|
||||
|
||||
gate .functor and, i1, i2, i3;
|
||||
|
||||
Notice the first parameter of the .functor is the type. The type
|
||||
includes a truth table that describes the output with a given
|
||||
input. If the gate is wider then four inputs, then cascade
|
||||
functors. For example:
|
||||
|
||||
and gate (out, i1, i2, i3, i4, i5, i6, i7, i8);
|
||||
|
||||
becomes:
|
||||
|
||||
gate.0 .functor and, i1, i2, i3, i4;
|
||||
gate.1 .functor and, i5, i6, i7, i8;
|
||||
gate .functor and, gate.0, gate.1;
|
||||
|
||||
|
||||
* reg and other variables
|
||||
|
||||
Reg and integer are cases of what Verilog calls ``variables.''
|
||||
Variables are, simply put, things that behavioral code can assign
|
||||
to. These are not the same as ``nets,'' which include wires and the
|
||||
like.
|
||||
|
||||
Each bit of a variable is created by a ``.var'' statement. For example:
|
||||
|
||||
reg a;
|
||||
|
||||
becomes:
|
||||
|
||||
a .var "a", 0, 0;
|
||||
|
||||
|
||||
* named events
|
||||
|
||||
Events in general are implemented as functors, but named events in
|
||||
partinular have no inputs and only the event output. The way to
|
||||
generate code for these is like so:
|
||||
|
||||
a .event "name";
|
||||
|
||||
This creates a functor and makes it into a mode-2 functor. Then the
|
||||
trigger statement, "-> a", cause a ``%set a, 0;'' statement be
|
||||
generated. This is sufficient to trigger the event.
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: codes.cc,v 1.5 2001/03/22 05:28:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "codes.h"
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
const unsigned code_index0_size = 2 << 9;
|
||||
const unsigned code_index1_size = 2 << 11;
|
||||
const unsigned code_index2_size = 2 << 10;
|
||||
|
||||
struct code_index0 {
|
||||
struct vvp_code_s table[code_index0_size];
|
||||
};
|
||||
|
||||
struct code_index1 {
|
||||
struct code_index0* table[code_index1_size];
|
||||
};
|
||||
|
||||
static vvp_cpoint_t code_count = 0;
|
||||
static struct code_index1*code_table[code_index2_size] = { 0 };
|
||||
|
||||
|
||||
void codespace_init(void)
|
||||
{
|
||||
code_table[0] = 0;
|
||||
code_count = 1;
|
||||
}
|
||||
|
||||
vvp_cpoint_t codespace_allocate(void)
|
||||
{
|
||||
vvp_cpoint_t idx = code_count;
|
||||
|
||||
idx /= code_index0_size;
|
||||
|
||||
unsigned index1 = idx % code_index1_size;
|
||||
idx /= code_index1_size;
|
||||
|
||||
assert(idx < code_index2_size);
|
||||
|
||||
if (code_table[idx] == 0) {
|
||||
code_table[idx] = new struct code_index1;
|
||||
memset(code_table[idx], 0, sizeof code_table[idx]);
|
||||
}
|
||||
|
||||
if (code_table[idx]->table[index1] == 0) {
|
||||
code_table[idx]->table[index1] = new struct code_index0;
|
||||
memset(code_table[idx]->table[index1],
|
||||
0, sizeof(struct code_index0));
|
||||
}
|
||||
|
||||
vvp_cpoint_t res = code_count;
|
||||
code_count += 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
vvp_code_t codespace_index(vvp_cpoint_t point)
|
||||
{
|
||||
assert(point < code_count);
|
||||
|
||||
unsigned index0 = point % code_index0_size;
|
||||
point /= code_index0_size;
|
||||
|
||||
unsigned index1 = point % code_index1_size;
|
||||
point /= code_index1_size;
|
||||
|
||||
return code_table[point]->table[index1]->table + index0;
|
||||
}
|
||||
|
||||
void codespace_dump(FILE*fd)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < code_count ; idx += 1) {
|
||||
fprintf(fd, " %8x: ", idx);
|
||||
vvp_code_t cop = codespace_index(idx);
|
||||
|
||||
if (cop->opcode == &of_ASSIGN) {
|
||||
fprintf(fd, "%%assign 0x%u, %u, %u\n",
|
||||
cop->iptr, cop->bit_idx1, cop->bit_idx2);
|
||||
|
||||
} else if (cop->opcode == &of_DELAY) {
|
||||
fprintf(fd, "%%delay %lu\n", (unsigned long)cop->number);
|
||||
|
||||
} else if (cop->opcode == &of_END) {
|
||||
fprintf(fd, "%%end\n");
|
||||
|
||||
} else if (cop->opcode == &of_JMP) {
|
||||
fprintf(fd, "%%jmp 0x%u\n", cop->cptr);
|
||||
|
||||
} else if (cop->opcode == &of_JMP0) {
|
||||
fprintf(fd, "%%jmp/0 0x%u\n", cop->cptr);
|
||||
|
||||
} else if (cop->opcode == &of_SET) {
|
||||
fprintf(fd, "%%set 0x%u, %u\n", cop->iptr, cop->bit_idx1);
|
||||
|
||||
} else {
|
||||
fprintf(fd, "opcode %p\n", cop->opcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: codes.cc,v $
|
||||
* Revision 1.5 2001/03/22 05:28:41 steve
|
||||
* Add code label forward references.
|
||||
*
|
||||
* Revision 1.4 2001/03/22 05:08:00 steve
|
||||
* implement %load, %inv, %jum/0 and %cmp/u
|
||||
*
|
||||
* Revision 1.3 2001/03/20 06:16:23 steve
|
||||
* Add support for variable vectors.
|
||||
*
|
||||
* Revision 1.2 2001/03/11 23:06:49 steve
|
||||
* Compact the vvp_code_s structure.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
*/
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
#ifndef __codes_H
|
||||
#define __codes_H
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: codes.h,v 1.10 2001/03/31 17:36:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pointers.h"
|
||||
# include "vthread.h"
|
||||
# include <stdio.h>
|
||||
|
||||
typedef struct vvp_code_s *vvp_code_t;
|
||||
typedef bool (*vvp_code_fun)(vthread_t thr, vvp_code_t code);
|
||||
|
||||
/*
|
||||
* These functions are implementations of executable op-codes. The
|
||||
* implementation lives in the vthread.cc file so that they have
|
||||
* access to the thread context.
|
||||
*/
|
||||
extern bool of_ADD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_CMPU(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DELAY(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_END(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_FORK(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_INV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP0XZ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JMP1(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_WAIT(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);
|
||||
|
||||
/*
|
||||
* This is the format of a machine code instruction.
|
||||
*/
|
||||
struct vvp_code_s {
|
||||
vvp_code_fun opcode;
|
||||
|
||||
union {
|
||||
unsigned number;
|
||||
vvp_ipoint_t iptr;
|
||||
vvp_cpoint_t cptr;
|
||||
struct __vpiHandle*handle;
|
||||
};
|
||||
|
||||
unsigned short bit_idx1;
|
||||
unsigned short bit_idx2;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This function clears the code space, ready for initialization. This
|
||||
* needs to be done exactly once before any instructions are created.
|
||||
*/
|
||||
extern void codespace_init(void);
|
||||
|
||||
/*
|
||||
* This function returns a pointer to the next free instruction in the
|
||||
* code address space.
|
||||
*/
|
||||
extern vvp_cpoint_t codespace_allocate(void);
|
||||
|
||||
/*
|
||||
* Return a pointer to the indexed instruction in the codespace. The
|
||||
* ptr must be a value returned from codespace_allocate. The compiler
|
||||
* can use this to get a handle on the instruction to be created, and
|
||||
* the runtime uses this to get the instruction addressed by the PC or
|
||||
* by a branch instruction.
|
||||
*/
|
||||
extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
|
||||
|
||||
extern void codespace_dump(FILE*fd);
|
||||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.10 2001/03/31 17:36:02 steve
|
||||
* Add the jmp/1 instruction.
|
||||
*
|
||||
* Revision 1.9 2001/03/31 01:59:58 steve
|
||||
* Add the ADD instrunction.
|
||||
*
|
||||
* Revision 1.8 2001/03/30 04:55:22 steve
|
||||
* Add fork and join instructions.
|
||||
*
|
||||
* Revision 1.7 2001/03/26 04:00:39 steve
|
||||
* Add the .event statement and the %wait instruction.
|
||||
*
|
||||
* Revision 1.6 2001/03/25 03:54:26 steve
|
||||
* Add JMP0XZ and postpone net inputs when needed.
|
||||
*
|
||||
* Revision 1.5 2001/03/22 05:08:00 steve
|
||||
* implement %load, %inv, %jum/0 and %cmp/u
|
||||
*
|
||||
* Revision 1.4 2001/03/20 06:16:24 steve
|
||||
* Add support for variable vectors.
|
||||
*
|
||||
* Revision 1.3 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.2 2001/03/11 23:06:49 steve
|
||||
* Compact the vvp_code_s structure.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+763
@@ -0,0 +1,763 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: compile.cc,v 1.22 2001/03/31 19:00:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
# include "functor.h"
|
||||
# include "symbols.h"
|
||||
# include "codes.h"
|
||||
# include "schedule.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "vthread.h"
|
||||
# include "parse_misc.h"
|
||||
# include <malloc.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
unsigned compile_errors = 0;
|
||||
|
||||
/*
|
||||
* The opcode table lists all the code mnemonics, along with their
|
||||
* opcode and operand types. The table is written sorted by mnemonic
|
||||
* so that it can be searched by binary search. The opcode_compare
|
||||
* function is a helper function for that lookup.
|
||||
*/
|
||||
|
||||
enum operand_e {
|
||||
/* Place holder for unused operand */
|
||||
OA_NONE,
|
||||
/* The operand is a number, an immediate unsigned integer */
|
||||
OA_NUMBER,
|
||||
/* The operand is a thread bit index */
|
||||
OA_BIT1,
|
||||
OA_BIT2,
|
||||
/* The operand is a pointer to code space */
|
||||
OA_CODE_PTR,
|
||||
/* The operand is a variable or net pointer */
|
||||
OA_FUNC_PTR
|
||||
};
|
||||
|
||||
struct opcode_table_s {
|
||||
const char*mnemonic;
|
||||
vvp_code_fun opcode;
|
||||
|
||||
unsigned argc;
|
||||
enum operand_e argt[OPERAND_MAX];
|
||||
};
|
||||
|
||||
const static struct opcode_table_s opcode_table[] = {
|
||||
{ "%add", of_ADD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%cmp/u", of_CMPU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%delay", of_DELAY, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%fork", of_FORK, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%inv", of_INV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
|
||||
{ "%jmp", of_JMP, 1, {OA_CODE_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%jmp/0", of_JMP0, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/0xz",of_JMP0XZ, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%jmp/1", of_JMP1, 2, {OA_CODE_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%join", of_JOIN, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%wait", of_WAIT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ 0, of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} }
|
||||
};
|
||||
|
||||
static unsigned opcode_count = 0;
|
||||
|
||||
static int opcode_compare(const void*k, const void*r)
|
||||
{
|
||||
const char*kp = (const char*)k;
|
||||
const struct opcode_table_s*rp = (const struct opcode_table_s*)r;
|
||||
return strcmp(kp, rp->mnemonic);
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep a symbol table of addresses within code space. Labels on
|
||||
* executable opcodes are mapped to their address here.
|
||||
*/
|
||||
static symbol_table_t sym_codespace = 0;
|
||||
|
||||
/*
|
||||
* Keep a symbol table of functors mentioned in the source. This table
|
||||
* is used to resolve references as they come.
|
||||
*/
|
||||
static symbol_table_t sym_functors = 0;
|
||||
|
||||
/*
|
||||
* VPI objects are indexed during compile time so that they can be
|
||||
* linked together as they are created. This symbol table matches
|
||||
* labels to vpiHandles.
|
||||
*/
|
||||
static symbol_table_t sym_vpi = 0;
|
||||
|
||||
|
||||
/*
|
||||
* If a functor parameter makes a forward reference to a functor, then
|
||||
* I need to save that reference and resolve it after the functors are
|
||||
* created. Use this structure to keep the unresolved references in an
|
||||
* unsorted singly linked list.
|
||||
*
|
||||
* The postpone_functor_input arranges for a functor input to be
|
||||
* resolved and connected at cleanup. This is used if the symbol is
|
||||
* defined after its use in a functor. The ptr parameter is the
|
||||
* complete vvp_input_t for the input port.
|
||||
*/
|
||||
struct resolv_list_s {
|
||||
struct resolv_list_s*next;
|
||||
vvp_ipoint_t port;
|
||||
|
||||
char*source;
|
||||
unsigned idx;
|
||||
};
|
||||
|
||||
static struct resolv_list_s*resolv_list = 0;
|
||||
|
||||
static void postpone_functor_input(vvp_ipoint_t ptr, char*lab, unsigned idx)
|
||||
{
|
||||
struct resolv_list_s*res = (struct resolv_list_s*)
|
||||
calloc(1, sizeof(struct resolv_list_s));
|
||||
|
||||
res->port = ptr;
|
||||
res->source = lab;
|
||||
res->idx = idx;
|
||||
res->next = resolv_list;
|
||||
resolv_list = res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Instructions may make forward references to labels. In this case,
|
||||
* the compile makes one of these to remember to retry the
|
||||
* resolution.
|
||||
*/
|
||||
struct cresolv_list_s {
|
||||
struct cresolv_list_s*next;
|
||||
struct vvp_code_s*cp;
|
||||
char*lab;
|
||||
};
|
||||
|
||||
static struct cresolv_list_s*cresolv_list = 0;
|
||||
|
||||
void compile_vpi_symbol(const char*label, vpiHandle obj)
|
||||
{
|
||||
symbol_value_t val;
|
||||
val.ptr = obj;
|
||||
sym_set_value(sym_vpi, label, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the compiler by allocation empty symbol tables and
|
||||
* initializing the various address spaces.
|
||||
*/
|
||||
void compile_init(void)
|
||||
{
|
||||
sym_vpi = new_symbol_table();
|
||||
compile_vpi_symbol("$time", vpip_sim_time());
|
||||
|
||||
sym_functors = new_symbol_table();
|
||||
functor_init();
|
||||
|
||||
sym_codespace = new_symbol_table();
|
||||
codespace_init();
|
||||
|
||||
opcode_count = 0;
|
||||
while (opcode_table[opcode_count].mnemonic)
|
||||
opcode_count += 1;
|
||||
}
|
||||
|
||||
void compile_load_vpi_module(char*name)
|
||||
{
|
||||
vpip_load_module(name, module_path);
|
||||
free(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* The parser calls this function to create a functor. I allocate a
|
||||
* functor, and map the name to the vvp_ipoint_t address for the
|
||||
* functor. Also resolve the inputs to the functor.
|
||||
*/
|
||||
void compile_functor(char*label, char*type, unsigned init,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_t obj = functor_index(fdx);
|
||||
|
||||
{ symbol_value_t val;
|
||||
val.num = fdx;
|
||||
sym_set_value(sym_functors, label, val);
|
||||
}
|
||||
|
||||
assert(argc <= 4);
|
||||
|
||||
/* Run through the arguments looking for the functors that are
|
||||
connected to my input ports. For each source functor that I
|
||||
find, connect the output of that functor to the indexed
|
||||
input by inserting myself (complete with the port number in
|
||||
the vvp_ipoint_t) into the list that the source heads.
|
||||
|
||||
If the source functor is not declared yet, then don't do
|
||||
the link yet. Save the reference to be resolved later. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < argc ; idx += 1) {
|
||||
symbol_value_t val = sym_get_value(sym_functors, argv[idx].text);
|
||||
vvp_ipoint_t tmp = val.num;
|
||||
|
||||
if (tmp) {
|
||||
tmp = ipoint_index(tmp, argv[idx].idx);
|
||||
functor_t fport = functor_index(tmp);
|
||||
obj->port[idx] = fport->out;
|
||||
fport->out = ipoint_make(fdx, idx);
|
||||
|
||||
free(argv[idx].text);
|
||||
|
||||
} else {
|
||||
postpone_functor_input(ipoint_make(fdx, idx),
|
||||
argv[idx].text,
|
||||
argv[idx].idx);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
obj->ival = init;
|
||||
obj->oval = 2;
|
||||
obj->mode = 0;
|
||||
|
||||
if (strcmp(type, "OR") == 0) {
|
||||
obj->table = ft_OR;
|
||||
|
||||
} else if (strcmp(type, "AND") == 0) {
|
||||
obj->table = ft_AND;
|
||||
|
||||
} else if (strcmp(type, "NOR") == 0) {
|
||||
obj->table = ft_NOR;
|
||||
|
||||
} else if (strcmp(type, "NOT") == 0) {
|
||||
obj->table = ft_NOT;
|
||||
|
||||
} else {
|
||||
yyerror("invalid functor type.");
|
||||
}
|
||||
|
||||
free(argv);
|
||||
free(label);
|
||||
free(type);
|
||||
}
|
||||
|
||||
void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_t obj = functor_index(fdx);
|
||||
|
||||
{ symbol_value_t val;
|
||||
val.num = fdx;
|
||||
sym_set_value(sym_functors, label, val);
|
||||
}
|
||||
|
||||
assert(argc <= 4);
|
||||
|
||||
/* Run through the arguments looking for the functors that are
|
||||
connected to my input ports. For each source functor that I
|
||||
find, connect the output of that functor to the indexed
|
||||
input by inserting myself (complete with the port number in
|
||||
the vvp_ipoint_t) into the list that the source heads.
|
||||
|
||||
If the source functor is not declared yet, then don't do
|
||||
the link yet. Save the reference to be resolved later. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < argc ; idx += 1) {
|
||||
symbol_value_t val = sym_get_value(sym_functors, argv[idx].text);
|
||||
vvp_ipoint_t tmp = val.num;
|
||||
|
||||
if (tmp) {
|
||||
tmp = ipoint_index(tmp, argv[idx].idx);
|
||||
functor_t fport = functor_index(tmp);
|
||||
obj->port[idx] = fport->out;
|
||||
fport->out = ipoint_make(fdx, idx);
|
||||
|
||||
free(argv[idx].text);
|
||||
|
||||
} else {
|
||||
postpone_functor_input(ipoint_make(fdx, idx),
|
||||
argv[idx].text,
|
||||
argv[idx].idx);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
free(argv);
|
||||
|
||||
obj->ival = 0xaa;
|
||||
obj->oval = 2;
|
||||
obj->mode = 1;
|
||||
|
||||
obj->event = (struct vvp_event_s*) malloc(sizeof (struct vvp_event_s));
|
||||
obj->event->threads = 0;
|
||||
obj->event->ival = obj->ival;
|
||||
|
||||
if (strcmp(type,"posedge") == 0)
|
||||
obj->event->vvp_edge_tab = vvp_edge_posedge;
|
||||
else if (strcmp(type,"negedge") == 0)
|
||||
obj->event->vvp_edge_tab = vvp_edge_negedge;
|
||||
else if (strcmp(type,"edge") == 0)
|
||||
obj->event->vvp_edge_tab = vvp_edge_anyedge;
|
||||
else
|
||||
obj->event->vvp_edge_tab = 0;
|
||||
|
||||
free(type);
|
||||
free(label);
|
||||
}
|
||||
|
||||
void compile_named_event(char*label, char*name)
|
||||
{
|
||||
vvp_ipoint_t fdx = functor_allocate(1);
|
||||
functor_t obj = functor_index(fdx);
|
||||
|
||||
{ symbol_value_t val;
|
||||
val.num = fdx;
|
||||
sym_set_value(sym_functors, label, val);
|
||||
}
|
||||
|
||||
obj->ival = 0xaa;
|
||||
obj->oval = 2;
|
||||
obj->mode = 2;
|
||||
|
||||
obj->event = (struct vvp_event_s*) malloc(sizeof (struct vvp_event_s));
|
||||
obj->event->threads = 0;
|
||||
obj->event->ival = obj->ival;
|
||||
|
||||
free(label);
|
||||
free(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* The parser uses this function to compile an link an executable
|
||||
* opcode. I do this by looking up the opcode in the opcode_table. The
|
||||
* table gives the operand structure that is acceptible, so I can
|
||||
* process the operands here as well.
|
||||
*/
|
||||
void compile_code(char*label, char*mnem, comp_operands_t opa)
|
||||
{
|
||||
vvp_cpoint_t ptr = codespace_allocate();
|
||||
|
||||
/* First, I can give the label a value that is the current
|
||||
codespace pointer. Don't need the text of the label after
|
||||
this is done. */
|
||||
if (label) {
|
||||
symbol_value_t val;
|
||||
val.num = ptr;
|
||||
sym_set_value(sym_codespace, label, val);
|
||||
free(label);
|
||||
}
|
||||
|
||||
/* Lookup the opcode in the opcode table. */
|
||||
struct opcode_table_s*op = (struct opcode_table_s*)
|
||||
bsearch(mnem, opcode_table, opcode_count,
|
||||
sizeof(struct opcode_table_s), &opcode_compare);
|
||||
if (op == 0) {
|
||||
yyerror("Invalid opcode");
|
||||
return;
|
||||
}
|
||||
|
||||
assert(op);
|
||||
|
||||
/* Build up the code from the information about the opcode and
|
||||
the information from the comiler. */
|
||||
vvp_code_t code = codespace_index(ptr);
|
||||
code->opcode = op->opcode;
|
||||
|
||||
if (op->argc != (opa? opa->argc : 0)) {
|
||||
yyerror("operand count");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pull the operands that the instruction expects from the
|
||||
list that the parser supplied. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < op->argc ; idx += 1) {
|
||||
symbol_value_t tmp;
|
||||
|
||||
switch (op->argt[idx]) {
|
||||
case OA_NONE:
|
||||
break;
|
||||
|
||||
case OA_BIT1:
|
||||
if (opa->argv[idx].ltype != L_NUMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
code->bit_idx1 = opa->argv[idx].numb;
|
||||
break;
|
||||
|
||||
case OA_BIT2:
|
||||
if (opa->argv[idx].ltype != L_NUMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
code->bit_idx2 = opa->argv[idx].numb;
|
||||
break;
|
||||
|
||||
case OA_CODE_PTR:
|
||||
if (opa->argv[idx].ltype != L_SYMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
assert(opa->argv[idx].symb.idx == 0);
|
||||
tmp = sym_get_value(sym_codespace, opa->argv[idx].symb.text);
|
||||
code->cptr = tmp.num;
|
||||
if (code->cptr == 0) {
|
||||
struct cresolv_list_s*res = (struct cresolv_list_s*)
|
||||
calloc(1, sizeof(struct cresolv_list_s));
|
||||
res->cp = code;
|
||||
res->lab = opa->argv[idx].symb.text;
|
||||
res->next = cresolv_list;
|
||||
cresolv_list = res;
|
||||
|
||||
} else {
|
||||
|
||||
free(opa->argv[idx].symb.text);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OA_FUNC_PTR:
|
||||
if (opa->argv[idx].ltype != L_SYMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = sym_get_value(sym_functors, opa->argv[idx].symb.text);
|
||||
if (tmp.num == 0) {
|
||||
yyerror("functor undefined");
|
||||
break;
|
||||
}
|
||||
code->iptr = ipoint_index(tmp.num, opa->argv[idx].symb.idx);
|
||||
|
||||
free(opa->argv[idx].symb.text);
|
||||
break;
|
||||
|
||||
case OA_NUMBER:
|
||||
if (opa->argv[idx].ltype != L_NUMB) {
|
||||
yyerror("operand format");
|
||||
break;
|
||||
}
|
||||
|
||||
code->number = opa->argv[idx].numb;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (opa) free(opa);
|
||||
|
||||
free(mnem);
|
||||
}
|
||||
|
||||
void compile_vpi_call(char*label, char*name, unsigned argc, vpiHandle*argv)
|
||||
{
|
||||
vvp_cpoint_t ptr = codespace_allocate();
|
||||
|
||||
/* First, I can give the label a value that is the current
|
||||
codespace pointer. Don't need the text of the label after
|
||||
this is done. */
|
||||
if (label) {
|
||||
symbol_value_t val;
|
||||
val.num = ptr;
|
||||
sym_set_value(sym_codespace, label, val);
|
||||
free(label);
|
||||
}
|
||||
|
||||
/* Create an instruction in the code space. */
|
||||
vvp_code_t code = codespace_index(ptr);
|
||||
code->opcode = &of_VPI_CALL;
|
||||
|
||||
/* Create a vpiHandle that bundles the call information, and
|
||||
store that handle in the instruction. */
|
||||
code->handle = vpip_build_vpi_call(name, argc, argv);
|
||||
if (code->handle == 0)
|
||||
compile_errors += 1;
|
||||
|
||||
/* Done with the lexor-allocated name string. */
|
||||
free(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the parser finds a thread statement, I create a new thread
|
||||
* with the start address referenced by the program symbol passed to
|
||||
* me.
|
||||
*/
|
||||
void compile_thread(char*start_sym)
|
||||
{
|
||||
symbol_value_t tmp = sym_get_value(sym_codespace, start_sym);
|
||||
vvp_cpoint_t pc = tmp.num;
|
||||
if (pc == 0) {
|
||||
yyerror("unresolved address");
|
||||
return;
|
||||
}
|
||||
|
||||
vthread_t thr = v_newthread(pc);
|
||||
schedule_vthread(thr, 0);
|
||||
free(start_sym);
|
||||
}
|
||||
|
||||
vpiHandle compile_vpi_lookup(const char*label)
|
||||
{
|
||||
symbol_value_t val;
|
||||
|
||||
val = sym_get_value(sym_vpi, label);
|
||||
return (vpiHandle) val.ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* A variable is a special functor, so we allocate that functor and
|
||||
* write the label into the symbol table.
|
||||
*/
|
||||
void compile_variable(char*label, char*name, int msb, int lsb)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
vvp_ipoint_t fdx = functor_allocate(wid);
|
||||
symbol_value_t val;
|
||||
val.num = fdx;
|
||||
sym_set_value(sym_functors, label, val);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
functor_t obj = functor_index(ipoint_index(fdx,idx));
|
||||
obj->table = ft_var;
|
||||
obj->ival = 0x22;
|
||||
obj->oval = 0x02;
|
||||
obj->mode = 0;
|
||||
}
|
||||
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vpiHandle obj = vpip_make_reg(name, msb, lsb, fdx);
|
||||
compile_vpi_symbol(label, obj);
|
||||
|
||||
free(label);
|
||||
}
|
||||
|
||||
void compile_net(char*label, char*name, int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv)
|
||||
{
|
||||
unsigned wid = ((msb > lsb)? msb-lsb : lsb-msb) + 1;
|
||||
vvp_ipoint_t fdx = functor_allocate(wid);
|
||||
symbol_value_t val;
|
||||
val.num = fdx;
|
||||
sym_set_value(sym_functors, label, val);
|
||||
|
||||
/* Allocate all the functors for the net itself. */
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
functor_t obj = functor_index(ipoint_index(fdx,idx));
|
||||
obj->table = ft_var;
|
||||
obj->ival = 0x22;
|
||||
obj->oval = 0x02;
|
||||
obj->mode = 0;
|
||||
}
|
||||
|
||||
assert(argc == wid);
|
||||
|
||||
/* Connect port[0] of each of the net functors to the output
|
||||
of the addressed object. */
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t ptr = ipoint_index(fdx,idx);
|
||||
functor_t obj = functor_index(ptr);
|
||||
|
||||
val = sym_get_value(sym_functors, argv[idx].text);
|
||||
if (val.num) {
|
||||
|
||||
functor_t src = functor_index(ipoint_index(val.num,
|
||||
argv[idx].idx));
|
||||
obj->port[0] = src->out;
|
||||
src->out = ptr;
|
||||
|
||||
} else {
|
||||
postpone_functor_input(ipoint_make(ptr, 0),
|
||||
argv[idx].text,
|
||||
argv[idx].idx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the vpiHandle for the reg. */
|
||||
vpiHandle obj = vpip_make_net(name, msb, lsb, fdx);
|
||||
compile_vpi_symbol(label, obj);
|
||||
|
||||
free(label);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* When parsing is otherwise complete, this function is called to do
|
||||
* the final stuff. Clean up deferred linking here.
|
||||
*/
|
||||
void compile_cleanup(void)
|
||||
{
|
||||
struct resolv_list_s*tmp_list = resolv_list;
|
||||
resolv_list = 0;
|
||||
|
||||
while (tmp_list) {
|
||||
struct resolv_list_s*res = tmp_list;
|
||||
tmp_list = res->next;
|
||||
|
||||
/* Get the addressed functor object and select the input
|
||||
port that needs resolution. */
|
||||
functor_t obj = functor_index(res->port);
|
||||
unsigned idx = ipoint_port(res->port);
|
||||
|
||||
/* Try again to look up the symbol that was not defined
|
||||
the first time around. */
|
||||
symbol_value_t val = sym_get_value(sym_functors, res->source);
|
||||
vvp_ipoint_t tmp = val.num;
|
||||
|
||||
if (tmp != 0) {
|
||||
/* The symbol is defined, link the functor input
|
||||
to the resolved output. */
|
||||
|
||||
tmp = ipoint_index(tmp, res->idx);
|
||||
functor_t fport = functor_index(tmp);
|
||||
obj->port[idx] = fport->out;
|
||||
fport->out = res->port;
|
||||
|
||||
free(res->source);
|
||||
free(res);
|
||||
|
||||
} else {
|
||||
/* Still not resolved. put back into the list. */
|
||||
res->next = resolv_list;
|
||||
resolv_list = res;
|
||||
}
|
||||
}
|
||||
|
||||
struct cresolv_list_s*tmp_clist = cresolv_list;
|
||||
cresolv_list = 0;
|
||||
|
||||
while (tmp_clist) {
|
||||
struct cresolv_list_s*res = tmp_clist;
|
||||
tmp_clist = res->next;
|
||||
|
||||
symbol_value_t val = sym_get_value(sym_codespace, res->lab);
|
||||
vvp_cpoint_t tmp = val.num;
|
||||
|
||||
if (tmp != 0) {
|
||||
res->cp->cptr = tmp;
|
||||
free(res->lab);
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "unresolved code label: %s\n", res->lab);
|
||||
res->next = cresolv_list;
|
||||
cresolv_list = res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void compile_dump(FILE*fd)
|
||||
{
|
||||
fprintf(fd, "FUNCTOR SYMBOL TABLE:\n");
|
||||
sym_dump(sym_functors, fd);
|
||||
fprintf(fd, "FUNCTORS:\n");
|
||||
functor_dump(fd);
|
||||
fprintf(fd, "UNRESOLVED PORT INPUTS:\n");
|
||||
for (struct resolv_list_s*cur = resolv_list ; cur ; cur = cur->next)
|
||||
fprintf(fd, " %p: %s\n", (void*)cur->port, cur->source);
|
||||
|
||||
fprintf(fd, "CODE SPACE SYMBOL TABLE:\n");
|
||||
sym_dump(sym_codespace, fd);
|
||||
|
||||
fprintf(fd, "CODE SPACE DISASSEMBLY:\n");
|
||||
codespace_dump(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.22 2001/03/31 19:00:43 steve
|
||||
* Add VPI support for the simulation time.
|
||||
*
|
||||
* Revision 1.21 2001/03/31 17:36:02 steve
|
||||
* Add the jmp/1 instruction.
|
||||
*
|
||||
* Revision 1.20 2001/03/31 01:59:59 steve
|
||||
* Add the ADD instrunction.
|
||||
*
|
||||
* Revision 1.19 2001/03/30 04:55:22 steve
|
||||
* Add fork and join instructions.
|
||||
*
|
||||
* Revision 1.18 2001/03/29 03:46:36 steve
|
||||
* Support named events as mode 2 functors.
|
||||
*
|
||||
* Revision 1.17 2001/03/28 17:24:32 steve
|
||||
* include string.h for strcmp et al.
|
||||
*
|
||||
* Revision 1.16 2001/03/26 04:00:39 steve
|
||||
* Add the .event statement and the %wait instruction.
|
||||
*
|
||||
* Revision 1.15 2001/03/25 19:38:23 steve
|
||||
* Support NOR and NOT gates.
|
||||
*
|
||||
* Revision 1.14 2001/03/25 03:54:26 steve
|
||||
* Add JMP0XZ and postpone net inputs when needed.
|
||||
*
|
||||
* Revision 1.13 2001/03/25 00:35:35 steve
|
||||
* Add the .net statement.
|
||||
*
|
||||
* Revision 1.12 2001/03/23 02:40:22 steve
|
||||
* Add the :module header statement.
|
||||
*
|
||||
* Revision 1.11 2001/03/22 22:38:13 steve
|
||||
* Detect undefined system tasks at compile time.
|
||||
*
|
||||
* Revision 1.10 2001/03/22 05:28:41 steve
|
||||
* Add code label forward references.
|
||||
*
|
||||
* Revision 1.9 2001/03/22 05:08:00 steve
|
||||
* implement %load, %inv, %jum/0 and %cmp/u
|
||||
*
|
||||
* Revision 1.8 2001/03/21 05:13:03 steve
|
||||
* Allow var objects as vpiHandle arguments to %vpi_call.
|
||||
*
|
||||
* Revision 1.7 2001/03/20 06:16:24 steve
|
||||
* Add support for variable vectors.
|
||||
*
|
||||
* Revision 1.6 2001/03/18 04:35:18 steve
|
||||
* Add support for string constants to VPI.
|
||||
*
|
||||
* Revision 1.5 2001/03/18 00:37:55 steve
|
||||
* Add support for vpi scopes.
|
||||
*
|
||||
* Revision 1.4 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.3 2001/03/11 23:06:49 steve
|
||||
* Compact the vvp_code_s structure.
|
||||
*
|
||||
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||
* Functor values and propagation.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
*/
|
||||
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
#ifndef __compile_H
|
||||
#define __compile_H
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: compile.h,v 1.12 2001/03/29 03:46:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include "parse_misc.h"
|
||||
# include "vpi_user.h"
|
||||
|
||||
/*
|
||||
* The functions described here are the compile time support
|
||||
* functions. Various bits of the compile process are taken care of
|
||||
* here. What is called when is mostly controlled by the parser.
|
||||
*
|
||||
* Before compilation takes place, the compile_init function must be
|
||||
* called once to set stuff up.
|
||||
*/
|
||||
|
||||
extern void compile_init(void);
|
||||
|
||||
extern void compile_cleanup(void);
|
||||
|
||||
/*
|
||||
* This is a count of errors encountered during compilation. If this
|
||||
* is non-zero, then simulation is not recommended.
|
||||
*/
|
||||
extern unsigned compile_errors;
|
||||
|
||||
extern const char* module_path;
|
||||
extern void compile_load_vpi_module(char*name);
|
||||
|
||||
/*
|
||||
* This function is called by the parser to compile a functor
|
||||
* statement. The strings passed in are allocated by the lexor, but
|
||||
* this function will free them. (Or save them permanently.) This
|
||||
* includes the argv array and the strings it references.
|
||||
*
|
||||
* The argc and argv are a list of char* that are the port paramters
|
||||
* of the functor. The compile should match those port parameters up
|
||||
* to existing functors to manage the linking.
|
||||
*/
|
||||
extern void compile_functor(char*label, char*type, unsigned init,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
|
||||
extern void compile_vpi_symbol(const char*label, vpiHandle obj);
|
||||
extern vpiHandle compile_vpi_lookup(const char*label);
|
||||
|
||||
/*
|
||||
* The compile_event function takes the parts of the event statement
|
||||
* and makes the various objects needed to simulate it. This includes
|
||||
* the functor that receives the signals and the event_t that holds
|
||||
* the threads.
|
||||
*/
|
||||
extern void compile_event(char*label, char*type,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
extern void compile_named_event(char*label, char*name);
|
||||
|
||||
/*
|
||||
* A code statement is a label, an opcode and up to 3 operands. There
|
||||
* are a few lexical types that the parser recognizes of the operands,
|
||||
* given by the ltype_e enumeration. The compile_code function takes
|
||||
* the label, mnemonic and parsed operands and writes a properly
|
||||
* formed instruction into the code space. The label is set into the
|
||||
* symbol table with the address of the instruction.
|
||||
*/
|
||||
|
||||
#define OPERAND_MAX 3
|
||||
enum ltype_e { L_NUMB, L_SYMB };
|
||||
|
||||
struct comp_operands_s {
|
||||
unsigned argc;
|
||||
struct {
|
||||
enum ltype_e ltype;
|
||||
union {
|
||||
unsigned long numb;
|
||||
struct symb_s symb;
|
||||
};
|
||||
} argv[OPERAND_MAX];
|
||||
};
|
||||
|
||||
typedef struct comp_operands_s*comp_operands_t;
|
||||
|
||||
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
|
||||
extern void compile_vpi_call(char*label, char*name,
|
||||
unsigned argc, vpiHandle*argv);
|
||||
|
||||
/*
|
||||
* The parser uses these functions to compile .scope statements.
|
||||
* The implementations of these live in the vpi_scope.cc file.
|
||||
*/
|
||||
extern void compile_scope_decl(char*lab, char*nam, char*par);
|
||||
extern void compile_scope_recall(char*sym);
|
||||
|
||||
/*
|
||||
* The parser uses this function to declare a thread. The start_sym is
|
||||
* the start instruction, and must already be defined.
|
||||
*/
|
||||
extern void compile_thread(char*start_sym);
|
||||
|
||||
/*
|
||||
* This function is called to create a var vector with the given name.
|
||||
*/
|
||||
extern void compile_variable(char*label, char*name, int msb, int lsb);
|
||||
|
||||
extern void compile_net(char*label, char*name, int msb, int lsb,
|
||||
unsigned argc, struct symb_s*argv);
|
||||
|
||||
/*
|
||||
* This is a diagnostic aid. Dump all the compiler tables to the file
|
||||
* descriptor in a readable form.
|
||||
*/
|
||||
extern void compile_dump(FILE*fd);
|
||||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.12 2001/03/29 03:46:36 steve
|
||||
* Support named events as mode 2 functors.
|
||||
*
|
||||
* Revision 1.11 2001/03/26 04:00:39 steve
|
||||
* Add the .event statement and the %wait instruction.
|
||||
*
|
||||
* Revision 1.10 2001/03/25 00:35:35 steve
|
||||
* Add the .net statement.
|
||||
*
|
||||
* Revision 1.9 2001/03/23 02:40:22 steve
|
||||
* Add the :module header statement.
|
||||
*
|
||||
* Revision 1.8 2001/03/22 22:38:14 steve
|
||||
* Detect undefined system tasks at compile time.
|
||||
*
|
||||
* Revision 1.7 2001/03/21 05:13:03 steve
|
||||
* Allow var objects as vpiHandle arguments to %vpi_call.
|
||||
*
|
||||
* Revision 1.6 2001/03/20 06:16:24 steve
|
||||
* Add support for variable vectors.
|
||||
*
|
||||
* Revision 1.5 2001/03/18 04:35:18 steve
|
||||
* Add support for string constants to VPI.
|
||||
*
|
||||
* Revision 1.4 2001/03/18 00:37:55 steve
|
||||
* Add support for vpi scopes.
|
||||
*
|
||||
* Revision 1.3 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||
* Functor values and propagation.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+912
@@ -0,0 +1,912 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# 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.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Written by Per Bothner <[email protected]>.
|
||||
# The master version of this file is at the FSF in /home/gd/gnu/lib.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
# exits with 0. Otherwise, it exits with 1.
|
||||
#
|
||||
# The plan is that this can be called by configure scripts if you
|
||||
# don't specify an explicit system type (host/target name).
|
||||
#
|
||||
# Only a few systems have been added to this list; please add others
|
||||
# (but try to keep the structure clean).
|
||||
#
|
||||
|
||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
|
||||
# ([email protected] 8/24/94.)
|
||||
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
|
||||
PATH=$PATH:/.attbin ; export PATH
|
||||
fi
|
||||
|
||||
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
|
||||
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
||||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
||||
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||
|
||||
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
|
||||
|
||||
# Note: order is significant - the case branches are not exclusive.
|
||||
|
||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
alpha:OSF1:*:*)
|
||||
if test $UNAME_RELEASE = "V4.0"; then
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
fi
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
cat <<EOF >dummy.s
|
||||
.globl main
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,0,\$26,0
|
||||
.prologue 0
|
||||
.long 0x47e03d80 # implver $0
|
||||
lda \$2,259
|
||||
.long 0x47e20c21 # amask $2,$1
|
||||
srl \$1,8,\$2
|
||||
sll \$2,2,\$2
|
||||
sll \$0,3,\$0
|
||||
addl \$1,\$0,\$0
|
||||
addl \$2,\$0,\$0
|
||||
ret \$31,(\$26),1
|
||||
.end main
|
||||
EOF
|
||||
${CC-cc} dummy.s -o dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy
|
||||
case "$?" in
|
||||
7)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
15)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
14)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
10)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
16)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -f dummy.s dummy
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
|
||||
exit 0 ;;
|
||||
21064:Windows_NT:50:3)
|
||||
echo alpha-dec-winnt3.5
|
||||
exit 0 ;;
|
||||
Amiga*:UNIX_System_V:4.0:*)
|
||||
echo m68k-cbm-sysv4
|
||||
exit 0;;
|
||||
amiga:NetBSD:*:*)
|
||||
echo m68k-cbm-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
amiga:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arc64:OpenBSD:*:*)
|
||||
echo mips64el-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hkmips:OpenBSD:*:*)
|
||||
echo mips-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
pmax:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sgi:OpenBSD:*:*)
|
||||
echo mips-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
wgrisc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||
exit 0;;
|
||||
arm32:NetBSD:*:*)
|
||||
echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
SR2?01:HI-UX/MPP:*:*)
|
||||
echo hppa1.1-hitachi-hiuxmpp
|
||||
exit 0;;
|
||||
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
|
||||
# [email protected] (Earle F. Ake) contributed MIS and NILE.
|
||||
if test "`(/bin/universe) 2>/dev/null`" = att ; then
|
||||
echo pyramid-pyramid-sysv3
|
||||
else
|
||||
echo pyramid-pyramid-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
NILE:*:*:dcosx)
|
||||
echo pyramid-pyramid-svr4
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
i86pc:SunOS:5.*:*)
|
||||
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
# According to config.sub, this is the proper way to canonicalize
|
||||
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
|
||||
# it's likely to be more like Solaris than SunOS4.
|
||||
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:*:*)
|
||||
case "`/usr/bin/arch -k`" in
|
||||
Series*|S4*)
|
||||
UNAME_RELEASE=`uname -v`
|
||||
;;
|
||||
esac
|
||||
# Japanese Language versions have a version number like `4.1.3-JL'.
|
||||
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
|
||||
exit 0 ;;
|
||||
sun3*:SunOS:*:*)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
sun3)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
;;
|
||||
sun4)
|
||||
echo sparc-sun-sunos${UNAME_RELEASE}
|
||||
;;
|
||||
esac
|
||||
exit 0 ;;
|
||||
aushp:SunOS:*:*)
|
||||
echo sparc-auspex-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:NetBSD:*:*)
|
||||
echo m68k-atari-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:NetBSD:*:*)
|
||||
echo m68k-sun-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:NetBSD:*:*)
|
||||
echo m68k-apple-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme88k:OpenBSD:*:*)
|
||||
echo m88k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
powerpc:machten:*:*)
|
||||
echo powerpc-apple-machten${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
RISC*:Mach:*:*)
|
||||
echo mips-dec-mach_bsd4.3
|
||||
exit 0 ;;
|
||||
RISC*:ULTRIX:*:*)
|
||||
echo mips-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
VAX*:ULTRIX*:*:*)
|
||||
echo vax-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
2020:CLIX:*:*)
|
||||
echo clipper-intergraph-clix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mips:*:*:UMIPS | mips:*:*:RISCos)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
int main (argc, argv) int argc; char **argv; {
|
||||
#if defined (host_mips) && defined (MIPSEB)
|
||||
#if defined (SYSTYPE_SYSV)
|
||||
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#if defined (SYSTYPE_SVR4)
|
||||
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
|
||||
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
exit (-1);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy \
|
||||
&& ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo mips-mips-riscos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Night_Hawk:Power_UNIX:*:*)
|
||||
echo powerpc-harris-powerunix
|
||||
exit 0 ;;
|
||||
m88k:CX/UX:7*:*)
|
||||
echo m88k-harris-cxux7
|
||||
exit 0 ;;
|
||||
m88k:*:4*:R4*)
|
||||
echo m88k-motorola-sysv4
|
||||
exit 0 ;;
|
||||
m88k:*:3*:R3*)
|
||||
echo m88k-motorola-sysv3
|
||||
exit 0 ;;
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
|
||||
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
|
||||
echo m88k-dg-dgux${UNAME_RELEASE}
|
||||
else
|
||||
echo m88k-dg-dguxbcs${UNAME_RELEASE}
|
||||
fi
|
||||
else echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
||||
echo m88k-dolphin-sysv3
|
||||
exit 0 ;;
|
||||
M88*:*:R3*:*)
|
||||
# Delta 88k system running SVR3
|
||||
echo m88k-motorola-sysv3
|
||||
exit 0 ;;
|
||||
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
|
||||
echo m88k-tektronix-sysv3
|
||||
exit 0 ;;
|
||||
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
|
||||
echo m68k-tektronix-bsd
|
||||
exit 0 ;;
|
||||
*:IRIX*:*:*)
|
||||
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
|
||||
exit 0 ;;
|
||||
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
|
||||
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
|
||||
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
|
||||
i?86:AIX:*:*)
|
||||
echo i386-ibm-aix
|
||||
exit 0 ;;
|
||||
*:AIX:2:3)
|
||||
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
main()
|
||||
{
|
||||
if (!__power_pc())
|
||||
exit(1);
|
||||
puts("powerpc-ibm-aix3.2.5");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo rs6000-ibm-aix3.2.5
|
||||
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
echo rs6000-ibm-aix3.2.4
|
||||
else
|
||||
echo rs6000-ibm-aix3.2
|
||||
fi
|
||||
exit 0 ;;
|
||||
*:AIX:*:4)
|
||||
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
else
|
||||
IBM_ARCH=powerpc
|
||||
fi
|
||||
if [ -x /usr/bin/oslevel ] ; then
|
||||
IBM_REV=`/usr/bin/oslevel`
|
||||
else
|
||||
IBM_REV=4.${UNAME_RELEASE}
|
||||
fi
|
||||
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
|
||||
exit 0 ;;
|
||||
*:AIX:*:*)
|
||||
echo rs6000-ibm-aix
|
||||
exit 0 ;;
|
||||
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
|
||||
echo romp-ibm-bsd4.4
|
||||
exit 0 ;;
|
||||
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
|
||||
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
|
||||
exit 0 ;; # report: romp-ibm BSD 4.3
|
||||
*:BOSX:*:*)
|
||||
echo rs6000-bull-bosx
|
||||
exit 0 ;;
|
||||
DPX/2?00:B.O.S.:*:*)
|
||||
echo m68k-bull-sysv3
|
||||
exit 0 ;;
|
||||
9000/[34]??:4.3bsd:1.*:*)
|
||||
echo m68k-hp-bsd
|
||||
exit 0 ;;
|
||||
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
|
||||
echo m68k-hp-bsd4.4
|
||||
exit 0 ;;
|
||||
9000/[3478]??:HP-UX:*:*)
|
||||
case "${UNAME_MACHINE}" in
|
||||
9000/31? ) HP_ARCH=m68000 ;;
|
||||
9000/[34]?? ) HP_ARCH=m68k ;;
|
||||
9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
|
||||
9000/8?? ) HP_ARCH=hppa1.0 ;;
|
||||
esac
|
||||
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
exit 0 ;;
|
||||
3050*:HI-UX:*:*)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
#include <unistd.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
long cpu = sysconf (_SC_CPU_VERSION);
|
||||
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
|
||||
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
|
||||
results, however. */
|
||||
if (CPU_IS_PA_RISC (cpu))
|
||||
{
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
|
||||
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
|
||||
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
|
||||
default: puts ("hppa-hitachi-hiuxwe2"); break;
|
||||
}
|
||||
}
|
||||
else if (CPU_IS_HP_MC68K (cpu))
|
||||
puts ("m68k-hitachi-hiuxwe2");
|
||||
else puts ("unknown-hitachi-hiuxwe2");
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo unknown-hitachi-hiuxwe2
|
||||
exit 0 ;;
|
||||
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
|
||||
echo hppa1.1-hp-bsd
|
||||
exit 0 ;;
|
||||
9000/8??:4.3bsd:*:*)
|
||||
echo hppa1.0-hp-bsd
|
||||
exit 0 ;;
|
||||
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
|
||||
echo hppa1.1-hp-osf
|
||||
exit 0 ;;
|
||||
hp8??:OSF1:*:*)
|
||||
echo hppa1.0-hp-osf
|
||||
exit 0 ;;
|
||||
i?86:OSF1:*:*)
|
||||
if [ -x /usr/sbin/sysversion ] ; then
|
||||
echo ${UNAME_MACHINE}-unknown-osf1mk
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-osf1
|
||||
fi
|
||||
exit 0 ;;
|
||||
parisc*:Lites*:*:*)
|
||||
echo hppa1.1-hp-lites
|
||||
exit 0 ;;
|
||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
|
||||
echo c34-convex-bsd
|
||||
exit 0 ;;
|
||||
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
|
||||
echo c38-convex-bsd
|
||||
exit 0 ;;
|
||||
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
|
||||
echo c4-convex-bsd
|
||||
exit 0 ;;
|
||||
CRAY*X-MP:*:*:*)
|
||||
echo xmp-cray-unicos
|
||||
exit 0 ;;
|
||||
CRAY*Y-MP:*:*:*)
|
||||
echo ymp-cray-unicos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
CRAY*[A-Z]90:*:*:*)
|
||||
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
|
||||
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
|
||||
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
|
||||
exit 0 ;;
|
||||
CRAY*TS:*:*:*)
|
||||
echo t90-cray-unicos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
CRAY-2:*:*:*)
|
||||
echo cray2-cray-unicos
|
||||
exit 0 ;;
|
||||
F300:UNIX_System_V:*:*)
|
||||
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit 0 ;;
|
||||
F301:UNIX_System_V:*:*)
|
||||
echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
|
||||
exit 0 ;;
|
||||
hp3[0-9][05]:NetBSD:*:*)
|
||||
echo m68k-hp-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hp300:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
i?86:BSD/386:*:* | *:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:FreeBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||
exit 0 ;;
|
||||
*:NetBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
i*:CYGWIN*:*)
|
||||
echo i386-pc-cygwin32
|
||||
exit 0 ;;
|
||||
i*:MINGW*:*)
|
||||
echo i386-pc-mingw32
|
||||
exit 0 ;;
|
||||
p*:CYGWIN*:*)
|
||||
echo powerpcle-unknown-cygwin32
|
||||
exit 0 ;;
|
||||
prep*:SunOS:5.*:*)
|
||||
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
*:GNU:*:*)
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
exit 0 ;;
|
||||
*:Linux:*:*)
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us.
|
||||
ld_help_string=`ld --help 2>&1`
|
||||
ld_supported_emulations=`echo $ld_help_string \
|
||||
| sed -ne '/supported emulations:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/.*supported emulations: *//
|
||||
s/ .*//
|
||||
p'`
|
||||
case "$ld_supported_emulations" in
|
||||
i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
|
||||
i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
|
||||
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
elf32ppc)
|
||||
# Determine Lib Version
|
||||
cat >dummy.c <<EOF
|
||||
#include <features.h>
|
||||
#if defined(__GLIBC__)
|
||||
extern char __libc_version[];
|
||||
extern char __libc_release[];
|
||||
#endif
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#if defined(__GLIBC__)
|
||||
printf("%s %s\n", __libc_version, __libc_release);
|
||||
#else
|
||||
printf("unkown\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy | grep 1\.99 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f dummy.c dummy
|
||||
echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
|
||||
esac
|
||||
|
||||
if test "${UNAME_MACHINE}" = "alpha" ; then
|
||||
sed 's/^ //' <<EOF >dummy.s
|
||||
.globl main
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,0,\$26,0
|
||||
.prologue 0
|
||||
.long 0x47e03d80 # implver $0
|
||||
lda \$2,259
|
||||
.long 0x47e20c21 # amask $2,$1
|
||||
srl \$1,8,\$2
|
||||
sll \$2,2,\$2
|
||||
sll \$0,3,\$0
|
||||
addl \$1,\$0,\$0
|
||||
addl \$2,\$0,\$0
|
||||
ret \$31,(\$26),1
|
||||
.end main
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} dummy.s -o dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy
|
||||
case "$?" in
|
||||
7)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
15)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
14)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
10)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
16)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
esac
|
||||
|
||||
objdump --private-headers dummy | \
|
||||
grep ld.so.1 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f dummy.s dummy
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
|
||||
elif test "${UNAME_MACHINE}" = "mips" ; then
|
||||
cat >dummy.c <<EOF
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __MIPSEB__
|
||||
printf ("%s-unknown-linux-gnu\n", argv[1]);
|
||||
#endif
|
||||
#ifdef __MIPSEL__
|
||||
printf ("%sel-unknown-linux-gnu\n", argv[1]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
else
|
||||
# Either a pre-BFD a.out linker (linux-gnuoldld)
|
||||
# or one that does not give us useful --help.
|
||||
# GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
|
||||
# If ld does not provide *any* "supported emulations:"
|
||||
# that means it is gnuoldld.
|
||||
echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
|
||||
test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
|
||||
|
||||
case "${UNAME_MACHINE}" in
|
||||
i?86)
|
||||
VENDOR=pc;
|
||||
;;
|
||||
*)
|
||||
VENDOR=unknown;
|
||||
;;
|
||||
esac
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
cat >dummy.c <<EOF
|
||||
#include <features.h>
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
|
||||
# else
|
||||
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
|
||||
# endif
|
||||
# else
|
||||
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
|
||||
# endif
|
||||
#else
|
||||
printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
fi ;;
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
|
||||
# are messed up and put the nodename in both sysname and nodename.
|
||||
i?86:DYNIX/ptx:4*:*)
|
||||
echo i386-sequent-sysv4
|
||||
exit 0 ;;
|
||||
i?86:UNIX_SV:4.2MP:2.*)
|
||||
# Unixware is an offshoot of SVR4, but it has its own version
|
||||
# number series starting with 2...
|
||||
# I am not positive that other SVR4 systems won't match this,
|
||||
# I just have to hope. -- rms.
|
||||
# Use sysv4.2uw... so that sysv4* matches it.
|
||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
|
||||
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
|
||||
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*:3.2:*)
|
||||
if test -f /usr/options/cb.name; then
|
||||
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
|
||||
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
|
||||
elif /bin/uname -X 2>/dev/null >/dev/null ; then
|
||||
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
|
||||
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv32
|
||||
fi
|
||||
exit 0 ;;
|
||||
pc:*:*:*)
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i386.
|
||||
echo i386-pc-msdosdjgpp
|
||||
exit 0 ;;
|
||||
Intel:Mach:3*:*)
|
||||
echo i386-pc-mach3
|
||||
exit 0 ;;
|
||||
paragon:*:*:*)
|
||||
echo i860-intel-osf1
|
||||
exit 0 ;;
|
||||
i860:*:4.*:*) # i860-SVR4
|
||||
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
|
||||
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
|
||||
else # Add other i860-SVR4 vendors below as they are discovered.
|
||||
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
|
||||
fi
|
||||
exit 0 ;;
|
||||
mini*:CTIX:SYS*5:*)
|
||||
# "miniframe"
|
||||
echo m68010-convergent-sysv
|
||||
exit 0 ;;
|
||||
M68*:*:R3V[567]*:*)
|
||||
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
|
||||
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
|
||||
OS_REL=''
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& echo i486-ncr-sysv4.3${OS_REL} && exit 0
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
&& echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
|
||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& echo i486-ncr-sysv4 && exit 0 ;;
|
||||
m68*:LynxOS:2.*:*)
|
||||
echo m68k-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mc68030:UNIX_System_V:4.*:*)
|
||||
echo m68k-atari-sysv4
|
||||
exit 0 ;;
|
||||
i?86:LynxOS:2.*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
TSUNAMI:LynxOS:2.*:*)
|
||||
echo sparc-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
|
||||
echo rs6000-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
SM[BE]S:UNIX_SV:*:*)
|
||||
echo mips-dde-sysv${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
RM*:SINIX-*:*:*)
|
||||
echo mips-sni-sysv4
|
||||
exit 0 ;;
|
||||
*:SINIX-*:*:*)
|
||||
if uname -p 2>/dev/null >/dev/null ; then
|
||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||
echo ${UNAME_MACHINE}-sni-sysv4
|
||||
else
|
||||
echo ns32k-sni-sysv
|
||||
fi
|
||||
exit 0 ;;
|
||||
PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
||||
# says <[email protected]>
|
||||
echo i586-unisys-sysv4
|
||||
exit 0 ;;
|
||||
*:UNIX_System_V:4*:FTX*)
|
||||
# From Gerald Hewes <[email protected]>.
|
||||
# How about differentiating between stratus architectures? -djm
|
||||
echo hppa1.1-stratus-sysv4
|
||||
exit 0 ;;
|
||||
*:*:*:FTX*)
|
||||
# From [email protected].
|
||||
echo i860-stratus-sysv4
|
||||
exit 0 ;;
|
||||
mc68*:A/UX:*:*)
|
||||
echo m68k-apple-aux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
news*:NEWS-OS:*:6*)
|
||||
echo mips-sony-newsos6
|
||||
exit 0 ;;
|
||||
R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
|
||||
if [ -d /usr/nec ]; then
|
||||
echo mips-nec-sysv${UNAME_RELEASE}
|
||||
else
|
||||
echo mips-unknown-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
|
||||
|
||||
cat >dummy.c <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
#if defined (MIPSEB)
|
||||
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
|
||||
I don't know.... */
|
||||
printf ("mips-sony-bsd\n"); exit (0);
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
printf ("m68k-sony-newsos%s\n",
|
||||
#ifdef NEWSOS4
|
||||
"4"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__arm) && defined (__acorn) && defined (__unix)
|
||||
printf ("arm-acorn-riscix"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (hp300) && !defined (hpux)
|
||||
printf ("m68k-hp-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (NeXT)
|
||||
#if !defined (__ARCHITECTURE__)
|
||||
#define __ARCHITECTURE__ "m68k"
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (MULTIMAX) || defined (n16)
|
||||
#if defined (UMAXV)
|
||||
printf ("ns32k-encore-sysv\n"); exit (0);
|
||||
#else
|
||||
#if defined (CMU)
|
||||
printf ("ns32k-encore-mach\n"); exit (0);
|
||||
#else
|
||||
printf ("ns32k-encore-bsd\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__386BSD__)
|
||||
printf ("i386-pc-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (sequent)
|
||||
#if defined (i386)
|
||||
printf ("i386-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#if defined (ns32000)
|
||||
printf ("ns32k-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (_SEQUENT_)
|
||||
struct utsname un;
|
||||
|
||||
uname(&un);
|
||||
|
||||
if (strncmp(un.version, "V2", 2) == 0) {
|
||||
printf ("i386-sequent-ptx2\n"); exit (0);
|
||||
}
|
||||
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
|
||||
printf ("i386-sequent-ptx1\n"); exit (0);
|
||||
}
|
||||
printf ("i386-sequent-ptx\n"); exit (0);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (vax)
|
||||
#if !defined (ultrix)
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
#else
|
||||
printf ("vax-dec-ultrix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (alliant) && defined (i860)
|
||||
printf ("i860-alliant-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
exit (1);
|
||||
}
|
||||
EOF
|
||||
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
|
||||
|
||||
# Convex versions that predate uname can use getsysinfo(1)
|
||||
|
||||
if [ -x /usr/convex/getsysinfo ]
|
||||
then
|
||||
case `getsysinfo -f cpu_type` in
|
||||
c1*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
c2*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
c34*)
|
||||
echo c34-convex-bsd
|
||||
exit 0 ;;
|
||||
c38*)
|
||||
echo c38-convex-bsd
|
||||
exit 0 ;;
|
||||
c4*)
|
||||
echo c4-convex-bsd
|
||||
exit 0 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#echo '(Unable to guess system type)' 1>&2
|
||||
|
||||
exit 1
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef __config_H
|
||||
#define __config_H
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: config.h.in,v 1.3 2001/03/22 21:26:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# define SIZEOF_UNSIGNED_LONG 0
|
||||
# define SIZEOF_UNSIGNED 0
|
||||
|
||||
# undef HAVE_DLFCN_H
|
||||
# undef HAVE_DL_H
|
||||
|
||||
# define LU ""
|
||||
# define TU ""
|
||||
|
||||
#ifndef MODULE_DIR
|
||||
# define MODULE_DIR "."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.3 2001/03/22 21:26:53 steve
|
||||
* Compile in a default VPI module dir.
|
||||
*
|
||||
* Revision 1.2 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+1178
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
AC_INIT(Makefile.in)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
AC_CHECK_SIZEOF(unsigned)
|
||||
|
||||
# --
|
||||
# Look for a dl library to use. First look for the standard dlopen
|
||||
# functions, and failing that look for the HP specific shl_load function.
|
||||
|
||||
AC_CHECK_HEADERS(dlfcn.h dl.h, break)
|
||||
|
||||
DLLIB=''
|
||||
AC_CHECK_LIB(dl,dlopen,[DLLIB=-ldl])
|
||||
if test -z "$DLLIB" ; then
|
||||
AC_CHECK_LIB(dld,shl_load,[DLLIB=-ldld])
|
||||
fi
|
||||
AC_SUBST(DLLIB)
|
||||
|
||||
|
||||
# The -rdynamic flag is used by iverilog when compiling the target,
|
||||
# to know how to export symbols of the main program to loadable modules
|
||||
# that are brought in by -ldl. VPI support requires this.
|
||||
AC_MSG_CHECKING("for -rdynamic compiler flag")
|
||||
|
||||
rdynamic=-rdynamic
|
||||
case "${host}" in
|
||||
|
||||
*-*-netbsd*)
|
||||
rdynamic="-Wl,--export-dynamic"
|
||||
;;
|
||||
|
||||
*-*-solaris*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
rdynamic="-E"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(rdynamic)
|
||||
AC_MSG_RESULT($rdynamic)
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (c) 2001 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
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: draw_tt.c,v 1.3 2001/03/25 20:45:09 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
static void draw_AND(void)
|
||||
{
|
||||
unsigned i0, i1, i2, i3;
|
||||
|
||||
printf("const unsigned char ft_AND[64] = {");
|
||||
|
||||
for (i3 = 0 ; i3 < 4 ; i3 += 1)
|
||||
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
|
||||
printf("\n ");
|
||||
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
|
||||
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
|
||||
unsigned char byte = 0;
|
||||
|
||||
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
|
||||
unsigned val;
|
||||
if ((i0 == 0) || (i1 == 0) ||
|
||||
(i2 == 0) || (i3 == 0))
|
||||
val = 0;
|
||||
else if ((i0 == 1) && (i1 == 1) &&
|
||||
(i2 == 1) && (i3 == 1))
|
||||
val = 1;
|
||||
else
|
||||
val = 2;
|
||||
|
||||
byte |= val << (i0*2);
|
||||
}
|
||||
|
||||
printf("0x%02x, ", byte);
|
||||
}
|
||||
}
|
||||
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static void draw_NOR(void)
|
||||
{
|
||||
unsigned i0, i1, i2, i3;
|
||||
|
||||
printf("const unsigned char ft_NOR[64] = {");
|
||||
|
||||
for (i3 = 0 ; i3 < 4 ; i3 += 1)
|
||||
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
|
||||
printf("\n ");
|
||||
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
|
||||
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
|
||||
unsigned char byte = 0;
|
||||
|
||||
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
|
||||
unsigned val;
|
||||
if ((i0 == 1) || (i1 == 1) ||
|
||||
(i2 == 1) || (i3 == 1))
|
||||
val = 0;
|
||||
else if ((i0 == 0) && (i1 == 0) &&
|
||||
(i2 == 0) && (i3 == 0))
|
||||
val = 1;
|
||||
else
|
||||
val = 2;
|
||||
|
||||
byte |= val << (i0*2);
|
||||
}
|
||||
|
||||
printf("0x%02x, ", byte);
|
||||
}
|
||||
}
|
||||
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static void draw_NOT(void)
|
||||
{
|
||||
unsigned i0, i1, i2, i3;
|
||||
|
||||
printf("const unsigned char ft_NOT[64] = {");
|
||||
|
||||
for (i3 = 0 ; i3 < 4 ; i3 += 1)
|
||||
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
|
||||
printf("\n ");
|
||||
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
|
||||
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
|
||||
unsigned char byte = 0;
|
||||
|
||||
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
|
||||
unsigned val;
|
||||
if (i0 == 1)
|
||||
val = 0;
|
||||
else if (i0 == 0)
|
||||
val = 1;
|
||||
else
|
||||
val = 2;
|
||||
|
||||
byte |= val << (i0*2);
|
||||
}
|
||||
|
||||
printf("0x%02x, ", byte);
|
||||
}
|
||||
}
|
||||
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static void draw_OR(void)
|
||||
{
|
||||
unsigned i0, i1, i2, i3;
|
||||
|
||||
printf("const unsigned char ft_OR[64] = {");
|
||||
|
||||
for (i3 = 0 ; i3 < 4 ; i3 += 1)
|
||||
for (i2 = 0 ; i2 < 4 ; i2 += 1) {
|
||||
printf("\n ");
|
||||
for (i1 = 0 ; i1 < 4 ; i1 += 1) {
|
||||
unsigned idx = (i3 << 4) | (i2 << 2) | i1;
|
||||
unsigned char byte = 0;
|
||||
|
||||
for (i0 = 0 ; i0 < 4 ; i0 += 1) {
|
||||
unsigned val;
|
||||
if ((i0 == 1) || (i1 == 1) ||
|
||||
(i2 == 1) || (i3 == 1))
|
||||
val = 1;
|
||||
else if ((i0 == 0) && (i1 == 0) &&
|
||||
(i2 == 0) && (i3 == 0))
|
||||
val = 0;
|
||||
else
|
||||
val = 2;
|
||||
|
||||
byte |= val << (i0*2);
|
||||
}
|
||||
|
||||
printf("0x%02x, ", byte);
|
||||
}
|
||||
}
|
||||
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* The hex_digits table is not a functor truth table per say, but a
|
||||
* map of a 4-vbit value to a hex digit. The table handles the display
|
||||
* of x, X, z, Z, etc.
|
||||
*/
|
||||
static void draw_hex_table()
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
printf("extern const char hex_digits[256] = {\n");
|
||||
for (idx = 0 ; idx < 256 ; idx += 1) {
|
||||
unsigned cnt_z = 0, cnt_x = 0;
|
||||
unsigned bv = 0, bdx;
|
||||
|
||||
for (bdx = 0 ; bdx < 4 ; bdx += 1) {
|
||||
switch ((idx >> (bdx * 2)) & 3) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
bv |= 1<<bdx;
|
||||
break;
|
||||
case 2:
|
||||
cnt_x += 1;
|
||||
break;
|
||||
case 3:
|
||||
cnt_z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt_z == 4)
|
||||
printf(" 'z',");
|
||||
|
||||
else if (cnt_x == 4)
|
||||
printf(" 'x',");
|
||||
|
||||
else if ((cnt_z > 0) && (cnt_x == 0))
|
||||
printf(" 'Z',");
|
||||
|
||||
else if (cnt_x > 0)
|
||||
printf(" 'X',");
|
||||
|
||||
else
|
||||
printf(" '%c',", "0123456789abcdef"[bv]);
|
||||
|
||||
if (((idx+1) % 8) == 0)
|
||||
printf("\n");
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static void draw_oct_table()
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
printf("extern const char oct_digits[64] = {\n");
|
||||
for (idx = 0 ; idx < 64 ; idx += 1) {
|
||||
unsigned cnt_z = 0, cnt_x = 0;
|
||||
unsigned bv = 0, bdx;
|
||||
|
||||
for (bdx = 0 ; bdx < 3 ; bdx += 1) {
|
||||
switch ((idx >> (bdx * 2)) & 3) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
bv |= 1<<bdx;
|
||||
break;
|
||||
case 2:
|
||||
cnt_x += 1;
|
||||
break;
|
||||
case 3:
|
||||
cnt_z += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cnt_z == 3)
|
||||
printf(" 'z',");
|
||||
|
||||
else if (cnt_x == 3)
|
||||
printf(" 'x',");
|
||||
|
||||
else if ((cnt_z > 0) && (cnt_x == 0))
|
||||
printf(" 'Z',");
|
||||
|
||||
else if (cnt_x > 0)
|
||||
printf(" 'X',");
|
||||
|
||||
else
|
||||
printf(" '%c',", "01234567"[bv]);
|
||||
|
||||
if (((idx+1) % 8) == 0)
|
||||
printf("\n");
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
printf("# include \"functor.h\"\n");
|
||||
draw_AND();
|
||||
draw_NOR();
|
||||
draw_NOT();
|
||||
draw_OR();
|
||||
draw_hex_table();
|
||||
draw_oct_table();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: draw_tt.c,v $
|
||||
* Revision 1.3 2001/03/25 20:45:09 steve
|
||||
* Add vpiOctStrVal access to signals.
|
||||
*
|
||||
* Revision 1.2 2001/03/25 19:37:26 steve
|
||||
* Calculate NOR and NOT tables, and also the hex_digits table.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 22:42:11 steve
|
||||
* Functor values and propagation.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001 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
|
||||
|
||||
|
||||
; This example is similar to the code that the following Verilog program
|
||||
; would make:
|
||||
;
|
||||
; module main;
|
||||
; reg a;
|
||||
; wire b = a;
|
||||
; initial begin
|
||||
; a = 0;
|
||||
; #1 $display("a=%b, b=%b", a, b);
|
||||
; a = 1;
|
||||
; #1 $display("a=%b, b=%b", a, b);
|
||||
; end
|
||||
; endmodule
|
||||
;
|
||||
; This tests that a simple continuous assign of a net from a var works
|
||||
; properly. This is a very trivial functor propagation that is initiated
|
||||
; by the %set instruction.
|
||||
|
||||
main .scope "main";
|
||||
|
||||
V_main.a .var "a", 0, 0;
|
||||
V_main.b .net "b", 0, 0, V_main.a;
|
||||
|
||||
code
|
||||
%set V_main.a, 0;
|
||||
%delay 1;
|
||||
%vpi_call "$display", "a=%b, b=%b", V_main.a, V_main.b;
|
||||
%set V_main.a, 1;
|
||||
%delay 1;
|
||||
%vpi_call "$display", "a=%b, b=%b", V_main.a, V_main.b;
|
||||
%end;
|
||||
|
||||
.thread code;
|
||||
@@ -0,0 +1,52 @@
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001 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
|
||||
|
||||
|
||||
; This example tests the operation of a simple posedge event. The module
|
||||
; that would generate code like this would be:
|
||||
;
|
||||
; module main;
|
||||
; reg a;
|
||||
;
|
||||
; initial begin
|
||||
; a = 0;
|
||||
; #1 a = 1;
|
||||
; end
|
||||
;
|
||||
; always @(posedge a) $display("Got a posedge.");
|
||||
;
|
||||
; endmodule
|
||||
;
|
||||
|
||||
main .scope "main";
|
||||
|
||||
V_main.a .var "a", 0, 0;
|
||||
V_main.b .event posedge, V_main.a;
|
||||
|
||||
code
|
||||
%set V_main.a, 0;
|
||||
%delay 1;
|
||||
%set V_main.a, 1;
|
||||
%end;
|
||||
.thread code;
|
||||
|
||||
loop %wait V_main.b;
|
||||
%vpi_call "$display", "Got a posedge.";
|
||||
%jmp loop;
|
||||
.thread loop;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user