Compare commits

...
118 Commits
Author SHA1 Message Date
steve e29ecdc234 Fix compilation warnings. 2001-03-31 19:29:23 +00:00
steve 0f6eea7024 Handle $time as system task parameter. 2001-03-31 19:08:22 +00:00
steve 97dd559fca Clear results of condition expressions. 2001-03-31 19:02:13 +00:00
steve a4c722b195 Add VPI support for the simulation time. 2001-03-31 19:00:43 +00:00
steve b3a3b888d8 Generate vvp code for case statements. 2001-03-31 17:36:38 +00:00
steve 2f1d258acb Add the jmp/1 instruction. 2001-03-31 17:36:02 +00:00
steve 7aa9bc9892 Generate code for + and concat expressions. 2001-03-31 02:00:44 +00:00
steve 4a058632b2 Add the ADD instrunction. 2001-03-31 01:59:58 +00:00
steve 6a72b4c10e Make empty event sub-expression a noop. 2001-03-30 23:24:02 +00:00
steve 00d44222dd Initialize the event_ list of new scopes. 2001-03-30 06:10:15 +00:00
steve b36b6d0ca0 Generate code for fork/join statements. 2001-03-30 05:49:52 +00:00
steve 386958f9a0 Add fork and join instructions. 2001-03-30 04:55:22 +00:00
steve f6eb581aff Handle truncation/padding of numbers. 2001-03-29 05:16:25 +00:00
steve 966f7a4bff Behavioral trigger statements. 2001-03-29 03:47:38 +00:00
steve 2cb76cabef events can take up to 4 inputs. 2001-03-29 03:47:13 +00:00
steve 609d5fe727 Support named events as mode 2 functors. 2001-03-29 03:46:36 +00:00
steve 522d0ec864 Add unary ~ operator to tgt-vvp. 2001-03-29 02:52:39 +00:00
steve ad8565f8a6 Add const probe method to NetEvent. 2001-03-29 02:52:01 +00:00
steve b0c003dc34 include string.h for strcmp et al. 2001-03-28 17:24:32 +00:00
steve a4e528f0c3 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.
2001-03-28 06:07:39 +00:00
steve c8d9ade58c Evaluate === and !== 2001-03-27 06:43:27 +00:00
steve 61e3eed49c Generate code for simple @ statements. 2001-03-27 06:27:40 +00:00
steve afb8e285db Support error code from target_t::end_design method. 2001-03-27 03:31:06 +00:00
steve 79ce94b585 Add the .event statement and the %wait instruction. 2001-03-26 04:00:39 +00:00
steve f7f5ccce05 Add vpiOctStrVal access to signals. 2001-03-25 20:45:09 +00:00
steve 25d25ff7fe Support NOR and NOT gates. 2001-03-25 19:38:23 +00:00
steve 31b0037299 Support making hex strings. 2001-03-25 19:38:05 +00:00
steve 16f514739f Calculate NOR and NOT tables, and also the hex_digits table. 2001-03-25 19:37:26 +00:00
steve 604ce0db09 Accept <> characters in labels and symbols. 2001-03-25 19:36:45 +00:00
steve a71dbd3987 Draw AND NOR and NOT gates. 2001-03-25 19:36:12 +00:00
steve 417186b06f Add a README for notes about the vvp target. 2001-03-25 18:10:39 +00:00
steve ac91dc38b8 Recursive make check target. 2001-03-25 05:59:46 +00:00
steve 6d0be3de3a vpip.def needed by vpip, not vvm. 2001-03-25 04:48:04 +00:00
steve 2d4f33a0dd Use the correct paths for vpip in make check. 2001-03-25 04:47:47 +00:00
steve c6088c8820 Add JMP0XZ and postpone net inputs when needed. 2001-03-25 03:54:26 +00:00
steve 5134636932 Include signal bit index in functor input. 2001-03-25 03:53:40 +00:00
steve 5d051ffbde Skip true clause if condition ix 0, x or z 2001-03-25 03:53:24 +00:00
steve 97985bba64 Generate .net statements, and nexus inputs. 2001-03-25 03:25:43 +00:00
steve 9ec5fa972e Draw signal inputs to system tasks. 2001-03-25 03:24:10 +00:00
steve 9e04ef4abd Add the .net statement. 2001-03-25 00:35:35 +00:00
steve 68dc83b322 Use the :vpi_module directive. 2001-03-25 00:34:40 +00:00
steve 97e9b62080 Describe the .net directive. 2001-03-24 22:59:28 +00:00
steve 4072021ba4 Install vvp and vvp.tgt. 2001-03-24 22:58:56 +00:00
steve c901945871 eq is x if either value of cmp/u has x or z. 2001-03-23 04:56:03 +00:00
steve 95281e5d82 Generate :module statements. 2001-03-23 02:41:04 +00:00
steve 2858c2f09b Add the :module header statement. 2001-03-23 02:40:22 +00:00
steve 034cdae445 assignments with non-trival r-values. 2001-03-23 01:54:32 +00:00
steve e71ea8c9de Support set of functors from thread bits. 2001-03-23 01:53:46 +00:00
steve b2a136e07e Handle vectors pulled out of a constant bit. 2001-03-23 01:11:06 +00:00
steve c2dc3fe5c3 Assure that operands are the correct width. 2001-03-23 01:10:24 +00:00
steve 548ff4f89a Detect undefined system tasks at compile time. 2001-03-22 22:38:13 +00:00
steve b3c24adb11 install vvp. 2001-03-22 22:37:36 +00:00
steve e81d0d9f23 Compile in a default VPI module dir. 2001-03-22 21:26:53 +00:00
steve 715d140d85 Test print that interferes with output. 2001-03-22 05:39:34 +00:00
steve fa46de1021 Add code label forward references. 2001-03-22 05:28:41 +00:00
steve aa31884d3b no longer need out message. 2001-03-22 05:28:16 +00:00
steve aacce5ef1b implement %load, %inv, %jum/0 and %cmp/u 2001-03-22 05:08:00 +00:00
steve 565088160e Geneate code for conditional statements. 2001-03-22 05:06:21 +00:00
steve b24011b84b fgetc patch from Peter Monta. 2001-03-22 02:23:17 +00:00
steve 2b8d9abd3e Allow var objects as vpiHandle arguments to %vpi_call. 2001-03-21 05:13:03 +00:00
steve e24facfaf6 Describe the compilation major steps. 2001-03-21 05:12:15 +00:00
steve 27e717839a Scan the scopes of a design, and draw behavioral
blocking  assignments of constants to vectors.
2001-03-21 01:49:43 +00:00
steve 52c7108782 Add support for variable vectors. 2001-03-20 06:16:23 +00:00
steve 90ed3dd124 Copyright notices. 2001-03-20 02:48:40 +00:00
steve 8118203766 Lexical numbers may be signed. 2001-03-20 02:45:25 +00:00
steve e8518c5056 Put processes in the proper scope. 2001-03-20 01:44:13 +00:00
steve f02d4574f9 Get vpi_user from .., not ../vpip. 2001-03-20 01:43:16 +00:00
steve f1ff1149f7 vpi_user.h is in .., and not ./vpi. 2001-03-20 00:29:10 +00:00
steve 034a38ea36 Fix inclule paths to find files in srcdir. 2001-03-19 04:37:59 +00:00
steve f8c3b84f68 Add support for the vpiReset sim control. 2001-03-19 01:55:38 +00:00
steve d8ef63efd1 Pass -o value to vvp target. 2001-03-19 01:29:13 +00:00
steve a240be73e7 vpi_user header file is a root header. 2001-03-19 01:21:45 +00:00
steve 1563643c92 Add the tgt-vvp code generator target. 2001-03-19 01:20:46 +00:00
steve 5b89249f10 Add the hello example program. 2001-03-18 04:37:35 +00:00
steve bf70673380 Accept empty statements. 2001-03-18 04:37:16 +00:00
steve 6779f01f3a Add support for string constants to VPI. 2001-03-18 04:35:18 +00:00
steve 66f7ef97da Add support for vpi scopes. 2001-03-18 00:37:55 +00:00
steve e03859b834 $display can take 0 arguments. 2001-03-18 00:31:32 +00:00
steve f2c1902984 Add structures for VPI support, and all the %vpi_call
instruction. Get linking of VPI modules to work.
2001-03-16 01:44:34 +00:00
steve 32f3881344 Rearrange VPI support libraries. 2001-03-14 19:27:44 +00:00
steve 264e629c74 VPI support documentation. 2001-03-14 19:26:58 +00:00
steve 8969ab03d7 Thread details 2001-03-14 19:26:40 +00:00
steve 952ebe8516 Copyright notice. 2001-03-14 19:26:15 +00:00
steve f355cf334c Stub install and unistall targets. 2001-03-14 19:26:01 +00:00
steve 01c5321208 Add chapter on threads vs functors vs events. 2001-03-13 00:49:50 +00:00
steve 970ba895c9 Compact the vvp_code_s structure. 2001-03-11 23:06:49 +00:00
steve cbc3be0304 Functor values and propagation. 2001-03-11 22:42:11 +00:00
steve cb65ee5e00 Add the vvp engine to cvs. 2001-03-11 00:29:38 +00:00
steve debe707097 check signals in the cprop functor. 2001-02-18 01:07:32 +00:00
steve 79b60da54c I allow function ports to have types. 2001-02-17 05:27:31 +00:00
steve 84c7795d16 Allow task ports to be given real types. 2001-02-17 05:15:33 +00:00
steve 410a93b52c Cannot elide task ports. 2001-02-17 05:14:35 +00:00
steve 78355b6038 Check that the port really exists here. 2001-02-17 05:13:36 +00:00
steve 59b69c6dd1 Constant propagation for compare ==. 2001-02-16 03:27:31 +00:00
steve d3bff8a451 links to root inputs are not constant. 2001-02-16 03:27:07 +00:00
steve 43ddd97426 Missing . in names generated from scope locals. 2001-02-16 03:25:09 +00:00
steve 4399042b8d Use Mersenne Twister 19937 pseudo-random number generator
for the $random system task, and support the seed paramter.
2001-02-16 00:26:38 +00:00
steve 2b0aaec8ab FreeBSD port has a maintainer now. 2001-02-15 06:59:35 +00:00
steve 7d7ccd4f08 Generate proper code for wide condition expressions. 2001-02-13 04:11:24 +00:00
steve 93463b6ff5 Binary or and nor resilient to bit widths. 2001-02-13 03:38:55 +00:00
steve 4b0c56c3a8 Rant about bit widths. 2001-02-12 16:48:04 +00:00
steve 1bae567728 Add the netmisc.cc source file. 2001-02-11 02:15:52 +00:00
steve 7d7beeecc1 Binary operators with operands of indefinite width
has itself an indefinite width.
2001-02-10 21:20:38 +00:00
steve f5d0211864 In the context of range declarations, use elab_and_eval instead
of the less robust eval_const methods.
2001-02-10 20:29:39 +00:00
steve 1f4232187c Slightly more specific error message. 2001-02-10 19:50:33 +00:00
steve f45ba008d8 Catch constants driving root module ports. (PR#130) 2001-02-10 04:50:54 +00:00
steve ac629b313c Report errors when XNF code has constant X values. (PR#128) 2001-02-10 03:22:49 +00:00
steve 563065053e Make the add func resilient to bit widths (PR#141) 2001-02-10 01:57:18 +00:00
steve 2b903f5d0e Detect part select out of range in nets. (PR#138) 2001-02-09 20:18:15 +00:00
steve 7ef3b44ab1 support evaluation of constant < in expressions. 2001-02-09 05:44:23 +00:00
steve 8376553349 Report bit/part select out of range errors. (PR#133) 2001-02-09 03:16:48 +00:00
steve 3885f17d0f Be more clear about scope of failure. 2001-02-09 02:49:59 +00:00
steve 4b0e5bd173 trim the length of unsized numbers. 2001-02-08 05:38:18 +00:00
steve d78c7392c2 Remove dead code. 2001-02-08 01:10:30 +00:00
steve cf3f1b38c3 ivl_target header search path fixes. 2001-02-07 22:21:59 +00:00
steve 2fbc0af1ea Fix expression widths for rvalues and parameters (PR#131,132) 2001-02-07 21:47:13 +00:00
steve 94a1d59817 Support constant evaluation of / and % (PR#124) 2001-02-07 02:46:31 +00:00
steve 57d1bfaf29 Add 0? and 1? patterns to UDP syntax. (PR#137) 2001-02-07 01:08:21 +00:00
135 changed files with 13326 additions and 433 deletions
+17 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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)
+137 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+7 -2
View File
@@ -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
*
+5 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+10
View File
@@ -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
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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.
*
+3 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: lexor.lex,v 1.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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
*
+37 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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
View File
@@ -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.
*
*/
+16 -29
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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
View File
@@ -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
View File
@@ -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.
*
+13 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+74 -3
View File
@@ -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.
*
+58 -6
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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.
*
+20 -5
View File
@@ -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.
*
+29 -10
View File
@@ -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.
*
+6 -2
View File
@@ -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.
*
+7 -3
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.6 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
View File
@@ -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.
*
+2 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.5 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
+5 -2
View File
@@ -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.
*
+6
View File
@@ -0,0 +1,6 @@
Makefile
configure
config.status
config.log
dep
vvp.tgt
+87
View File
@@ -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)
+18
View File
@@ -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.
+53
View File
@@ -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)
+425
View File
@@ -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.
*
*/
+83
View File
@@ -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
/*
*/
+94
View File
@@ -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
+530
View File
@@ -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.
*
*/
+278
View File
@@ -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
View File
@@ -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
View File
@@ -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 ~.
*
+20 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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
View File
@@ -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)
+115
View File
@@ -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
View File
@@ -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
View File
@@ -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.
*
+10 -1
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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.
*
+6
View File
@@ -0,0 +1,6 @@
libvpip.a
Makefile
configure
config.log
config.status
dep
+122
View File
@@ -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)
+11
View File
@@ -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)
+40
View File
@@ -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
+4 -1
View File
@@ -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
*
+4 -1
View File
@@ -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.
*
+4 -1
View File
@@ -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.
*
+4 -1
View File
@@ -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.
*
+30 -2
View File
@@ -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;
}
+4 -1
View File
@@ -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.
*
+4 -1
View File
@@ -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)
*
+4 -1
View File
@@ -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
+5 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: 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.
*
+4 -1
View File
@@ -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)
*
+4 -1
View File
@@ -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)
*
+4 -1
View File
@@ -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.
*
+4 -1
View File
@@ -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.
*
+1 -1
View File
@@ -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>
View File
+5 -53
View File
@@ -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
View File
@@ -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.
+12
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
Vendored Executable
+912
View File
@@ -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
+51
View File
@@ -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
Vendored Executable
+1178
View File
File diff suppressed because it is too large Load Diff
+54
View File
@@ -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
View File
@@ -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.
*
*/
+53
View File
@@ -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;
+52
View File
@@ -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